Scheduled service maintenance on November 22


On Friday, November 22, 2024, between 06:00 CET and 18:00 CET, GIN services will undergo planned maintenance. Extended service interruptions should be expected. We will try to keep downtimes to a minimum, but recommend that users avoid critical tasks, large data uploads, or DOI requests during this time.

We apologize for any inconvenience.

Snakefile 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  1. from os.path import join, getsize
  2. import math
  3. configfile: 'configfile.yaml'
  4. localrules: amsterdam_all, workflow_diagrams
  5. SOURCE = config['sourcedir']
  6. CODE_DIR = config['codedir']
  7. METADATA_DIR = config['metadatadir']
  8. LOG_DIR = config['logdir'] # This is used in the job submission
  9. SESSIONS = config['sessions']
  10. SAMPLES = config['sample_sessions']
  11. NSPCOUNT = config['nsp_count']
  12. SNR_THRESHOLD = config["SNR_threshold"]
  13. RF_SESSIONS = {'L': ['RF_260617', 'RF_280617'],
  14. 'A': ['RF_290818', 'RF_280818']}
  15. """
  16. Set of functions used to find the path to all the files in the workflow
  17. """
  18. def target_arrays(wcs):
  19. files = []
  20. for session in SESSIONS:
  21. path = join(SOURCE, 'data', session, 'anasig_placeholder')
  22. for nsp_id in range(1, NSPCOUNT + 1):
  23. nsp = join(path, 'NSP' + str(nsp_id) + '_array')
  24. arr1 = nsp + str(2*nsp_id-1)
  25. arr2 = nsp + str(2*nsp_id)
  26. files.append(arr1)
  27. files.append(arr2)
  28. return files
  29. def target_LFP(wcs):
  30. arrayfiles = target_arrays(wcs)
  31. files = [file.replace('anasig_placeholder', 'LFP') + '_LFP.nix'
  32. for file in arrayfiles]
  33. return files
  34. def target_MUAe(wcs):
  35. arrayfiles = target_arrays(wcs)
  36. files = [file.replace('anasig_placeholder', 'MUAe') + '_MUAe.nix'
  37. for file in arrayfiles]
  38. return files
  39. def target_arrayplots(wcs):
  40. files = []
  41. for ses in SESSIONS:
  42. if 'SNR' in ses:
  43. pdf_SNR = join(METADATA_DIR,
  44. 'signal_to_noise_ratio',
  45. ses + '_arrayplot.pdf')
  46. files.append(pdf_SNR)
  47. pdf_response_timing = join(METADATA_DIR,
  48. 'stimulus_evoked_response_timing',
  49. ses + '_response_timing_arrayplot.pdf')
  50. files.append(pdf_response_timing)
  51. return files
  52. def get_sample_session(wcs):
  53. subject = wcs.monkey + '_'
  54. for session in SAMPLES:
  55. if subject in session:
  56. path = join(SOURCE,
  57. 'data',
  58. session,
  59. 'raw',
  60. 'NSP1_aligned.ns6')
  61. return path
  62. def get_ns6_nsp_from_arr(wcs):
  63. ns6 = join(SOURCE,
  64. 'data',
  65. wcs.monkey + '_' + wcs.exp + '_' + wcs.ses,
  66. 'raw',
  67. 'NSP' + str(math.ceil(float(wcs.arr)/2)) + '_aligned.ns6')
  68. return ns6
  69. def get_SNR_csv(wcs):
  70. files = []
  71. for nsp_id in range(1, NSPCOUNT + 1):
  72. arr1 = str(2*nsp_id-1)
  73. arr2 = str(2*nsp_id)
  74. base = join(SOURCE,
  75. 'tmp',
  76. 'signal_to_noise_ratio',
  77. wcs.monkey + '_SNR_' + wcs.ses,
  78. 'NSP' + str(nsp_id) + '_array')
  79. path1 = base + arr1 + '_SNR.csv'
  80. path2 = base + arr2 + '_SNR.csv'
  81. files.append(path1)
  82. files.append(path2)
  83. return files
  84. def get_RF_csv(wcs):
  85. files = []
  86. for nsp_id in range(1, NSPCOUNT + 1):
  87. arr1 = str(2*nsp_id-1)
  88. arr2 = str(2*nsp_id)
  89. base = join(SOURCE,
  90. 'tmp',
  91. 'receptive_fields',
  92. wcs.monkey + '_RF_' + wcs.ses,
  93. 'NSP' + str(nsp_id) + '_array')
  94. path1 = base + arr1 + '_RF.csv'
  95. path2 = base + arr2 + '_RF.csv'
  96. files.append(path1)
  97. files.append(path2)
  98. return files
  99. def get_RFs_of_monkey(wcs):
  100. files = []
  101. for ses in RF_SESSIONS[wcs.monkey]:
  102. file = join(SOURCE,
  103. 'tmp',
  104. 'receptive_fields',
  105. wcs.monkey + '_' + ses + '_full.csv')
  106. files.append(file)
  107. return files
  108. def target_eyeplot(wcs):
  109. files = []
  110. for ses in SESSIONS:
  111. if 'RS' in ses:
  112. file = join(METADATA_DIR,
  113. 'eye_signals',
  114. f'{ses}_eyes.pdf')
  115. files.append(file)
  116. return files
  117. def target_metadata(wcs):
  118. files = []
  119. for ses in SESSIONS:
  120. file = join(SOURCE, 'data', ses, 'metadata_' + ses + '.odml')
  121. files.append(file)
  122. return files
  123. def target_RF_metadata(wcs):
  124. files = []
  125. for ses in SESSIONS:
  126. if 'RF' in ses:
  127. file = join(SOURCE, 'data', ses, 'metadata_' + ses + '.odml')
  128. files.append(file)
  129. return files
  130. def target_synchrofacts(wcs):
  131. files = []
  132. for ses in SESSIONS:
  133. if 'RS' in ses:
  134. for i in range(1, NSPCOUNT + 1):
  135. out = join(SOURCE, 'tmp', ses, 'thr_crossings',
  136. 'thr_crossings_nsp' + str(i) + '.pkl')
  137. files.append(out)
  138. counts = join(SOURCE,
  139. 'tmp',
  140. ses,
  141. 'synchrofacts',
  142. f'{ses}_tot_syncounts.npy')
  143. files.append(counts)
  144. counts = join(SOURCE,
  145. 'tmp',
  146. ses,
  147. 'synchrofacts',
  148. f'{ses}_el_syncounts.npy')
  149. files.append(counts)
  150. metadata = join(METADATA_DIR,
  151. 'cross_talk_removal',
  152. f'{ses}_removal_metadata.csv')
  153. files.append(metadata)
  154. return files
  155. def mem_lim_synchrofacts(wcs):
  156. if wcs.monkey == 'L':
  157. return 110*1024
  158. if wcs.monkey == 'A':
  159. return 110*1024
  160. def cpus_synchrofacts(wcs):
  161. if wcs.monkey == 'L':
  162. return 48
  163. if wcs.monkey == 'A':
  164. return 48
  165. def sample_MUAe_array_for_eyeplot(wcs):
  166. if wcs.monkey =='L':
  167. muae = join(SOURCE,
  168. 'data',
  169. f'{wcs.monkey}_RS_{wcs.ses}',
  170. 'MUAe',
  171. 'NSP6_array11_MUAe.nix')
  172. elif wcs.monkey == 'A':
  173. muae = join(SOURCE,
  174. 'data',
  175. f'{wcs.monkey}_RS_{wcs.ses}',
  176. 'MUAe',
  177. 'NSP5_array10_MUAe.nix')
  178. return muae
  179. '''
  180. DEFINE OBJECTIVES
  181. '''
  182. rule amsterdam_all:
  183. input:
  184. rfs = target_RF_metadata,
  185. crossings = target_synchrofacts,
  186. lfp = target_LFP,
  187. muae = target_MUAe,
  188. pdf_SNR = target_arrayplots,
  189. png_eyes = target_eyeplot,
  190. metadata = target_metadata,
  191. rulegraph_pdf = join(CODE_DIR, 'rulegraph.png')
  192. '''
  193. METADATA HANDLING
  194. '''
  195. rule metadata_setup:
  196. input:
  197. # xls files to create initial odml files with odmltables
  198. equipment = join(METADATA_DIR,
  199. 'experimental_setup',
  200. 'equipment_specifications.xls'),
  201. subject = join(METADATA_DIR,
  202. 'subjects',
  203. 'subject_{monkey}.xls'),
  204. # metadata files that need to be integrated in the odml structure
  205. impedances = join(METADATA_DIR,
  206. 'experimental_setup',
  207. 'impedance_{monkey}'),
  208. id_map = join(METADATA_DIR,
  209. 'experimental_setup',
  210. 'channel_area_mapping_{monkey}.mat'),
  211. sample_session = get_sample_session,
  212. # Array and electrode approximate positions
  213. array_pos = join(METADATA_DIR,
  214. 'experimental_setup',
  215. 'approximate_array_positions_{monkey}.csv'),
  216. elec_pos = join(METADATA_DIR,
  217. 'experimental_setup',
  218. 'elec_position_in_array.csv'),
  219. # Scripts that will be needed
  220. script_odmltables = join(CODE_DIR,
  221. 'metadata_handling',
  222. 'initialize_odml_from_xls.py'),
  223. script_enrich = join(CODE_DIR,
  224. 'metadata_handling',
  225. 'enrich_odml_IDs.py')
  226. output:
  227. tmp_odml = join(SOURCE,
  228. 'tmp',
  229. 'metadata',
  230. 'basic_{monkey}_template.odml'),
  231. odml = join(SOURCE,
  232. 'tmp',
  233. 'metadata',
  234. 'subject_{monkey}_template.odml')
  235. wildcard_constraints:
  236. monkey = 'L|A'
  237. conda:
  238. join(CODE_DIR, 'environment.yaml')
  239. shell:
  240. """
  241. python {input.script_odmltables} --equipment {input.equipment} \
  242. --subject {input.subject} \
  243. --out {output.tmp_odml}
  244. python {input.script_enrich} --odml-template {output.tmp_odml} \
  245. --impedance {input.impedances} \
  246. --id-map {input.id_map} \
  247. --ns6 {input.sample_session} \
  248. --array-pos {input.array_pos} \
  249. --elec-pos {input.elec_pos} \
  250. --out {output.odml}
  251. """
  252. rule eye_signals:
  253. input:
  254. session = join(SOURCE,
  255. 'data',
  256. '{monkey}_RS_{ses}',
  257. 'raw',
  258. 'NSP1_aligned.ns6'),
  259. mat = join(SOURCE,
  260. 'data',
  261. '{monkey}_RS_{ses}',
  262. 'eye_signals',
  263. 'aligned_eye_data.mat'),
  264. odml_template = rules.metadata_setup.output.odml,
  265. # Scripts
  266. nix_script = join(CODE_DIR,
  267. 'metadata_handling',
  268. 'eyesig_conversion_and_epochs.py'),
  269. trials_script = join(CODE_DIR,
  270. 'metadata_handling',
  271. 'enrich_odml_epochs.py')
  272. output:
  273. nix = join(SOURCE,
  274. 'data',
  275. '{monkey}_RS_{ses}',
  276. 'eye_signals',
  277. '{monkey}_RS_{ses}_aligned_eye_data.nix'),
  278. csv = join(METADATA_DIR,
  279. 'epochs',
  280. 'epochs_{monkey}_RS_{ses}.csv'),
  281. odml = join(SOURCE,
  282. 'tmp',
  283. 'metadata',
  284. 'partial_{monkey}_RS_{ses}_with_epochs.odml')
  285. conda:
  286. join(CODE_DIR, 'environment.yaml')
  287. shell:
  288. """
  289. python {input.nix_script} --eyesig {input.mat} \
  290. --csv {output.csv} \
  291. --out {output.nix}
  292. python {input.trials_script} --template {input.odml_template} \
  293. --csv {output.csv} \
  294. --SNR-thresh {SNR_THRESHOLD} \
  295. --ns6 {input.session} \
  296. --out {output.odml}
  297. """
  298. rule metadata_recording:
  299. input:
  300. session = join(SOURCE,
  301. 'data',
  302. '{monkey}_{exp}_{ses}',
  303. 'raw',
  304. 'NSP1_aligned.ns6'),
  305. odml_template = rules.metadata_setup.output.odml,
  306. # Scripts
  307. csv_script = join(CODE_DIR,
  308. 'metadata_handling',
  309. 'generate_trial_csv.py'),
  310. trials_script = join(CODE_DIR,
  311. 'metadata_handling',
  312. 'enrich_odml_epochs.py')
  313. output:
  314. csv = join(METADATA_DIR,
  315. 'epochs',
  316. 'epochs_{monkey}_{exp}_{ses}.csv'),
  317. odml = join(SOURCE,
  318. 'tmp',
  319. 'metadata',
  320. 'partial_{monkey}_{exp}_{ses}_with_epochs.odml')
  321. conda:
  322. join(CODE_DIR, 'environment.yaml')
  323. wildcard_constraints:
  324. exp = 'SNR|RF'
  325. shell:
  326. """
  327. python {input.csv_script} --ns6 {input.session} \
  328. --out {output.csv}
  329. python {input.trials_script} --template {input.odml_template} \
  330. --csv {output.csv} \
  331. --SNR-thresh {SNR_THRESHOLD} \
  332. --ns6 {input.session} \
  333. --out {output.odml}
  334. """
  335. rule metadata_SNR:
  336. input:
  337. csv_SNR = join(METADATA_DIR,
  338. 'signal_to_noise_ratio',
  339. '{monkey}_SNR_{ses}_full.csv'),
  340. odml_template = join(SOURCE,
  341. 'tmp',
  342. 'metadata',
  343. 'partial_{monkey}_SNR_{ses}_with_epochs.odml'),
  344. script = join(CODE_DIR,
  345. 'metadata_handling',
  346. 'finalize_odml_SNR.py')
  347. output:
  348. odml = join(SOURCE,
  349. 'data',
  350. '{monkey}_SNR_{ses}',
  351. 'metadata_{monkey}_SNR_{ses}.odml')
  352. conda:
  353. join(CODE_DIR, "environment.yaml")
  354. shell:
  355. """
  356. python {input.script} --csv-SNR {input.csv_SNR} \
  357. --odml {input.odml_template} \
  358. --out {output.odml}
  359. """
  360. rule metadata_RF:
  361. input:
  362. csv_RF = join(METADATA_DIR,
  363. 'receptive_fields',
  364. 'combined_{monkey}_RF.csv'),
  365. odml_template = join(SOURCE,
  366. 'tmp',
  367. 'metadata',
  368. 'partial_{monkey}_RF_{ses}_with_epochs.odml'),
  369. script = join(CODE_DIR,
  370. 'metadata_handling',
  371. 'finalize_odml_RF.py')
  372. output:
  373. odml = join(SOURCE,
  374. 'data',
  375. '{monkey}_RF_{ses}',
  376. 'metadata_{monkey}_RF_{ses}.odml')
  377. conda:
  378. join(CODE_DIR, "environment.yaml")
  379. shell:
  380. """
  381. python {input.script} --csv-RF {input.csv_RF} \
  382. --odml {input.odml_template} \
  383. --out {output.odml}
  384. """
  385. rule metadata_RS:
  386. input:
  387. csv_RF = join(METADATA_DIR,
  388. 'receptive_fields',
  389. 'combined_{monkey}_RF.csv'),
  390. csv_SNR = join(METADATA_DIR,
  391. 'signal_to_noise_ratio',
  392. '{monkey}_SNR_{ses}_full.csv'),
  393. csv_sync = join(METADATA_DIR,
  394. 'cross_talk_removal',
  395. '{monkey}_RS_{ses}_removal_metadata.csv'),
  396. odml_template = join(SOURCE,
  397. 'tmp',
  398. 'metadata',
  399. 'partial_{monkey}_RS_{ses}_with_epochs.odml'),
  400. script = join(CODE_DIR,
  401. 'metadata_handling',
  402. 'finalize_odml_RS.py')
  403. output:
  404. odml = join(SOURCE,
  405. 'data',
  406. '{monkey}_RS_{ses}',
  407. 'metadata_{monkey}_RS_{ses}.odml')
  408. conda:
  409. join(CODE_DIR, "environment.yaml")
  410. shell:
  411. """
  412. python {input.script} --csv-RF {input.csv_RF} \
  413. --csv-SNR {input.csv_SNR} \
  414. --csv-sync {input.csv_sync} \
  415. --odml {input.odml_template} \
  416. --out {output.odml}
  417. """
  418. '''
  419. ANALOG SIGNALS
  420. '''
  421. rule LFP:
  422. input:
  423. ns6 = get_ns6_nsp_from_arr,
  424. odml = rules.metadata_recording.output.odml,
  425. script = join(CODE_DIR,
  426. 'signal_processing',
  427. 'calculate_LFP.py')
  428. output:
  429. lfp = join(SOURCE,
  430. 'data',
  431. '{monkey}_{exp}_{ses}',
  432. 'LFP',
  433. 'NSP{nsp}_array{arr}_LFP.nix')
  434. conda:
  435. join(CODE_DIR, "environment.yaml")
  436. wildcard_constraints:
  437. exp = 'SNR|RF'
  438. resources:
  439. mem_mb = lambda wcs, input: int(2*getsize(input.ns6)/1024/1024) # MB
  440. shell:
  441. '''
  442. python {input.script} --ns6 {input.ns6} \
  443. --array {wildcards.arr} \
  444. --odml {input.odml} \
  445. --out {output.lfp}
  446. '''
  447. rule LFP_RS:
  448. input:
  449. ns6 = get_ns6_nsp_from_arr,
  450. odml = rules.metadata_RS.output.odml,
  451. eye = rules.eye_signals.output.nix,
  452. script = join(CODE_DIR,
  453. 'signal_processing',
  454. 'calculate_LFP.py')
  455. output:
  456. lfp = join(SOURCE,
  457. 'data',
  458. '{monkey}_{exp}_{ses}',
  459. 'LFP',
  460. 'NSP{nsp}_array{arr}_LFP.nix')
  461. conda:
  462. join(CODE_DIR, "environment.yaml")
  463. wildcard_constraints:
  464. exp = 'RS'
  465. resources:
  466. mem_mb = lambda wcs, input: int(2*getsize(input.ns6)/1024/1024) # MB
  467. shell:
  468. '''
  469. python {input.script} --ns6 {input.ns6} \
  470. --array {wildcards.arr} \
  471. --odml {input.odml} \
  472. --eyesig {input.eye} \
  473. --out {output.lfp}
  474. '''
  475. rule MUAe:
  476. input:
  477. ns6 = get_ns6_nsp_from_arr,
  478. odml = rules.metadata_recording.output.odml,
  479. script = join(CODE_DIR,
  480. 'signal_processing',
  481. 'calculate_MUAe.py')
  482. output:
  483. muae = join(SOURCE,
  484. 'data',
  485. '{monkey}_{exp}_{ses}',
  486. 'MUAe',
  487. 'NSP{nsp}_array{arr}_MUAe.nix'
  488. )
  489. conda:
  490. join(CODE_DIR, "environment.yaml")
  491. wildcard_constraints:
  492. exp = 'SNR|RF'
  493. resources:
  494. mem_mb = lambda wcs, input: int(3*getsize(input.ns6)/1024/1024) # MB
  495. shell:
  496. '''
  497. python {input.script} --ns6 {input.ns6} \
  498. --array {wildcards.arr} \
  499. --odml {input.odml} \
  500. --out {output.muae}
  501. '''
  502. rule MUAe_RS:
  503. input:
  504. ns6 = get_ns6_nsp_from_arr,
  505. odml = rules.metadata_RS.output.odml,
  506. eye = rules.eye_signals.output.nix,
  507. script = join(CODE_DIR,
  508. 'signal_processing',
  509. 'calculate_MUAe.py')
  510. output:
  511. muae = join(SOURCE,
  512. 'data',
  513. '{monkey}_{exp}_{ses}',
  514. 'MUAe',
  515. 'NSP{nsp}_array{arr}_MUAe.nix'
  516. )
  517. conda:
  518. join(CODE_DIR, "environment.yaml")
  519. wildcard_constraints:
  520. exp = 'RS'
  521. resources:
  522. mem_mb = lambda wcs, input: int(3*getsize(input.ns6)/1024/1024) # MB
  523. shell:
  524. '''
  525. python {input.script} --ns6 {input.ns6} \
  526. --array {wildcards.arr} \
  527. --odml {input.odml} \
  528. --eyesig {input.eye} \
  529. --out {output.muae}
  530. '''
  531. '''
  532. METADATA GENERATION
  533. '''
  534. rule receptive_fields:
  535. input:
  536. muae = rules.MUAe.output.muae,
  537. odml = rules.metadata_recording.output.odml,
  538. RF_script = join(CODE_DIR,
  539. 'signal_processing',
  540. 'calculate_RF.py')
  541. output:
  542. csv = join(SOURCE,
  543. 'tmp',
  544. 'receptive_fields',
  545. '{monkey}_{exp}_{ses}',
  546. 'NSP{nsp}_array{arr}_RF.csv')
  547. params:
  548. plt_path = join(METADATA_DIR,
  549. 'receptive_fields',
  550. '{monkey}_{exp}_{ses}',
  551. 'response_plot_NSP{nsp}_array{arr}_RF')
  552. resources:
  553. mem_mb = lambda wcs, input: 8*int(getsize(input.muae)/1024/1024) # MB
  554. conda:
  555. join(CODE_DIR, "environment.yaml")
  556. wildcard_constraints:
  557. exp = 'RF'
  558. shell:
  559. """
  560. python {input.RF_script} --muae {input.muae} \
  561. --odml {input.odml} \
  562. --plt {params.plt_path} \
  563. --out {output.csv}
  564. """
  565. rule signal_to_noise_ratio_of_channel:
  566. input:
  567. muae = rules.MUAe.output.muae,
  568. odml = rules.metadata_recording.output.odml,
  569. SNR_script = join(CODE_DIR,
  570. 'signal_processing',
  571. 'calculate_SNR.py')
  572. output:
  573. csv = join(SOURCE,
  574. 'tmp',
  575. 'signal_to_noise_ratio',
  576. '{monkey}_{exp}_{ses}',
  577. 'NSP{nsp}_array{arr}_SNR.csv'),
  578. plt_path = join(METADATA_DIR,
  579. 'signal_to_noise_ratio',
  580. '{monkey}_{exp}_{ses}',
  581. 'response_plot_NSP{nsp}_array{arr}_SNR.png')
  582. wildcard_constraints:
  583. exp = 'SNR'
  584. resources:
  585. mem_mb = lambda wcs, input: 16*int(getsize(input.muae)/1024/1024) # MB
  586. conda:
  587. join(CODE_DIR, "environment.yaml")
  588. shell:
  589. """
  590. python {input.SNR_script} --muae {input.muae} \
  591. --odml {input.odml} \
  592. --plt {output.plt_path} \
  593. --out {output.csv}
  594. """
  595. rule merge_SNR:
  596. input:
  597. SNR = get_SNR_csv,
  598. script = join(CODE_DIR,
  599. 'metadata_handling',
  600. 'merge_csv.py')
  601. output:
  602. csv = join(METADATA_DIR,
  603. 'signal_to_noise_ratio',
  604. '{monkey}_SNR_{ses}_full.csv')
  605. conda:
  606. join(CODE_DIR, "environment.yaml")
  607. shell:
  608. """
  609. python {input.script} --csv-list "{input.SNR}" \
  610. --out {output.csv}
  611. """
  612. rule merge_RF:
  613. input:
  614. RF = get_RF_csv,
  615. script = join(CODE_DIR,
  616. 'metadata_handling',
  617. 'merge_csv.py')
  618. output:
  619. csv = join(SOURCE,
  620. 'tmp',
  621. 'receptive_fields',
  622. '{monkey}_RF_{ses}_full.csv')
  623. conda:
  624. join(CODE_DIR, "environment.yaml")
  625. shell:
  626. """
  627. python {input.script} --csv-list "{input.RF}" \
  628. --out {output.csv}
  629. """
  630. rule combine_RF_and_plot:
  631. input:
  632. RF = get_RFs_of_monkey,
  633. mapping = join(METADATA_DIR,
  634. 'experimental_setup',
  635. 'channel_area_mapping_{monkey}.csv'),
  636. script = join(CODE_DIR,
  637. 'metadata_handling',
  638. 'combine_RF.py')
  639. output:
  640. plt = join(METADATA_DIR,
  641. 'receptive_fields',
  642. 'combined_{monkey}_RF.pdf'),
  643. csv = join(METADATA_DIR,
  644. 'receptive_fields',
  645. 'combined_{monkey}_RF.csv')
  646. conda:
  647. join(CODE_DIR, "environment.yaml")
  648. shell:
  649. """
  650. str="{input.RF}"
  651. str="${{str// /;}}"
  652. python {input.script} --csv-list $str \
  653. --mapping {input.mapping} \
  654. --plt {output.plt} \
  655. --monkey {wildcards.monkey} \
  656. --out {output.csv}
  657. """
  658. '''
  659. SYNCHROFACTS
  660. '''
  661. rule filter_hi:
  662. input:
  663. ns6 = join(SOURCE,
  664. 'data',
  665. '{monkey}_{exp}_{ses}',
  666. 'raw',
  667. 'NSP{nsp}_aligned.ns6'),
  668. npy_script = join(CODE_DIR,
  669. 'signal_processing',
  670. 'highpass_ns6.py'),
  671. output:
  672. npy = join(SOURCE,
  673. 'tmp',
  674. 'thr_crossings',
  675. '{monkey}_{exp}_{ses}_hipass_nsp{nsp}.npy')
  676. conda:
  677. join(CODE_DIR, "environment.yaml")
  678. shell:
  679. """
  680. python {input.npy_script} --ns6 {input.ns6} \
  681. --out {output.npy}
  682. """
  683. rule threshold_crossings:
  684. input:
  685. npy = rules.filter_hi.output.npy,
  686. ns6 = join(SOURCE,
  687. 'data',
  688. '{monkey}_{exp}_{ses}',
  689. 'raw',
  690. 'NSP{nsp}_aligned.ns6'),
  691. script = join(CODE_DIR,
  692. 'synchrofacts',
  693. 'get_thr_crossings.py')
  694. output:
  695. eigval = join(SOURCE,
  696. 'tmp',
  697. 'thr_crossings',
  698. '{monkey}_{exp}_{ses}_eigval_nsp{nsp}.npy'),
  699. eigvec = join(SOURCE,
  700. 'tmp',
  701. 'thr_crossings',
  702. '{monkey}_{exp}_{ses}_eigvec_nsp{nsp}.npy'),
  703. npy_pca = join(SOURCE,
  704. 'tmp',
  705. 'thr_crossings',
  706. '{monkey}_{exp}_{ses}_clean_hipass_nsp{nsp}.npy'),
  707. out = join(SOURCE,
  708. 'tmp',
  709. '{monkey}_{exp}_{ses}',
  710. 'thr_crossings',
  711. 'thr_crossings_nsp{nsp}.pkl'),
  712. shell:
  713. """
  714. python {input.script} {input.npy} \
  715. {output.eigval} \
  716. {output.eigvec} \
  717. {output.npy_pca} \
  718. {input.ns6} \
  719. {output.out}
  720. """
  721. rule count_synchrofacts:
  722. input:
  723. pkl = expand(join(SOURCE, 'tmp', '{{monkey}}_RS_{{ses}}',
  724. 'thr_crossings', 'thr_crossings_nsp{nsp}.pkl'),
  725. nsp=range(1, 9)),
  726. script = join(CODE_DIR,
  727. 'synchrofacts',
  728. 'count_synchrofacts.py'),
  729. odml = rules.metadata_SNR.output.odml
  730. output:
  731. lowSNR = join(SOURCE,
  732. 'tmp',
  733. '{monkey}_RS_{ses}',
  734. 'synchrofacts',
  735. 'low_SNR.txt'),
  736. lowFR = join(SOURCE,
  737. 'tmp',
  738. '{monkey}_RS_{ses}',
  739. 'synchrofacts',
  740. 'low_FR.txt'),
  741. counts_tot = join(SOURCE,
  742. 'tmp',
  743. '{monkey}_RS_{ses}',
  744. 'synchrofacts',
  745. '{monkey}_RS_{ses}_tot_syncounts.npy'),
  746. counts_el = join(SOURCE,
  747. 'tmp',
  748. '{monkey}_RS_{ses}',
  749. 'synchrofacts',
  750. '{monkey}_RS_{ses}_el_syncounts.npy'),
  751. surrs_tot = join(SOURCE,
  752. 'tmp',
  753. '{monkey}_RS_{ses}',
  754. 'synchrofacts',
  755. '{monkey}_RS_{ses}_surr_tot_syncounts.npy'),
  756. surrs_el = join(SOURCE,
  757. 'tmp',
  758. '{monkey}_RS_{ses}',
  759. 'synchrofacts',
  760. '{monkey}_RS_{ses}_surr_el_syncounts.npy'),
  761. epoch = join(SOURCE,
  762. 'tmp',
  763. '{monkey}_RS_{ses}',
  764. 'synchrofacts',
  765. '{monkey}_RS_{ses}_synobj.pkl')
  766. conda:
  767. join(CODE_DIR, "environment.yaml")
  768. resources:
  769. mem_mb = mem_lim_synchrofacts, # MB
  770. cpus = cpus_synchrofacts
  771. shell:
  772. """
  773. str="{input.pkl}"
  774. str="${{str// /;}}"
  775. python {input.script} --crossings $str \
  776. --odml {input.odml} \
  777. --lowSNR {output.lowSNR} \
  778. --lowFR {output.lowFR} \
  779. --outcountstot {output.counts_tot} \
  780. --outcountsel {output.counts_el} \
  781. --outsurrtot {output.surrs_tot} \
  782. --outsurrel {output.surrs_el} \
  783. --outobj {output.epoch}
  784. """
  785. rule remove_synchrofact_electrodes:
  786. input:
  787. odml = rules.metadata_SNR.output.odml,
  788. lowFR = rules.count_synchrofacts.output.lowFR,
  789. synobj = rules.count_synchrofacts.output.epoch,
  790. counts_tot = rules.count_synchrofacts.output.counts_tot,
  791. counts_el = rules.count_synchrofacts.output.counts_el,
  792. surrs_tot = rules.count_synchrofacts.output.surrs_tot,
  793. surrs_el = rules.count_synchrofacts.output.surrs_el,
  794. script = join(CODE_DIR,
  795. 'synchrofacts',
  796. 'systematic_removal_of_electrodes.py')
  797. output:
  798. plotdir = directory(join(METADATA_DIR,
  799. 'cross_talk_removal',
  800. '{monkey}_RS_{ses}_removal_plots')),
  801. csv = join(METADATA_DIR,
  802. 'cross_talk_removal',
  803. '{monkey}_RS_{ses}_removal_metadata.csv')
  804. conda:
  805. join(CODE_DIR, "environment.yaml")
  806. resources:
  807. mem_mb = mem_lim_synchrofacts, # MB
  808. cpus = cpus_synchrofacts
  809. shell:
  810. """
  811. python {input.script} --ses {wildcards.monkey}_RS_{wildcards.ses} \
  812. --odml {input.odml} \
  813. --lowFR {input.lowFR} \
  814. --syn-obj {input.synobj} \
  815. --orig-tot-cpx {input.counts_tot} \
  816. --orig-el-cpx {input.counts_el} \
  817. --surr-tot-cpx {input.surrs_tot} \
  818. --surr-el-cpx {input.surrs_el} \
  819. --plot-dir {output.plotdir} \
  820. --out-csv {output.csv}
  821. """
  822. '''
  823. PLOTTING
  824. '''
  825. rule plot_SNR:
  826. input:
  827. odml_template = rules.metadata_SNR.output.odml,
  828. script_SNR = join(CODE_DIR,
  829. 'plotting',
  830. 'arrayplot_SNR.py'),
  831. output:
  832. SNR = join(METADATA_DIR,
  833. 'signal_to_noise_ratio',
  834. '{monkey}_{exp}_{ses}_arrayplot.pdf'),
  835. conda:
  836. join(CODE_DIR, "environment.yaml")
  837. shell:
  838. """
  839. python {input.script_SNR} --odml {input.odml_template} \
  840. --out {output.SNR}
  841. """
  842. rule plot_response_timing:
  843. input:
  844. odml_template = rules.metadata_SNR.output.odml,
  845. script_timing = join(CODE_DIR,
  846. 'plotting',
  847. 'arrayplot_response_timing.py'),
  848. output:
  849. r_timing = join(METADATA_DIR,
  850. 'stimulus_evoked_response_timing',
  851. '{monkey}_{exp}_{ses}_response_timing_arrayplot.pdf'),
  852. conda:
  853. join(CODE_DIR, "environment.yaml")
  854. shell:
  855. """
  856. python {input.script_timing} --odml {input.odml_template} \
  857. --out {output.r_timing}
  858. """
  859. rule plot_eyes:
  860. input:
  861. nix = join(SOURCE,
  862. 'data',
  863. '{monkey}_RS_{ses}',
  864. 'eye_signals',
  865. '{monkey}_RS_{ses}_aligned_eye_data_downsampled_1Hz.nix'),
  866. script = join(CODE_DIR,
  867. 'plotting',
  868. 'eye_epochs_plot.py'),
  869. muae = sample_MUAe_array_for_eyeplot
  870. output:
  871. fig = join(METADATA_DIR,
  872. 'eye_signals',
  873. '{monkey}_RS_{ses}_eyes.pdf')
  874. conda:
  875. join(CODE_DIR, "environment.yaml")
  876. shell:
  877. """
  878. python {input.script} --eyenix {input.nix} \
  879. --muae {input.muae} \
  880. --out {output.fig}
  881. """
  882. rule workflow_diagrams:
  883. output:
  884. rulegraph = join(CODE_DIR, 'rulegraph.png'),
  885. dag = join(CODE_DIR, 'dag.pdf')
  886. shell:
  887. """
  888. mv ~/tmp_rulegraph.png {output.rulegraph}
  889. mv ~/tmp_dag.pdf {output.dag}
  890. """