spacr 0.5.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

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 (100) hide show
  1. spacr/__init__.py +0 -2
  2. spacr/__main__.py +3 -3
  3. spacr/core.py +13 -106
  4. spacr/gui_core.py +2 -2
  5. spacr/gui_utils.py +1 -13
  6. spacr/io.py +24 -25
  7. spacr/mediar.py +12 -8
  8. spacr/plot.py +50 -13
  9. spacr/settings.py +45 -6
  10. spacr/submodules.py +11 -1
  11. spacr/timelapse.py +21 -3
  12. spacr/utils.py +154 -15
  13. {spacr-0.5.0.dist-info → spacr-0.9.0.dist-info}/METADATA +62 -62
  14. spacr-0.9.0.dist-info/RECORD +109 -0
  15. {spacr-0.5.0.dist-info → spacr-0.9.0.dist-info}/WHEEL +1 -1
  16. spacr/resources/MEDIAR/.gitignore +0 -18
  17. spacr/resources/MEDIAR/LICENSE +0 -21
  18. spacr/resources/MEDIAR/README.md +0 -189
  19. spacr/resources/MEDIAR/SetupDict.py +0 -39
  20. spacr/resources/MEDIAR/__pycache__/SetupDict.cpython-39.pyc +0 -0
  21. spacr/resources/MEDIAR/__pycache__/evaluate.cpython-39.pyc +0 -0
  22. spacr/resources/MEDIAR/__pycache__/generate_mapping.cpython-39.pyc +0 -0
  23. spacr/resources/MEDIAR/__pycache__/main.cpython-39.pyc +0 -0
  24. spacr/resources/MEDIAR/config/baseline.json +0 -60
  25. spacr/resources/MEDIAR/config/mediar_example.json +0 -72
  26. spacr/resources/MEDIAR/config/pred/pred_mediar.json +0 -17
  27. spacr/resources/MEDIAR/config/step1_pretraining/phase1.json +0 -55
  28. spacr/resources/MEDIAR/config/step1_pretraining/phase2.json +0 -58
  29. spacr/resources/MEDIAR/config/step2_finetuning/finetuning1.json +0 -66
  30. spacr/resources/MEDIAR/config/step2_finetuning/finetuning2.json +0 -66
  31. spacr/resources/MEDIAR/config/step3_prediction/base_prediction.json +0 -16
  32. spacr/resources/MEDIAR/config/step3_prediction/ensemble_tta.json +0 -23
  33. spacr/resources/MEDIAR/core/BasePredictor.py +0 -120
  34. spacr/resources/MEDIAR/core/BaseTrainer.py +0 -240
  35. spacr/resources/MEDIAR/core/Baseline/Predictor.py +0 -59
  36. spacr/resources/MEDIAR/core/Baseline/Trainer.py +0 -113
  37. spacr/resources/MEDIAR/core/Baseline/__init__.py +0 -2
  38. spacr/resources/MEDIAR/core/Baseline/__pycache__/Predictor.cpython-39.pyc +0 -0
  39. spacr/resources/MEDIAR/core/Baseline/__pycache__/Trainer.cpython-39.pyc +0 -0
  40. spacr/resources/MEDIAR/core/Baseline/__pycache__/__init__.cpython-39.pyc +0 -0
  41. spacr/resources/MEDIAR/core/Baseline/__pycache__/utils.cpython-39.pyc +0 -0
  42. spacr/resources/MEDIAR/core/Baseline/utils.py +0 -80
  43. spacr/resources/MEDIAR/core/MEDIAR/EnsemblePredictor.py +0 -105
  44. spacr/resources/MEDIAR/core/MEDIAR/Predictor.py +0 -234
  45. spacr/resources/MEDIAR/core/MEDIAR/Trainer.py +0 -172
  46. spacr/resources/MEDIAR/core/MEDIAR/__init__.py +0 -3
  47. spacr/resources/MEDIAR/core/MEDIAR/__pycache__/EnsemblePredictor.cpython-39.pyc +0 -0
  48. spacr/resources/MEDIAR/core/MEDIAR/__pycache__/Predictor.cpython-39.pyc +0 -0
  49. spacr/resources/MEDIAR/core/MEDIAR/__pycache__/Trainer.cpython-39.pyc +0 -0
  50. spacr/resources/MEDIAR/core/MEDIAR/__pycache__/__init__.cpython-39.pyc +0 -0
  51. spacr/resources/MEDIAR/core/MEDIAR/__pycache__/utils.cpython-39.pyc +0 -0
  52. spacr/resources/MEDIAR/core/MEDIAR/utils.py +0 -429
  53. spacr/resources/MEDIAR/core/__init__.py +0 -2
  54. spacr/resources/MEDIAR/core/__pycache__/BasePredictor.cpython-39.pyc +0 -0
  55. spacr/resources/MEDIAR/core/__pycache__/BaseTrainer.cpython-39.pyc +0 -0
  56. spacr/resources/MEDIAR/core/__pycache__/__init__.cpython-39.pyc +0 -0
  57. spacr/resources/MEDIAR/core/__pycache__/utils.cpython-39.pyc +0 -0
  58. spacr/resources/MEDIAR/core/utils.py +0 -40
  59. spacr/resources/MEDIAR/evaluate.py +0 -71
  60. spacr/resources/MEDIAR/generate_mapping.py +0 -121
  61. spacr/resources/MEDIAR/image/examples/img1.tiff +0 -0
  62. spacr/resources/MEDIAR/image/examples/img2.tif +0 -0
  63. spacr/resources/MEDIAR/image/failure_cases.png +0 -0
  64. spacr/resources/MEDIAR/image/mediar_framework.png +0 -0
  65. spacr/resources/MEDIAR/image/mediar_model.PNG +0 -0
  66. spacr/resources/MEDIAR/image/mediar_results.png +0 -0
  67. spacr/resources/MEDIAR/main.py +0 -125
  68. spacr/resources/MEDIAR/predict.py +0 -70
  69. spacr/resources/MEDIAR/requirements.txt +0 -14
  70. spacr/resources/MEDIAR/train_tools/__init__.py +0 -3
  71. spacr/resources/MEDIAR/train_tools/__pycache__/__init__.cpython-39.pyc +0 -0
  72. spacr/resources/MEDIAR/train_tools/__pycache__/measures.cpython-39.pyc +0 -0
  73. spacr/resources/MEDIAR/train_tools/__pycache__/utils.cpython-39.pyc +0 -0
  74. spacr/resources/MEDIAR/train_tools/data_utils/__init__.py +0 -1
  75. spacr/resources/MEDIAR/train_tools/data_utils/__pycache__/__init__.cpython-39.pyc +0 -0
  76. spacr/resources/MEDIAR/train_tools/data_utils/__pycache__/datasetter.cpython-39.pyc +0 -0
  77. spacr/resources/MEDIAR/train_tools/data_utils/__pycache__/transforms.cpython-39.pyc +0 -0
  78. spacr/resources/MEDIAR/train_tools/data_utils/__pycache__/utils.cpython-39.pyc +0 -0
  79. spacr/resources/MEDIAR/train_tools/data_utils/custom/CellAware.py +0 -88
  80. spacr/resources/MEDIAR/train_tools/data_utils/custom/LoadImage.py +0 -161
  81. spacr/resources/MEDIAR/train_tools/data_utils/custom/NormalizeImage.py +0 -77
  82. spacr/resources/MEDIAR/train_tools/data_utils/custom/__init__.py +0 -3
  83. spacr/resources/MEDIAR/train_tools/data_utils/custom/__pycache__/CellAware.cpython-39.pyc +0 -0
  84. spacr/resources/MEDIAR/train_tools/data_utils/custom/__pycache__/LoadImage.cpython-39.pyc +0 -0
  85. spacr/resources/MEDIAR/train_tools/data_utils/custom/__pycache__/NormalizeImage.cpython-39.pyc +0 -0
  86. spacr/resources/MEDIAR/train_tools/data_utils/custom/__pycache__/__init__.cpython-39.pyc +0 -0
  87. spacr/resources/MEDIAR/train_tools/data_utils/custom/modalities.pkl +0 -0
  88. spacr/resources/MEDIAR/train_tools/data_utils/datasetter.py +0 -208
  89. spacr/resources/MEDIAR/train_tools/data_utils/transforms.py +0 -148
  90. spacr/resources/MEDIAR/train_tools/data_utils/utils.py +0 -84
  91. spacr/resources/MEDIAR/train_tools/measures.py +0 -200
  92. spacr/resources/MEDIAR/train_tools/models/MEDIARFormer.py +0 -102
  93. spacr/resources/MEDIAR/train_tools/models/__init__.py +0 -1
  94. spacr/resources/MEDIAR/train_tools/models/__pycache__/MEDIARFormer.cpython-39.pyc +0 -0
  95. spacr/resources/MEDIAR/train_tools/models/__pycache__/__init__.cpython-39.pyc +0 -0
  96. spacr/resources/MEDIAR/train_tools/utils.py +0 -70
  97. spacr-0.5.0.dist-info/RECORD +0 -190
  98. {spacr-0.5.0.dist-info → spacr-0.9.0.dist-info}/LICENSE +0 -0
  99. {spacr-0.5.0.dist-info → spacr-0.9.0.dist-info}/entry_points.txt +0 -0
  100. {spacr-0.5.0.dist-info → spacr-0.9.0.dist-info}/top_level.txt +0 -0
spacr/__init__.py CHANGED
@@ -21,7 +21,6 @@ from . import app_measure
21
21
  from . import app_classify
22
22
  from . import app_sequencing
23
23
  from . import app_umap
24
- from . import mediar
25
24
  from . import submodules
26
25
  from . import openai
27
26
  from . import ml
@@ -52,7 +51,6 @@ __all__ = [
52
51
  "app_classify",
53
52
  "app_sequencing",
54
53
  "app_umap",
55
- "mediar",
56
54
  "submodules",
57
55
  "openai",
58
56
  "ml",
spacr/__main__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """
2
- Copyright © 2024 Something
2
+ Copyright © 2025 Something
3
3
  """
4
4
 
5
- if __name__ == "__main__":
6
- main()
5
+ #if __name__ == "__main__":
6
+ # main()
spacr/core.py CHANGED
@@ -98,15 +98,12 @@ def preprocess_generate_masks(settings):
98
98
  files_to_process = 3
99
99
  files_processed = 0
100
100
  if settings['masks']:
101
- mask_src = os.path.join(src, 'norm_channel_stack')
101
+ mask_src = os.path.join(src, 'masks')
102
102
  if settings['cell_channel'] != None:
103
103
  time_ls=[]
104
104
  if check_mask_folder(src, 'cell_mask_stack'):
105
105
  start = time.time()
106
- if settings['segmentation_mode'] == 'cellpose':
107
- generate_cellpose_masks(mask_src, settings, 'cell')
108
- elif settings['segmentation_mode'] == 'mediar':
109
- generate_mediar_masks(mask_src, settings, 'cell')
106
+ generate_cellpose_masks(mask_src, settings, 'cell')
110
107
  stop = time.time()
111
108
  duration = (stop - start)
112
109
  time_ls.append(duration)
@@ -117,10 +114,7 @@ def preprocess_generate_masks(settings):
117
114
  time_ls=[]
118
115
  if check_mask_folder(src, 'nucleus_mask_stack'):
119
116
  start = time.time()
120
- if settings['segmentation_mode'] == 'cellpose':
121
- generate_cellpose_masks(mask_src, settings, 'nucleus')
122
- elif settings['segmentation_mode'] == 'mediar':
123
- generate_mediar_masks(mask_src, settings, 'nucleus')
117
+ generate_cellpose_masks(mask_src, settings, 'nucleus')
124
118
  stop = time.time()
125
119
  duration = (stop - start)
126
120
  time_ls.append(duration)
@@ -131,10 +125,7 @@ def preprocess_generate_masks(settings):
131
125
  time_ls=[]
132
126
  if check_mask_folder(src, 'pathogen_mask_stack'):
133
127
  start = time.time()
134
- if settings['segmentation_mode'] == 'cellpose':
135
- generate_cellpose_masks(mask_src, settings, 'pathogen')
136
- elif settings['segmentation_mode'] == 'mediar':
137
- generate_mediar_masks(mask_src, settings, 'pathogen')
128
+ generate_cellpose_masks(mask_src, settings, 'pathogen')
138
129
  stop = time.time()
139
130
  duration = (stop - start)
140
131
  time_ls.append(duration)
@@ -386,7 +377,13 @@ def generate_cellpose_masks(src, settings, object_type):
386
377
  timelapse_remove_transient=timelapse_remove_transient,
387
378
  radius=radius,
388
379
  n_jobs=n_jobs)
389
- if timelapse_mode == 'trackpy':
380
+
381
+ if timelapse_mode == 'trackpy' or timelapse_mode == 'iou':
382
+ if timelapse_mode == 'iou':
383
+ track_by_iou = True
384
+ else:
385
+ track_by_iou = False
386
+
390
387
  mask_stack = _trackpy_track_cells(src=src,
391
388
  name=name,
392
389
  batch_filenames=batch_filenames,
@@ -397,7 +394,8 @@ def generate_cellpose_masks(src, settings, object_type):
397
394
  timelapse_remove_transient=timelapse_remove_transient,
398
395
  plot=settings['plot'],
399
396
  save=settings['save'],
400
- mode=timelapse_mode)
397
+ mode=timelapse_mode,
398
+ track_by_iou=track_by_iou)
401
399
  else:
402
400
  mask_stack = _masks_to_masks_stack(masks)
403
401
  else:
@@ -819,97 +817,6 @@ def reducer_hyperparameter_search(settings={}, reduction_params=None, dbscan_par
819
817
 
820
818
  return
821
819
 
822
- def generate_mediar_masks(src, settings, object_type):
823
- """
824
- Generates masks using the MEDIARPredictor.
825
-
826
- :param src: Source folder containing images or npz files.
827
- :param settings: Dictionary of settings for generating masks.
828
- :param object_type: Type of object to detect (e.g., 'cell', 'nucleus', etc.).
829
- """
830
- from .mediar import MEDIARPredictor
831
- from .io import _create_database, _save_object_counts_to_database
832
- from .plot import plot_masks
833
- from .settings import set_default_settings_preprocess_generate_masks
834
- from .utils import prepare_batch_for_segmentation
835
-
836
- # Clear CUDA cache and check if CUDA is available
837
- gc.collect()
838
- if not torch.cuda.is_available():
839
- print(f'Torch CUDA is not available, using CPU')
840
-
841
- settings['src'] = src
842
-
843
- # Preprocess settings
844
- settings = set_default_settings_preprocess_generate_masks(settings)
845
-
846
- if settings['verbose']:
847
- settings_df = pd.DataFrame(list(settings.items()), columns=['setting_key', 'setting_value'])
848
- settings_df['setting_value'] = settings_df['setting_value'].apply(str)
849
- display(settings_df)
850
-
851
- figuresize = 10
852
- timelapse = settings['timelapse']
853
- batch_size = settings['batch_size']
854
-
855
- # Get object settings and initialize MEDIARPredictor
856
- mediar_predictor = MEDIARPredictor(input_path=None, output_path=None, normalize=settings['normalize'], use_tta=False)
857
-
858
- # Paths to input npz files
859
- paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.npz')]
860
-
861
- # Initialize a database for saving measurements
862
- count_loc = os.path.join(os.path.dirname(src), 'measurements', 'measurements.db')
863
- os.makedirs(os.path.dirname(src) + '/measurements', exist_ok=True)
864
- _create_database(count_loc)
865
-
866
- for file_index, path in enumerate(paths):
867
- name = os.path.basename(path)
868
- name, ext = os.path.splitext(name)
869
- output_folder = os.path.join(os.path.dirname(path), f'{object_type}_mask_stack')
870
- os.makedirs(output_folder, exist_ok=True)
871
-
872
- with np.load(path) as data:
873
- stack = data['data']
874
- filenames = data['filenames']
875
-
876
- for i, filename in enumerate(filenames):
877
- output_path = os.path.join(output_folder, filename)
878
- if os.path.exists(output_path):
879
- print(f"File {filename} already exists. Skipping...")
880
- continue
881
-
882
- # Process each batch of images in the stack
883
- for i in range(0, stack.shape[0], batch_size):
884
- batch = stack[i: i + batch_size]
885
- batch_filenames = filenames[i: i + batch_size]
886
-
887
- # Prepare batch for MEDIARPredictor (optional)
888
- batch = prepare_batch_for_segmentation(batch)
889
-
890
- # Predict masks using MEDIARPredictor
891
- predicted_masks = mediar_predictor.predict_batch(batch)
892
-
893
- # Save predicted masks
894
- for j, mask in enumerate(predicted_masks):
895
- output_filename = os.path.join(output_folder, batch_filenames[j])
896
- mask = mask.astype(np.uint16)
897
- np.save(output_filename, mask)
898
-
899
- # Optional: Plot the masks
900
- if settings['plot']:
901
- for idx, mask in enumerate(predicted_masks):
902
- plot_masks(batch[idx], mask, cmap='inferno', figuresize=figuresize)
903
-
904
- # Save object counts to database
905
- _save_object_counts_to_database(predicted_masks, object_type, batch_filenames, count_loc)
906
-
907
- # Clear CUDA cache after each file
908
- gc.collect()
909
- torch.cuda.empty_cache()
910
-
911
- print("Mask generation completed.")
912
-
913
820
  def generate_screen_graphs(settings):
914
821
  """
915
822
  Generate screen graphs for different measurements in a given source directory.
spacr/gui_core.py CHANGED
@@ -872,7 +872,7 @@ def check_src_folders_files(settings, settings_type, q):
872
872
  pictures_continue = _folder_has_images(path)
873
873
  folder_chan_continue = _has_folder(path, "1")
874
874
  folder_stack_continue = _has_folder(path, "stack")
875
- folder_npz_continue = _has_folder(path, "norm_channel_stack")
875
+ folder_npz_continue = _has_folder(path, "masks")
876
876
 
877
877
  if not pictures_continue:
878
878
  if not any([folder_chan_continue, folder_stack_continue, folder_npz_continue]):
@@ -883,7 +883,7 @@ def check_src_folders_files(settings, settings_type, q):
883
883
  q.put(f"Error: Missing stack folder in folder: {path}")
884
884
 
885
885
  if not folder_npz_continue:
886
- q.put(f"Error: Missing norm_channel_stack folder in folder: {path}")
886
+ q.put(f"Error: Missing masks folder in folder: {path}")
887
887
  else:
888
888
  q.put(f"Error: No images in folder: {path}")
889
889
 
spacr/gui_utils.py CHANGED
@@ -376,26 +376,14 @@ def convert_settings_dict_for_gui(settings):
376
376
  'channel_dims': ('combo', chan_list, '[0,1,2,3]'),
377
377
  'dataset_mode': ('combo', ['annotation', 'metadata', 'recruitment'], 'metadata'),
378
378
  'cov_type': ('combo', ['HC0', 'HC1', 'HC2', 'HC3', None], None),
379
- #'cell_mask_dim': ('combo', chans_v3, None),
380
- #'cell_chann_dim': ('combo', chans_v3, None),
381
- #'nucleus_mask_dim': ('combo', chans_v3, None),
382
- #'nucleus_chann_dim': ('combo', chans_v3, None),
383
- #'pathogen_mask_dim': ('combo', chans_v3, None),
384
- #'pathogen_chann_dim': ('combo', chans_v3, None),
385
379
  'crop_mode': ('combo', ["['cell']", "['nucleus']", "['pathogen']", "['cell', 'nucleus']", "['cell', 'pathogen']", "['nucleus', 'pathogen']", "['cell', 'nucleus', 'pathogen']"], "['cell']"),
386
- #'magnification': ('combo', [20, 40, 60], 20),
387
- #'nucleus_channel': ('combo', chans_v3, None),
388
- #'cell_channel': ('combo', chans_v3, None),
389
- #'channel_of_interest': ('combo', chans_v3, None),
390
- #'pathogen_channel': ('combo', chans_v3, None),
391
- 'timelapse_mode': ('combo', ['trackpy', 'btrack'], 'trackpy'),
380
+ 'timelapse_mode': ('combo', ['trackpy', 'iou', 'btrack'], 'trackpy'),
392
381
  'train_mode': ('combo', ['erm', 'irm'], 'erm'),
393
382
  'clustering': ('combo', ['dbscan', 'kmean'], 'dbscan'),
394
383
  'reduction_method': ('combo', ['umap', 'tsne'], 'umap'),
395
384
  'model_name': ('combo', ['cyto', 'cyto_2', 'cyto_3', 'nuclei'], 'cyto'),
396
385
  'regression_type': ('combo', ['ols','gls','wls','rlm','glm','mixed','quantile','logit','probit','poisson','lasso','ridge'], 'ols'),
397
386
  'timelapse_objects': ('combo', ["['cell']", "['nucleus']", "['pathogen']", "['cell', 'nucleus']", "['cell', 'pathogen']", "['nucleus', 'pathogen']", "['cell', 'nucleus', 'pathogen']", None], None),
398
- #'timelapse_objects': ('combo', '[cell]', '[nucleus]', '[pathogen]', '[cytoplasm]', None, None),
399
387
  'model_type': ('combo', torchvision_models, 'resnet50'),
400
388
  'optimizer_type': ('combo', ['adamw', 'adam'], 'adamw'),
401
389
  'schedule': ('combo', ['reduce_lr_on_plateau', 'step_lr'], 'reduce_lr_on_plateau'),
spacr/io.py CHANGED
@@ -1175,7 +1175,7 @@ def concatenate_and_normalize(src, channels, save_dtype=np.float32, settings={})
1175
1175
 
1176
1176
  paths = []
1177
1177
  time_ls = []
1178
- output_fldr = os.path.join(os.path.dirname(src), 'norm_channel_stack')
1178
+ output_fldr = os.path.join(os.path.dirname(src), 'masks')
1179
1179
  os.makedirs(output_fldr, exist_ok=True)
1180
1180
 
1181
1181
  if settings['timelapse']:
@@ -1333,7 +1333,7 @@ def _normalize_stack(src, backgrounds=[100, 100, 100], remove_backgrounds=[False
1333
1333
  None
1334
1334
  """
1335
1335
  paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.npz')]
1336
- output_fldr = os.path.join(os.path.dirname(src), 'norm_channel_stack')
1336
+ output_fldr = os.path.join(os.path.dirname(src), 'masks')
1337
1337
  os.makedirs(output_fldr, exist_ok=True)
1338
1338
  time_ls = []
1339
1339
 
@@ -1418,7 +1418,7 @@ def _normalize_timelapse(src, lower_percentile=2, save_dtype=np.float32):
1418
1418
  save_dtype (numpy.dtype, optional): The data type to save the normalized stack. Defaults to np.float32.
1419
1419
  """
1420
1420
  paths = [os.path.join(src, file) for file in os.listdir(src) if file.endswith('.npz')]
1421
- output_fldr = os.path.join(os.path.dirname(src), 'norm_channel_stack')
1421
+ output_fldr = os.path.join(os.path.dirname(src), 'masks')
1422
1422
  os.makedirs(output_fldr, exist_ok=True)
1423
1423
 
1424
1424
  for file_index, path in enumerate(paths):
@@ -1567,16 +1567,16 @@ def preprocess_img_data(settings):
1567
1567
  Returns:
1568
1568
  None
1569
1569
  """
1570
-
1571
1570
  src = settings['src']
1572
- delete_empty_subdirectories(src)
1573
- files = os.listdir(src)
1574
1571
 
1572
+ if len(os.listdir(src)) < 100:
1573
+ delete_empty_subdirectories(src)
1574
+
1575
+ files = os.listdir(src)
1575
1576
  valid_ext = ['tif', 'tiff', 'png', 'jpg', 'jpeg', 'bmp', 'nd2', 'czi', 'lif']
1576
1577
  extensions = [file.split('.')[-1].lower() for file in files]
1577
1578
  # Filter only valid extensions
1578
1579
  valid_extensions = [ext for ext in extensions if ext in valid_ext]
1579
-
1580
1580
  # Determine most common valid extension
1581
1581
  img_format = None
1582
1582
  if valid_extensions:
@@ -1595,10 +1595,10 @@ def preprocess_img_data(settings):
1595
1595
  print('Found existing stack folder.')
1596
1596
  if os.path.exists(os.path.join(src,'channel_stack')):
1597
1597
  print('Found existing channel_stack folder.')
1598
- if os.path.exists(os.path.join(src,'norm_channel_stack')):
1599
- print('Found existing norm_channel_stack folder. Skipping preprocessing')
1598
+ if os.path.exists(os.path.join(src,'masks')):
1599
+ print('Found existing masks folder. Skipping preprocessing')
1600
1600
  return settings, src
1601
-
1601
+
1602
1602
  mask_channels = [settings['nucleus_channel'], settings['cell_channel'], settings['pathogen_channel']]
1603
1603
 
1604
1604
  settings = set_default_settings_preprocess_img_data(settings)
@@ -1606,16 +1606,16 @@ def preprocess_img_data(settings):
1606
1606
  regex = _get_regex(settings['metadata_type'], img_format, settings['custom_regex'])
1607
1607
 
1608
1608
  if settings['test_mode']:
1609
-
1610
1609
  print(f"Running spacr in test mode")
1611
1610
  settings['plot'] = True
1612
- try:
1613
- os.rmdir(os.path.join(src, 'test'))
1614
- print(f"Deleted test directory: {os.path.join(src, 'test')}")
1615
- except OSError as e:
1616
- print(f"Error deleting test directory: {e}")
1617
- print(f"Delete manually before running test mode")
1618
- pass
1611
+ if os.path.exists(os.path.join(src,'test')):
1612
+ try:
1613
+ os.rmdir(os.path.join(src, 'test'))
1614
+ print(f"Deleted test directory: {os.path.join(src, 'test')}")
1615
+ except OSError as e:
1616
+ print(f"Error deleting test directory: {e}")
1617
+ print(f"Delete manually before running test mode")
1618
+ pass
1619
1619
 
1620
1620
  src = _run_test_mode(settings['src'], regex, settings['timelapse'], settings['test_images'], settings['random_test'])
1621
1621
  settings['src'] = src
@@ -1991,12 +1991,12 @@ def _load_and_concatenate_arrays(src, channels, cell_chann_dim, nucleus_chann_di
1991
1991
  """
1992
1992
  folder_paths = [os.path.join(src+'/stack')]
1993
1993
 
1994
- if cell_chann_dim is not None or os.path.exists(os.path.join(src, 'norm_channel_stack', 'cell_mask_stack')):
1995
- folder_paths = folder_paths + [os.path.join(src, 'norm_channel_stack','cell_mask_stack')]
1996
- if nucleus_chann_dim is not None or os.path.exists(os.path.join(src, 'norm_channel_stack', 'nucleus_mask_stack')):
1997
- folder_paths = folder_paths + [os.path.join(src, 'norm_channel_stack','nucleus_mask_stack')]
1998
- if pathogen_chann_dim is not None or os.path.exists(os.path.join(src, 'norm_channel_stack', 'pathogen_mask_stack')):
1999
- folder_paths = folder_paths + [os.path.join(src, 'norm_channel_stack','pathogen_mask_stack')]
1994
+ if cell_chann_dim is not None or os.path.exists(os.path.join(src, 'masks', 'cell_mask_stack')):
1995
+ folder_paths = folder_paths + [os.path.join(src, 'masks','cell_mask_stack')]
1996
+ if nucleus_chann_dim is not None or os.path.exists(os.path.join(src, 'masks', 'nucleus_mask_stack')):
1997
+ folder_paths = folder_paths + [os.path.join(src, 'masks','nucleus_mask_stack')]
1998
+ if pathogen_chann_dim is not None or os.path.exists(os.path.join(src, 'masks', 'pathogen_mask_stack')):
1999
+ folder_paths = folder_paths + [os.path.join(src, 'masks','pathogen_mask_stack')]
2000
2000
 
2001
2001
  output_folder = src+'/merged'
2002
2002
  reference_folder = folder_paths[0]
@@ -2870,7 +2870,6 @@ def generate_training_dataset(settings):
2870
2870
 
2871
2871
  return class_paths_ls
2872
2872
 
2873
- from .io import _read_and_merge_data, _read_db
2874
2873
  from .utils import get_paths_from_db, annotate_conditions, save_settings
2875
2874
  from .settings import set_generate_training_dataset_defaults
2876
2875
 
spacr/mediar.py CHANGED
@@ -15,14 +15,18 @@ if not os.path.exists(init_file):
15
15
  # Add MEDIAR to sys.path
16
16
  sys.path.insert(0, mediar_path)
17
17
 
18
- try:
19
- # Now import the dependencies from MEDIAR
20
- from core.MEDIAR import Predictor, EnsemblePredictor
21
- from train_tools.models import MEDIARFormer
22
- finally:
23
- # Remove the temporary __init__.py file after the import
24
- if os.path.exists(init_file):
25
- os.remove(init_file) # Remove the __init__.py file
18
+ #try:
19
+ # Now import the dependencies from MEDIAR
20
+ # from core.MEDIAR import Predictor, EnsemblePredictor
21
+ # from train_tools.models import MEDIARFormer
22
+
23
+ # from train_tools.models import MEDIARFormer
24
+ Predictor, EnsemblePredictor, MEDIARFormer = None, None, None
25
+
26
+ #finally:
27
+ # # Remove the temporary __init__.py file after the import
28
+ # if os.path.exists(init_file):
29
+ # os.remove(init_file) # Remove the __init__.py file
26
30
 
27
31
  def display_imgs_in_list(lists_of_imgs, cmaps=None):
28
32
  """
spacr/plot.py CHANGED
@@ -1414,7 +1414,8 @@ def _plot_recruitment(df, df_type, channel_of_interest, columns=[], figuresize=1
1414
1414
  sns.barplot(ax=ax, data=df, x='condition', y=f'{col}', hue='pathogen', capsize=.1, ci='sd', dodge=False)
1415
1415
  ax.set_xlabel(f'pathogen {df_type}', fontsize=font)
1416
1416
  ax.set_ylabel(f'{col}', fontsize=int(font*2))
1417
- ax.legend_.remove()
1417
+ if ax.get_legend() is not None:
1418
+ ax.legend_.remove()
1418
1419
  ax.tick_params(axis='both', which='major', labelsize=font)
1419
1420
  ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
1420
1421
  if i <= 5:
@@ -2031,7 +2032,7 @@ def plot_comparison_results(comparison_results):
2031
2032
  def plot_object_outlines(src, objects=['nucleus','cell','pathogen'], channels=[0,1,2], max_nr=10):
2032
2033
 
2033
2034
  for object_, channel in zip(objects, channels):
2034
- folders = [os.path.join(src, 'norm_channel_stack', f'{object_}_mask_stack'),
2035
+ folders = [os.path.join(src, 'masks', f'{object_}_mask_stack'),
2035
2036
  os.path.join(src,f'{channel+1}')]
2036
2037
  print(folders)
2037
2038
  plot_images_and_arrays(folders,
@@ -2597,7 +2598,7 @@ class spacrGraph:
2597
2598
  # Group by ['prc', grouping_column]
2598
2599
  group_cols = ['prc', self.grouping_column]
2599
2600
 
2600
- elif self.representation == 'plateID':
2601
+ elif self.representation == 'plate':
2601
2602
  # Make sure 'plateID' exists (split from 'prc' if needed)
2602
2603
  if 'plateID' not in df.columns:
2603
2604
  if 'prc' in df.columns:
@@ -2930,6 +2931,7 @@ class spacrGraph:
2930
2931
  self.df_melted = pd.melt(self.df, id_vars=[self.grouping_column], value_vars=self.data_column,var_name='Data Column', value_name='Value')
2931
2932
  unique_groups = self.df[self.grouping_column].unique()
2932
2933
  is_normal, normality_results = self.perform_normality_tests()
2934
+ is_normal = True
2933
2935
  levene_stat, levene_p = self.perform_levene_test(unique_groups)
2934
2936
  test_results = self.perform_statistical_tests(unique_groups, is_normal)
2935
2937
  posthoc_results = self.perform_posthoc_tests(is_normal, unique_groups)
@@ -3371,8 +3373,11 @@ class spacrGraph:
3371
3373
  return self.fig
3372
3374
 
3373
3375
  def plot_data_from_db(settings):
3376
+
3374
3377
  from .io import _read_db, _read_and_merge_data
3375
3378
  from .utils import annotate_conditions, save_settings
3379
+ from .settings import set_default_plot_data_from_db
3380
+
3376
3381
  """
3377
3382
  Extracts the specified table from the SQLite database and plots a specified column.
3378
3383
 
@@ -3385,8 +3390,8 @@ def plot_data_from_db(settings):
3385
3390
  df (pd.DataFrame): The extracted table as a DataFrame.
3386
3391
  """
3387
3392
 
3388
-
3389
-
3393
+ settings = set_default_plot_data_from_db(settings)
3394
+
3390
3395
  if isinstance(settings['src'], str):
3391
3396
  srcs = [settings['src']]
3392
3397
  elif isinstance(settings['src'], list):
@@ -3403,7 +3408,6 @@ def plot_data_from_db(settings):
3403
3408
 
3404
3409
  dfs = []
3405
3410
  for i, src in enumerate(srcs):
3406
-
3407
3411
  db_loc = os.path.join(src, 'measurements', settings['database'][i])
3408
3412
  print(f"Database: {db_loc}")
3409
3413
  if settings['table_names'] in ['saliency_image_correlations']:
@@ -3415,7 +3419,7 @@ def plot_data_from_db(settings):
3415
3419
  verbose=settings['verbose'],
3416
3420
  nuclei_limit=settings['nuclei_limit'],
3417
3421
  pathogen_limit=settings['pathogen_limit'])
3418
-
3422
+
3419
3423
  dft = annotate_conditions(df1,
3420
3424
  cells=settings['cell_types'],
3421
3425
  cell_loc=settings['cell_plate_metadata'],
@@ -3436,12 +3440,27 @@ def plot_data_from_db(settings):
3436
3440
 
3437
3441
  if settings['treatment_plate_metadata'] != None:
3438
3442
  df = df.dropna(subset='treatment')
3439
-
3443
+
3444
+ if settings['data_column'] == 'recruitment':
3445
+ pahtogen_measurement = df[f"pathogen_channel_{settings['channel_of_interest']}_mean_intensity"]
3446
+ cytoplasm_measurement = df[f"cytoplasm_channel_{settings['channel_of_interest']}_mean_intensity"]
3447
+ df['recruitment'] = pahtogen_measurement / cytoplasm_measurement
3448
+
3449
+ if settings['data_column'] not in df.columns:
3450
+ print(f"Data column {settings['data_column']} not found in DataFrame.")
3451
+ print(f'Please use one of the following columns:')
3452
+ for col in df.columns:
3453
+ print(col)
3454
+ display(df)
3455
+ return None
3456
+
3440
3457
  df = df.dropna(subset=settings['data_column'])
3441
3458
 
3442
3459
  if settings['grouping_column'] not in df.columns:
3443
3460
  print(f"Grouping column {settings['grouping_column']} not found in DataFrame.")
3444
- print(f'Please use one of the following columns: {df.columns}')
3461
+ print(f'Please use one of the following columns:')
3462
+ for col in df.columns:
3463
+ print(col)
3445
3464
  display(df)
3446
3465
  return None
3447
3466
 
@@ -3480,7 +3499,8 @@ def plot_data_from_db(settings):
3480
3499
 
3481
3500
  def plot_data_from_csv(settings):
3482
3501
  from .io import _read_db, _read_and_merge_data
3483
- from .utils import annotate_conditions, save_settings
3502
+ from .utils import annotate_conditions, save_settings, remove_outliers_by_group
3503
+ from .settings import get_plot_data_from_csv_default_settings
3484
3504
  """
3485
3505
  Extracts the specified table from the SQLite database and plots a specified column.
3486
3506
 
@@ -3492,7 +3512,12 @@ def plot_data_from_csv(settings):
3492
3512
  Returns:
3493
3513
  df (pd.DataFrame): The extracted table as a DataFrame.
3494
3514
  """
3515
+
3495
3516
 
3517
+ def filter_rows_by_column_values(df: pd.DataFrame, column: str, values: list) -> pd.DataFrame:
3518
+ """Return a filtered DataFrame where only rows with the column value in the list are kept."""
3519
+ return df[df[column].isin(values)].copy()
3520
+
3496
3521
  if isinstance(settings['src'], str):
3497
3522
  srcs = [settings['src']]
3498
3523
  elif isinstance(settings['src'], list):
@@ -3519,15 +3544,27 @@ def plot_data_from_csv(settings):
3519
3544
  except Exception as e:
3520
3545
  print(f"Could not split the prc column: {e}")
3521
3546
 
3522
-
3523
- display(df)
3524
-
3547
+ if 'keep_groups' in settings.keys():
3548
+ if isinstance(settings['keep_groups'], str):
3549
+ settings['keep_groups'] = [settings['keep_groups']]
3550
+ elif isinstance(settings['keep_groups'], list):
3551
+ df = filter_rows_by_column_values(df, settings['grouping_column'], settings['keep_groups'])
3552
+
3553
+ if settings['remove_outliers']:
3554
+ df = remove_outliers_by_group(df, settings['grouping_column'], settings['data_column'], method='iqr', threshold=1.5)
3555
+
3556
+ if settings['verbose']:
3557
+ display(df)
3558
+
3525
3559
  df = df.dropna(subset=settings['data_column'])
3526
3560
  df = df.dropna(subset=settings['grouping_column'])
3527
3561
  src = srcs[0]
3528
3562
  dst = os.path.join(os.path.dirname(src), 'results', settings['graph_name'])
3529
3563
  os.makedirs(dst, exist_ok=True)
3530
3564
 
3565
+ #data_csv = os.path.join(dst, f"{settings['graph_name']}_data.csv")
3566
+ #df.to_csv(data_csv, index=False)
3567
+
3531
3568
  spacr_graph = spacrGraph(
3532
3569
  df=df, # Your DataFrame
3533
3570
  grouping_column=settings['grouping_column'], # Column for grouping the data (x-axis)
spacr/settings.py CHANGED
@@ -29,7 +29,6 @@ def set_default_settings_preprocess_generate_masks(settings={}):
29
29
  settings.setdefault('denoise', False)
30
30
  settings.setdefault('src', 'path')
31
31
  settings.setdefault('delete_intermediate', False)
32
- settings.setdefault('segmentation_mode', 'cellpose')
33
32
  settings.setdefault('preprocess', True)
34
33
  settings.setdefault('masks', True)
35
34
  settings.setdefault('save', True)
@@ -100,6 +99,33 @@ def set_default_settings_preprocess_generate_masks(settings={}):
100
99
  settings.setdefault('adjust_cells', False)
101
100
  return settings
102
101
 
102
+ def set_default_plot_data_from_db(settings):
103
+ settings.setdefault('src', 'path')
104
+ settings.setdefault('database', 'measurements.db')
105
+ settings.setdefault('graph_name', 'Figure_1')
106
+ settings.setdefault('table_names', ['cell', 'cytoplasm', 'nucleus', 'pathogen'])
107
+ settings.setdefault('data_column', 'recruitment')
108
+ settings.setdefault('grouping_column', 'condition')
109
+ settings.setdefault('cell_types', ['Hela'])
110
+ settings.setdefault('cell_plate_metadata', None)
111
+ settings.setdefault('pathogen_types', None)
112
+ settings.setdefault('pathogen_plate_metadata', None)
113
+ settings.setdefault('treatments', None)
114
+ settings.setdefault('treatment_plate_metadata', None)
115
+ settings.setdefault('graph_type', 'jitter')
116
+ settings.setdefault('theme', 'deep')
117
+ settings.setdefault('save', True)
118
+ settings.setdefault('y_lim', [1,1.5])
119
+ settings.setdefault('verbose', False)
120
+ settings.setdefault('channel_of_interest', 1)
121
+ settings.setdefault('nuclei_limit', 2)
122
+ settings.setdefault('pathogen_limit', 3)
123
+ settings.setdefault('representation', 'well')
124
+ settings.setdefault('uninfected', False)
125
+ return settings
126
+
127
+
128
+
103
129
  def set_default_settings_preprocess_img_data_v1(settings):
104
130
 
105
131
  metadata_type = settings.setdefault('metadata_type', 'cellvoyager')
@@ -955,7 +981,6 @@ expected_types = {
955
981
  "png_type":str,
956
982
  "custom_model_path":str,
957
983
  "generate_training_dataset":bool,
958
- "segmentation_mode":str,
959
984
  "train_DL_model":bool,
960
985
  "normalize":bool,
961
986
  "overlay":bool,
@@ -1006,7 +1031,7 @@ expected_types = {
1006
1031
  }
1007
1032
 
1008
1033
  categories = {"Paths":[ "src", "grna", "barcodes", "custom_model_path", "dataset","model_path","grna_csv","row_csv","column_csv", "metadata_files", "score_data","count_data"],
1009
- "General": ["cell_mask_dim", "cytoplasm", "cell_chann_dim", "cell_channel", "nucleus_chann_dim", "nucleus_channel", "nucleus_mask_dim", "pathogen_mask_dim", "pathogen_chann_dim", "pathogen_channel", "test_mode", "plot", "metadata_type", "custom_regex", "experiment", "channels", "magnification", "channel_dims", "apply_model_to_dataset", "generate_training_dataset", "train_DL_model", "segmentation_mode", "delete_intermediate", "uninfected", ],
1034
+ "General": ["cell_mask_dim", "cytoplasm", "cell_chann_dim", "cell_channel", "nucleus_chann_dim", "nucleus_channel", "nucleus_mask_dim", "pathogen_mask_dim", "pathogen_chann_dim", "pathogen_channel", "test_mode", "plot", "metadata_type", "custom_regex", "experiment", "channels", "magnification", "channel_dims", "apply_model_to_dataset", "generate_training_dataset", "train_DL_model", "delete_intermediate", "uninfected", ],
1010
1035
  "Cellpose":["denoise","fill_in","from_scratch", "n_epochs", "width_height", "model_name", "custom_model", "resample", "rescale", "CP_prob", "flow_threshold", "percentiles", "invert", "diameter", "grayscale", "Signal_to_noise", "resize", "target_height", "target_width"],
1011
1036
  "Cell": ["cell_diamiter","cell_intensity_range", "cell_size_range", "cell_background", "cell_Signal_to_noise", "cell_CP_prob", "cell_FT", "remove_background_cell", "cell_min_size", "cytoplasm_min_size", "adjust_cells", "cells", "cell_loc"],
1012
1037
  "Nucleus": ["nucleus_diamiter","nucleus_intensity_range", "nucleus_size_range", "nucleus_background", "nucleus_Signal_to_noise", "nucleus_CP_prob", "nucleus_FT", "remove_background_nucleus", "nucleus_min_size", "nucleus_loc"],
@@ -1217,7 +1242,7 @@ def generate_fields(variables, scrollable_frame):
1217
1242
  "nucleus_min_size": "(int) - The minimum size of nucleus objects in pixels^2.",
1218
1243
  "normalize_by": "(str) - Normalize cropped png images by png or by field of view.",
1219
1244
  "dependent_variable": "(str) - The dependent variable for the regression analysis.",
1220
- "delete_intermediate": "(bool) - Delete intermediate folders (stack, channel, norm_channel_stack).",
1245
+ "delete_intermediate": "(bool) - Delete intermediate folders (stack, channel, masks).",
1221
1246
  "diameter": "(float) - Diameter of the objects to segment.",
1222
1247
  "dialate_png_ratios": "(list) - The ratios to use for dilating the PNG images. This will determine the amount of dilation applied to the images before cropping.",
1223
1248
  "dialate_pngs": "(bool) - Whether to dilate the PNG images before saving.",
@@ -1337,7 +1362,6 @@ def generate_fields(variables, scrollable_frame):
1337
1362
  "skip_mode": "(str) - The mode to use for skipping images. This will determine how to handle images that cannot be processed.",
1338
1363
  "smooth_lines": "(bool) - Whether to smooth lines in the plots.",
1339
1364
  "src": "(str, path) - Path to source directory.",
1340
- "segmentation_mode": "(str) - Algorithm to use for segmentation (cellpose or mediar).",
1341
1365
  "target": "(str) - Target variable for the analysis.",
1342
1366
  "target_height": "(int) - Target height for resizing the images.",
1343
1367
  "target_intensity_min": "(float) - Minimum intensity for the target objects.",
@@ -1376,7 +1400,6 @@ def generate_fields(variables, scrollable_frame):
1376
1400
  "dataset_mode": "str - How to generate train/test dataset.",
1377
1401
  "annotated_classes": "list - list of numbers in annotation column.",
1378
1402
  "um_per_pixel": "(float) - The micrometers per pixel for the images.",
1379
- "segmentation_model": "(str) - The segmentation model to use, either cellpose or mediar.",
1380
1403
  "pathogen_model": "(str) - use a custom cellpose model to detect pathogen objects.",
1381
1404
  "timelapse_displacement": "(int) - Displacement for timelapse tracking.",
1382
1405
  "timelapse_memory": "(int) - Memory for timelapse tracking.",
@@ -1596,4 +1619,20 @@ def set_analyze_class_proportion_defaults(settings):
1596
1619
  settings.setdefault('level','well')
1597
1620
  settings.setdefault('save',False)
1598
1621
  settings.setdefault('verbose', False)
1622
+ return settings
1623
+
1624
+ def get_plot_data_from_csv_default_settings(settings):
1625
+ settings.setdefault('src','path')
1626
+ settings.setdefault('data_column','choose column')
1627
+ settings.setdefault('grouping_column','choose column')
1628
+ settings.setdefault('graph_type','violin')
1629
+ settings.setdefault('save',False)
1630
+ settings.setdefault('y_lim',None)
1631
+ settings.setdefault('log_y',False)
1632
+ settings.setdefault('log_x',False)
1633
+ settings.setdefault('keep_groups',None)
1634
+ settings.setdefault('representation','well')
1635
+ settings.setdefault('theme','dark')
1636
+ settings.setdefault('remove_outliers',False)
1637
+ settings.setdefault('verbose',False)
1599
1638
  return settings