- main_channel and default_transform arguments for Imread.with_transform
This commit is contained in:
@@ -1253,6 +1253,8 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
||||
drift: bool = False,
|
||||
file: Path | str = None,
|
||||
bead_files: Sequence[Path | str] = (),
|
||||
main_channel: int = None,
|
||||
default_transform: Sequence[float] = None,
|
||||
) -> View:
|
||||
"""returns a view where channels and/or frames are registered with an affine transformation
|
||||
channels: True/False register channels using bead_files
|
||||
@@ -1260,6 +1262,11 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
||||
file: load registration from file with name file, default: transform.yml in self.path.parent
|
||||
bead_files: files used to register channels, default: files in self.path.parent,
|
||||
with names starting with 'beads'
|
||||
main channel: which channel to transform with default_transform
|
||||
default_transform: parameters of the default transform: [a, b, c, d, e, f] where the affine transform matrix is
|
||||
| a b e |
|
||||
| c d f |
|
||||
| 0 0 1 |
|
||||
"""
|
||||
view = self.view()
|
||||
if file is None:
|
||||
@@ -1278,7 +1285,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
||||
try:
|
||||
view.transform = Transforms.from_file(file, T=drift)
|
||||
except Exception: # noqa
|
||||
view.transform = Transforms().with_beads(view.cyllens, bead_files)
|
||||
view.transform = Transforms().with_beads(view.cyllens, bead_files, main_channel, default_transform)
|
||||
if drift:
|
||||
view.transform = view.transform.with_drift(view)
|
||||
view.transform.save(file.with_suffix(".yml"))
|
||||
|
||||
@@ -147,9 +147,11 @@ class Transforms(dict):
|
||||
else:
|
||||
raise TypeError("Not a pandas DataFrame or Series.")
|
||||
|
||||
def with_beads(self, cyllens, bead_files):
|
||||
def with_beads(self, cyllens, bead_files, main_channel=None, default_transform=None):
|
||||
assert len(bead_files) > 0, "At least one file is needed to calculate the registration."
|
||||
transforms = [self.calculate_channel_transforms(file, cyllens) for file in bead_files]
|
||||
transforms = [
|
||||
self.calculate_channel_transforms(file, cyllens, main_channel, default_transform) for file in bead_files
|
||||
]
|
||||
for key in {key for transform in transforms for key in transform.keys()}:
|
||||
new_transforms = [transform[key] for transform in transforms if key in transform]
|
||||
if len(new_transforms) == 1:
|
||||
@@ -191,7 +193,7 @@ class Transforms(dict):
|
||||
return checked_files
|
||||
|
||||
@staticmethod
|
||||
def calculate_channel_transforms(bead_file, cyllens):
|
||||
def calculate_channel_transforms(bead_file, cyllens, main_channel=None, default_transform=None):
|
||||
"""When no channel is not transformed by a cylindrical lens, assume that the image is scaled by a factor 1.162
|
||||
in the horizontal direction"""
|
||||
from . import Imread
|
||||
@@ -204,25 +206,30 @@ class Transforms(dict):
|
||||
untransformed = [c for c in range(im.shape["c"]) if cyllens[im.detector[c]].lower() == "none"]
|
||||
|
||||
good_and_untrans = sorted(set(goodch) & set(untransformed))
|
||||
if good_and_untrans:
|
||||
masterch = good_and_untrans[0]
|
||||
else:
|
||||
masterch = goodch[0]
|
||||
if main_channel is None:
|
||||
if good_and_untrans:
|
||||
main_channel = good_and_untrans[0]
|
||||
else:
|
||||
main_channel = goodch[0]
|
||||
transform = Transform()
|
||||
if not good_and_untrans:
|
||||
matrix = transform.matrix
|
||||
matrix[0, 0] = 0.86
|
||||
if default_transform is None:
|
||||
matrix[0, 0] = 0.86
|
||||
else:
|
||||
for i, t in zip(([0, 0], [0, 1], [1, 0], [1, 1], [0, 2], [1, 2]), default_transform):
|
||||
matrix[i] = t
|
||||
transform.matrix = matrix
|
||||
transforms = Transforms()
|
||||
for c in tqdm(goodch, desc="Calculating channel transforms"): # noqa
|
||||
if c == masterch:
|
||||
if c == main_channel:
|
||||
transforms[im.channel_names[c]] = transform
|
||||
else:
|
||||
transforms[im.channel_names[c]] = Transform.register(max_ims[masterch], max_ims[c]) * transform
|
||||
transforms[im.channel_names[c]] = Transform.register(max_ims[main_channel], max_ims[c]) * transform
|
||||
return transforms
|
||||
|
||||
@staticmethod
|
||||
def save_channel_transform_tiff(bead_files, tiffile):
|
||||
def save_channel_transform_tiff(bead_files, tiffile, default_transform=None):
|
||||
from . import Imread
|
||||
|
||||
n_channels = 0
|
||||
@@ -232,7 +239,7 @@ class Transforms(dict):
|
||||
with IJTiffFile(tiffile) as tif:
|
||||
for t, file in enumerate(bead_files):
|
||||
with Imread(file) as im:
|
||||
with Imread(file).with_transform() as jm:
|
||||
with Imread(file).with_transform(default_transform=default_transform) as jm:
|
||||
for c in range(im.shape["c"]):
|
||||
tif.save(np.hstack((im(c=c, t=0).max("z"), jm(c=c, t=0).max("z"))), c, 0, t)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "ndbioimage"
|
||||
version = "2026.1.0"
|
||||
version = "2026.1.1"
|
||||
description = "Bio image reading, metadata and some affine registration."
|
||||
authors = [
|
||||
{ name = "W. Pomp", email = "w.pomp@nki.nl" }
|
||||
|
||||
Reference in New Issue
Block a user