class_docstr: Prediction pipeline:
  - receives a patched patient image (n_patches, c, y, x, (z)) from patient data loader.
  - forwards patches through model in chunks of batch_size. (method: batch_tiling_forward)
  - unmolds predictions (boxes and segmentations) to original patient coordinates. (method: spatial_tiling_forward)
  
  Ensembling (mode == 'test'):
  - for inference, forwards 4 mirrored versions of image to through model and unmolds predictions afterwards
    accordingly (method: data_aug_forward)
  - for inference, loads multiple parameter-sets of the trained model corresponding to different epochs. for each
    parameter-set loops over entire test set, runs prediction pipeline for each patient. (method: predict_test_set)
  
  Consolidation of predictions:
  - consolidates a patient's predictions (boxes, segmentations) collected over patches, data_aug- and temporal ensembling,
    performs clustering and weighted averaging (external function: apply_wbc_to_patient) to obtain consistent outptus.
  - for 2D networks, consolidates box predictions to 3D cubes via clustering (adaption of non-maximum surpression).
    (external function: merge_2D_to_3D_preds_per_patient)
  
  Ground truth handling:
  - dissmisses any ground truth boxes returned by the model (happens in validation mode, patch-based groundtruth)
  - if provided by data loader, adds 3D ground truth to the final predictions to be passed to the evaluator.
class_docstr_tok: ["Prediction","pipeline",":","-","receives","a","patched","patient","image","(","n_patches",",","c",",","y",",","x",",","(","z",")",")","from","patient","data","loader",".","-","forwards","patches","through","model","in","chunks","of","batch_size",".","(","method",":","batch_tiling_forward",")","-","unmolds","predictions","(","boxes","and","segmentations",")","to","original","patient","coordinates",".","(","method",":","spatial_tiling_forward",")","Ensembling","(","mode","==","'test","'",")",":","-","for","inference",",","forwards","4","mirrored","versions","of","image","to","through","model","and","unmolds","predictions","afterwards","accordingly","(","method",":","data_aug_forward",")","-","for","inference",",","loads","multiple","parameter-sets","of","the","trained","model","corresponding","to","different","epochs",".","for","each","parameter-set","loops","over","entire","test","set",",","runs","prediction","pipeline","for","each","patient",".","(","method",":","predict_test_set",")","Consolidation","of","predictions",":","-","consolidates","a","patient","'s","predictions","(","boxes",",","segmentations",")","collected","over","patches",",","data_aug-","and","temporal","ensembling",",","performs","clustering","and","weighted","averaging","(","external","function",":","apply_wbc_to_patient",")","to","obtain","consistent","outptus",".","-","for","2D","networks",",","consolidates","box","predictions","to","3D","cubes","via","clustering","(","adaption","of","non-maximum","surpression",")",".","(","external","function",":","merge_2D_to_3D_preds_per_patient",")","Ground","truth","handling",":","-","dissmisses","any","ground","truth","boxes","returned","by","the","model","(","happens","in","validation","mode",",","patch-based","groundtruth",")","-","if","provided","by","data","loader",",","adds","3D","ground","truth","to","the","final","predictions","to","be","passed","to","the","evaluator","."]
docstr: calls the actual network forward method. in patch-based prediction, the batch dimension might be overladed
  with n_patches >> batch_size, which would exceed gpu memory. In this case, batches are processed in chunks of
  batch_size. validation mode calls the train method to monitor losses (returned ground truth objects are discarded).
  test mode calls the test forward method, no ground truth required / involved.
  :return. results_dict: stores the results for one patient. dictionary with keys:
           - 'boxes': list over batch elements. each element is a list over boxes, where each box is
                      one dictionary: [[box_0, ...], [box_n,...]]. batch elements are slices for 2D predictions,
                      and a dummy batch dimension of 1 for 3D predictions.
           - 'seg_preds': pixel-wise predictions. (b, 1, y, x, (z))
           - monitor_values (only in validation mode)
docstr_tok: ["calls","the","actual","network","forward","method",".","in","patch-based","prediction",",","the","batch","dimension","might","be","overladed","with","n_patches",">",">","batch_size",",","which","would","exceed","gpu","memory",".","In","this","case",",","batches","are","processed","in","chunks","of","batch_size",".","validation","mode","calls","the","train","method","to","monitor","losses","(","returned","ground","truth","objects","are","discarded",")",".","test","mode","calls","the","test","forward","method",",","no","ground","truth","required","\/","involved",".",":","return",".","results_dict",":","stores","the","results","for","one","patient",".","dictionary","with","keys",":","-","'boxes","'",":","list","over","batch","elements",".","each","element","is","a","list","over","boxes",",","where","each","box","is","one","dictionary",":","[","[","box_0",",","...","]",",","[","box_n",",","...","]","]",".","batch","elements","are","slices","for","2D","predictions",",","and","a","dummy","batch","dimension","of","1","for","3D","predictions",".","-","'seg_preds","'",":","pixel-wise","predictions",".","(","b",",","1",",","y",",","x",",","(","z",")",")","-","monitor_values","(","only","in","validation","mode",")"]
code: def batch_tiling_forward(self, batch):
      """
      calls the actual network forward method. in patch-based prediction, the batch dimension might be overladed
      with n_patches >> batch_size, which would exceed gpu memory. In this case, batches are processed in chunks of
      batch_size. validation mode calls the train method to monitor losses (returned ground truth objects are discarded).
      test mode calls the test forward method, no ground truth required / involved.
      :return. results_dict: stores the results for one patient. dictionary with keys:
               - 'boxes': list over batch elements. each element is a list over boxes, where each box is
                          one dictionary: [[box_0, ...], [box_n,...]]. batch elements are slices for 2D predictions,
                          and a dummy batch dimension of 1 for 3D predictions.
               - 'seg_preds': pixel-wise predictions. (b, 1, y, x, (z))
               - monitor_values (only in validation mode)
      """
      self.logger.info(
          "forwarding (patched) patient with shape: {}".format(
              batch["data"].shape
          )
      )
  
      img = batch["data"]
  
      if img.shape[0] <= self.cf.batch_size:
          if self.mode == "val":
              # call training method to monitor losses
              results_dict = self.net.train_forward(
                  batch, is_validation=True
              )
              # discard returned ground-truth boxes (also training info boxes).
              results_dict["boxes"] = [
                  [box for box in b if box["box_type"] == "det"]
                  for b in results_dict["boxes"]
              ]
          else:
              results_dict = self.net.test_forward(
                  batch, return_masks=self.cf.return_masks_in_test
              )
  
      else:
          split_ixs = np.split(
              np.arange(img.shape[0]),
              np.arange(img.shape[0])[:: self.cf.batch_size],
          )
          chunk_dicts = []
          for chunk_ixs in split_ixs[
              1:
          ]:  # first split is elements before 0, so empty
              b = {
                  k: batch[k][chunk_ixs]
                  for k in batch.keys()
                  if (
                      isinstance(batch[k], np.ndarray)
                      and batch[k].shape[0] == img.shape[0]
                  )
              }
              if self.mode == "val":
                  chunk_dicts += [
                      self.net.train_forward(b, is_validation=True)
                  ]
              else:
                  chunk_dicts += [
                      self.net.test_forward(
                          b, return_masks=self.cf.return_masks_in_test
                      )
                  ]
  
          results_dict = {}
          # flatten out batch elements from chunks ([chunk, chunk] -> [b, b, b, b, ...])
          results_dict["boxes"] = [
              item for d in chunk_dicts for item in d["boxes"]
          ]
          results_dict["seg_preds"] = np.array(
              [item for d in chunk_dicts for item in d["seg_preds"]]
          )
  
          if self.mode == "val":
              # estimate metrics by mean over batch_chunks. Most similar to training metrics.
              results_dict["monitor_values"] = {
                  k: np.mean(
                      [d["monitor_values"][k] for d in chunk_dicts]
                  )
                  for k in chunk_dicts[0]["monitor_values"].keys()
              }
              # discard returned ground-truth boxes (also training info boxes).
              results_dict["boxes"] = [
                  [box for box in b if box["box_type"] == "det"]
                  for b in results_dict["boxes"]
              ]
  
      return results_dict
  
imports: import os
  import numpy
  import torch
  from scipy.stats import norm
  from collections import OrderedDict
  from multiprocessing import Pool
  import pickle
  import pandas
label_desc: Use image node_id 7 for calling the Predictor obj's underlying member method code with example usage: obj.batch_tiling_forward(batch) and returns: results_dict