spacr 0.3.36__py3-none-any.whl → 0.3.38__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/gui_elements.py CHANGED
@@ -2267,14 +2267,24 @@ class AnnotateApp:
2267
2267
  self.grid_rows = max(1, self.grid_rows)
2268
2268
 
2269
2269
  def prefilter_paths_annotations(self):
2270
- from .io import _read_and_join_tables
2270
+ from .io import _read_and_join_tables, _read_db
2271
2271
  from .utils import is_list_of_lists
2272
2272
 
2273
2273
  if self.measurement and self.threshold is not None:
2274
2274
  df = _read_and_join_tables(self.db_path)
2275
+ png_list_df = _read_db(self.db_path, tables=['png_list'])[0]
2276
+ png_list_df = png_list_df.set_index('prcfo')
2277
+ df = df.merge(png_list_df, left_index=True, right_index=True)
2275
2278
  df[self.annotation_column] = None
2276
2279
  before = len(df)
2277
2280
 
2281
+ if isinstance(self.threshold, int):
2282
+ if isinstance(self.measurement, list):
2283
+ mes = self.measurement[0]
2284
+ if isinstance(self.measurement, str):
2285
+ mes = self.measurement
2286
+ df = df[df[f'{mes}'] == self.threshold]
2287
+
2278
2288
  if is_list_of_lists(self.measurement):
2279
2289
  if isinstance(self.threshold, list) or is_list_of_lists(self.threshold):
2280
2290
  if len(self.measurement) == len(self.threshold):
spacr/ml.py CHANGED
@@ -763,7 +763,7 @@ def generate_ml_scores(settings):
763
763
  raise ValueError("The 'png_list_df' DataFrame must contain 'prcfo' and 'test' columns.")
764
764
  annotated_df = png_list_df[['prcfo', settings['annotation_column']]].set_index('prcfo')
765
765
  df = annotated_df.merge(df, left_index=True, right_index=True)
766
- display(df)
766
+ #display(df)
767
767
  unique_values = df[settings['annotation_column']].dropna().unique()
768
768
  if len(unique_values) == 1:
769
769
  unannotated_rows = df[df[settings['annotation_column']].isna()].index
@@ -846,6 +846,7 @@ def generate_ml_scores(settings):
846
846
  return [output, plate_heatmap]
847
847
 
848
848
  def ml_analysis(df, channel_of_interest=3, location_column='col', positive_control='c2', negative_control='c1', exclude=None, n_repeats=10, top_features=30, n_estimators=100, test_size=0.2, model_type='xgboost', n_jobs=-1, remove_low_variance_features=True, remove_highly_correlated_features=True, verbose=False):
849
+
849
850
  """
850
851
  Calculates permutation importance for numerical features in the dataframe,
851
852
  comparing groups based on specified column values and uses the model to predict
@@ -878,7 +879,6 @@ def ml_analysis(df, channel_of_interest=3, location_column='col', positive_contr
878
879
  if 'cells_per_well' in df.columns:
879
880
  df = df.drop(columns=['cells_per_well'])
880
881
 
881
-
882
882
  df_metadata = df[[location_column]].copy()
883
883
 
884
884
  df, features = filter_dataframe_features(df, channel_of_interest, exclude, remove_low_variance_features, remove_highly_correlated_features, verbose)
spacr/plot.py CHANGED
@@ -2152,10 +2152,12 @@ class spacrGraph:
2152
2152
  def preprocess_data(self):
2153
2153
  """Preprocess the data: remove NaNs, sort/order the grouping column, and optionally group by 'prc'."""
2154
2154
  # Remove NaNs in both the grouping column and each data column
2155
- df = self.df.dropna(subset=[self.grouping_column] + self.data_column) # Handle multiple data columns
2155
+ df = self.df.dropna(subset=[self.grouping_column] + self.data_column)
2156
2156
  # Group by 'prc' column if representation is 'well'
2157
2157
  if self.representation == 'well':
2158
2158
  df = df.groupby(['prc', self.grouping_column])[self.data_column].agg(self.summary_func).reset_index()
2159
+ if self.representation == 'plate':
2160
+ df = df.groupby(['plate', self.grouping_column])[self.data_column].agg(self.summary_func).reset_index()
2159
2161
  if self.order:
2160
2162
  df[self.grouping_column] = pd.Categorical(df[self.grouping_column], categories=self.order, ordered=True)
2161
2163
  else:
@@ -2591,35 +2593,75 @@ class spacrGraph:
2591
2593
  return self.fig
2592
2594
 
2593
2595
  def plot_data_from_db(settings):
2594
- from .io import _read_db
2596
+ from .io import _read_db, _read_and_merge_data
2595
2597
  from .utils import annotate_conditions
2596
2598
  """
2597
2599
  Extracts the specified table from the SQLite database and plots a specified column.
2598
2600
 
2599
2601
  Args:
2600
2602
  db_path (str): The path to the SQLite database.
2601
- table_name (str): The name of the table to extract.
2603
+ table_names (str): The name of the table to extract.
2602
2604
  column_name (str): The column to plot from the table.
2603
2605
 
2604
2606
  Returns:
2605
2607
  df (pd.DataFrame): The extracted table as a DataFrame.
2606
2608
  """
2609
+
2610
+ if isinstance(settings['src'], str):
2611
+ srcs = [settings['src']]
2612
+ elif isinstance(settings['src'], list):
2613
+ srcs = settings['src']
2614
+ if isinstance(settings['database'], str):
2615
+ settings['database'] = [settings['database'] for _ in range(len(srcs))]
2616
+ else:
2617
+ raise ValueError("src must be a string or a list of strings.")
2607
2618
 
2608
- db_loc = os.path.join(settings['src'], 'measurements',settings['database'])
2609
-
2610
- [df] = _read_db(db_loc, tables=[settings['table_name']])
2619
+ dfs = []
2620
+ for i, src in enumerate(srcs):
2621
+
2622
+ db_loc = os.path.join(src, 'measurements', settings['database'][i])
2611
2623
 
2612
- df = annotate_conditions(df,
2613
- cells=settings['cell_types'],
2614
- cell_loc=settings['cell_plate_metadata'],
2615
- pathogens=settings['pathogen_types'],
2616
- pathogen_loc=settings['pathogen_plate_metadata'],
2617
- treatments=settings['treatments'],
2618
- treatment_loc=settings['treatment_plate_metadata'])
2619
-
2624
+ if settings['table_names'] in ['saliency_image_correlations']:
2625
+ [df1] = _read_db(db_loc, tables=[settings['table_names']])
2626
+ else:
2627
+ df1, _ = _read_and_merge_data(locs=[db_loc],
2628
+ tables = ['cell', 'nucleus', 'pathogen','cytoplasm'],
2629
+ verbose=settings['verbose'],
2630
+ nuclei_limit=settings['nuclei_limit'],
2631
+ pathogen_limit=settings['pathogen_limit'],
2632
+ uninfected=settings['uninfected'])
2633
+
2634
+ dft = annotate_conditions(df1,
2635
+ cells=settings['cell_types'],
2636
+ cell_loc=settings['cell_plate_metadata'],
2637
+ pathogens=settings['pathogen_types'],
2638
+ pathogen_loc=settings['pathogen_plate_metadata'],
2639
+ treatments=settings['treatments'],
2640
+ treatment_loc=settings['treatment_plate_metadata'])
2641
+ dfs.append(dft)
2642
+
2643
+ df = pd.concat(dfs, axis=0)
2620
2644
  df['prc'] = df['plate'].astype(str) + '_' + df['row'].astype(str) + '_' + df['col'].astype(str)
2645
+ df['recruitment'] = df['pathogen_channel_1_mean_intensity'] / df['cytoplasm_channel_1_mean_intensity']
2646
+
2647
+ if settings['cell_plate_metadata'] != None:
2648
+ df = df.dropna(subset='host_cell')
2649
+
2650
+ if settings['pathogen_plate_metadata'] != None:
2651
+ df = df.dropna(subset='pathogen')
2652
+
2653
+ if settings['treatment_plate_metadata'] != None:
2654
+ df = df.dropna(subset='treatment')
2655
+
2621
2656
  df = df.dropna(subset=settings['column_name'])
2622
- df['class'] = df['png_path'].apply(lambda x: 'class_1' if 'class_1' in x else ('class_0' if 'class_0' in x else None))
2657
+ df = df.dropna(subset=settings['grouping_column'])
2658
+
2659
+
2660
+
2661
+
2662
+ #display(df)
2663
+
2664
+ #df['class'] = df['png_path'].apply(lambda x: 'class_1' if 'class_1' in x else ('class_0' if 'class_0' in x else None))
2623
2665
 
2624
2666
  spacr_graph = spacrGraph(
2625
2667
  df=df, # Your DataFrame
@@ -2632,7 +2674,7 @@ def plot_data_from_db(settings):
2632
2674
  save=settings['save'], # Whether to save the plot and results
2633
2675
  y_lim=settings['y_lim'], # Starting point for y-axis (optional)
2634
2676
  error_bar_type='std', # Type of error bar ('std' or 'sem')
2635
- representation='well',
2677
+ representation=settings['representation'],
2636
2678
  theme=settings['theme'], # Seaborn color palette theme (e.g., 'pastel', 'muted')
2637
2679
  )
2638
2680
 
spacr/utils.py CHANGED
@@ -5047,6 +5047,7 @@ def add_column_to_database(settings):
5047
5047
  """
5048
5048
  Adds a new column to the database table by matching on a common column from the DataFrame.
5049
5049
  If the column already exists in the database, it adds the column with a suffix.
5050
+ NaN values will remain as NULL in the database.
5050
5051
 
5051
5052
  Parameters:
5052
5053
  - settings: A dictionary containing the following keys:
@@ -5060,6 +5061,11 @@ def add_column_to_database(settings):
5060
5061
  # Read the DataFrame from the provided CSV path
5061
5062
  df = pd.read_csv(settings['csv_path'])
5062
5063
 
5064
+ # Replace 0 values with 2 in the update column
5065
+ if (df[settings['update_column']] == 0).any():
5066
+ print("Replacing all 0 values with 2 in the update column.")
5067
+ df[settings['update_column']].replace(0, 2, inplace=True)
5068
+
5063
5069
  # Connect to the SQLite database
5064
5070
  conn = sqlite3.connect(settings['db_path'])
5065
5071
  cursor = conn.cursor()
@@ -5068,12 +5074,10 @@ def add_column_to_database(settings):
5068
5074
  cursor.execute(f"PRAGMA table_info({settings['table_name']})")
5069
5075
  columns_in_db = [col[1] for col in cursor.fetchall()]
5070
5076
 
5071
- # Check if the update column already exists in the database
5077
+ # Add a suffix if the update column already exists in the database
5072
5078
  if settings['update_column'] in columns_in_db:
5073
- # Add a suffix to the column name (e.g., '_new', '_1', or similar)
5074
5079
  suffix = 1
5075
5080
  new_column_name = f"{settings['update_column']}_{suffix}"
5076
- # Ensure uniqueness by incrementing the suffix if needed
5077
5081
  while new_column_name in columns_in_db:
5078
5082
  suffix += 1
5079
5083
  new_column_name = f"{settings['update_column']}_{suffix}"
@@ -5081,8 +5085,8 @@ def add_column_to_database(settings):
5081
5085
  else:
5082
5086
  new_column_name = settings['update_column']
5083
5087
 
5084
- # Add the new column to the database table
5085
- cursor.execute(f"ALTER TABLE {settings['table_name']} ADD COLUMN {new_column_name} TEXT")
5088
+ # Add the new column with INTEGER type to the database table
5089
+ cursor.execute(f"ALTER TABLE {settings['table_name']} ADD COLUMN {new_column_name} INTEGER")
5086
5090
  print(f"Added new column '{new_column_name}' to the table '{settings['table_name']}'.")
5087
5091
 
5088
5092
  # Iterate over the DataFrame and update the new column in the database
@@ -5090,6 +5094,10 @@ def add_column_to_database(settings):
5090
5094
  value_to_update = row[settings['update_column']]
5091
5095
  match_value = row[settings['match_column']]
5092
5096
 
5097
+ # Handle NaN values by converting them to None (SQLite equivalent of NULL)
5098
+ if pd.isna(value_to_update):
5099
+ value_to_update = None
5100
+
5093
5101
  # Prepare and execute the SQL update query
5094
5102
  query = f"""
5095
5103
  UPDATE {settings['table_name']}
@@ -5102,7 +5110,4 @@ def add_column_to_database(settings):
5102
5110
  conn.commit()
5103
5111
  conn.close()
5104
5112
 
5105
- print(f"Updated '{new_column_name}' in '{settings['table_name']}' using '{settings['match_column']}'.")
5106
-
5107
-
5108
-
5113
+ print(f"Updated '{new_column_name}' in '{settings['table_name']}' using '{settings['match_column']}'.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spacr
3
- Version: 0.3.36
3
+ Version: 0.3.38
4
4
  Summary: Spatial phenotype analysis of crisp screens (SpaCr)
5
5
  Home-page: https://github.com/EinarOlafsson/spacr
6
6
  Author: Einar Birnir Olafsson
@@ -12,22 +12,22 @@ spacr/core.py,sha256=G_x-w7FRIHNfSOoPaIZPSf_A7mVj7PA7o9HQZ4nIu5o,48231
12
12
  spacr/deep_spacr.py,sha256=HdOcNU8cHcE_19nP7_5uTz-ih3E169ffr2Hm--NvMvA,43255
13
13
  spacr/gui.py,sha256=ARyn9Q_g8HoP-cXh1nzMLVFCKqthY4v2u9yORyaQqQE,8230
14
14
  spacr/gui_core.py,sha256=LV_HX5zreu3Bye6sQFDbOuk8Dfj4StMoohy6hsrDEXA,41363
15
- spacr/gui_elements.py,sha256=puDqf7PJJ_UMA01fjqODk-zsfSmvzVXpvaZ1BYV988w,136554
15
+ spacr/gui_elements.py,sha256=w-S1MZdyxt5O3DsNAHNNXy_WGfwBPg0NhwQtCsJeiao,137071
16
16
  spacr/gui_utils.py,sha256=7e9DsZIuV7-jh97kEf7v1In_cFzlFueV4SGcGYGpTxw,45454
17
17
  spacr/io.py,sha256=AARmqn1fMmTgVDwWy8bEYK6SjH-6DZIulgCSPdBTyf0,143370
18
18
  spacr/logger.py,sha256=lJhTqt-_wfAunCPl93xE65Wr9Y1oIHJWaZMjunHUeIw,1538
19
19
  spacr/measure.py,sha256=BThn_sALgKrwGKnLOGpT4FyoJeRVoTZoP9SXbCtCMRw,54857
20
20
  spacr/mediar.py,sha256=FwLvbLQW5LQzPgvJZG8Lw7GniA2vbZx6Jv6vIKu7I5c,14743
21
- spacr/ml.py,sha256=Wy_H_bI5cD_N4xIZCo3_M-73wVvmCC35tJbLspMOWbg,49341
21
+ spacr/ml.py,sha256=ItibDL_q0cKwEsJdwpBtVqfpRQGPXGbb0BX5UB5iH5s,49342
22
22
  spacr/openai.py,sha256=5vBZ3Jl2llYcW3oaTEXgdyCB2aJujMUIO5K038z7w_A,1246
23
- spacr/plot.py,sha256=PtCSoBmLFlGC7ebmsk-vMlyd7q2ahXgRVaTtAq3w_po,116513
23
+ spacr/plot.py,sha256=W6F2Jaxq7WBnB9G3-7AESdQs6foGeyS70-LZwKgKJv8,118214
24
24
  spacr/sequencing.py,sha256=t18mgpK6rhWuB1LtFOsPxqgpFXxuUmrD06ecsaVQ0Gw,19655
25
25
  spacr/settings.py,sha256=AzP9NGiXI1MqT69bHObxwDSCUk0kdstBVvl1JpcD_-w,75960
26
26
  spacr/sim.py,sha256=1xKhXimNU3ukzIw-3l9cF3Znc_brW8h20yv8fSTzvss,71173
27
27
  spacr/submodules.py,sha256=AB7s6-cULsaqz-haAaCtXfGEIi8uPZGT4xoCslUJC3Y,18391
28
28
  spacr/timelapse.py,sha256=FSYpUtAVy6xc3lwprRYgyDTT9ysUhfRQ4zrP9_h2mvg,39465
29
29
  spacr/toxo.py,sha256=us3pQyULtMTyfTq0MWPn4QJTTmQ6BwAJKChNf75jo3I,10082
30
- spacr/utils.py,sha256=iCbweRXWjJgKGbp8DAVC20xUG9nwy2K9cvIsXORAKwA,216043
30
+ spacr/utils.py,sha256=j6qE7aTGu7D82_A68md5b5Vgn8UrW2w2saa6nCbANw8,216373
31
31
  spacr/version.py,sha256=axH5tnGwtgSnJHb5IDhiu4Zjk5GhLyAEDRe-rnaoFOA,409
32
32
  spacr/resources/MEDIAR/.gitignore,sha256=Ff1q9Nme14JUd-4Q3jZ65aeQ5X4uttptssVDgBVHYo8,152
33
33
  spacr/resources/MEDIAR/LICENSE,sha256=yEj_TRDLUfDpHDNM0StALXIt6mLqSgaV2hcCwa6_TcY,1065
@@ -150,9 +150,9 @@ spacr/resources/icons/umap.png,sha256=dOLF3DeLYy9k0nkUybiZMe1wzHQwLJFRmgccppw-8b
150
150
  spacr/resources/images/plate1_E01_T0001F001L01A01Z01C02.tif,sha256=Tl0ZUfZ_AYAbu0up_nO0tPRtF1BxXhWQ3T3pURBCCRo,7958528
151
151
  spacr/resources/images/plate1_E01_T0001F001L01A02Z01C01.tif,sha256=m8N-V71rA1TT4dFlENNg8s0Q0YEXXs8slIn7yObmZJQ,7958528
152
152
  spacr/resources/images/plate1_E01_T0001F001L01A03Z01C03.tif,sha256=Pbhk7xn-KUP6RSIhJsxQcrHFImBm3GEpLkzx7WOc-5M,7958528
153
- spacr-0.3.36.dist-info/LICENSE,sha256=SR-2MeGc6SCM1UORJYyarSWY_A-JaOMFDj7ReSs9tRM,1083
154
- spacr-0.3.36.dist-info/METADATA,sha256=NvcSKD3mIWOPeTDAAbugslvW-1_T0Dzd9k8WzSVNwbY,5949
155
- spacr-0.3.36.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
156
- spacr-0.3.36.dist-info/entry_points.txt,sha256=BMC0ql9aNNpv8lUZ8sgDLQMsqaVnX5L535gEhKUP5ho,296
157
- spacr-0.3.36.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
158
- spacr-0.3.36.dist-info/RECORD,,
153
+ spacr-0.3.38.dist-info/LICENSE,sha256=SR-2MeGc6SCM1UORJYyarSWY_A-JaOMFDj7ReSs9tRM,1083
154
+ spacr-0.3.38.dist-info/METADATA,sha256=IfwGcod8ZUdemPlpbdoCoONBap_IZQCfiL-KURN3KuI,5949
155
+ spacr-0.3.38.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
156
+ spacr-0.3.38.dist-info/entry_points.txt,sha256=BMC0ql9aNNpv8lUZ8sgDLQMsqaVnX5L535gEhKUP5ho,296
157
+ spacr-0.3.38.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
158
+ spacr-0.3.38.dist-info/RECORD,,
File without changes