From ef733d5c6f1175cea560f15dee82ed2ed80e80f7 Mon Sep 17 00:00:00 2001
From: Peter Powers <pmpowers@usgs.gov>
Date: Sun, 27 Mar 2022 14:15:30 -0600
Subject: [PATCH 1/2] refactor and cleaning

---
 .../earthquake/nshmp/www/gmm/GmmCalc.java     | 278 ++++++++++++++++++
 .../nshmp/www/gmm/GmmController.java          |  95 +++---
 .../earthquake/nshmp/www/gmm/GmmService.java  | 185 ++++--------
 .../nshmp/www/gmm/GroundMotionData.java       | 273 -----------------
 .../nshmp/www/gmm/ResponseSpectra.java        | 180 ------------
 .../{GmmServices.java => ServiceUtil.java}    |  65 ++--
 .../{XYDataGroup.java => XyDataGroup.java}    |  26 +-
 7 files changed, 417 insertions(+), 685 deletions(-)
 create mode 100644 src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
 delete mode 100644 src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GroundMotionData.java
 delete mode 100644 src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ResponseSpectra.java
 rename src/main/java/gov/usgs/earthquake/nshmp/www/gmm/{GmmServices.java => ServiceUtil.java} (88%)
 rename src/main/java/gov/usgs/earthquake/nshmp/www/gmm/{XYDataGroup.java => XyDataGroup.java} (59%)

diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
new file mode 100644
index 0000000..6e72c4d
--- /dev/null
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
@@ -0,0 +1,278 @@
+package gov.usgs.earthquake.nshmp.www.gmm;
+
+import static java.lang.Math.cos;
+import static java.lang.Math.hypot;
+import static java.lang.Math.sin;
+import static java.lang.Math.tan;
+import static java.lang.Math.toRadians;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.primitives.Doubles;
+
+import gov.usgs.earthquake.nshmp.Maths;
+import gov.usgs.earthquake.nshmp.gmm.Gmm;
+import gov.usgs.earthquake.nshmp.gmm.GmmInput;
+import gov.usgs.earthquake.nshmp.gmm.GroundMotion;
+import gov.usgs.earthquake.nshmp.gmm.GroundMotionModel;
+import gov.usgs.earthquake.nshmp.gmm.GroundMotions;
+import gov.usgs.earthquake.nshmp.gmm.Imt;
+import gov.usgs.earthquake.nshmp.tree.Branch;
+import gov.usgs.earthquake.nshmp.tree.LogicTree;
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Distance;
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Magnitude;
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Request;
+import jakarta.inject.Singleton;
+
+/*
+ * GMM service calculators.
+ *
+ * @author U.S. Geological Survey
+ */
+@Singleton
+class GmmCalc {
+
+  private static final double PGA_PERIOD = 0.001;
+
+  /* Compute ground motion response spectra. */
+  static Map<Gmm, GmmData> spectra(Request request, boolean commonImts) {
+
+    /*
+     * NOTE: At present, program assumes that all supplied Gmms support PGA.
+     * Although most currently implemented models do, this may not be the case
+     * in the future and program may produce unexpected results.
+     */
+
+    /* Common imts and periods; may not be used. */
+    Set<Imt> saImts = Gmm.responseSpectrumImts(request.gmms);
+    List<Double> periods = new ArrayList<>();
+    periods.add(PGA_PERIOD);
+    periods.addAll(Imt.periods(saImts));
+
+    Map<Gmm, GmmData> gmmSpectra = new EnumMap<>(Gmm.class);
+    for (Gmm gmm : request.gmms) {
+      if (!commonImts) {
+        saImts = gmm.responseSpectrumImts();
+        periods = ImmutableList.<Double> builder()
+            .add(PGA_PERIOD)
+            .addAll(Imt.periods(saImts))
+            .build();
+      }
+
+      List<LogicTree<GroundMotion>> imtTrees = new ArrayList<>();
+      imtTrees.add(gmm.instance(Imt.PGA).calc(request.input));
+      for (Imt imt : saImts) {
+        imtTrees.add(gmm.instance(imt).calc(request.input));
+      }
+
+      GmmData dataGroup = treesToDataGroup(periods, imtTrees);
+      gmmSpectra.put(gmm, dataGroup);
+    }
+    return gmmSpectra;
+  }
+
+  private static GmmData treesToDataGroup(
+      List<Double> xValues,
+      List<LogicTree<GroundMotion>> trees) {
+
+    // Can't use Trees.transpose() because some
+    // GMMs have period dependent weights
+
+    LogicTree<GroundMotion> modelTree = trees.get(0);
+    List<String> branchIds = modelTree.stream()
+        .map(Branch::id)
+        .collect(Collectors.toList());
+
+    double[] xs = xValues.stream().mapToDouble(Double::valueOf).toArray();
+    double[] μs = new double[xValues.size()];
+    double[] σs = new double[xValues.size()];
+
+    // build combined μ and σ
+    for (int i = 0; i < trees.size(); i++) {
+      GroundMotion combined = GroundMotions.combine(trees.get(i));
+      μs[i] = combined.mean();
+      σs[i] = combined.sigma();
+    }
+
+    List<EpiBranch> epiBranches = new ArrayList<>();
+
+    // short circuit if tree is single branch
+    if (modelTree.size() > 1) {
+
+      // branch index, imt index
+      List<double[]> μBranches = new ArrayList<>();
+      List<double[]> σBranches = new ArrayList<>();
+      List<double[]> weights = new ArrayList<>();
+      for (int i = 0; i < modelTree.size(); i++) {
+        μBranches.add(new double[xValues.size()]);
+        σBranches.add(new double[xValues.size()]);
+        weights.add(new double[xValues.size()]);
+      }
+
+      // imt indexing
+      for (int i = 0; i < trees.size(); i++) {
+        LogicTree<GroundMotion> tree = trees.get(i);
+        // epi branch indexing
+        for (int j = 0; j < tree.size(); j++) {
+          Branch<GroundMotion> branch = tree.get(j);
+          μBranches.get(j)[i] = branch.value().mean();
+          σBranches.get(j)[i] = branch.value().sigma();
+          weights.get(j)[i] = branch.weight();
+        }
+      }
+
+      for (int i = 0; i < modelTree.size(); i++) {
+        EpiBranch epiBranch = new EpiBranch(
+            branchIds.get(i),
+            μBranches.get(i),
+            σBranches.get(i),
+            weights.get(i));
+        epiBranches.add(epiBranch);
+      }
+    }
+
+    GmmData gmmData = new GmmData(xs, μs, σs, epiBranches);
+    return gmmData;
+  }
+
+  /* Compute ground motions over a range of distances. */
+  static Map<Gmm, GmmData> distance(Distance.Request request, double[] distances) {
+    var inputList = hangingWallDistances(request.input, distances);
+    return calculateGroundMotions(request.gmms, inputList, request.imt, distances);
+  }
+
+  /* Compute ground motions over a range of magnitudes. */
+  static Map<Gmm, GmmData> magnitude(
+      Magnitude.Request request,
+      double[] magnitudes,
+      double distance) {
+
+    var gmmInputs = Arrays.stream(magnitudes)
+        .mapToObj(Mw -> GmmInput.builder().fromCopy(request.input).mag(Mw).build())
+        .map(gmmInput -> hangingWallDistance(gmmInput, distance))
+        .collect(Collectors.toList());
+    return calculateGroundMotions(request.gmms, gmmInputs, request.imt, magnitudes);
+  }
+
+  private static List<GmmInput> hangingWallDistances(
+      GmmInput inputModel,
+      double[] rValues) {
+
+    return Arrays.stream(rValues)
+        .mapToObj(r -> hangingWallDistance(inputModel, r))
+        .collect(Collectors.toList());
+  }
+
+  /* Compute distance metrics for a fault. */
+  private static GmmInput hangingWallDistance(GmmInput in, double r) {
+    /* Dip in radians */
+    double δ = toRadians(in.dip);
+
+    /* Horizontal and vertical widths of fault */
+    double h = cos(δ) * in.width;
+    double v = sin(δ) * in.width;
+
+    /* Depth to bottom of rupture */
+    double zBot = in.zTor + v;
+
+    /* Distance range over which site is normal to fault plane */
+    double rCutLo = tan(δ) * in.zTor;
+    double rCutHi = tan(δ) * zBot + h;
+
+    /* rRup values corresponding to cutoffs above */
+    double rRupLo = Maths.hypot(in.zTor, rCutLo);
+    double rRupHi = Maths.hypot(zBot, rCutHi - h);
+
+    double rJB = (r < 0) ? -r : (r < h) ? 0.0 : r - h;
+    double rRup = (r < rCutLo)
+        ? hypot(r, in.zTor)
+        : (r > rCutHi)
+            ? hypot(r - h, zBot)
+            : rRupScaled(
+                r, rCutLo, rCutHi, rRupLo, rRupHi);
+
+    return GmmInput.builder()
+        .fromCopy(in)
+        .distances(rJB, rRup, r)
+        .build();
+  }
+
+  private static Map<Gmm, GmmData> calculateGroundMotions(
+      Set<Gmm> gmms,
+      List<GmmInput> gmmInputs,
+      Imt imt,
+      double[] distances) {
+
+    Map<Gmm, GmmData> gmValues = new EnumMap<>(Gmm.class);
+
+    for (Gmm gmm : gmms) {
+      List<LogicTree<GroundMotion>> trees = new ArrayList<>();
+      GroundMotionModel model = gmm.instance(imt);
+      for (GmmInput gmmInput : gmmInputs) {
+        trees.add(model.calc(gmmInput));
+      }
+      GmmData dataGroup = GmmCalc.treesToDataGroup(Doubles.asList(distances), trees);
+      gmValues.put(gmm, dataGroup);
+    }
+    return gmValues;
+  }
+
+  /*
+   * Computes rRup for a surface distance r. The range [rCutLo, rCutHi] must
+   * contain r; rRupLo and rRupHi are rRup at rCutLo and rCutHi, respectively.
+   */
+  private static double rRupScaled(
+      double r,
+      double rCutLo,
+      double rCutHi,
+      double rRupLo,
+      double rRupHi) {
+
+    double rRupΔ = rRupHi - rRupLo;
+    double rCutΔ = rCutHi - rCutLo;
+    return rRupLo + (r - rCutLo) / rCutΔ * rRupΔ;
+  }
+
+  static class GmmData {
+
+    final double[] xs;
+    final double[] μs;
+    final double[] σs;
+    final List<EpiBranch> tree;
+
+    GmmData(
+        double[] xs,
+        double[] μs,
+        double[] σs,
+        List<EpiBranch> tree) {
+
+      this.xs = xs;
+      this.μs = μs;
+      this.σs = σs;
+      this.tree = tree;
+    }
+  }
+
+  static class EpiBranch {
+
+    final String id;
+    final double[] μs;
+    final double[] σs;
+    final double[] weights;
+
+    EpiBranch(String id, double[] μs, double[] σs, double[] weights) {
+      this.id = id;
+      this.μs = μs;
+      this.σs = σs;
+      this.weights = weights;
+    }
+  }
+
+}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java
index 525e960..ccdfbb7 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java
@@ -8,8 +8,11 @@ import gov.usgs.earthquake.nshmp.gmm.GmmInput;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.Utils;
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Distance;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Id;
-
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Magnitude;
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Request;
+import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Spectra;
 import io.micronaut.core.annotation.Nullable;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -107,21 +110,17 @@ class GmmController {
       content = @Content(schema = @Schema(type = "string")))
   @Get(uri = "/spectra", produces = MediaType.APPLICATION_JSON)
   public HttpResponse<String> doGetSpectra(HttpRequest<?> http) {
-    Id serviceId = Id.SPECTRA;
+    Id id = Id.SPECTRA;
     try {
-      Set<Gmm> gmms = GmmServices.readGmms(http);
+      Set<Gmm> gmms = ServiceUtil.readGmms(http);
       if (gmms.isEmpty()) {
-        return GmmServices.metadata(http, serviceId);
+        return ServiceUtil.metadata(http, id);
       }
-      GmmInput in = GmmServices.readGmmInput(http);
-      GmmService.Request gmmRequest = new GmmService.Request(
-          http,
-          serviceId,
-          gmms,
-          in);
-      return GmmService.Spectra.processRequestSpectra(gmmRequest);
+      GmmInput in = ServiceUtil.readGmmInput(http);
+      Request gmmRequest = new Request(http, id, gmms, in);
+      return Spectra.process(gmmRequest);
     } catch (Exception e) {
-      return Utils.handleError(e, serviceId.name, http.getUri().getPath());
+      return Utils.handleError(e, id.name, http.getUri().getPath());
     }
   }
 
@@ -224,21 +223,17 @@ class GmmController {
           defaultValue = "",
           minimum = "0",
           maximum = "10") @QueryValue @Nullable Double z2p5) {
-    Id serviceId = Id.SPECTRA;
+    Id id = Id.SPECTRA;
     try {
-      Set<Gmm> gmms = GmmServices.readGmms(http);
+      Set<Gmm> gmms = ServiceUtil.readGmms(http);
       if (gmms.isEmpty()) {
-        return GmmServices.metadata(http, serviceId);
+        return ServiceUtil.metadata(http, id);
       }
-      GmmInput in = GmmServices.readGmmInput(http);
-      GmmService.Request gmmRequest = new GmmService.Request(
-          http,
-          serviceId,
-          gmms,
-          in);
-      return GmmService.Spectra.processRequestSpectra(gmmRequest);
+      GmmInput in = ServiceUtil.readGmmInput(http);
+      Request gmmRequest = new Request(http, id, gmms, in);
+      return Spectra.process(gmmRequest);
     } catch (Exception e) {
-      return Utils.handleError(e, serviceId.name, http.getUri().getPath());
+      return Utils.handleError(e, id.name, http.getUri().getPath());
     }
   }
 
@@ -354,20 +349,18 @@ class GmmController {
           defaultValue = "",
           minimum = "0",
           maximum = "10") @QueryValue @Nullable Double z2p5) {
-    Id serviceId = Id.DISTANCE;
+    Id id = Id.DISTANCE;
     try {
-      Set<Gmm> gmms = GmmServices.readGmms(http);
+      Set<Gmm> gmms = ServiceUtil.readGmms(http);
       if (gmms.isEmpty()) {
-        return GmmServices.metadata(http, serviceId);
+        return ServiceUtil.metadata(http, id);
       }
-      GmmInput in = GmmServices.readGmmInput(http);
-      GmmService.Distance.Request request = new GmmService.Distance.Request(
-          http, serviceId,
-          gmms, in,
-          imt, rMin, rMax);
-      return GmmService.Distance.processRequestDistance(request);
+      GmmInput in = ServiceUtil.readGmmInput(http);
+      Distance.Request request = new Distance.Request(
+          http, id, gmms, in, imt, rMin, rMax);
+      return Distance.process(request);
     } catch (Exception e) {
-      return Utils.handleError(e, serviceId.name, http.getUri().getPath());
+      return Utils.handleError(e, id.name, http.getUri().getPath());
     }
   }
 
@@ -465,20 +458,18 @@ class GmmController {
           minimum = "0",
           maximum = "10") @QueryValue @Nullable Double z2p5) {
 
-    Id serviceId = Id.HW_FW;
+    Id id = Id.HW_FW;
     try {
-      Set<Gmm> gmms = GmmServices.readGmms(http);
+      Set<Gmm> gmms = ServiceUtil.readGmms(http);
       if (gmms.isEmpty()) {
-        return GmmServices.metadata(http, serviceId);
+        return ServiceUtil.metadata(http, id);
       }
-      GmmInput in = GmmServices.readGmmInput(http);
-      GmmService.Distance.Request request = new GmmService.Distance.Request(
-          http, serviceId,
-          gmms, in,
-          imt, rMin, rMax);
-      return GmmService.Distance.processRequestDistance(request);
+      GmmInput in = ServiceUtil.readGmmInput(http);
+      Distance.Request request = new Distance.Request(
+          http, id, gmms, in, imt, rMin, rMax);
+      return Distance.process(request);
     } catch (Exception e) {
-      return Utils.handleError(e, serviceId.name, http.getUri().getPath());
+      return Utils.handleError(e, id.name, http.getUri().getPath());
     }
   }
 
@@ -585,20 +576,18 @@ class GmmController {
           defaultValue = "",
           minimum = "0",
           maximum = "10") @QueryValue @Nullable Double z2p5) {
-    Id serviceId = Id.MAGNITUDE;
+    Id id = Id.MAGNITUDE;
     try {
-      Set<Gmm> gmms = GmmServices.readGmms(http);
+      Set<Gmm> gmms = ServiceUtil.readGmms(http);
       if (gmms.isEmpty()) {
-        return GmmServices.metadata(http, serviceId);
+        return ServiceUtil.metadata(http, id);
       }
-      GmmInput in = GmmServices.readGmmInput(http);
-      GmmService.Magnitude.Request gmmRequest = new GmmService.Magnitude.Request(
-          http, serviceId,
-          gmms, in,
-          imt, mMin, mMax, step, distance);
-      return GmmService.Magnitude.processRequestMagnitude(gmmRequest);
+      GmmInput in = ServiceUtil.readGmmInput(http);
+      Magnitude.Request gmmRequest = new Magnitude.Request(
+          http, id, gmms, in, imt, mMin, mMax, step, distance);
+      return Magnitude.process(gmmRequest);
     } catch (Exception e) {
-      return Utils.handleError(e, serviceId.name, http.getUri().getPath());
+      return Utils.handleError(e, id.name, http.getUri().getPath());
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java
index a75c69a..c94054b 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java
@@ -17,18 +17,22 @@ import gov.usgs.earthquake.nshmp.gmm.Gmm;
 import gov.usgs.earthquake.nshmp.gmm.GmmInput;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.www.ResponseBody;
-import gov.usgs.earthquake.nshmp.www.gmm.ResponseSpectra.GmmData;
-import gov.usgs.earthquake.nshmp.www.gmm.XYDataGroup.EpiSeries;
-
+import gov.usgs.earthquake.nshmp.www.gmm.GmmCalc.GmmData;
+import gov.usgs.earthquake.nshmp.www.gmm.XyDataGroup.EpiSeries;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import jakarta.inject.Singleton;
 
+/*
+ * GMM service implementations.
+ *
+ * @author U.S. Geological Survey
+ */
 @Singleton
-public class GmmService {
+class GmmService {
 
   /* Base request object for all GMM services. */
-  public static class Request {
+  static class Request {
 
     transient final HttpRequest<?> http;
     transient final Id serviceId;
@@ -46,37 +50,19 @@ public class GmmService {
     }
   }
 
-  static class Spectra {
-
-    static HttpResponse<String> processRequestSpectra(
-        GmmService.Request request) {
-
-      Map<Gmm, GmmData> spectra = ResponseSpectra.spectra(request.gmms, request.input, false);
-      Response response = Response.create(request.serviceId, spectra);
-      var body = ResponseBody.success()
-          .name(request.serviceId.name)
-          .url(request.http.getUri().getPath())
-          .request(request)
-          .response(response)
-          .build();
-      String json = GmmServices.GSON.toJson(body);
-      return HttpResponse.ok(json);
-    }
-
-  }
-
+  /* Response object for all GMM services. */
   static class Response {
 
-    XYDataGroup means;
-    XYDataGroup sigmas;
+    XyDataGroup means;
+    XyDataGroup sigmas;
 
     private Response(Id service) {
-      means = XYDataGroup.create(
+      means = XyDataGroup.create(
           service.groupNameMean,
           service.xLabel,
           service.yLabelMedian);
 
-      sigmas = XYDataGroup.create(
+      sigmas = XyDataGroup.create(
           service.groupNameSigma,
           service.xLabel,
           service.yLabelSigma);
@@ -87,25 +73,15 @@ public class GmmService {
         Map<Gmm, GmmData> result) {
 
       Response response = new Response(service);
-      response.setXY(result);
-      return response;
-    }
-
-    private void setXY(Map<Gmm, GmmData> result) {
 
       for (Entry<Gmm, GmmData> entry : result.entrySet()) {
         Gmm gmm = entry.getKey();
         GmmData data = entry.getValue();
 
-        XySequence μTotal = XySequence.create(
-            data.periods,
-            formatExp(data.μs));
-
-        XySequence σTotal = XySequence.create(
-            data.periods,
-            format(data.σs));
+        XySequence μTotal = XySequence.create(data.xs, formatExp(data.μs));
+        XySequence σTotal = XySequence.create(data.xs, format(data.σs));
 
-        List<EpiSeries> meanEpi = List.of();
+        List<EpiSeries> μEpi = List.of();
         List<EpiSeries> sigmaEpi = List.of();
 
         // If we have a GMM with a single GroundMotion branch,
@@ -114,12 +90,12 @@ public class GmmService {
 
           boolean hasSigmaBranches = data.tree.get(0).id.contains(" : ");
 
-          meanEpi = data.tree.stream()
+          μEpi = data.tree.stream()
               .map(b -> new EpiSeries(b.id, formatExp(b.μs), b.weights))
               .collect(Collectors.toList());
 
           if (hasSigmaBranches) {
-            meanEpi = collapseGmTree(meanEpi, 0);
+            μEpi = collapseGmTree(μEpi, 0);
 
             sigmaEpi = data.tree.stream()
                 .map(b -> new EpiSeries(b.id, format(b.σs), b.weights))
@@ -127,11 +103,28 @@ public class GmmService {
             sigmaEpi = collapseGmTree(sigmaEpi, 1);
           }
         }
-
-        means.add(gmm.name(), gmm.toString(), μTotal, meanEpi);
-        sigmas.add(gmm.name(), gmm.toString(), σTotal, sigmaEpi);
+        response.means.add(gmm.name(), gmm.toString(), μTotal, μEpi);
+        response.sigmas.add(gmm.name(), gmm.toString(), σTotal, sigmaEpi);
       }
+      return response;
+    }
+  }
+
+  static class Spectra {
+
+    static HttpResponse<String> process(Request request) {
+      Map<Gmm, GmmData> spectra = GmmCalc.spectra(request, false);
+      Response response = Response.create(request.serviceId, spectra);
+      var body = ResponseBody.success()
+          .name(request.serviceId.name)
+          .url(request.http.getUri().getPath())
+          .request(request)
+          .response(response)
+          .build();
+      String json = ServiceUtil.GSON.toJson(body);
+      return HttpResponse.ok(json);
     }
+
   }
 
   static class Distance {
@@ -140,16 +133,11 @@ public class GmmService {
     private static final double R_MAX = 100.0;
     private final static int R_POINTS = 100;
 
-    static HttpResponse<String> processRequestDistance(
-        GmmService.Distance.Request request) {
+    static HttpResponse<String> process(Distance.Request request) {
 
       double[] rArray = distanceArray(request);
 
-      Map<Gmm, GmmData> gmvr = GroundMotionData.versusDistance2(
-          request.gmms,
-          request.input,
-          request.imt,
-          rArray);
+      Map<Gmm, GmmData> gmvr = GmmCalc.distance(request, rArray);
       Response response = Response.create(request.serviceId, gmvr);
       var body = ResponseBody.success()
           .name(request.serviceId.name)
@@ -157,19 +145,19 @@ public class GmmService {
           .request(request)
           .response(response)
           .build();
-      String json = GmmServices.GSON.toJson(body);
+      String json = ServiceUtil.GSON.toJson(body);
       return HttpResponse.ok(json);
     }
 
     private static double[] distanceArray(
         GmmService.Distance.Request request) {
-      var isLog = request.serviceId.equals(Id.DISTANCE) ? true : false;
-      var rStep = isLog
+      boolean isLog = request.serviceId.equals(Id.DISTANCE) ? true : false;
+      double rStep = isLog
           ? (Math.log10(request.rMax / request.rMin)) / (R_POINTS - 1)
           : 1.0;
       return isLog
-          ? GmmServices.sequenceLog(request.rMin, request.rMax, rStep)
-          : GmmServices.sequenceLinear(request.rMin, request.rMax, rStep);
+          ? ServiceUtil.sequenceLog(request.rMin, request.rMax, rStep)
+          : ServiceUtil.sequenceLinear(request.rMin, request.rMax, rStep);
     }
 
     static class Request extends GmmService.Request {
@@ -179,7 +167,7 @@ public class GmmService {
       double rMax;
 
       Request(
-          HttpRequest<?> http, GmmService.Id serviceId,
+          HttpRequest<?> http, Id serviceId,
           Set<Gmm> gmms, GmmInput in,
           Optional<Imt> imt,
           Optional<Double> rMin,
@@ -200,18 +188,12 @@ public class GmmService {
     public static final double M_STEP = 0.1;
     public static final double M_DISTANCE = 10.0;
 
-    static HttpResponse<String> processRequestMagnitude(
-        GmmService.Magnitude.Request request) {
+    static HttpResponse<String> process(Magnitude.Request request) {
 
-      double[] mArray = GmmServices.sequenceLinear(
+      double[] mArray = ServiceUtil.sequenceLinear(
           request.mMin, request.mMax, request.step);
 
-      Map<Gmm, GmmData> gmvm = GroundMotionData.versusMagnitude2(
-          request.gmms,
-          request.input,
-          request.imt,
-          mArray,
-          request.distance);
+      Map<Gmm, GmmData> gmvm = GmmCalc.magnitude(request, mArray, request.distance);
       Response response = Response.create(request.serviceId, gmvm);
       var body = ResponseBody.success()
           .name(request.serviceId.name)
@@ -219,7 +201,7 @@ public class GmmService {
           .request(request)
           .response(response)
           .build();
-      String json = GmmServices.GSON.toJson(body);
+      String json = ServiceUtil.GSON.toJson(body);
       return HttpResponse.ok(json);
     }
 
@@ -232,7 +214,7 @@ public class GmmService {
       double distance;
 
       Request(
-          HttpRequest<?> http, GmmService.Id serviceId,
+          HttpRequest<?> http, Id serviceId,
           Set<Gmm> gmms, GmmInput in,
           Optional<Imt> imt,
           Optional<Double> mMin,
@@ -250,8 +232,6 @@ public class GmmService {
     }
   }
 
-  /* ***********************************************/
-
   /*
    * Consolidators of epi branches. GMMs return logic trees that represent all
    * combinations of means and sigmas. For the response spectra service we want
@@ -288,73 +268,16 @@ public class GmmService {
   private static double[] formatExp(double[] values) {
     return Arrays.stream(values)
         .map(Math::exp)
-        .map(d -> Maths.roundToDigits(d, GmmServices.ROUND))
+        .map(d -> Maths.roundToDigits(d, ServiceUtil.ROUND))
         .toArray();
   }
 
   private static double[] format(double[] values) {
     return Arrays.stream(values)
-        .map(d -> Maths.roundToDigits(d, GmmServices.ROUND))
+        .map(d -> Maths.roundToDigits(d, ServiceUtil.ROUND))
         .toArray();
   }
 
-  // currently used for distance and magnitude
-  @Deprecated
-  static class Response2 {
-
-    XYDataGroup means;
-    XYDataGroup sigmas;
-
-    private Response2(Id service) {
-      means = XYDataGroup.create(
-          service.groupNameMean,
-          service.xLabel,
-          service.yLabelMedian);
-
-      sigmas = XYDataGroup.create(
-          service.groupNameSigma,
-          service.xLabel,
-          service.yLabelSigma);
-    }
-
-    static Response2 create(
-        Id service,
-        GroundMotionData result) {
-
-      Response2 response = new Response2(service);
-      response.setXY(
-          result.xs(),
-          result.means(),
-          result.sigmas());
-      return response;
-    }
-
-    private Response2 setXY(
-        Map<Gmm, List<Double>> xs,
-        Map<Gmm, List<Double>> means,
-        Map<Gmm, List<Double>> sigmas) {
-
-      for (Gmm gmm : means.keySet()) {
-
-        List<Double> gmmMeans = means.get(gmm).stream()
-            .map(Math::exp)
-            .map(mu -> Maths.roundToDigits(mu, GmmServices.ROUND))
-            .collect(Collectors.toList());
-
-        XySequence xyMeans = XySequence.create(
-            xs.get(gmm),
-            gmmMeans);
-        this.means.add(gmm.name(), gmm.toString(), xyMeans, null);
-
-        XySequence xySigmas = XySequence.create(
-            xs.get(gmm),
-            DoubleData.round(GmmServices.ROUND, new ArrayList<>(sigmas.get(gmm))));
-        this.sigmas.add(gmm.name(), gmm.toString(), xySigmas, null);
-      }
-      return this;
-    }
-  }
-
   public static enum Id {
 
     DISTANCE(
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GroundMotionData.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GroundMotionData.java
deleted file mode 100644
index 855788c..0000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GroundMotionData.java
+++ /dev/null
@@ -1,273 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.gmm;
-
-import static java.lang.Math.cos;
-import static java.lang.Math.hypot;
-import static java.lang.Math.sin;
-import static java.lang.Math.tan;
-import static java.lang.Math.toRadians;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.stream.Collectors;
-
-import com.google.common.primitives.Doubles;
-
-import gov.usgs.earthquake.nshmp.Maths;
-import gov.usgs.earthquake.nshmp.gmm.Gmm;
-import gov.usgs.earthquake.nshmp.gmm.GmmInput;
-import gov.usgs.earthquake.nshmp.gmm.GroundMotion;
-import gov.usgs.earthquake.nshmp.gmm.GroundMotionModel;
-import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.tree.LogicTree;
-import gov.usgs.earthquake.nshmp.www.gmm.ResponseSpectra.GmmData;
-
-class GroundMotionData {
-
-  private TreeMap<Gmm, List<Double>> means;
-  private TreeMap<Gmm, List<Double>> sigmas;
-  private TreeMap<Gmm, List<Double>> xs;
-
-  private GroundMotionData(
-      TreeMap<Gmm, List<Double>> means,
-      TreeMap<Gmm, List<Double>> sigmas,
-      TreeMap<Gmm, List<Double>> xs) {
-    this.means = means;
-    this.sigmas = sigmas;
-    this.xs = xs;
-  }
-
-  /**
-   * Calculate ground motion VS distance.
-   *
-   * @param gmms The GMMs
-   * @param inputModel The GMM input
-   * @param imt The intensity measure type
-   * @param distance The distances to calculate ground motions
-   */
-  static GroundMotionData versusDistance(
-      Set<Gmm> gmms,
-      GmmInput inputModel,
-      Imt imt,
-      double[] distances) {
-    var gmmInputList = hangingWallDistances(inputModel, distances);
-    return calculateGroundMotions(gmms, gmmInputList, imt, distances);
-  }
-
-  /**
-   * Calculate ground motion VS distance.
-   *
-   * @param gmms The GMMs
-   * @param inputModel The GMM input
-   * @param imt The intensity measure type
-   * @param distance The distances to calculate ground motions
-   */
-  static Map<Gmm, GmmData> versusDistance2(
-      Set<Gmm> gmms,
-      GmmInput inputModel,
-      Imt imt,
-      double[] distances) {
-    var gmmInputList = hangingWallDistances(inputModel, distances);
-    return calculateGroundMotions2(gmms, gmmInputList, imt, distances);
-  }
-
-  /**
-   * Calculate ground motion VS magnitude.
-   *
-   * @param gmms The GMMs
-   * @param inputModel The GMM input
-   * @param imt The intensity measure type
-   * @param magnitudes The magnitudes to calculate the ground motions
-   * @param distance The distance to calculate ground motions
-   */
-  static GroundMotionData versusMagnitude(
-      Set<Gmm> gmms,
-      GmmInput inputModel,
-      Imt imt,
-      double[] magnitudes,
-      double distance) {
-    var gmmInputs = Arrays.stream(magnitudes)
-        .mapToObj(Mw -> GmmInput.builder().fromCopy(inputModel).mag(Mw).build())
-        .map(gmmInput -> hangingWallDistance(gmmInput, distance))
-        .collect(Collectors.toList());
-
-    return calculateGroundMotions(gmms, gmmInputs, imt, magnitudes);
-  }
-
-  /**
-   * Calculate ground motion VS magnitude.
-   *
-   * @param gmms The GMMs
-   * @param inputModel The GMM input
-   * @param imt The intensity measure type
-   * @param magnitudes The magnitudes to calculate the ground motions
-   * @param distance The distance to calculate ground motions
-   */
-  static Map<Gmm, GmmData> versusMagnitude2(
-      Set<Gmm> gmms,
-      GmmInput inputModel,
-      Imt imt,
-      double[] magnitudes,
-      double distance) {
-    var gmmInputs = Arrays.stream(magnitudes)
-        .mapToObj(Mw -> GmmInput.builder().fromCopy(inputModel).mag(Mw).build())
-        .map(gmmInput -> hangingWallDistance(gmmInput, distance))
-        .collect(Collectors.toList());
-
-    return calculateGroundMotions2(gmms, gmmInputs, imt, magnitudes);
-  }
-
-  Map<Gmm, List<Double>> means() {
-    return Collections.unmodifiableMap(this.means);
-  }
-
-  Map<Gmm, List<Double>> sigmas() {
-    return Collections.unmodifiableMap(this.sigmas);
-  }
-
-  Map<Gmm, List<Double>> xs() {
-    return Collections.unmodifiableMap(this.xs);
-  }
-
-  private static GroundMotionData calculateGroundMotions(
-      Set<Gmm> gmms,
-      List<GmmInput> gmmInputs,
-      Imt imt,
-      double[] distance) {
-    var xsMap = new TreeMap<Gmm, List<Double>>();
-    var meanMap = new TreeMap<Gmm, List<Double>>();
-    var sigmaMap = new TreeMap<Gmm, List<Double>>();
-
-    for (Gmm gmm : gmms) {
-      var means = new ArrayList<Double>();
-      var sigmas = new ArrayList<Double>();
-
-      GroundMotionModel model = gmm.instance(imt);
-      for (GmmInput gmmInput : gmmInputs) {
-        GroundMotion gm = gov.usgs.earthquake.nshmp.gmm.GroundMotions.combine(
-            model.calc(gmmInput));
-        means.add(gm.mean());
-        sigmas.add(gm.sigma());
-      }
-
-      meanMap.put(gmm, List.copyOf(means));
-      sigmaMap.put(gmm, List.copyOf(sigmas));
-      xsMap.put(gmm, Doubles.asList(distance));
-    }
-
-    return new GroundMotionData(
-        meanMap,
-        sigmaMap,
-        xsMap);
-  }
-
-  private static Map<Gmm, GmmData> calculateGroundMotions2(
-      Set<Gmm> gmms,
-      List<GmmInput> gmmInputs,
-      Imt imt,
-      double[] distances) {
-
-    // var xsMap = new TreeMap<Gmm, List<Double>>();
-    // var meanMap = new TreeMap<Gmm, List<Double>>();
-    // var sigmaMap = new TreeMap<Gmm, List<Double>>();
-
-    Map<Gmm, GmmData> gmValues = new EnumMap<>(Gmm.class);
-
-    for (Gmm gmm : gmms) {
-
-      List<LogicTree<GroundMotion>> trees = new ArrayList<>();
-
-      // var means = new ArrayList<Double>();
-      // var sigmas = new ArrayList<Double>();
-
-      GroundMotionModel model = gmm.instance(imt);
-
-      for (GmmInput gmmInput : gmmInputs) {
-
-        trees.add(model.calc(gmmInput));
-
-        // GroundMotion gm = GroundMotions.combine(model.calc(gmmInput));
-        // means.add(gm.mean());
-        // sigmas.add(gm.sigma());
-      }
-
-      GmmData dataGroup = ResponseSpectra.treesToDataGroup(Doubles.asList(distances), trees);
-      gmValues.put(gmm, dataGroup);
-      // meanMap.put(gmm, List.copyOf(means));
-      // sigmaMap.put(gmm, List.copyOf(sigmas));
-      // xsMap.put(gmm, Doubles.asList(distance));
-    }
-
-    return gmValues;
-    // return new GroundMotionData(
-    // meanMap,
-    // sigmaMap,
-    // xsMap);
-  }
-
-  /*
-   * Compute distance metrics for a fault.
-   */
-  private static GmmInput hangingWallDistance(GmmInput inputModel, double r) {
-    /* Dip in radians */
-    double δ = toRadians(inputModel.dip);
-
-    /* Horizontal and vertical widths of fault */
-    double h = cos(δ) * inputModel.width;
-    double v = sin(δ) * inputModel.width;
-
-    /* Depth to bottom of rupture */
-    double zBot = inputModel.zTor + v;
-
-    /* Distance range over which site is normal to fault plane */
-    double rCutLo = tan(δ) * inputModel.zTor;
-    double rCutHi = tan(δ) * zBot + h;
-
-    /* rRup values corresponding to cutoffs above */
-    double rRupLo = Maths.hypot(inputModel.zTor, rCutLo);
-    double rRupHi = Maths.hypot(zBot, rCutHi - h);
-
-    double rJB = (r < 0) ? -r : (r < h) ? 0.0 : r - h;
-    double rRup = (r < rCutLo)
-        ? hypot(r, inputModel.zTor)
-        : (r > rCutHi)
-            ? hypot(r - h, zBot)
-            : rRupScaled(
-                r, rCutLo, rCutHi, rRupLo, rRupHi);
-
-    return GmmInput.builder()
-        .fromCopy(inputModel)
-        .distances(rJB, rRup, r)
-        .build();
-  }
-
-  private static List<GmmInput> hangingWallDistances(
-      GmmInput inputModel,
-      double[] rValues) {
-    return Arrays.stream(rValues)
-        .mapToObj(r -> hangingWallDistance(inputModel, r))
-        .collect(Collectors.toList());
-  }
-
-  /*
-   * Computes rRup for a surface distance r. The range [rCutLo, rCutHi] must
-   * contain r; rRupLo and rRupHi are rRup at rCutLo and rCutHi, respectively.
-   */
-  private static double rRupScaled(
-      double r,
-      double rCutLo,
-      double rCutHi,
-      double rRupLo,
-      double rRupHi) {
-
-    double rRupΔ = rRupHi - rRupLo;
-    double rCutΔ = rCutHi - rCutLo;
-    return rRupLo + (r - rCutLo) / rCutΔ * rRupΔ;
-  }
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ResponseSpectra.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ResponseSpectra.java
deleted file mode 100644
index e7fec23..0000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ResponseSpectra.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.gmm;
-
-import java.util.ArrayList;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.google.common.collect.ImmutableList;
-
-import gov.usgs.earthquake.nshmp.gmm.Gmm;
-import gov.usgs.earthquake.nshmp.gmm.GmmInput;
-import gov.usgs.earthquake.nshmp.gmm.GroundMotion;
-import gov.usgs.earthquake.nshmp.gmm.GroundMotions;
-import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.tree.Branch;
-import gov.usgs.earthquake.nshmp.tree.LogicTree;
-
-/**
- * Factory class for computing deterministic response spectra.
- *
- * @author U.S. Geological Survey
- */
-class ResponseSpectra {
-
-  private static final double PGA_PERIOD = 0.001;
-
-  /**
-   * Compute the spectra of ground motions and their standard deviations for
-   * multiple models and a source. This method provides the option to compute
-   * ground motion values either for the set of common spectral accelerations
-   * supported by the {@link Gmm}s specified, or for every spectral acceleration
-   * supported by each {@link Gmm}. PGA is included in the results with a
-   * spectral period of 0.001s.
-   *
-   * @param gmms {@code GroundMotionModel}s to use
-   * @param input source and site parameterization
-   * @param commonImts {@code true} if only ground motions corresponding to the
-   *        spectral accelerations common to all {@code gmms} should be
-   *        computed; {@code false} if all spectral accelerations supported by
-   *        each gmm should be used.
-   * @return a {@link Result} data container
-   */
-  static Map<Gmm, GmmData> spectra(Set<Gmm> gmms, GmmInput input, boolean commonImts) {
-
-    /*
-     * NOTE: At present, program assumes that all supplied Gmms support PGA.
-     * Although most currently implemented models do, this may not be the case
-     * in the future and program may produce unexpected results.
-     */
-
-    /* Common imts and periods; may not be used. */
-    Set<Imt> saImts = Gmm.responseSpectrumImts(gmms);
-    List<Double> periods = new ArrayList<>();
-    periods.add(PGA_PERIOD);
-    periods.addAll(Imt.periods(saImts));
-
-    Map<Gmm, GmmData> gmmSpectra = new EnumMap<>(Gmm.class);
-    for (Gmm gmm : gmms) {
-      if (!commonImts) {
-        saImts = gmm.responseSpectrumImts();
-        periods = ImmutableList.<Double> builder()
-            .add(PGA_PERIOD)
-            .addAll(Imt.periods(saImts))
-            .build();
-      }
-
-      List<LogicTree<GroundMotion>> imtTrees = new ArrayList<>();
-      imtTrees.add(gmm.instance(Imt.PGA).calc(input));
-      for (Imt imt : saImts) {
-        imtTrees.add(gmm.instance(imt).calc(input));
-      }
-
-      GmmData dataGroup = treesToDataGroup(periods, imtTrees);
-      gmmSpectra.put(gmm, dataGroup);
-    }
-    return gmmSpectra;
-  }
-
-  static GmmData treesToDataGroup(
-      List<Double> periods,
-      List<LogicTree<GroundMotion>> trees) {
-
-    // Can't use Trees.transpose() because some
-    // GMMs have period dependent weights
-
-    LogicTree<GroundMotion> modelTree = trees.get(0);
-    List<String> branchIds = modelTree.stream()
-        .map(Branch::id)
-        .collect(Collectors.toList());
-
-    double[] Ts = periods.stream().mapToDouble(Double::valueOf).toArray();
-    double[] μs = new double[periods.size()];
-    double[] σs = new double[periods.size()];
-
-    // build combined μ and σ
-    for (int i = 0; i < trees.size(); i++) {
-      GroundMotion combined = GroundMotions.combine(trees.get(i));
-      μs[i] = combined.mean();
-      σs[i] = combined.sigma();
-    }
-
-    List<EpiBranch> epiBranches = new ArrayList<>();
-
-    // short circuit if tree is single branch
-    if (modelTree.size() > 1) {
-
-      // branch index, imt index
-      List<double[]> μBranches = new ArrayList<>();
-      List<double[]> σBranches = new ArrayList<>();
-      List<double[]> weights = new ArrayList<>();
-      for (int i = 0; i < modelTree.size(); i++) {
-        μBranches.add(new double[periods.size()]);
-        σBranches.add(new double[periods.size()]);
-        weights.add(new double[periods.size()]);
-      }
-
-      // imt indexing
-      for (int i = 0; i < trees.size(); i++) {
-        LogicTree<GroundMotion> tree = trees.get(i);
-        // epi branch indexing
-        for (int j = 0; j < tree.size(); j++) {
-          Branch<GroundMotion> branch = tree.get(j);
-          μBranches.get(j)[i] = branch.value().mean();
-          σBranches.get(j)[i] = branch.value().sigma();
-          weights.get(j)[i] = branch.weight();
-        }
-      }
-
-      for (int i = 0; i < modelTree.size(); i++) {
-        EpiBranch epiBranch = new EpiBranch(
-            branchIds.get(i),
-            μBranches.get(i),
-            σBranches.get(i),
-            weights.get(i));
-        epiBranches.add(epiBranch);
-      }
-    }
-
-    GmmData gmmData = new GmmData(Ts, μs, σs, epiBranches);
-    return gmmData;
-  }
-
-  static class GmmData {
-
-    final double[] periods; // should be any x-value
-    final double[] μs;
-    final double[] σs;
-    final List<EpiBranch> tree;
-
-    GmmData(
-        double[] periods,
-        double[] μs,
-        double[] σs,
-        List<EpiBranch> tree) {
-
-      this.periods = periods;
-      this.μs = μs;
-      this.σs = σs;
-      this.tree = tree;
-    }
-  }
-
-  static class EpiBranch {
-
-    final String id;
-    final double[] μs;
-    final double[] σs;
-    final double[] weights;
-
-    EpiBranch(String id, double[] μs, double[] σs, double[] weights) {
-      this.id = id;
-      this.μs = μs;
-      this.σs = σs;
-      this.weights = weights;
-    }
-  }
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmServices.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java
similarity index 88%
rename from src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmServices.java
rename to src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java
index 5db6efd..918aee7 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmServices.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java
@@ -49,12 +49,11 @@ import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Id;
 import gov.usgs.earthquake.nshmp.www.meta.EnumParameter;
-
 import io.micronaut.http.HttpParameters;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 
-class GmmServices {
+class ServiceUtil {
 
   final static int ROUND = 5;
   static final Range<Double> MAGNITUDE_DEFAULT_VALUES = Range.closed(5.0, 8.0);
@@ -70,39 +69,28 @@ class GmmServices {
         .serializeNulls()
         .disableHtmlEscaping()
         .registerTypeAdapter(Double.class, new WsUtils.NaNSerializer())
-        .registerTypeAdapter(GmmServices.Parameters.class,
-            new GmmServices.Parameters.Serializer())
+        .registerTypeAdapter(ServiceUtil.Parameters.class,
+            new ServiceUtil.Parameters.Serializer())
         .registerTypeAdapter(Imt.class, new WsUtils.EnumSerializer<Imt>())
         .registerTypeAdapter(Constraints.class, new WsUtils.ConstraintsSerializer())
         .create();
   }
 
   public static HttpResponse<String> metadata(HttpRequest<?> request, Id service) {
-    var metadata = GSON.toJson(GmmServices.getMetadata(request, service));
+    var metadata = GSON.toJson(ServiceUtil.getMetadata(request, service));
     return HttpResponse.ok(metadata);
   }
 
   /** Query and JSON reqest/response keys. */
   static final class Key {
     public static final String DISTANCE = "distance";
-    public static final String ID = "id";
     public static final String IMT = "imt";
     public static final String GMM = "gmm";
-    public static final String GPSDATASET = "gpsdataset";
-    public static final String GROUP = "group";
-    public static final String LABEL = "label";
-    public static final String LATITUDE = "latitude";
-    public static final String LONGITUDE = "longitude";
     public static final String M_MIN = "mMin";
     public static final String M_MAX = "mMax";
-    public static final String MODEL = "model";
-    public static final String NAME = "name";
     public static final String R_MAX = "rMax";
     public static final String R_MIN = "rMin";
     public static final String STEP = "step";
-    public static final String Z1P0 = "z1p0";
-    public static final String Z2P5 = "z2p5";
-
   }
 
   /* Read the GMM input query values. */
@@ -139,7 +127,7 @@ class GmmServices {
   static ResponseBody<String, MetadataResponse> getMetadata(
       HttpRequest<?> request,
       Id service) {
-    var url = request.getUri().getPath();
+    String url = request.getUri().getPath();
     return ResponseBody.<String, MetadataResponse> usage()
         .name(service.name)
         .url(url)
@@ -180,7 +168,9 @@ class GmmServices {
   private static Param createGmmInputParam(
       Field field,
       Optional<?> constraint) {
-    return (field == VSINF) ? new BooleanParam(field)
+
+    return (field == VSINF)
+        ? new BooleanParam(field)
         : new NumberParam(field, (Range<Double>) constraint.orElseThrow());
   }
 
@@ -211,7 +201,7 @@ class GmmServices {
           final EnumParameter<Imt> imts = new EnumParameter<>(
               "Intensity measure type",
               imtSet);
-          root.add(Key.IMT.toString(), context.serialize(imts));
+          root.add(Key.IMT, context.serialize(imts));
         }
 
         /* Serialize input fields. */
@@ -227,60 +217,61 @@ class GmmServices {
         }
 
         if (meta.service.equals(Id.DISTANCE) || meta.service.equals(Id.HW_FW)) {
-          var min = meta.service.equals(Id.HW_FW) ? Range.openClosed(0.0, 1.0).lowerEndpoint()
+          double min = meta.service.equals(Id.HW_FW)
+              ? Range.openClosed(0.0, 1.0).lowerEndpoint()
               : DISTANCE_DEFAULT_VALUES.lowerEndpoint();
-          var rMin = new NumberParam(
+          NumberParam rMin = new NumberParam(
               "Minimum distance",
               "The minimum distance to use for calculation",
               Field.RX.units.orElse(null),
               Range.openClosed(0.0, 1000.0),
               min);
-          root.add(Key.R_MIN.toString(), context.serialize(rMin));
+          root.add(Key.R_MIN, context.serialize(rMin));
 
-          var rMax = new NumberParam(
+          NumberParam rMax = new NumberParam(
               "Maximum distance",
               "The maximum distance to use for calculation",
               Field.RX.units.orElse(null),
               Range.closed(-1000.0, 1000.0),
               DISTANCE_DEFAULT_VALUES.upperEndpoint());
-          root.add(Key.R_MAX.toString(), context.serialize(rMax));
+          root.add(Key.R_MAX, context.serialize(rMax));
         }
 
         if (meta.service.equals(Id.MAGNITUDE)) {
           @SuppressWarnings("unchecked")
-          var mMin = new NumberParam(
+          NumberParam mMin = new NumberParam(
               "Minimum distance",
               "The minimum distance to use for calculation",
               Field.MW.units.orElse(null),
               (Range<Double>) defaults.get(Field.MW).orElseThrow(),
               MAGNITUDE_DEFAULT_VALUES.lowerEndpoint());
-          root.add(Key.M_MIN.toString(), context.serialize(mMin));
+          root.add(Key.M_MIN, context.serialize(mMin));
 
           @SuppressWarnings("unchecked")
-          var mMax = new NumberParam(
+          NumberParam mMax = new NumberParam(
               "Maximum magnitude",
               "The maximum magnitude to use for calculation",
               Field.MW.units.orElse(null),
               (Range<Double>) defaults.get(Field.MW).orElseThrow(),
               MAGNITUDE_DEFAULT_VALUES.upperEndpoint());
-          root.add(Key.M_MAX.toString(), context.serialize(mMax));
+          root.add(Key.M_MAX, context.serialize(mMax));
 
           @SuppressWarnings("unchecked")
-          var distance = new NumberParam(
+          NumberParam distance = new NumberParam(
               "Distance",
               "The distance between site and trace ",
               Field.RX.units.orElse(null),
               (Range<Double>) defaults.get(Field.RX).orElseThrow(),
               MAGNITUDE_DEFAULT_DISTANCE);
-          root.add(Key.DISTANCE.toString(), context.serialize(distance));
+          root.add(Key.DISTANCE, context.serialize(distance));
 
-          var step = new NumberParam(
+          NumberParam step = new NumberParam(
               "Magnitude step",
               "The step between each magnitude ",
               null,
               Range.closed(0.0001, 1.0),
               MAGNITUDE_DEFAULT_STEP);
-          root.add(Key.STEP.toString(), context.serialize(step));
+          root.add(Key.STEP, context.serialize(step));
         }
 
         /* Add only add those Gmms that belong to a Group. */
@@ -294,7 +285,7 @@ class GmmServices {
             GMM_NAME,
             GMM_INFO,
             gmms);
-        root.add(Key.GMM.toString(), context.serialize(gmmParam));
+        root.add(Key.GMM, context.serialize(gmmParam));
 
         /* Add gmm groups. */
         GroupParam groups = new GroupParam(
@@ -316,6 +307,7 @@ class GmmServices {
    */
   private static interface Param {}
 
+  @SuppressWarnings("unused")
   private static final class NumberParam implements Param {
 
     final String label;
@@ -348,6 +340,7 @@ class GmmServices {
     }
   }
 
+  @SuppressWarnings("unused")
   private static final class BooleanParam implements Param {
 
     final String label;
@@ -368,6 +361,7 @@ class GmmServices {
   private static final String GMM_NAME = "Ground Motion Models";
   private static final String GMM_INFO = "Empirical models of ground motion";
 
+  @SuppressWarnings("unused")
   private static class GmmParam implements Param {
 
     final String label;
@@ -392,12 +386,12 @@ class GmmServices {
       Value(Gmm gmm) {
         this.id = gmm.name();
         this.label = gmm.toString();
-        this.supportedImts = SupportedImts(gmm.supportedImts());
+        this.supportedImts = supportedImts(gmm.supportedImts());
         this.constraints = gmm.constraints();
       }
     }
 
-    private static ArrayList<String> SupportedImts(Set<Imt> imts) {
+    private static ArrayList<String> supportedImts(Set<Imt> imts) {
       ArrayList<String> supportedImts = new ArrayList<>();
 
       for (Imt imt : imts) {
@@ -413,6 +407,7 @@ class GmmServices {
   private static final String GROUP_NAME = "Ground Motion Model Groups";
   private static final String GROUP_INFO = "Groups of related ground motion models ";
 
+  @SuppressWarnings("unused")
   private static final class GroupParam implements Param {
 
     final String label;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/XYDataGroup.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/XyDataGroup.java
similarity index 59%
rename from src/main/java/gov/usgs/earthquake/nshmp/www/gmm/XYDataGroup.java
rename to src/main/java/gov/usgs/earthquake/nshmp/www/gmm/XyDataGroup.java
index 7a02bcc..2b3b3ca 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/XYDataGroup.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/XyDataGroup.java
@@ -5,45 +5,45 @@ import java.util.List;
 
 import gov.usgs.earthquake.nshmp.data.XySequence;
 
-/**
- * Container class of XY data sequences prior to JSON serialization.
+/*
+ * XY data sequences serialization object.
  *
  * @author U.S. Geological Survey
  */
 @SuppressWarnings("unused")
-public class XYDataGroup {
+class XyDataGroup {
 
   private final String label;
   private final String xLabel;
   private final String yLabel;
   private final List<Series> data;
 
-  private XYDataGroup(String label, String xLabel, String yLabel) {
+  private XyDataGroup(String label, String xLabel, String yLabel) {
     this.label = label;
     this.xLabel = xLabel;
     this.yLabel = yLabel;
     this.data = new ArrayList<>();
   }
 
-  /** Create a data group. */
-  public static XYDataGroup create(String name, String xLabel, String yLabel) {
-    return new XYDataGroup(name, xLabel, yLabel);
+  /* Create a data group. */
+  static XyDataGroup create(String name, String xLabel, String yLabel) {
+    return new XyDataGroup(name, xLabel, yLabel);
   }
 
-  /** Add a data sequence */
-  public XYDataGroup add(String id, String name, XySequence data, List<EpiSeries> tree) {
+  /* Add a data sequence */
+  XyDataGroup add(String id, String name, XySequence data, List<EpiSeries> tree) {
     this.data.add(new Series(id, name, data, tree));
     return this;
   }
 
-  public static class Series {
+  static class Series {
 
     private final String id;
     private final String label;
     private final XySequence data;
     private final List<EpiSeries> tree;
 
-    public Series(String id, String label, XySequence data, List<EpiSeries> tree) {
+    Series(String id, String label, XySequence data, List<EpiSeries> tree) {
       this.id = id;
       this.label = label;
       this.data = data;
@@ -51,13 +51,13 @@ public class XYDataGroup {
     }
   }
 
-  public static class EpiSeries {
+  static class EpiSeries {
 
     final String id;
     final double[] values;
     final double[] weights;
 
-    public EpiSeries(String id, double[] values, double[] weights) {
+    EpiSeries(String id, double[] values, double[] weights) {
       this.id = id;
       this.values = values;
       this.weights = weights;
-- 
GitLab


From c061f1ffabf4e2b1f42da32613fb3da3cff663ad Mon Sep 17 00:00:00 2001
From: Peter Powers <pmpowers@usgs.gov>
Date: Sun, 27 Mar 2022 14:19:43 -0600
Subject: [PATCH 2/2] spotless formatting

---
 src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java     | 1 +
 .../java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java    | 1 +
 src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java  | 1 +
 src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java | 1 +
 4 files changed, 4 insertions(+)

diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
index 6e72c4d..405dd20 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
@@ -29,6 +29,7 @@ import gov.usgs.earthquake.nshmp.tree.LogicTree;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Distance;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Magnitude;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Request;
+
 import jakarta.inject.Singleton;
 
 /*
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java
index ccdfbb7..2829212 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmController.java
@@ -13,6 +13,7 @@ import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Id;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Magnitude;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Request;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Spectra;
+
 import io.micronaut.core.annotation.Nullable;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java
index c94054b..8bff81f 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmService.java
@@ -19,6 +19,7 @@ import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmCalc.GmmData;
 import gov.usgs.earthquake.nshmp.www.gmm.XyDataGroup.EpiSeries;
+
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
 import jakarta.inject.Singleton;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java
index 918aee7..f817cc4 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/ServiceUtil.java
@@ -49,6 +49,7 @@ import gov.usgs.earthquake.nshmp.www.ResponseBody;
 import gov.usgs.earthquake.nshmp.www.WsUtils;
 import gov.usgs.earthquake.nshmp.www.gmm.GmmService.Id;
 import gov.usgs.earthquake.nshmp.www.meta.EnumParameter;
+
 import io.micronaut.http.HttpParameters;
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
-- 
GitLab