class_docstr: This class computes the occlusion sensitivity for a model's prediction of a given image. By occlusion sensitivity,
  we mean how the probability of a given prediction changes as the occluded section of an image changes. This can be
  useful to understand why a network is making certain decisions.
  
  As important parts of the image are occluded, the probability of classifying the image correctly will decrease.
  Hence, more negative values imply the corresponding occluded volume was more important in the decision process.
  
  Two ``torch.Tensor`` will be returned by the ``__call__`` method: an occlusion map and an image of the most probable
  class. Both images will be cropped if a bounding box used, but voxel sizes will always match the input.
  
  The occlusion map shows the inference probabilities when the corresponding part of the image is occluded. Hence,
  more -ve values imply that region was important in the decision process. The map will have shape ``BCHW(D)N``,
  where ``N`` is the number of classes to be inferred by the network. Hence, the occlusion for class ``i`` can
  be seen with ``map[...,i]``.
  
  The most probable class is an image of the probable class when the corresponding part of the image is occluded
  (equivalent to ``occ_map.argmax(dim=-1)``).
  
  See: R. R. Selvaraju et al. Grad-CAM: Visual Explanations from Deep Networks via
  Gradient-based Localization. https://doi.org/10.1109/ICCV.2017.74.
  
  Examples:
  
  .. code-block:: python
  
      # densenet 2d
      from monai.networks.nets import DenseNet121
      from monai.visualize import OcclusionSensitivity
      import torch
  
      model_2d = DenseNet121(spatial_dims=2, in_channels=1, out_channels=3)
      occ_sens = OcclusionSensitivity(nn_module=model_2d)
      occ_map, most_probable_class = occ_sens(x=torch.rand((1, 1, 48, 64)), b_box=[2, 40, 1, 62])
  
      # densenet 3d
      from monai.networks.nets import DenseNet
      from monai.visualize import OcclusionSensitivity
  
      model_3d = DenseNet(spatial_dims=3, in_channels=1, out_channels=3, init_features=2, growth_rate=2, block_config=(6,))
      occ_sens = OcclusionSensitivity(nn_module=model_3d, n_batch=10)
      occ_map, most_probable_class = occ_sens(torch.rand(1, 1, 6, 6, 6), b_box=[1, 3, -1, -1, -1, -1])
  
  See Also:
  
      - :py:class:`monai.visualize.occlusion_sensitivity.OcclusionSensitivity.`
class_docstr_tok: ["This","class","computes","the","occlusion","sensitivity","for","a","model","'s","prediction","of","a","given","image",".","By","occlusion","sensitivity",",","we","mean","how","the","probability","of","a","given","prediction","changes","as","the","occluded","section","of","an","image","changes",".","This","can","be","useful","to","understand","why","a","network","is","making","certain","decisions",".","As","important","parts","of","the","image","are","occluded",",","the","probability","of","classifying","the","image","correctly","will","decrease",".","Hence",",","more","negative","values","imply","the","corresponding","occluded","volume","was","more","important","in","the","decision","process",".","Two","``","torch.Tensor","``","will","be","returned","by","the","``","__call__","``","method",":","an","occlusion","map","and","an","image","of","the","most","probable","class",".","Both","images","will","be","cropped","if","a","bounding","box","used",",","but","voxel","sizes","will","always","match","the","input",".","The","occlusion","map","shows","the","inference","probabilities","when","the","corresponding","part","of","the","image","is","occluded",".","Hence",",","more","-ve","values","imply","that","region","was","important","in","the","decision","process",".","The","map","will","have","shape","``","BCHW","(","D",")","N","``",",","where","``","N","``","is","the","number","of","classes","to","be","inferred","by","the","network",".","Hence",",","the","occlusion","for","class","``","i","``","can","be","seen","with","``","map","[","...",",","i","]","``",".","The","most","probable","class","is","an","image","of","the","probable","class","when","the","corresponding","part","of","the","image","is","occluded","(","equivalent","to","``","occ_map.argmax","(","dim=-1",")","``",")",".","See",":","R.","R.","Selvaraju","et","al",".","Grad-CAM",":","Visual","Explanations","from","Deep","Networks","via","Gradient-based","Localization",".","https",":","\/\/doi.org\/10.1109\/ICCV.2017.74",".","Examples",":","..","code-block",":",":","python","#","densenet","2d","from","monai.networks.nets","import","DenseNet121","from","monai.visualize","import","OcclusionSensitivity","import","torch","model_2d","=","DenseNet121","(","spatial_dims=2",",","in_channels=1",",","out_channels=3",")","occ_sens","=","OcclusionSensitivity","(","nn_module=model_2d",")","occ_map",",","most_probable_class","=","occ_sens","(","x=torch.rand","(","(","1",",","1",",","48",",","64",")",")",",","b_box=","[","2",",","40",",","1",",","62","]",")","#","densenet","3d","from","monai.networks.nets","import","DenseNet","from","monai.visualize","import","OcclusionSensitivity","model_3d","=","DenseNet","(","spatial_dims=3",",","in_channels=1",",","out_channels=3",",","init_features=2",",","growth_rate=2",",","block_config=","(","6",",",")",")","occ_sens","=","OcclusionSensitivity","(","nn_module=model_3d",",","n_batch=10",")","occ_map",",","most_probable_class","=","occ_sens","(","torch.rand","(","1",",","1",",","6",",","6",",","6",")",",","b_box=","[","1",",","3",",","-1",",","-1",",","-1",",","-1","]",")","See","Also",":","-",":","py",":","class",":","`","monai.visualize.occlusion_sensitivity.OcclusionSensitivity.","`"]
docstr: Args:
      x: Image to use for inference. Should be a tensor consisting of 1 batch.
      b_box: Bounding box on which to perform the analysis. The output image will be limited to this size.
          There should be a minimum and maximum for all spatial dimensions: ``[min1, max1, min2, max2,...]``.
          * By default, the whole image will be used. Decreasing the size will speed the analysis up, which might
              be useful for larger images.
          * Min and max are inclusive, so ``[0, 63, ...]`` will have size ``(64, ...)``.
          * Use -ve to use ``min=0`` and ``max=im.shape[x]-1`` for xth dimension.
          * N.B.: we add half of the mask size to the bounding box to ensure that the region of interest has a
              sufficiently large area surrounding it.
      kwargs: any extra arguments to be passed on to the module as part of its `__call__`.
  
  Returns:
      * Occlusion map:
          * Shows the inference probabilities when the corresponding part of the image is occluded.
              Hence, more -ve values imply that region was important in the decision process.
          * The map will have shape ``BCHW(D)N``, where N is the number of classes to be inferred by the
              network. Hence, the occlusion for class ``i`` can be seen with ``map[...,i]``.
          * If `per_channel==False`, output ``C`` will equal 1: ``B1HW(D)N``
      * Most probable class:
          * The most probable class when the corresponding part of the image is occluded (``argmax(dim=-1)``).
      Both images will be cropped if a bounding box used, but voxel sizes will always match the input.
docstr_tok: ["Args",":","x",":","Image","to","use","for","inference",".","Should","be","a","tensor","consisting","of","1","batch",".","b_box",":","Bounding","box","on","which","to","perform","the","analysis",".","The","output","image","will","be","limited","to","this","size",".","There","should","be","a","minimum","and","maximum","for","all","spatial","dimensions",":","``","[","min1",",","max1",",","min2",",","max2",",","...","]","``",".","*","By","default",",","the","whole","image","will","be","used",".","Decreasing","the","size","will","speed","the","analysis","up",",","which","might","be","useful","for","larger","images",".","*","Min","and","max","are","inclusive",",","so","``","[","0",",","63",",","...","]","``","will","have","size","``","(","64",",","...",")","``",".","*","Use","-ve","to","use","``","min=0","``","and","``","max=im.shape","[","x","]","-1","``","for","xth","dimension",".","*","N.B",".",":","we","add","half","of","the","mask","size","to","the","bounding","box","to","ensure","that","the","region","of","interest","has","a","sufficiently","large","area","surrounding","it",".","kwargs",":","any","extra","arguments","to","be","passed","on","to","the","module","as","part","of","its","`","__call__","`",".","Returns",":","*","Occlusion","map",":","*","Shows","the","inference","probabilities","when","the","corresponding","part","of","the","image","is","occluded",".","Hence",",","more","-ve","values","imply","that","region","was","important","in","the","decision","process",".","*","The","map","will","have","shape","``","BCHW","(","D",")","N","``",",","where","N","is","the","number","of","classes","to","be","inferred","by","the","network",".","Hence",",","the","occlusion","for","class","``","i","``","can","be","seen","with","``","map","[","...",",","i","]","``",".","*","If","`","per_channel==False","`",",","output","``","C","``","will","equal","1",":","``","B1HW","(","D",")","N","``","*","Most","probable","class",":","*","The","most","probable","class","when","the","corresponding","part","of","the","image","is","occluded","(","``","argmax","(","dim=-1",")","``",")",".","Both","images","will","be","cropped","if","a","bounding","box","used",",","but","voxel","sizes","will","always","match","the","input","."]
code: def __call__(
      self,
      x: torch.Tensor,
      b_box: Sequence | None = None,
      **kwargs: Any,
  ) -> tuple[torch.Tensor, torch.Tensor]:
      """
      Args:
          x: Image to use for inference. Should be a tensor consisting of 1 batch.
          b_box: Bounding box on which to perform the analysis. The output image will be limited to this size.
              There should be a minimum and maximum for all spatial dimensions: ``[min1, max1, min2, max2,...]``.
              * By default, the whole image will be used. Decreasing the size will speed the analysis up, which might
                  be useful for larger images.
              * Min and max are inclusive, so ``[0, 63, ...]`` will have size ``(64, ...)``.
              * Use -ve to use ``min=0`` and ``max=im.shape[x]-1`` for xth dimension.
              * N.B.: we add half of the mask size to the bounding box to ensure that the region of interest has a
                  sufficiently large area surrounding it.
          kwargs: any extra arguments to be passed on to the module as part of its `__call__`.
  
      Returns:
          * Occlusion map:
              * Shows the inference probabilities when the corresponding part of the image is occluded.
                  Hence, more -ve values imply that region was important in the decision process.
              * The map will have shape ``BCHW(D)N``, where N is the number of classes to be inferred by the
                  network. Hence, the occlusion for class ``i`` can be seen with ``map[...,i]``.
              * If `per_channel==False`, output ``C`` will equal 1: ``B1HW(D)N``
          * Most probable class:
              * The most probable class when the corresponding part of the image is occluded (``argmax(dim=-1)``).
          Both images will be cropped if a bounding box used, but voxel sizes will always match the input.
      """
      if x.shape[0] > 1:
          raise ValueError("Expected batch size of 1.")
  
      sd = x.ndim - 2
      mask_size: Sequence = ensure_tuple_rep(self.mask_size, sd)
  
      # get the meshgrid (so that sliding_window_inference can tell us which bit to occlude)
      grid: MetaTensor = MetaTensor(
          np.stack(
              np.meshgrid(
                  *[np.arange(0, i) for i in x.shape[2:]], indexing="ij"
              )
          )[None],
          device=x.device,
          dtype=x.dtype,
      )
      # if bounding box given, crop the grid to only infer subsections of the image
      if b_box is not None:
          grid, cropper, mask_size = self.crop_meshgrid(
              grid, b_box, mask_size
          )
  
      # check that the grid is bigger than the mask size
      if any(m > g for g, m in zip(grid.shape[2:], mask_size)):
          raise ValueError(
              f"Image (spatial shape) {grid.shape[2:]} should be bigger than mask {mask_size}."
          )
  
      # get additive and multiplicative factors if they are unchanged for all patches (i.e., not mean_patch)
      add: float | torch.Tensor | None
      mul: float | torch.Tensor | None
      # multiply by 0, add value
      if isinstance(self.mode, float):
          mul, add = self.constant_occlusion(x, self.mode, mask_size)
      # multiply by 0, add mean of image
      elif self.mode == "mean_img":
          mul, add = self.constant_occlusion(
              x, x.mean().item(), mask_size
          )
      # for gaussian, additive = 0, multiplicative = gaussian
      elif self.mode == "gaussian":
          mul, add = self.gaussian_occlusion(x, mask_size)
      # else will be determined on each patch individually so calculated later
      else:
          add, mul = None, None
  
      with eval_mode(self.nn_module):
          # needs to go here to avoid circular import
          from monai.inferers import sliding_window_inference
  
          sensitivity_im: MetaTensor = sliding_window_inference(  # type: ignore
              grid,
              roi_size=mask_size,
              sw_batch_size=self.n_batch,
              predictor=OcclusionSensitivity.predictor,
              overlap=self.overlap,
              mode="gaussian"
              if self.mode == "gaussian"
              else "constant",
              progress=self.verbose,
              nn_module=self.nn_module,
              x=x,
              add=add,
              mul=mul,
              mask_size=mask_size,
              occ_mode=self.mode,
              activate=self.activate,
              module_kwargs=kwargs,
          )
  
      if b_box is not None:
          # undo the cropping that was applied to the meshgrid
          sensitivity_im = cropper.inverse(sensitivity_im[0])[None]  # type: ignore
          # crop using the bounding box (ignoring the mask size this time)
          bbox_min = [max(b, 0) for b in b_box[::2]]
          bbox_max = [
              b if b > 0 else s
              for b, s in zip(b_box[1::2], x.shape[2:])
          ]
          cropper = SpatialCrop(roi_start=bbox_min, roi_end=bbox_max)
          sensitivity_im = cropper(sensitivity_im[0])[None]  # type: ignore
  
      # The most probable class is the max in the classification dimension (1)
      most_probable_class = sensitivity_im.argmax(dim=1, keepdim=True)
      return sensitivity_im, most_probable_class
  
file_path: MONAI/monai/visualize/occlusion_sensitivity.py
imports: from __future__ import annotations
  from collections.abc import Callable, Mapping, Sequence
  from typing import Any
  import numpy
  import torch
  import torch.nn
  from monai.data.meta_tensor import MetaTensor
  from monai.networks.utils import eval_mode
  from monai.transforms import Compose, GaussianSmooth, Lambda, ScaleIntensity, SpatialCrop
  from monai.utils import ensure_tuple_rep
label_desc: Use image node_id 6 for calling the OcclusionSensitivity obj's underlying member method code with example usage: obj.__call__(x, b_box) and returns: sensitivity_im,  most_probable_class