squidpy
squidpy copied to clipboard
Image segmentation and extract segmentation features
... Hello, I had a question concerning image segmentation and feature extraction. I am using a Visium image with H&E stains. When I follow your tutorial with your image, I get no errors but when I use mine I get the following error:
ValueError: Expected height to be in interval [0, 2000], found 9761.
My image has the following size:
ImageContainer object with 3 layers:
image: y (2000), x (1935), z (1), channels (3)
image_smooth: y (2000), x (1935), z (1), channels (3)
segmented_watershed: y (2000), x (1935), z (1), channels:0 (1)
Many thanks!
Hi @Nasrine26 , thank you for the interest in squidpy! from the log you posted it seems like the segmentation was already performed (looking at the segmented_watershed
layer). Would you mind sharing at what point of the tutorial it fails as well as te tracebak? thank you!
Yes segmentation is performed but then when I try to extract the features with:
sq.im.calculate_image_features(
adata_vis,
my_image,
layer="image",
features="segmentation",
key_added="segmentation_features",
features_kwargs={
"segmentation": {
"label_layer": "segmented_watershed",
"props": ["label", "area", "mean_intensity"],
"channels": [1, 2],
}
},
mask_circle=True,
)
following this [tutorial](https://squidpy.readthedocs.io/en/stable/auto_examples/image/compute_segmentation_features.html, I get the following error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-13-090ef3048512> in <module>
----> 1 sq.im.calculate_image_features(
2 adata_vis,
3 my_image,
4 layer="image",
5 features="segmentation",
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/squidpy/im/_feature.py in calculate_image_features(adata, img, layer, library_id, features, features_kwargs, key_added, copy, n_jobs, backend, show_progress_bar, **kwargs)
89 start = logg.info(f"Calculating features `{list(features)}` using `{n_jobs}` core(s)")
90
---> 91 res = parallelize(
92 _calculate_image_features_helper,
93 collection=adata.obs_names,
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/squidpy/_utils.py in wrapper(*args, **kwargs)
166 pbar, queue, thread = None, None, None # type: ignore[assignment]
167
--> 168 res = jl.Parallel(n_jobs=n_jobs, backend=backend)(
169 jl.delayed(runner if use_runner else callback)(
170 *((i, cs) if use_ixs else (cs,)),
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/parallel.py in __call__(self, iterable)
1039 # remaining jobs.
1040 self._iterating = False
-> 1041 if self.dispatch_one_batch(iterator):
1042 self._iterating = self._original_iterator is not None
1043
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/parallel.py in dispatch_one_batch(self, iterator)
857 return False
858 else:
--> 859 self._dispatch(tasks)
860 return True
861
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/parallel.py in _dispatch(self, batch)
775 with self._lock:
776 job_idx = len(self._jobs)
--> 777 job = self._backend.apply_async(batch, callback=cb)
778 # A job can complete so quickly than its callback is
779 # called before we get here, causing self._jobs to
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/_parallel_backends.py in apply_async(self, func, callback)
206 def apply_async(self, func, callback=None):
207 """Schedule a func to be run"""
--> 208 result = ImmediateResult(func)
209 if callback:
210 callback(result)
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/_parallel_backends.py in __init__(self, batch)
570 # Don't delay the application, to avoid keeping the input
571 # arguments in memory
--> 572 self.results = batch()
573
574 def get(self):
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/parallel.py in __call__(self)
260 # change the default number of processes to -1
261 with parallel_backend(self._backend, n_jobs=self._n_jobs):
--> 262 return [func(*args, **kwargs)
263 for func, args, kwargs in self.items]
264
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/joblib/parallel.py in <listcomp>(.0)
260 # change the default number of processes to -1
261 with parallel_backend(self._backend, n_jobs=self._n_jobs):
--> 262 return [func(*args, **kwargs)
263 for func, args, kwargs in self.items]
264
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/squidpy/im/_feature.py in _calculate_image_features_helper(obs_ids, adata, img, layer, library_id, features, features_kwargs, queue, **kwargs)
117 ) -> pd.DataFrame:
118 features_list = []
--> 119 for crop in img.generate_spot_crops(
120 adata, obs_names=obs_ids, library_id=library_id, return_obs=False, as_array=False, **kwargs
121 ):
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/squidpy/im/_container.py in generate_spot_crops(self, adata, spatial_key, library_id, spot_scale, obs_names, as_array, squeeze, return_obs, **kwargs)
813 y = int(y - self.data.attrs[Key.img.coords].y0)
814 x = int(x - self.data.attrs[Key.img.coords].x0)
--> 815 crop = self.crop_center(y=y, x=x, radius=radius, library_id=obs_library_ids[i], **kwargs)
816 crop.data.attrs[Key.img.obs] = obs
817 crop = crop._maybe_as_array(as_array, squeeze=squeeze, lazy=False)
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/squidpy/im/_container.py in crop_center(self, y, x, radius, **kwargs)
647 """
648 y, x = self._convert_to_pixel_space((y, x))
--> 649 _assert_in_range(y, 0, self.shape[0], name="height")
650 _assert_in_range(x, 0, self.shape[1], name="width")
651
/data/BCI-CRC/nasrine/anaconda/envs/scanpy/lib/python3.8/site-packages/squidpy/gr/_utils.py in _assert_in_range(value, minn, maxx, name)
186 def _assert_in_range(value: float, minn: float, maxx: float, *, name: str) -> None:
187 if not (minn <= value <= maxx):
--> 188 raise ValueError(f"Expected `{name}` to be in interval `[{minn}, {maxx}]`, found `{value}`.")
189
190
ValueError: Expected `height` to be in interval `[0, 2000]`, found `9761`.
Hi @Nasrine26
I was having the same issue and the solution here (set scale factors) worked for me: https://github.com/theislab/squidpy/issues/399
Hi, I had the same issue as above "ValueError: Expected height to be in interval [0, 2000], found 21430". I tried adding a scale factor as mentioned in #399 but it does not solve my problem.
My code: `scale = 1 img = sq.im.ImageContainer("image_path", scale=scale) feature_name = f"features_summary_scale{scale}"
sq.im.calculate_image_features( adata, img, features="summary", key_added=feature_name, n_jobs=4, scale=scale )`
hi @Charlottehero ,
the scaling factor should be in adata.uns["spatial"]["V1_Adult_Mouse_Brain"]["scalefactors"]
, You should choose the one you are interested in with respect to your image resolution. May I kjnow what the file name in image_path
in the image container you are pointing to? would be useful for debugging
Hi @dst53,
the scale (set scale factors) worked for me as well. Many thanks!
Hi @giovp,
I had a question concerning extracting segmentation features.
I'm using the full H&E image fromadata.uns['spatial'][library_id]['images']['hires']
to infer segmentation features.
More precisely, I perform the following steps:
- smooth it using squidpy.im.process()
- squidpy.im.segment() with method = 'watershed' to do the segmentation, use the channel 0 as it is supposed to contain most of the nuclei info for H&E stain
- calculate segmentation features using:
sq.im.calculate_image_features(
adata_vis,
my_image,
layer='image',
features="segmentation",
key_added="segmentation_features",
features_kwargs={
"segmentation": {
"label_layer": "segmented_watershed",
"props": ["label", "area", "mean_intensity"],
"channels": [1, 2],
}
},
mask_circle=True,
)
I then look at the number of nuclei per spot adata_vis.obsm["segmentation_features"]['segmentation_label'].describe()
- How can I be sure the segmentation is well performed and trust these values?
- Also is it ok if I use the image that's stored in
adata.uns['spatial'][library_id]['images']['hires']
? - Finally, Are the steps are perform ok or would you go about it another way?
Many thanks, I am very new to segmentation!
Thanks @giovp. I figured out the scale factor value from your reply, but now I am encountering a resolution issue with the image. I used the sq.im.ImageContainer() to load in the hires_image I got from spatial results, but the resulting segmentation quality is not as good as what is shown in the tutorial here https://squidpy.readthedocs.io/en/stable/auto_tutorials/tutorial_visium_fluo.html. Am I going the right way?
Hi @Nasrine26,
regarding your questions:
- I would suggest to look at the segmented image (stored as an additional layer in the ImageContainer) and do a visual inspectino of the results, see this tutorial
- You can perform the segmentation on any image, so using
adata.uns['spatial'][library_id]['images']['hires']
is fine. - I believe that the described steps are reasonable - most importantly the results should help your analysis. If they do, that is great!
Hi @Charlottehero,
plase have a look at the previous post to evaluate segmentation quality. Bad results can be related to the data, do you think that the image quality might be an issue?
closing due to inactivity, feel free to reopen