o  i@sddlmZddlZddlmZmZddlmZmZddl m Z ddl m Z ddl ZddlZddlmZddlmZmZmZdd lmZmZmZmZmZmZdd lmZdd lm Z dd l!m"Z"m#Z#dd l$m%Z%ddl&m'Z'm(Z(ddl)m*Z*ddl+m,Z,m-Z-m.Z.ddl/m0Z0m1Z1ee2dZ3gdZ4Gddde%eZ5Gddde5Z6Gddde5Z7Gddde5Z8Gddde5Z9Gddde5Z:Gd d!d!e5Z;Gd"d#d#e5ZdS)() annotationsN)ABCabstractmethod)HashableMapping)deepcopy)Any) get_logger) OperationsSampleOperationsSummaryOperations)concat_multikeys_to_dictconcat_val_to_npget_foreground_imageget_foreground_label get_label_ccpverify_report_format) ConfigParser) ID_SEP_KEY) MetaTensoraffine_to_spacing) MapTransform)sumunique)convert_to_numpy) DataStatsKeysImageStatsKeysLabelStatsKeys) ImageMetaKey label_union) module_name) Analyzer ImageStats FgImageStats LabelStatsImageStatsSummFgImageStatsSummLabelStatsSumm FilenameStatsImageHistogramImageHistogramSummcsdeZdZdZdfdd Zdd dZdddZd ddZeddZ d!ddZ e d"ddZ Z S)#r!a The Analyzer component is a base class. Other classes inherit this class will provide a callable with the same class name and produces one pre-formatted dictionary for the input data. The format is pre-defined by the init function of the class that inherit this base class. Function operations can also be registered before the runtime of the callable. Args: report_format: a dictionary that outlines the key structures of the report format. stats_namestr report_formatdictreturnNonecs<tdt|dd}|d|_||_tidd|_dS)NF)globals)super__init__rgetr-r+ops)selfr+r-parser __class__Z/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/auto3dseg/analyzer.pyr4Fs   zAnalyzer.__init__keyopr cCs<||j|<t|j}||ddkr|||<|d|_dS)z Register a statistical operation to the Analyzer and update the report_format. Args: key: value key in the report. op: Operation sub-class object that represents statistical operations. r0r2N)r6rr-r5)r7r=r>r8r;r;r< update_opsMs zAnalyzer.update_ops nested_keycCs|t}t|dkrtd|\}}}||jvrig|j|<|j|d|di||j|<t|j}||ddkrC|||<dSdS)a0 Update operations for nested label format. Operation value in report_format will be resolved to a dict with only keys. Args: nested_key: str that has format of 'key1#0#key2'. op: Operation sub-class object that represents statistical operations. zFNested_key input format is wrong. Please ensure it is like key1#0#key2rNNA) splitrlen ValueErrorr6updaterr-r5)r7r@r>keysroot_Z child_keyr8r;r;r<update_ops_nested_label^s       z Analyzer.update_ops_nested_labelcCs||j|jS)z Get the report format by resolving the registered operations recursively. Returns: a dictionary with {keys: None} pairs. )resolve_formatr-r7r;r;r<get_report_formatws zAnalyzer.get_report_formatcCs8tt|j}t|dr|jD] }||diq|S)a= Unwrap a function value and generates the same set keys in a dict when the function is actually called in runtime Args: func: Operation sub-class object that represents statistical operations. The func object should have a `data` dictionary which stores the statistical operation information. For some operations (ImageStats for example), it may also contain the data_addon property, which is part of the update process. Returns: a dict with a set of keys. data_addonN)r.fromkeyslistdatahasattrrNrF)funcretr=r;r;r< unwrap_opss   zAnalyzer.unwrap_opsreportcCs^|D](\}}t|tr||||<qt|tr(t|dkr(||dq|||<qdS)z Resolve the format of the pre-defined report. Args: report: the dictionary to resolve. Values will be replaced in-place. rN)items isinstancer rUrPrDrK)r7rVkvr;r;r<rKs  zAnalyzer.resolve_formatrQrcCstd|jjd)z:Analyze the dict format dataset, return the summary reportz Subclass z must implement this method.)NotImplementedErrorr:__name__)r7rQr;r;r<__call__szAnalyzer.__call__)r+r,r-r.r/r0)r=r,r>r r/r0)r@r,r>r r/r0)r/r.)rVr.r/r0)rQrr/r.)r\ __module__ __qualname____doc__r4r?rJrM staticmethodrUrKrr] __classcell__r;r;r9r<r!:s     r!cs0eZdZdZejfd fdd Zd d ZZS) r"a Analyzer to extract image stats properties for each case(image). Args: image_key: the key to find image data in the callable function input (data) Examples: .. code-block:: python import numpy as np from monai.auto3dseg import ImageStats from monai.data import MetaTensor input = {} input['image'] = np.random.rand(1,30,30,30) input['image'] = MetaTensor(np.random.rand(1,30,30,30)) # MetaTensor analyzer = ImageStats(image_key="image") print(analyzer(input)["image_stats"]) Notes: if the image data is NumPy array, the spacing stats will be [1.0] * `ndims` of the array, where the `ndims` is the lesser value between the image dimension and 3. image_keyr,r+r/r0c sbt|ts td||_tjdtjdtjdtjdtj dtj di}t ||| tj tdS)Nzimage_key input must be str)rXr,rErcrSHAPECHANNELS CROPPED_SHAPESPACINGSIZEMM INTENSITYr3r4r?r )r7rcr+r-r9r;r<r4s  zImageStats.__init__cst|tstdt|jdj|vrtdjd|j}t|tjt j t fs' must be a numpy array, torch.Tensor, or MetaTensor, but got rAzImage data under 'z1' must have at least 3 dimensions, but got shape Fcg|] }j|qSr;rc.0idr7r;r< z'ImageStats.__call__..r nda_croppedscSsg|]}t|qSr;)rrnndar;r;r<rrcSg|]}t|jqSr;rPshaperur;r;r<rr cSrxr;ryrnZnda_cr;r;r<rr r{g?cSsg|]\}}||qSr;r;)rnabr;r;r<rrs cg|] }jtj|qSr;r6rrievaluater|rLr;r<rrreport generated by differs from the report format.zGet image stats spent )(rXr. TypeErrortyper\rcKeyErrornpndarraytorchTensorrndimrErztimeis_grad_enabledset_grad_enabledrangerrMrrdrDrerfraffinetolistminrgziprhrir RuntimeErrorr:r+loggerdebug)r7rQimagestartrestore_grad_statendasrtrVr;rpr<r]sV      $     zImageStats.__call__)rcr,r+r,r/r0 r\r^r_r`r IMAGE_STATSr4r]rbr;r;r9r<r"sr"cs2eZdZdZejfdfdd Zdd d ZZS)r#ay Analyzer to extract foreground label properties for each case(image and label). Args: image_key: the key to find image data in the callable function input (data) label_key: the key to find label data in the callable function input (data) Examples: .. code-block:: python import numpy as np from monai.auto3dseg import FgImageStats input = {} input['image'] = np.random.rand(1,30,30,30) input['label'] = np.ones([30,30,30]) analyzer = FgImageStats(image_key='image', label_key='label') print(analyzer(input)["image_foreground_stats"]) rcr, label_keyr+cs8||_||_tjdi}t|||tjtdSN)rcrrrir3r4r?r )r7rcrr+r-r9r;r<r4;s  zFgImageStats.__init__rQrr/r.cst|t}t}tdfddtjjdD}jj|djkr>t djd|djfdd|D}dd|D}t  }fd d|D|t j <t| sptd jd |j<t|td t|S) ak Callable to execute the pre-defined functions Returns: A dictionary. The dict has the key in self.report_format and value in a list format. Each element of the value list has stats pre-defined by SampleOperations (max, min, ....). Raises: RuntimeError if the stats report generated is not consistent with the pre- defined report_format. Note: The stats operation uses numpy and torch to compute max, min, and other functions. If the input has nan/inf, the stats results will be nan/inf. Fcrkr;rlrmrpr;r<rr[rsz)FgImageStats.__call__..r Label shape  is different from image shape cg|]}t|qSr;rru ndas_labelr;r<rrar{cSs&g|]}|dkr |ntdgqS)rg)numelrrur;r;r<rrbs&crr;rrnZnda_frLr;r<rrgrrrz!Get foreground image stats spent )r.rrrrrrcrzrrErrMrrirrr:r+rr)r7rQrrrnda_foregroundsrVr;)rqrr7r<r]Ds( $      zFgImageStats.__call__)rcr,rr,r+r,)rQrr/r. r\r^r_r`rFG_IMAGE_STATSr4r]rbr;r;r9r<r#$s r#cs4eZdZdZejdfdfd d ZdddZZS)r$a Analyzer to extract label stats properties for each case(image and label). Args: image_key: the key to find image data in the callable function input (data) label_key: the key to find label data in the callable function input (data) do_ccp: performs connected component analysis. Default is True. Examples: .. code-block:: python import numpy as np from monai.auto3dseg import LabelStats input = {} input['image'] = np.random.rand(1,30,30,30) input['label'] = np.ones([30,30,30]) analyzer = LabelStats(image_key='image', label_key='label') print(analyzer(input)["label_stats"]) Trcr,rr+do_ccp bool | Nonec s||_||_||_tjdtjdtjtjdtjdigi}|jr.|tjdtj dtj dit ||| tjtttjdtjg}||tdSNr0)rcrrr LABEL_UID IMAGE_INTSTLABEL PIXEL_PCTrF LABEL_SHAPE LABEL_NCOMPr3r4r?r rjoinrJ)r7rcrr+rr-id_seqr9r;r<r4szLabelStats.__init__rQMapping[Hashable, MetaTensor]r/!dict[Hashable, MetaTensor | dict]cst|t}tjtjtfrjjjdkrd}nd}t }t dfddt jj dD}j tjj |dj kr[tdj d|dj fd d|D}d d|D}t}tttjfr~|j}|tj}g}d} g} |D]]} t} i} | kfd d|D}fd d|D| tj<t}| || |7} jr|r~tjt\}}|| tj<|| tj <|| t!"d | dt| qt#|D]\}}||$tj%t&| || iqt'(}||tj)<fdd|D|tj<||tj*<t+|(s2t,dj-d|j.<t |t!"dt|S)a Callable to execute the pre-defined functions. Returns: A dictionary. The dict has the key in self.report_format and value in a list format. Each element of the value list has stats pre-defined by SampleOperations (max, min, ....). Examples: output dict contains { LabelStatsKeys.LABEL_UID:[0,1,3], LabelStatsKeys.IMAGE_INTST: {...}, LabelStatsKeys.LABEL:[ { LabelStatsKeys.PIXEL_PCT: 0.8, LabelStatsKeys.IMAGE_INTST: {...}, LabelStatsKeys.LABEL_SHAPE: [...], LabelStatsKeys.LABEL_NCOMP: 1 } { LabelStatsKeys.PIXEL_PCT: 0.1, LabelStatsKeys.IMAGE_INTST: {...}, LabelStatsKeys.LABEL_SHAPE: [...], LabelStatsKeys.LABEL_NCOMP: 1 } { LabelStatsKeys.PIXEL_PCT: 0.1, LabelStatsKeys.IMAGE_INTST: {...}, LabelStatsKeys.LABEL_SHAPE: [...], LabelStatsKeys.LABEL_NCOMP: 1 } ] } Raises: RuntimeError if the stats report generated is not consistent with the pre- defined report_format. Notes: The label class_ID of the dictionary in LabelStatsKeys.LABEL IS NOT the index. Instead, the class_ID is the LabelStatsKeys.LABEL_UID with the same index. For instance, the last dict in LabelStatsKeys.LABEL in the Examples is 3, which is the last element under LabelStatsKeys.LABEL_UID. The stats operation uses numpy and torch to compute max, min, and other functions. If the input has nan/inf, the stats results will be nan/inf. cudaTFcrkr;rlrmrpr;r<rrrsz'LabelStats.__call__..rrrcrr;rrurr;r<rrr{cSs(g|]}|dkr |ntdgqS)r)rrrrur;r;r<rrs(csg|]}|qSr;r;ru) mask_indexr;r<rrrwcrr;r6rrr)rnZnda_mrLr;r<rrrz label z stats takes crr;rrrLr;r<rrrrrzGet label stats spent )/r.rrXrcrrrdevicerrrrrzrastypeint16rErrQcpunumpyrrrrrappendrr empty_cacherrrrr enumeraterFrfloatrrMrrrrr:r+)r7rQrZ using_cudarrr unique_labelZlabel_substatsZ pixel_sumZ pixel_arrindexZ start_label label_dictZ nda_masksZ pixel_count shape_list ncomponentsrorIrVr;)rqrrr7r<r]sl0( $         "      zLabelStats.__call__)rcr,rr,r+r,rr)rQrr/r r\r^r_r`r LABEL_STATSr4r]rbr;r;r9r<r$us r$c4eZdZdZejdfdfdd Zdd dZZS)r%au This summary analyzer processes the values of specific key `stats_name` in a list of dict. Typically, the list of dict is the output of case analyzer under the same prefix (ImageStats). Args: stats_name: the key of the to-process value in the dict. average: whether to average the statistical value across different image modalities. Tr+r,averagerc s||_tjdtjdtjdtjdtjdtjdi}t ||| tjt | tjt | tjt | tjt | tjt | tjt dSr) summary_averagerrdrerfrgrhrir3r4r?r r r7r+rr-r9r;r<r4*szImageStatsSumm.__init__rQ list[dict]r/r.cCs(t|tstd|jdt|dkrtd|jd|j|dvr,t|jdt|}t j t j t j t j t jfD] }t||j|g}|j|j||jdkrX|jrXdndd||<q>t j}||}t||j|g|}|j|j||jr|d ndd||<t||std |jd |S)  Callable to execute the pre-defined functions Returns: A dictionary. The dict has the key in self.report_format and value in a list format. Each element of the value list has stats pre-defined by SampleOperations (max, min, ....). Raises: RuntimeError if the stats report generated is not consistent with the pre- defined report_format. Examples: output dict contains a dictionary for all of the following keys{ ImageStatsKeys.SHAPE:{...} ImageStatsKeys.CHANNELS: {...}, ImageStatsKeys.CROPPED_SHAPE: {...}, ImageStatsKeys.SPACING: {...}, ImageStatsKeys.SIZEMM: {...}, ImageStatsKeys.INTENSITY: {...}, } Notes: The stats operation uses numpy and torch to compute max, min, and other functions. If the input has nan/inf, the stats results will be nan/inf. Callable  requires list inputsr input list is empty is not in input datardimNrr)rXrPrEr:rDr+rrrMrrdrerfrgrhrr6rrrrirGr rr)r7rQrVrYZv_np intst_strop_keys intst_dictr;r;r<r]=s,   . "zImageStatsSumm.__call__r+r,rrrQrr/r.rr;r;r9r<r%s r%cr)r&ax This summary analyzer processes the values of specific key `stats_name` in a list of dict. Typically, the list of dict is the output of case analyzer under the similar name (FgImageStats). Args: stats_name: the key of the to-process value in the dict. average: whether to average the statistical value across different image modalities. Tr+r,rrc2||_tjdi}t|||tjtdSr)rrrir3r4r?r rr9r;r<r4s zFgImageStatsSumm.__init__rQrr/r.cCst|tstd|jdt|dkrtd|jd|j|dvr,t|jdt|}t j }|| }t ||j|g|}|j |j||jrOdndd||<t||setd|jd |S) aY Callable to execute the pre-defined functions. Returns: A dictionary. The dict has the key in self.report_format and value in a list format. Each element of the value list has stats pre-defined by SampleOperations (max, min, ....) and SummaryOperation (max of the max, mean of the mean, etc). Raises: RuntimeError if the stats report generated is not consistent with the pre- defined report_format. Examples: output dict contains a dictionary for all of the following keys{ ImageStatsKeys.INTENSITY: {...}, } Notes: The stats operation uses numpy and torch to compute max, min, and other functions. If the input has nan/inf, the stats results will be nan/inf. rrrrz is not in input data.Nrrr)rXrPrEr:rDr+rrrMrrirGr r6rrrr)r7rQrVrrrr;r;r<r]s    "zFgImageStatsSumm.__call__rrrr;r;r9r<r&x r&cs6eZdZdZejddfdfdd ZdddZZS)r'av This summary analyzer processes the values of specific key `stats_name` in a list of dict. Typically, the list of dict is the output of case analyzer under the similar name (LabelStats). Args: stats_name: the key of the to-process value in the dict. average: whether to average the statistical value across different image modalities. Tr+r,rrrc s||_||_tjdtjdtjtjdtjdigi}|jr+|tjdtjdtj dit ||| tjt ttjdtjg}||tttjdtjg}||t ttjdtjg}||tttjdtj g}||tdSr)rrrrrrrrFrrr3r4r?r rrrJr )r7r+rrr-rr9r;r<r4s(zLabelStatsSumm.__init__rQrr/r.cCst|tstd|jdt|dkrtd|jd|j|dvr,t|jdt|}t ||jt j gddd}t |}||t j <t j }||}t||j|g|}|j|j||jrddndd ||<g}t j} |D]} i} t j} |j| | | g} t || dd }|j| d| j||jd kr|jrd ndd | | <|jrt j}|jt j| |g}t ||dd }|j| d|j||jd kr|jrd ndd | |<t j}|j| | t jg}t ||ddd }|j| d|j||jd kr|jrd ndd | |<t j }|j| | |g}|| d|}t|||dd }|j| d|j||jr(dndd | |<|| qq||t j<t||sJtd|jd|S)a Callable to execute the pre-defined functions Returns: A dictionary. The dict has the key in self.report_format and value in a list format. Each element of the value list has stats pre-defined by SampleOperations (max, min, ....) and SummaryOperation (max of the max, mean of the mean, etc). Raises: RuntimeError if the stats report generated is not consistent with the pre- defined report_format. Notes: The stats operation uses numpy and torch to compute max, min, and other functions. If the input has nan/inf, the stats results will be nan/inf. rrrrrNT)axisraggedr) allow_missingrr)rrrr)rXrPrEr:rDr+rrrMrrrrrrGr r6rrrrrrrrrrr)r7rQrVZuid_nprrrrZdetailed_label_listZ label_strZlabel_idstatsZpct_strZpct_fixed_keysZpct_npZ ncomp_strZncomp_fixed_keysZncomp_npZ shape_strZshape_fixed_keysshape_npZintst_fixed_keysr;r;r<r]sb     "     zLabelStatsSumm.__call__)r+r,rrrrrrr;r;r9r<r's   r'cs*eZdZdZd fdd Zd d ZZS) r(a/ This class finds the file path for the loaded image/label and writes the info into the data pipeline as a monai transforms. Args: key: the key to fetch the filename (for example, "image", "label"). stats_name: the key to store the filename in the output stats report. r= str | Noner+r,r/r0cs||_t|idSr)r=r3r4)r7r=r+r9r;r<r4FszFilenameStats.__init__cCst|}|jrK|j|vrtd|jdt||jts&td|jdtj||jjvr=ttjd||jd||jjtj||j<|Sd||j<|S)NzData with key z is missing.zValue type of z is not MetaTensor.z not found in MetaTensor rjr0) r.r=rErXrrFILENAME_OR_OBJmetar+)r7rQrqr;r;r<r]Js  zFilenameStats.__call__)r=rr+r,r/r0)r\r^r_r`r4r]rbr;r;r9r<r(;s r(cs6eZdZdZejddfdfd d ZdddZZS)r)a! Analyzer to compute intensity histogram. Args: image_key: the key to find image data in the callable function input (data) hist_bins: list of positive integers (one for each channel) for setting the number of bins used to compute the histogram. Defaults to [100]. hist_range: list of lists of two floats (one for each channel) setting the intensity range to compute the histogram. Defaults to [-500, 500]. Examples: .. code-block:: python import numpy as np from monai.auto3dseg.analyzer import ImageHistogram input = {} input['image'] = np.random.rand(1,30,30,30) input['label'] = np.ones([30,30,30]) analyzer = ImageHistogram(image_key='image') print(analyzer(input)) Nrcr,r+ hist_binslist[int] | int | None hist_range list | Nonec s<||_|dur dgn t|tr|n|g|_|durddgn||_ddd}t|||tj t t dd|jDsC|jg|_t |jt |jkr^t dt |jdt |jd tt|j|jD]4\}}|\}} t|trx|d krt d |d d |t| trt | dkrt d |d d| qgdS)Ndi icounts bin_edgescss|]}t|tVqdSr)rXrP)rnhrr;r;r< sz*ImageHistogram.__init__..zNumber of histogram bins () and histogram ranges (z) need to be the same!rz Expected rz1. hist_bins value to be positive integer but got rz8. hist_range values to be list of length 2 but received )rcrXrPrrr3r4r?r HISTOGRAMr allrDrErrint) r7rcr+rrr-roZ hist_paramsZ _hist_binsZ _hist_ranger9r;r<r4us.   zImageHistogram.__init__rQr.r/c CsFt|}t||jdd}t|d}t|jdkr!||j|_t|j|kr6td|dt|jdt|jdkrC||j|_t|j|krXtd|dt|jdg}t |D]=}tj ||d f|j||j|d|j|dfd \}}| | d } t | | std |jd || q^|||j<|S)a Callable to execute the pre-defined functions Returns: A dictionary. The dict has the key in self.report_format and value Raises: RuntimeError if the stats report generated is not consistent with the pre- defined report_format. Note: The stats operation uses numpy and torch to compute max, min, and other functions. If the input has nan/inf, the stats results will be nan/inf. T) wrap_sequencerrz4There is a mismatch between the number of channels (z) and number histogram bins (z).r.)binsrrrr)r.rrcrrzrDrrErr histogramrrrMrr:rr+) r7rQrqrZ nr_channelsreportschannelrr_reportr;r;r<r]s@       zImageHistogram.__call__)rcr,r+r,rrrr)rQr.r/r. r\r^r_r`rIMAGE_HISTOGRAMr4r]rbr;r;r9r<r)[s#r)cr)r*ay This summary analyzer processes the values of specific key `stats_name` in a list of dict. Typically, the list of dict is the output of case analyzer under the same prefix (ImageHistogram). Args: stats_name: the key of the to-process value in the dict. average: whether to average the statistical value across different image modalities. Tr+r,rrcrr)rrrr3r4r?r rr9r;r<r4s zImageHistogramSumm.__init__rQrr/r.c Cst|tstd|jdt|dkrtd|jd|j|dvr,t|jdi}|D]d}|sP|tj}t t|D]}t ||d||d<q?q0t t|D]=}||dt |tj|d7<t ||d|tj|dkrtd||dd |tj|dqVq0t t|D]}||d ||d<qtj|i}t||std |jd |S) rrrrrrrrzbin edges are not consistent! z vs. rr)rXrPrEr:rDr+rrrrrarrayrrrrrrMr)r7rQZsumm_histogramrqrYrVr;r;r<r]s:   ($  zImageHistogramSumm.__call__rrrr;r;r9r<r*rr*)? __future__rrabcrrcollections.abcrrcopyrtypingrrrrmonai.apps.utilsr Zmonai.auto3dseg.operationsr r r monai.auto3dseg.utilsr rrrrrmonai.bundle.config_parserrZmonai.bundle.utilsr monai.datarrmonai.transforms.transformr0monai.transforms.utils_pytorch_numpy_unificationrr monai.utilsrmonai.utils.enumsrrrmonai.utils.miscrrr\r__all__r!r"r#r$r%r&r'r(r)r*r;r;r;r<sB          tvQ*Z@ s