code: def fit_truncated_gaussian(samples, lower_bounds, upper_bounds):
      
      if len(samples.shape) == 1:
          return _TruncatedNormalFitter()((samples, lower_bounds, upper_bounds))
  
      def item_generator():
          for ind in range(samples.shape[0]):
              if is_scalar(lower_bounds):
                  lower_bound = lower_bounds
              else:
                  lower_bound = lower_bounds[ind]
  
              if is_scalar(upper_bounds):
                  upper_bound = upper_bounds
              else:
                  upper_bound = upper_bounds[ind]
  
              yield (samples[ind], lower_bound, upper_bound)
  
      results = np.array(multiprocess_mapping(_TruncatedNormalFitter(), item_generator()))
      return results[:, 0], results[:, 1]
docs: Fits a truncated gaussian distribution on the given samples.
  
      This will do a maximum likelihood estimation of a truncated Gaussian on the provided samples, with the
      truncation points given by the lower and upper bounds.
  
      Args:
          samples (ndarray): a one or two dimensional array. If one dimensional we fit the truncated Gaussian on all
              values. If two dimensional, we calculate the truncated Gaussian for every set of samples over the
              first dimension.
          lower_bounds (ndarray or float): the lower bound, either a scalar or a lower bound per problem (first index of
              samples)
          upper_bounds (ndarray or float): the upper bound, either a scalar or an upper bound per problem (first index of
              samples)
  
      Returns:
          mean, std: the mean and std of the fitted truncated Gaussian