oceanproc 1.2.0__tar.gz → 1.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {oceanproc-1.2.0 → oceanproc-1.2.1}/PKG-INFO +1 -1
  2. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/bids_wrapper.py +51 -24
  3. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/ocean_proc.py +4 -1
  4. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/preprocessing_wrapper.py +17 -6
  5. {oceanproc-1.2.0 → oceanproc-1.2.1}/pyproject.toml +1 -1
  6. {oceanproc-1.2.0 → oceanproc-1.2.1}/README.md +0 -0
  7. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/__init__.py +0 -0
  8. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/events_long.py +0 -0
  9. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/firstlevel/__init__.py +0 -0
  10. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/firstlevel/run_glm.py +0 -0
  11. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/firstlevel/tests/__init__.py +0 -0
  12. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/firstlevel/tests/test_run_glm.py +0 -0
  13. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/group_series.py +0 -0
  14. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/grouplevel/__init__.py +0 -0
  15. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/grouplevel/computations.py +0 -0
  16. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/grouplevel/design_mat_utils.py +0 -0
  17. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/grouplevel/dscalar_utils.py +0 -0
  18. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/grouplevel/utils.py +0 -0
  19. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/oceanparse.py +0 -0
  20. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/segmentation_wrapper.py +0 -0
  21. {oceanproc-1.2.0 → oceanproc-1.2.1}/oceanproc/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: oceanproc
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: MRI preprocessing for WUSTL Ocean labs
5
5
  Author-Email: Ramone Agard <rhagard@wustl.edu>, Joey Scanga <joeyscanga92@gmail.com>
6
6
  Requires-Python: <3.13,>=3.10
@@ -182,19 +182,6 @@ def run_dcm2niix(source_dir:Path,
182
182
  exit_program_early(f"Problem running '{title}'.",
183
183
  exit_func=clean_up_func if clean_up_func else None)
184
184
 
185
- # Delete or move extra files from short runs
186
- files_to_remove = list(tmp_nifti_dir.glob("*a.nii.gz")) + list(tmp_nifti_dir.glob("*a.json")) + list(tmp_nifti_dir.glob(f"10[0-9][0-9]_{source_dir.name}*"))
187
- if flags.debug:
188
- unused_files_dir = tmp_nifti_dir.parent / f"{tmp_nifti_dir.name}_unused"
189
- unused_files_dir.mkdir(exist_ok=True)
190
- logger.debug(f"moving some unused files and files created from shortened runs to directory {unused_files_dir}")
191
- for f in files_to_remove:
192
- shutil.move(f.resolve(), (unused_files_dir / f.name).resolve())
193
- else:
194
- logger.info(f"removing some unused files and files created from shortened runs :\n {[str(f) for f in files_to_remove]}")
195
- for f in files_to_remove:
196
- os.remove(f)
197
-
198
185
 
199
186
  def get_usability_from_file(usability_file:Path):
200
187
  quality_pairs = {}
@@ -310,7 +297,8 @@ def dicom_to_bids(subject:str,
310
297
  nifti:bool = False,
311
298
  skip_validate:bool = False,
312
299
  skip_prompt:bool = False,
313
- session_index:int = 0):
300
+ session_index:int = 0,
301
+ keep_all_niftis:bool = False):
314
302
  """
315
303
  Facilitates the conversion of DICOM data into NIFTI data in BIDS format, and the removal of data marked 'unusable'.
316
304
 
@@ -346,32 +334,71 @@ def dicom_to_bids(subject:str,
346
334
  else:
347
335
  return
348
336
 
349
- tmp_path = bids_dir / f"tmp_dcm2bids/sub-{subject}_ses-{session}"
337
+ tmp_nifti_path = bids_dir / f"tmp_dcm2bids/sub-{subject}_ses-{session}"
350
338
 
351
339
  def clean_up(quiet=False):
352
340
  try:
353
- logger.debug(f"removing the temporary directory used by dcm2bids: {tmp_path}")
354
- shutil.rmtree(tmp_path)
341
+ logger.debug(f"removing the temporary directory used by dcm2bids: {tmp_nifti_path}")
342
+ shutil.rmtree(tmp_nifti_path)
355
343
  except Exception:
356
344
  if not quiet:
357
- logger.warning(f"There was a problem deleting the temporary directory at {tmp_path}")
345
+ logger.warning(f"There was a problem deleting the temporary directory at {tmp_nifti_path}")
358
346
 
359
- nifti_path = None
360
347
  clean_up(quiet=True)
361
348
  if not nifti:
362
349
  run_dcm2niix(source_dir=source_dir,
363
- tmp_nifti_dir=tmp_path)
364
- nifti_path = tmp_path
350
+ tmp_nifti_dir=tmp_nifti_path)
365
351
  else:
366
- nifti_path = source_dir
352
+ # copy current niftis to tmp_nifti_path
353
+ logger.info(f"copying the source NIFTI files to tmp directory, {tmp_nifti_path}")
354
+ shutil.copytree(source_dir.resolve(), tmp_nifti_path.resolve())
355
+
356
+
357
+ # filter out know 'weird' files that can be created during conversion
358
+ if not keep_all_niftis:
359
+ files_to_remove = []
360
+ short_runs = list(tmp_nifti_path.glob("[!.]*[a-z].nii*")) + list(tmp_nifti_path.glob("[!.]*[a-z].json"))
361
+ for sr in short_runs:
362
+ suffix = None
363
+ if sr.name.endswith(".nii.gz"):
364
+ suffix = ".nii.gz"
365
+ elif sr.name.endswith(".nii"):
366
+ suffix = ".nii"
367
+ elif sr.name.endswith(".json"):
368
+ suffix = ".json"
369
+ else:
370
+ continue
371
+ if (sr.parent / f"{sr.name.removesuffix(suffix)[:-1]}{suffix}").exists():
372
+ files_to_remove.append(sr)
373
+
374
+ for jf in tmp_nifti_path.glob("[!.]*.json"):
375
+ with open(jf, "r") as f:
376
+ jd = json.load(f)
377
+ if int(jd["SeriesNumber"]) > 1000:
378
+ files_to_remove.extend(list(tmp_nifti_path.glob(f"{jf.stem}.*")))
379
+
380
+ if len(files_to_remove) > 0:
381
+ logger.info("filtering out NIFTI files")
382
+ file_list_string = '\n\t'.join([str(f) for f in files_to_remove])
383
+ if flags.debug:
384
+ unused_files_dir = tmp_nifti_path.parent / f"{tmp_nifti_path.name}_unused"
385
+ unused_files_dir.mkdir(exist_ok=True)
386
+ logger.debug(f"moving some unused files and files created from shortened runs to directory {unused_files_dir}:\n\t{file_list_string}")
387
+ for f in files_to_remove:
388
+ shutil.move(f.resolve(), (unused_files_dir / f.name).resolve())
389
+ else:
390
+ file_list_string = '\n\t'.join([str(f) for f in files_to_remove])
391
+ logger.info(f"removing some unused files and files created from shortened runs :\n\t{file_list_string}")
392
+ for f in files_to_remove:
393
+ os.remove(f)
367
394
 
368
- add_information_to_sidecar(nifti_dir=nifti_path,
395
+ add_information_to_sidecar(nifti_dir=tmp_nifti_path,
369
396
  usability_file=usability_file,
370
397
  session_number=session_index)
371
398
 
372
399
  run_dcm2bids(subject=subject,
373
400
  session=session,
374
- nifti_dir=nifti_path,
401
+ nifti_dir=tmp_nifti_path,
375
402
  bids_output_dir=bids_dir,
376
403
  config_file=bids_config,
377
404
  nordic_config=nordic_config,
@@ -121,6 +121,8 @@ def main():
121
121
  help="The path to the second dcm2bids config file to use for this subject and session. This implies that the session contains NORDIC data")
122
122
  config_args.add_argument("--nifti", action=argparse.BooleanOptionalAction,
123
123
  help="Flag to specify that the source directory contains files of type NIFTI (.nii/.jsons) instead of DICOM")
124
+ config_args.add_argument("--keep_all_niftis", action=argparse.BooleanOptionalAction,
125
+ help="Oceanproc will try its best to remove 'weird' NIFTI files that can be introduced during conversion from DICOM. This flag specifies that oceanproc should not do that and keep all of the files instead.")
124
126
  config_args.add_argument("--anat_only", action=argparse.BooleanOptionalAction,
125
127
  help="Flag to specify only anatomical images should be processed.")
126
128
  config_args.add_argument("--fd_spike_threshold", "-fd", type=float, default=0.9,
@@ -258,7 +260,8 @@ def main():
258
260
  nifti=args.nifti,
259
261
  skip_validate=args.skip_bids_validation,
260
262
  skip_prompt=index > 0,
261
- session_index=index
263
+ session_index=index,
264
+ keep_all_niftis=args.keep_all_niftis
262
265
  )
263
266
  if index > 0:
264
267
  extend_session(subject=args.subject,
@@ -256,16 +256,27 @@ def insert_dummy_frames(subject:str,
256
256
  for bfile in func_files:
257
257
  if not Path(bfile.path).exists:
258
258
  continue
259
+
259
260
  # Find the dscans file for bold run
261
+ try_find = True
260
262
  dscans_entities = bids_layout.parse_file_entities(bfile.path) | {"suffix":dscans_suffix, "extension":".tsv"}
261
- dscans_bids_path = bids_layout.build_path(dscans_entities, path_patterns=[dscans_path_pattern], validate=False)
262
- dscans_file = sorted(dscan_dir.glob(Path(dscans_bids_path).name))
263
- if len(dscans_file) > 1:
264
- exit_program_early(f"Found more than one dscans file for bold run {bfile} --> {dscans_file}")
265
- elif len(dscans_file) == 0:
263
+ while try_find:
264
+ dscans_bids_path = bids_layout.build_path(dscans_entities, path_patterns=[dscans_path_pattern], validate=False)
265
+ dscans_file = sorted(dscan_dir.glob(Path(dscans_bids_path).name))
266
+ if len(dscans_file) > 1:
267
+ exit_program_early(f"Found more than one dscans file for bold run {bfile} --> {dscans_file}")
268
+ elif len(dscans_file) == 1:
269
+ try_find = False
270
+ if ("echo" in dscans_entities) and try_find:
271
+ del dscans_entities["echo"]
272
+ else:
273
+ try_find = False
274
+
275
+ if len(dscans_file) == 0:
266
276
  logger.info(f"Did not find any dscans files for bold run: {bfile}, file will remain unmodified.")
267
277
  continue
268
- dscans_file = dscans_file[0]
278
+ else:
279
+ dscans_file = dscans_file[0]
269
280
  logger.info(f"found dscans file <{dscans_file.name}> for bold run <{bfile.filename}>")
270
281
 
271
282
  dscans_list = pd.read_csv(dscans_file, sep="\t").loc[:, "dummy_scan"].to_numpy().astype(np.int32)
@@ -34,7 +34,7 @@ dependencies = [
34
34
  "pybids>=0.16.3",
35
35
  ]
36
36
  name = "oceanproc"
37
- version = "1.2.0"
37
+ version = "1.2.1"
38
38
  description = "MRI preprocessing for WUSTL Ocean labs"
39
39
  readme = "README.md"
40
40
 
File without changes
File without changes