U Ph:I@sddlmZddlZddlmZmZddlmZddlm Z ddl Z ddl m Z ddl mZmZddlmZdd lmZdd lmZdd lmZdd lmZmZmZmZmZmZmZdd l m!Z!ddgZ"GdddeZ#Gddde#eZ$dS)) annotationsN)HashableMapping)contextmanager)Any) transforms)MetaObjget_track_meta) MetaTensor) to_affine_nd)InvertibleTrait) Transform)LazyAttrMetaKeys TraceKeysTraceStatusKeysconvert_to_dst_typeconvert_to_numpyconvert_to_tensor) MONAIEnvVarsTraceableTransformInvertibleTransformc@seZdZdZedkZdddddZed)d d d d Z ed dZ ddddZ ddZ e d*d dddddZdddddZd+d ddd d!d"Zd,d dd#d$d%Zedd&d'd(ZdS)-ra% Maintains a stack of applied transforms to data. Data can be one of two types: 1. A `MetaTensor` (this is the preferred data type). 2. A dictionary of data containing arrays/tensors and auxiliary metadata. In this case, a key must be supplied (this dictionary-based approach is deprecated). If `data` is of type `MetaTensor`, then the applied transform will be added to ``data.applied_operations``. If `data` is a dictionary, then one of two things can happen: 1. If data[key] is a `MetaTensor`, the applied transform will be added to ``data[key].applied_operations``. 2. Else, the applied transform will be appended to an adjacent list using `trace_key`. If, for example, the key is `image`, then the transform will be appended to `image_transforms` (this dictionary-based approach is deprecated). Hopefully it is clear that there are three total possibilities: 1. data is `MetaTensor` 2. data is dictionary, data[key] is `MetaTensor` 3. data is dictionary, data[key] is not `MetaTensor` (this is a deprecated approach). The ``__call__`` method of this transform class must be implemented so that the transformation information is stored during the data transformation. The information in the stack of applied transforms must be compatible with the default collate, by only storing strings, numbers and arrays. `tracing` could be enabled by `self.set_tracing` or setting `MONAI_TRACE_TRANSFORM` when initializing the class. 0boolNone)tracingreturncCs ||_dS)z Set whether to trace transforms.Nr)selfrrM/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/transforms/inverse.py set_tracingKszTraceableTransform.set_tracingNrkeycCs|dkrtjS|tjS)z1The key to store the stack of applied transforms.N)r KEY_SUFFIXr"rrr trace_keyOszTraceableTransform.trace_keycCstjtjtjtjfS)z9The keys to store necessary info of an applied transform.)r CLASS_NAMEIDTRACING DO_TRANSFORMrrrr transform_info_keysVsz&TraceableTransform.transform_info_keysdict)rcCs8|jjt||jt|dr |jndf}tt||S)zg Return a dictionary with the relevant information pertaining to an applied transform. _do_transformT) __class____name__idrhasattrr,r+zipr*)rvalsrrr get_transform_info[s z%TraceableTransform.get_transform_infoc Os0|dd}|}|tjd}|p(i}|dd}|rtrt|tr|s|r`|j|ddni}|j ||tj |d} | | S|r|j }| } ||n |i}} |j ||d| d} | | S||d<d|krt|dtr|d|n||d<tj|f||} t|tr,| | S|S) a Push to a stack of applied transforms of ``data``. Args: data: dictionary of data or `MetaTensor`. args: additional positional arguments to track_transform_meta. kwargs: additional keyword arguments to track_transform_meta, set ``replace=True`` (default False) to rewrite the last transform infor in applied_operation/pending_operation based on ``self.get_transform_info()``. lazyFTreplace)check) orig_size extra_info)transform_infor4r8r9)getr3rr)popr isinstancer pop_transformpush_transform ORIG_SIZEcopy_meta_frompending_operationscopyupdater+rtrack_transform_meta) rdataargskwargsZ lazy_evalr9Z do_transformr5xformmeta_objextrarrr r>gs.       z!TraceableTransform.push_transformFz dict | Nonez tuple | None)r#r8r7c  Cs|dk r||n|} t} t| tr8| j| | jd|rLtsLtd|s|dk rt| tr| } t | |t j dd} z | t t| d|t j d}WnJtk r} z,| jdkr| jrd} nd } t| | nW5d} ~ XYnXt|t d t j d | jtj<tr*|r*|tjspt|trlt|tsJt|}t| tr`| | n| ||<|S| S|}|dk r||tj<nsz;TraceableTransform.track_transform_meta..z for key )5rr<r r@__dict__rKr warningswarnpeek_pending_affinertorchfloat64r len RuntimeErrorndimis_batchrrPmetarAFFINEr:rr(rr+rBr?peek_pending_shaper0rQLAZYr;rSHAPE EXTRA_INFOtuplertolistget_default_affinepush_pending_operationrAr&STATUSESrPENDING_DURING_APPLYlistappendpush_applied_operationrr%)clsrEr#Zsp_sizeaffiner8r7r9r4Zdata_tZout_objZ orig_affineemsginfoZtransform_nameZpendstatusesmessagesZx_krrr rDs#                                  z'TraceableTransform.track_transform_metar) transformrc Cs|tjd}|t|krdS|tjkr,dS|tjd}|tjid}|r\t|t j dkrz||j j krzdStd|j j d|d|dt|d dS) z&Check transforms are of same instance.rSNrZ)spawnNzError z8 getting the most recently applied invertible transform  z != .)r:rr'r/NONEr&rgrYrZr\multiprocessingget_start_methodr-r.r_)rrxZxform_idZ xform_name warning_msgrrr check_transforms_matchs   $z)TraceableTransform.check_transforms_matchT)r#r6r;cCs|jstdt|tr |j}nXt|trd||krLt||trL||j}qx|||t}nt dt |d|r| |d|r| S|dS)a Get most recent transform for the stack. Args: data: dictionary of data or `MetaTensor`. key: if data is a dictionary, data[key] will be modified. check: if true, check that `self` is the same type as the most recently-applied transform. pop: if true, remove the transform as it is returned. Returns: Dictionary of most recently applied transform Raises: - RuntimeError: data is neither `MetaTensor` nor dictionary zCTransform Tracing must be enabled to get the most recent transform.z8`data` should be either `MetaTensor` or dictionary, got r{rW) rr_r<r applied_operationsrr:r%get_default_applied_operations ValueErrortyperr;)rrEr#r6r;all_transformsrrr get_most_recent_transform$s   z,TraceableTransform.get_most_recent_transform)r#r6cCs|j|||ddS)a Return and pop the most recent transform. Args: data: dictionary of data or `MetaTensor` key: if data is a dictionary, data[key] will be modified check: if true, check that `self` is the same type as the most recently-applied transform. Returns: Dictionary of most recently applied transform Raises: - RuntimeError: data is neither `MetaTensor` nor dictionary T)r;)r)rrEr#r6rrr r=Csz TraceableTransform.pop_transform)to_traceccs|j}||_dV||_dS)zITemporarily set the tracing status of a transform with a context manager.Nr)rrprevrrr trace_transformTsz"TraceableTransform.trace_transform)N)NNNNNNF)NTF)NT)r. __module__ __qualname____doc__rrrr! staticmethodr%r*r3r> classmethodrDrrr=rrrrr r)s0   %c@s(eZdZdZddZdddddZdS) ra:Classes for invertible transforms. This class exists so that an ``invert`` method can be implemented. This allows, for example, images to be cropped, rotated, padded, etc., during training and inference, and after be returned to their original size before saving to file for comparison in an external viewer. When the ``inverse`` method is called: - the inverse is called on each key individually, which allows for different parameters being passed to each label (e.g., different interpolation for image and label). - the inverse transforms are applied in a last-in-first-out order. As the inverse is applied, its entry is removed from the list detailing the applied transformations. That is to say that during the forward pass, the list of applied transforms grows, and then during the inverse it shrinks back down to an empty list. We currently check that the ``id()`` of the transform is the same in the forward and inverse directions. This is a useful check to ensure that the inverses are being processed in the correct order. Note to developers: When converting a transform to an invertible transform, you need to: #. Inherit from this class. #. In ``__call__``, add a call to ``push_transform``. #. Any extra information that might be needed for the inverse can be included with the dictionary ``extra_info``. This dictionary should have the same keys regardless of whether ``do_transform`` was `True` or `False` and can only contain objects that are accepted in pytorch data loader's collate function (e.g., `None` is not allowed). #. Implement an ``inverse`` method. Make sure that after performing the inverse, ``pop_transform`` is called. cCsdt|trt|tjs|St|}||D]2}tj|}||ks,||sNq,tj||dd}q,|S)z This function is to be called before every `self.inverse(data)`, update each MetaTensor `data[key]` using `data[key_transforms]` and `data[key_meta_dict]`, for MetaTensor backward compatibility 0.9.0. F)t)r<r+r MapTransformZ key_iteratorrr%sync_meta_info)rrEdkZ transform_keyrrr inverse_updates z"InvertibleTransform.inverse_updater)rErcCstd|jjddS)z Inverse of ``__call__``. Raises: NotImplementedError: When the subclass does not override this method. z Subclass z must implement this method.N)NotImplementedErrorr-r.)rrErrr inverseszInvertibleTransform.inverseN)r.rrrrrrrrr r]s$)% __future__rrYcollections.abcrr contextlibrtypingrr\monairmonai.data.meta_objrr monai.data.meta_tensorr monai.data.utilsr monai.transforms.traitsr monai.transforms.transformr monai.utilsrrrrrrrmonai.utils.miscr__all__rrrrrr  s$        $ 6