def test_transforms(self): key = "im" _, im = self.get_im() tr = Compose([ToMetaTensord(key), BorderPadd(key, 1), DivisiblePadd(key, 16), FromMetaTensord(key)]) num_tr = len(tr.transforms) data = {key: im, PostFix.meta(key): {"affine": torch.eye(4)}} # apply one at a time for i, _tr in enumerate(tr.transforms): data = _tr(data) is_meta = isinstance(_tr, (ToMetaTensord, BorderPadd, DivisiblePadd)) if is_meta: self.assertEqual(len(data), 1 if not config.USE_META_DICT else 2) # im, im_transforms, compatibility self.assertIsInstance(data[key], MetaTensor) n_applied = len(data[key].applied_operations) else: self.assertEqual(len(data), 3) # im, im_meta_dict, im_transforms self.assertIsInstance(data[key], torch.Tensor) self.assertNotIsInstance(data[key], MetaTensor) n_applied = len(data[PostFix.transforms(key)]) self.assertEqual(n_applied, i + 1) # inverse one at a time for i, _tr in enumerate(tr.transforms[::-1]): data = _tr.inverse(data) is_meta = isinstance(_tr, (FromMetaTensord, BorderPadd, DivisiblePadd)) if is_meta: self.assertEqual(len(data), 1) # im self.assertIsInstance(data[key], MetaTensor) n_applied = len(data[key].applied_operations) else: self.assertEqual(len(data), 3) # im, im_meta_dict, im_transforms self.assertIsInstance(data[key], torch.Tensor) self.assertNotIsInstance(data[key], MetaTensor) n_applied = len(data[PostFix.transforms(key)]) self.assertEqual(n_applied, num_tr - i - 1) # apply all in one go data = tr({key: im, PostFix.meta(key): {"affine": torch.eye(4)}}) self.assertEqual(len(data), 3) # im, im_meta_dict, im_transforms self.assertIsInstance(data[key], torch.Tensor) self.assertNotIsInstance(data[key], MetaTensor) n_applied = len(data[PostFix.transforms(key)]) self.assertEqual(n_applied, num_tr) # inverse all in one go data = tr.inverse(data) self.assertEqual(len(data), 3) # im, im_meta_dict, im_transforms self.assertIsInstance(data[key], torch.Tensor) self.assertNotIsInstance(data[key], MetaTensor) n_applied = len(data[PostFix.transforms(key)]) self.assertEqual(n_applied, 0)
def __call__( self, data: Mapping[Hashable, NdarrayOrTensor] ) -> Dict[Hashable, NdarrayOrTensor]: d = dict(data) for key in self.key_iterator(d): self.push_transform(d, key) im = d[key] meta = d.pop(PostFix.meta(key), None) transforms = d.pop(PostFix.transforms(key), None) im = MetaTensor(im, meta=meta, applied_operations=transforms) # type: ignore d[key] = im return d
def inverse( self, data: Mapping[Hashable, NdarrayOrTensor] ) -> Dict[Hashable, NdarrayOrTensor]: d = dict(data) for key in self.key_iterator(d): # check transform _ = self.get_most_recent_transform(d, key) # do the inverse im = d[key] meta = d.pop(PostFix.meta(key), None) transforms = d.pop(PostFix.transforms(key), None) im = MetaTensor(im, meta=meta, applied_operations=transforms) # type: ignore d[key] = im # Remove the applied transform self.pop_transform(d, key) return d
def as_dict(self, key: str) -> dict: """ Get the object as a dictionary for backwards compatibility. This method makes a copy of the objects. Args: key: Base key to store main data. The key for the metadata will be determined using `PostFix.meta`. Return: A dictionary consisting of two keys, the main data (stored under `key`) and the metadata. """ return { key: self.as_tensor().clone().detach(), PostFix.meta(key): deepcopy(self.meta), PostFix.transforms(key): deepcopy(self.applied_operations), }
def as_dict(self, key: str, output_type=torch.Tensor, dtype=None) -> dict: """ Get the object as a dictionary for backwards compatibility. This method does not make a deep copy of the objects. Args: key: Base key to store main data. The key for the metadata will be determined using `PostFix`. output_type: `torch.Tensor` or `np.ndarray` for the main data. dtype: dtype of output data. Converted to correct library type (e.g., `np.float32` is converted to `torch.float32` if output type is `torch.Tensor`). If left blank, it remains unchanged. Return: A dictionary consisting of three keys, the main data (stored under `key`) and the metadata. """ if output_type not in (torch.Tensor, np.ndarray): raise ValueError( f"output_type must be torch.Tensor or np.ndarray, got {output_type}." ) return { key: self.get_array(output_type=output_type, dtype=dtype), PostFix.meta(key): self.meta, PostFix.transforms(key): self.applied_operations, }
def test_from_to_meta_tensord(self, device, dtype): m1 = self.get_im(device=device, dtype=dtype) m2 = self.get_im(device=device, dtype=dtype) m3 = self.get_im(device=device, dtype=dtype) d_metas = {"m1": m1, "m2": m2, "m3": m3} m1_meta = {k: v for k, v in m1.meta.items() if k != "affine"} m1_aff = m1.affine # FROM -> forward t_from_meta = FromMetaTensord(["m1", "m2"]) d_dict = t_from_meta(d_metas) self.assertEqual( sorted(d_dict.keys()), [ "m1", PostFix.meta("m1"), PostFix.transforms("m1"), "m2", PostFix.meta("m2"), PostFix.transforms("m2"), "m3", ], ) self.check(d_dict["m3"], m3, ids=True) # unchanged self.check(d_dict["m1"], m1.as_tensor(), ids=False) meta_out = { k: v for k, v in d_dict["m1_meta_dict"].items() if k != "affine" } aff_out = d_dict["m1_meta_dict"]["affine"] self.check(aff_out, m1_aff, ids=True) self.assertEqual(meta_out, m1_meta) # FROM -> inverse d_meta_dict_meta = t_from_meta.inverse(d_dict) self.assertEqual(sorted(d_meta_dict_meta.keys()), [ "m1", PostFix.transforms("m1"), "m2", PostFix.transforms("m2"), "m3" ]) self.check(d_meta_dict_meta["m3"], m3, ids=False) # unchanged (except deep copy in inverse) self.check(d_meta_dict_meta["m1"], m1, ids=False) meta_out = { k: v for k, v in d_meta_dict_meta["m1"].meta.items() if k != "affine" } aff_out = d_meta_dict_meta["m1"].affine self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta) # TO -> Forward t_to_meta = ToMetaTensord(["m1", "m2"]) del d_dict["m1_transforms"] del d_dict["m2_transforms"] d_dict_meta = t_to_meta(d_dict) self.assertEqual(sorted(d_dict_meta.keys()), [ "m1", PostFix.transforms("m1"), "m2", PostFix.transforms("m2"), "m3" ]) self.check(d_dict_meta["m3"], m3, ids=True) # unchanged (except deep copy in inverse) self.check(d_dict_meta["m1"], m1, ids=False) meta_out = { k: v for k, v in d_dict_meta["m1"].meta.items() if k != "affine" } aff_out = d_dict_meta["m1"].meta["affine"] self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta) # TO -> Inverse d_dict_meta_dict = t_to_meta.inverse(d_dict_meta) self.assertEqual( sorted(d_dict_meta_dict.keys()), [ "m1", PostFix.meta("m1"), PostFix.transforms("m1"), "m2", PostFix.meta("m2"), PostFix.transforms("m2"), "m3", ], ) self.check(d_dict_meta_dict["m3"], m3.as_tensor(), ids=False) # unchanged (except deep copy in inverse) self.check(d_dict_meta_dict["m1"], m1.as_tensor(), ids=False) meta_out = { k: v for k, v in d_dict_meta_dict["m1_meta_dict"].items() if k != "affine" } aff_out = d_dict_meta_dict["m1_meta_dict"]["affine"] self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta)
def test_from_to_meta_tensord(self, device, dtype, data_type="tensor"): m1 = self.get_im(device=device, dtype=dtype) m2 = self.get_im(device=device, dtype=dtype) m3 = self.get_im(device=device, dtype=dtype) d_metas = {"m1": m1, "m2": m2, "m3": m3} m1_meta = {k: v for k, v in m1.meta.items() if k != "affine"} m1_aff = m1.affine # FROM -> forward t_from_meta = FromMetaTensord(["m1", "m2"], data_type=data_type) d_dict = t_from_meta(d_metas) self.assertEqual( sorted(d_dict.keys()), [ "m1", PostFix.meta("m1"), PostFix.transforms("m1"), "m2", PostFix.meta("m2"), PostFix.transforms("m2"), "m3", ], ) self.check(d_dict["m3"], m3, ids=True) # unchanged if data_type == "tensor": self.check(d_dict["m1"], m1.as_tensor(), ids=False) else: self.assertIsInstance(d_dict["m1"], np.ndarray) meta_out = { k: v for k, v in d_dict["m1_meta_dict"].items() if k != "affine" } aff_out = d_dict["m1_meta_dict"]["affine"] self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta) # FROM -> inverse d_meta_dict_meta = t_from_meta.inverse(d_dict) self.assertEqual(sorted(d_meta_dict_meta.keys()), ["m1", "m2", "m3"]) if data_type == "numpy": m1, m1_aff = m1.cpu(), m1_aff.cpu() self.check(d_meta_dict_meta["m1"], m1, ids=False) meta_out = { k: v for k, v in d_meta_dict_meta["m1"].meta.items() if k != "affine" } aff_out = d_meta_dict_meta["m1"].affine self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta) # TO -> Forward t_to_meta = ToMetaTensord(["m1", "m2"]) d_dict_meta = t_to_meta(d_dict) self.assertEqual(sorted(d_dict_meta.keys()), ["m1", "m2", "m3"], f"flag: {config.USE_META_DICT}") self.check(d_dict_meta["m3"], m3, ids=True) # unchanged (except deep copy in inverse) self.check(d_dict_meta["m1"], m1, ids=False) meta_out = { k: v for k, v in d_dict_meta["m1"].meta.items() if k != "affine" } aff_out = d_dict_meta["m1"].meta["affine"] self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta) # TO -> Inverse d_dict_meta_dict = t_to_meta.inverse(d_dict_meta) self.assertEqual( sorted(d_dict_meta_dict.keys()), [ "m1", PostFix.meta("m1"), PostFix.transforms("m1"), "m2", PostFix.meta("m2"), PostFix.transforms("m2"), "m3", ], ) self.check(d_dict_meta_dict["m3"], m3.as_tensor(), ids=False) # unchanged (except deep copy in inverse) self.check(d_dict_meta_dict["m1"], m1.as_tensor(), ids=False) meta_out = { k: v for k, v in d_dict_meta_dict["m1_meta_dict"].items() if k != "affine" } aff_out = d_dict_meta_dict["m1_meta_dict"]["affine"] self.check(aff_out, m1_aff, ids=False) self.assertEqual(meta_out, m1_meta)