- add option to skip autoscaling brightness when saving as mp4
- let coords_pandas also deal with polars dataframes
This commit is contained in:
@@ -418,7 +418,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
)
|
)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def __getstate__(self) -> dict[str:Any]:
|
def __getstate__(self) -> dict[str, Any]:
|
||||||
return {key: value for key, value in self.__dict__.items() if key not in self.do_not_pickle} | {
|
return {key: value for key, value in self.__dict__.items() if key not in self.do_not_pickle} | {
|
||||||
"cache_size": self.cache.maxlen
|
"cache_size": self.cache.maxlen
|
||||||
}
|
}
|
||||||
@@ -1100,6 +1100,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
t: str | int | Sequence[int] = None, # noqa
|
t: str | int | Sequence[int] = None, # noqa
|
||||||
colors: tuple[str] = None,
|
colors: tuple[str] = None,
|
||||||
brightnesses: tuple[float] = None,
|
brightnesses: tuple[float] = None,
|
||||||
|
no_scale_movie_brightnesses: bool = False,
|
||||||
scale: int = None,
|
scale: int = None,
|
||||||
bar: bool = True,
|
bar: bool = True,
|
||||||
speed: float = None,
|
speed: float = None,
|
||||||
@@ -1133,9 +1134,20 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
frame = np.dstack([255 * frame * i for i in color])
|
frame = np.dstack([255 * frame * i for i in color])
|
||||||
return np.clip(np.round(frame), 0, 255).astype("uint8")
|
return np.clip(np.round(frame), 0, 255).astype("uint8")
|
||||||
|
|
||||||
ab = list(zip(*[get_ab(i) for i in self.transpose("cztyx")])) # type: ignore
|
if no_scale_movie_brightnesses and self.dtype.kind != "f":
|
||||||
|
info = np.iinfo(self.dtype)
|
||||||
|
ab = list(zip(*[(info.min, info.max) for _ in range(self.shape["c"])]))
|
||||||
|
elif no_scale_movie_brightnesses:
|
||||||
|
ab = list(zip(*[(0, 1) for _ in range(self.shape["c"])]))
|
||||||
|
else:
|
||||||
|
ab = list(zip(*[get_ab(i) for i in self.transpose("cztyx")])) # type: ignore
|
||||||
colors = colors or ("r", "g", "b")[: self.shape["c"]] + max(0, self.shape["c"] - 3) * ("w",)
|
colors = colors or ("r", "g", "b")[: self.shape["c"]] + max(0, self.shape["c"] - 3) * ("w",)
|
||||||
brightnesses = brightnesses or (1,) * self.shape["c"]
|
if brightnesses is None:
|
||||||
|
brightnesses = (1,) * self.shape["c"]
|
||||||
|
elif len(brightnesses) == 1:
|
||||||
|
brightnesses = brightnesses * self.shape["c"]
|
||||||
|
elif len(brightnesses) != self.shape["c"]:
|
||||||
|
raise ValueError("brightnesses must have same length as shape[c]")
|
||||||
scale = scale or 1
|
scale = scale or 1
|
||||||
shape_x = 2 * ((self.shape["x"] * scale + 1) // 2)
|
shape_x = 2 * ((self.shape["x"] * scale + 1) // 2)
|
||||||
shape_y = 2 * ((self.shape["y"] * scale + 1) // 2)
|
shape_y = 2 * ((self.shape["y"] * scale + 1) // 2)
|
||||||
@@ -1538,6 +1550,13 @@ def main() -> None:
|
|||||||
parser.add_argument("-C", "--movie-colors", help="colors for channels in movie", type=str, nargs="*")
|
parser.add_argument("-C", "--movie-colors", help="colors for channels in movie", type=str, nargs="*")
|
||||||
parser.add_argument("-V", "--movie_speed", help="speed of move, default = 25 / 7", type=float, default=None)
|
parser.add_argument("-V", "--movie_speed", help="speed of move, default = 25 / 7", type=float, default=None)
|
||||||
parser.add_argument("-B", "--movie-brightnesses", help="scale brightness of each channel", type=float, nargs="*")
|
parser.add_argument("-B", "--movie-brightnesses", help="scale brightness of each channel", type=float, nargs="*")
|
||||||
|
parser.add_argument(
|
||||||
|
"-N",
|
||||||
|
"--no-scale-movie-brightnesses",
|
||||||
|
help="do not scale brightness of each channel,"
|
||||||
|
" if image file has an integer data type it's range will be scaled to [0, 1]",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
parser.add_argument("-S", "--movie-scale", help="upscale movie xy size, int", type=float)
|
parser.add_argument("-S", "--movie-scale", help="upscale movie xy size, int", type=float)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -1559,6 +1578,7 @@ def main() -> None:
|
|||||||
args.time,
|
args.time,
|
||||||
args.movie_colors,
|
args.movie_colors,
|
||||||
args.movie_brightnesses,
|
args.movie_brightnesses,
|
||||||
|
args.no_scale_movie_brightnesses,
|
||||||
args.movie_scale,
|
args.movie_scale,
|
||||||
bar=len(args.file) == 1,
|
bar=len(args.file) == 1,
|
||||||
speed=args.movie_speed,
|
speed=args.movie_speed,
|
||||||
|
|||||||
@@ -16,9 +16,14 @@ except ImportError:
|
|||||||
sitk = None
|
sitk = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from pandas import DataFrame, Series, concat
|
import pandas as pd
|
||||||
except ImportError:
|
except ImportError:
|
||||||
DataFrame, Series, concat = None, None, None
|
pd = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import polars as pl
|
||||||
|
except ImportError:
|
||||||
|
pl = None
|
||||||
|
|
||||||
|
|
||||||
if hasattr(yaml, "full_load"):
|
if hasattr(yaml, "full_load"):
|
||||||
@@ -126,9 +131,13 @@ class Transforms(dict):
|
|||||||
return inverse
|
return inverse
|
||||||
|
|
||||||
def coords_pandas(self, array, channel_names, columns=None):
|
def coords_pandas(self, array, channel_names, columns=None):
|
||||||
if isinstance(array, DataFrame):
|
if pd is None:
|
||||||
return concat([self.coords_pandas(row, channel_names, columns) for _, row in array.iterrows()], axis=1).T
|
raise ImportError("pandas is not available")
|
||||||
elif isinstance(array, Series):
|
if isinstance(array, pd.DataFrame):
|
||||||
|
return pd.concat(
|
||||||
|
[self.coords_pandas(row, channel_names, columns) for _, row in array.iterrows()], axis=1
|
||||||
|
).T
|
||||||
|
elif isinstance(array, pd.Series):
|
||||||
key = []
|
key = []
|
||||||
if "C" in array:
|
if "C" in array:
|
||||||
key.append(channel_names[int(array["C"])])
|
key.append(channel_names[int(array["C"])])
|
||||||
@@ -459,14 +468,21 @@ class Transform:
|
|||||||
"""
|
"""
|
||||||
if self.is_unity():
|
if self.is_unity():
|
||||||
return array.copy()
|
return array.copy()
|
||||||
elif DataFrame is not None and isinstance(array, (DataFrame, Series)):
|
elif pd is not None and isinstance(array, (pd.DataFrame, pd.Series)):
|
||||||
columns = columns or ["x", "y"]
|
columns = columns or ["x", "y"]
|
||||||
array = array.copy()
|
array = array.copy()
|
||||||
if isinstance(array, DataFrame):
|
if isinstance(array, pd.DataFrame):
|
||||||
array[columns] = self.coords(np.atleast_2d(array[columns].to_numpy()))
|
array[columns] = self.coords(np.atleast_2d(array[columns].to_numpy()))
|
||||||
elif isinstance(array, Series):
|
elif isinstance(array, pd.Series):
|
||||||
array[columns] = self.coords(np.atleast_2d(array[columns].to_numpy()))[0]
|
array[columns] = self.coords(np.atleast_2d(array[columns].to_numpy()))[0]
|
||||||
return array
|
return array
|
||||||
|
elif pl is not None and isinstance(array, (pl.DataFrame, pl.LazyFrame)):
|
||||||
|
columns = columns or ["x", "y"]
|
||||||
|
if isinstance(array, pl.DataFrame):
|
||||||
|
xy = self.coords(np.atleast_2d(array.select(columns).to_numpy()))
|
||||||
|
elif isinstance(array, pl.LazyFrame):
|
||||||
|
xy = self.coords(np.atleast_2d(array.select(columns).collect().to_numpy()))
|
||||||
|
return array.with_columns(**{c: i for c, i in zip(columns, xy.T)})
|
||||||
else: # somehow we need to use the inverse here to get the same effect as when using self.frame
|
else: # somehow we need to use the inverse here to get the same effect as when using self.frame
|
||||||
return np.array([self.inverse.transform.TransformPoint(i.tolist()) for i in np.asarray(array)])
|
return np.array([self.inverse.transform.TransformPoint(i.tolist()) for i in np.asarray(array)])
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "ndbioimage"
|
name = "ndbioimage"
|
||||||
version = "2025.8.0"
|
version = "2025.9.0"
|
||||||
description = "Bio image reading, metadata and some affine registration."
|
description = "Bio image reading, metadata and some affine registration."
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "W. Pomp", email = "w.pomp@nki.nl" }
|
{ name = "W. Pomp", email = "w.pomp@nki.nl" }
|
||||||
|
|||||||
Reference in New Issue
Block a user