spacr 1.0.0__py3-none-any.whl → 1.0.1__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 +2 -2
- spacr/gui_core.py +28 -63
- spacr/gui_utils.py +0 -38
- {spacr-1.0.0.dist-info → spacr-1.0.1.dist-info}/METADATA +14 -6
- {spacr-1.0.0.dist-info → spacr-1.0.1.dist-info}/RECORD +9 -9
- {spacr-1.0.0.dist-info → spacr-1.0.1.dist-info}/LICENSE +0 -0
- {spacr-1.0.0.dist-info → spacr-1.0.1.dist-info}/WHEEL +0 -0
- {spacr-1.0.0.dist-info → spacr-1.0.1.dist-info}/entry_points.txt +0 -0
- {spacr-1.0.0.dist-info → spacr-1.0.1.dist-info}/top_level.txt +0 -0
spacr/core.py
CHANGED
@@ -417,8 +417,8 @@ def generate_cellpose_masks(src, settings, object_type):
|
|
417
417
|
else:
|
418
418
|
mask_stack = _masks_to_masks_stack(masks)
|
419
419
|
|
420
|
-
if settings['plot']:
|
421
|
-
|
420
|
+
#if settings['plot']:
|
421
|
+
# plot_cellpose4_output(batch_list, masks, flows, cmap='inferno', figuresize=figuresize, nr=1, print_object_number=True)
|
422
422
|
|
423
423
|
if not np.any(mask_stack):
|
424
424
|
avg_num_objects_per_image, average_obj_size = 0, 0
|
spacr/gui_core.py
CHANGED
@@ -176,7 +176,6 @@ def display_figure(fig):
|
|
176
176
|
show_next_figure()
|
177
177
|
|
178
178
|
def zoom(event):
|
179
|
-
# Define zoom factors
|
180
179
|
zoom_in_factor = 1 / 1.2
|
181
180
|
zoom_out_factor = 1.2
|
182
181
|
|
@@ -187,83 +186,49 @@ def display_figure(fig):
|
|
187
186
|
else:
|
188
187
|
return
|
189
188
|
|
189
|
+
# Find the axis under the cursor
|
190
|
+
ref_ax = None
|
190
191
|
for ax in canvas.figure.get_axes():
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
try:
|
195
|
-
data_x, data_y = inv.transform((event.x, event.y))
|
196
|
-
except ValueError:
|
197
|
-
continue # e.g. axis has no data
|
198
|
-
|
199
|
-
xlim = ax.get_xlim()
|
200
|
-
ylim = ax.get_ylim()
|
201
|
-
|
202
|
-
# Zoom around (data_x, data_y) in *that axis's* data space
|
203
|
-
new_xlim = [data_x - (data_x - xlim[0]) * factor,
|
204
|
-
data_x + (xlim[1] - data_x) * factor]
|
205
|
-
new_ylim = [data_y - (data_y - ylim[0]) * factor,
|
206
|
-
data_y + (ylim[1] - data_y) * factor]
|
207
|
-
|
208
|
-
ax.set_xlim(new_xlim)
|
209
|
-
ax.set_ylim(new_ylim)
|
210
|
-
|
211
|
-
# Clip text labels
|
212
|
-
for label in ax.texts:
|
213
|
-
label.set_clip_on(True)
|
214
|
-
|
215
|
-
# Update label visibility
|
216
|
-
if hasattr(ax, '_label_annotations'):
|
217
|
-
for label in ax._label_annotations:
|
218
|
-
x, y = label.get_position()
|
219
|
-
is_visible = (new_xlim[0] <= x <= new_xlim[1]) and (new_ylim[0] <= y <= new_ylim[1])
|
220
|
-
label.set_visible(is_visible)
|
221
|
-
|
222
|
-
canvas.draw_idle()
|
192
|
+
if ax.get_window_extent().contains(event.x, event.y):
|
193
|
+
ref_ax = ax
|
194
|
+
break
|
223
195
|
|
224
|
-
|
225
|
-
|
226
|
-
zoom_in_factor = 1 / 1.2
|
227
|
-
zoom_out_factor = 1.2
|
196
|
+
if ref_ax is None:
|
197
|
+
return
|
228
198
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
else:
|
199
|
+
try:
|
200
|
+
# Convert mouse position to data coords in reference axis
|
201
|
+
data_x, data_y = ref_ax.transData.inverted().transform((event.x, event.y))
|
202
|
+
except ValueError:
|
234
203
|
return
|
235
204
|
|
205
|
+
# Get current limits
|
206
|
+
xlim = ref_ax.get_xlim()
|
207
|
+
ylim = ref_ax.get_ylim()
|
208
|
+
|
209
|
+
# Compute new limits for the reference axis
|
210
|
+
new_xlim = [
|
211
|
+
data_x - (data_x - xlim[0]) * factor,
|
212
|
+
data_x + (xlim[1] - data_x) * factor
|
213
|
+
]
|
214
|
+
new_ylim = [
|
215
|
+
data_y - (data_y - ylim[0]) * factor,
|
216
|
+
data_y + (ylim[1] - data_y) * factor
|
217
|
+
]
|
218
|
+
|
219
|
+
# Apply the same limits to all axes
|
236
220
|
for ax in canvas.figure.get_axes():
|
237
|
-
# Translate mouse position to figure coordinates
|
238
|
-
mouse_x, mouse_y = event.x, event.y
|
239
|
-
inv = ax.transData.inverted()
|
240
|
-
data_x, data_y = inv.transform((mouse_x, mouse_y))
|
241
|
-
|
242
|
-
xlim = ax.get_xlim()
|
243
|
-
ylim = ax.get_ylim()
|
244
|
-
|
245
|
-
# Compute new limits centered on the mouse data position
|
246
|
-
new_width = (xlim[1] - xlim[0]) * factor
|
247
|
-
new_height = (ylim[1] - ylim[0]) * factor
|
248
|
-
|
249
|
-
new_xlim = [data_x - (data_x - xlim[0]) * factor,
|
250
|
-
data_x + (xlim[1] - data_x) * factor]
|
251
|
-
new_ylim = [data_y - (data_y - ylim[0]) * factor,
|
252
|
-
data_y + (ylim[1] - data_y) * factor]
|
253
|
-
|
254
221
|
ax.set_xlim(new_xlim)
|
255
222
|
ax.set_ylim(new_ylim)
|
256
223
|
|
257
|
-
# Clip all text labels to the axes area
|
258
224
|
for label in ax.texts:
|
259
225
|
label.set_clip_on(True)
|
260
226
|
|
261
|
-
# Update label visibility based on new limits
|
262
227
|
if hasattr(ax, '_label_annotations'):
|
263
228
|
for label in ax._label_annotations:
|
264
229
|
x, y = label.get_position()
|
265
|
-
|
266
|
-
label.set_visible(
|
230
|
+
visible = new_xlim[0] <= x <= new_xlim[1] and new_ylim[0] <= y <= new_ylim[1]
|
231
|
+
label.set_visible(visible)
|
267
232
|
|
268
233
|
canvas.draw_idle()
|
269
234
|
|
spacr/gui_utils.py
CHANGED
@@ -242,45 +242,9 @@ def annotate(settings):
|
|
242
242
|
threshold=settings['threshold'],
|
243
243
|
normalize_channels=settings['normalize_channels'])
|
244
244
|
|
245
|
-
#next_button = tk.Button(root, text="Next", command=app.next_page)
|
246
|
-
#next_button.grid(row=app.grid_rows, column=app.grid_cols - 1)
|
247
|
-
#back_button = tk.Button(root, text="Back", command=app.previous_page)
|
248
|
-
#back_button.grid(row=app.grid_rows, column=app.grid_cols - 2)
|
249
|
-
#exit_button = tk.Button(root, text="Exit", command=app.shutdown)
|
250
|
-
#exit_button.grid(row=app.grid_rows, column=app.grid_cols - 3)
|
251
|
-
|
252
245
|
app.load_images()
|
253
246
|
root.mainloop()
|
254
247
|
|
255
|
-
def generate_annotate_fields_v1(frame):
|
256
|
-
from .settings import set_annotate_default_settings
|
257
|
-
from .gui_elements import set_dark_style
|
258
|
-
|
259
|
-
style_out = set_dark_style(ttk.Style())
|
260
|
-
font_loader = style_out['font_loader']
|
261
|
-
font_size = style_out['font_size'] - 2
|
262
|
-
|
263
|
-
vars_dict = {}
|
264
|
-
settings = set_annotate_default_settings(settings={})
|
265
|
-
|
266
|
-
for setting in settings:
|
267
|
-
vars_dict[setting] = {
|
268
|
-
'entry': ttk.Entry(frame),
|
269
|
-
'value': settings[setting]
|
270
|
-
}
|
271
|
-
|
272
|
-
# Arrange input fields and labels
|
273
|
-
for row, (name, data) in enumerate(vars_dict.items()):
|
274
|
-
tk.Label(frame, text=f"{name.replace('_', ' ').capitalize()}:", bg=style_out['bg_color'], fg=style_out['fg_color'], font=font_loader.get_font(size=font_size)).grid(row=row, column=0)
|
275
|
-
if isinstance(data['value'], list):
|
276
|
-
# Convert lists to comma-separated strings
|
277
|
-
data['entry'].insert(0, ','.join(map(str, data['value'])))
|
278
|
-
else:
|
279
|
-
data['entry'].insert(0, data['value'])
|
280
|
-
data['entry'].grid(row=row, column=1)
|
281
|
-
|
282
|
-
return vars_dict
|
283
|
-
|
284
248
|
def generate_annotate_fields(frame):
|
285
249
|
from .settings import set_annotate_default_settings
|
286
250
|
from .gui_elements import set_dark_style
|
@@ -496,8 +460,6 @@ def function_gui_wrapper(function=None, settings={}, q=None, fig_queue=None, imp
|
|
496
460
|
# Restore the original plt.show function
|
497
461
|
plt.show = original_show
|
498
462
|
|
499
|
-
|
500
|
-
|
501
463
|
def run_function_gui(settings_type, settings, q, fig_queue, stop_requested):
|
502
464
|
|
503
465
|
from .core import generate_image_umap, preprocess_generate_masks
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: spacr
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.1
|
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
|
@@ -91,12 +91,15 @@ Requires-Dist: opencv-python-headless ; extra == 'headless'
|
|
91
91
|
:target: https://github.com/EinarOlafsson/spacr/blob/main/LICENSE
|
92
92
|
.. |repo size| image:: https://img.shields.io/github/repo-size/EinarOlafsson/spacr
|
93
93
|
:target: https://github.com/EinarOlafsson/spacr/
|
94
|
+
.. |Tutorial| image:: https://img.shields.io/badge/Tutorial-Click%20Here-brightgreen
|
95
|
+
:target: https://einarolafsson.github.io/spacr/tutorial/
|
96
|
+
|
94
97
|
|
95
98
|
.. _docs: https://einarolafsson.github.io/spacr/index.html
|
96
99
|
|
97
100
|
Badges
|
98
101
|
------
|
99
|
-
|Docs| |PyPI version| |Python version| |Licence: MIT| |repo size|
|
102
|
+
|Docs| |PyPI version| |Python version| |Licence: MIT| |repo size| |Tutorial|
|
100
103
|
|
101
104
|
SpaCr
|
102
105
|
=====
|
@@ -123,7 +126,6 @@ Features
|
|
123
126
|
:alt: SpaCr workflow
|
124
127
|
:align: center
|
125
128
|
|
126
|
-
|
127
129
|
**Overview and data organization of spaCR.**
|
128
130
|
|
129
131
|
**a.** Schematic workflow of the spaCR pipeline for pooled image-based CRISPR screens. Microscopy images (TIFF, LIF, CZI, NDI) and sequencing reads (FASTQ) are used as inputs (black). The main modules (teal) are: (1) Mask: generates object masks for cells, nuclei, pathogens, and cytoplasm; (2) Measure: extracts object-level features and crops object images, storing quantitative data in an SQL database; (3) Classify—applies machine learning (ML, e.g., XGBoost) or deep learning (DL, e.g., PyTorch) models to classify objects, summarizing results as well-level classification scores; (4) Map Barcodes: extracts and maps row, column, and gRNA barcodes from sequencing data to corresponding wells; (5) Regression: estimates gRNA effect sizes and gene scores via multiple linear regression using well-level summary statistics.
|
@@ -141,8 +143,7 @@ If using Windows, switch to Linux—it's free, open-source, and better.
|
|
141
143
|
|
142
144
|
::
|
143
145
|
|
144
|
-
brew install libomp
|
145
|
-
brew install hdf5
|
146
|
+
brew install libomp hdf5 cmake openssl
|
146
147
|
|
147
148
|
**Linux GUI requirement:**
|
148
149
|
SpaCr GUI requires Tkinter.
|
@@ -201,7 +202,7 @@ Interactive Tutorial (under construction)
|
|
201
202
|
|
202
203
|
Click below to explore the step-by-step GUI and Notebook tutorials for spaCR:
|
203
204
|
|
204
|
-
|
205
|
+
|Tutorial|
|
205
206
|
|
206
207
|
License
|
207
208
|
-------
|
@@ -213,3 +214,10 @@ How to Cite
|
|
213
214
|
If you use spaCR in your research, please cite:
|
214
215
|
Olafsson EB, et al. SpaCr: Spatial phenotype analysis of CRISPR-Cas9 screens. *Manuscript in preparation*.
|
215
216
|
|
217
|
+
Papers Using spaCR
|
218
|
+
-------------------
|
219
|
+
Below are selected publications that have used or cited spaCR:
|
220
|
+
|
221
|
+
- Olafsson EB, et al. *SpaCr: Spatial phenotype analysis of CRISPR-Cas9 screens.* Manuscript in preparation.
|
222
|
+
- `IRE1α promotes phagosomal calcium flux to enhance macrophage fungicidal activity <https://doi.org/10.1016/j.celrep.2025.115694>`_
|
223
|
+
- `Metabolic adaptability and nutrient scavenging in Toxoplasma gondii: insights from ingestion pathway-deficient mutants <https://doi.org/10.1128/msphere.01011-24>`_
|
@@ -8,12 +8,12 @@ spacr/app_measure.py,sha256=_K7APYIeOKpV6e_LcqabBjvEi7mfq9Fch8175x1x0k8,162
|
|
8
8
|
spacr/app_sequencing.py,sha256=DjG26jy4cpddnV8WOOAIiExtOe9MleVMY4MFa5uTo5w,157
|
9
9
|
spacr/app_umap.py,sha256=ZWAmf_OsIKbYvolYuWPMYhdlVe-n2CADoJulAizMiEo,153
|
10
10
|
spacr/chat_bot.py,sha256=n3Fhqg3qofVXHmh3H9sUcmfYy9MmgRnr48663MVdY9E,1244
|
11
|
-
spacr/core.py,sha256=
|
11
|
+
spacr/core.py,sha256=A1PCJHtlYjJBMdIY0QH1VcrmjsAZy-JYVHQcBXQ5za8,46640
|
12
12
|
spacr/deep_spacr.py,sha256=055tIo3WP3elGFiIuSZaLURgu2XyUDxAdbw5ezASEqM,54526
|
13
13
|
spacr/gui.py,sha256=NhMh96KoArrSAaJBV6PhDQpIC1cQpxgb6SclhRbYG8s,8122
|
14
|
-
spacr/gui_core.py,sha256=
|
14
|
+
spacr/gui_core.py,sha256=kgOXpQiBp4QXp08KViWinDVB6pVM7Gfn26bKeees6tM,54561
|
15
15
|
spacr/gui_elements.py,sha256=OTU7aeLrPiMUTnyCT-J7ygng3beI9tdA0MmypOavEkw,156123
|
16
|
-
spacr/gui_utils.py,sha256=
|
16
|
+
spacr/gui_utils.py,sha256=1mWns46yK-CQpbhtERSTPx7KXBYPUIQz2UnFFxNxOrU,40749
|
17
17
|
spacr/io.py,sha256=g6vybQeGLdTXrAqEjM6X1aoB6lyZVUq6pTI0ASppX4g,159257
|
18
18
|
spacr/logger.py,sha256=lJhTqt-_wfAunCPl93xE65Wr9Y1oIHJWaZMjunHUeIw,1538
|
19
19
|
spacr/measure.py,sha256=nYvrfVfCIqD1AUk4QBE2jtpeSFtLdfUcnkhkqf9G4xQ,60877
|
@@ -103,9 +103,9 @@ spacr/resources/icons/umap.png,sha256=dOLF3DeLYy9k0nkUybiZMe1wzHQwLJFRmgccppw-8b
|
|
103
103
|
spacr/resources/images/plate1_E01_T0001F001L01A01Z01C02.tif,sha256=Tl0ZUfZ_AYAbu0up_nO0tPRtF1BxXhWQ3T3pURBCCRo,7958528
|
104
104
|
spacr/resources/images/plate1_E01_T0001F001L01A02Z01C01.tif,sha256=m8N-V71rA1TT4dFlENNg8s0Q0YEXXs8slIn7yObmZJQ,7958528
|
105
105
|
spacr/resources/images/plate1_E01_T0001F001L01A03Z01C03.tif,sha256=Pbhk7xn-KUP6RSIhJsxQcrHFImBm3GEpLkzx7WOc-5M,7958528
|
106
|
-
spacr-1.0.
|
107
|
-
spacr-1.0.
|
108
|
-
spacr-1.0.
|
109
|
-
spacr-1.0.
|
110
|
-
spacr-1.0.
|
111
|
-
spacr-1.0.
|
106
|
+
spacr-1.0.1.dist-info/LICENSE,sha256=t0Pov6pnK8thLteoF4xZGmdCwe5mhNwl3OXxLYTGD9U,1081
|
107
|
+
spacr-1.0.1.dist-info/METADATA,sha256=C_PPoW7NPT7RH3d3iJ2yfX3GR8cy-uQ8tx1RGmqq854,10963
|
108
|
+
spacr-1.0.1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
109
|
+
spacr-1.0.1.dist-info/entry_points.txt,sha256=BMC0ql9aNNpv8lUZ8sgDLQMsqaVnX5L535gEhKUP5ho,296
|
110
|
+
spacr-1.0.1.dist-info/top_level.txt,sha256=GJPU8FgwRXGzKeut6JopsSRY2R8T3i9lDgya42tLInY,6
|
111
|
+
spacr-1.0.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|