Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## Version 0.0.6
- Added `read_tenx_visium()` function to load 10x Visium data as SpatialExperiment
- Added `combine_columns` function
- Implemented `__eq__` override for `SpatialImage` subclasses

Expand Down
8 changes: 6 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ install_requires =
biocframe>=0.6.1
biocutils>=0.2
summarizedexperiment>=0.5
singlecellexperiment>=0.5.6
singlecellexperiment>=0.5.7
pillow>=11.0
requests
scipy~=1.13
geopandas


Expand All @@ -67,12 +67,16 @@ exclude =
# Add here additional requirements for extra features, to install with:
# `pip install SpatialExperiment[PDF]` like:
# PDF = ReportLab; RXP
optional =
pandas
requests

# Add here test requirements (semicolon/line-separated)
testing =
setuptools
pytest
pytest-cov
%(optional)s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool, wish i knew we can do this


[options.entry_points]
# Add here console scripts like:
Expand Down
13 changes: 13 additions & 0 deletions src/spatialexperiment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
del version, PackageNotFoundError

from .ProxySFE import ProxySpatialFeatureExperiment
from .io import read_tenx_visium
from .SpatialExperiment import SpatialExperiment
from .SpatialImage import (
LoadedSpatialImage,
Expand All @@ -24,3 +25,15 @@
VirtualSpatialImage,
construct_spatial_image_class,
)

__all__ = [
"ProxySpatialFeatureExperiment",
"read_tenx_visium",
"SpatialExperiment",
"LoadedSpatialImage",
"RemoteSpatialImage",
"StoredSpatialImage",
"VirtualSpatialImage",
"construct_spatial_image_class",
]

83 changes: 82 additions & 1 deletion src/spatialexperiment/_imgutils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,91 @@
from typing import Union

import os
from io import BytesIO
from pathlib import Path
from urllib.parse import urlparse
from PIL import Image
from biocframe import BiocFrame
from .SpatialImage import construct_spatial_image_class

__author__ = "keviny2"
__copyright__ = "keviny2"
__license__ = "MIT"



def read_image(input_image):
"""Read image from PIL Image, file path, or URL.

Args:
input_image: PIL Image, string path to local file, or URL string.

Returns:
The loaded image.

Raises:
TypeError: If input is not PIL Image, path string, or URL string.
"""
import requests

if isinstance(input_image, Image.Image):
return input_image

if isinstance(input_image, (str, Path)):
is_url = urlparse(str(input_image)).scheme in ("http", "https", "ftp")
if is_url:
response = requests.get(input_image)
return Image.open(BytesIO(response.content))
else:
return Image.open(input_image)

raise TypeError(f"Expected PIL Image, path, or URL. Got {type(input_image)}")


def get_img_data(
img: Union[str, os.PathLike],
scale_factor: str,
sample_id: str,
image_id: str,
load: bool = True
) -> BiocFrame:
"""
Construct an image data dataframe.

Args:
img:
A path or url to the image file.

scale_factor:
The scale factor associated with the image.

sample_id:
A unique identifier for the sample to which the image belongs.

image_id:
A unique identifier for the image itself.

load:
A boolean specifying whether the image(s) should be loaded into memory? If False, will store the path/URL instead.
Defaults to `True`.

Returns:
The image data.
"""
if load:
img = read_image(img)

spi = construct_spatial_image_class(img)
return BiocFrame(
{
"sample_id": [sample_id],
"image_id": [image_id],
"data": [spi],
"scale_factor": [scale_factor]
}
)


def retrieve_rows_by_id(
img_data: BiocFrame,
sample_id: Union[str, bool, None] = None,
Expand All @@ -16,7 +95,9 @@ def retrieve_rows_by_id(
Retrieve rows from `img_data` based on specified `sample_id` and `image_id`.

Args:
img_data: The data from which to retrieve rows.
img_data:
The data from which to retrieve rows.

sample_id:
- `sample_id=True`: Matches all samples.
- `sample_id=None`: Matches the first sample.
Expand Down
4 changes: 2 additions & 2 deletions src/spatialexperiment/_initutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from biocframe import BiocFrame
from PIL import Image
from SpatialImage import SpatialImage
from .SpatialImage import construct_spatial_image_class
from summarizedexperiment._frameutils import _sanitize_frame

__author__ = "keviny2"
Expand Down Expand Up @@ -96,7 +96,7 @@ def construct_img_data(
spis = []
for image_source in image_sources:
result = Image.open(image_source) if load_image else image_source
spi = SpatialImage(result)
spi = construct_spatial_image_class(result)
spis.append(spi)

img_data = {
Expand Down
4 changes: 4 additions & 0 deletions src/spatialexperiment/io/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .tenx_visium import read_tenx_visium

__all__ = ["read_tenx_visium"]

Loading