o  iN{@s`ddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl mZddlmZmZmZddlmZddlmZddlmZmZmZmZmZddlZddlZddlm Z m!Z!m"Z"dd l#m$Z$m%Z%erdd l&m'Z'n e$d d d d\Z'Z(gdZ)dddZ*da+ej,j-j.Z/ej,j-j0Z1e2ej3j4Z5e5dZ6ej78ddej7d<e9dddZ:ddZ;edZZ?edd#d$Z@edd&d$Z@ddd'd$Z@dd*d+ZAdd,d-ZBddd2d3ZCddd8d9ZDddcomplexr<tuplergrangeslicerhrNrNrOrs$rFrU wrap_arrayrmcCs2|rt|tjtjfr|fSt|rt|S|fS)a# Returns a tuple of `vals`. Args: vals: input data to convert to a tuple. wrap_array: if `True`, treat the input numerical array (ndarray/tensor) as one item of the tuple. if `False`, try to convert the array with `tuple(vals)`, default to `False`. )rfnpndarraytorchTensorrrm)rUrprNrNrOrs rdimrjpad_valpad_from_startcCsHt|}|t|}|dkr|d|S|r|f||S||f|S)zn Returns a copy of `tup` with `dim` values by either shortened or padded with `pad_val` as necessary. rN)rlen)rUrurvrwtupZpad_dimrNrNrOrs  rrytuple[Any, ...]cCspt|tjr|}t|tjr|}t |s!|f|St ||kr+t |St d|dt |d)al Returns a copy of `tup` with `dim` values by either shortened or duplicated input. Raises: ValueError: When ``tup`` is a sequence and ``tup`` length is not ``dim``. Examples:: >>> ensure_tuple_rep(1, 3) (1, 1, 1) >>> ensure_tuple_rep(None, 3) (None, None, None) >>> ensure_tuple_rep('test', 3) ('test', 'test', 'test') >>> ensure_tuple_rep([1, 2, 3], 3) (1, 2, 3) >>> ensure_tuple_rep(range(3), 3) (0, 1, 2) >>> ensure_tuple_rep([1, 2], 3) ValueError: Sequence must have length 3, got length 2. zSequence must have length z, got .) rfrsrtdetachcpunumpyrqrrtolistrrxrmrL)ryrurNrNrOrs    rdictionary_of_tuplesdictkeystuple[dict[Any, Any], ...]csPttdkrtiSfdd|DtfddttDS)a Given a dictionary whose values contain scalars or tuples (with the same length as ``keys``), Create a dictionary for each key containing the scalar values mapping to that key. Args: dictionary_of_tuples: a dictionary whose values are scalars or tuples whose length is the length of ``keys`` keys: a tuple of string values representing the keys in question Returns: a tuple of dictionaries that contain scalar values, one dictionary for each key Raises: ValueError: when values in the dictionary are tuples but not the same length as the length of ``keys`` Examples: >>> to_tuple_of_dictionaries({'a': 1 'b': (2, 3), 'c': (4, 4)}, ("x", "y")) ({'a':1, 'b':2, 'c':4}, {'a':1, 'b':3, 'c':4}) rcs i|] \}}|t|tqSrN)rrx.0kv)rrNrO s z,to_tuple_of_dictionaries..c3s&|]fddDVqdS)csi|] \}}||qSrNrNrikrNrOrz6to_tuple_of_dictionaries...N)items)r)dict_overridesrrO s$z+to_tuple_of_dictionaries..)rrxrmrrn)rrrN)rrrOr s  r cCs |o|dkSNrrNxrNrNrOs r user_providedSequence | NdarrayTensorfuncrcs.t|}t||}tfddt||DS)a$ Refine `user_provided` according to the `default`, and returns as a validated tuple. The validation is done for each element in `user_provided` using `func`. If `func(user_provided[idx])` returns False, the corresponding `default[idx]` will be used as the fallback. Typically used when `user_provided` is a tuple of window size provided by the user, `default` is defined by data, this function returns an updated `user_provided` with its non-positive components replaced by the corresponding components from `default`. Args: user_provided: item to be validated. default: a sequence used to provided the fallbacks. func: a Callable to validate every components of `user_provided`. Examples:: >>> fall_back_tuple((1, 2), (32, 32)) (1, 2) >>> fall_back_tuple(None, (32, 32)) (32, 32) >>> fall_back_tuple((-1, 10), (32, 32)) (32, 10) >>> fall_back_tuple((-1, None), (32, 32)) (32, 32) >>> fall_back_tuple((1, None), (32, 32)) (1, 32) >>> fall_back_tuple(0, (32, 32)) (32, 32) >>> fall_back_tuple(range(3), (32, 64, 48)) (32, 1, 2) >>> fall_back_tuple([0], (32, 32)) ValueError: Sequence must have length 2, got length 1. c3s$|] \}}|r |n|VqdSr^rN)rZ default_cZuser_crrNrOr-s z"fall_back_tuple..)rxrrmrS)rr\rrcuserrNrrOr!s '  r!cCst|tjo |jdkSr)rfrsrtrcrMrNrNrOr"2sr"cCs(t|tjr |jdkr dStt|S)NrT)rfrsrtrcr>rqisscalarrMrNrNrOr#6sr#indexcountdesc str | Nonebar_lennewlineNonecCs|sdnd}t|||}|dur|dnd}|dd|d||d7}t|d |d||d ||krAtddSdS) aprint a progress bar to track some time consuming task. Args: index: current status in progress. count: total steps of the progress. desc: description of the progress bar, if not None, show before the progress bar. bar_len: the total length of the bar on screen, default is 30 char. newline: whether to print in a new line for every index.  z N [=]/)end)rjprint)rrrrrrZ filled_lenbarrNrNrOr$<s   r$ int | NonecCstSr^)_seedrNrNrNrOr%Or_r%seeduse_deterministic_algorithms bool | Noneadditional_settings Set random seed for modules to enable or disable deterministic training. Args: seed: the random seed to use, default is np.iinfo(np.int32).max. It is recommended to set a large seed, i.e. a number that has a good balance of 0 and 1 bits. Avoid having many 0 bits in the seed. if set to None, will disable deterministic training. use_deterministic_algorithms: Set whether PyTorch operations must use "deterministic" algorithms. additional_settings: additional settings that need to set random seed. Note: This function will not affect the randomizable objects in :py:class:`monai.transforms.Randomizable`, which have independent random states. For those objects, the ``set_random_state()`` method should be used to ensure the deterministic behavior (alternatively, :py:class:`monai.data.DataLoader` by default sets the seeds according to the global random state, please see also: :py:class:`monai.data.utils.worker_init_fn` and :py:class:`monai.data.utils.set_rnd`). NTF)rsdefault_generatorrr( manual_seedrjrrandomrqrbackends__allow_nonbracketed_mutationcudnn deterministic benchmark_flag_deterministic_flag_cudnn_benchmarkr)rrrZseed_rrNrNrOr&Ss.           r&c Csdd}i}|rJ|D]?}||\}}z||vrtd|dt|||<Wq tyIz ttt|||<Wn tyF|||<YnwYq w|S)a9 To convert a list of "key=value" pairs into a dictionary. For examples: items: `["a=1", "b=2", "c=3"]`, return: {"a": "1", "b": "2", "c": "3"}. If no "=" in the pair, use None as the value, for example: ["a"], return: {"a": None}. Note that it will remove the blanks around keys and values. cSsB|jddd}|dd}t|dkr|ddnd}||fS)NrrQ)maxsplitrz ')splitstriprx)srkeyvaluerNrNrO _parse_varsz list_to_dict.._parse_varzencounter duplicated key r{)KeyErrorrrLr>rPr<)rrditemrrrNrNrOr's$     r'Tdevicestr | torch.device | None non_blockingverbosecst|dr |jdSt|trtfdd|DSt|tr,fdd|DSt|tr=fdd|DS|rXttj t j j }t|d t|d |S) a Copy object or tuple/list/dictionary of objects to ``device``. Args: obj: object or tuple/list/dictionary of objects to move to ``device``. device: move ``obj`` to this device. Can be a string (e.g., ``cpu``, ``cuda``, ``cuda:0``, etc.) or of type ``torch.device``. non_blocking: when `True`, moves data to device asynchronously if possible, e.g., moving CPU Tensors with pinned memory to CUDA devices. verbose: when `True`, will print a warning for any elements of incompatible type not copied to ``device``. Returns: Same as input, copied to ``device`` where possible. Original input will be unchanged. to)rc3s|] }t|VqdSr^r)rorrrNrOrsz!copy_to_device..csg|]}t|qSrNrrrrNrO z"copy_to_device..csi|] \}}|t|qSrNr)rrrrrNrOrsz"copy_to_device..z called with incompatible type: z". Data will be returned unchanged.)rdrrfrmlistrrr types FrameTypeinspect currentframef_codeco_namewarningswarnri)rbrrrfn_namerNrrOr)s    r)r str | bool raise_exccCsft|tr|Sd}d}t|tr |}||vrdS||vr dS|r1td|dd|||S)a Convert a string to a boolean. Case insensitive. True: yes, true, t, y, 1. False: no, false, f, n, 0. Args: value: string to be converted to a boolean. If value is a bool already, simply return it. raise_exc: if value not in tuples of expected true or false inputs, should we raise an exception? If not, return `default`. Raises ValueError: value not in tuples of expected true or false inputs and `raise_exc` is `True`. Useful with argparse, for example: parser.add_argument("--convert", default=False, type=str2bool) python mycode.py --convert=True )r@rBrAr?rD)rFrHrGrErJTFzGot "z", expected a value from: , )rfr>r<rKrLjoin)rr\rZtrue_setZ false_setrNrNrOr*s  r*str | list | None list | Nonec Cs|durdSt|tr |St|tr9|d}tt|D]}zt||}|||<Wqty6Yqw|S|rCt d|ddS)a Convert a string to a list. Useful with argparse commandline arguments: parser.add_argument("--blocks", default=[1,2,3], type=str2list) python mycode.py --blocks=1,2,2,4 Args: value: string (comma separated) to be converted to a list raise_exc: if not possible to convert to a list, raise an exception Raises ValueError: value not a string or list or not possible to convert N,zUnable to convert "z-", expected a comma-separated str, e.g. 1,2,3) rfrr<rrnrxrrrerL)rrrraarNrNrOr+s"      r+c@seZdZdZedddZedddZedd d Zedd d Zedd dZ edddZ edddZ edddZ edddZ dS)r,z. Environment variables used by MONAI. r=rcC tjdS)NZMONAI_DATA_DIRECTORYosenvirongetrNrNrNrOdata_dir zMONAIEnvVars.data_dirr>cCs$tjdd}t|tr|St|S)NZ MONAI_DEBUGF)rrrrfr>r*rMrNrNrOdebugszMONAIEnvVars.debugcCr)NZMONAI_DOC_IMAGESrrNrNrNrO doc_imagesrzMONAIEnvVars.doc_imagescCtjddS)NZMONAI_ALGO_HASHZ21ed8e5rrNrNrNrO algo_hash zMONAIEnvVars.algo_hashcCr)NZMONAI_TRACE_TRANSFORMrDrrNrNrNrOtrace_transform$rzMONAIEnvVars.trace_transformcCr)NZMONAI_EVAL_EXPRrDrrNrNrNrO eval_expr(rzMONAIEnvVars.eval_exprcCr)NZMONAI_ALLOW_MISSING_REFERENCErDrrNrNrNrOallow_missing_reference,rz$MONAIEnvVars.allow_missing_referencecCr)NZMONAI_EXTRA_TEST_DATArDrrNrNrNrOextra_test_data0rzMONAIEnvVars.extra_test_datacCstjddS)NZMONAI_TESTING_ALGO_TEMPLATErrNrNrNrOtesting_algo_template4rz"MONAIEnvVars.testing_algo_templateN)r=r)r=r>)__name__ __module__ __qualname____doc__ staticmethodrrrrrrrrrrNrNrNrOr,s(        r,c@seZdZdZdZdZdZdS)r-z; Common key names in the metadata header of images filename_or_objZ patch_index spatial_shapeN)rrrrZFILENAME_OR_OBJZ PATCH_INDEX SPATIAL_SHAPErNrNrNrOr-9s r-keywordsstr | Sequence[str]cs0t|sdSt|tfddt|DS)zk Return a boolean indicating whether the given callable `obj` has the `keywords` in its signature. Fc3s|]}|jvVqdSr^) parameters)rrsigrNrOrJszhas_option..)callabler signatureallr)rbrrNrrOr/Cs r/cCs&dtt|}|j|kot||jS)a!Determine if a module's version is at least equal to the given value. Args: module: imported module's name, e.g., `np` or `torch`. version: required version, given as a tuple, e.g., `(1, 8, 0)`. Returns: `True` if module is the given version or newer. r{)rmapr< __version__r)moduleversionZtest_verrNrNrOr.Ms r.datar as_indices slicevalscGs4tdgt|j}|r|nt|||<|t|S)asample several slices of input numpy array or Tensor on specified `dim`. Args: data: input data to sample slices, can be numpy array or PyTorch Tensor. dim: expected dimension index to sample slices, default to `1`. as_indices: if `True`, `slicevals` arg will be treated as the expected indices of slice, like: `1, 3, 5` means `data[..., [1, 3, 5], ...]`, if `False`, `slicevals` arg will be treated as args for `slice` func, like: `1, None` means `data[..., [1:], ...]`, `1, 5` means `data[..., [1: 5], ...]`. slicevals: indices of slices or start and end indices of expected slices, depends on `as_indices` flag. N)rorxshaperm)rrur r slicesrNrNrOr0Zs  r0pathr create_dircCs>t|}|j}|s|r|jdddStd|ddS)a Utility to check whether the parent directory of the `path` exists. Args: path: input path to check the parent directory. create_dir: if True, when the parent directory doesn't exist, create the directory, otherwise, raise exception. T)parentsz1the directory of specified path does not exist: `z`.N)rparentexistsmkdirrL)r rZpath_dirrNrNrOr1ls r1objectatomicCallable | NonekwargscKst|}t||d|rt||durtj}|s(|d||d|dSz?t0}t||j }|d||d|| rTt t ||WdWdSWdWdS1s`wYWdStyqYdSw)a Save an object to file with specified path. Support to serialize to a temporary file first, then move to final destination, so that files are guaranteed to not be damaged if exception occurs. Args: obj: input object data to save. path: target file path to save the input object. create_dir: whether to create dictionary of the path if not existing, default to `True`. atomic: if `True`, state is serialized to a temporary file first, then move to final destination. so that files are guaranteed to not be damaged if exception occurs. default to `True`. func: the function to save file, if None, default to `torch.save`. kwargs: other args for the save `func` except for the checkpoint and filename. default `func` is `torch.save()`, details of other args: https://pytorch.org/docs/stable/generated/torch.save.html. )r rN)rbrGrN)rr1rrremoverssavetempfileTemporaryDirectoryris_fileshutilmover<PermissionError)rbr rrrrtempdir temp_pathrNrNrOr2s*   & r2rlist | np.ndarrayrcCstttt|S)z Compute the union of class IDs in label and generate a list to include all class IDs Args: x: a list of numbers (for example, class_IDs) Returns a list showing the union (the union the class IDs) )rsetunionrqarrayrrrNrNrOr3s r3? torch.Tensorsigmoid thresholdrkcKs"|s tj|fi|S||kS)z Compute the lab from the probability of predicted feature maps Args: sigmoid: If the sigmoid function should be used. threshold: threshold value to activate the sigmoid function. )rsargmaxrj)rr'r(rrNrNrO prob2classs"r*cCst|S)z Convert a file path to URI. if not absolute path, will convert to absolute path first. Args: path: input file path to convert, can be a string or `Path` object. )rabsoluteas_uri)r rNrNrOr4sr4n_linescCspt|d}t|d}t||ddkr3t||d}|d|d|dg|| d}d|S) z Pretty print the head and tail ``n_lines`` of ``val``, and omit the middle part if the part has more than 3 lines. Returns: the formatted string. TrQNz ... omitted z line(s) r)pprintpformat splitlinesmaxrxr)r;r.val_strZhidden_nrNrNrOr5s  ( r5 ordered_pairsSequence[tuple[Any, Any]]dict[Any, Any]cCsdt}|D](\}}||vr(tjdddkrtd|dtd|dq||qt|S)a Checks if there is a duplicated key in the sequence of `ordered_pairs`. If there is - it will log a warning or raise ValueError (if configured by environmental var `MONAI_FAIL_ON_DUPLICATE_CONFIG==1`) Otherwise, it returns the dict made from this sequence. Satisfies a format for an `object_pairs_hook` in `json.load` Args: ordered_pairs: sequence of (key, value) MONAI_FAIL_ON_DUPLICATE_CONFIGrJrDDuplicate key: ``) r"rrrrLrraddr)r6rr_rNrNrOr6s  r6cseZdZdfdd ZZS)r7Fcsxt}|jD].\}}|j||d}||vr/tjdddkr&td|dtd|d| |qt ||S)N)deepr9rJrDr:r;) r"rZconstruct_objectrrrrLrrr<superconstruct_mapping)selfnoder>mappingZkey_noder=r __class__rNrOr@s z.CheckKeyDuplicatesYamlLoader.construct_mappingF)rrrr@ __classcell__rNrNrDrOr7sr7c@steZdZdZdddddZddd d d d d ddddddddZgdZd*ddZddZd d!Z d"d#Z d+d'd(Z d)S),r8z Convert the values from input unit to the target unit Args: input_unit: the unit of the input quantity target_unit: the unit of the target quantity g F%u?gׁ?gB?gL7A`%@)inchfootZyardZmile r0r/rQiiii)ZpetaZteraZgigaZmegaZkiloZhectoZdecaZdeciZcentimillimicronanoZpicoZfemto)meterbytebit input_unitr< target_unitr=rcCsR||\|_}||\|_}||kr||_n td|d|||_dS)NzPBoth input and target units should be from the same quantity. Input quantity is z while target quantity is )_get_valid_unit_and_baserWrX unit_baserL_calculate_conversion_factorconversion_factor)rArWrXZ input_baseZ target_baserNrNrO__init__%szConvertUnits.__init__cCsPt|}||jvr|dfS|jD] }||r||fSqtd|d)NrTz3Currently, it only supports length conversion but `z ` is given.)r<rKimperial_unit_of_length base_unitsendswithrL)rAunitZ base_unitrNrNrOrY1s     z%ConvertUnits._get_valid_unit_and_basecCs@||jvr t|j|S|dt|j}|dkrdS|j|S)zDCalculate the power of the unit factor with respect to the base unitNr?)r^rrxrZ unit_prefix)rAraprefixrNrNrO_get_unit_power:s  zConvertUnits._get_unit_powercCs4|j|jkrdS||j}||j}d||S)z?Calculate unit conversion factor with respect to the input unitrb )rWrXre)rAZ input_powerZ target_powerrNrNrOr[Ds    z)ConvertUnits._calculate_conversion_factorr int | floatr cCst||jSr^)rkr\)rArrNrNrO__call__LszConvertUnits.__call__N)rWr<rXr<r=r)rrgr=r ) rrrrr^rcr_r]rYrer[rhrNrNrNrOr8s0     r8cCs:t|j}t|jdh}t|}||}|tk|fS)a  Check if the all keys in kwargs exist in the __init__ method of the class. Args: cls: the class to check. kwargs: kwargs to examine. Returns: a boolean indicating if all keys exist. a set of extra keys that are not used in the __init__. rA)rrr]r"r)clsrZinit_signatureZ init_paramsZ input_kwargs extra_kwargsrNrNrOr9Ps r9cmd_list list[str]subprocess.CompletedProcessc Kst}|d||d<|ddr!ddl}|jjd|z t j |fi|WSt j y]}z%|s7t |j jdd}t |jjdd}td |jd |d |d |d}~ww) a Run a command by using ``subprocess.run`` with capture_output=True and stderr=subprocess.STDOUT so that the raise exception will have that information. The argument `capture_output` can be set explicitly if desired, but will be overriden with the debug status from the variable. Args: cmd_list: a list of strings describing the command to run. kwargs: keyword arguments supported by the ``subprocess.run`` method. Returns: a CompletedProcess instance after the command completes. capture_outputZrun_cmd_verboseFrNzmonai.utils.run_cmdreplace)errorszsubprocess call error z: rr{)r,rrpopmonaiappsutils get_loggerinfo subprocessrunCalledProcessErrorr<stdoutdecodestderr RuntimeError returncode)rkrrrreoutputrprNrNrOr:ds   r:numSequence[int] | intcCs6t|}dd|D}ddt||D}t||kS)zS Determine if the input is a square number or a squence of square numbers. cSsg|] }tt|qSrN)rjmathsqrt)rZ_numrNrNrOrrzis_sqrt..cSsg|]\}}||qSrNrN)r_iZ_jrNrNrOrr)rrS)rZsqrt_numretrNrNrOis_sqrts rarrrccCs|dd||jS)zMAppend 1-sized dimensions to `arr` to create a result with `ndim` dimensions.).r^rcrrcrNrNrOunsqueeze_rightsrcCs|d||jS)zNPrepend 1-sized dimensions to `arr` to create a result with `ndim` dimensions.r^rrrNrNrOunsqueeze_leftsrmetricsdict[str, Any]cCs<i}|D]\}}t|tr|t|q|||<q|S)z= Flatten the nested dictionary to a flat dictionary. )rrfrupdate flatten_dict)rresultrrrNrNrOrs   r)r;r<r=r>)rZr[r\rXr=rX)rZr[r=r`r^)rZr[r\r`r=r`)rbr r=r>rF)rUr rpr>r=rm)rF) rUr rurjrvr rwr>r=rm)ryr rurjr=rz)rrrr r=r)rr r\rrrr=rz)r;r r=r>)NrF) rrjrrjrrrrjrr>r=r)r=r)rrrrrrr=r)TF) rbr rrrr>rr>r=r )FT)rrr\r>rr>r=r>)T)rrrr>r=r)rbrrrr=r>)rQT) rrrurjr r>r rjr=r)r rrr>r=r)TTN)rbrr rrr>rr>rrrr r=r)rr!r=r)Fr%) rr&r'r>r(rkrr r=r&)r rr=r<)r-)r;r r.rjr=r<)r6r7r=r8)rkrlrr r=rm)rrr=r>)rrYrcrjr=rY)rrr=r)e __future__rrrVrrr1rrrwrrrastrcollections.abcrrrrpathlibrtypingr r r r r r~rqrsZmonai.config.type_definitionsrrrmonai.utils.modulerrrrr=__all__rPrrrrrrriinfouint32r4ZNP_MAXr(rrrrrrXrrrtrYrrrrrrr r!r"r#r$r%r&r'r)r*r+r,r-r/r.r0r1r2r3r*r4r5r6r7r8r9r:rrrrrNrNrNrOs     '       # .    6! " # +   0 I