spacr 0.3.42__py3-none-any.whl → 0.3.45__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.
spacr/plot.py CHANGED
@@ -1,8 +1,9 @@
1
- import os, random, cv2, glob, math, torch
1
+ import os, random, cv2, glob, math, torch, skimage
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
5
5
  import matplotlib.pyplot as plt
6
+ from matplotlib.colors import ListedColormap
6
7
  import matplotlib as mpl
7
8
  import scipy.ndimage as ndi
8
9
  import seaborn as sns
@@ -13,6 +14,9 @@ from IPython.display import display
13
14
  from skimage.segmentation import find_boundaries
14
15
  from skimage import measure
15
16
  from skimage.measure import find_contours, label, regionprops
17
+ from skimage.segmentation import mark_boundaries
18
+ from skimage.transform import resize as sk_resize
19
+
16
20
  import tifffile as tiff
17
21
 
18
22
  from scipy.stats import normaltest, ttest_ind, mannwhitneyu, f_oneway, kruskal
@@ -1520,8 +1524,135 @@ def plot_plates(df, variable, grouping, min_max, cmap, min_count=0, verbose=True
1520
1524
  plt.show()
1521
1525
  return fig
1522
1526
 
1523
- def print_mask_and_flows(stack, mask, flows, overlay=False):
1524
- fig, axs = plt.subplots(1, 3, figsize=(30, 10)) # Adjust subplot layout
1527
+ def print_mask_and_flows(stack, mask, flows, overlay=True, max_size=1000, thickness=2):
1528
+ """
1529
+ Display the original image, mask with outlines, and flow images.
1530
+
1531
+ Args:
1532
+ stack (np.array): Original image or stack.
1533
+ mask (np.array): Mask image.
1534
+ flows (list): List of flow images.
1535
+ overlay (bool): Whether to overlay the mask outlines on the original image.
1536
+ max_size (int): Maximum allowed size for any dimension of the images.
1537
+ thickness (int): Thickness of the contour outlines.
1538
+ """
1539
+
1540
+ def resize_if_needed(image, max_size):
1541
+ """Resize image if any dimension exceeds max_size while maintaining aspect ratio."""
1542
+ if max(image.shape[:2]) > max_size:
1543
+ scale = max_size / max(image.shape[:2])
1544
+ new_shape = (int(image.shape[0] * scale), int(image.shape[1] * scale))
1545
+ if image.ndim == 3:
1546
+ new_shape += (image.shape[2],)
1547
+ return sk_resize(image, new_shape, preserve_range=True, anti_aliasing=True).astype(image.dtype)
1548
+ return image
1549
+
1550
+ def generate_contours(mask):
1551
+ """Generate contours for each object in the mask using OpenCV."""
1552
+ contours, _ = cv2.findContours(mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
1553
+ return contours
1554
+
1555
+ def apply_contours_on_image(image, mask, color=(255, 0, 0), thickness=2):
1556
+ """Draw the contours on the original image."""
1557
+ # Ensure the image is in RGB format
1558
+ if image.ndim == 2: # Grayscale to RGB
1559
+ image = normalize_to_uint8(image) # Convert to uint8 if needed
1560
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
1561
+ else:
1562
+ image_rgb = image.copy()
1563
+
1564
+ # Generate and draw contours
1565
+ contours = generate_contours(mask)
1566
+ cv2.drawContours(image_rgb, contours, -1, color, thickness)
1567
+
1568
+ return image_rgb
1569
+
1570
+ def normalize_to_uint8(image):
1571
+ """Normalize and convert image to uint8."""
1572
+ image = np.clip(image, 0, 1) # Ensure values are between 0 and 1
1573
+ return (image * 255).astype(np.uint8) # Convert to uint8
1574
+
1575
+
1576
+ # Resize if necessary
1577
+ stack = resize_if_needed(stack, max_size)
1578
+ mask = resize_if_needed(mask, max_size)
1579
+ if flows != None:
1580
+ flows = [resize_if_needed(flow, max_size) for flow in flows]
1581
+
1582
+ fig, axs = plt.subplots(1, 3, figsize=(12, 4))
1583
+ else:
1584
+ fig, axs = plt.subplots(1, 2, figsize=(12, 4))
1585
+
1586
+ if stack.shape[-1] == 1:
1587
+ stack = np.squeeze(stack)
1588
+
1589
+ # Display original image
1590
+ if stack.ndim == 2:
1591
+ original_image = stack
1592
+ elif stack.ndim == 3:
1593
+ original_image = stack[..., 0] # Use the first channel as the base
1594
+ else:
1595
+ raise ValueError("Unexpected stack dimensionality.")
1596
+
1597
+ axs[0].imshow(original_image, cmap='gray')
1598
+ axs[0].set_title('Original Image')
1599
+ axs[0].axis('off')
1600
+
1601
+ # Overlay mask outlines on original image if overlay is True
1602
+ if overlay:
1603
+ outlined_image = apply_contours_on_image(original_image, mask, color=(255, 0, 0), thickness=thickness)
1604
+ axs[1].imshow(outlined_image)
1605
+ else:
1606
+ axs[1].imshow(mask, cmap='gray')
1607
+
1608
+ axs[1].set_title('Mask with Overlay' if overlay else 'Mask')
1609
+ axs[1].axis('off')
1610
+
1611
+ if flows != None:
1612
+
1613
+ # Display flow image or its first channel
1614
+ if flows and isinstance(flows, list) and flows[0].ndim in [2, 3]:
1615
+ flow_image = flows[0]
1616
+ if flow_image.ndim == 3:
1617
+ flow_image = flow_image[:, :, 0] # Use first channel for 3D
1618
+ axs[2].imshow(flow_image, cmap='jet')
1619
+ else:
1620
+ raise ValueError("Unexpected flow dimensionality or structure.")
1621
+
1622
+ axs[2].set_title('Flows')
1623
+ axs[2].axis('off')
1624
+
1625
+ fig.tight_layout()
1626
+ plt.show()
1627
+
1628
+ def print_mask_and_flows_v1(stack, mask, flows, overlay=False, max_size=1000):
1629
+ """
1630
+ Display the original image, mask, and flow with optional resizing for large images.
1631
+
1632
+ Args:
1633
+ stack (np.array): Original image or stack.
1634
+ mask (np.array): Mask image.
1635
+ flows (list): List of flow images.
1636
+ overlay (bool): Whether to overlay the mask on the original image.
1637
+ max_size (int): Maximum allowed size for any dimension of the images.
1638
+ """
1639
+
1640
+ def resize_if_needed(image, max_size):
1641
+ """Resize image if any dimension exceeds max_size while maintaining aspect ratio."""
1642
+ if max(image.shape[:2]) > max_size:
1643
+ scale = max_size / max(image.shape[:2])
1644
+ new_shape = (int(image.shape[0] * scale), int(image.shape[1] * scale))
1645
+ if image.ndim == 3:
1646
+ new_shape += (image.shape[2],)
1647
+ return skimage.transform.resize(image, new_shape, preserve_range=True, anti_aliasing=True).astype(image.dtype)
1648
+ return image
1649
+
1650
+ # Resize if necessary
1651
+ stack = resize_if_needed(stack, max_size)
1652
+ mask = resize_if_needed(mask, max_size)
1653
+ flows = [resize_if_needed(flow, max_size) for flow in flows]
1654
+
1655
+ fig, axs = plt.subplots(1, 3, figsize=(12, 4)) # Adjust subplot layout
1525
1656
 
1526
1657
  if stack.shape[-1] == 1:
1527
1658
  stack = np.squeeze(stack)
@@ -2140,8 +2271,8 @@ def create_grouped_plot(df, grouping_column, data_column, graph_type='bar', summ
2140
2271
 
2141
2272
  class spacrGraph:
2142
2273
  def __init__(self, df, grouping_column, data_column, graph_type='bar', summary_func='mean',
2143
- order=None, colors=None, output_dir='./output', save=False, y_lim=None,
2144
- error_bar_type='std', remove_outliers=False, theme='pastel', representation='object',
2274
+ order=None, colors=None, output_dir='./output', save=False, y_lim=None, log_y=False,
2275
+ log_x=False, error_bar_type='std', remove_outliers=False, theme='pastel', representation='object',
2145
2276
  paired=False, all_to_all=True, compare_group=None, graph_name=None):
2146
2277
 
2147
2278
  """
@@ -2166,7 +2297,8 @@ class spacrGraph:
2166
2297
  self.compare_group = compare_group
2167
2298
  self.y_lim = y_lim
2168
2299
  self.graph_name = graph_name
2169
-
2300
+ self.log_x = log_x
2301
+ self.log_y = log_y
2170
2302
 
2171
2303
  self.results_df = pd.DataFrame()
2172
2304
  self.sns_palette = None
@@ -2582,6 +2714,11 @@ class spacrGraph:
2582
2714
  # Set legend and labels
2583
2715
  ax.set_xlabel(self.grouping_column)
2584
2716
 
2717
+ if self.log_y:
2718
+ ax.set_yscale('log')
2719
+ if self.log_x:
2720
+ ax.set_xscale('log')
2721
+
2585
2722
  def _create_jitter_plot(self, ax):
2586
2723
  """Helper method to create a jitter plot (strip plot) with consistent spacing."""
2587
2724
  # Combine grouping column and data column if needed
@@ -2606,6 +2743,11 @@ class spacrGraph:
2606
2743
  unique_labels = dict(zip(labels, handles))
2607
2744
  ax.legend(unique_labels.values(), unique_labels.keys(), loc='best')
2608
2745
 
2746
+ if self.log_y:
2747
+ ax.set_yscale('log')
2748
+ if self.log_x:
2749
+ ax.set_xscale('log')
2750
+
2609
2751
  def _create_line_graph(self, ax):
2610
2752
  """Helper method to create a line graph with one line per group based on epochs and accuracy."""
2611
2753
  #display(self.df)
@@ -2629,6 +2771,11 @@ class spacrGraph:
2629
2771
  ax.set_xlabel(f"{x_axis_column}")
2630
2772
  ax.set_ylabel(f"{y_axis_column}")
2631
2773
 
2774
+ if self.log_y:
2775
+ ax.set_yscale('log')
2776
+ if self.log_x:
2777
+ ax.set_xscale('log')
2778
+
2632
2779
  def _create_line_with_std_area(self, ax):
2633
2780
  """Helper method to create a line graph with shaded area representing standard deviation."""
2634
2781
 
@@ -2652,7 +2799,12 @@ class spacrGraph:
2652
2799
  # Adjust axis labels
2653
2800
  ax.set_xlabel(f"{x_axis_column}")
2654
2801
  ax.set_ylabel(f"{y_axis_column}")
2655
-
2802
+
2803
+ if self.log_y:
2804
+ ax.set_yscale('log')
2805
+ if self.log_x:
2806
+ ax.set_xscale('log')
2807
+
2656
2808
  def _create_box_plot(self, ax):
2657
2809
  """Helper method to create a box plot with consistent spacing."""
2658
2810
  # Combine grouping column and data column if needed
@@ -2676,6 +2828,11 @@ class spacrGraph:
2676
2828
  handles, labels = ax.get_legend_handles_labels()
2677
2829
  unique_labels = dict(zip(labels, handles))
2678
2830
  ax.legend(unique_labels.values(), unique_labels.keys(), loc='best')
2831
+
2832
+ if self.log_y:
2833
+ ax.set_yscale('log')
2834
+ if self.log_x:
2835
+ ax.set_xscale('log')
2679
2836
 
2680
2837
  def _create_violin_plot(self, ax):
2681
2838
  """Helper method to create a violin plot with consistent spacing."""
@@ -2702,6 +2859,11 @@ class spacrGraph:
2702
2859
  unique_labels = dict(zip(labels, handles))
2703
2860
  ax.legend(unique_labels.values(), unique_labels.keys(), loc='best')
2704
2861
 
2862
+ if self.log_y:
2863
+ ax.set_yscale('log')
2864
+ if self.log_x:
2865
+ ax.set_xscale('log')
2866
+
2705
2867
  def _create_jitter_bar_plot(self, ax):
2706
2868
  """Helper method to create a bar plot with consistent bar thickness and centered error bars."""
2707
2869
  # Flatten DataFrame: Combine grouping column and data column into one group if needed
@@ -2739,6 +2901,11 @@ class spacrGraph:
2739
2901
  # Set legend and labels
2740
2902
  ax.set_xlabel(self.grouping_column)
2741
2903
 
2904
+ if self.log_y:
2905
+ ax.set_yscale('log')
2906
+ if self.log_x:
2907
+ ax.set_xscale('log')
2908
+
2742
2909
  def _create_jitter_box_plot(self, ax):
2743
2910
  """Helper method to create a box plot with consistent spacing."""
2744
2911
  # Combine grouping column and data column if needed
@@ -2764,6 +2931,11 @@ class spacrGraph:
2764
2931
  unique_labels = dict(zip(labels, handles))
2765
2932
  ax.legend(unique_labels.values(), unique_labels.keys(), loc='best')
2766
2933
 
2934
+ if self.log_y:
2935
+ ax.set_yscale('log')
2936
+ if self.log_x:
2937
+ ax.set_xscale('log')
2938
+
2767
2939
  def _save_results(self):
2768
2940
  """Helper method to save the plot and results."""
2769
2941
  os.makedirs(self.output_dir, exist_ok=True)
@@ -2907,15 +3079,12 @@ def plot_data_from_csv(settings):
2907
3079
 
2908
3080
  dfs = []
2909
3081
  for i, src in enumerate(srcs):
2910
-
2911
3082
  dft = pd.read_csv(src)
2912
3083
  if 'plate' not in dft.columns:
2913
3084
  dft['plate'] = f"plate{i+1}"
2914
3085
  dfs.append(dft)
2915
-
2916
- df = pd.concat(dfs, axis=0)
2917
- #display(df)
2918
3086
 
3087
+ df = pd.concat(dfs, axis=0)
2919
3088
  df = df.dropna(subset=settings['data_column'])
2920
3089
  df = df.dropna(subset=settings['grouping_column'])
2921
3090
  src = srcs[0]
@@ -2933,6 +3102,7 @@ def plot_data_from_csv(settings):
2933
3102
  output_dir=dst, # Directory to save the plot and results
2934
3103
  save=settings['save'], # Whether to save the plot and results
2935
3104
  y_lim=settings['y_lim'], # Starting point for y-axis (optional)
3105
+ log_y=settings['log_y'], # Log-transform the y-axis
2936
3106
  error_bar_type='std', # Type of error bar ('std' or 'sem')
2937
3107
  representation=settings['representation'],
2938
3108
  theme=settings['theme'], # Seaborn color palette theme (e.g., 'pastel', 'muted')
@@ -3073,3 +3243,87 @@ def plot_image_grid(image_paths, percentiles):
3073
3243
  plt.subplots_adjust(wspace=0, hspace=0, left=0, right=1, top=1, bottom=0)
3074
3244
 
3075
3245
  return fig
3246
+
3247
+ def overlay_masks_on_images(img_folder, normalize=True, resize=True, save=False, plot=False, thickness=2):
3248
+ """
3249
+ Load images and masks from folders, overlay mask contours on images, and optionally normalize, resize, and save.
3250
+
3251
+ Args:
3252
+ img_folder (str): Path to the folder containing images.
3253
+ mask_folder (str): Path to the folder containing masks.
3254
+ normalize (bool): If True, normalize images to the 1st and 99th percentiles.
3255
+ resize (bool): If True, resize the final overlay to 500x500.
3256
+ save (bool): If True, save the final overlay in an 'overlay' folder within the image folder.
3257
+ thickness (int): Thickness of the contour lines.
3258
+ """
3259
+
3260
+ def normalize_image(image):
3261
+ """Normalize the image to the 1st and 99th percentiles."""
3262
+ lower, upper = np.percentile(image, [1, 99])
3263
+ image = np.clip((image - lower) / (upper - lower), 0, 1)
3264
+ return (image * 255).astype(np.uint8)
3265
+
3266
+
3267
+ mask_folder = os.path.join(img_folder,'masks')
3268
+ overlay_folder = os.path.join(img_folder, "overlay")
3269
+ if save and not os.path.exists(overlay_folder):
3270
+ os.makedirs(overlay_folder)
3271
+
3272
+ # Get common filenames in both image and mask folders
3273
+ image_filenames = set(os.listdir(img_folder))
3274
+ mask_filenames = set(os.listdir(mask_folder))
3275
+ common_filenames = image_filenames.intersection(mask_filenames)
3276
+
3277
+ if not common_filenames:
3278
+ print("No matching filenames found in both folders.")
3279
+ return
3280
+
3281
+ for filename in common_filenames:
3282
+ # Load image and mask
3283
+ img_path = os.path.join(img_folder, filename)
3284
+ mask_path = os.path.join(mask_folder, filename)
3285
+
3286
+ image = tiff.imread(img_path)
3287
+ mask = tiff.imread(mask_path)
3288
+
3289
+ # Normalize the image if requested
3290
+ if normalize:
3291
+ image = normalize_image(image)
3292
+
3293
+ # Ensure the mask is binary
3294
+ mask = (mask > 0).astype(np.uint8)
3295
+
3296
+ # Resize the mask if it doesn't match the image size
3297
+ if mask.shape != image.shape[:2]:
3298
+ mask = cv2.resize(mask, (image.shape[1], image.shape[0]), interpolation=cv2.INTER_NEAREST)
3299
+
3300
+ # Generate contours from the mask
3301
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
3302
+
3303
+ # Convert to RGB if grayscale
3304
+ if image.ndim == 2:
3305
+ image_rgb = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
3306
+ else:
3307
+ image_rgb = image.copy()
3308
+
3309
+ # Draw contours with alpha blending
3310
+ overlay = image_rgb.copy()
3311
+ cv2.drawContours(overlay, contours, -1, (255, 0, 0), thickness)
3312
+ blended = cv2.addWeighted(overlay, 0.7, image_rgb, 0.3, 0)
3313
+
3314
+ # Resize the final overlay if requested
3315
+ if resize:
3316
+ blended = cv2.resize(blended, (1000, 1000), interpolation=cv2.INTER_AREA)
3317
+
3318
+ # Save the overlay if requested
3319
+ if save:
3320
+ save_path = os.path.join(overlay_folder, filename)
3321
+ cv2.imwrite(save_path, cv2.cvtColor(blended, cv2.COLOR_RGB2BGR))
3322
+
3323
+ if plot:
3324
+ # Display the result
3325
+ plt.figure(figsize=(10, 10))
3326
+ plt.imshow(blended)
3327
+ plt.title(f"Overlay: {filename}")
3328
+ plt.axis('off')
3329
+ plt.show()
spacr/settings.py CHANGED
@@ -566,7 +566,6 @@ def get_check_cellpose_models_default_settings(settings):
566
566
  settings.setdefault('normalize', True)
567
567
  settings.setdefault('channels', [0,0])
568
568
  settings.setdefault('percentiles', None)
569
- settings.setdefault('circular', False)
570
569
  settings.setdefault('invert', False)
571
570
  settings.setdefault('plot', True)
572
571
  settings.setdefault('diameter', 40)
@@ -581,6 +580,7 @@ def get_check_cellpose_models_default_settings(settings):
581
580
  return settings
582
581
 
583
582
  def get_identify_masks_finetune_default_settings(settings):
583
+ settings.setdefault('src', 'path')
584
584
  settings.setdefault('model_name', 'cyto')
585
585
  settings.setdefault('custom_model', None)
586
586
  settings.setdefault('channels', [0,0])
@@ -595,7 +595,6 @@ def get_identify_masks_finetune_default_settings(settings):
595
595
  settings.setdefault('verbose', False)
596
596
  settings.setdefault('normalize', True)
597
597
  settings.setdefault('percentiles', None)
598
- settings.setdefault('circular', False)
599
598
  settings.setdefault('invert', False)
600
599
  settings.setdefault('resize', False)
601
600
  settings.setdefault('target_height', None)
@@ -603,6 +602,7 @@ def get_identify_masks_finetune_default_settings(settings):
603
602
  settings.setdefault('rescale', False)
604
603
  settings.setdefault('resample', False)
605
604
  settings.setdefault('grayscale', True)
605
+ settings.setdefault('fill_in', True)
606
606
  return settings
607
607
 
608
608
  q = None
@@ -690,6 +690,7 @@ expected_types = {
690
690
  "filter_min_max": (list, type(None)),
691
691
  "channel_dims": list,
692
692
  "backgrounds": list,
693
+ "background": str,
693
694
  "outline_thickness": int,
694
695
  "outline_color": str,
695
696
  "overlay_chans": list,
@@ -706,6 +707,7 @@ expected_types = {
706
707
  "remove_background_pathogen": bool,
707
708
  "pathogen_model": (str, type(None)),
708
709
  "filter": bool,
710
+ "fill_in":bool,
709
711
  "upscale": bool,
710
712
  "upscale_factor": float,
711
713
  "adjust_cells": bool,
@@ -831,7 +833,6 @@ expected_types = {
831
833
  "CP_prob": float,
832
834
  "flow_threshold": float,
833
835
  "percentiles": (list, type(None)),
834
- "circular": bool,
835
836
  "invert": bool,
836
837
  "diameter": int,
837
838
  "grayscale": bool,
@@ -897,7 +898,7 @@ expected_types = {
897
898
 
898
899
  categories = {"Paths":[ "src", "grna", "barcodes", "custom_model_path", "dataset","model_path","grna_csv","row_csv","column_csv"],
899
900
  "General": ["metadata_type", "custom_regex", "experiment", "channels", "magnification", "channel_dims", "apply_model_to_dataset", "generate_training_dataset", "train_DL_model", "segmentation_mode"],
900
- "Cellpose":["from_scratch", "n_epochs", "width_height", "model_name", "custom_model", "resample", "rescale", "CP_prob", "flow_threshold", "percentiles", "circular", "invert", "diameter", "grayscale", "background", "Signal_to_noise", "resize", "target_height", "target_width"],
901
+ "Cellpose":["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"],
901
902
  "Cell": ["cell_intensity_range", "cell_size_range", "cell_chann_dim", "cell_channel", "cell_background", "cell_Signal_to_noise", "cell_CP_prob", "cell_FT", "remove_background_cell", "cell_min_size", "cell_mask_dim", "cytoplasm", "cytoplasm_min_size", "uninfected", "merge_edge_pathogen_cells", "adjust_cells", "cells", "cell_loc"],
902
903
  "Nucleus": ["nucleus_intensity_range", "nucleus_size_range", "nucleus_chann_dim", "nucleus_channel", "nucleus_background", "nucleus_Signal_to_noise", "nucleus_CP_prob", "nucleus_FT", "remove_background_nucleus", "nucleus_min_size", "nucleus_mask_dim", "nucleus_loc"],
903
904
  "Pathogen": ["pathogen_intensity_range", "pathogen_size_range", "pathogen_chann_dim", "pathogen_channel", "pathogen_background", "pathogen_Signal_to_noise", "pathogen_CP_prob", "pathogen_FT", "pathogen_model", "remove_background_pathogen", "pathogen_min_size", "pathogen_mask_dim", "pathogens", "pathogen_loc", "pathogen_types", "pathogen_plate_metadata", ],
@@ -909,12 +910,12 @@ categories = {"Paths":[ "src", "grna", "barcodes", "custom_model_path", "dataset
909
910
  "Hyperparamiters (Embedding)": ["visualize","n_neighbors","min_dist","metric","resnet_features","reduction_method","embedding_by_controls","col_to_compare","log_data"],
910
911
  "Hyperparamiters (Clustering)": ["eps","min_samples","analyze_clusters","clustering","remove_cluster_noise"],
911
912
  "Hyperparamiters (Regression)":["cov_type", "class_1_threshold", "plate", "other", "fraction_threshold", "alpha", "random_row_column_effects", "regression_type", "min_cell_count", "agg_type", "transform", "dependent_variable"],
912
- "Hyperparamiters (Activation)":["cam_type", "normalize", "overlay", "correlation", "target_layer", "normalize_input"],
913
+ "Hyperparamiters (Activation)":["cam_type", "overlay", "correlation", "target_layer", "normalize_input"],
913
914
  "Annotation": ["nc_loc", "pc_loc", "nc", "pc", "cell_plate_metadata","treatment_plate_metadata", "metadata_types", "cell_types", "target","positive_control","negative_control", "location_column", "treatment_loc", "channel_of_interest", "measurement", "treatments", "um_per_pixel", "nr_imgs", "exclude", "exclude_conditions", "mix", "pos", "neg"],
914
915
  "Plot": ["plot", "plot_control", "plot_nr", "examples_to_plot", "normalize_plots", "cmap", "figuresize", "plot_cluster_grids", "img_zoom", "row_limit", "color_by", "plot_images", "smooth_lines", "plot_points", "plot_outlines", "black_background", "plot_by_cluster", "heatmap_feature","grouping","min_max","cmap","save_figure"],
915
916
  "Test": ["test_mode", "test_images", "random_test", "test_nr", "test", "test_split"],
916
917
  "Timelapse": ["timelapse", "fps", "timelapse_displacement", "timelapse_memory", "timelapse_frame_limits", "timelapse_remove_transient", "timelapse_mode", "timelapse_objects", "compartments"],
917
- "Advanced": ["shuffle", "target_intensity_min", "cells_per_well", "nuclei_limit", "pathogen_limit", "uninfected", "backgrounds", "schedule", "test_size","exclude","n_repeats","top_features", "model_type_ml", "model_type","minimum_cell_count","n_estimators","preprocess", "remove_background", "normalize", "lower_percentile", "merge_pathogens", "batch_size", "filter", "save", "masks", "verbose", "randomize", "n_jobs"],
918
+ "Advanced": ["shuffle", "target_intensity_min", "cells_per_well", "nuclei_limit", "pathogen_limit", "uninfected", "background", "backgrounds", "schedule", "test_size","exclude","n_repeats","top_features", "model_type_ml", "model_type","minimum_cell_count","n_estimators","preprocess", "remove_background", "normalize", "lower_percentile", "merge_pathogens", "batch_size", "filter", "save", "masks", "verbose", "randomize", "n_jobs"],
918
919
  "Miscellaneous": ["all_to_mip", "pick_slice", "skip_mode", "upscale", "upscale_factor"]
919
920
  }
920
921
 
@@ -1069,6 +1070,7 @@ def generate_fields(variables, scrollable_frame):
1069
1070
  "figuresize": "(tuple) - Size of the figures to plot.",
1070
1071
  "filter": "(dict) - Filter settings for the analysis.",
1071
1072
  "filter_by": "(str) - Feature to filter the data by.",
1073
+ "fill_in": "(bool) - Whether to fill in the segmented objects.",
1072
1074
  "flow_threshold": "(float) - Flow threshold for segmentation.",
1073
1075
  "fps": "(int) - Frames per second of the automatically generated timelapse movies.",
1074
1076
  "fraction_threshold": "(float) - Threshold for the fraction of cells to consider in the analysis.",
@@ -1252,7 +1254,6 @@ def generate_fields(variables, scrollable_frame):
1252
1254
  "pos": "(str) - Positive control identifier.",
1253
1255
  "neg": "(str) - Negative control identifier.",
1254
1256
  "minimum_cell_count": "(int) - Minimum number of cells/well. if number of cells < minimum_cell_count, the well is excluded from the analysis.",
1255
- "circular": "(bool) - If a circle is to be drawn and corners excluded (e.g. square images of round wells).",
1256
1257
  "highlight": "(str) - highlight genes/grnas containing this string.",
1257
1258
  "pathogen_plate_metadata": "(str) - Metadata for the pathogen plate.",
1258
1259
  "treatment_plate_metadata": "(str) - Metadata for the treatment plate.",
@@ -1313,6 +1314,8 @@ descriptions = {
1313
1314
 
1314
1315
  'activation': "",
1315
1316
 
1317
+ 'analyze_plaques': "Analyze plaque images to quantify plaque properties. Function: analyze_plaques from spacr.analysis.\n\nKey Features:\n- Plaque Analysis: Quantify plaque properties such as size, intensity, and shape.\n- Batch Processing: Analyze multiple plaque images efficiently.\n- Visualization: Generate visualizations to represent plaque data and patterns.",
1318
+
1316
1319
  'recruitment': "Analyze recruitment data to understand sample recruitment dynamics. Function: recruitment_analysis_tools from spacr.analysis.\n\nKey Features:\n- Recruitment Analysis: Investigate and analyze the recruitment of samples over time or conditions.\n- Visualization: Generate visualizations to represent recruitment trends and patterns.\n- Integration: Utilize data from various sources for a comprehensive recruitment analysis."
1317
1320
  }
1318
1321
 
@@ -1366,5 +1369,23 @@ def get_default_generate_activation_map_settings(settings):
1366
1369
  settings.setdefault('correlation', True)
1367
1370
  settings.setdefault('manders_thresholds', [15,50, 75])
1368
1371
  settings.setdefault('n_jobs', None)
1369
-
1372
+ return settings
1373
+
1374
+ def get_analyze_plaque_settings(settings):
1375
+ settings.setdefault('src', 'path')
1376
+ settings.setdefault('masks', True)
1377
+ settings.setdefault('background', 200)
1378
+ settings.setdefault('Signal_to_noise', 10)
1379
+ settings.setdefault('CP_prob', 0)
1380
+ settings.setdefault('diameter', 30)
1381
+ settings.setdefault('batch_size', 50)
1382
+ settings.setdefault('flow_threshold', 0.4)
1383
+ settings.setdefault('save', True)
1384
+ settings.setdefault('verbose', True)
1385
+ settings.setdefault('resize', True)
1386
+ settings.setdefault('target_height', 1120)
1387
+ settings.setdefault('target_width', 1120)
1388
+ settings.setdefault('rescale', False)
1389
+ settings.setdefault('resample', False)
1390
+ settings.setdefault('fill_in', True)
1370
1391
  return settings