code: def doRuns(cfg, dataInterface, subjInterface, webInterface):
      """
      This function is called by 'main()' below. Here, we use the 'dataInterface'
      to read in dicoms (presumably from the scanner, but here it's from a folder
      with previously collected dicom files), doing some sort of analysis in the
      cloud, and then sending the info to the web browser.
  
      INPUT:
          [1] cfg (configuration file with important variables)
          [2] dataInterface (this will allow a script from the cloud to access files
                 from the stimulus computer, which receives dicom files directly
                 from the Siemens console computer)
          [3] subjInterface - this allows sending feedback (e.g. classification results)
                  to a subjectService running on the presentation computer to provide
                  feedback to the subject (and optionally get their response).
      OUTPUT:
          None.
      """
  
      # variables we'll use throughout
      scanNum = cfg.scanNum[0]
      runNum = cfg.runNum[0]
  
      # obtain the path for the directory where the subject's dicoms live
      cfg.dicomDir = cfg.imgDir
      print("Location of the subject's dicoms: %s\n" % cfg.dicomDir)
  
      # Initialize a watch for the entire dicom folder using the function 'initWatch'
      # in dataInterface. (Later we will use watchFile() to look for a specific dicom)
      #   INPUT:
      #       [1] cfg.dicomDir (where the subject's dicom files live)
      #       [2] cfg.dicomNamePattern (the naming pattern of dicom files)
      #       [3] cfg.minExpectedDicomSize (a check on size to make sure we don't
      #               accidentally grab a dicom before it's fully acquired)
      dataInterface.initWatch(
          cfg.dicomDir, cfg.dicomNamePattern, cfg.minExpectedDicomSize
      )
  
      # We will use the function plotDataPoint in webInterface whenever we
      #  want to send values to the web browser so that they can be plotted in the
      #  --Data Plots-- tab.
      # However at the start of a run we will want to clear the plot, and we can use
      # clearRunPlot(runId), or clearAllPlots() also in the webInterface object.
      print(
          "\n\nClear any pre-existing plot for this run using 'clearRunPlot(runNum)'"
      )
      webInterface.clearRunPlot(runNum)
      print(
          ""
          "###################################################################################"
      )
  
      # declare the total number of TRs
      num_trainingData = cfg.numTrainingTRs
      num_total_TRs = cfg.numSynthetic
  
      for this_TR in np.arange(num_total_TRs):
          # declare variables that are needed to use 'readRetryDicomFromDataInterface'
          timeout_file = 5  # small number because of demo, can increase for real-time
  
          # use 'getDicomFileName' from 'imageHandling.py' to obtain the filename
          #   of the dicom data you want to get... which is useful considering how
          #   complicated these filenames can be!
          #   INPUT:
          #       [1] cfg (config parameters)
          #       [2] scanNum (scan number)
          #       [3] fileNum (TR number, which will reference the correct file)
          #   OUTPUT:
          #       [1] fullFileName (the filename of the dicom that should be grabbed)
          fileName = getDicomFileName(cfg, scanNum, this_TR)
  
          # Use 'readRetryDicomFromDataInterface' in 'imageHandling.py' to wait for dicom
          #    files to be written by the scanner (uses 'watchFile' internally) and then
          #    reading the dicom file once it is available.
          # INPUT:
          #    [1] dataInterface (allows a cloud script to access files from the
          #        control room computer)
          #    [2] filename (the dicom file we're watching for and want to load)
          #    [3] timeout (time spent waiting for a file before timing out)
          # OUTPUT:
          #    [1] dicomData (with class 'pydicom.dataset.FileDataset')
          dicomData = readRetryDicomFromDataInterface(
              dataInterface, fileName, timeout_file
          )
  
          # We can use the 'convertDicomFileToNifti' function with dicomData as
          #   input to get the data in NifTi format
          base, ext = os.path.splitext(fileName)
          assert ext == ".dcm"
          niftiFilename = base + ".nii"
          convertDicomFileToNifti(fileName, niftiFilename)
          niftiObject = readNifti(niftiFilename)
  
          # declare various things if it's the first TR
          if this_TR == 0:
              # load the labels and mask
              labels = np.load(os.path.join(cfg.imgDir, "labels.npy"))
              print(os.path.join(cfg.imgDir, "labels.npy"))
              ROI_nib = nib.load(
                  os.path.join(currPath, "ROI_mask.nii.gz")
              )
              ROI_mask = np.array(ROI_nib.dataobj)
              mask_nib = nib.Nifti1Image(
                  ROI_mask.T, affine=niftiObject.affine
              )
              # declare the number of TRs we will shift the data to account for the hemodynamic lag
              num_shiftTRs = 3
              # shift the labels to account for hemodynamic lag
              shifted_labels = np.concatenate(
                  [np.full((num_shiftTRs, 1), np.nan), labels]
              )
              # set up a matrix that will hold all of the preprocessed data
              preprocessed_data = np.full(
                  (num_total_TRs, int(ROI_mask.sum())), np.nan
              )
  
          # preprocess the training data by applying the mask
          preprocessed_data[this_TR, :] = np.ravel(
              apply_mask(niftiObject, mask_nib).reshape(
                  int(ROI_mask.sum()), 1
              )
          )
  
          ## Now we divide into one of three possible steps
  
          # STEP 1: collect the training data
          if this_TR < num_trainingData:
              print("Collected training data for TR %s" % this_TR)
          # STEP 2: train the SVM model
          elif this_TR == num_trainingData:
              print(
                  ""
                  "###################################################################################"
              )
              print(
                  "Done collecting training data! \nStart training the classifier."
              )
  
              # snapshot of time to keep track of how long it takes to train the classifier
              start_time = time.time()
  
              scaler = StandardScaler()
              X_train = preprocessed_data[num_shiftTRs:num_trainingData]
              y_train = shifted_labels[
                  num_shiftTRs:num_trainingData
              ].reshape(
                  -1,
              )
              # we don't want to include rest data
              X_train_noRest = X_train[y_train != 0]
              y_train_noRest = y_train[y_train != 0]
              # and we want to zscore the bold data
              X_train_noRest_zscored = scaler.fit_transform(
                  X_train_noRest
              )
              clf = svm.SVC(
                  kernel="linear", C=0.01, class_weight="balanced"
              )
              clf.fit(X_train_noRest_zscored, y_train_noRest)
  
              # print out the amount of time it took to train the classifier
              print(
                  "Classifier done training! Time it took: %.2f s"
                  % (time.time() - start_time)
              )
              print(
                  ""
                  "###################################################################################"
              )
          elif this_TR > num_trainingData:
              # apply the classifier to new data to obtain prediction IF not a rest trial
              if shifted_labels[this_TR] != 0:
                  prediction = clf.predict(
                      scaler.transform(
                          preprocessed_data[this_TR, :].reshape(1, -1)
                      )
                  )
                  print(
                      f"Plotting classifier prediction for TR {this_TR}: {prediction}"
                  )
                  webInterface.plotDataPoint(
                      runNum, int(this_TR), float(prediction)
                  )
  
                  # To send feedback for the subject at the presentation computer use
                  #   the subjInterface as shown below. For this demo there is no
                  #   presentation computer so we won't actually it.
                  # subjInterface.setResult(runNum, int(this_TR), float(prediction))
              else:
                  print(
                      f"Skipping classification because it is a rest trial"
                  )
  
      X_test = preprocessed_data[num_trainingData + 1 :]
      y_test = shifted_labels[
          num_trainingData + 1 : num_total_TRs
      ].reshape(
          -1,
      )
      # we don't want to include the rest data
      X_test_noRest = X_test[y_test != 0]
      y_test_noRest = y_test[y_test != 0]
      # and we want to zscore the bold data
      X_test_noRest_zscored = scaler.transform(X_test_noRest)
      accuracy_score = clf.score(X_test_noRest_zscored, y_test_noRest)
      print("Accuracy of classifier on new data: %s" % accuracy_score)
      # print(y_test_noRest)
      # print(clf.predict(X_test_noRest_zscored))
  
      print(
          ""
          "###################################################################################\n"
          "REAL-TIME EXPERIMENT COMPLETE!"
      )
  
      return
  
file_path: brainiak/docs/examples/real-time/sample.py
imports: import os
  import sys
  import time
  import argparse
  import numpy
  import nibabel
  import scipy.io
  from nilearn.input_data import NiftiMasker
  from sklearn import preprocessing
  from sklearn import svm
  import nilearn
  from nilearn.masking import apply_mask
  from scipy.stats import zscore
  from sklearn.preprocessing import StandardScaler
  import warnings
  from rtCommon.utils import loadConfigFile
  from rtCommon.clientInterface import ClientInterface
  from rtCommon.imageHandling import readRetryDicomFromDataInterface, getDicomFileName, convertDicomImgToNifti, convertDicomFileToNifti, readNifti, convertDicomFileToNifti
label_desc: Use image node_id 1 for calling a global function with example usage: doRuns(cfg, dataInterface, subjInterface, webInterface) without return types