class_docstr: The class is a collection of utilities to write images to disk.
  
  Main aspects to be considered are:
  
      - dimensionality of the data array, arrangements of spatial dimensions and channel/time dimensions
          - ``convert_to_channel_last()``
      - metadata of the current affine and output affine, the data array should be converted accordingly
          - ``get_meta_info()``
          - ``resample_if_needed()``
      - data type handling of the output image (as part of ``resample_if_needed()``)
  
  Subclasses of this class should implement the backend-specific functions:
  
      - ``set_data_array()`` to set the data array (input must be numpy array or torch tensor)
          - this method sets the backend object's data part
      - ``set_metadata()`` to set the metadata and output affine
          - this method sets the metadata including affine handling and image resampling
      - backend-specific data object ``create_backend_obj()``
      - backend-specific writing function ``write()``
  
  The primary usage of subclasses of ``ImageWriter`` is:
  
  .. code-block:: python
  
      writer = MyWriter()  # subclass of ImageWriter
      writer.set_data_array(data_array)
      writer.set_metadata(meta_dict)
      writer.write(filename)
  
  This creates an image writer object based on ``data_array`` and ``meta_dict`` and write to ``filename``.
  
  It supports up to three spatial dimensions (with the resampling step supports for both 2D and 3D).
  When saving multiple time steps or multiple channels `data_array`, time
  and/or modality axes should be the at the `channel_dim`. For example,
  the shape of a 2D eight-class and ``channel_dim=0``, the segmentation
  probabilities to be saved could be `(8, 64, 64)`; in this case
  ``data_array`` will be converted to `(64, 64, 1, 8)` (the third
  dimension is reserved as a spatial dimension).
  
  The ``metadata`` could optionally have the following keys:
  
      - ``'original_affine'``: for data original affine, it will be the
          affine of the output object, defaulting to an identity matrix.
      - ``'affine'``: it should specify the current data affine, defaulting to an identity matrix.
      - ``'spatial_shape'``: for data output spatial shape.
  
  When ``metadata`` is specified, the saver will may resample data from the space defined by
  `"affine"` to the space defined by `"original_affine"`, for more details, please refer to the
  ``resample_if_needed`` method.
class_docstr_tok: ["The","class","is","a","collection","of","utilities","to","write","images","to","disk",".","Main","aspects","to","be","considered","are",":","-","dimensionality","of","the","data","array",",","arrangements","of","spatial","dimensions","and","channel\/time","dimensions","-","``","convert_to_channel_last","(",")","``","-","metadata","of","the","current","affine","and","output","affine",",","the","data","array","should","be","converted","accordingly","-","``","get_meta_info","(",")","``","-","``","resample_if_needed","(",")","``","-","data","type","handling","of","the","output","image","(","as","part","of","``","resample_if_needed","(",")","``",")","Subclasses","of","this","class","should","implement","the","backend-specific","functions",":","-","``","set_data_array","(",")","``","to","set","the","data","array","(","input","must","be","numpy","array","or","torch","tensor",")","-","this","method","sets","the","backend","object","'s","data","part","-","``","set_metadata","(",")","``","to","set","the","metadata","and","output","affine","-","this","method","sets","the","metadata","including","affine","handling","and","image","resampling","-","backend-specific","data","object","``","create_backend_obj","(",")","``","-","backend-specific","writing","function","``","write","(",")","``","The","primary","usage","of","subclasses","of","``","ImageWriter","``","is",":","..","code-block",":",":","python","writer","=","MyWriter","(",")","#","subclass","of","ImageWriter","writer.set_data_array","(","data_array",")","writer.set_metadata","(","meta_dict",")","writer.write","(","filename",")","This","creates","an","image","writer","object","based","on","``","data_array","``","and","``","meta_dict","``","and","write","to","``","filename","``",".","It","supports","up","to","three","spatial","dimensions","(","with","the","resampling","step","supports","for","both","2D","and","3D",")",".","When","saving","multiple","time","steps","or","multiple","channels","`","data_array","`",",","time","and\/or","modality","axes","should","be","the","at","the","`","channel_dim","`",".","For","example",",","the","shape","of","a","2D","eight-class","and","``","channel_dim=0","``",",","the","segmentation","probabilities","to","be","saved","could","be","`","(","8",",","64",",","64",")","`",";","in","this","case","``","data_array","``","will","be","converted","to","`","(","64",",","64",",","1",",","8",")","`","(","the","third","dimension","is","reserved","as","a","spatial","dimension",")",".","The","``","metadata","``","could","optionally","have","the","following","keys",":","-","``","'original_affine","'","``",":","for","data","original","affine",",","it","will","be","the","affine","of","the","output","object",",","defaulting","to","an","identity","matrix",".","-","``","'affine","'","``",":","it","should","specify","the","current","data","affine",",","defaulting","to","an","identity","matrix",".","-","``","'spatial_shape","'","``",":","for","data","output","spatial","shape",".","When","``","metadata","``","is","specified",",","the","saver","will","may","resample","data","from","the","space","defined","by","`","``","affine","''","`","to","the","space","defined","by","`","``","original_affine","''","`",",","for","more","details",",","please","refer","to","the","``","resample_if_needed","``","method","."]
docstr: Convert the ``data_array`` into the coordinate system specified by
  ``target_affine``, from the current coordinate definition of ``affine``.
  
  If the transform between ``affine`` and ``target_affine`` could be
  achieved by simply transposing and flipping ``data_array``, no resampling
  will happen.  Otherwise, this function resamples ``data_array`` using the
  transformation computed from ``affine`` and ``target_affine``.
  
  This function assumes the NIfTI dimension notations. Spatially it
  supports up to three dimensions, that is, H, HW, HWD for 1D, 2D, 3D
  respectively. When saving multiple time steps or multiple channels,
  time and/or modality axes should be appended after the first three
  dimensions. For example, shape of 2D eight-class segmentation
  probabilities to be saved could be `(64, 64, 1, 8)`. Also, data in
  shape `(64, 64, 8)` or `(64, 64, 8, 1)` will be considered as a
  single-channel 3D image. The ``convert_to_channel_last`` method can be
  used to convert the data to the format described here.
  
  Note that the shape of the resampled ``data_array`` may subject to some
  rounding errors. For example, resampling a 20x20 pixel image from pixel
  size (1.5, 1.5)-mm to (3.0, 3.0)-mm space will return a 10x10-pixel
  image. However, resampling a 20x20-pixel image from pixel size (2.0,
  2.0)-mm to (3.0, 3.0)-mm space will output a 14x14-pixel image, where
  the image shape is rounded from 13.333x13.333 pixels. In this case
  ``output_spatial_shape`` could be specified so that this function
  writes image data to a designated shape.
  
  Args:
      data_array: input data array to be converted.
      affine: the current affine of ``data_array``. Defaults to identity
      target_affine: the designated affine of ``data_array``.
          The actual output affine might be different from this value due to precision changes.
      output_spatial_shape: spatial shape of the output image.
          This option is used when resampling is needed.
      mode: available options are {``"bilinear"``, ``"nearest"``, ``"bicubic"``}.
          This option is used when resampling is needed.
          Interpolation mode to calculate output values. Defaults to ``"bilinear"``.
          See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
      padding_mode: available options are {``"zeros"``, ``"border"``, ``"reflection"``}.
          This option is used when resampling is needed.
          Padding mode for outside grid values. Defaults to ``"border"``.
          See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
      align_corners: boolean option of ``grid_sample`` to handle the corner convention.
          See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
      dtype: data type for resampling computation. Defaults to
          ``np.float64`` for best precision. If ``None``, use the data type of input data.
          The output data type of this method is always ``np.float32``.
docstr_tok: ["Convert","the","``","data_array","``","into","the","coordinate","system","specified","by","``","target_affine","``",",","from","the","current","coordinate","definition","of","``","affine","``",".","If","the","transform","between","``","affine","``","and","``","target_affine","``","could","be","achieved","by","simply","transposing","and","flipping","``","data_array","``",",","no","resampling","will","happen",".","Otherwise",",","this","function","resamples","``","data_array","``","using","the","transformation","computed","from","``","affine","``","and","``","target_affine","``",".","This","function","assumes","the","NIfTI","dimension","notations",".","Spatially","it","supports","up","to","three","dimensions",",","that","is",",","H",",","HW",",","HWD","for","1D",",","2D",",","3D","respectively",".","When","saving","multiple","time","steps","or","multiple","channels",",","time","and\/or","modality","axes","should","be","appended","after","the","first","three","dimensions",".","For","example",",","shape","of","2D","eight-class","segmentation","probabilities","to","be","saved","could","be","`","(","64",",","64",",","1",",","8",")","`",".","Also",",","data","in","shape","`","(","64",",","64",",","8",")","`","or","`","(","64",",","64",",","8",",","1",")","`","will","be","considered","as","a","single-channel","3D","image",".","The","``","convert_to_channel_last","``","method","can","be","used","to","convert","the","data","to","the","format","described","here",".","Note","that","the","shape","of","the","resampled","``","data_array","``","may","subject","to","some","rounding","errors",".","For","example",",","resampling","a","20x20","pixel","image","from","pixel","size","(","1.5",",","1.5",")","-mm","to","(","3.0",",","3.0",")","-mm","space","will","return","a","10x10-pixel","image",".","However",",","resampling","a","20x20-pixel","image","from","pixel","size","(","2.0",",","2.0",")","-mm","to","(","3.0",",","3.0",")","-mm","space","will","output","a","14x14-pixel","image",",","where","the","image","shape","is","rounded","from","13.333x13.333","pixels",".","In","this","case","``","output_spatial_shape","``","could","be","specified","so","that","this","function","writes","image","data","to","a","designated","shape",".","Args",":","data_array",":","input","data","array","to","be","converted",".","affine",":","the","current","affine","of","``","data_array","``",".","Defaults","to","identity","target_affine",":","the","designated","affine","of","``","data_array","``",".","The","actual","output","affine","might","be","different","from","this","value","due","to","precision","changes",".","output_spatial_shape",":","spatial","shape","of","the","output","image",".","This","option","is","used","when","resampling","is","needed",".","mode",":","available","options","are","{","``","``","bilinear","''","``",",","``","``","nearest","''","``",",","``","``","bicubic","''","``","}",".","This","option","is","used","when","resampling","is","needed",".","Interpolation","mode","to","calculate","output","values",".","Defaults","to","``","``","bilinear","''","``",".","See","also",":","https",":","\/\/pytorch.org\/docs\/stable\/nn.functional.html","#","grid-sample","padding_mode",":","available","options","are","{","``","``","zeros","''","``",",","``","``","border","''","``",",","``","``","reflection","''","``","}",".","This","option","is","used","when","resampling","is","needed",".","Padding","mode","for","outside","grid","values",".","Defaults","to","``","``","border","''","``",".","See","also",":","https",":","\/\/pytorch.org\/docs\/stable\/nn.functional.html","#","grid-sample","align_corners",":","boolean","option","of","``","grid_sample","``","to","handle","the","corner","convention",".","See","also",":","https",":","\/\/pytorch.org\/docs\/stable\/nn.functional.html","#","grid-sample","dtype",":","data","type","for","resampling","computation",".","Defaults","to","``","np.float64","``","for","best","precision",".","If","``","None","``",",","use","the","data","type","of","input","data",".","The","output","data","type","of","this","method","is","always","``","np.float32","``","."]
code: def resample_if_needed(
      cls,
      data_array: NdarrayOrTensor,
      affine: NdarrayOrTensor | None = None,
      target_affine: NdarrayOrTensor | None = None,
      output_spatial_shape: Sequence[int] | int | None = None,
      mode: str = GridSampleMode.BILINEAR,
      padding_mode: str = GridSamplePadMode.BORDER,
      align_corners: bool = False,
      dtype: DtypeLike = np.float64,
  ):
      """
      Convert the ``data_array`` into the coordinate system specified by
      ``target_affine``, from the current coordinate definition of ``affine``.
  
      If the transform between ``affine`` and ``target_affine`` could be
      achieved by simply transposing and flipping ``data_array``, no resampling
      will happen.  Otherwise, this function resamples ``data_array`` using the
      transformation computed from ``affine`` and ``target_affine``.
  
      This function assumes the NIfTI dimension notations. Spatially it
      supports up to three dimensions, that is, H, HW, HWD for 1D, 2D, 3D
      respectively. When saving multiple time steps or multiple channels,
      time and/or modality axes should be appended after the first three
      dimensions. For example, shape of 2D eight-class segmentation
      probabilities to be saved could be `(64, 64, 1, 8)`. Also, data in
      shape `(64, 64, 8)` or `(64, 64, 8, 1)` will be considered as a
      single-channel 3D image. The ``convert_to_channel_last`` method can be
      used to convert the data to the format described here.
  
      Note that the shape of the resampled ``data_array`` may subject to some
      rounding errors. For example, resampling a 20x20 pixel image from pixel
      size (1.5, 1.5)-mm to (3.0, 3.0)-mm space will return a 10x10-pixel
      image. However, resampling a 20x20-pixel image from pixel size (2.0,
      2.0)-mm to (3.0, 3.0)-mm space will output a 14x14-pixel image, where
      the image shape is rounded from 13.333x13.333 pixels. In this case
      ``output_spatial_shape`` could be specified so that this function
      writes image data to a designated shape.
  
      Args:
          data_array: input data array to be converted.
          affine: the current affine of ``data_array``. Defaults to identity
          target_affine: the designated affine of ``data_array``.
              The actual output affine might be different from this value due to precision changes.
          output_spatial_shape: spatial shape of the output image.
              This option is used when resampling is needed.
          mode: available options are {``"bilinear"``, ``"nearest"``, ``"bicubic"``}.
              This option is used when resampling is needed.
              Interpolation mode to calculate output values. Defaults to ``"bilinear"``.
              See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
          padding_mode: available options are {``"zeros"``, ``"border"``, ``"reflection"``}.
              This option is used when resampling is needed.
              Padding mode for outside grid values. Defaults to ``"border"``.
              See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
          align_corners: boolean option of ``grid_sample`` to handle the corner convention.
              See also: https://pytorch.org/docs/stable/nn.functional.html#grid-sample
          dtype: data type for resampling computation. Defaults to
              ``np.float64`` for best precision. If ``None``, use the data type of input data.
              The output data type of this method is always ``np.float32``.
      """
      orig_type = type(data_array)
      data_array = convert_to_tensor(data_array, track_meta=True)
      if affine is not None:
          data_array.affine = convert_to_tensor(affine, track_meta=False)  # type: ignore
      resampler = SpatialResample(
          mode=mode,
          padding_mode=padding_mode,
          align_corners=align_corners,
          dtype=dtype,
      )
      output_array = resampler(
          data_array[None], dst_affine=target_affine, spatial_size=output_spatial_shape  # type: ignore
      )
      # convert back at the end
      if isinstance(output_array, MetaTensor):
          output_array.applied_operations = []
      data_array, *_ = convert_data_type(
          output_array, output_type=orig_type
      )
      affine, *_ = convert_data_type(output_array.affine, output_type=orig_type)  # type: ignore
      return data_array[0], affine
  
imports: from __future__ import annotations
  from collections.abc import Mapping, Sequence
  from typing import TYPE_CHECKING, Any, cast
  import numpy
  from monai.apps.utils import get_logger
  from monai.config import DtypeLike, NdarrayOrTensor, PathLike
  from monai.data.meta_tensor import MetaTensor
  from monai.data.utils import affine_to_spacing, ensure_tuple, ensure_tuple_rep, orientation_ras_lps, to_affine_nd
  from monai.transforms.spatial.array import Resize, SpatialResample
  from monai.transforms.utils_pytorch_numpy_unification import ascontiguousarray, moveaxis
  from monai.utils import GridSampleMode, GridSamplePadMode, InterpolateMode, MetaKeys, OptionalImportError, SpaceKeys, convert_data_type, convert_to_tensor, get_equivalent_dtype, look_up_option, optional_import, require_pkg
label_desc: Use image node_id 6 for calling the ImageWriter obj's underlying member method code with example usage: obj.resample_if_needed(cls, data_array, affine, target_affine, output_spatial_shape, mode, padding_mode, align_corners, dtype) and returns: data_array,  affine