class_docstr: Dictionary-like object representing an SALib Problem specification.
  
  Attributes
  ----------
  samples : np.array, of generated samples
  results : np.array, of evaluations (i.e., model outputs)
  analysis : np.array or dict, of sensitivity indices
docstr: Analyze sampled results using the given function in parallel.
  
  Parameters
  ----------
  func : function,
      Analysis method to use. The provided function must accept the
      problem specification as the first parameter, X values if needed,
      Y values, and return a numpy array.
  
  *args : list,
      Additional arguments to be passed to `func`
  
  nprocs : int,
      Number of processors to use.
      Capped to the number of outputs or available processors.
  
  **kwargs : dict,
      Additional keyword arguments passed to `func`
  
  Returns
  -------
  self : ProblemSpec object
docstr_tok: ["Analyze","sampled","results","using","the","given","function","in","parallel",".","Parameters","--","--","--","--","--","func",":","function",",","Analysis","method","to","use",".","The","provided","function","must","accept","the","problem","specification","as","the","first","parameter",",","X","values","if","needed",",","Y","values",",","and","return","a","numpy","array",".","*","args",":","list",",","Additional","arguments","to","be","passed","to","`","func","`","nprocs",":","int",",","Number","of","processors","to","use",".","Capped","to","the","number","of","outputs","or","available","processors",".","*","*","kwargs",":","dict",",","Additional","keyword","arguments","passed","to","`","func","`","Returns","--","--","--","-","self",":","ProblemSpec","object"]
code: def analyze_parallel(self, func, *args, nprocs=None, **kwargs):
      """Analyze sampled results using the given function in parallel.
  
      Parameters
      ----------
      func : function,
          Analysis method to use. The provided function must accept the
          problem specification as the first parameter, X values if needed,
          Y values, and return a numpy array.
  
      *args : list,
          Additional arguments to be passed to `func`
  
      nprocs : int,
          Number of processors to use.
          Capped to the number of outputs or available processors.
  
      **kwargs : dict,
          Additional keyword arguments passed to `func`
  
      Returns
      -------
      self : ProblemSpec object
      """
      warnings.warn(
          "Parallel analysis is an experimental feature and may not work."
      )
  
      if self._results is None:
          raise RuntimeError("Model not yet evaluated")
  
      if "X" in func.__code__.co_varnames:
          # enforce passing of X if expected
          func = partial(func, *args, X=self._samples, **kwargs)
      else:
          func = partial(func, *args, **kwargs)
  
      out_cols = self.get("outputs", None)
      if out_cols is None:
          if len(self._results.shape) == 1:
              self["outputs"] = ["Y"]
          else:
              num_cols = self._results.shape[1]
              self["outputs"] = [
                  f"Y{i}" for i in range(1, num_cols + 1)
              ]
  
      # Cap number of processors used
      Yn = len(self["outputs"])
      if Yn == 1:
          # Only single output, cannot parallelize
          warnings.warn(
              f"Analysis was not parallelized: {nprocs} processors requested"
              f" for 1 output."
          )
  
          res = func(self, Y=self._results)
      else:
          max_procs = cpu_count()
          if nprocs is None:
              nprocs = max_procs
          else:
              nprocs = min(Yn, nprocs, max_procs)
  
          if ptqdm_available:
              # Display progress bar if available
              res = p_imap(
                  lambda y: func(self, Y=y),
                  [self._results[:, i] for i in range(Yn)],
                  num_cpus=nprocs,
              )
          else:
              with Pool(nprocs) as pool:
                  res = list(
                      pool.imap(
                          lambda y: func(self, Y=y),
                          [self._results[:, i] for i in range(Yn)],
                      )
                  )
  
      # Assign by output name if more than 1 output, otherwise
      # attach directly
      if Yn > 1:
          self._analysis = {}
          for out, Si in zip(self["outputs"], list(res)):
              self._analysis[out] = Si
      else:
          self._analysis = res
  
      return self
  
imports: import warnings
  import importlib
  from types import MethodType
  from functools import partial, wraps
  from multiprocess import Pool, cpu_count
  import numpy
  import SALib.sample
  import SALib.analyze
  from SALib.util import avail_approaches
  from SALib.util.results import ResultDict
label_desc: Use image node_id 14 for calling the ProblemSpec obj's underlying member method code with example usage: obj.analyze_parallel(func) and returns: self