code: def call_projection_function(self, hist: Hist) -> Hist:
          
          # Restrict projection axis ranges
          for axis in self.projection_axes:
              logger.debug(f"Apply projection axes hist range: {axis.name}")
              axis.apply_range_set(hist)
  
          projected_hist = None
          if hasattr(hist, "ProjectionND") and hasattr(hist, "Projection"):
              # THnBase defines ProjectionND and Projection, so we will use those as proxies.
              projected_hist = self._project_THn(hist = hist)
          elif hasattr(hist, "ProjectionZ") and hasattr(hist, "Project3D"):
              # TH3 defines ProjectionZ and Project3D, so we will use those as proxies.
              projected_hist = self._project_TH3(hist = hist)
          elif hasattr(hist, "ProjectionX") and hasattr(hist, "ProjectionY"):
              # TH2 defines ProjectionX and ProjectionY, so we will use those as proxies.
              projected_hist = self._project_TH2(hist = hist)
          else:
              raise TypeError(type(hist), f"Could not recognize hist {hist} of type {type(hist)}")
  
          # Cleanup restricted axes
          self.cleanup_cuts(hist, cut_axes = self.projection_axes)
  
          return projected_hist
docs: Calls the actual projection function for the hist.
  
          Args:
              hist: Histogram from which the projections should be performed.
          Returns:
              The projected histogram.