Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utilize TSAI tiler to crop out FOVs #20

Merged
merged 28 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
19bdb99
Add internal functionality for segmenting out glycan cores
alex-l-kong Nov 16, 2023
f4b33cf
Format using pre-commit hooks
alex-l-kong Nov 17, 2023
2f98ec5
Include core cropping process in Jupyter notebook, and update glycan …
alex-l-kong Nov 17, 2023
d863f9a
Add commented line that user can run to crop out all cores on a TMA s…
alex-l-kong Nov 20, 2023
388e623
Add functionality to visualize the cropping mask after completion
alex-l-kong Nov 20, 2023
897dda9
Change cores_to_crop to include names that are more TSAI-friendly
alex-l-kong Nov 20, 2023
3e7d11d
PYCODESTYLE and add test in case certain cores don't map onto the poslog
alex-l-kong Nov 21, 2023
2c0ca43
Ensure line length is 100 like the other angelolab repos (not 110)
alex-l-kong Nov 21, 2023
6fe1ca5
Use rng fixture to generate random nums
alex-l-kong Nov 21, 2023
6cc4909
Simplify cropping logic for all cores, allow user to set cores_to_cro…
alex-l-kong Nov 21, 2023
9d8a6a6
Only read in the columns we need for region_core_info
alex-l-kong Nov 21, 2023
55ee0af
Update core cropping process to include mask generation prior
alex-l-kong Nov 27, 2023
765fd30
The TSAI tiler, unfortunately, does not support .tiff files
alex-l-kong Nov 28, 2023
a505f33
Add type annotations
alex-l-kong Nov 28, 2023
ba0052f
Update core cropping functionality to support a list of poslog files
alex-l-kong Nov 29, 2023
b2970cc
Ensure regex is R(\d+)X, not R(\d+)XY
alex-l-kong Nov 29, 2023
d32b133
Pre-generate all the individual crop masks, then load in as necessary
alex-l-kong Dec 5, 2023
2058c9e
Update the notebook with the new pre-generated mask workflow
alex-l-kong Dec 5, 2023
9ec12a9
Ensure masks are of dtype np.uint32
alex-l-kong Jan 17, 2024
bf8c32f
Ensure glycan_crop_save_dir is set as a pathlib.Path
alex-l-kong Jan 17, 2024
83e5fc6
Change from np.uint32 to np.uint8
alex-l-kong Jan 18, 2024
4baab51
Fix path specification for load_glycan_crop_masks
alex-l-kong Jan 23, 2024
0f916c3
Add core-cropping notebook (will be renamed)
alex-l-kong May 15, 2024
0cf5173
Don't include full metadata
alex-l-kong May 17, 2024
7d487f9
Add templates.json file for TSAI tiler
alex-l-kong May 17, 2024
4a6ad62
Document where to find the template.json file for TSAI tiler
alex-l-kong May 17, 2024
7540686
Map to closest core in case centroid in mapping dict was "missed" by …
alex-l-kong Aug 29, 2024
664d01b
Fix remaining tests
alex-l-kong Nov 11, 2024
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
116 changes: 114 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""Shared Fixtures for tests."""

import json
import os
from pathlib import Path
from typing import Generator
from typing import Generator, List

import numpy as np
import pandas as pd
import pytest
import skimage.io as io
import xarray as xr
from pyimzml.ImzMLParser import ImzMLParser
from pyimzml.ImzMLWriter import ImzMLWriter
Expand All @@ -26,7 +29,8 @@ def imz_data(tmp_path_factory: TempPathFactory, rng: np.random.Generator) -> Imz
img_dim: int = 10

# Generate random integers n for each coordinate (10 x 10). These will be used for creating
# random m/z and intensity values of length n. Lengths n are distributed along the standard gamma.
# random m/z and intensity values of length n.
# Lengths n are distributed along the standard gamma.
ns: np.ndarray = np.rint(rng.standard_gamma(shape=2.5, size=(img_dim**2)) * 100).astype(int)

# Generate random masses and sample different amounts of them, so we get duplicates
Expand Down Expand Up @@ -114,3 +118,111 @@ def image_xr(rng: np.random.Generator, library: pd.DataFrame) -> Generator[xr.Da
dims=["peak", "x", "y"],
)
yield img_xr


@pytest.fixture(scope="session")
def glycan_img_path(
tmp_path_factory: TempPathFactory, imz_data: ImzMLParser, rng: np.random.Generator
) -> Generator[Path, None, None]:
coords: np.ndarray = np.array([coord[:2] for coord in imz_data.coordinates])

glycan_img: np.ndarray = np.zeros((10, 10))
glycan_img[coords[:, 1] - 1, coords[:, 0] - 1] = rng.random(coords.shape[0])

glycan_img_file: Path = tmp_path_factory.mktemp("glycan_imgs") / "glycan_img.tiff"
io.imsave(glycan_img_file, glycan_img)

yield glycan_img_file


@pytest.fixture(scope="session")
def poslog_dir(
tmp_path_factory: TempPathFactory, imz_data: ImzMLParser, rng: np.random.Generator
) -> Generator[Path, None, None]:
columns_write: List[str] = ["Date", "Time", "Region", "PosX", "PosY", "X", "Y", "Z"]
poslog_base_dir: Path = tmp_path_factory.mktemp("poslogs")

for i in np.arange(2):
poslog_data: pd.DataFrame = pd.DataFrame(
rng.random(size=(int(len(imz_data.coordinates) / 2) + 2, len(columns_write))),
columns=columns_write,
)

poslog_regions: List[str] = []
for j in np.arange(2):
poslog_regions.append("__")
poslog_regions.extend([f"R{j}XY"] * 25)
poslog_data["Region"] = poslog_regions

poslog_file: Path = poslog_base_dir / f"poslog{i}.txt"
poslog_data.to_csv(poslog_file, header=None, index=False, sep=" ", mode="w", columns=columns_write)

yield poslog_base_dir


@pytest.fixture(scope="session")
def centroid_path(tmp_path_factory: TempPathFactory, imz_data: ImzMLParser) -> Generator[Path, None, None]:
coords: np.ndarray = np.array([coord[:2] for coord in imz_data.coordinates])
center_coord_indices: np.ndarray = np.arange(10, coords.shape[0], 25)

centroid_data: dict = {}
centroid_data["exportDateTime"] = None
centroid_data["fovs"] = []
for i, cci in enumerate(center_coord_indices):
center_coord = coords[cci, :]
center_point_data = {
"name": f"Region{i}",
"centerPointPixels": {"x": center_coord[0].item(), "y": center_coord[1].item()},
}
centroid_data["fovs"].append(center_point_data)

centroid_file: Path = tmp_path_factory.mktemp("centroids") / "centroids.json"
with open(centroid_file, "w") as outfile:
outfile.write(json.dumps(centroid_data))

yield centroid_file


@pytest.fixture(scope="session")
def bad_centroid_path(
tmp_path_factory: TempPathFactory, imz_data: ImzMLParser
) -> Generator[Path, None, None]:
coords: np.ndarray = np.array([coord[:2] for coord in imz_data.coordinates])
center_coord_indices: np.ndarray = np.arange(10, coords.shape[0], 25)

centroid_data: dict = {}
centroid_data["exportDateTime"] = None
centroid_data["fovs"] = []
for i, cci in enumerate(center_coord_indices):
center_coord = coords[cci, :]
center_point_data = {
"name": f"Region{i}",
"centerPointPixels": {"x": center_coord[0].item() + 10000, "y": center_coord[1].item() + 10000},
}
centroid_data["fovs"].append(center_point_data)

centroid_file: Path = tmp_path_factory.mktemp("centroids") / "centroids.json"
with open(centroid_file, "w") as outfile:
outfile.write(json.dumps(centroid_data))

yield centroid_file


@pytest.fixture(scope="session")
def region_core_info(imz_data: ImzMLParser, centroid_path: Path, poslog_dir: Path) -> pd.DataFrame:
poslog_paths: List[Path] = [poslog_dir / pf for pf in os.listdir(poslog_dir)]
region_core_info: pd.DataFrame = extraction.map_coordinates_to_core_name(
imz_data, centroid_path, poslog_paths
)

yield region_core_info


@pytest.fixture(scope="session")
def glycan_crop_save_dir(
tmp_path_factory: TempPathFactory, glycan_img_path: Path, region_core_info: pd.DataFrame
) -> Generator[Path, None, None]:
glycan_crop_save_dir: Path = tmp_path_factory.mktemp("glycan_crops")
extraction.generate_glycan_crop_masks(glycan_img_path, region_core_info, glycan_crop_save_dir)

yield glycan_crop_save_dir
12 changes: 12 additions & 0 deletions files/template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"exportDateTime": "2023-08-02T16:55:21.610Z",
"fovs": [
{
"name": "Template",
"centerPointPixels": {
"x": 88,
"y": 88
}
}
]
}
Loading
Loading