spacr 0.2.45__py3-none-any.whl → 0.2.53__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/core.py +27 -21
- spacr/gui.py +0 -2
- spacr/gui_core.py +113 -127
- spacr/gui_elements.py +367 -152
- spacr/gui_utils.py +71 -66
- spacr/io.py +24 -19
- spacr/measure.py +196 -145
- spacr/plot.py +2 -42
- spacr/resources/font/open_sans/OFL.txt +93 -0
- spacr/resources/font/open_sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- spacr/resources/font/open_sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
- spacr/resources/font/open_sans/README.txt +100 -0
- spacr/resources/font/open_sans/static/OpenSans-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans-SemiBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Bold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Italic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Light.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Medium.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-Regular.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
- spacr/resources/font/open_sans/static/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
- spacr/sequencing.py +107 -13
- spacr/settings.py +27 -84
- spacr/utils.py +9 -9
- {spacr-0.2.45.dist-info → spacr-0.2.53.dist-info}/METADATA +6 -4
- spacr-0.2.53.dist-info/RECORD +100 -0
- spacr-0.2.45.dist-info/RECORD +0 -60
- {spacr-0.2.45.dist-info → spacr-0.2.53.dist-info}/LICENSE +0 -0
- {spacr-0.2.45.dist-info → spacr-0.2.53.dist-info}/WHEEL +0 -0
- {spacr-0.2.45.dist-info → spacr-0.2.53.dist-info}/entry_points.txt +0 -0
- {spacr-0.2.45.dist-info → spacr-0.2.53.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
Open Sans Variable Font
|
2
|
+
=======================
|
3
|
+
|
4
|
+
This download contains Open Sans as both variable fonts and static fonts.
|
5
|
+
|
6
|
+
Open Sans is a variable font with these axes:
|
7
|
+
wdth
|
8
|
+
wght
|
9
|
+
|
10
|
+
This means all the styles are contained in these files:
|
11
|
+
OpenSans-VariableFont_wdth,wght.ttf
|
12
|
+
OpenSans-Italic-VariableFont_wdth,wght.ttf
|
13
|
+
|
14
|
+
If your app fully supports variable fonts, you can now pick intermediate styles
|
15
|
+
that aren’t available as static fonts. Not all apps support variable fonts, and
|
16
|
+
in those cases you can use the static font files for Open Sans:
|
17
|
+
static/OpenSans_Condensed-Light.ttf
|
18
|
+
static/OpenSans_Condensed-Regular.ttf
|
19
|
+
static/OpenSans_Condensed-Medium.ttf
|
20
|
+
static/OpenSans_Condensed-SemiBold.ttf
|
21
|
+
static/OpenSans_Condensed-Bold.ttf
|
22
|
+
static/OpenSans_Condensed-ExtraBold.ttf
|
23
|
+
static/OpenSans_SemiCondensed-Light.ttf
|
24
|
+
static/OpenSans_SemiCondensed-Regular.ttf
|
25
|
+
static/OpenSans_SemiCondensed-Medium.ttf
|
26
|
+
static/OpenSans_SemiCondensed-SemiBold.ttf
|
27
|
+
static/OpenSans_SemiCondensed-Bold.ttf
|
28
|
+
static/OpenSans_SemiCondensed-ExtraBold.ttf
|
29
|
+
static/OpenSans-Light.ttf
|
30
|
+
static/OpenSans-Regular.ttf
|
31
|
+
static/OpenSans-Medium.ttf
|
32
|
+
static/OpenSans-SemiBold.ttf
|
33
|
+
static/OpenSans-Bold.ttf
|
34
|
+
static/OpenSans-ExtraBold.ttf
|
35
|
+
static/OpenSans_Condensed-LightItalic.ttf
|
36
|
+
static/OpenSans_Condensed-Italic.ttf
|
37
|
+
static/OpenSans_Condensed-MediumItalic.ttf
|
38
|
+
static/OpenSans_Condensed-SemiBoldItalic.ttf
|
39
|
+
static/OpenSans_Condensed-BoldItalic.ttf
|
40
|
+
static/OpenSans_Condensed-ExtraBoldItalic.ttf
|
41
|
+
static/OpenSans_SemiCondensed-LightItalic.ttf
|
42
|
+
static/OpenSans_SemiCondensed-Italic.ttf
|
43
|
+
static/OpenSans_SemiCondensed-MediumItalic.ttf
|
44
|
+
static/OpenSans_SemiCondensed-SemiBoldItalic.ttf
|
45
|
+
static/OpenSans_SemiCondensed-BoldItalic.ttf
|
46
|
+
static/OpenSans_SemiCondensed-ExtraBoldItalic.ttf
|
47
|
+
static/OpenSans-LightItalic.ttf
|
48
|
+
static/OpenSans-Italic.ttf
|
49
|
+
static/OpenSans-MediumItalic.ttf
|
50
|
+
static/OpenSans-SemiBoldItalic.ttf
|
51
|
+
static/OpenSans-BoldItalic.ttf
|
52
|
+
static/OpenSans-ExtraBoldItalic.ttf
|
53
|
+
|
54
|
+
Get started
|
55
|
+
-----------
|
56
|
+
|
57
|
+
1. Install the font files you want to use
|
58
|
+
|
59
|
+
2. Use your app's font picker to view the font family and all the
|
60
|
+
available styles
|
61
|
+
|
62
|
+
Learn more about variable fonts
|
63
|
+
-------------------------------
|
64
|
+
|
65
|
+
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
|
66
|
+
https://variablefonts.typenetwork.com
|
67
|
+
https://medium.com/variable-fonts
|
68
|
+
|
69
|
+
In desktop apps
|
70
|
+
|
71
|
+
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
|
72
|
+
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
|
73
|
+
|
74
|
+
Online
|
75
|
+
|
76
|
+
https://developers.google.com/fonts/docs/getting_started
|
77
|
+
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
|
78
|
+
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
|
79
|
+
|
80
|
+
Installing fonts
|
81
|
+
|
82
|
+
MacOS: https://support.apple.com/en-us/HT201749
|
83
|
+
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
|
84
|
+
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
|
85
|
+
|
86
|
+
Android Apps
|
87
|
+
|
88
|
+
https://developers.google.com/fonts/docs/android
|
89
|
+
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
|
90
|
+
|
91
|
+
License
|
92
|
+
-------
|
93
|
+
Please read the full license text (OFL.txt) to understand the permissions,
|
94
|
+
restrictions and requirements for usage, redistribution, and modification.
|
95
|
+
|
96
|
+
You can use them in your products & projects – print or digital,
|
97
|
+
commercial or otherwise.
|
98
|
+
|
99
|
+
This isn't legal advice, please consider consulting a lawyer and see the full
|
100
|
+
license for all details.
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
spacr/sequencing.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import os, gc, gzip, re, time, math, subprocess
|
1
|
+
import os, gc, gzip, re, time, math, subprocess, traceback
|
2
2
|
import pandas as pd
|
3
3
|
import numpy as np
|
4
4
|
from tqdm import tqdm
|
@@ -21,6 +21,96 @@ from sklearn.preprocessing import FunctionTransformer, MinMaxScaler
|
|
21
21
|
from scipy.stats import shapiro
|
22
22
|
from patsy import dmatrices
|
23
23
|
|
24
|
+
import os
|
25
|
+
import gzip
|
26
|
+
from Bio import SeqIO
|
27
|
+
from Bio.Seq import Seq
|
28
|
+
from Bio.SeqRecord import SeqRecord
|
29
|
+
|
30
|
+
def consensus_sequence(fastq_r1, fastq_r2, output_file, chunk_size=1000000):
|
31
|
+
|
32
|
+
total_reads = 0
|
33
|
+
chunk_count = 0
|
34
|
+
|
35
|
+
with gzip.open(fastq_r1, "rt") as r1_handle, gzip.open(fastq_r2, "rt") as r2_handle, gzip.open(output_file, "wt") as output_handle:
|
36
|
+
r1_iter = SeqIO.parse(r1_handle, "fastq")
|
37
|
+
r2_iter = SeqIO.parse(r2_handle, "fastq")
|
38
|
+
|
39
|
+
while True:
|
40
|
+
r1_chunk = [rec for rec in (next(r1_iter, None) for _ in range(chunk_size)) if rec is not None]
|
41
|
+
r2_chunk = [rec for rec in (next(r2_iter, None) for _ in range(chunk_size)) if rec is not None]
|
42
|
+
|
43
|
+
# If either chunk is empty, we have reached the end of one or both files
|
44
|
+
if not r1_chunk or not r2_chunk:
|
45
|
+
break
|
46
|
+
|
47
|
+
chunk_count += 1
|
48
|
+
total_reads += len(r1_chunk)
|
49
|
+
|
50
|
+
for r1_record, r2_record in zip(r1_chunk, r2_chunk):
|
51
|
+
best_sequence = []
|
52
|
+
best_quality = []
|
53
|
+
for base1, base2, qual1, qual2 in zip(r1_record.seq, r2_record.seq, r1_record.letter_annotations["phred_quality"], r2_record.letter_annotations["phred_quality"]):
|
54
|
+
if qual1 >= qual2:
|
55
|
+
best_sequence.append(base1)
|
56
|
+
best_quality.append(qual1)
|
57
|
+
else:
|
58
|
+
best_sequence.append(base2)
|
59
|
+
best_quality.append(qual2)
|
60
|
+
|
61
|
+
consensus_seq = Seq("".join(best_sequence))
|
62
|
+
|
63
|
+
# Create a new SeqRecord for the consensus sequence
|
64
|
+
consensus_record = SeqRecord(consensus_seq, id=r1_record.id, description="", letter_annotations={"phred_quality": best_quality})
|
65
|
+
|
66
|
+
# Write the consensus sequence to the output file
|
67
|
+
SeqIO.write(consensus_record, output_handle, "fastq")
|
68
|
+
|
69
|
+
print(f"Progress: Chunk {chunk_count} with {total_reads} reads.")
|
70
|
+
|
71
|
+
def parse_gz_files(folder_path):
|
72
|
+
"""
|
73
|
+
Parses the .fastq.gz files in the specified folder path and returns a dictionary
|
74
|
+
containing the sample names and their corresponding file paths.
|
75
|
+
|
76
|
+
Args:
|
77
|
+
folder_path (str): The path to the folder containing the .fastq.gz files.
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
dict: A dictionary where the keys are the sample names and the values are
|
81
|
+
dictionaries containing the file paths for the 'R1' and 'R2' read directions.
|
82
|
+
"""
|
83
|
+
files = os.listdir(folder_path)
|
84
|
+
gz_files = [f for f in files if f.endswith('.fastq.gz')]
|
85
|
+
|
86
|
+
samples_dict = {}
|
87
|
+
for gz_file in gz_files:
|
88
|
+
parts = gz_file.split('_')
|
89
|
+
sample_name = parts[0]
|
90
|
+
read_direction = parts[1]
|
91
|
+
|
92
|
+
if sample_name not in samples_dict:
|
93
|
+
samples_dict[sample_name] = {}
|
94
|
+
|
95
|
+
if read_direction == "R1":
|
96
|
+
samples_dict[sample_name]['R1'] = os.path.join(folder_path, gz_file)
|
97
|
+
elif read_direction == "R2":
|
98
|
+
samples_dict[sample_name]['R2'] = os.path.join(folder_path, gz_file)
|
99
|
+
|
100
|
+
return samples_dict
|
101
|
+
|
102
|
+
def generate_consensus_sequence(src, chunk_size):
|
103
|
+
samples_dict = parse_gz_files(src)
|
104
|
+
for key in samples_dict:
|
105
|
+
if samples_dict[key]['R1'] and samples_dict[key]['R2']:
|
106
|
+
R1 = samples_dict[key]['R1']
|
107
|
+
R2 = samples_dict[key]['R2']
|
108
|
+
consensus_dir = os.path.join(os.path.dirname(R1), 'consensus')
|
109
|
+
os.makedirs(consensus_dir, exist_ok=True) # Use os.makedirs() instead of os.mkdir()
|
110
|
+
consensus = os.path.join(consensus_dir, f"{key}_consensus.fastq.gz")
|
111
|
+
consensus_sequence(R1, R2, consensus, chunk_size)
|
112
|
+
|
113
|
+
|
24
114
|
def analyze_reads(settings):
|
25
115
|
"""
|
26
116
|
Analyzes reads from gzipped fastq files and combines them based on specified settings.
|
@@ -291,12 +381,15 @@ def analyze_reads(settings):
|
|
291
381
|
qc_df.to_csv(qc_file_path, index=False)
|
292
382
|
|
293
383
|
from .settings import get_analyze_reads_default_settings
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
384
|
+
try:
|
385
|
+
settings = get_analyze_reads_default_settings(settings)
|
386
|
+
samples_dict = parse_gz_files(settings['src'])
|
387
|
+
combine_reads(samples_dict, settings['src'], settings['chunk_size'], settings['barecode_length_1'], settings['barecode_length_2'], settings['upstream'], settings['downstream'])
|
388
|
+
except Exception as e:
|
389
|
+
print(e)
|
390
|
+
Error = traceback.format_exc()
|
391
|
+
print(Error)
|
392
|
+
|
300
393
|
def map_barcodes(h5_file_path, settings={}):
|
301
394
|
"""
|
302
395
|
Maps barcodes and performs quality control on sequencing data.
|
@@ -461,9 +554,7 @@ def map_barcodes(h5_file_path, settings={}):
|
|
461
554
|
return filtered_df
|
462
555
|
|
463
556
|
from .settings import get_map_barcodes_default_settings
|
464
|
-
|
465
557
|
settings = get_map_barcodes_default_settings(settings)
|
466
|
-
|
467
558
|
fldr = os.path.splitext(h5_file_path)[0]
|
468
559
|
file_name = os.path.basename(fldr)
|
469
560
|
|
@@ -729,7 +820,12 @@ def grna_plate_heatmap(path, specific_grna=None, min_max='all', cmap='viridis',
|
|
729
820
|
|
730
821
|
return fig
|
731
822
|
|
732
|
-
def map_barcodes_folder(
|
823
|
+
def map_barcodes_folder(settings={}):
|
824
|
+
from .settings import get_map_barcodes_default_settings
|
825
|
+
settings = get_map_barcodes_default_settings(settings)
|
826
|
+
|
827
|
+
print(settings)
|
828
|
+
src = settings['src']
|
733
829
|
for file in os.listdir(src):
|
734
830
|
if file.endswith('.h5'):
|
735
831
|
print(file)
|
@@ -1846,6 +1942,4 @@ def perform_regression(df, settings):
|
|
1846
1942
|
|
1847
1943
|
print('Significant Genes')
|
1848
1944
|
display(significant)
|
1849
|
-
return coef_df
|
1850
|
-
|
1851
|
-
|
1945
|
+
return coef_df
|
spacr/settings.py
CHANGED
@@ -220,6 +220,7 @@ def get_measure_crop_settings(settings):
|
|
220
220
|
|
221
221
|
settings.setdefault('src', 'path')
|
222
222
|
settings.setdefault('verbose', False)
|
223
|
+
settings.setdefault('experiment', 'exp')
|
223
224
|
|
224
225
|
# Test mode
|
225
226
|
settings.setdefault('test_mode', False)
|
@@ -252,8 +253,6 @@ def get_measure_crop_settings(settings):
|
|
252
253
|
|
253
254
|
# Operational settings
|
254
255
|
settings.setdefault('plot',False)
|
255
|
-
settings.setdefault('plot_filtration',False)
|
256
|
-
settings.setdefault('representative_images', False)
|
257
256
|
settings.setdefault('n_jobs', os.cpu_count()-2)
|
258
257
|
|
259
258
|
# Object settings
|
@@ -268,24 +267,9 @@ def get_measure_crop_settings(settings):
|
|
268
267
|
settings.setdefault('cytoplasm_min_size',0)
|
269
268
|
settings.setdefault('merge_edge_pathogen_cells', True)
|
270
269
|
|
271
|
-
# Miscellaneous settings
|
272
|
-
settings.setdefault('experiment', 'exp')
|
273
|
-
settings.setdefault('cells', ['HeLa'])
|
274
|
-
settings.setdefault('cell_loc', None)
|
275
|
-
settings.setdefault('pathogens', ['ME49Dku80WT', 'ME49Dku80dgra8:GRA8', 'ME49Dku80dgra8', 'ME49Dku80TKO'])
|
276
|
-
settings.setdefault('pathogen_loc', [['c1', 'c2', 'c3', 'c4', 'c5', 'c6'], ['c7', 'c8', 'c9', 'c10', 'c11', 'c12'], ['c13', 'c14', 'c15', 'c16', 'c17', 'c18'], ['c19', 'c20', 'c21', 'c22', 'c23', 'c24']])
|
277
|
-
settings.setdefault('treatments', ['BR1', 'BR2', 'BR3'])
|
278
|
-
settings.setdefault('treatment_loc', [['c1', 'c2', 'c7', 'c8', 'c13', 'c14', 'c19', 'c20'], ['c3', 'c4', 'c9', 'c10', 'c15', 'c16', 'c21', 'c22'], ['c5', 'c6', 'c11', 'c12', 'c17', 'c18', 'c23', 'c24']])
|
279
|
-
settings.setdefault('channel_of_interest', 2)
|
280
|
-
settings.setdefault('compartments', ['pathogen', 'cytoplasm'])
|
281
|
-
settings.setdefault('measurement', 'mean_intensity')
|
282
|
-
settings.setdefault('nr_imgs', 32)
|
283
|
-
settings.setdefault('um_per_pixel', 0.1)
|
284
|
-
|
285
270
|
if settings['test_mode']:
|
286
271
|
settings['verbose'] = True
|
287
272
|
settings['plot'] = True
|
288
|
-
settings['plot_filtration'] = True
|
289
273
|
test_imgs = settings['test_nr']
|
290
274
|
print(f'Test mode enabled with {test_imgs} images, plotting set to True')
|
291
275
|
|
@@ -384,6 +368,7 @@ def get_analyze_recruitment_default_settings(settings):
|
|
384
368
|
return settings
|
385
369
|
|
386
370
|
def get_analyze_reads_default_settings(settings):
|
371
|
+
settings.setdefault('src', 'path')
|
387
372
|
settings.setdefault('upstream', 'CTTCTGGTAAATGGGGATGTCAAGTT')
|
388
373
|
settings.setdefault('downstream', 'GTTTAAGAGCTATGCTGGAAACAGCAG') #This is the reverce compliment of the column primer starting from the end #TGCTGTTTAAGAGCTATGCTGGAAACAGCA
|
389
374
|
settings.setdefault('barecode_length_1', 8)
|
@@ -396,7 +381,7 @@ def get_map_barcodes_default_settings(settings):
|
|
396
381
|
settings.setdefault('src', 'path')
|
397
382
|
settings.setdefault('grna', '/home/carruthers/Documents/grna_barcodes.csv')
|
398
383
|
settings.setdefault('barcodes', '/home/carruthers/Documents/SCREEN_BARCODES.csv')
|
399
|
-
settings.setdefault('plate_dict', {'EO1': 'plate1', 'EO2': 'plate2', 'EO3': 'plate3', 'EO4': 'plate4', 'EO5': 'plate5', 'EO6': 'plate6', 'EO7': 'plate7', 'EO8': 'plate8'})
|
384
|
+
settings.setdefault('plate_dict', "{'EO1': 'plate1', 'EO2': 'plate2', 'EO3': 'plate3', 'EO4': 'plate4', 'EO5': 'plate5', 'EO6': 'plate6', 'EO7': 'plate7', 'EO8': 'plate8'}")
|
400
385
|
settings.setdefault('test', False)
|
401
386
|
settings.setdefault('verbose', True)
|
402
387
|
settings.setdefault('pc', 'TGGT1_220950_1')
|
@@ -554,8 +539,6 @@ expected_types = {
|
|
554
539
|
"png_dims": list,
|
555
540
|
"normalize_by": str,
|
556
541
|
"save_measurements": bool,
|
557
|
-
"representative_images": bool,
|
558
|
-
"plot_filtration": bool,
|
559
542
|
"include_uninfected": bool,
|
560
543
|
"dialate_pngs": bool,
|
561
544
|
"dialate_png_ratios": list,
|
@@ -742,60 +725,6 @@ expected_types = {
|
|
742
725
|
"fraction_threshold": float,
|
743
726
|
}
|
744
727
|
|
745
|
-
def check_settings_v1(vars_dict, expected_types,q=None):
|
746
|
-
from .gui_utils import parse_list
|
747
|
-
settings = {}
|
748
|
-
# Define the expected types for each key, including None where applicable
|
749
|
-
|
750
|
-
for key, (label, widget, var) in vars_dict.items():
|
751
|
-
if key not in expected_types:
|
752
|
-
if key not in ["General","Nucleus","Cell","Pathogen","Timelapse","Plot","Object Image","Annotate Data","Measurements","Advanced","Miscellaneous","Test"]:
|
753
|
-
q.put(f"Key {key} not found in expected types.")
|
754
|
-
continue
|
755
|
-
|
756
|
-
value = var.get()
|
757
|
-
expected_type = expected_types.get(key, str)
|
758
|
-
|
759
|
-
try:
|
760
|
-
if key in ["png_size", "pathogen_plate_metadata", "treatment_plate_metadata"]:
|
761
|
-
parsed_value = ast.literal_eval(value) if value else None
|
762
|
-
if isinstance(parsed_value, list):
|
763
|
-
if all(isinstance(i, list) for i in parsed_value) or all(not isinstance(i, list) for i in parsed_value):
|
764
|
-
settings[key] = parsed_value
|
765
|
-
else:
|
766
|
-
raise ValueError("Invalid format: Mixed list and list of lists")
|
767
|
-
else:
|
768
|
-
raise ValueError("Invalid format for list or list of lists")
|
769
|
-
elif expected_type == list:
|
770
|
-
settings[key] = parse_list(value) if value else None
|
771
|
-
elif expected_type == bool:
|
772
|
-
settings[key] = value if isinstance(value, bool) else value.lower() in ['true', '1', 't', 'y', 'yes']
|
773
|
-
elif expected_type == (int, type(None)):
|
774
|
-
settings[key] = int(value) if value else None
|
775
|
-
elif expected_type == (float, type(None)):
|
776
|
-
settings[key] = float(value) if value else None
|
777
|
-
elif expected_type == (int, float):
|
778
|
-
settings[key] = float(value) if '.' in value else int(value)
|
779
|
-
elif expected_type == (str, type(None)):
|
780
|
-
settings[key] = str(value) if value else None
|
781
|
-
elif isinstance(expected_type, tuple):
|
782
|
-
for typ in expected_type:
|
783
|
-
try:
|
784
|
-
settings[key] = typ(value) if value else None
|
785
|
-
break
|
786
|
-
except (ValueError, TypeError):
|
787
|
-
continue
|
788
|
-
else:
|
789
|
-
raise ValueError
|
790
|
-
else:
|
791
|
-
settings[key] = expected_type(value) if value else None
|
792
|
-
except (ValueError, SyntaxError):
|
793
|
-
expected_type_name = ' or '.join([t.__name__ for t in expected_type]) if isinstance(expected_type, tuple) else expected_type.__name__
|
794
|
-
q.put(f"Error: Invalid format for {key}. Expected type: {expected_type_name}.")
|
795
|
-
return
|
796
|
-
|
797
|
-
return settings
|
798
|
-
|
799
728
|
def check_settings(vars_dict, expected_types, q=None):
|
800
729
|
from .gui_utils import parse_list
|
801
730
|
|
@@ -805,9 +734,9 @@ def check_settings(vars_dict, expected_types, q=None):
|
|
805
734
|
|
806
735
|
settings = {}
|
807
736
|
|
808
|
-
for key, (label, widget, var) in vars_dict.items():
|
737
|
+
for key, (label, widget, var, _) in vars_dict.items():
|
809
738
|
if key not in expected_types:
|
810
|
-
if key not in ["General", "Nucleus", "Cell", "Pathogen", "Timelapse", "Plot", "Object Image", "Annotate Data", "Measurements", "Advanced", "Miscellaneous", "Test"]:
|
739
|
+
if key not in ["General", "Nucleus", "Cell", "Pathogen", "Timelapse", "Plot", "Object Image", "Annotate Data", "Measurements", "Advanced", "Miscellaneous", "Test", "Paths"]:
|
811
740
|
q.put(f"Key {key} not found in expected types.")
|
812
741
|
continue
|
813
742
|
|
@@ -836,6 +765,20 @@ def check_settings(vars_dict, expected_types, q=None):
|
|
836
765
|
settings[key] = float(value) if '.' in value else int(value)
|
837
766
|
elif expected_type == (str, type(None)):
|
838
767
|
settings[key] = str(value) if value else None
|
768
|
+
elif expected_type == dict:
|
769
|
+
try:
|
770
|
+
# Ensure that the value is a string that can be converted to a dictionary
|
771
|
+
if isinstance(value, str):
|
772
|
+
settings[key] = ast.literal_eval(value)
|
773
|
+
else:
|
774
|
+
raise ValueError("Expected a string representation of a dictionary.")
|
775
|
+
|
776
|
+
# Check if the result is actually a dictionary
|
777
|
+
if not isinstance(settings[key], dict):
|
778
|
+
raise ValueError("Value is not a valid dictionary.")
|
779
|
+
except (ValueError, SyntaxError) as e:
|
780
|
+
settings[key] = {}
|
781
|
+
q.put(f"Error: Invalid format for {key}. Expected type: dict. Error: {e}")
|
839
782
|
elif isinstance(expected_type, tuple):
|
840
783
|
for typ in expected_type:
|
841
784
|
try:
|
@@ -856,7 +799,7 @@ def check_settings(vars_dict, expected_types, q=None):
|
|
856
799
|
|
857
800
|
def generate_fields(variables, scrollable_frame):
|
858
801
|
from .gui_utils import create_input_field
|
859
|
-
from .gui_elements import spacrToolTip
|
802
|
+
from .gui_elements import set_dark_style, spacrToolTip
|
860
803
|
row = 1
|
861
804
|
vars_dict = {}
|
862
805
|
tooltips = {
|
@@ -1014,7 +957,6 @@ def generate_fields(variables, scrollable_frame):
|
|
1014
957
|
"plot_by_cluster": "(bool) - Whether to plot images by clusters.",
|
1015
958
|
"plot_cluster_grids": "(bool) - Whether to plot grids of clustered images.",
|
1016
959
|
"plot_control": "(dict) - Control settings for plotting.",
|
1017
|
-
"plot_filtration": "(bool) - Whether to plot the filtration steps.",
|
1018
960
|
"plot_images": "(bool) - Whether to plot images.",
|
1019
961
|
"plot_nr": "(int) - Number of plots to generate.",
|
1020
962
|
"plot_outlines": "(bool) - Whether to plot outlines of segmented objects.",
|
@@ -1036,7 +978,6 @@ def generate_fields(variables, scrollable_frame):
|
|
1036
978
|
"remove_image_canvas": "(bool) - Whether to remove the image canvas after plotting.",
|
1037
979
|
"remove_low_variance_features": "(bool) - Whether to remove low variance features from the analysis.",
|
1038
980
|
"remove_row_column_effect": "(bool) - Whether to remove row and column effects from the data.",
|
1039
|
-
"representative_images": "(bool) - Whether to save representative images of the segmented objects (Not working yet).",
|
1040
981
|
"resize": "(bool) - Resize factor for the images.",
|
1041
982
|
"resample": "(bool) - Whether to resample the images during processing.",
|
1042
983
|
"rescale": "(float) - Rescaling factor for the images.",
|
@@ -1080,17 +1021,19 @@ def generate_fields(variables, scrollable_frame):
|
|
1080
1021
|
"um_per_pixel": "(float) - The micrometers per pixel for the images."
|
1081
1022
|
}
|
1082
1023
|
|
1083
|
-
|
1084
1024
|
for key, (var_type, options, default_value) in variables.items():
|
1085
|
-
label, widget, var = create_input_field(scrollable_frame.scrollable_frame, key, row, var_type, options, default_value)
|
1086
|
-
vars_dict[key] = (label, widget, var) # Store the label, widget, and variable
|
1025
|
+
label, widget, var, frame = create_input_field(scrollable_frame.scrollable_frame, key, row, var_type, options, default_value)
|
1026
|
+
vars_dict[key] = (label, widget, var, frame) # Store the label, widget, and variable
|
1087
1027
|
|
1088
1028
|
# Add tooltip to the label if it exists in the tooltips dictionary
|
1089
1029
|
if key in tooltips:
|
1090
1030
|
spacrToolTip(label, tooltips[key])
|
1031
|
+
|
1091
1032
|
row += 1
|
1033
|
+
|
1092
1034
|
return vars_dict
|
1093
1035
|
|
1036
|
+
|
1094
1037
|
categories = {
|
1095
1038
|
"General": ["src", "metadata_type", "custom_regex", "experiment", "channels", "magnification", "channel_dims"],
|
1096
1039
|
"Paths":["grna", "barcodes"],
|
@@ -1100,9 +1043,9 @@ categories = {
|
|
1100
1043
|
"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", "include_uninfected", "merge_edge_pathogen_cells", "adjust_cells"],
|
1101
1044
|
"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"],
|
1102
1045
|
"Timelapse": ["fps", "timelapse_displacement", "timelapse_memory", "timelapse_frame_limits", "timelapse_remove_transient", "timelapse_mode", "timelapse_objects", "compartments"],
|
1103
|
-
"Plot": ["plot_control", "plot_nr", "
|
1046
|
+
"Plot": ["plot_control", "plot_nr", "examples_to_plot", "normalize_plots", "normalize", "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"],
|
1104
1047
|
"Object Image": ["save_png", "dialate_pngs", "dialate_png_ratios", "png_size", "png_dims", "save_arrays", "normalize_by", "dialate_png_ratios", "crop_mode", "dialate_pngs", "normalize", "use_bounding_box"],
|
1105
|
-
"Annotate Data": ["nc_loc", "pc_loc", "nc", "pc", "cell_plate_metadata","pathogen_types", "pathogen_plate_metadata", "treatment_plate_metadata", "metadata_types", "cell_types", "target","positive_control","negative_control", "location_column", "treatment_loc", "cells", "cell_loc", "pathogens", "pathogen_loc", "channel_of_interest", "measurement", "treatments", "
|
1048
|
+
"Annotate Data": ["nc_loc", "pc_loc", "nc", "pc", "cell_plate_metadata","pathogen_types", "pathogen_plate_metadata", "treatment_plate_metadata", "metadata_types", "cell_types", "target","positive_control","negative_control", "location_column", "treatment_loc", "cells", "cell_loc", "pathogens", "pathogen_loc", "channel_of_interest", "measurement", "treatments", "um_per_pixel", "nr_imgs", "exclude", "exclude_conditions", "mix", "pos", "neg"],
|
1106
1049
|
"Measurements": ["remove_image_canvas", "remove_highly_correlated", "homogeneity", "homogeneity_distances", "radial_dist", "calculate_correlation", "manders_thresholds", "save_measurements", "tables", "image_nr", "dot_size", "filter_by", "remove_highly_correlated_features", "remove_low_variance_features", "channel_of_interest"],
|
1107
1050
|
"Advanced": ["plate_dict", "target_intensity_min", "cells_per_well", "include_multinucleated", "include_multiinfected", "include_noninfected", "backgrounds", "plot", "timelapse", "schedule", "test_size","exclude","n_repeats","top_features", "model_type","minimum_cell_count","n_estimators","preprocess", "remove_background", "normalize", "lower_percentile", "merge_pathogens", "batch_size", "filter", "save", "masks", "verbose", "randomize", "n_jobs", "train_mode","amsgrad","use_checkpoint","gradient_accumulation","gradient_accumulation_steps","intermedeate_save","pin_memory","n_jobs","channels","augment"],
|
1108
1051
|
"Clustering": ["eps","min_samples","analyze_clusters","clustering","remove_cluster_noise"],
|
spacr/utils.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import sys, os, re, sqlite3, torch, torchvision, random, string, shutil, cv2, tarfile, glob, psutil, platform
|
1
|
+
import sys, os, re, sqlite3, torch, torchvision, random, string, shutil, cv2, tarfile, glob, psutil, platform
|
2
2
|
|
3
3
|
import numpy as np
|
4
4
|
from cellpose import models as cp_models
|
@@ -90,9 +90,9 @@ from scipy import stats
|
|
90
90
|
|
91
91
|
def print_progress(files_processed, files_to_process, n_jobs, time_ls=None, batch_size=None, operation_type=""):
|
92
92
|
if isinstance(files_processed, list):
|
93
|
-
files_processed = len(files_processed)
|
93
|
+
files_processed = len(set(files_processed))
|
94
94
|
if isinstance(files_to_process, list):
|
95
|
-
files_to_process = len(files_to_process)
|
95
|
+
files_to_process = len(set(files_to_process))
|
96
96
|
if isinstance(batch_size, list):
|
97
97
|
batch_size = len(batch_size)
|
98
98
|
|
@@ -3628,22 +3628,22 @@ def delete_folder(folder_path):
|
|
3628
3628
|
def measure_test_mode(settings):
|
3629
3629
|
|
3630
3630
|
if settings['test_mode']:
|
3631
|
-
if not os.path.basename(settings['
|
3632
|
-
all_files = os.listdir(settings['
|
3631
|
+
if not os.path.basename(settings['src']) == 'test':
|
3632
|
+
all_files = os.listdir(settings['src'])
|
3633
3633
|
random_files = random.sample(all_files, settings['test_nr'])
|
3634
3634
|
|
3635
|
-
src = os.path.join(os.path.dirname(settings['
|
3635
|
+
src = os.path.join(os.path.dirname(settings['src']),'test', 'merged')
|
3636
3636
|
if os.path.exists(src):
|
3637
3637
|
delete_folder(src)
|
3638
3638
|
os.makedirs(src, exist_ok=True)
|
3639
3639
|
|
3640
3640
|
for file in random_files:
|
3641
|
-
shutil.copy(os.path.join(settings['
|
3641
|
+
shutil.copy(os.path.join(settings['src'], file), os.path.join(src,file))
|
3642
3642
|
|
3643
|
-
settings['
|
3643
|
+
settings['src'] = src
|
3644
3644
|
print(f'Changed source folder to {src} for test mode')
|
3645
3645
|
else:
|
3646
|
-
print(f'Test mode enabled, using source folder {settings["
|
3646
|
+
print(f'Test mode enabled, using source folder {settings["src"]}')
|
3647
3647
|
|
3648
3648
|
return settings
|
3649
3649
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: spacr
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.53
|
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
|
@@ -9,9 +9,9 @@ Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
10
10
|
Classifier: Operating System :: OS Independent
|
11
11
|
License-File: LICENSE
|
12
|
-
Requires-Dist: torch <3.0,>=2.
|
13
|
-
Requires-Dist: torchvision <1.0,>=0.
|
14
|
-
Requires-Dist: torch-geometric <3.0,>=2.5
|
12
|
+
Requires-Dist: torch <3.0,>=2.0
|
13
|
+
Requires-Dist: torchvision <1.0,>=0.1
|
14
|
+
Requires-Dist: torch-geometric <3.0,>=2.5
|
15
15
|
Requires-Dist: numpy <2.0,>=1.26.4
|
16
16
|
Requires-Dist: pandas <3.0,>=2.2.1
|
17
17
|
Requires-Dist: statsmodels <1.0,>=0.14.1
|
@@ -42,6 +42,8 @@ Requires-Dist: lxml <6.0,>=5.1.0
|
|
42
42
|
Requires-Dist: psutil <6.0,>=5.9.8
|
43
43
|
Requires-Dist: gputil <2.0,>=1.4.0
|
44
44
|
Requires-Dist: gpustat <2.0,>=1.1.1
|
45
|
+
Requires-Dist: pyautogui <1.0,>=0.9.54
|
46
|
+
Requires-Dist: tables <4.0,>=3.8.0
|
45
47
|
Requires-Dist: huggingface-hub <0.25,>=0.24.0
|
46
48
|
Provides-Extra: dev
|
47
49
|
Requires-Dist: pytest <3.11,>=3.9 ; extra == 'dev'
|