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

FOV resolution check #391

Merged
merged 9 commits into from
Jul 19, 2023
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
46 changes: 46 additions & 0 deletions src/toffy/json_utils.py
camisowers marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import warnings

import pandas as pd
from alpineer import io_utils


Expand Down Expand Up @@ -194,3 +195,48 @@ def check_for_empty_files(bin_file_dir):

# return the list of fov names
return empty_json_files


def check_fov_resolutions(bin_file_dir, run_name, save_path=None):
"""Use the run metadata to calculate the resolution of each fov
Args:
bin_file_dir (str): directory containing the run json file
run_name (str): name of the run and corresponding run file
save_path (str): path to save data to, default None doesn't write data out

Returns:
pd.DataFrame: details fov names and corresponding resolution value
"""
# read in run metadata
run_file_path = os.path.join(bin_file_dir, run_name + ".json")
io_utils.validate_paths([run_file_path])
run_metadata = read_json_file(run_file_path, encoding="utf-8")

fov_names, custom_names, resolutions = [], [], []
for fov in run_metadata.get("fovs", ()):
# get fov names
fov_number = fov.get("runOrder")
default_name = f"fov-{fov_number}-scan-1"
custom_name = fov.get("name")
fov_names.append(default_name)
custom_names.append(custom_name)

# retrieve pixel and micron specs
fov_pixel_length = fov.get("frameSizePixels")["width"]
camisowers marked this conversation as resolved.
Show resolved Hide resolved
fov_micron_length = fov.get("fovSizeMicrons")

# calculate and save fov resolution per 400 microns
mult = 400 / fov_micron_length
pixels_adj = int(mult * fov_pixel_length)

# output values
print(f"{default_name} ({custom_name}): {pixels_adj} pixels x {400} microns")
resolutions.append(pixels_adj)

resolution_data = pd.DataFrame(
{"fov": fov_names, "name": custom_names, "pixels / 400 microns": resolutions}
)
if save_path:
resolution_data.to_csv(save_path, index=False)

return resolution_data
79 changes: 79 additions & 0 deletions templates/3f_check_resolutions.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "4857c47b-f476-4494-9a0d-742ef35c0a85",
"metadata": {},
"source": [
"# Check FOV Resolutions\n",
"This notebook will use the run file to check the image resolution for each FOV in the run. Consistent resolution level is important for downstream processing."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "353ffbc5-4784-49e1-9fd5-f1344d7892da",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from toffy.json_utils import check_fov_resolutions"
]
},
{
"cell_type": "markdown",
"id": "cd7ff391-2d75-4098-bd9d-4d98e07d45ba",
"metadata": {},
"source": [
"## Required variables\n",
"You will need to define the following argument for this notebook.\n",
" - `run_name` should contain the exact name of the MIBI run to extract from"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4b81ca96-e7dc-4603-87ce-284edeb2d423",
"metadata": {},
"outputs": [],
"source": [
"# set up args for current run\n",
"run_name = 'YYYY-MM-DD_run_name'\n",
"\n",
"bin_file_dir = os.path.join('D:\\\\Data', run_name)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b30a4058-4976-4bdc-9714-f9babe056d85",
"metadata": {},
"outputs": [],
"source": [
"# check resolutions \n",
"resolution_data = check_fov_resolutions(bin_file_dir, run_name, save_path=None)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "toffy_env",
"language": "python",
"name": "toffy_env"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
48 changes: 48 additions & 0 deletions tests/json_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,51 @@ def test_check_for_empty_files():
empty_files = json_utils.check_for_empty_files(temp_dir)

assert empty_files == ["empty_file"]


def test_check_fov_resolutions():
with tempfile.TemporaryDirectory() as temp_dir:
run_data = {
"fovs": [
{
"runOrder": 1,
"scanCount": 1,
"frameSizePixels": {"width": 32, "height": 32},
"fovSizeMicrons": 100,
},
{
"runOrder": 2,
"scanCount": 1,
"frameSizePixels": {"width": 32, "height": 32},
"fovSizeMicrons": 100,
},
{
"runOrder": 3,
"scanCount": 1,
"frameSizePixels": {"width": 16, "height": 16},
"fovSizeMicrons": 100,
},
],
}

json_utils.write_json_file(os.path.join(temp_dir, "test_run.json"), run_data)

# test successful resolution check
resolution_data = json_utils.check_fov_resolutions(
temp_dir, "test_run", save_path=os.path.join(temp_dir, "resolution_data.csv")
)

assert resolution_data.shape == (3, 3)
assert (
np.array(["fov-1-scan-1", "fov-2-scan-1", "fov-3-scan-1"]) == resolution_data["fov"]
).all()
assert (
resolution_data["pixels / 400 microns"].iloc[0]
== resolution_data["pixels / 400 microns"].iloc[1]
)
assert (
resolution_data["pixels / 400 microns"].iloc[0]
!= resolution_data["pixels / 400 microns"].iloc[2]
)

assert os.path.exists(os.path.join(temp_dir, "resolution_data.csv"))
Loading