class_docstr: Class that inherits from both `torch.Tensor` and `MetaObj`, adding support for metadata.
  
  Metadata is stored in the form of a dictionary. Nested, an affine matrix will be
  stored. This should be in the form of `torch.Tensor`.
  
  Behavior should be the same as `torch.Tensor` aside from the extended
  meta functionality.
  
  Copying of information:
  
      * For `c = a + b`, then auxiliary data (e.g., metadata) will be copied from the
        first instance of `MetaTensor` if `a.is_batch` is False
        (For batched data, the metadata will be shallow copied for efficiency purposes).
  
  Example:
      .. code-block:: python
  
          import torch
          from monai.data import MetaTensor
  
          t = torch.tensor([1,2,3])
          affine = torch.as_tensor([[2,0,0,0],
                                    [0,2,0,0],
                                    [0,0,2,0],
                                    [0,0,0,1]], dtype=torch.float64)
          meta = {"some": "info"}
          m = MetaTensor(t, affine=affine, meta=meta)
          m2 = m + m
          assert isinstance(m2, MetaTensor)
          assert m2.meta["some"] == "info"
          assert torch.all(m2.affine == affine)
  
  Notes:
      - Requires pytorch 1.9 or newer for full compatibility.
      - Older versions of pytorch (<=1.8), `torch.jit.trace(net, im)` may
        not work if `im` is of type `MetaTensor`. This can be resolved with
        `torch.jit.trace(net, im.as_tensor())`.
      - For pytorch < 1.8, sharing `MetaTensor` instances across processes may not be supported.
      - For pytorch < 1.9, next(iter(meta_tensor)) returns a torch.Tensor.
        see: https://github.com/pytorch/pytorch/issues/54457
      - A warning will be raised if in the constructor `affine` is not `None` and
        `meta` already contains the key `affine`.
      - You can query whether the `MetaTensor` is a batch with the `is_batch` attribute.
      - With a batch of data, `batch[0]` will return the 0th image
        with the 0th metadata. When the batch dimension is non-singleton, e.g.,
        `batch[:, 0]`, `batch[..., -1]` and `batch[1:3]`, then all (or a subset in the
        last example) of the metadata will be returned, and `is_batch` will return `True`.
      - When creating a batch with this class, use `monai.data.DataLoader` as opposed
        to `torch.utils.data.DataLoader`, as this will take care of collating the
        metadata properly.
class_docstr_tok: ["Class","that","inherits","from","both","`","torch.Tensor","`","and","`","MetaObj","`",",","adding","support","for","metadata",".","Metadata","is","stored","in","the","form","of","a","dictionary",".","Nested",",","an","affine","matrix","will","be","stored",".","This","should","be","in","the","form","of","`","torch.Tensor","`",".","Behavior","should","be","the","same","as","`","torch.Tensor","`","aside","from","the","extended","meta","functionality",".","Copying","of","information",":","*","For","`","c","=","a","+","b","`",",","then","auxiliary","data","(","e.g.",",","metadata",")","will","be","copied","from","the","first","instance","of","`","MetaTensor","`","if","`","a.is_batch","`","is","False","(","For","batched","data",",","the","metadata","will","be","shallow","copied","for","efficiency","purposes",")",".","Example",":","..","code-block",":",":","python","import","torch","from","monai.data","import","MetaTensor","t","=","torch.tensor","(","[","1,2,3","]",")","affine","=","torch.as_tensor","(","[","[","2,0,0,0","]",",","[","0,2,0,0","]",",","[","0,0,2,0","]",",","[","0,0,0,1","]","]",",","dtype=torch.float64",")","meta","=","{","``","some","''",":","``","info","''","}","m","=","MetaTensor","(","t",",","affine=affine",",","meta=meta",")","m2","=","m","+","m","assert","isinstance","(","m2",",","MetaTensor",")","assert","m2.meta","[","``","some","''","]","==","``","info","''","assert","torch.all","(","m2.affine","==","affine",")","Notes",":","-","Requires","pytorch","1.9","or","newer","for","full","compatibility",".","-","Older","versions","of","pytorch","(","<","=1.8",")",",","`","torch.jit.trace","(","net",",","im",")","`","may","not","work","if","`","im","`","is","of","type","`","MetaTensor","`",".","This","can","be","resolved","with","`","torch.jit.trace","(","net",",","im.as_tensor","(",")",")","`",".","-","For","pytorch","<","1.8",",","sharing","`","MetaTensor","`","instances","across","processes","may","not","be","supported",".","-","For","pytorch","<","1.9",",","next","(","iter","(","meta_tensor",")",")","returns","a","torch.Tensor",".","see",":","https",":","\/\/github.com\/pytorch\/pytorch\/issues\/54457","-","A","warning","will","be","raised","if","in","the","constructor","`","affine","`","is","not","`","None","`","and","`","meta","`","already","contains","the","key","`","affine","`",".","-","You","can","query","whether","the","`","MetaTensor","`","is","a","batch","with","the","`","is_batch","`","attribute",".","-","With","a","batch","of","data",",","`","batch","[","0","]","`","will","return","the","0th","image","with","the","0th","metadata",".","When","the","batch","dimension","is","non-singleton",",","e.g.",",","`","batch","[",":",",","0","]","`",",","`","batch","[","...",",","-1","]","`","and","`","batch","[","1:3","]","`",",","then","all","(","or","a","subset","in","the","last","example",")","of","the","metadata","will","be","returned",",","and","`","is_batch","`","will","return","`","True","`",".","-","When","creating","a","batch","with","this","class",",","use","`","monai.data.DataLoader","`","as","opposed","to","`","torch.utils.data.DataLoader","`",",","as","this","will","take","care","of","collating","the","metadata","properly","."]
docstr: Update the metadata from the output of `MetaTensor.__torch_function__`.
  
  The output of `torch.Tensor.__torch_function__` could be a single object or a
  sequence of them. Hence, in `MetaTensor.__torch_function__` we convert them to a
  list of not already, and then we loop across each element, processing metadata
  as necessary. For each element, if not of type `MetaTensor`, then nothing to do.
  
  Args:
      rets: the output from `torch.Tensor.__torch_function__`, which has been
          converted to a list in `MetaTensor.__torch_function__` if it wasn't
          already a `Sequence`.
      func: the torch function that was applied. Examples might be `torch.squeeze`
          or `torch.Tensor.__add__`. We need this since the metadata need to be
          treated differently if a batch of data is considered. For example,
          slicing (`torch.Tensor.__getitem__`) the ith element of the 0th
          dimension of a batch of data should return a ith tensor with the ith
          metadata.
      args: positional arguments that were passed to `func`.
      kwargs: keyword arguments that were passed to `func`.
  
  Returns:
      A sequence with the same number of elements as `rets`. For each element, if
      the input type was not `MetaTensor`, then no modifications will have been
      made. If global parameters have been set to false (e.g.,
      `not get_track_meta()`), then any `MetaTensor` will be converted to
      `torch.Tensor`. Else, metadata will be propagated as necessary (see
      :py:func:`MetaTensor._copy_meta`).
docstr_tok: ["Update","the","metadata","from","the","output","of","`","MetaTensor.__torch_function__","`",".","The","output","of","`","torch.Tensor.__torch_function__","`","could","be","a","single","object","or","a","sequence","of","them",".","Hence",",","in","`","MetaTensor.__torch_function__","`","we","convert","them","to","a","list","of","not","already",",","and","then","we","loop","across","each","element",",","processing","metadata","as","necessary",".","For","each","element",",","if","not","of","type","`","MetaTensor","`",",","then","nothing","to","do",".","Args",":","rets",":","the","output","from","`","torch.Tensor.__torch_function__","`",",","which","has","been","converted","to","a","list","in","`","MetaTensor.__torch_function__","`","if","it","wasn't","already","a","`","Sequence","`",".","func",":","the","torch","function","that","was","applied",".","Examples","might","be","`","torch.squeeze","`","or","`","torch.Tensor.__add__","`",".","We","need","this","since","the","metadata","need","to","be","treated","differently","if","a","batch","of","data","is","considered",".","For","example",",","slicing","(","`","torch.Tensor.__getitem__","`",")","the","ith","element","of","the","0th","dimension","of","a","batch","of","data","should","return","a","ith","tensor","with","the","ith","metadata",".","args",":","positional","arguments","that","were","passed","to","`","func","`",".","kwargs",":","keyword","arguments","that","were","passed","to","`","func","`",".","Returns",":","A","sequence","with","the","same","number","of","elements","as","`","rets","`",".","For","each","element",",","if","the","input","type","was","not","`","MetaTensor","`",",","then","no","modifications","will","have","been","made",".","If","global","parameters","have","been","set","to","false","(","e.g.",",","`","not","get_track_meta","(",")","`",")",",","then","any","`","MetaTensor","`","will","be","converted","to","`","torch.Tensor","`",".","Else",",","metadata","will","be","propagated","as","necessary","(","see",":","py",":","func",":","`","MetaTensor._copy_meta","`",")","."]
code: def update_meta(rets: Sequence, func, args, kwargs) -> Sequence:
      """
      Update the metadata from the output of `MetaTensor.__torch_function__`.
  
      The output of `torch.Tensor.__torch_function__` could be a single object or a
      sequence of them. Hence, in `MetaTensor.__torch_function__` we convert them to a
      list of not already, and then we loop across each element, processing metadata
      as necessary. For each element, if not of type `MetaTensor`, then nothing to do.
  
      Args:
          rets: the output from `torch.Tensor.__torch_function__`, which has been
              converted to a list in `MetaTensor.__torch_function__` if it wasn't
              already a `Sequence`.
          func: the torch function that was applied. Examples might be `torch.squeeze`
              or `torch.Tensor.__add__`. We need this since the metadata need to be
              treated differently if a batch of data is considered. For example,
              slicing (`torch.Tensor.__getitem__`) the ith element of the 0th
              dimension of a batch of data should return a ith tensor with the ith
              metadata.
          args: positional arguments that were passed to `func`.
          kwargs: keyword arguments that were passed to `func`.
  
      Returns:
          A sequence with the same number of elements as `rets`. For each element, if
          the input type was not `MetaTensor`, then no modifications will have been
          made. If global parameters have been set to false (e.g.,
          `not get_track_meta()`), then any `MetaTensor` will be converted to
          `torch.Tensor`. Else, metadata will be propagated as necessary (see
          :py:func:`MetaTensor._copy_meta`).
      """
      out = []
      metas = None  # optional output metadicts for each of the return value in `rets`
      is_batch = any(
          x.is_batch
          for x in MetaObj.flatten_meta_objs(args, kwargs.values())
          if hasattr(x, "is_batch")
      )
      for idx, ret in enumerate(rets):
          # if not `MetaTensor`, nothing to do.
          if not isinstance(ret, MetaTensor):
              pass
          # if not tracking, convert to `torch.Tensor`.
          elif not get_track_meta():
              ret = ret.as_tensor()
          # else, handle the `MetaTensor` metadata.
          else:
              meta_args = MetaObj.flatten_meta_objs(
                  args, kwargs.values()
              )
              ret.is_batch = is_batch
              ret.copy_meta_from(meta_args, copy_attr=not is_batch)
              # the following is not implemented but the network arch may run into this case:
              # if func == torch.cat and any(m.is_batch if hasattr(m, "is_batch") else False for m in meta_args):
              #     raise NotImplementedError("torch.cat is not implemented for batch of MetaTensors.")
              if is_batch:
                  ret = MetaTensor._handle_batched(
                      ret, idx, metas, func, args, kwargs
                  )
          out.append(ret)
      # if the input was a tuple, then return it as a tuple
      return tuple(out) if isinstance(rets, tuple) else out
  
imports: from __future__ import annotations
  import functools
  import warnings
  from copy import deepcopy
  from typing import Any, Sequence
  import numpy
  import torch
  import monai
  from monai.config.type_definitions import NdarrayTensor
  from monai.data.meta_obj import MetaObj, get_track_meta
  from monai.data.utils import affine_to_spacing, decollate_batch, list_data_collate, remove_extra_metadata
  from monai.utils import look_up_option
  from monai.utils.enums import LazyAttr, MetaKeys, PostFix, SpaceKeys
  from monai.utils.type_conversion import convert_data_type, convert_to_dst_type, convert_to_numpy, convert_to_tensor
label_desc: Use image node_id 3 for calling the MetaTensor obj's underlying member method code with example usage: obj.update_meta(rets, func, args, kwargs) and returns: unknown