Repository: Project-MONAI/MONAI

Issue:
too many warning messages `inverse.py`
**Is your feature request related to a problem? Please describe.**
```
../monai/transforms/inverse.py:229: UserWarning: Applying transform Lambda to a MetaTensor with pending operations is not supported (as this eventually changes the ordering of applied_operations when the pending operations are executed). Please clear the pending operations before transform Lambda.
Pending operations: ['SpatialResample'].
```
![image](https://user-images.githubusercontent.com/831580/234196701-c8fa2221-6231-4803-a313-9a02db90208e.png)

cc @myron 


too many warning messages `inverse.py`
**Is your feature request related to a problem? Please describe.**
```
../monai/transforms/inverse.py:229: UserWarning: Applying transform Lambda to a MetaTensor with pending operations is not supported (as this eventually changes the ordering of applied_operations when the pending operations are executed). Please clear the pending operations before transform Lambda.
Pending operations: ['SpatialResample'].
```
![image](https://user-images.githubusercontent.com/831580/234196701-c8fa2221-6231-4803-a313-9a02db90208e.png)

cc @myron 




Discussion:

Resolving patch:
diff --git a/monai/transforms/inverse.py b/monai/transforms/inverse.py
--- a/monai/transforms/inverse.py
+++ b/monai/transforms/inverse.py
@@ -226,12 +226,18 @@ def track_transform_meta(
         else:
             if out_obj.pending_operations:
                 transform_name = info.get(TraceKeys.CLASS_NAME, "") if isinstance(info, dict) else ""
-                warnings.warn(
+                msg = (
                     f"Applying transform {transform_name} to a MetaTensor with pending operations "
                     "is not supported (as this eventually changes the ordering of applied_operations when the pending "
                     f"operations are executed). Please clear the pending operations before transform {transform_name}."
                     f"\nPending operations: {[x.get(TraceKeys.CLASS_NAME) for x in out_obj.pending_operations]}."
                 )
+                pend = out_obj.pending_operations[-1]
+                if not isinstance(pend.get(TraceKeys.EXTRA_INFO), dict):
+                    pend[TraceKeys.EXTRA_INFO] = dict(pend.get(TraceKeys.EXTRA_INFO, {}))
+                if not isinstance(info.get(TraceKeys.EXTRA_INFO), dict):
+                    info[TraceKeys.EXTRA_INFO] = dict(info.get(TraceKeys.EXTRA_INFO, {}))
+                info[TraceKeys.EXTRA_INFO]["warn"] = pend[TraceKeys.EXTRA_INFO]["warn"] = msg
             out_obj.push_applied_operation(info)
         if isinstance(data, Mapping):
             if not isinstance(data, dict):
@@ -255,6 +261,9 @@ def check_transforms_match(self, transform: Mapping) -> None:
         if xform_id == TraceKeys.NONE:
             return
         xform_name = transform.get(TraceKeys.CLASS_NAME, "")
+        warning_msg = transform.get(TraceKeys.EXTRA_INFO, {}).get("warn")
+        if warning_msg:
+            warnings.warn(warning_msg)
         # basic check if multiprocessing uses 'spawn' (objects get recreated so don't have same ID)
         if torch.multiprocessing.get_start_method() in ("spawn", None) and xform_name == self.__class__.__name__:
             return


Test patch:
diff --git a/tests/test_invert.py b/tests/test_invert.py
--- a/tests/test_invert.py
+++ b/tests/test_invert.py
@@ -24,6 +24,7 @@
     Compose,
     EnsureChannelFirst,
     Invert,
+    Lambda,
     LoadImage,
     Orientation,
     RandAffine,
@@ -88,6 +89,18 @@ def test_invert(self):
         self.assertTrue((reverted.size - n_good) < 300000, f"diff. {reverted.size - n_good}")
         set_determinism(seed=None)
 
+    def test_invert_warn_pending(self):
+        set_determinism(seed=0)
+        im_fname = make_nifti_image(create_test_image_3d(101, 100, 107, noise_max=100)[1])  # label image, discrete
+        transform = Compose(
+            [LoadImage(image_only=True), EnsureChannelFirst(), Orientation("RPS"), Lambda(func=lambda x: x)],
+            lazy_evaluation=True,
+        )
+        output = transform([im_fname for _ in range(2)])
+        with self.assertRaises(RuntimeError):  # transform id mismatch because of lambda
+            with self.assertWarns(Warning):  # warning of wrong ordering lazy + nonlazy_invertible
+                transform.inverse(output)
+
 
 if __name__ == "__main__":
     unittest.main()