code: def get_properties_for_stage(
      self,
      current_spacing,
      original_spacing,
      original_shape,
      num_cases,
      num_modalities,
      num_classes,
  ):
      new_median_shape = np.round(
          original_spacing / current_spacing * original_shape
      ).astype(int)
  
      dataset_num_voxels = (
          np.prod(new_median_shape, dtype=np.int64) * num_cases
      )
      input_patch_size = new_median_shape[1:]
  
      (
          network_num_pool_per_axis,
          pool_op_kernel_sizes,
          conv_kernel_sizes,
          new_shape,
          shape_must_be_divisible_by,
      ) = get_pool_and_conv_props(
          current_spacing[1:],
          input_patch_size,
          self.unet_featuremap_min_edge_length,
          self.unet_max_numpool,
      )
  
      ref = (
          use_this_for_batch_size_computation_2D
          * DEFAULT_BATCH_SIZE_2D
          / 2
      )
      here = compute_approx_vram_consumption(
          new_shape,
          network_num_pool_per_axis,
          30,
          self.unet_max_num_filters,
          num_modalities,
          num_classes,
          pool_op_kernel_sizes,
          conv_per_stage=self.conv_per_stage,
      )
      while here > ref:
          axis_to_be_reduced = np.argsort(
              new_shape / new_median_shape[1:]
          )[-1]
  
          tmp = deepcopy(new_shape)
          tmp[axis_to_be_reduced] -= shape_must_be_divisible_by[
              axis_to_be_reduced
          ]
          (
              _,
              _,
              _,
              _,
              shape_must_be_divisible_by_new,
          ) = get_pool_and_conv_props(
              current_spacing[1:],
              tmp,
              self.unet_featuremap_min_edge_length,
              self.unet_max_numpool,
          )
          new_shape[
              axis_to_be_reduced
          ] -= shape_must_be_divisible_by_new[axis_to_be_reduced]
  
          (
              network_num_pool_per_axis,
              pool_op_kernel_sizes,
              conv_kernel_sizes,
              new_shape,
              shape_must_be_divisible_by,
          ) = get_pool_and_conv_props(
              current_spacing[1:],
              new_shape,
              self.unet_featuremap_min_edge_length,
              self.unet_max_numpool,
          )
  
          here = compute_approx_vram_consumption(
              new_shape,
              network_num_pool_per_axis,
              self.unet_base_num_features,
              self.unet_max_num_filters,
              num_modalities,
              num_classes,
              pool_op_kernel_sizes,
              conv_per_stage=self.conv_per_stage,
          )
  
      batch_size = int(np.floor(ref / here) * 2)
      input_patch_size = new_shape
  
      max_batch_size = np.round(
          self.batch_size_covers_max_percent_of_dataset
          * dataset_num_voxels
          / np.prod(input_patch_size, dtype=np.int64)
      ).astype(int)
      batch_size = max(1, min(batch_size, max_batch_size))
  
      plan = {
          "batch_size": batch_size,
          "num_pool_per_axis": network_num_pool_per_axis,
          "patch_size": input_patch_size,
          "median_patient_size_in_voxels": new_median_shape,
          "current_spacing": current_spacing,
          "original_spacing": original_spacing,
          "pool_op_kernel_sizes": pool_op_kernel_sizes,
          "conv_kernel_sizes": conv_kernel_sizes,
          "do_dummy_2D_data_aug": False,
      }
      return plan
  
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 2 for calling the ExperimentPlanner2D_v21 obj's underlying member method code with example usage: obj.get_properties_for_stage(current_spacing, original_spacing, original_shape, num_cases, num_modalities, num_classes) and returns: plan