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: loads raw predictions saved by self.predict_test_set. consolidates and merges 2D boxes to 3D cubes for evaluation.
  (if model predicts 2D but evaluation is run in 3D)
  :return: (optionally) list_of_results_per_patient: list over patient results. each entry is a dict 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
                      (if not merged to 3D), and a dummy batch dimension of 1 for 3D predictions.
           - 'seg_preds': not implemented yet. todo for evaluation of instance/semantic segmentation.
docstr_tok: ["loads","raw","predictions","saved","by","self.predict_test_set",".","consolidates","and","merges","2D","boxes","to","3D","cubes","for","evaluation",".","(","if","model","predicts","2D","but","evaluation","is","run","in","3D",")",":","return",":","(","optionally",")","list_of_results_per_patient",":","list","over","patient","results",".","each","entry","is","a","dict","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","(","if","not","merged","to","3D",")",",","and","a","dummy","batch","dimension","of","1","for","3D","predictions",".","-","'seg_preds","'",":","not","implemented","yet",".","todo","for","evaluation","of","instance\/semantic","segmentation","."]
code: def load_saved_predictions(self, apply_wbc=False):
      """
      loads raw predictions saved by self.predict_test_set. consolidates and merges 2D boxes to 3D cubes for evaluation.
      (if model predicts 2D but evaluation is run in 3D)
      :return: (optionally) list_of_results_per_patient: list over patient results. each entry is a dict 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
                          (if not merged to 3D), and a dummy batch dimension of 1 for 3D predictions.
               - 'seg_preds': not implemented yet. todo for evaluation of instance/semantic segmentation.
      """
  
      # load predictions for a single test-set fold.
      if not self.cf.hold_out_test_set:
          with open(
              os.path.join(
                  self.cf.fold_dir, "raw_pred_boxes_list.pickle"
              ),
              "rb",
          ) as handle:
              list_of_results_per_patient = pickle.load(handle)
          da_factor = 4 if self.cf.test_aug else 1
          n_ens = self.cf.test_n_epochs * da_factor
          self.logger.info(
              "loaded raw test set predictions with n_patients = {} and n_ens = {}".format(
                  len(list_of_results_per_patient), n_ens
              )
          )
  
      # if hold out test set was perdicted, aggregate predictions of all trained models
      # corresponding to all CV-folds and flatten them.
      else:
          boxes_list = []
          for fold in self.cf.folds:
              fold_dir = os.path.join(
                  self.cf.exp_dir, "fold_{}".format(fold)
              )
              with open(
                  os.path.join(
                      fold_dir, "raw_pred_boxes_hold_out_list.pickle"
                  ),
                  "rb",
              ) as handle:
                  fold_list = pickle.load(handle)
                  pids = [ii[1] for ii in fold_list]
                  boxes_list.append([ii[0] for ii in fold_list])
          list_of_results_per_patient = [
              [
                  [
                      [
                          box
                          for fold_list in boxes_list
                          for box in fold_list[pix][0]
                          if box["box_type"] == "det"
                      ]
                  ],
                  pid,
              ]
              for pix, pid in enumerate(pids)
          ]
          da_factor = 4 if self.cf.test_aug else 1
          n_ens = self.cf.test_n_epochs * da_factor * len(self.cf.folds)
  
      # consolidate predictions.
      if apply_wbc:
          self.logger.info(
              "applying wcs to test set predictions with iou = {} and n_ens = {}.".format(
                  self.cf.wcs_iou, n_ens
              )
          )
          pool = Pool(processes=6)
          mp_inputs = [
              [ii[0], ii[1], self.cf.class_dict, self.cf.wcs_iou, n_ens]
              for ii in list_of_results_per_patient
          ]
          list_of_results_per_patient = pool.map(
              apply_wbc_to_patient, mp_inputs, chunksize=1
          )
          pool.close()
          pool.join()
      else:
          list_of_results_per_patient = list_of_results_per_patient
  
      # merge 2D box predictions to 3D cubes (if model predicts 2D but evaluation is run in 3D)
      if self.cf.merge_2D_to_3D_preds:
          self.logger.info(
              "applying 2Dto3D merging to test set predictions with iou = {}.".format(
                  self.cf.merge_3D_iou
              )
          )
          pool = Pool(processes=6)
          mp_inputs = [
              [ii[0], ii[1], self.cf.class_dict, self.cf.merge_3D_iou]
              for ii in list_of_results_per_patient
          ]
          list_of_results_per_patient = pool.map(
              merge_2D_to_3D_preds_per_patient, mp_inputs, chunksize=1
          )
          pool.close()
          pool.join()
  
      return list_of_results_per_patient
  
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 4 for calling the Predictor obj's underlying member method code with example usage: obj.load_saved_predictions(apply_wbc) and returns: list_of_results_per_patient