biapy 3.4.2__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.2 → biapy-3.4.4}/PKG-INFO +1 -1
  2. {biapy-3.4.2 → biapy-3.4.4}/biapy/_biapy.py +2 -1
  3. {biapy-3.4.2 → biapy-3.4.4}/biapy/config/config.py +46 -23
  4. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/data_2D_manipulation.py +95 -30
  5. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/data_3D_manipulation.py +170 -35
  6. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/__init__.py +14 -7
  7. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/augmentors.py +1 -1
  8. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/pair_base_data_generator.py +20 -53
  9. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/pair_data_2D_generator.py +4 -3
  10. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/pair_data_3D_generator.py +10 -8
  11. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/single_base_data_generator.py +21 -10
  12. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/test_pair_data_generators.py +15 -8
  13. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/test_single_data_generator.py +17 -4
  14. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/post_processing/post_processing.py +6 -5
  15. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/pre_processing.py +125 -17
  16. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/base_workflow.py +263 -236
  17. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/check_configuration.py +72 -48
  18. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/classification.py +20 -5
  19. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/detection.py +11 -9
  20. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/instance_seg.py +120 -49
  21. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/train_engine.py +4 -0
  22. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/mae.py +8 -5
  23. biapy-3.4.4/biapy/utils/scripts/run_checks.py +3151 -0
  24. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/tif_to_h5.py +1 -1
  25. biapy-3.4.4/biapy/utils/scripts/tif_to_zarr.py +43 -0
  26. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/util.py +33 -0
  27. {biapy-3.4.2 → biapy-3.4.4}/biapy.egg-info/PKG-INFO +1 -1
  28. {biapy-3.4.2 → biapy-3.4.4}/biapy.egg-info/SOURCES.txt +3 -1
  29. {biapy-3.4.2 → biapy-3.4.4}/pyproject.toml +1 -1
  30. {biapy-3.4.2 → biapy-3.4.4}/LICENSE.md +0 -0
  31. {biapy-3.4.2 → biapy-3.4.4}/README.md +0 -0
  32. {biapy-3.4.2 → biapy-3.4.4}/biapy/__init__.py +0 -0
  33. {biapy-3.4.2 → biapy-3.4.4}/biapy/config/__init__.py +0 -0
  34. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/__init__.py +0 -0
  35. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/single_data_2D_generator.py +0 -0
  36. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/generators/single_data_3D_generator.py +0 -0
  37. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/post_processing/__init__.py +0 -0
  38. {biapy-3.4.2 → biapy-3.4.4}/biapy/data/post_processing/smooth_tiled_predictions.py +0 -0
  39. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/__init__.py +0 -0
  40. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/denoising.py +0 -0
  41. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/image_to_image.py +0 -0
  42. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/metrics.py +0 -0
  43. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/schedulers/warmup_cosine_decay.py +0 -0
  44. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/self_supervised.py +0 -0
  45. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/semantic_seg.py +0 -0
  46. {biapy-3.4.2 → biapy-3.4.4}/biapy/engine/super_resolution.py +0 -0
  47. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/__init__.py +0 -0
  48. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/attention_unet.py +0 -0
  49. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/blocks.py +0 -0
  50. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/dfcan.py +0 -0
  51. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/edsr.py +0 -0
  52. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/efficientnet.py +0 -0
  53. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/multiresunet.py +0 -0
  54. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/rcan.py +0 -0
  55. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/resunet++.py +0 -0
  56. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/resunet.py +0 -0
  57. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/seunet.py +0 -0
  58. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/simple_cnn.py +0 -0
  59. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/tr_layers.py +0 -0
  60. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/unet.py +0 -0
  61. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/unetr.py +0 -0
  62. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/vit.py +0 -0
  63. {biapy-3.4.2 → biapy-3.4.4}/biapy/models/wdsr.py +0 -0
  64. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/callbacks.py +0 -0
  65. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/matching.py +0 -0
  66. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/misc.py +0 -0
  67. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/calculate_detection_metrics.py +0 -0
  68. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/calculate_metrics_3D.py +0 -0
  69. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/create_probability_csv.py +0 -0
  70. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/crop_2D_dataset.py +0 -0
  71. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/crop_3D_dataset.py +0 -0
  72. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/crop_and_discard_3D_dataset.py +0 -0
  73. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/detection_plots.py +0 -0
  74. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/detection_probs_to_points.py +0 -0
  75. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/fill_holes_in_seg_masks.py +0 -0
  76. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/filter_close_points.py +0 -0
  77. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/from_class_csv_to_folders.py +0 -0
  78. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/h5_to_tif.py +0 -0
  79. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/h5_to_zarr.py +0 -0
  80. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/lightmycell_data_preparation.py +0 -0
  81. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/merge_dataset_channels.py +0 -0
  82. {biapy-3.4.2 → biapy-3.4.4}/biapy/utils/scripts/order_axes.py +0 -0
  83. {biapy-3.4.2 → biapy-3.4.4}/biapy.egg-info/dependency_links.txt +0 -0
  84. {biapy-3.4.2 → biapy-3.4.4}/biapy.egg-info/entry_points.txt +0 -0
  85. {biapy-3.4.2 → biapy-3.4.4}/biapy.egg-info/requires.txt +0 -0
  86. {biapy-3.4.2 → biapy-3.4.4}/biapy.egg-info/top_level.txt +0 -0
  87. {biapy-3.4.2 → 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.2
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>
@@ -11,7 +11,7 @@ import numpy as np
11
11
  import importlib
12
12
  import multiprocessing
13
13
 
14
- from biapy.utils.misc import init_devices, is_dist_avail_and_initialized, set_seed, get_rank
14
+ from biapy.utils.misc import init_devices, is_dist_avail_and_initialized, set_seed, get_rank, setup_for_distributed
15
15
  from biapy.config.config import Config
16
16
  from biapy.engine.check_configuration import check_configuration
17
17
 
@@ -420,6 +420,7 @@ class BiaPy():
420
420
 
421
421
  if is_dist_avail_and_initialized():
422
422
  print(f"[Rank {get_rank()} ({os.getpid()})] Process waiting (test finished) . . . ")
423
+ setup_for_distributed(self.args.rank == 0)
423
424
  dist.barrier()
424
425
  dist.destroy_process_group()
425
426
 
@@ -184,24 +184,26 @@ class Config:
184
184
  _C.DATA.W_BACKGROUND = 0.06 # Used when _C.DATA.PROBABILITY_MAP=True
185
185
 
186
186
  # Whether to reshape the dimensions that does not satisfy the patch shape selected by padding it with reflect. It's not
187
- # implemented in super-resolution workflow.
187
+ # implemented in super-resolution inference phase workflow (as usually the patch size is small).
188
188
  _C.DATA.REFLECT_TO_COMPLETE_SHAPE = False
189
189
 
190
190
  _C.DATA.NORMALIZATION = CN()
191
+ # Whether to apply or not a percentile clipping before normalizing the data
192
+ _C.DATA.NORMALIZATION.PERC_CLIP = False
193
+ # Lower and upper bound for percentile clip. Must be set when DATA.NORMALIZATION.PERC_CLIP = 'True'
194
+ _C.DATA.NORMALIZATION.PERC_LOWER = -1.0
195
+ _C.DATA.NORMALIZATION.PERC_UPPER = -1.0
191
196
  # Normalization type to use. Possible options:
192
197
  # 'div' to divide values from 0/255 (or 0/65535 if uint16) in [0,1] range
193
198
  # 'custom' to use DATA.NORMALIZATION.CUSTOM_MEAN and DATA.NORMALIZATION.CUSTOM_STD to normalize
194
199
  _C.DATA.NORMALIZATION.TYPE = 'div'
195
- # Whether to apply the normalization by sample ("image") or by all dataset statistics ("dataset"). Options: ["image", "dataset"]
200
+ # Whether to apply the normalization by sample ("image") or by all dataset statistics ("dataset").
201
+ # Used with 'DATA.NORMALIZATION.PERC_CLIP' == 'True' and/or when 'DATA.NORMALIZATION.TYPE' == 'custom'.
202
+ # Options: ["image", "dataset"]
196
203
  _C.DATA.NORMALIZATION.APPLICATION_MODE = "image"
197
204
  # Custom normalization variables: mean and std (they are calculated if not provided)
198
205
  _C.DATA.NORMALIZATION.CUSTOM_MEAN = -1.0
199
206
  _C.DATA.NORMALIZATION.CUSTOM_STD = -1.0
200
- # Whether to apply or not a percentile clipping before normalizing the data
201
- _C.DATA.NORMALIZATION.PERC_CLIP = False
202
- # Lower and upper bound for percentile clip. Must be set when DATA.NORMALIZATION.PERC_CLIP = 'True'
203
- _C.DATA.NORMALIZATION.PERC_LOWER = -1.0
204
- _C.DATA.NORMALIZATION.PERC_UPPER = -1.0
205
207
 
206
208
  # If 'DATA.PATCH_SIZE' selected has 3 channels, e.g. RGB images are expected, so will force grayscale images to be
207
209
  # converted into RGB (e.g. in ImageNet some of the images are grayscale)
@@ -214,6 +216,13 @@ class Config:
214
216
  _C.DATA.TRAIN.IN_MEMORY = True
215
217
  _C.DATA.TRAIN.PATH = os.path.join("user_data", 'train', 'x')
216
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 = ''
217
226
  # File to load/save data prepared with the appropiate channels in a instance segmentation problem.
218
227
  # E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
219
228
  _C.DATA.TRAIN.INSTANCE_CHANNELS_DIR = os.path.join("user_data", 'train', 'x_'+_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
@@ -238,9 +247,9 @@ class Config:
238
247
  # Minimum foreground percentage that each image loaded need to have to not discard it (only used when TRAIN.IN_MEMORY == True).
239
248
  # This option is only valid for SEMANTIC_SEG, INSTANCE_SEG and DETECTION.
240
249
  _C.DATA.TRAIN.MINIMUM_FOREGROUND_PER = -1.
241
- # 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.
242
251
  _C.DATA.TRAIN.INPUT_IMG_AXES_ORDER = 'TZCYX'
243
- # 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.
244
253
  _C.DATA.TRAIN.INPUT_MASK_AXES_ORDER = 'TZCYX'
245
254
 
246
255
  # PREPROCESSING
@@ -368,6 +377,13 @@ class Config:
368
377
  _C.DATA.VAL.PATH = os.path.join("user_data", 'val', 'x')
369
378
  # Path to the validation data mask. Used when _C.DATA.VAL.FROM_TRAIN = False
370
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 = ''
371
387
  # File to load/save data prepared with the appropiate channels in a instance segmentation problem.
372
388
  # E.g. _C.PROBLEM.TYPE ='INSTANCE_SEG' and _C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS != 'B'
373
389
  _C.DATA.VAL.INSTANCE_CHANNELS_DIR = os.path.join("user_data", 'val', 'x_'+_C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS)
@@ -384,15 +400,11 @@ class Config:
384
400
  # Padding to be done in (y,x)/(z,y,x) when cropping validation data. Useful to avoid patch 'border effect'. This
385
401
  # is only used when the validation is loaded from disk, and thus, not extracted from training.
386
402
  _C.DATA.VAL.PADDING = (0,0)
387
- # Directory where validation binary masks should be located. This binary mask will be applied only when MW_TH*
388
- # optimized values are find, that is, when _C.PROBLEM.INSTANCE_SEG.DATA_MW_OPTIMIZE_THS = True and _C.TEST.POST_PROCESSING.APPLY_MASK = True
389
- _C.DATA.VAL.BINARY_MASKS = os.path.join("user_data", 'val', 'bin_mask')
390
403
  # Not used yet.
391
404
  _C.DATA.VAL.RESOLUTION = (-1,)
392
- # 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.
393
406
  _C.DATA.VAL.INPUT_IMG_AXES_ORDER = 'TZCYX'
394
- # Order of the axes of the mask when using Zarr/H5 images to train.
395
- # detection the mask
407
+ # Order of the axes of the mask when using Zarr/H5 images in validation data.
396
408
  _C.DATA.VAL.INPUT_MASK_AXES_ORDER = 'TZCYX'
397
409
 
398
410
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -435,7 +447,7 @@ class Config:
435
447
  # How to fill up the new values created with affine transformations (rotations, shear, shift and zoom).
436
448
  # Same meaning as in scipy: 'reflect', grid-'mirror', 'constant', 'grid-constant', 'nearest', 'mirror',
437
449
  # 'grid-wrap' and 'wrap'.
438
- _C.AUGMENTOR.AFFINE_MODE = 'constant'
450
+ _C.AUGMENTOR.AFFINE_MODE = 'reflect'
439
451
  # Make vertical flips
440
452
  _C.AUGMENTOR.VFLIP = False
441
453
  # Make horizontal flips
@@ -821,6 +833,16 @@ class Config:
821
833
  _C.TEST.BY_CHUNKS.FLUSH_EACH = 100
822
834
  # Input Numpy/Zarr/H5 image's axes order. Options: ['TZCYX', 'TZYXC', 'ZCYX', 'ZYXC']
823
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
+
824
846
  # Whether if after reconstructing the prediction the pipeline will continue each workflow specific steps. For this process
825
847
  # the prediction image needs to be loaded into memory so be sure that it can fit in you memory. E.g. in instance
826
848
  # segmentation the instances will be created from the prediction.
@@ -843,7 +865,7 @@ class Config:
843
865
  _C.TEST.REUSE_PREDICTIONS = False
844
866
 
845
867
  # If PROBLEM.NDIM = '2D' this can be activated to process each image entirely instead of patch by patch. Only can be done
846
- # if the neural network is fully convolutional
868
+ # if the neural network is fully convolutional. It's not implemented in super-resolution workflow.
847
869
  _C.TEST.FULL_IMG = False
848
870
 
849
871
  ### Instance segmentation
@@ -891,9 +913,12 @@ class Config:
891
913
  _C.TEST.POST_PROCESSING.YZ_FILTERING_SIZE = 5
892
914
  _C.TEST.POST_PROCESSING.Z_FILTERING = False
893
915
  _C.TEST.POST_PROCESSING.Z_FILTERING_SIZE = 5
894
- # Apply a binary mask to remove possible segmentation outside it
916
+ # Apply a binary mask to remove possible segmentation outside it (you need to provide the mask and it must
917
+ # contain two values: '1' -> preserve the pixel ; '0' discard pixel ). A mask for each test sample must be
918
+ # provided and it will be loaded using 'DATA.TEST.BINARY_MASKS' variable.
895
919
  _C.TEST.POST_PROCESSING.APPLY_MASK = False
896
920
 
921
+ ### Instance segmentation
897
922
  # Whether to measure morphological features on each instances, i.e. 'circularity' (2D), 'elongation' (2D), 'npixels', 'area', 'diameter',
898
923
  # 'perimeter', 'sphericity' (3D)
899
924
  _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES = CN()
@@ -964,7 +989,6 @@ class Config:
964
989
  # "greather equal", e.g. ">=", "less than", e.g. "<", and "less equal" e.g. "<=" comparisons.
965
990
  _C.TEST.POST_PROCESSING.MEASURE_PROPERTIES.REMOVE_BY_PROPERTIES.SIGN = []
966
991
 
967
- ### Instance segmentation
968
992
  # Whether to apply Voronoi using 'BC' or 'M' channels need to be present
969
993
  _C.TEST.POST_PROCESSING.VORONOI_ON_MASK = False
970
994
  # Threshold to be applied to the 'M' channel when expanding the instances with Voronoi. Need to be in [0,1] range.
@@ -986,7 +1010,8 @@ class Config:
986
1010
  _C.TEST.POST_PROCESSING.REMOVE_CLOSE_POINTS_RADIUS = [-1.0]
987
1011
  # Whether to apply a watershed to grow the points detected
988
1012
  _C.TEST.POST_PROCESSING.DET_WATERSHED = False
989
- # Structure per each class to dilate the initial seeds before watershed
1013
+ # Structure per each class to dilate the initial seeds before watershed. For instance, with two classes in a 3D problem:
1014
+ # [ [2,2,1], [10,10,4] ]
990
1015
  _C.TEST.POST_PROCESSING.DET_WATERSHED_FIRST_DILATION = [[-1,-1],]
991
1016
  # List of classes to be consider as 'donuts'. For those class points, the 'donuts' type cell means that their nucleus is
992
1017
  # to big and that the seeds need to be dilated more so the watershed can grow the instances properly.
@@ -1014,6 +1039,7 @@ class Config:
1014
1039
  _C.PATHS.RESULT_DIR.FULL_IMAGE_INSTANCES = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'full_image_instances')
1015
1040
  _C.PATHS.RESULT_DIR.FULL_IMAGE_POST_PROCESSING = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'full_image_post_processing')
1016
1041
  _C.PATHS.RESULT_DIR.AS_3D_STACK = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'as_3d_stack')
1042
+ _C.PATHS.RESULT_DIR.AS_3D_STACK_BIN = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'as_3d_stack_binarized')
1017
1043
  _C.PATHS.RESULT_DIR.AS_3D_STACK_POST_PROCESSING = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'as_3d_stack_post_processing')
1018
1044
  _C.PATHS.RESULT_DIR.DET_LOCAL_MAX_COORDS_CHECK = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'per_image_local_max_check')
1019
1045
  _C.PATHS.RESULT_DIR.DET_ASSOC_POINTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'point_associations')
@@ -1023,7 +1049,6 @@ class Config:
1023
1049
  _C.PATHS.PROFILER = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'profiler')
1024
1050
 
1025
1051
  # Name of the folder where the charts of the loss and metrics values while training the network are stored.
1026
- # Additionally, MW_TH* variable charts are stored if _C.PROBLEM.INSTANCE_SEG.DATA_MW_OPTIMIZE_THS = True
1027
1052
  _C.PATHS.CHARTS = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'charts')
1028
1053
  # Folder where samples of DA will be stored
1029
1054
  _C.PATHS.DA_SAMPLES = os.path.join(_C.PATHS.RESULT_DIR.PATH, 'aug')
@@ -1091,8 +1116,6 @@ class Config:
1091
1116
  self._C.DATA.VAL.INSTANCE_CHANNELS_DIR = self._C.DATA.VAL.PATH+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
1092
1117
  self._C.DATA.VAL.INSTANCE_CHANNELS_MASK_DIR = self._C.DATA.VAL.GT_PATH+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
1093
1118
  # If value is not the default
1094
- if self._C.DATA.VAL.BINARY_MASKS == os.path.join("user_data", 'val', 'bin_mask'):
1095
- self._C.DATA.VAL.BINARY_MASKS = os.path.join(self._C.DATA.VAL.PATH, '..', 'bin_mask')
1096
1119
  self._C.DATA.VAL.DETECTION_MASK_DIR = self._C.DATA.VAL.GT_PATH+'_detection_masks'
1097
1120
  self._C.DATA.VAL.SSL_SOURCE_DIR = self._C.DATA.VAL.PATH+'_ssl_source'
1098
1121
  self._C.DATA.TEST.INSTANCE_CHANNELS_DIR = self._C.DATA.TEST.PATH+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CHANNELS+'_'+self._C.PROBLEM.INSTANCE_SEG.DATA_CONTOUR_MODE
@@ -102,7 +102,7 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
102
102
  filenames : List of str
103
103
  Loaded train filenames.
104
104
 
105
- val_index : List of ints
105
+ test_index : List of ints
106
106
  Indexes of the samples beloging to the validation.
107
107
 
108
108
  Examples
@@ -144,7 +144,7 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
144
144
  print("### LOAD ###")
145
145
 
146
146
  # Disable crops when random_crops_in_DA is selected
147
- # Disable crops when random_crops_in_DA is selected
147
+ delay_crop = False
148
148
  if random_crops_in_DA:
149
149
  crop = False
150
150
  else:
@@ -154,7 +154,6 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
154
154
  delay_crop = True
155
155
  else:
156
156
  crop = True
157
- delay_crop = False
158
157
 
159
158
  # Check validation
160
159
  if val_split > 0 or cross_val:
@@ -172,6 +171,19 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
172
171
  Y_train, _, _, _ = load_data_from_dir(train_mask_path, crop=crop, crop_shape=scrop, overlap=ov, padding=padding,
173
172
  return_filenames=True, check_channel=False, check_drange=False, reflect_to_complete_shape=reflect_to_complete_shape,
174
173
  preprocess_cfg=preprocess_cfg, is_mask=is_y_mask, preprocess_f=preprocess_f)
174
+
175
+ # Check that the shape of all images match
176
+ if isinstance(Y_train, list):
177
+ for i in range(len(Y_train)):
178
+ xshape = X_train[i].shape
179
+ yshape = Y_train[i].shape
180
+ real_x_shape = (xshape[0]*y_upscaling[0], xshape[1]*y_upscaling[1], xshape[2])
181
+ real_y_shape = (yshape[0]*y_upscaling[0], yshape[1]*y_upscaling[1], yshape[2])
182
+ print(real_x_shape,real_y_shape)
183
+ if real_x_shape != real_y_shape:
184
+ raise ValueError(f"There is a mismatch between input image and its corresponding ground truth ({real_x_shape} vs "
185
+ f"{real_y_shape}). Please check the images. Specifically, the sample that doesn't match is the number {i}"
186
+ f" (file: {t_filenames[i]})")
175
187
  else:
176
188
  Y_train = None
177
189
 
@@ -257,22 +269,36 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
257
269
  skf = StratifiedKFold(n_splits=cross_val_nsplits, shuffle=shuffle_val,
258
270
  random_state=seed)
259
271
  fold = 1
260
- train_index, val_index = None, None
272
+ train_index, test_index = None, None
261
273
 
262
274
  y_len = len(Y_train) if Y_train is not None else len(X_train)
263
275
  for t_index, te_index in skf.split(np.zeros(len(X_train)), np.zeros(y_len)):
264
276
  if cross_val_fold == fold:
265
- X_train, X_val = X_train[t_index], X_train[te_index]
277
+ if not isinstance(X_train, list):
278
+ X_train, X_val = X_train[t_index], X_train[te_index]
279
+ else:
280
+ X_val = []
281
+ for val_idx in te_index:
282
+ X_val.append(X_train[val_idx])
283
+ for val_idx in te_index:
284
+ del X_val[val_idx]
266
285
  if Y_train is not None:
267
- Y_train, Y_val = Y_train[t_index], Y_train[te_index]
286
+ if not isinstance(Y_train, list):
287
+ Y_train, Y_val = Y_train[t_index], Y_train[te_index]
288
+ else:
289
+ Y_val = []
290
+ for val_idx in te_index:
291
+ Y_val.append(Y_val[val_idx])
292
+ for val_idx in te_index:
293
+ del Y_val[val_idx]
268
294
  train_index, test_index = t_index.copy(), te_index.copy()
269
295
  break
270
296
  fold+= 1
271
297
 
272
- if len(val_index) > 5:
273
- print("Fold number {}. Printing the first 5 ids: {}".format(fold, val_index[:5]))
298
+ if len(test_index) > 5:
299
+ print("Fold number {}. Printing the first 5 ids: {}".format(fold, test_index[:5]))
274
300
  else:
275
- print("Fold number {}. Indexes used in cross validation: {}".format(fold, val_index))
301
+ print("Fold number {}. Indexes used in cross validation: {}".format(fold, test_index))
276
302
 
277
303
  # Then crop after cross validation
278
304
  if delay_crop:
@@ -280,8 +306,8 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
280
306
  data = []
281
307
  for img_num in range(len(X_train)):
282
308
  if X_train[img_num].shape != crop_shape[:2]+(X_train[img_num].shape[-1],):
283
- img = X_train[img_num]
284
- img = crop_2D_data_with_overlap(X_train[img_num][0] if isinstance(X_train, list) else X_train[img_num],
309
+ img = crop_data_with_overlap(
310
+ X_train[img_num][0] if isinstance(X_train, list) else np.expand_dims(X_train[img_num],0),
285
311
  crop_shape[:2]+(X_train[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
286
312
  data.append(img)
287
313
  X_train = np.concatenate(data)
@@ -293,8 +319,8 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
293
319
  scrop = (crop_shape[0]*y_upscaling[0], crop_shape[1]*y_upscaling[1], crop_shape[2])
294
320
  for img_num in range(len(Y_train)):
295
321
  if Y_train[img_num].shape != scrop[:2]+(Y_train[img_num].shape[-1],):
296
- img = Y_train[img_num]
297
- img = crop_2D_data_with_overlap(Y_train[img_num][0] if isinstance(Y_train, list) else Y_train[img_num],
322
+ img = crop_data_with_overlap(
323
+ Y_train[img_num][0] if isinstance(Y_train, list) else np.expand_dims(Y_train[img_num],0),
298
324
  scrop[:2]+(Y_train[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
299
325
  data_mask.append(img)
300
326
  Y_train = np.concatenate(data_mask)
@@ -304,8 +330,8 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
304
330
  data = []
305
331
  for img_num in range(len(X_val)):
306
332
  if X_val[img_num].shape != crop_shape[:2]+(X_val[img_num].shape[-1],):
307
- img = X_val[img_num]
308
- img = crop_2D_data_with_overlap(X_val[img_num][0] if isinstance(X_val, list) else X_val[img_num],
333
+ img = crop_data_with_overlap(
334
+ X_val[img_num][0] if isinstance(X_val, list) else np.expand_dims(X_val[img_num],0),
309
335
  crop_shape[:2]+(X_val[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
310
336
  data.append(img)
311
337
  X_val = np.concatenate(data)
@@ -317,13 +343,26 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
317
343
  scrop = (crop_shape[0]*y_upscaling[0], crop_shape[1]*y_upscaling[1], crop_shape[2])
318
344
  for img_num in range(len(Y_val)):
319
345
  if Y_val[img_num].shape != scrop[:2]+(Y_val[img_num].shape[-1],):
320
- img = Y_val[img_num]
321
- img = crop_2D_data_with_overlap(Y_val[img_num][0] if isinstance(Y_val, list) else Y_val[img_num],
346
+ img = crop_data_with_overlap(
347
+ Y_val[img_num][0] if isinstance(Y_val, list) else np.expand_dims(Y_val[img_num],0),
322
348
  scrop[:2]+(Y_val[img_num].shape[-1],), overlap=ov, padding=padding, verbose=False)
323
349
  data_mask.append(img)
324
350
  Y_val = np.concatenate(data_mask)
325
351
  del data_mask
326
352
 
353
+ # Check that the shape of all images match
354
+ if Y_train is not None:
355
+ if not isinstance(X_train, list):
356
+ if Y_train.shape[0] != X_train.shape[0]:
357
+ raise ValueError(f"Seems that input images do not correspond to their ground truth in shape ({X_train.shape[0]} samples vs "
358
+ f"{Y_train.shape[0]} samples). Please check the images. If you are in super-resolution workflow maybe you did not "
359
+ "configured properly 'PROBLEM.SUPER_RESOLUTION.UPSCALING' variable")
360
+ else:
361
+ if Y_train[0].shape[0] != X_train[0].shape[0]:
362
+ raise ValueError(f"Seems that input images do not correspond to their ground truth in shape ({X_train[0].shape[0]} samples vs "
363
+ f"{Y_train[0].shape[0]} samples). Please check the images. If you are in super-resolution workflow maybe you did not "
364
+ "configured properly 'PROBLEM.SUPER_RESOLUTION.UPSCALING' variable")
365
+
327
366
  s = X_train.shape if not isinstance(X_train, list) else (len(X_train),)+X_train[0].shape[1:]
328
367
  if Y_train is not None:
329
368
  sm = Y_train.shape if not isinstance(Y_train, list) else (len(Y_train),)+Y_train[0].shape[1:]
@@ -344,7 +383,7 @@ def load_and_prepare_2D_train_data(train_path, train_mask_path, cross_val=False,
344
383
  if not cross_val:
345
384
  return X_train, Y_train, X_val, Y_val, t_filenames
346
385
  else:
347
- return X_train, Y_train, X_val, Y_val, t_filenames, val_index
386
+ return X_train, Y_train, X_val, Y_val, t_filenames, test_index
348
387
  else:
349
388
  print("*** Loaded train data shape is: {}".format(s))
350
389
  print("### END LOAD ###")
@@ -443,7 +482,11 @@ def crop_data_with_overlap(data, crop_shape, data_mask=None, overlap=(0,0), padd
443
482
  # **** New data shape is: (3960, 256, 256, 1)
444
483
  """
445
484
 
485
+ if data.ndim != 4:
486
+ raise ValueError("data expected to be 4 dimensional, given {}".format(data.shape))
446
487
  if data_mask is not None:
488
+ if data.ndim != 4:
489
+ raise ValueError("data mask expected to be 4 dimensional, given {}".format(data_mask.shape))
447
490
  if data.shape[:-1] != data_mask.shape[:-1]:
448
491
  raise ValueError("data and data_mask shapes mismatch: {} vs {}".format(data.shape[:-1], data_mask.shape[:-1]))
449
492
 
@@ -799,8 +842,8 @@ def merge_data_with_overlap(data, original_shape, data_mask=None, overlap=(0,0),
799
842
  return merged_data
800
843
 
801
844
 
802
- def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expected_classes=None, cross_val=False, cross_val_nsplits=5, cross_val_fold=1,
803
- val_split=0.1, seed=0, shuffle_val=True):
845
+ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expected_classes=None, cross_val=False, cross_val_nsplits=5,
846
+ cross_val_fold=1, val_split=0.1, seed=0, shuffle_val=True, preprocess_cfg=None, preprocess_f=None):
804
847
  """
805
848
  Load data to train classification methods.
806
849
 
@@ -837,6 +880,12 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
837
880
  shuffle_val : bool, optional
838
881
  Take random training examples to create validation data.
839
882
 
883
+ preprocess_cfg : dict, optional
884
+ Configuration parameters for preprocessing, is necessary in case you want to apply any preprocessing.
885
+
886
+ preprocess_f : function, optional
887
+ The preprocessing function, is necessary in case you want to apply any preprocessing.
888
+
840
889
  Returns
841
890
  -------
842
891
  X_data : 4D Numpy array
@@ -854,7 +903,7 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
854
903
  all_ids : List of str
855
904
  Loaded data filenames.
856
905
 
857
- val_index : List of ints
906
+ test_index : List of ints
858
907
  Indexes of the samples beloging to the validation.
859
908
  """
860
909
 
@@ -889,7 +938,8 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
889
938
 
890
939
  # Loading images
891
940
  images, _, _, image_ids = load_data_from_dir(f, return_filenames=True, crop_shape=patch_shape,
892
- convert_to_rgb=convert_to_rgb)
941
+ convert_to_rgb=convert_to_rgb, preprocess_cfg=preprocess_cfg, is_mask=False,
942
+ preprocess_f=preprocess_f)
893
943
 
894
944
  X_data.append(images)
895
945
  Y_data.append((c_num,)*len(ids))
@@ -908,26 +958,41 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
908
958
  if create_val:
909
959
  print("Creating validation data")
910
960
  if not cross_val:
961
+ if len(X_data) == 1:
962
+ raise ValueError("Validation data can not be extracted from training data as it only has one sample. Please check the data.")
911
963
  X_data, X_val, Y_data, Y_val = train_test_split(
912
964
  X_data, Y_data, test_size=val_split, shuffle=shuffle_val, random_state=seed,
913
965
  stratify=Y_data)
914
966
  else:
967
+ if len(X_data) < cross_val_nsplits:
968
+ raise ValueError(f"Validation data can not be extracted from training data as the number of splits ({cross_val_nsplits}) "
969
+ f"is greater than the number of samples {len(X_data)}. Please check the data.")
915
970
  skf = StratifiedKFold(n_splits=cross_val_nsplits, shuffle=shuffle_val,
916
971
  random_state=seed)
917
972
  fold = 1
918
- train_index, val_index = None, None
973
+ train_index, test_index = None, None
919
974
 
920
975
  for t_index, te_index in skf.split(X_data, Y_data):
921
976
  if cross_val_fold == fold:
922
- X_data, X_val = X_data[t_index], X_data[te_index]
923
- Y_data, Y_val = Y_data[t_index], Y_data[te_index]
924
- train_index, val_index = t_index.copy(), te_index.copy()
977
+ if not isinstance(X_data, list):
978
+ X_data, X_val = X_data[t_index], X_data[te_index]
979
+ Y_data, Y_val = Y_data[t_index], Y_data[te_index]
980
+ else:
981
+ X_val = []
982
+ Y_val = []
983
+ for val_idx in te_index:
984
+ X_val.append(X_data[val_idx])
985
+ Y_val.append(Y_data[val_idx])
986
+ for val_idx in te_index:
987
+ del X_val[val_idx]
988
+ del Y_val[val_idx]
989
+ train_index, test_index = t_index.copy(), te_index.copy()
925
990
  break
926
991
  fold+= 1
927
- if len(val_index) > 5:
928
- print("Fold number {}. Printing the first 5 ids: {}".format(fold, val_index[:5]))
992
+ if len(test_index) > 5:
993
+ print("Fold number {}. Printing the first 5 ids: {}".format(fold, test_index[:5]))
929
994
  else:
930
- print("Fold number {}. Indexes used in cross validation: {}".format(fold, val_index))
995
+ print("Fold number {}. Indexes used in cross validation: {}".format(fold, test_index))
931
996
 
932
997
  if create_val:
933
998
  print("*** Loaded train data shape is: {}".format(X_data.shape))
@@ -935,7 +1000,7 @@ def load_data_classification(data_dir, patch_shape, convert_to_rgb=True, expecte
935
1000
  if not cross_val:
936
1001
  return X_data, Y_data, X_val, Y_val, all_ids
937
1002
  else:
938
- return X_data, Y_data, X_val, Y_val, all_ids, val_index
1003
+ return X_data, Y_data, X_val, Y_val, all_ids, test_index
939
1004
  else:
940
1005
  print("*** Loaded train data shape is: {}".format(X_data.shape))
941
1006
  return X_data, Y_data, all_ids