// single thread system calc
  static final HazardCurveSet systemToCurves(
      final SystemSourceSet sourceSet, final Site site, final CalcConfig config) {

    Stopwatch sw = Stopwatch.createStarted();

    Function<SystemSourceSet, InputList> inputFn = new SystemSourceSet.ToInputs(site);
    InputList inputs = inputFn.apply(sourceSet);
    System.out.println("Inputs: " + inputs.size() + "  " + sw);

    Set<Gmm> gmms = sourceSet.groundMotionModels().gmms();
    Table<Gmm, Imt, GroundMotionModel> gmmInstances = Gmm.instances(gmms, config.imts);
    Function<InputList, GroundMotions> gmFn = new InputsToGroundMotions(gmmInstances);
    GroundMotions groundMotions = gmFn.apply(inputs);
    System.out.println("GroundMotions: " + sw);

    Map<Imt, ArrayXY_Sequence> modelCurves = config.logModelCurves;
    Function<GroundMotions, HazardCurves> curveFn = new GroundMotionsToCurves(config);
    HazardCurves hazardCurves = curveFn.apply(groundMotions);
    System.out.println("HazardCurves: " + sw);

    Function<List<HazardCurves>, HazardCurveSet> consolidateFn =
        new CurveConsolidator(sourceSet, modelCurves);
    HazardCurveSet curveSet = consolidateFn.apply(ImmutableList.of(hazardCurves));
    System.out.println("CurveSet: " + sw);

    return curveSet;
  }
  // single thread calc
  static final List<HazardCurveSet> sourceSetToCurves(
      final SourceSet<? extends Source> sourceSet, final Site site, final CalcConfig config) {

    //		Stopwatch sw = Stopwatch.createStarted();

    List<HazardCurveSet> curveSetList = new ArrayList<>();
    for (Source source : sourceSet.iterableForLocation(site.location)) {

      Function<Source, InputList> inputFn = new SourceToInputs(site);
      InputList inputs = inputFn.apply(source);
      //			System.out.println("Inputs: " + inputs.size() + "  " + sw);

      Set<Gmm> gmms = sourceSet.groundMotionModels().gmms();
      Table<Gmm, Imt, GroundMotionModel> gmmInstances = Gmm.instances(gmms, config.imts);
      Function<InputList, GroundMotions> gmFn = new InputsToGroundMotions(gmmInstances);
      GroundMotions groundMotions = gmFn.apply(inputs);
      //			System.out.println("GroundMotions: " + sw);

      Map<Imt, ArrayXY_Sequence> modelCurves = config.logModelCurves;
      Function<GroundMotions, HazardCurves> curveFn = new GroundMotionsToCurves(config);
      HazardCurves hazardCurves = curveFn.apply(groundMotions);
      //			System.out.println("HazardCurves: " + sw);

      Function<List<HazardCurves>, HazardCurveSet> consolidateFn =
          new CurveConsolidator(sourceSet, modelCurves);
      HazardCurveSet curveSet = consolidateFn.apply(ImmutableList.of(hazardCurves));
      //			System.out.println("CurveSet: " + sw);

      curveSetList.add(curveSet);
    }

    return curveSetList;
  }
  /** Convert a future List of SystemInputs to a future List of SystemGroundMotions. */
  static final ListenableFuture<GroundMotions> toSystemGroundMotions(
      final ListenableFuture<InputList> inputs,
      final SystemSourceSet sourceSet,
      final Set<Imt> imts,
      final Executor ex) {

    Set<Gmm> gmms = sourceSet.groundMotionModels().gmms();
    Table<Gmm, Imt, GroundMotionModel> gmmInstances = Gmm.instances(gmms, imts);
    Function<InputList, GroundMotions> function = new InputsToGroundMotions(gmmInstances);
    return transform(inputs, function, ex);
  }
 @Override
 public String toString() {
   StringBuilder sb = new StringBuilder(getClass().getSimpleName());
   sb.append(" [").append(inputs.parentName()).append("]");
   sb.append(": ").append(LINE_SEPARATOR.value());
   for (int i = 0; i < inputs.size(); i++) {
     sb.append(inputs.get(i));
     sb.append(" ");
     for (Entry<Imt, Map<Gmm, List<Double>>> imtEntry : means.entrySet()) {
       Imt imt = imtEntry.getKey();
       sb.append(imt.name()).append(" [");
       for (Entry<Gmm, List<Double>> gmmEntry : imtEntry.getValue().entrySet()) {
         Gmm gmm = gmmEntry.getKey();
         sb.append(gmm.name()).append(" ");
         sb.append(String.format("μ=%.3f", gmmEntry.getValue().get(i))).append(" ");
         sb.append(String.format("σ=%.3f", sigmas.get(imt).get(gmm).get(i))).append(" ");
       }
       sb.append("] ");
     }
     sb.append(LINE_SEPARATOR.value());
   }
   return sb.toString();
 }
  /** Convert a List of future HazardInputs to a List of future HazardGroundMotions. */
  static final AsyncList<GroundMotions> toGroundMotions(
      final AsyncList<InputList> inputsList,
      final SourceSet<? extends Source> sourceSet,
      final Set<Imt> imts,
      final Executor ex) {

    Set<Gmm> gmms = sourceSet.groundMotionModels().gmms();
    Table<Gmm, Imt, GroundMotionModel> gmmInstances = Gmm.instances(gmms, imts);
    Function<InputList, GroundMotions> function = new InputsToGroundMotions(gmmInstances);
    AsyncList<GroundMotions> result = createWithCapacity(inputsList.size());
    for (ListenableFuture<InputList> hazardInputs : inputsList) {
      result.add(transform(hazardInputs, function, ex));
    }
    return result;
  }