spacr 0.4.0__py3-none-any.whl → 0.4.2__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/__init__.py +2 -2
- spacr/core.py +14 -3
- spacr/deep_spacr.py +2 -95
- spacr/gui_core.py +301 -46
- spacr/gui_elements.py +131 -0
- spacr/gui_utils.py +24 -20
- spacr/io.py +312 -8
- spacr/measure.py +11 -12
- spacr/plot.py +2 -2
- spacr/settings.py +157 -49
- spacr/sp_stats.py +221 -0
- spacr/submodules.py +2 -2
- spacr/utils.py +115 -33
- {spacr-0.4.0.dist-info → spacr-0.4.2.dist-info}/METADATA +2 -1
- {spacr-0.4.0.dist-info → spacr-0.4.2.dist-info}/RECORD +19 -18
- {spacr-0.4.0.dist-info → spacr-0.4.2.dist-info}/LICENSE +0 -0
- {spacr-0.4.0.dist-info → spacr-0.4.2.dist-info}/WHEEL +0 -0
- {spacr-0.4.0.dist-info → spacr-0.4.2.dist-info}/entry_points.txt +0 -0
- {spacr-0.4.0.dist-info → spacr-0.4.2.dist-info}/top_level.txt +0 -0
spacr/utils.py
CHANGED
@@ -319,7 +319,6 @@ def load_settings(csv_file_path, show=False, setting_key='setting_key', setting_
|
|
319
319
|
|
320
320
|
return result_dict
|
321
321
|
|
322
|
-
|
323
322
|
def save_settings(settings, name='settings', show=False):
|
324
323
|
|
325
324
|
settings_df = pd.DataFrame(list(settings.items()), columns=['Key', 'Value'])
|
@@ -328,14 +327,19 @@ def save_settings(settings, name='settings', show=False):
|
|
328
327
|
|
329
328
|
if isinstance(settings['src'], list):
|
330
329
|
src = settings['src'][0]
|
331
|
-
#if os.path.exists(src):
|
332
|
-
|
333
330
|
name = f"{name}_list"
|
334
331
|
else:
|
335
332
|
src = settings['src']
|
333
|
+
|
334
|
+
if 'test_mode' in settings.keys():
|
335
|
+
settings['test_mode'] = False
|
336
|
+
|
337
|
+
if 'plot' in settings.keys():
|
338
|
+
settings['plot'] = False
|
336
339
|
|
337
340
|
settings_csv = os.path.join(src,'settings',f'{name}.csv')
|
338
341
|
os.makedirs(os.path.join(src,'settings'), exist_ok=True)
|
342
|
+
print(f"Saving settings to {settings_csv}")
|
339
343
|
settings_df.to_csv(settings_csv, index=False)
|
340
344
|
|
341
345
|
def print_progress(files_processed, files_to_process, n_jobs, time_ls=None, batch_size=None, operation_type=""):
|
@@ -1145,7 +1149,7 @@ def _masks_to_masks_stack(masks):
|
|
1145
1149
|
mask_stack.append(mask)
|
1146
1150
|
return mask_stack
|
1147
1151
|
|
1148
|
-
def
|
1152
|
+
def _get_diam_v1(mag, obj):
|
1149
1153
|
|
1150
1154
|
if mag == 20:
|
1151
1155
|
if obj == 'cell':
|
@@ -1176,11 +1180,28 @@ def _get_diam(mag, obj):
|
|
1176
1180
|
diamiter = 60
|
1177
1181
|
else:
|
1178
1182
|
raise ValueError("Invalid magnification: Use 20, 40 or 60")
|
1183
|
+
|
1179
1184
|
else:
|
1180
1185
|
raise ValueError("Invalid magnification: Use 20, 40 or 60")
|
1181
1186
|
|
1182
1187
|
return diamiter
|
1183
1188
|
|
1189
|
+
def _get_diam(mag, obj):
|
1190
|
+
|
1191
|
+
if obj == 'cell':
|
1192
|
+
diamiter = 2 * mag + 80
|
1193
|
+
|
1194
|
+
if obj == 'cell_large':
|
1195
|
+
diamiter = 2 * mag + 120
|
1196
|
+
|
1197
|
+
if obj == 'nucleus':
|
1198
|
+
diamiter = 0.75 * mag + 45
|
1199
|
+
|
1200
|
+
if obj == 'pathogen':
|
1201
|
+
diamiter = mag
|
1202
|
+
|
1203
|
+
return int(diamiter)
|
1204
|
+
|
1184
1205
|
def _get_object_settings(object_type, settings):
|
1185
1206
|
object_settings = {}
|
1186
1207
|
|
@@ -1333,20 +1354,25 @@ def annotate_conditions(df, cells=None, cell_loc=None, pathogens=None, pathogen_
|
|
1333
1354
|
def _map_or_default(column_name, values, loc, df):
|
1334
1355
|
"""
|
1335
1356
|
Consolidates the logic for mapping values or assigning defaults when loc is None.
|
1336
|
-
|
1357
|
+
|
1337
1358
|
Args:
|
1338
1359
|
column_name (str): The column in the DataFrame to annotate.
|
1339
1360
|
values (list/str): The list of values or a single string to annotate.
|
1340
1361
|
loc (list of lists): Location mapping for the values, or None if not used.
|
1341
1362
|
df (pandas.DataFrame): The DataFrame to modify.
|
1342
1363
|
"""
|
1343
|
-
if isinstance(values, str)
|
1344
|
-
#
|
1345
|
-
df[column_name] = values
|
1364
|
+
if isinstance(values, str) and loc is None:
|
1365
|
+
# If a single string is provided and loc is None, assign the value to all rows
|
1366
|
+
df[column_name] = values
|
1367
|
+
|
1368
|
+
elif isinstance(values, list) and loc is None:
|
1369
|
+
# If a list of values is provided but no loc, assign the first value to all rows
|
1370
|
+
df[column_name] = values[0]
|
1371
|
+
|
1346
1372
|
elif values is not None and loc is not None:
|
1347
|
-
# Perform
|
1373
|
+
# Perform location-based mapping
|
1348
1374
|
value_dict = {val: key for key, loc_list in zip(values, loc) for val in loc_list}
|
1349
|
-
df[column_name] = np.nan
|
1375
|
+
df[column_name] = np.nan # Start with NaN
|
1350
1376
|
for val, key in value_dict.items():
|
1351
1377
|
loc_type = _get_type(val)
|
1352
1378
|
if loc_type:
|
@@ -3099,12 +3125,8 @@ def _get_regex(metadata_type, img_format, custom_regex=None):
|
|
3099
3125
|
regex = f'(?P<plateID>.*)_(?P<wellID>.*)_T(?P<timeID>.*)F(?P<fieldID>.*)L(?P<laserID>..)A(?P<AID>..)Z(?P<sliceID>.*)C(?P<chanID>.*){img_format}'
|
3100
3126
|
elif metadata_type == 'cq1':
|
3101
3127
|
regex = f'W(?P<wellID>.*)F(?P<fieldID>.*)T(?P<timeID>.*)Z(?P<sliceID>.*)C(?P<chanID>.*){img_format}'
|
3102
|
-
elif metadata_type == '
|
3103
|
-
regex = f'(?P<plateID>.*)_(?P<wellID>.*)_T(?P<timeID>.*)F(?P<fieldID>.*)L(?P<laserID
|
3104
|
-
elif metadata_type == 'zeis':
|
3105
|
-
regex = f'(?P<plateID>.*)_(?P<wellID>.*)_T(?P<timeID>.*)F(?P<fieldID>.*)L(?P<laserID>..)A(?P<AID>..)Z(?P<sliceID>.*)C(?P<chanID>.*){img_format}'
|
3106
|
-
elif metadata_type == 'leica':
|
3107
|
-
regex = f'(?P<plateID>.*)_(?P<wellID>.*)_T(?P<timeID>.*)F(?P<fieldID>.*)L(?P<laserID>..)A(?P<AID>..)Z(?P<sliceID>.*)C(?P<chanID>.*){img_format}'
|
3128
|
+
elif metadata_type == 'auto':
|
3129
|
+
regex = f'(?P<plateID>.*)_(?P<wellID>.*)_T(?P<timeID>.*)F(?P<fieldID>.*)L(?P<laserID>.*)C(?P<chanID>.*).tif'
|
3108
3130
|
elif metadata_type == 'custom':
|
3109
3131
|
regex = f'({custom_regex}){img_format}'
|
3110
3132
|
|
@@ -4945,7 +4967,7 @@ def download_models(repo_id="einarolafsson/models", retries=5, delay=5):
|
|
4945
4967
|
if not os.path.exists(local_dir):
|
4946
4968
|
os.makedirs(local_dir)
|
4947
4969
|
elif len(os.listdir(local_dir)) > 0:
|
4948
|
-
print(f"Models already downloaded to: {local_dir}")
|
4970
|
+
#print(f"Models already downloaded to: {local_dir}")
|
4949
4971
|
return local_dir
|
4950
4972
|
|
4951
4973
|
attempt = 0
|
@@ -5011,22 +5033,22 @@ def generate_cytoplasm_mask(nucleus_mask, cell_mask):
|
|
5011
5033
|
return cytoplasm_mask
|
5012
5034
|
|
5013
5035
|
def add_column_to_database(settings):
|
5014
|
-
|
5015
|
-
|
5016
|
-
|
5017
|
-
|
5018
|
-
|
5019
|
-
|
5020
|
-
|
5021
|
-
|
5022
|
-
|
5023
|
-
|
5024
|
-
|
5025
|
-
|
5026
|
-
|
5027
|
-
|
5028
|
-
|
5029
|
-
|
5036
|
+
"""
|
5037
|
+
Adds a new column to the database table by matching on a common column from the DataFrame.
|
5038
|
+
If the column already exists in the database, it adds the column with a suffix.
|
5039
|
+
NaN values will remain as NULL in the database.
|
5040
|
+
|
5041
|
+
Parameters:
|
5042
|
+
settings (dict): A dictionary containing the following keys:
|
5043
|
+
csv_path (str): Path to the CSV file with the data to be added.
|
5044
|
+
db_path (str): Path to the SQLite database (or connection string for other databases).
|
5045
|
+
table_name (str): The name of the table in the database.
|
5046
|
+
update_column (str): The name of the new column in the DataFrame to add to the database.
|
5047
|
+
match_column (str): The common column used to match rows.
|
5048
|
+
|
5049
|
+
Returns:
|
5050
|
+
None
|
5051
|
+
"""
|
5030
5052
|
|
5031
5053
|
# Read the DataFrame from the provided CSV path
|
5032
5054
|
df = pd.read_csv(settings['csv_path'])
|
@@ -5337,3 +5359,63 @@ def calculate_shortest_distance(df, object1, object2):
|
|
5337
5359
|
df[f'{object1}_{object2}_shortest_distance'] = np.maximum(shortest_distance, 0)
|
5338
5360
|
|
5339
5361
|
return df
|
5362
|
+
|
5363
|
+
def format_path_for_system(path):
|
5364
|
+
"""
|
5365
|
+
Takes a file path and reformats it to be compatible with the current operating system.
|
5366
|
+
|
5367
|
+
Args:
|
5368
|
+
path (str): The file path to be formatted.
|
5369
|
+
|
5370
|
+
Returns:
|
5371
|
+
str: The formatted path for the current operating system.
|
5372
|
+
"""
|
5373
|
+
system = platform.system()
|
5374
|
+
|
5375
|
+
# Convert Windows-style paths to Unix-style (Linux/macOS)
|
5376
|
+
if system in ["Linux", "Darwin"]: # Darwin is macOS
|
5377
|
+
formatted_path = path.replace("\\", "/")
|
5378
|
+
|
5379
|
+
# Convert Unix-style paths to Windows-style
|
5380
|
+
elif system == "Windows":
|
5381
|
+
formatted_path = path.replace("/", "\\")
|
5382
|
+
|
5383
|
+
else:
|
5384
|
+
raise ValueError(f"Unsupported OS: {system}")
|
5385
|
+
|
5386
|
+
# Normalize path to ensure consistency
|
5387
|
+
new_path = os.path.normpath(formatted_path)
|
5388
|
+
if os.path.exists(new_path):
|
5389
|
+
print(f"Found path: {new_path}")
|
5390
|
+
else:
|
5391
|
+
print(f"Path not found: {new_path}")
|
5392
|
+
|
5393
|
+
return new_path
|
5394
|
+
|
5395
|
+
|
5396
|
+
def normalize_src_path(src):
|
5397
|
+
"""
|
5398
|
+
Ensures that the 'src' value is properly formatted as either a list of strings or a single string.
|
5399
|
+
|
5400
|
+
Args:
|
5401
|
+
src (str or list): The input source path(s).
|
5402
|
+
|
5403
|
+
Returns:
|
5404
|
+
list or str: A correctly formatted list if the input was a list (or string representation of a list),
|
5405
|
+
otherwise a single string.
|
5406
|
+
"""
|
5407
|
+
if isinstance(src, list):
|
5408
|
+
return src # Already a list, return as-is
|
5409
|
+
|
5410
|
+
if isinstance(src, str):
|
5411
|
+
try:
|
5412
|
+
# Check if it is a string representation of a list
|
5413
|
+
evaluated_src = ast.literal_eval(src)
|
5414
|
+
if isinstance(evaluated_src, list) and all(isinstance(item, str) for item in evaluated_src):
|
5415
|
+
return evaluated_src # Convert to real list
|
5416
|
+
except (SyntaxError, ValueError):
|
5417
|
+
pass # Not a valid list, treat as a string
|
5418
|
+
|
5419
|
+
return src # Return as a string if not a list
|
5420
|
+
|
5421
|
+
raise ValueError(f"Invalid type for 'src': {type(src).__name__}, expected str or list")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: spacr
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.2
|
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
|
@@ -41,6 +41,7 @@ Requires-Dist: pillow<11.0,>=10.2.0
|
|
41
41
|
Requires-Dist: tifffile>=2023.4.12
|
42
42
|
Requires-Dist: nd2reader<4.0,>=3.3.0
|
43
43
|
Requires-Dist: czifile
|
44
|
+
Requires-Dist: readlif
|
44
45
|
Requires-Dist: imageio<3.0,>=2.34.0
|
45
46
|
Requires-Dist: pingouin<1.0,>=0.5.5
|
46
47
|
Requires-Dist: umap-learn<1.0,>=0.5.6
|
@@ -1,4 +1,4 @@
|
|
1
|
-
spacr/__init__.py,sha256=
|
1
|
+
spacr/__init__.py,sha256=iPlE-WRc1CjSNGPMbVvEKlJsTQlKjq29VjzvNUCpcOM,1401
|
2
2
|
spacr/__main__.py,sha256=bkAJJD2kjIqOP-u1kLvct9jQQCeUXzlEjdgitwi1Lm8,75
|
3
3
|
spacr/app_annotate.py,sha256=W9eLPa_LZIvXsXx_-0iDFEU938LBDvRy6prXo0qF4KQ,2533
|
4
4
|
spacr/app_classify.py,sha256=urTP_wlZ58hSyM5a19slYlBxN0PdC-9-ga0hvq8CGWc,165
|
@@ -9,27 +9,28 @@ spacr/app_sequencing.py,sha256=DjG26jy4cpddnV8WOOAIiExtOe9MleVMY4MFa5uTo5w,157
|
|
9
9
|
spacr/app_umap.py,sha256=ZWAmf_OsIKbYvolYuWPMYhdlVe-n2CADoJulAizMiEo,153
|
10
10
|
spacr/cellpose.py,sha256=RBHMs2vwXcfkj0xqAULpALyzJYXddSRycgZSzmwI7v0,14755
|
11
11
|
spacr/chat_bot.py,sha256=n3Fhqg3qofVXHmh3H9sUcmfYy9MmgRnr48663MVdY9E,1244
|
12
|
-
spacr/core.py,sha256=
|
13
|
-
spacr/deep_spacr.py,sha256=
|
12
|
+
spacr/core.py,sha256=KymF-YPvODMkp4J3xva7NwAKBLAUK_Z5x8_pjl9oaP4,49448
|
13
|
+
spacr/deep_spacr.py,sha256=WN64EaQqF87JZg3Uan46t5Y28xsAGD2KMjr2ht6CyDs,54563
|
14
14
|
spacr/gui.py,sha256=ARyn9Q_g8HoP-cXh1nzMLVFCKqthY4v2u9yORyaQqQE,8230
|
15
|
-
spacr/gui_core.py,sha256=
|
16
|
-
spacr/gui_elements.py,sha256=
|
17
|
-
spacr/gui_utils.py,sha256=
|
18
|
-
spacr/io.py,sha256=
|
15
|
+
spacr/gui_core.py,sha256=BZpIdNztQn9U2BZxRsmYhr2uhVAm7ZW8-nZxu38QUvs,59027
|
16
|
+
spacr/gui_elements.py,sha256=Or38I_X9-lJRsyIAtbEfZPXzls0IORagf7vEe6IlI5Y,152647
|
17
|
+
spacr/gui_utils.py,sha256=dWVPFwDj793Z3ERG4mMC0hI0MKkOrvXJpUYlcjpCBsU,41357
|
18
|
+
spacr/io.py,sha256=bOfKwTqo5Z4YtS2E9PB5JVOvn1NkUJKeYxg8nDdGdGE,151762
|
19
19
|
spacr/logger.py,sha256=lJhTqt-_wfAunCPl93xE65Wr9Y1oIHJWaZMjunHUeIw,1538
|
20
|
-
spacr/measure.py,sha256=
|
20
|
+
spacr/measure.py,sha256=Z3u4BU5RzcY82IZuboQ0OsxuXaPVwOlH65Rw6FrL5z4,55045
|
21
21
|
spacr/mediar.py,sha256=FwLvbLQW5LQzPgvJZG8Lw7GniA2vbZx6Jv6vIKu7I5c,14743
|
22
22
|
spacr/ml.py,sha256=MrIAtUUxMOibWVL1SjCUnYlizawCp3l3SeY4Y9yEsPw,97251
|
23
23
|
spacr/openai.py,sha256=5vBZ3Jl2llYcW3oaTEXgdyCB2aJujMUIO5K038z7w_A,1246
|
24
|
-
spacr/plot.py,sha256=
|
24
|
+
spacr/plot.py,sha256=Q5TbsR2NUWhA7z4HyF_2_FAEBFSNMU-G3UNDbRzW6mM,169485
|
25
25
|
spacr/sequencing.py,sha256=ClUfwPPK6rNUbUuiEkzcwakzVyDKKUMv9ricrxT8qQY,25227
|
26
|
-
spacr/settings.py,sha256=
|
26
|
+
spacr/settings.py,sha256=72bhOwr0U83uoWwaKtSNZucYhpgwTP1_GItRk9f6A6c,87592
|
27
27
|
spacr/sim.py,sha256=1xKhXimNU3ukzIw-3l9cF3Znc_brW8h20yv8fSTzvss,71173
|
28
|
+
spacr/sp_stats.py,sha256=mbhwsyIqt5upsSD346qGjdCw7CFBa0tIS7zHU9e0jNI,9536
|
28
29
|
spacr/stats.py,sha256=mbhwsyIqt5upsSD346qGjdCw7CFBa0tIS7zHU9e0jNI,9536
|
29
|
-
spacr/submodules.py,sha256=
|
30
|
+
spacr/submodules.py,sha256=jFlJeVNuIEf63TtCOpTlOZ4iiSLr238kRBiGAAAgKE4,67626
|
30
31
|
spacr/timelapse.py,sha256=KGfG4L4-QnFfgbF7L6C5wL_3gd_rqr05Foje6RsoTBg,39603
|
31
32
|
spacr/toxo.py,sha256=TmuhejSIPLBvsgeblsUgSvBFCR1gOkApyTKidooJ5Us,26044
|
32
|
-
spacr/utils.py,sha256=
|
33
|
+
spacr/utils.py,sha256=v13vzgEQwUnQAtQya_akKIkem26-0Nn5j9uhx_NcJXQ,228599
|
33
34
|
spacr/version.py,sha256=axH5tnGwtgSnJHb5IDhiu4Zjk5GhLyAEDRe-rnaoFOA,409
|
34
35
|
spacr/resources/MEDIAR/.gitignore,sha256=Ff1q9Nme14JUd-4Q3jZ65aeQ5X4uttptssVDgBVHYo8,152
|
35
36
|
spacr/resources/MEDIAR/LICENSE,sha256=yEj_TRDLUfDpHDNM0StALXIt6mLqSgaV2hcCwa6_TcY,1065
|
@@ -152,9 +153,9 @@ spacr/resources/icons/umap.png,sha256=dOLF3DeLYy9k0nkUybiZMe1wzHQwLJFRmgccppw-8b
|
|
152
153
|
spacr/resources/images/plate1_E01_T0001F001L01A01Z01C02.tif,sha256=Tl0ZUfZ_AYAbu0up_nO0tPRtF1BxXhWQ3T3pURBCCRo,7958528
|
153
154
|
spacr/resources/images/plate1_E01_T0001F001L01A02Z01C01.tif,sha256=m8N-V71rA1TT4dFlENNg8s0Q0YEXXs8slIn7yObmZJQ,7958528
|
154
155
|
spacr/resources/images/plate1_E01_T0001F001L01A03Z01C03.tif,sha256=Pbhk7xn-KUP6RSIhJsxQcrHFImBm3GEpLkzx7WOc-5M,7958528
|
155
|
-
spacr-0.4.
|
156
|
-
spacr-0.4.
|
157
|
-
spacr-0.4.
|
158
|
-
spacr-0.4.
|
159
|
-
spacr-0.4.
|
160
|
-
spacr-0.4.
|
156
|
+
spacr-0.4.2.dist-info/LICENSE,sha256=SR-2MeGc6SCM1UORJYyarSWY_A-JaOMFDj7ReSs9tRM,1083
|
157
|
+
spacr-0.4.2.dist-info/METADATA,sha256=1yh08ENDvMjQGyCKwh6BX5j78vwd9JyE8JlBzpkYg7o,6095
|
158
|
+
spacr-0.4.2.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
159
|
+
spacr-0.4.2.dist-info/entry_points.txt,sha256=BMC0ql9aNNpv8lUZ8sgDLQMsqaVnX5L535gEhKUP5ho,296
|
160
|
+
spacr-0.4.2.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
|
161
|
+
spacr-0.4.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|