parameters: (
      env: "SCEnvironment", ref_file: Path, sample_file: Path
  )
docstring: Compare two 2D arrays of spatial or time profiles. Each data set should
      contain the time or space coordinate in the first column and data series
      to be compared in successive columns.
  
      The coordinates in each data set do not need to be the same: The data from
      the second data set will be interpolated onto the coordinates in the first
      data set before being compared. This means that the range of the "sample"
      data set should be at least as long as the "reference" data set.
  
      After interpolation, each data point must satisfy a combined relative and absolute
      error criterion specified by `rtol` and `atol`.
docstring_summary: Compare two 2D arrays of spatial or time profiles. Each data set should
      contain the time or space coordinate in the first column and data series
      to be compared in successive columns.
docstring_tokens: Compare two 2D arrays of spatial or time profiles . Each data set should contain the time or space coordinate in the first column and data series to be compared in successive columns .
function: def compare_profiles(
      env: "SCEnvironment", ref_file: Path, sample_file: Path
  ) -> TestResult:
      """
      Compare two 2D arrays of spatial or time profiles. Each data set should
      contain the time or space coordinate in the first column and data series
      to be compared in successive columns.
  
      The coordinates in each data set do not need to be the same: The data from
      the second data set will be interpolated onto the coordinates in the first
      data set before being compared. This means that the range of the "sample"
      data set should be at least as long as the "reference" data set.
  
      After interpolation, each data point must satisfy a combined relative and absolute
      error criterion specified by `rtol` and `atol`.
      """
      if not np:
          logger.warning("Skipping profile comparison because numpy is not available")
          return TestResult.PASS
  
      atol = env["test_csv_threshold"]
      rtol = env["test_csv_tolerance"]
      xtol = env["test_csv_tolerance"]
  
      reference = np.genfromtxt(ref_file, delimiter=",").T
      sample = np.genfromtxt(sample_file, delimiter=",").T
      if reference.shape[0] != sample.shape[0]:
          logger.error(
              "The output array does not have the same number of variabls as the "
              "reference array."
          )
          return TestResult.FAIL
  
      # trim header columns if present
      if np.isnan(sample[0, 0]) and np.isnan(reference[0, 0]):
          reference = reference[:, 1:]
          sample = sample[:, 1:]
      if np.isnan(reference).any() or np.isnan(sample).any():
          logger.error(
              "The output array and reference array have different headers "
              "or contain non-numeric data."
          )
          return TestResult.FAIL
  
      n_vars = reference.shape[0]
      n_times = reference.shape[1]
  
      bad = []
      template = "{0:10.4e}  {1:5d}  {2:14.7e}  {3:14.7e}  {4:9.3e}  {5:9.3e}  {6:9.3e}"
      header = ["Failed series comparisons:"]
      header.append("{:10s}  {:5s}  {:14s}  {:14s}  {:9s}  {:9s}  {:9s}".format(
          "coordinate", "comp.", "reference val.", "test value", "abs. err", "rel. err",
          "pos. err"
      ))
      header.append(f"{10*'-'}  -----  {14*'-'}  {14*'-'}  {9*'-'}  {9*'-'}  {9*'-'}")
      ref_ptp = reference.ptp(axis=1)
      ref_max = np.abs(reference).max(axis=1)
      sample_ptp = sample.ptp(axis=1)
      sample_max = np.abs(sample).max(axis=1)
      scale = np.maximum(
          np.maximum(ref_ptp[1:], ref_max[1:]),
          np.maximum(sample_ptp[1:], sample_max[1:])
      ).reshape(n_vars - 1, -1)
      ref_diff = np.diff(reference)
      slope = ref_diff[1:, :] / ref_diff[0, :] * ref_ptp[0]
      slope = np.hstack((np.zeros((n_vars - 1, 1)), slope))
      comp = np.zeros((n_vars - 1, n_times))
      for i, row in enumerate(sample[1:]):
          comp[i, :] = np.interp(reference[0, :], sample[0, :], row)
  
      abserr = np.abs(reference[1:] - comp)
      relerr = abserr / (scale + atol)
      # error that can be accounted for by shifting the profile along
      # the time / spatial coordinate
      xerr = abserr / (np.abs(slope) + atol)
      if np.any(abserr > atol) and np.any(relerr > rtol) and np.any(xerr > xtol):
          it = np.nditer((abserr, relerr, xerr), flags=["multi_index"])
          for a, r, x in it:
              i, j = it.multi_index
              bad.append((reference[0, j], i, reference[i, j], comp[i, j], a, r, x))
  
      footer = []
      maxrows = 10
      if len(bad) > maxrows:
          bad.sort(key=lambda row: -row[5])
          footer += [f"Plus {len(bad) - maxrows} more points exceeding error thresholds."]
          bad = bad[:maxrows]
  
      if bad:
          logger.error(
              "\n".join(header + [template.format(*row) for row in bad] + footer),
              print_level=False,
          )
          return TestResult.FAIL
      else:
          return TestResult.PASS
function_tokens: def compare_profiles ( env : "SCEnvironment" , ref_file : Path , sample_file : Path ) -> TestResult : if not np : logger . warning ( "Skipping profile comparison because numpy is not available" ) return TestResult . PASS atol = env [ "test_csv_threshold" ] rtol = env [ "test_csv_tolerance" ] xtol = env [ "test_csv_tolerance" ] reference = np . genfromtxt ( ref_file , delimiter = "," ) . T sample = np . genfromtxt ( sample_file , delimiter = "," ) . T if reference . shape [ 0 ] != sample . shape [ 0 ] : logger . error ( "The output array does not have the same number of variabls as the " "reference array." ) return TestResult . FAIL # trim header columns if present if np . isnan ( sample [ 0 , 0 ] ) and np . isnan ( reference [ 0 , 0 ] ) : reference = reference [ : , 1 : ] sample = sample [ : , 1 : ] if np . isnan ( reference ) . any ( ) or np . isnan ( sample ) . any ( ) : logger . error ( "The output array and reference array have different headers " "or contain non-numeric data." ) return TestResult . FAIL n_vars = reference . shape [ 0 ] n_times = reference . shape [ 1 ] bad = [ ] template = "{0:10.4e}  {1:5d}  {2:14.7e}  {3:14.7e}  {4:9.3e}  {5:9.3e}  {6:9.3e}" header = [ "Failed series comparisons:" ] header . append ( "{:10s}  {:5s}  {:14s}  {:14s}  {:9s}  {:9s}  {:9s}" . format ( "coordinate" , "comp." , "reference val." , "test value" , "abs. err" , "rel. err" , "pos. err" ) ) header . append ( f"{10*'-'}  -----  {14*'-'}  {14*'-'}  {9*'-'}  {9*'-'}  {9*'-'}" ) ref_ptp = reference . ptp ( axis = 1 ) ref_max = np . abs ( reference ) . max ( axis = 1 ) sample_ptp = sample . ptp ( axis = 1 ) sample_max = np . abs ( sample ) . max ( axis = 1 ) scale = np . maximum ( np . maximum ( ref_ptp [ 1 : ] , ref_max [ 1 : ] ) , np . maximum ( sample_ptp [ 1 : ] , sample_max [ 1 : ] ) ) . reshape ( n_vars - 1 , - 1 ) ref_diff = np . diff ( reference ) slope = ref_diff [ 1 : , : ] / ref_diff [ 0 , : ] * ref_ptp [ 0 ] slope = np . hstack ( ( np . zeros ( ( n_vars - 1 , 1 ) ) , slope ) ) comp = np . zeros ( ( n_vars - 1 , n_times ) ) for i , row in enumerate ( sample [ 1 : ] ) : comp [ i , : ] = np . interp ( reference [ 0 , : ] , sample [ 0 , : ] , row ) abserr = np . abs ( reference [ 1 : ] - comp ) relerr = abserr / ( scale + atol ) # error that can be accounted for by shifting the profile along # the time / spatial coordinate xerr = abserr / ( np . abs ( slope ) + atol ) if np . any ( abserr > atol ) and np . any ( relerr > rtol ) and np . any ( xerr > xtol ) : it = np . nditer ( ( abserr , relerr , xerr ) , flags = [ "multi_index" ] ) for a , r , x in it : i , j = it . multi_index bad . append ( ( reference [ 0 , j ] , i , reference [ i , j ] , comp [ i , j ] , a , r , x ) ) footer = [ ] maxrows = 10 if len ( bad ) > maxrows : bad . sort ( key = lambda row : - row [ 5 ] ) footer += [ f"Plus {len(bad) - maxrows} more points exceeding error thresholds." ] bad = bad [ : maxrows ] if bad : logger . error ( "\n" . join ( header + [ template . format ( * row ) for row in bad ] + footer ) , print_level = False , ) return TestResult . FAIL else : return TestResult . PASS