code: def run(self):
      # temporary dir
      temporary_dir = self.params.temporary_dir
      if temporary_dir is None:
          temporary_dir = tempfile.mkdtemp(prefix="calamari")
      else:
          temporary_dir = os.path.abspath(temporary_dir)
  
      if not os.path.exists(temporary_dir):
          os.makedirs(temporary_dir)
  
      # Compute the files in the cross fold (create a CrossFold)
      fold_file = os.path.join(temporary_dir, "folds.json")
      cross_fold = CrossFold(
          n_folds=self.params.n_folds,
          data_generator_params=self.params.trainer.gen.train,
          output_dir=temporary_dir,
      )
      if self.params.run_split is not None:
          cfg_path = os.path.join(temporary_dir, "split.cfg.json")
          with open(cfg_path, "w") as f:
              json.dump(cross_fold.to_dict(), f)
          check_call(
              self.params.run_split.split()
              + [
                  sys.executable,
                  "-u",
                  self.cf_split_script_path,
                  cfg_path,
                  "--dir",
                  fold_file,
              ]
              + (
                  ["--progress_bar"]
                  if self.params.trainer.progress_bar
                  else []
              ),
              stdout=sys.stdout,
              stderr=sys.stderr,
          )
          with open(cfg_path) as f:
              cross_fold = CrossFold.from_dict(json.load(f))
      else:
          # do not run as separate call
          cross_fold.create_folds(self.params.trainer.progress_bar)
          cross_fold.write_folds_to_json(fold_file)
  
      # Create the json argument file for each individual training
      run_args = []
      seed = self.params.trainer.random_seed or -1
      folds_to_run = (
          self.params.single_fold
          if len(self.params.single_fold) > 0
          else range(len(cross_fold.folds))
      )
      for fold in folds_to_run:
          train_files = cross_fold.train_files(fold)
          test_files = cross_fold.test_files(fold)
          path = os.path.join(
              temporary_dir, "fold_{}.json".format(fold)
          )
          with open(path, "w") as f:
              trainer_params = deepcopy(self.params.trainer)
              trainer_params.gen = CalamariDefaultTrainerPipelineParams(
                  train=trainer_params.gen.train,
                  val=deepcopy(trainer_params.gen.train),
                  setup=trainer_params.gen.setup,
              )
              if cross_fold.is_h5_dataset:
                  tp = trainer_params.gen.train.to_dict()
                  del tp["__cls__"]
                  tp["files"] = train_files
                  trainer_params.gen.train = Hdf5.from_dict(tp)
                  vp = trainer_params.gen.val.to_dict()
                  del vp["__cls__"]
                  vp["files"] = test_files
                  trainer_params.gen.val = Hdf5.from_dict(vp)
              else:
                  trainer_params.gen.train.images = train_files
                  trainer_params.gen.val.images = test_files
                  trainer_params.gen.val.gt_extension = (
                      trainer_params.gen.train.gt_extension
                  )
  
              trainer_params.scenario.id = fold
              trainer_params.progress_bar_mode = 2
              trainer_params.output_dir = os.path.join(
                  temporary_dir, "fold_{}".format(fold)
              )
              trainer_params.early_stopping.best_model_output_dir = (
                  self.params.best_models_dir
              )
              trainer_params.early_stopping.best_model_name = ""
              best_model_prefix = self.params.best_model_label.format(
                  id=fold
              )
              trainer_params.best_model_prefix = best_model_prefix
  
              if self.params.visible_gpus:
                  assert (
                      trainer_params.device.gpus is None
                  ), "Using visible_gpus with device.gpus is not supported"
                  trainer_params.device.gpus = [
                      self.params.visible_gpus[
                          fold % len(self.params.visible_gpus)
                      ]
                  ]
  
              if seed >= 0:
                  trainer_params.random_seed = seed + fold
  
              if len(self.params.weights) == 1:
                  trainer_params.warmstart.model = self.params.weights[
                      0
                  ]
              elif len(self.params.weights) > 1:
                  trainer_params.warmstart.model = self.params.weights[
                      fold
                  ]
  
              # start from scratch via None
              if trainer_params.warmstart.model:
                  if (
                      len(trainer_params.warmstart.model.strip()) == 0
                      or trainer_params.warmstart.model.upper()
                      == "NONE"
                  ):
                      trainer_params.warmstart.model = None
                  else:
                      # access model once to upgrade the model if necessary
                      # (can not be performed in parallel if multiple folds use the same model)
                      SavedCalamariModel(trainer_params.warmstart.model)
  
              post_init(trainer_params)
  
              json.dump(
                  trainer_params.to_dict(),
                  f,
                  indent=4,
              )
  
          run_args.append(
              {
                  "json": path,
                  "args": trainer_params,
                  "id": fold,
                  "train_script": self.train_script_path,
                  "run": self.params.run_train,
                  "verbose": True,
              }
          )
  
      if not self.params.no_train:
          logger.info("Starting the training.")
          # Launch the individual processes for each training
          with multiprocessing.pool.ThreadPool(
              processes=self.params.max_parallel_models
          ) as pool:
              # workaround to forward keyboard interrupt
              pool.map_async(train_individual_model, run_args).get()
      else:
          logger.info("Not training since the `no_train` flag is set.")
  
      if not self.params.keep_temporary_files:
          import shutil
  
          shutil.rmtree(temporary_dir)
  
imports: import inspect
  import json
  import logging
  import multiprocessing
  import os
  import sys
  import tempfile
  from copy import deepcopy
  from dataclasses import dataclass, field
  from subprocess import check_call
  from typing import Optional, List
  from paiargparse import pai_dataclass, pai_meta
  from tfaip.util.tfaipargparse import post_init
  from calamari_ocr.ocr import CrossFold, SavedCalamariModel
  from calamari_ocr.ocr.dataset.datareader.hdf5.reader import Hdf5
  from calamari_ocr.ocr.scenario import CalamariScenario
  from calamari_ocr.ocr.training.params import TrainerParams, CalamariDefaultTrainerPipelineParams
  from calamari_ocr.utils.multiprocessing import prefix_run_command, run
label_desc: Use image node_id 2 for calling the CrossFoldTrainer obj's underlying member method code with example usage: obj.run() without return types