docstr: Provides useful information about different files used in
  medical imaging. Any number of input files can be provided. The
  program identifies the type of file by its extension.
  
  Parameters
  ----------
  input_files : variable string
      Any number of Nifti1, bvals or bvecs files.
  b0_threshold : float, optional
      Threshold used to find b0 volumes.
  bvecs_tol : float, optional
      Threshold used to check that norm(bvec) = 1 +/- bvecs_tol
      b-vectors are unit vectors.
  bshell_thr : float, optional
      Threshold for distinguishing b-values in different shells.
  reference : string, optional
      Reference anatomy for tck/vtk/fib/dpy file.
      support (.nii or .nii.gz).
docstr_tok: ["Provides","useful","information","about","different","files","used","in","medical","imaging",".","Any","number","of","input","files","can","be","provided",".","The","program","identifies","the","type","of","file","by","its","extension",".","Parameters","--","--","--","--","--","input_files",":","variable","string","Any","number","of","Nifti1",",","bvals","or","bvecs","files",".","b0_threshold",":","float",",","optional","Threshold","used","to","find","b0","volumes",".","bvecs_tol",":","float",",","optional","Threshold","used","to","check","that","norm","(","bvec",")","=","1","+\/-","bvecs_tol","b-vectors","are","unit","vectors",".","bshell_thr",":","float",",","optional","Threshold","for","distinguishing","b-values","in","different","shells",".","reference",":","string",",","optional","Reference","anatomy","for","tck\/vtk\/fib\/dpy","file",".","support","(",".nii","or",".nii.gz",")","."]
code: def run(
      self,
      input_files,
      b0_threshold=50,
      bvecs_tol=0.01,
      bshell_thr=100,
      reference=None,
  ):
      """Provides useful information about different files used in
      medical imaging. Any number of input files can be provided. The
      program identifies the type of file by its extension.
  
      Parameters
      ----------
      input_files : variable string
          Any number of Nifti1, bvals or bvecs files.
      b0_threshold : float, optional
          Threshold used to find b0 volumes.
      bvecs_tol : float, optional
          Threshold used to check that norm(bvec) = 1 +/- bvecs_tol
          b-vectors are unit vectors.
      bshell_thr : float, optional
          Threshold for distinguishing b-values in different shells.
      reference : string, optional
          Reference anatomy for tck/vtk/fib/dpy file.
          support (.nii or .nii.gz).
  
      """
      np.set_printoptions(3, suppress=True)
  
      io_it = self.get_io_iterator()
  
      for input_path in io_it:
          mult_ = len(input_path)
          logging.info("-----------" + mult_ * "-")
          logging.info("Looking at {0}".format(input_path))
          logging.info("-----------" + mult_ * "-")
  
          ipath_lower = input_path.lower()
          extension = os.path.splitext(ipath_lower)[1]
  
          if ipath_lower.endswith(".nii") or ipath_lower.endswith(
              ".nii.gz"
          ):
              data, affine, img, vox_sz, affcodes = load_nifti(
                  input_path,
                  return_img=True,
                  return_voxsize=True,
                  return_coords=True,
              )
              logging.info("Data size {0}".format(data.shape))
              logging.info("Data type {0}".format(data.dtype))
  
              if data.ndim == 3:
                  logging.info(
                      "Data min {0} max {1} avg {2}".format(
                          data.min(), data.max(), data.mean()
                      )
                  )
                  logging.info(
                      "2nd percentile {0} 98th percentile {1}".format(
                          np.percentile(data, 2),
                          np.percentile(data, 98),
                      )
                  )
              if data.ndim == 4:
                  logging.info(
                      "Data min {0} max {1} avg {2} of vol 0".format(
                          data[..., 0].min(),
                          data[..., 0].max(),
                          data[..., 0].mean(),
                      )
                  )
                  msg = (
                      "2nd percentile {0} 98th percentile {1} of vol 0"
                  )
                  logging.info(
                      msg.format(
                          np.percentile(data[..., 0], 2),
                          np.percentile(data[..., 0], 98),
                      )
                  )
              logging.info(
                  "Native coordinate system {0}".format(
                      "".join(affcodes)
                  )
              )
              logging.info(f"Affine Native to RAS matrix \n{affine}")
              logging.info("Voxel size {0}".format(np.array(vox_sz)))
              if np.sum(np.abs(np.diff(vox_sz))) > 0.1:
                  msg = "Voxel size is not isotropic. Please reslice.\n"
                  logging.warning(msg)
  
          if os.path.basename(input_path).lower().find("bval") > -1:
              bvals = np.loadtxt(input_path)
              logging.info("b-values \n{0}".format(bvals))
              logging.info(
                  "Total number of b-values {}".format(len(bvals))
              )
              shells = np.sum(np.diff(np.sort(bvals)) > bshell_thr)
              logging.info(
                  "Number of gradient shells {0}".format(shells)
              )
              logging.info(
                  "Number of b0s {0} (b0_thr {1})\n".format(
                      np.sum(bvals <= b0_threshold), b0_threshold
                  )
              )
  
          if os.path.basename(input_path).lower().find("bvec") > -1:
              bvecs = np.loadtxt(input_path)
              logging.info(
                  "Bvectors shape on disk is {0}".format(bvecs.shape)
              )
              rows, cols = bvecs.shape
              if rows < cols:
                  bvecs = bvecs.T
              logging.info("Bvectors are \n{0}".format(bvecs))
              norms = np.array([np.linalg.norm(bvec) for bvec in bvecs])
              res = np.where(
                  (norms <= 1 + bvecs_tol) & (norms >= 1 - bvecs_tol)
              )
              ncl1 = np.sum(norms < 1 - bvecs_tol)
              logging.info(
                  "Total number of unit bvectors {0}".format(
                      len(res[0])
                  )
              )
              logging.info(
                  "Total number of non-unit bvectors {0}\n".format(ncl1)
              )
  
          if extension in [
              ".trk",
              ".tck",
              ".trx",
              ".vtk",
              ".vtp",
              ".fib",
              ".dpy",
          ]:
              sft = None
              if extension in [".trk", ".trx"]:
                  sft = load_tractogram(
                      input_path, "same", bbox_valid_check=False
                  )
              else:
                  sft = load_tractogram(
                      input_path, reference, bbox_valid_check=False
                  )
  
              lengths_mm = list(length(sft.streamlines))
  
              sft.to_voxmm()
  
              lengths, steps = [], []
              for streamline in sft.streamlines:
                  lengths += [len(streamline)]
                  steps += [
                      np.sqrt(
                          np.sum(
                              np.diff(streamline, axis=0) ** 2, axis=1
                          )
                      )
                  ]
              steps = np.hstack(steps)
  
              logging.info(f"Number of streamlines: {len(sft)}")
              logging.info(
                  f"min_length_mm: {float(np.min(lengths_mm))}"
              )
              logging.info(
                  f"mean_length_mm: {float(np.mean(lengths_mm))}"
              )
              logging.info(
                  f"max_length_mm: {float(np.max(lengths_mm))}"
              )
              logging.info(
                  f"std_length_mm: {float(np.std(lengths_mm))}"
              )
              logging.info(
                  f"min_length_nb_points: {float(np.min(lengths))}"
              )
              logging.info(
                  "mean_length_nb_points: " f"{float(np.mean(lengths))}"
              )
              logging.info(
                  f"max_length_nb_points: {float(np.max(lengths))}"
              )
              logging.info(
                  f"std_length_nb_points: {float(np.std(lengths))}"
              )
              logging.info(f"min_step_size: {float(np.min(steps))}")
              logging.info(f"mean_step_size: {float(np.mean(steps))}")
              logging.info(f"max_step_size: {float(np.max(steps))}")
              logging.info(f"std_step_size: {float(np.std(steps))}")
              logging.info(
                  "data_per_point_keys: "
                  f"{list(sft.data_per_point.keys())}"
              )
              logging.info(
                  "data_per_streamline_keys: "
                  f"{list(sft.data_per_streamline.keys())}"
              )
  
      np.set_printoptions()
  
imports: import importlib
  import os
  import sys
  import logging
  from inspect import getmembers, isfunction
  import warnings
  import trx.trx_file_memmap
  import numpy
  from dipy.io.image import load_nifti, save_nifti
  from dipy.io.streamline import load_tractogram, save_tractogram
  from dipy.reconst.shm import convert_sh_descoteaux_tournier
  from dipy.tracking.streamlinespeed import length
  from dipy.utils.tractogram import concatenate_tractogram
  from dipy.workflows.workflow import Workflow
label_desc: Use image node_id 2 for calling the IoInfoFlow obj's underlying member method code with example usage: obj.run(input_files, b0_threshold, bvecs_tol, bshell_thr, reference) without return types