biapy 3.4.3__tar.gz → 3.4.4__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 (87) hide show
  1. {biapy-3.4.3 → biapy-3.4.4}/PKG-INFO +1 -1
  2. {biapy-3.4.3 → biapy-3.4.4}/biapy/config/config.py +28 -5
  3. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/data_3D_manipulation.py +69 -7
  4. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/__init__.py +6 -4
  5. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/pair_base_data_generator.py +3 -32
  6. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/pre_processing.py +122 -15
  7. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/base_workflow.py +248 -220
  8. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/check_configuration.py +38 -19
  9. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/instance_seg.py +98 -33
  10. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/run_checks.py +545 -182
  11. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/tif_to_h5.py +1 -1
  12. biapy-3.4.4/biapy/utils/scripts/tif_to_zarr.py +43 -0
  13. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/util.py +33 -0
  14. {biapy-3.4.3 → biapy-3.4.4}/biapy.egg-info/PKG-INFO +1 -1
  15. {biapy-3.4.3 → biapy-3.4.4}/biapy.egg-info/SOURCES.txt +2 -1
  16. {biapy-3.4.3 → biapy-3.4.4}/pyproject.toml +1 -1
  17. {biapy-3.4.3 → biapy-3.4.4}/LICENSE.md +0 -0
  18. {biapy-3.4.3 → biapy-3.4.4}/README.md +0 -0
  19. {biapy-3.4.3 → biapy-3.4.4}/biapy/__init__.py +0 -0
  20. {biapy-3.4.3 → biapy-3.4.4}/biapy/_biapy.py +0 -0
  21. {biapy-3.4.3 → biapy-3.4.4}/biapy/config/__init__.py +0 -0
  22. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/__init__.py +0 -0
  23. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/data_2D_manipulation.py +0 -0
  24. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/augmentors.py +0 -0
  25. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/pair_data_2D_generator.py +0 -0
  26. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/pair_data_3D_generator.py +0 -0
  27. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/single_base_data_generator.py +0 -0
  28. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/single_data_2D_generator.py +0 -0
  29. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/single_data_3D_generator.py +0 -0
  30. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/test_pair_data_generators.py +0 -0
  31. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/generators/test_single_data_generator.py +0 -0
  32. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/post_processing/__init__.py +0 -0
  33. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/post_processing/post_processing.py +0 -0
  34. {biapy-3.4.3 → biapy-3.4.4}/biapy/data/post_processing/smooth_tiled_predictions.py +0 -0
  35. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/__init__.py +0 -0
  36. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/classification.py +0 -0
  37. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/denoising.py +0 -0
  38. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/detection.py +0 -0
  39. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/image_to_image.py +0 -0
  40. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/metrics.py +0 -0
  41. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/schedulers/warmup_cosine_decay.py +0 -0
  42. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/self_supervised.py +0 -0
  43. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/semantic_seg.py +0 -0
  44. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/super_resolution.py +0 -0
  45. {biapy-3.4.3 → biapy-3.4.4}/biapy/engine/train_engine.py +0 -0
  46. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/__init__.py +0 -0
  47. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/attention_unet.py +0 -0
  48. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/blocks.py +0 -0
  49. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/dfcan.py +0 -0
  50. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/edsr.py +0 -0
  51. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/efficientnet.py +0 -0
  52. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/mae.py +0 -0
  53. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/multiresunet.py +0 -0
  54. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/rcan.py +0 -0
  55. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/resunet++.py +0 -0
  56. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/resunet.py +0 -0
  57. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/seunet.py +0 -0
  58. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/simple_cnn.py +0 -0
  59. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/tr_layers.py +0 -0
  60. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/unet.py +0 -0
  61. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/unetr.py +0 -0
  62. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/vit.py +0 -0
  63. {biapy-3.4.3 → biapy-3.4.4}/biapy/models/wdsr.py +0 -0
  64. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/callbacks.py +0 -0
  65. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/matching.py +0 -0
  66. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/misc.py +0 -0
  67. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/calculate_detection_metrics.py +0 -0
  68. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/calculate_metrics_3D.py +0 -0
  69. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/create_probability_csv.py +0 -0
  70. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/crop_2D_dataset.py +0 -0
  71. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/crop_3D_dataset.py +0 -0
  72. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/crop_and_discard_3D_dataset.py +0 -0
  73. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/detection_plots.py +0 -0
  74. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/detection_probs_to_points.py +0 -0
  75. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/fill_holes_in_seg_masks.py +0 -0
  76. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/filter_close_points.py +0 -0
  77. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/from_class_csv_to_folders.py +0 -0
  78. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/h5_to_tif.py +0 -0
  79. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/h5_to_zarr.py +0 -0
  80. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/lightmycell_data_preparation.py +0 -0
  81. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/merge_dataset_channels.py +0 -0
  82. {biapy-3.4.3 → biapy-3.4.4}/biapy/utils/scripts/order_axes.py +0 -0
  83. {biapy-3.4.3 → biapy-3.4.4}/biapy.egg-info/dependency_links.txt +0 -0
  84. {biapy-3.4.3 → biapy-3.4.4}/biapy.egg-info/entry_points.txt +0 -0
  85. {biapy-3.4.3 → biapy-3.4.4}/biapy.egg-info/requires.txt +0 -0
  86. {biapy-3.4.3 → biapy-3.4.4}/biapy.egg-info/top_level.txt +0 -0
  87. {biapy-3.4.3 → biapy-3.4.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: biapy
3
- Version: 3.4.3
3
+ Version: 3.4.4
4
4
  Summary: BiaPy: Bioimage analysis pipelines in Python
5
5
  Author-email: Daniel Franco-Barranco <daniel.franco@dipc.org>
6
6
  Maintainer-email: Daniel Franco-Barranco <daniel.franco@dipc.org>
@@ -216,6 +216,13 @@ class Config:
216
216
  _C.DATA.TRAIN.IN_MEMORY = True
217
217
  _C.DATA.TRAIN.PATH = os.path.join("user_data", 'train', 'x')
218
218
  _C.DATA.TRAIN.GT_PATH = os.path.join("user_data", 'train', 'y')
219
+ # Whether if your input Zarr contains the raw images and labels together or not. Use 'DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH'
220
+ # and 'DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_GT_PATH' to determine the tag to find within the Zarr
221
+ _C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA = False
222
+ # Paths to the raw and gt within the Zarr file. Only used when 'DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA' is True.
223
+ # E.g. 'volumes.raw' for raw and 'volumes.labels.neuron_ids' for GT path.
224
+ _C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH = ''
225
+ _C.DATA.TRAIN.INPUT_ZARR_MULTIPLE_DATA_GT_PATH = ''
219
226
  # File to load/save data prepared with the appropiate channels in a instance segmentation problem.
220
227
  # E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
221
228
  _C.DATA.TRAIN.INSTANCE_CHANNELS_DIR = os.path.join("user_data", 'train', 'x_'+_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
@@ -240,9 +247,9 @@ class Config:
240
247
  # Minimum foreground percentage that each image loaded need to have to not discard it (only used when TRAIN.IN_MEMORY == True).
241
248
  # This option is only valid for SEMANTIC_SEG, INSTANCE_SEG and DETECTION.
242
249
  _C.DATA.TRAIN.MINIMUM_FOREGROUND_PER = -1.
243
- # Order of the axes of the image when using Zarr/H5 images to train
250
+ # Order of the axes of the image when using Zarr/H5 images in train data.
244
251
  _C.DATA.TRAIN.INPUT_IMG_AXES_ORDER = 'TZCYX'
245
- # Order of the axes of the mask when using Zarr/H5 images to train
252
+ # Order of the axes of the mask when using Zarr/H5 images in train data.
246
253
  _C.DATA.TRAIN.INPUT_MASK_AXES_ORDER = 'TZCYX'
247
254
 
248
255
  # PREPROCESSING
@@ -370,6 +377,13 @@ class Config:
370
377
  _C.DATA.VAL.PATH = os.path.join("user_data", 'val', 'x')
371
378
  # Path to the validation data mask. Used when _C.DATA.VAL.FROM_TRAIN = False
372
379
  _C.DATA.VAL.GT_PATH = os.path.join("user_data", 'val', 'y')
380
+ # Whether if your input Zarr contains the raw images and labels together or not. Use 'DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH'
381
+ # and 'DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_GT_PATH' to determine the tag to find within the Zarr
382
+ _C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA = False
383
+ # Paths to the raw and gt within the Zarr file. Only used when 'DATA.VAL.INPUT_ZARR_MULTIPLE_DATA' is True.
384
+ # E.g. 'volumes.raw' for raw and 'volumes.labels.neuron_ids' for GT path.
385
+ _C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH = ''
386
+ _C.DATA.VAL.INPUT_ZARR_MULTIPLE_DATA_GT_PATH = ''
373
387
  # File to load/save data prepared with the appropiate channels in a instance segmentation problem.
374
388
  # E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
375
389
  _C.DATA.VAL.INSTANCE_CHANNELS_DIR = os.path.join("user_data", 'val', 'x_'+_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
@@ -388,10 +402,9 @@ class Config:
388
402
  _C.DATA.VAL.PADDING = (0,0)
389
403
  # Not used yet.
390
404
  _C.DATA.VAL.RESOLUTION = (-1,)
391
- # Order of the axes of the image when using Zarr/H5 images to train
405
+ # Order of the axes of the image when using Zarr/H5 images in validation data.
392
406
  _C.DATA.VAL.INPUT_IMG_AXES_ORDER = 'TZCYX'
393
- # Order of the axes of the mask when using Zarr/H5 images to train.
394
- # detection the mask
407
+ # Order of the axes of the mask when using Zarr/H5 images in validation data.
395
408
  _C.DATA.VAL.INPUT_MASK_AXES_ORDER = 'TZCYX'
396
409
 
397
410
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -820,6 +833,16 @@ class Config:
820
833
  _C.TEST.BY_CHUNKS.FLUSH_EACH = 100
821
834
  # Input Numpy/Zarr/H5 image's axes order. Options: ['TZCYX', 'TZYXC', 'ZCYX', 'ZYXC']
822
835
  _C.TEST.BY_CHUNKS.INPUT_IMG_AXES_ORDER = 'TZCYX'
836
+ # Input Numpy/Zarr/H5 image's axes order. Options: ['TZCYX', 'TZYXC', 'ZCYX', 'ZYXC']
837
+ _C.TEST.BY_CHUNKS.INPUT_MASK_AXES_ORDER = 'TZCYX'
838
+ # Whether if your input Zarr contains the raw images and labels together or not. Use 'TEST.BY_CHUNKS.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH'
839
+ # and 'TEST.BY_CHUNKS.INPUT_ZARR_MULTIPLE_DATA_GT_PATH' to determine the tag to find within the Zarr
840
+ _C.TEST.BY_CHUNKS.INPUT_ZARR_MULTIPLE_DATA = False
841
+ # Paths to the raw and gt within the Zarr file. Only used when 'TEST.BY_CHUNKS.INPUT_ZARR_MULTIPLE_DATA' is True.
842
+ # E.g. 'volumes.raw' for raw and 'volumes.labels.neuron_ids' for GT path.
843
+ _C.TEST.BY_CHUNKS.INPUT_ZARR_MULTIPLE_DATA_RAW_PATH = ''
844
+ _C.TEST.BY_CHUNKS.INPUT_ZARR_MULTIPLE_DATA_GT_PATH = ''
845
+
823
846
  # Whether if after reconstructing the prediction the pipeline will continue each workflow specific steps. For this process
824
847
  # the prediction image needs to be loaded into memory so be sure that it can fit in you memory. E.g. in instance
825
848
  # segmentation the instances will be created from the prediction.
@@ -6,7 +6,7 @@ from skimage.io import imread
6
6
  from tqdm import tqdm
7
7
  from sklearn.model_selection import train_test_split, StratifiedKFold
8
8
 
9
- from biapy.utils.util import load_3d_images_from_dir, order_dimensions, read_chunked_data
9
+ from biapy.utils.util import load_3d_images_from_dir, order_dimensions, read_chunked_data, read_chunked_nested_data
10
10
  from biapy.utils.misc import is_main_process
11
11
 
12
12
  def load_and_prepare_3D_data(train_path, train_mask_path, cross_val=False, cross_val_nsplits=5, cross_val_fold=1,
@@ -381,7 +381,7 @@ def load_and_prepare_3D_data(train_path, train_mask_path, cross_val=False, cross
381
381
 
382
382
  def load_and_prepare_3D_efficient_format_data(train_path, train_mask_path, input_img_axes, input_mask_axes=None, cross_val=False,
383
383
  cross_val_nsplits=5, cross_val_fold=1, val_split=0.1, seed=0, shuffle_val=True, crop_shape=(80, 80, 80, 1), y_upscaling=(1,1,1),
384
- ov=(0,0,0), padding=(0,0,0), minimum_foreground_perc=-1):
384
+ ov=(0,0,0), padding=(0,0,0), minimum_foreground_perc=-1, multiple_data_within_zarr=None):
385
385
  """
386
386
  Load train and validation images from the given paths to create 3D data.
387
387
 
@@ -433,6 +433,9 @@ def load_and_prepare_3D_efficient_format_data(train_path, train_mask_path, input
433
433
  minimum_foreground_perc : float, optional
434
434
  Minimum percetnage of foreground that a sample need to have no not be discarded.
435
435
 
436
+ multiple_data_within_zarr : dict, optional
437
+ Additional information of where to find the data within the Zarr files.
438
+
436
439
  Returns
437
440
  -------
438
441
  X_train : 5D Numpy array
@@ -457,7 +460,9 @@ def load_and_prepare_3D_efficient_format_data(train_path, train_mask_path, input
457
460
  create_val = False
458
461
 
459
462
  print("0) Loading train image information . . .")
460
- X_train, X_train_total_patches = load_3D_efficient_files(train_path, input_img_axes, crop_shape, ov, padding)
463
+ data_within_zarr_path = multiple_data_within_zarr['raw_path'] if multiple_data_within_zarr is not None else None
464
+ X_train, X_train_total_patches = load_3D_efficient_files(train_path, input_img_axes, crop_shape, ov, padding,
465
+ data_within_zarr_path=data_within_zarr_path)
461
466
 
462
467
  if train_mask_path is not None:
463
468
  if input_mask_axes is None:
@@ -465,8 +470,11 @@ def load_and_prepare_3D_efficient_format_data(train_path, train_mask_path, input
465
470
 
466
471
  print("0) Loading train GT information . . .")
467
472
  scrop = (crop_shape[0]*y_upscaling[0], crop_shape[1]*y_upscaling[1], crop_shape[2]*y_upscaling[2], crop_shape[3])
473
+ data_within_zarr_path = None
474
+ if multiple_data_within_zarr is not None and multiple_data_within_zarr['use_gt_path']:
475
+ data_within_zarr_path = multiple_data_within_zarr['gt_path']
468
476
  Y_train, Y_train_total_patches = load_3D_efficient_files(train_mask_path, input_mask_axes, scrop, ov, padding,
469
- check_channel=False)
477
+ check_channel=False, data_within_zarr_path=data_within_zarr_path)
470
478
 
471
479
  for i in range(len(Y_train_total_patches)):
472
480
  if Y_train_total_patches[i] != X_train_total_patches[i]:
@@ -629,7 +637,8 @@ def load_and_prepare_3D_efficient_format_data(train_path, train_mask_path, input
629
637
  print("*** Loaded train GT shape is: {}".format(yshape))
630
638
  return X_train, Y_train
631
639
 
632
- def load_3D_efficient_files(data_path, input_axes, crop_shape, overlap, padding, check_channel=True):
640
+ def load_3D_efficient_files(data_path, input_axes, crop_shape, overlap, padding, check_channel=True,
641
+ data_within_zarr_path=None):
633
642
  """
634
643
  Load information of all patches that can be extracted from all the Zarr/H5 samples in ``data_path``.
635
644
 
@@ -654,6 +663,9 @@ def load_3D_efficient_files(data_path, input_axes, crop_shape, overlap, padding,
654
663
  check_channel : bool, optional
655
664
  Whether to check if the crop_shape channel matches with the loaded images' one.
656
665
 
666
+ data_within_zarr_path : str, optional
667
+ Path to find the data within the Zarr file. E.g. 'volumes.labels.neuron_ids'.
668
+
657
669
  Returns
658
670
  -------
659
671
  data_info : dict
@@ -669,8 +681,11 @@ def load_3D_efficient_files(data_path, input_axes, crop_shape, overlap, padding,
669
681
 
670
682
  for i, filename in enumerate(data_path):
671
683
  print(f"Reading Zarr/H5 file: {filename}")
672
- file, data = read_chunked_data(filename)
673
-
684
+ if data_within_zarr_path:
685
+ file, data = read_chunked_nested_data(filename, data_within_zarr_path)
686
+ else:
687
+ file, data = read_chunked_data(filename)
688
+
674
689
  # Modify crop_shape with the channel
675
690
  c_index = -1
676
691
  try:
@@ -714,6 +729,53 @@ def load_3D_efficient_files(data_path, input_axes, crop_shape, overlap, padding,
714
729
 
715
730
  return data_info, data_total_patches
716
731
 
732
+ def load_img_part_from_efficient_file(filepath, patch_coords, data_axis_order="ZYXC", data_path=None):
733
+ """
734
+ Loads from ``filepath`` the patch determined by ``patch_coords``.
735
+
736
+ Parameters
737
+ ----------
738
+ filepath : str
739
+ Path to the Zarr/H5 file to read the patch from.
740
+
741
+ patch_coords : Tuple of tuples of ints
742
+ Coordinates of patch to extract.
743
+
744
+ data_axis_order : str
745
+ Order of axes of ``data``. E.g. 'TZCYX', 'TZYXC', 'ZCYX', 'ZYXC'.
746
+
747
+ data_path : str, optional
748
+ Path to find the data within the Zarr file. E.g. 'volumes.labels.neuron_ids'.
749
+
750
+ Returns
751
+ -------
752
+ img : Numpy array
753
+ Extracted patch. E.g. ``(z, y, x, channels)``.
754
+ """
755
+ if data_path is not None:
756
+ imgfile, img = read_chunked_nested_data(filepath, data_path)
757
+ else:
758
+ imgfile, img = read_chunked_data(filepath)
759
+
760
+ # Prepare slices to extract the patch
761
+ slices = []
762
+ for j in range(len(patch_coords)):
763
+ if isinstance(patch_coords[j], int):
764
+ # +1 to prevent 0 length axes that can not be removed with np.squeeze later
765
+ slices.append(slice(0,patch_coords[j]+1))
766
+ else:
767
+ slices.append(slice(patch_coords[j][0],patch_coords[j][1]))
768
+
769
+ slices = tuple(slices)
770
+ data_ordered_slices = tuple(order_dimensions(slices, input_order="ZYXC", output_order=data_axis_order,
771
+ default_value=0))
772
+ img = np.squeeze(np.array(img[data_ordered_slices]))
773
+
774
+ if isinstance(imgfile, h5py.File):
775
+ imgfile.close()
776
+
777
+ return img
778
+
717
779
  def crop_3D_data_with_overlap(data, vol_shape, data_mask=None, overlap=(0,0,0), padding=(0,0,0), verbose=True,
718
780
  median_padding=False):
719
781
  """Crop 3D data into smaller volumes with a defined overlap. The opposite function is :func:`~merge_3D_data_with_overlap`.
@@ -121,8 +121,9 @@ def create_train_val_augmentors(cfg, X_train, Y_train, X_val, Y_val, world_size,
121
121
  if cfg.DATA.TRAIN.IN_MEMORY:
122
122
  data_mode = "in_memory"
123
123
  else:
124
- if cfg.PROBLEM.NDIM == '3D' and X_train is not None and isinstance(X_train, list) and isinstance(X_train[0], dict) and \
125
- 'filepath' in X_train[0] and ('.zarr' in X_train[0]['filepath'] or '.h5' in X_train[0]['filepath']):
124
+ if cfg.PROBLEM.NDIM == '3D' and X_train is not None and (isinstance(X_train, list) or isinstance(X_train, dict)) and \
125
+ isinstance(X_train[0], dict) and 'filepath' in X_train[0] and ('.zarr' in X_train[0]['filepath'] or \
126
+ '.h5' in X_train[0]['filepath']):
126
127
  data_mode = "chunked_data"
127
128
  else:
128
129
  data_mode = "not_in_memory"
@@ -226,8 +227,9 @@ def create_train_val_augmentors(cfg, X_train, Y_train, X_val, Y_val, world_size,
226
227
  if cfg.DATA.VAL.IN_MEMORY:
227
228
  val_data_mode = "in_memory"
228
229
  else:
229
- if cfg.PROBLEM.NDIM == '3D' and X_val is not None and isinstance(X_val, list) and isinstance(X_val[0], dict) and \
230
- 'filepath' in X_val[0] and ('.zarr' in X_val[0]['filepath'] or '.h5' in X_val[0]['filepath']):
230
+ if cfg.PROBLEM.NDIM == '3D' and X_val is not None and (isinstance(X_val, list) or isinstance(X_val, dict)) and \
231
+ isinstance(X_val[0], dict) and 'filepath' in X_val[0] and ('.zarr' in X_val[0]['filepath'] or \
232
+ '.h5' in X_val[0]['filepath']):
231
233
  val_data_mode = "chunked_data"
232
234
  else:
233
235
  val_data_mode = "not_in_memory"
@@ -18,6 +18,7 @@ from biapy.utils.util import img_to_onehot_encoding, pad_and_reflect, read_chunk
18
18
  from biapy.data.generators.augmentors import *
19
19
  from biapy.data.pre_processing import normalize, norm_range01, percentile_clip
20
20
  from biapy.utils.misc import is_main_process
21
+ from biapy.data.data_3D_manipulation import load_img_part_from_efficient_file
21
22
 
22
23
  class PairBaseDataGenerator(Dataset, metaclass=ABCMeta):
23
24
  """
@@ -832,39 +833,9 @@ class PairBaseDataGenerator(Dataset, metaclass=ABCMeta):
832
833
  if self.Y_provided:
833
834
  mask = np.squeeze(mask)
834
835
  else: # self.data_mode == "chunked_data"
835
- imgfile, img = read_chunked_data(self.X[idx]['filepath'])
836
-
837
- # Prepare slices to extract the patch
838
- slices = []
839
- for j in range(len(self.X[idx]['patch_coords'])):
840
- if isinstance(self.X[idx]['patch_coords'][j], int):
841
- # +1 to prevent 0 length axes that can not be removed with np.squeeze later
842
- slices.append(slice(0,self.X[idx]['patch_coords'][j]+1))
843
- else:
844
- slices.append(slice(self.X[idx]['patch_coords'][j][0],self.X[idx]['patch_coords'][j][1]))
845
-
846
- img = np.squeeze(np.array(img[tuple(slices)]))
847
-
848
- if isinstance(imgfile, h5py.File):
849
- imgfile.close()
850
-
836
+ img = load_img_part_from_efficient_file(self.X[idx]['filepath'], self.X[idx]['patch_coords'])
851
837
  if self.Y_provided:
852
- maskfile, mask = read_chunked_data(self.Y[idx]['filepath'])
853
-
854
- # Prepare slices to extract the patch
855
- slices = []
856
- for j in range(len(self.Y[idx]['patch_coords'])):
857
- if isinstance(self.Y[idx]['patch_coords'][j], int):
858
- # +1 to prevent 0 length axes that can not be removed with np.squeeze later
859
- slices.append(slice(0,self.Y[idx]['patch_coords'][j]+1))
860
- else:
861
- slices.append(slice(self.Y[idx]['patch_coords'][j][0],self.Y[idx]['patch_coords'][j][1]))
862
-
863
- mask = np.squeeze(np.array(mask[tuple(slices)]))
864
-
865
- if isinstance(maskfile, h5py.File):
866
- maskfile.close()
867
-
838
+ mask = load_img_part_from_efficient_file(self.Y[idx]['filepath'], self.Y[idx]['patch_coords'])
868
839
  if self.Y_provided:
869
840
  img, mask = self.ensure_shape(img, mask)
870
841
  else:
@@ -2,6 +2,7 @@ import os
2
2
  import torch
3
3
  import scipy
4
4
  import h5py
5
+ import zarr
5
6
  import numpy as np
6
7
  from tqdm import tqdm
7
8
  import pandas as pd
@@ -17,8 +18,10 @@ from skimage.exposure import equalize_adapthist
17
18
  from skimage.color import rgb2gray
18
19
  from skimage.filters import gaussian, median
19
20
 
20
- from biapy.utils.util import load_data_from_dir, load_3d_images_from_dir, save_tif, write_chunked_data, read_chunked_data
21
+ from biapy.utils.util import (load_data_from_dir, load_3d_images_from_dir, save_tif, write_chunked_data, read_chunked_data,
22
+ order_dimensions)
21
23
  from biapy.utils.misc import is_main_process
24
+ from biapy.data.data_3D_manipulation import load_3D_efficient_files, load_img_part_from_efficient_file
22
25
 
23
26
  #########################
24
27
  # INSTANCE SEGMENTATION #
@@ -42,10 +45,41 @@ def create_instance_channels(cfg, data_type='train'):
42
45
  """
43
46
 
44
47
  assert data_type in ['train', 'val']
45
-
46
- f_name = load_data_from_dir if cfg.PROBLEM.NDIM == '2D' else load_3d_images_from_dir
47
48
  tag = "TRAIN" if data_type == "train" else "VAL"
48
- Y, _, _, filenames = f_name(getattr(cfg.DATA, tag).GT_PATH, check_drange=False, return_filenames=True)
49
+
50
+ # Checking if the user inputted Zarr/H5 files
51
+ if getattr(cfg.DATA, tag).INPUT_ZARR_MULTIPLE_DATA:
52
+ zarr_files = sorted(next(os.walk(getattr(cfg.DATA, tag).PATH))[1])
53
+ h5_files = sorted(next(os.walk(getattr(cfg.DATA, tag).PATH))[2])
54
+ else:
55
+ zarr_files = sorted(next(os.walk(getattr(cfg.DATA, tag).GT_PATH))[1])
56
+ h5_files = sorted(next(os.walk(getattr(cfg.DATA, tag).GT_PATH))[2])
57
+
58
+ # Find patches info so we can iterate over them to create the instance mask
59
+ working_with_zarr_h5_files = False
60
+ if cfg.PROBLEM.NDIM == '3D' and (len(zarr_files) > 0 and '.zarr' in zarr_files[0]) or \
61
+ (len(h5_files) > 0 and '.h5' in h5_files[0]):
62
+ working_with_zarr_h5_files = True
63
+ # Check if the raw images and labels are within the same file
64
+ mult_dat = None
65
+ data_path = getattr(cfg.DATA, tag).GT_PATH
66
+ if getattr(cfg.DATA, tag).INPUT_ZARR_MULTIPLE_DATA:
67
+ data_path = getattr(cfg.DATA, tag).PATH
68
+
69
+ if len(zarr_files) > 0 and '.zarr' in zarr_files[0]:
70
+ print("Working with Zarr files . . .")
71
+ img_files = [os.path.join(data_path, x) for x in zarr_files]
72
+ elif len(h5_files) > 0 and '.h5' in h5_files[0]:
73
+ print("Working with H5 files . . .")
74
+ img_files = [os.path.join(data_path, x) for x in h5_files]
75
+
76
+ Y, Y_total_patches = load_3D_efficient_files(img_files, input_axes=getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER,
77
+ crop_shape=cfg.DATA.PATCH_SIZE, overlap=getattr(cfg.DATA, tag).OVERLAP, padding=getattr(cfg.DATA, tag).PADDING)
78
+ else:
79
+ f_name = load_data_from_dir if cfg.PROBLEM.NDIM == '2D' else load_3d_images_from_dir
80
+ Y, _, _, filenames = f_name(getattr(cfg.DATA, tag).GT_PATH, check_drange=False, return_filenames=True)
81
+ del zarr_files, h5_files
82
+
49
83
  print("Creating Y_{} channels . . .".format(data_type))
50
84
  if isinstance(Y, list):
51
85
  for i in tqdm(range(len(Y)), disable=not is_main_process()):
@@ -61,6 +95,78 @@ def create_instance_channels(cfg, data_type='train'):
61
95
  else:
62
96
  Y[i] = labels_into_channels(Y[i], mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CHANNELS, save_dir=getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'),
63
97
  fb_mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE)
98
+ # Create the mask patch by patch (Zarr/H5)
99
+ elif working_with_zarr_h5_files and isinstance(Y, dict):
100
+ savepath = data_path+'_'+cfg.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+cfg.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
101
+ if 'D' in cfg.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE:
102
+ dtype_str = "float32"
103
+ raise ValueError("Currently distance creation using Zarr by chunks is not implemented.")
104
+ else:
105
+ dtype_str = "uint8"
106
+
107
+ mask = None
108
+ last_zarr_file = None
109
+ for i in tqdm(range(len(Y.keys())), disable=not is_main_process()):
110
+ # Extract the patch to process
111
+ patch_coords = Y[i]['patch_coords']
112
+ img = load_img_part_from_efficient_file(Y[i]['filepath'], patch_coords,
113
+ data_axis_order=getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER,
114
+ data_path=getattr(cfg.DATA, tag).INPUT_ZARR_MULTIPLE_DATA_GT_PATH)
115
+ if img.ndim == 3: img = np.expand_dims(img,-1)
116
+ if img.ndim == 4: img = np.expand_dims(img,0)
117
+
118
+ # Create the instance mask
119
+ if cfg.MODEL.N_CLASSES > 2:
120
+ if img.shape[-1] != 2:
121
+ raise ValueError("In instance segmentation, when 'MODEL.N_CLASSES' are more than 2 labels need to have two channels, "
122
+ "e.g. (256,256,2), containing the instance segmentation map (first channel) and classification map (second channel).")
123
+ else:
124
+ class_channel = np.expand_dims(img[...,1].copy(),-1)
125
+ img = labels_into_channels(img, mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CHANNELS, save_dir=getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'),
126
+ fb_mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE)
127
+ img = np.concatenate([img,class_channel],axis=-1)
128
+ else:
129
+ img = labels_into_channels(img, mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CHANNELS, save_dir=getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'),
130
+ fb_mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE)
131
+ img = img[0]
132
+
133
+ # Create the Zarr file where the mask will be placed
134
+ if mask is None or os.path.basename(Y[i]['filepath']) != last_zarr_file:
135
+ last_zarr_file = os.path.basename(Y[i]['filepath'])
136
+ imgfile, data = read_chunked_data(Y[i]['filepath'])
137
+ fname = os.path.join(savepath, os.path.basename(Y[i]['filepath']))
138
+ fid_mask = zarr.open_group(fname, mode="w")
139
+
140
+ # Determine data shape
141
+ out_data_shape = np.array(data.shape)
142
+ if "C" not in getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER:
143
+ out_data_shape = tuple(out_data_shape) + (img.shape[-1],)
144
+ out_data_order = getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER + "C"
145
+ channel_pos = -1
146
+ else:
147
+ out_data_shape[getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER.index("C")] = 1
148
+ out_data_shape = tuple(out_data_shape)
149
+ out_data_order = getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER
150
+ channel_pos = getattr(cfg.DATA, tag).INPUT_IMG_AXES_ORDER.index("C")
151
+
152
+ mask = fid_mask.create_dataset("data", shape=out_data_shape, dtype=dtype_str)
153
+ del data, imgfile, fname
154
+
155
+ # Adjust slices to calculate where to insert the predicted patch. This slice does not have into account the
156
+ # channel so any of them can be inserted
157
+ slices = (slice(patch_coords[0][0],patch_coords[0][1]), slice(patch_coords[1][0],patch_coords[1][1]),
158
+ slice(patch_coords[2][0],patch_coords[2][1]), slice(0,out_data_shape[channel_pos]))
159
+ data_ordered_slices = tuple(order_dimensions(slices, input_order="ZYXC",
160
+ output_order=out_data_order, default_value=0))
161
+
162
+ # Adjust patch slice to transpose it before inserting intop the final data
163
+ current_order = np.array(range(len(img.shape)))
164
+ transpose_order = order_dimensions(current_order, input_order="ZYXC", output_order=out_data_order,
165
+ default_value=np.nan)
166
+ transpose_order = [x for x in transpose_order if not np.isnan(x)]
167
+
168
+ # Place the patch into the Zarr
169
+ mask[data_ordered_slices] = img.transpose(transpose_order)
64
170
  else:
65
171
  if cfg.MODEL.N_CLASSES > 2:
66
172
  if Y.shape[-1] != 2:
@@ -75,17 +181,18 @@ def create_instance_channels(cfg, data_type='train'):
75
181
  Y = labels_into_channels(Y, mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CHANNELS, save_dir=getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'),
76
182
  fb_mode=cfg.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE)
77
183
 
78
- save_tif(Y, data_dir=getattr(cfg.DATA, tag).INSTANCE_CHANNELS_MASK_DIR, filenames=filenames, verbose=cfg.TEST.VERBOSE)
79
- X, _, _, filenames = f_name(getattr(cfg.DATA, tag).PATH, return_filenames=True)
80
- print("Creating X_{} channels . . .".format(data_type))
81
- save_tif(X, data_dir=getattr(cfg.DATA, tag).INSTANCE_CHANNELS_DIR, filenames=filenames, verbose=cfg.TEST.VERBOSE)
82
-
83
- # Save original X data with the labels
84
- for i in range(min(3,len(X))):
85
- if isinstance(X, list):
86
- save_tif(X[i], getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'), filenames=['vol'+str(i)+".tif"], verbose=False)
87
- else:
88
- save_tif(np.expand_dims(X[i],0), getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'), filenames=['vol'+str(i)+".tif"], verbose=False)
184
+ if not working_with_zarr_h5_files:
185
+ save_tif(Y, data_dir=getattr(cfg.DATA, tag).INSTANCE_CHANNELS_MASK_DIR, filenames=filenames, verbose=cfg.TEST.VERBOSE)
186
+ X, _, _, filenames = f_name(getattr(cfg.DATA, tag).PATH, return_filenames=True)
187
+ print("Creating X_{} channels . . .".format(data_type))
188
+ save_tif(X, data_dir=getattr(cfg.DATA, tag).INSTANCE_CHANNELS_DIR, filenames=filenames, verbose=cfg.TEST.VERBOSE)
189
+
190
+ # Save original X data with the labels
191
+ for i in range(min(3,len(X))):
192
+ if isinstance(X, list):
193
+ save_tif(X[i], getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'), filenames=['vol'+str(i)+".tif"], verbose=False)
194
+ else:
195
+ save_tif(np.expand_dims(X[i],0), getattr(cfg.PATHS, tag+'_INSTANCE_CHANNELS_CHECK'), filenames=['vol'+str(i)+".tif"], verbose=False)
89
196
 
90
197
  def create_test_instance_channels(cfg):
91
198
  """Create test new data with appropiate channels based on ``PROBLEM.INSTANCE_SEG.DATA_CHANNELS`` for instance segmentation.