Skip to content

Commit e654135

Browse files
committed
Ruff formatting
1 parent 5ebebd0 commit e654135

File tree

4 files changed

+101
-38
lines changed

4 files changed

+101
-38
lines changed

sopa/cli/segmentation.py

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,16 @@ def cellpose(
1616
help="Names of the channels used for Cellpose. If one channel, then provide just a nucleus channel. If two channels, this is the nucleus and then the cytoplasm channel"
1717
),
1818
flow_threshold: float = typer.Option(2, help="Cellpose `flow_threshold` parameter"),
19-
cellprob_threshold: float = typer.Option(-6, help="Cellpose `cellprob_threshold` parameter"),
19+
cellprob_threshold: float = typer.Option(
20+
-6, help="Cellpose `cellprob_threshold` parameter"
21+
),
2022
model_type: str = typer.Option("cyto3", help="Name of the cellpose model"),
21-
pretrained_model: str = typer.Option(None, help="Path to the pretrained model to be loaded"),
22-
min_area: int = typer.Option(0, help="Minimum area (in pixels^2) for a cell to be considered as valid"),
23+
pretrained_model: str = typer.Option(
24+
None, help="Path to the pretrained model to be loaded"
25+
),
26+
min_area: int = typer.Option(
27+
0, help="Minimum area (in pixels^2) for a cell to be considered as valid"
28+
),
2329
clip_limit: float = typer.Option(
2430
0.2,
2531
help="Parameter for skimage.exposure.equalize_adapthist (applied before running cellpose)",
@@ -88,8 +94,12 @@ def generic_staining(
8894
callback=ast.literal_eval,
8995
help="Kwargs for the method. This should be a dictionnary, in inline string format.",
9096
),
91-
channels: list[str] = typer.Option(None, help="Names of the channels used for segmentation."),
92-
min_area: int = typer.Option(0, help="Minimum area (in pixels^2) for a cell to be considered as valid"),
97+
channels: list[str] = typer.Option(
98+
None, help="Names of the channels used for segmentation."
99+
),
100+
min_area: int = typer.Option(
101+
0, help="Minimum area (in pixels^2) for a cell to be considered as valid"
102+
),
93103
clip_limit: float = typer.Option(
94104
0.2,
95105
help="Parameter for skimage.exposure.equalize_adapthist (applied before running the segmentation method)",
@@ -124,9 +134,9 @@ def generic_staining(
124134
"""
125135
from sopa.segmentation import methods
126136

127-
assert hasattr(
128-
methods, method_name
129-
), f"'{method_name}' is not a valid method builder under `sopa.segmentation.methods`"
137+
assert hasattr(methods, method_name), (
138+
f"'{method_name}' is not a valid method builder under `sopa.segmentation.methods`"
139+
)
130140

131141
_run_staining_segmentation(
132142
sdata_path,
@@ -215,7 +225,10 @@ def comseg(
215225
default=None,
216226
help="Index of the patch on which the segmentation method should be run.",
217227
),
218-
min_area: float = typer.Option(default=0, help="Minimum area (in micron^2) for a cell to be considered as valid"),
228+
min_area: float = typer.Option(
229+
default=0,
230+
help="Minimum area (in micron^2) for a cell to be considered as valid",
231+
),
219232
):
220233
"""Perform ComSeg segmentation. This can be done on all patches directly, or on one individual patch."""
221234
from sopa.io.standardize import read_zarr_standardized
@@ -240,8 +253,13 @@ def baysor(
240253
default=None,
241254
help="Index of the patch on which the segmentation method should be run. By default, run on all patches.",
242255
),
243-
min_area: float = typer.Option(default=0, help="Minimum area (in micron^2) for a cell to be considered as valid"),
244-
scale: float = typer.Option(default=None, help="Baysor scale parameter (for config inference)"),
256+
min_area: float = typer.Option(
257+
default=0,
258+
help="Minimum area (in micron^2) for a cell to be considered as valid",
259+
),
260+
scale: float = typer.Option(
261+
default=None, help="Baysor scale parameter (for config inference)"
262+
),
245263
):
246264
"""Perform Baysor segmentation. This can be done on all patches directly, or on one individual patch."""
247265
import sys
@@ -253,7 +271,13 @@ def baysor(
253271
sdata = read_zarr_standardized(sdata_path)
254272

255273
try:
256-
baysor(sdata, config=config, min_area=min_area, patch_index=patch_index, scale=scale)
274+
baysor(
275+
sdata,
276+
config=config,
277+
min_area=min_area,
278+
patch_index=patch_index,
279+
scale=scale,
280+
)
257281
except CalledProcessError as e:
258282
sys.exit(e.returncode)
259283

@@ -321,4 +345,6 @@ def tissue(
321345

322346
sdata = read_zarr_standardized(sdata_path)
323347

324-
sopa.segmentation.tissue(sdata, image_key=image_key, level=level, mode=mode, **kwargs)
348+
sopa.segmentation.tissue(
349+
sdata, image_key=image_key, level=level, mode=mode, **kwargs
350+
)

sopa/patches/_factory.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ def make_image_patches(
2828
"""
2929
image_key, _ = get_spatial_image(sdata, key=image_key, return_key=True)
3030

31-
patches = Patches2D(sdata, image_key, patch_width=patch_width, patch_overlap=patch_overlap)
31+
patches = Patches2D(
32+
sdata, image_key, patch_width=patch_width, patch_overlap=patch_overlap
33+
)
3234

3335
patches.add_shapes(key_added=key_added)
3436

@@ -65,10 +67,14 @@ def make_transcript_patches(
6567
key_added: Optional name of the patches to be saved. By default, uses `"transcripts_patches"`.
6668
**kwargs: Additional arguments passed to the `OnDiskTranscriptPatches` class.
6769
"""
68-
assert not write_cells_centroids or prior_shapes_key, "write_cells_centroids argument requires prior_shapes_key"
70+
assert not write_cells_centroids or prior_shapes_key, (
71+
"write_cells_centroids argument requires prior_shapes_key"
72+
)
6973

7074
points_key, _ = get_spatial_element(
71-
sdata.points, key=points_key or sdata.attrs.get(SopaAttrs.TRANSCRIPTS), return_key=True
75+
sdata.points,
76+
key=points_key or sdata.attrs.get(SopaAttrs.TRANSCRIPTS),
77+
return_key=True,
7278
)
7379

7480
if patch_width is None:

sopa/segmentation/_transcripts.py

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,28 @@ def resolve(
5656
geo_df_new = ShapesModel.parse(geo_df_new, transformations=transformations)
5757

5858
log.info("Aggregating transcripts on merged cells")
59-
table_conflicts = count_transcripts(sdata, gene_column, geo_df=geo_df_new, points_key=points_key)
59+
table_conflicts = count_transcripts(
60+
sdata, gene_column, geo_df=geo_df_new, points_key=points_key
61+
)
6062
table_conflicts.obs_names = new_ids
6163
table_conflicts = [table_conflicts]
6264

6365
valid_ids = set(list(geo_df.index))
6466
table = anndata.concat(
65-
[adata[list(valid_ids & set(list(adata.obs_names)))] for adata in adatas] + table_conflicts,
67+
[adata[list(valid_ids & set(list(adata.obs_names)))] for adata in adatas]
68+
+ table_conflicts,
6669
join="outer",
6770
)
6871
table.obs.dropna(axis="columns", inplace=True)
6972

7073
geo_df = geo_df.loc[table.obs_names]
7174

72-
table.obsm["spatial"] = np.array([[centroid.x, centroid.y] for centroid in geo_df.centroid])
73-
table.obs[SopaKeys.REGION_KEY] = pd.Series(key_added, index=table.obs_names, dtype="category")
75+
table.obsm["spatial"] = np.array(
76+
[[centroid.x, centroid.y] for centroid in geo_df.centroid]
77+
)
78+
table.obs[SopaKeys.REGION_KEY] = pd.Series(
79+
key_added, index=table.obs_names, dtype="category"
80+
)
7481
table.obs[SopaKeys.INSTANCE_KEY] = geo_df.index
7582

7683
table = TableModel.parse(
@@ -83,7 +90,9 @@ def resolve(
8390
add_spatial_element(sdata, key_added, geo_df)
8491
add_spatial_element(sdata, SopaKeys.TABLE, table)
8592

86-
log.info(f"Added sdata.tables['{SopaKeys.TABLE}'], and {len(geo_df)} cell boundaries to sdata['{key_added}']")
93+
log.info(
94+
f"Added sdata.tables['{SopaKeys.TABLE}'], and {len(geo_df)} cell boundaries to sdata['{key_added}']"
95+
)
8796

8897

8998
def _read_one_segmented_patch(
@@ -94,13 +103,18 @@ def _read_one_segmented_patch(
94103

95104
loom_file = directory / "segmentation_counts.loom"
96105
if loom_file.exists():
97-
adata = anndata.io.read_loom(directory / "segmentation_counts.loom", obs_names="Name", var_names="Name")
106+
adata = anndata.io.read_loom(
107+
directory / "segmentation_counts.loom", obs_names="Name", var_names="Name"
108+
)
98109
else:
99110
adata = anndata.io.read_h5ad(directory / "segmentation_counts.h5ad")
100111

101112
adata.obs.rename(columns={"area": SopaKeys.ORIGINAL_AREA_OBS}, inplace=True)
102113

103-
cells_ids = pd.Series(adata.obs_names if id_as_string else adata.obs["CellID"].astype(int), index=adata.obs_names)
114+
cells_ids = pd.Series(
115+
adata.obs_names if id_as_string else adata.obs["CellID"].astype(int),
116+
index=adata.obs_names,
117+
)
104118
del adata.obs["CellID"]
105119

106120
with open(polygon_file) as f:
@@ -114,12 +128,16 @@ def _keep_cell(ID: str | int):
114128

115129
cells_ids = cells_ids[cells_ids.map(_keep_cell)]
116130

117-
geo_df = gpd.GeoDataFrame(index=cells_ids.index, geometry=[shape(polygons_dict[ID]) for ID in cells_ids])
131+
geo_df = gpd.GeoDataFrame(
132+
index=cells_ids.index, geometry=[shape(polygons_dict[ID]) for ID in cells_ids]
133+
)
118134
geo_df = shapes.to_valid_polygons(geo_df)
119135

120136
ratio_filtered = (geo_df.area <= min_area).mean()
121137
if ratio_filtered > 0.2:
122-
log.warning(f"{ratio_filtered:.2%} of cells will be filtered due to {min_area=}")
138+
log.warning(
139+
f"{ratio_filtered:.2%} of cells will be filtered due to {min_area=}"
140+
)
123141

124142
geo_df = geo_df[geo_df.area > min_area]
125143

@@ -131,7 +149,9 @@ def _find_polygon_file(directory: Path) -> tuple[bool, Path]:
131149
if old_baysor_path.exists():
132150
return False, old_baysor_path
133151
new_baysor_path = directory / "segmentation_polygons_2d.json"
134-
assert new_baysor_path.exists(), f"Could not find the segmentation polygons file in {directory}"
152+
assert new_baysor_path.exists(), (
153+
f"Could not find the segmentation polygons file in {directory}"
154+
)
135155
return True, new_baysor_path
136156

137157

@@ -163,25 +183,34 @@ def _resolve_patches(
163183
"""
164184
patch_ids = [adata.obs_names for adata in adatas]
165185

166-
patch_indices = np.arange(len(patches_cells)).repeat([len(cells) for cells in patches_cells])
186+
patch_indices = np.arange(len(patches_cells)).repeat(
187+
[len(cells) for cells in patches_cells]
188+
)
167189
cells = [cell for cells in patches_cells for cell in cells]
168190
segmentation_ids = np.array([cell_id for ids in patch_ids for cell_id in ids])
169191

170-
cells_resolved, cells_indices = solve_conflicts(cells, patch_indices=patch_indices, return_indices=True)
192+
cells_resolved, cells_indices = solve_conflicts(
193+
cells, patch_indices=patch_indices, return_indices=True
194+
)
171195

172196
existing_ids = segmentation_ids[cells_indices[cells_indices >= 0]]
173-
new_ids = np.char.add("merged_cell_", np.arange((cells_indices == -1).sum()).astype(str))
197+
new_ids = np.char.add(
198+
"merged_cell_", np.arange((cells_indices == -1).sum()).astype(str)
199+
)
174200
cells_resolved.index = np.concatenate([existing_ids, new_ids])
175201

176202
return cells_resolved, cells_indices, new_ids
177203

178204

179205
def _check_transcript_patches(sdata: SpatialData, with_prior: bool = False):
180-
assert (
181-
SopaKeys.TRANSCRIPTS_PATCHES in sdata.shapes
182-
), "Transcript patches not found in the SpatialData object. Run `sopa.make_transcript_patches(...)` first."
206+
assert SopaKeys.TRANSCRIPTS_PATCHES in sdata.shapes, (
207+
"Transcript patches not found in the SpatialData object. Run `sopa.make_transcript_patches(...)` first."
208+
)
183209

184-
directories = [Path(path) for path in sdata[SopaKeys.TRANSCRIPTS_PATCHES][SopaKeys.CACHE_PATH_KEY]]
210+
directories = [
211+
Path(path)
212+
for path in sdata[SopaKeys.TRANSCRIPTS_PATCHES][SopaKeys.CACHE_PATH_KEY]
213+
]
185214

186215
assert all(directory.exists() for directory in directories), (
187216
"Some patch directories are missing. "
@@ -191,7 +220,9 @@ def _check_transcript_patches(sdata: SpatialData, with_prior: bool = False):
191220
)
192221

193222
if with_prior:
194-
assert SopaKeys.PRIOR_SHAPES_KEY in sdata[SopaKeys.TRANSCRIPTS_PATCHES].columns, (
223+
assert (
224+
SopaKeys.PRIOR_SHAPES_KEY in sdata[SopaKeys.TRANSCRIPTS_PATCHES].columns
225+
), (
195226
"You need to create the transcript patches with a `prior_shapes_key`. "
196227
"For that, you can run cellpose first, and then run again `sopa.make_transcript_patches` with `prior_shapes_key='cellpose_boundaries'`"
197228
)
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from ._cellpose import cellpose_patch, cellpose
2-
from ._comseg import comseg
3-
from ._dummy import dummy_method
41
from ._baysor import baysor
2+
from ._cellpose import cellpose, cellpose_patch
3+
from ._comseg import comseg
54
from ._custom import custom_staining_based
6-
from ._stardist import stardist_patch, stardist
5+
from ._dummy import dummy_method
76
from ._proseg import proseg
7+
from ._stardist import stardist, stardist_patch

0 commit comments

Comments
 (0)