- 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,
|
drift: bool = False,
|
||||||
file: Path | str = None,
|
file: Path | str = None,
|
||||||
bead_files: Sequence[Path | str] = (),
|
bead_files: Sequence[Path | str] = (),
|
||||||
|
main_channel: int = None,
|
||||||
|
default_transform: Sequence[float] = None,
|
||||||
) -> View:
|
) -> View:
|
||||||
"""returns a view where channels and/or frames are registered with an affine transformation
|
"""returns a view where channels and/or frames are registered with an affine transformation
|
||||||
channels: True/False register channels using bead_files
|
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
|
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,
|
bead_files: files used to register channels, default: files in self.path.parent,
|
||||||
with names starting with 'beads'
|
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()
|
view = self.view()
|
||||||
if file is None:
|
if file is None:
|
||||||
@@ -1278,7 +1285,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
try:
|
try:
|
||||||
view.transform = Transforms.from_file(file, T=drift)
|
view.transform = Transforms.from_file(file, T=drift)
|
||||||
except Exception: # noqa
|
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:
|
if drift:
|
||||||
view.transform = view.transform.with_drift(view)
|
view.transform = view.transform.with_drift(view)
|
||||||
view.transform.save(file.with_suffix(".yml"))
|
view.transform.save(file.with_suffix(".yml"))
|
||||||
|
|||||||
@@ -147,9 +147,11 @@ class Transforms(dict):
|
|||||||
else:
|
else:
|
||||||
raise TypeError("Not a pandas DataFrame or Series.")
|
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."
|
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()}:
|
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]
|
new_transforms = [transform[key] for transform in transforms if key in transform]
|
||||||
if len(new_transforms) == 1:
|
if len(new_transforms) == 1:
|
||||||
@@ -191,7 +193,7 @@ class Transforms(dict):
|
|||||||
return checked_files
|
return checked_files
|
||||||
|
|
||||||
@staticmethod
|
@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
|
"""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"""
|
in the horizontal direction"""
|
||||||
from . import Imread
|
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"]
|
untransformed = [c for c in range(im.shape["c"]) if cyllens[im.detector[c]].lower() == "none"]
|
||||||
|
|
||||||
good_and_untrans = sorted(set(goodch) & set(untransformed))
|
good_and_untrans = sorted(set(goodch) & set(untransformed))
|
||||||
if good_and_untrans:
|
if main_channel is None:
|
||||||
masterch = good_and_untrans[0]
|
if good_and_untrans:
|
||||||
else:
|
main_channel = good_and_untrans[0]
|
||||||
masterch = goodch[0]
|
else:
|
||||||
|
main_channel = goodch[0]
|
||||||
transform = Transform()
|
transform = Transform()
|
||||||
if not good_and_untrans:
|
if not good_and_untrans:
|
||||||
matrix = transform.matrix
|
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
|
transform.matrix = matrix
|
||||||
transforms = Transforms()
|
transforms = Transforms()
|
||||||
for c in tqdm(goodch, desc="Calculating channel transforms"): # noqa
|
for c in tqdm(goodch, desc="Calculating channel transforms"): # noqa
|
||||||
if c == masterch:
|
if c == main_channel:
|
||||||
transforms[im.channel_names[c]] = transform
|
transforms[im.channel_names[c]] = transform
|
||||||
else:
|
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
|
return transforms
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def save_channel_transform_tiff(bead_files, tiffile):
|
def save_channel_transform_tiff(bead_files, tiffile, default_transform=None):
|
||||||
from . import Imread
|
from . import Imread
|
||||||
|
|
||||||
n_channels = 0
|
n_channels = 0
|
||||||
@@ -232,7 +239,7 @@ class Transforms(dict):
|
|||||||
with IJTiffFile(tiffile) as tif:
|
with IJTiffFile(tiffile) as tif:
|
||||||
for t, file in enumerate(bead_files):
|
for t, file in enumerate(bead_files):
|
||||||
with Imread(file) as im:
|
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"]):
|
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)
|
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]
|
[project]
|
||||||
name = "ndbioimage"
|
name = "ndbioimage"
|
||||||
version = "2026.1.0"
|
version = "2026.1.1"
|
||||||
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