code: def plan_experiment(self):
      use_nonzero_mask_for_normalization = (
          self.determine_whether_to_use_mask_for_norm()
      )
      if use_nonzero_mask_for_normalization:
          print("We are using the nonzero mask for normalization.")
      else:
          print("We do not use the nonzero mask for normalization.")
      spacings = self.dataset_properties["all_spacings"]
      sizes = self.dataset_properties["all_sizes"]
  
      all_classes = self.dataset_properties["all_classes"]
      modalities = self.dataset_properties["modalities"]
      num_modalities = len(list(modalities.keys()))
  
      target_spacing = self.get_target_spacing()
      new_shapes = [
          np.array(i) / target_spacing * np.array(j)
          for i, j in zip(spacings, sizes)
      ]
  
      max_spacing_axis = np.argmax(target_spacing)
      remaining_axes = [
          i for i in list(range(3)) if i != max_spacing_axis
      ]
      self.transpose_forward = [max_spacing_axis] + remaining_axes
      self.transpose_backward = [
          np.argwhere(np.array(self.transpose_forward) == i)[0][0]
          for i in range(3)
      ]
  
      median_shape = np.median(np.vstack(new_shapes), 0)
      print(
          "The median shape of the dataset is {}.".format(median_shape)
      )
  
      max_shape = np.max(np.vstack(new_shapes), 0)
      print("The max shape in the dataset is {}.".format(max_shape))
      min_shape = np.min(np.vstack(new_shapes), 0)
      print("The min shape in the dataset is {}.".format(min_shape))
  
      print(
          "Feature maps in model will greater than {} in the bottleneck.".format(
              self.unet_featuremap_min_edge_length
          )
      )
  
      self.plans_per_stage = list()
  
      target_spacing_transposed = np.array(target_spacing)[
          self.transpose_forward
      ]
      median_shape_transposed = np.array(median_shape)[
          self.transpose_forward
      ]
      print(
          "The transposed median shape of the dataset is {}.".format(
              median_shape_transposed
          )
      )
  
      print("Generating configuration for 3d_fullres")
      self.plans_per_stage.append(
          self.get_properties_for_stage(
              target_spacing_transposed,
              target_spacing_transposed,
              median_shape_transposed,
              len(self.list_of_cropped_npz_files),
              num_modalities,
              len(all_classes) + 1,
          )
      )
  
      architecture_input_voxels_here = np.prod(
          self.plans_per_stage[-1]["patch_size"], dtype=np.int64
      )
      if (
          np.prod(median_shape) / architecture_input_voxels_here
          < self.how_much_of_a_patient_must_the_network_see_at_stage0
      ):
          gen_lowres_config = False
      else:
          gen_lowres_config = True
  
      if gen_lowres_config:
          print("Generating configuration for 3d_lowres")
          lowres_stage_spacing = deepcopy(target_spacing)
          num_voxels = np.prod(median_shape, dtype=np.float64)
          while (
              num_voxels
              > self.how_much_of_a_patient_must_the_network_see_at_stage0
              * architecture_input_voxels_here
          ):
              max_spacing = max(lowres_stage_spacing)
              if np.any((max_spacing / lowres_stage_spacing) > 2):
                  lowres_stage_spacing[
                      (max_spacing / lowres_stage_spacing) > 2
                  ] *= 1.01
              else:
                  lowres_stage_spacing *= 1.01
              num_voxels = np.prod(
                  target_spacing / lowres_stage_spacing * median_shape,
                  dtype=np.float64,
              )
  
              lowres_stage_spacing_transposed = np.array(
                  lowres_stage_spacing
              )[self.transpose_forward]
              lowres_props = self.get_properties_for_stage(
                  lowres_stage_spacing_transposed,
                  target_spacing_transposed,
                  median_shape_transposed,
                  len(self.list_of_cropped_npz_files),
                  num_modalities,
                  len(all_classes) + 1,
              )
              architecture_input_voxels_here = np.prod(
                  lowres_props["patch_size"], dtype=np.int64
              )
          if 2 * np.prod(
              lowres_props["median_patient_size_in_voxels"],
              dtype=np.int64,
          ) < np.prod(
              self.plans_per_stage[0]["median_patient_size_in_voxels"],
              dtype=np.int64,
          ):
              self.plans_per_stage.append(lowres_props)
  
      self.plans_per_stage = self.plans_per_stage[::-1]
      self.plans_per_stage = {
          i: self.plans_per_stage[i]
          for i in range(len(self.plans_per_stage))
      }
  
      print(self.plans_per_stage)
      print("transpose forward", self.transpose_forward)
      print("transpose backward", self.transpose_backward)
  
      normalization_schemes = self.determine_normalization_scheme()
      (
          only_keep_largest_connected_component,
          min_size_per_class,
          min_region_size_per_class,
      ) = (None, None, None)
  
      plans = {
          "num_stages": len(list(self.plans_per_stage.keys())),
          "num_modalities": num_modalities,
          "modalities": modalities,
          "normalization_schemes": normalization_schemes,
          "dataset_properties": self.dataset_properties,
          "list_of_npz_files": self.list_of_cropped_npz_files,
          "original_spacings": spacings,
          "original_sizes": sizes,
          "preprocessed_data_folder": self.preprocessed_output_folder,
          "num_classes": len(all_classes),
          "all_classes": all_classes,
          "base_num_features": self.unet_base_num_features,
          "use_mask_for_norm": use_nonzero_mask_for_normalization,
          "keep_only_largest_region": only_keep_largest_connected_component,
          "min_region_size_per_class": min_region_size_per_class,
          "min_size_per_class": min_size_per_class,
          "transpose_forward": self.transpose_forward,
          "transpose_backward": self.transpose_backward,
          "data_identifier": self.data_identifier,
          "plans_per_stage": self.plans_per_stage,
          "preprocessor_name": self.preprocessor_name.__name__,
          "conv_per_stage": self.conv_per_stage,
      }
  
      self.plans = plans
      self.save_my_plans()
  
imports: import os
  import pickle
  import shutil
  from collections import OrderedDict
  from .image_crop import get_case_identifier_from_npz
  from .preprocessing import GenericPreprocessor, PreprocessorFor2D
  from .experiment_utils import *
  from .path_utils import join_paths
label_desc: Use image node_id 6 for calling the ExperimentPlanner obj's underlying member method code with example usage: obj.plan_experiment() without return types