Skip to content

Commit 031157a

Browse files
committed
merge main
2 parents 24a540f + 4df580d commit 031157a

File tree

3 files changed

+47
-73
lines changed

3 files changed

+47
-73
lines changed

.readthedocs.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Read the Docs configuration file
2+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3+
4+
# Required
5+
version: 2
6+
7+
# Set the OS, Python version, and other tools you might need
8+
build:
9+
os: ubuntu-24.04
10+
tools:
11+
python: "3.12"
12+
jobs:
13+
post_build:
14+
- python docs/scripts/fix_md_links.py
15+
16+
# Optionally, but recommended,
17+
# declare the Python requirements required to build your documentation
18+
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
19+
python:
20+
install:
21+
- method: pip
22+
path: .
23+
extra_requirements:
24+
- docs
25+
26+
# Build documentation in the "docs/" directory with Sphinx
27+
sphinx:
28+
configuration: docs/conf.py

viscy/utils/meta_utils.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
import iohub.ngff as ngff
88
import numpy as np
99
import pandas as pd
10-
from numpy.typing import NDArray
10+
import tensorstore
11+
from tqdm import tqdm
1112

12-
import viscy.utils.mp_utils as mp_utils
13-
from viscy.utils.cli_utils import show_progress_bar
13+
from viscy.utils.mp_utils import get_val_stats
1414

1515

1616
def write_meta_field(position: ngff.Position, metadata, field_name, subfield_name):
@@ -54,6 +54,21 @@ def write_meta_field(position: ngff.Position, metadata, field_name, subfield_nam
5454
position.zattrs[field_name] = field_metadata
5555

5656

57+
def _grid_sample(
58+
position: ngff.Position, grid_spacing: int, channel_index: int, num_workers: int
59+
):
60+
return (
61+
position["0"]
62+
.tensorstore(
63+
context=tensorstore.Context(
64+
{"data_copy_concurrency": {"limit": num_workers}}
65+
)
66+
)[:, channel_index, :, ::grid_spacing, ::grid_spacing]
67+
.read()
68+
.result()
69+
)
70+
71+
5772
def generate_normalization_metadata(
5873
zarr_dir: str | Path,
5974
num_workers: int = 4,
@@ -181,8 +196,7 @@ def generate_normalization_metadata(
181196
subfield_name=str(channel_id),
182197
)
183198

184-
print(f"Generated normalization metadata for {len(channel_ids)} channels")
185-
print(f"Dataset-level statistics: {final_dataset_stats}")
199+
plate.close()
186200

187201

188202
def compute_normalization_stats(

viscy/utils/mp_utils.py

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -323,71 +323,3 @@ def get_val_stats(sample_values: list[float]) -> dict[str, float]:
323323
"iqr": float(scipy.stats.iqr(sample_values)),
324324
}
325325
return meta_row
326-
327-
328-
def mp_sample_im_pixels(
329-
fn_args: list[tuple[Any, ...]], workers: int
330-
) -> list[list[Any]]:
331-
"""Read and compute statistics of images with multiprocessing.
332-
333-
Parameters
334-
----------
335-
fn_args : list[tuple[Any, ...]]
336-
List with tuples of function arguments.
337-
workers : int
338-
Max number of workers.
339-
340-
Returns
341-
-------
342-
list[list[Any]]
343-
List of paths and corresponding returned df from get_im_stats.
344-
"""
345-
with ProcessPoolExecutor(workers) as ex:
346-
# can't use map directly as it works only with single arg functions
347-
res = ex.map(sample_im_pixels, *zip(*fn_args))
348-
return list(map(list, zip(*list(res))))
349-
350-
351-
def sample_im_pixels(
352-
position: ngff.Position,
353-
grid_spacing: int,
354-
channel: int,
355-
) -> tuple[ngff.Position, NDArray]:
356-
# TODO move out of mp utils into normalization utils
357-
"""Read and compute statistics of images for each point in a grid.
358-
359-
Grid spacing determines distance in pixels between grid points
360-
for rows and cols. By default, samples from every time position and every z-depth,
361-
and assumes that the data in the zarr store is stored in [T,C,Z,Y,X] format,
362-
for time, channel, z, y, x.
363-
364-
Parameters
365-
----------
366-
position : ngff.Position
367-
NGFF position node object.
368-
grid_spacing : int
369-
Spacing of sampling grid in x and y.
370-
channel : int
371-
Channel to sample from.
372-
373-
Returns
374-
-------
375-
tuple[ngff.Position, NDArray]
376-
Position and array with intensity data for each grid point.
377-
"""
378-
image_zarr = position.data
379-
380-
all_sample_values = []
381-
all_time_indices = list(range(image_zarr.shape[0]))
382-
all_z_indices = list(range(image_zarr.shape[2]))
383-
384-
for time_index in all_time_indices:
385-
for z_index in all_z_indices:
386-
image_slice = image_zarr[time_index, channel, z_index, :, :]
387-
_, _, sample_values = image_utils.grid_sample_pixel_values(
388-
image_slice, grid_spacing
389-
)
390-
all_sample_values.append(sample_values)
391-
sample_values = np.stack(all_sample_values, 0).flatten()
392-
393-
return position, sample_values

0 commit comments

Comments
 (0)