diff --git a/gradle.properties b/gradle.properties
index a21f15bb4f8e436b6f07268d710529931fb34690..05d85ab7cfb8528be67b23d6ef80b6cbc261647b 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -9,7 +9,7 @@ junitVersion = 5.5.2
 logbackVersion = 1.2.3
 mnOpenAPIVersion = 1.4.0
 mnVersion = 1.3.2
-nshmpLibVersion = 0.2.4
+nshmpLibVersion = 0.2.8
 shadowVersion = 5.2.0
 spotbugsVersion = 4.2.4
 spotlessVersion = 4.1.0
diff --git a/settings.gradle b/settings.gradle
index 7163afdd2ea2fbcd05d2a68d3a1fa17040a9eb48..fddc289feaadbb730967c279b9d21f322f5f1337 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -9,6 +9,6 @@ git {
 
   fetch("https://code.usgs.gov/ghsc/nshmp/nshm-conus-2018.git", {
     name "nshmp-haz-dep--nshm-conus-2018"
-    tag "0.2.0"
+    tag "0.2.3"
   })
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/GroundMotions.java b/src/main/java/gov/usgs/earthquake/nshmp/GroundMotions.java
deleted file mode 100644
index 377b9473f825aab412a07ddee4ee8c804b1c2eb4..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/GroundMotions.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package gov.usgs.earthquake.nshmp;
-
-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.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.google.common.primitives.Doubles;
-
-import gov.usgs.earthquake.nshmp.data.DoubleData;
-import gov.usgs.earthquake.nshmp.gmm.Gmm;
-import gov.usgs.earthquake.nshmp.gmm.GmmInput;
-import gov.usgs.earthquake.nshmp.gmm.GroundMotionModel;
-import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.gmm.ScalarGroundMotion;
-
-@Deprecated
-public class GroundMotions {
-
-  private final static int ROUND = 5;
-  private final static int R_POINTS = 100;
-
-  public static DistanceResult distanceGroundMotions(
-      Set<Gmm> gmms,
-      GmmInput inputModel,
-      Imt imt,
-      double rMin,
-      double rMax,
-      boolean isLogSpace) {
-
-    double[] distance = isLogSpace ? distanceLog(rMin, rMax) : distanceLinear(rMin, rMax);
-    List<GmmInput> gmmInputs = hangingWallDistances(distance, inputModel);
-
-    Map<Gmm, List<Double>> distanceMap = Maps.newEnumMap(Gmm.class);
-    Map<Gmm, List<Double>> meanMap = Maps.newEnumMap(Gmm.class);
-    Map<Gmm, List<Double>> sigmaMap = Maps.newEnumMap(Gmm.class);
-
-    for (Gmm gmm : gmms) {
-      ImmutableList.Builder<Double> means = ImmutableList.builder();
-      ImmutableList.Builder<Double> sigmas = ImmutableList.builder();
-
-      GroundMotionModel model = gmm.instance(imt);
-      for (GmmInput gmmInput : gmmInputs) {
-        ScalarGroundMotion gm = model.calc(gmmInput);
-        means.add(gm.mean());
-        sigmas.add(gm.sigma());
-      }
-
-      meanMap.put(gmm, means.build());
-      sigmaMap.put(gmm, sigmas.build());
-      distanceMap.put(gmm, Doubles.asList(distance));
-    }
-
-    return new DistanceResult(
-        Maps.immutableEnumMap(distanceMap),
-        Maps.immutableEnumMap(meanMap),
-        Maps.immutableEnumMap(sigmaMap));
-  }
-
-  public static class DistanceResult {
-
-    public final Map<Gmm, List<Double>> means;
-    public final Map<Gmm, List<Double>> distance;
-    public final Map<Gmm, List<Double>> sigmas;
-
-    DistanceResult(
-        Map<Gmm, List<Double>> distance,
-        Map<Gmm, List<Double>> means,
-        Map<Gmm, List<Double>> sigmas) {
-      this.distance = distance;
-      this.means = means;
-      this.sigmas = sigmas;
-    }
-  }
-
-  static double[] distanceLog(double rMin, double rMax) {
-    double rStep = (Math.log10(rMax / rMin)) / (R_POINTS - 1);
-    double[] distance = DoubleData.round(ROUND, DoubleData.pow10(
-        DoubleData.buildSequence(Math.log10(rMin), Math.log10(rMax), rStep, true)));
-
-    return distance;
-  }
-
-  static double[] distanceLinear(double rMin, double rMax) {
-    double rStep = 1.0;
-    double[] distance = DoubleData.buildCleanSequence(
-        rMin, rMax, rStep, true, ROUND);
-
-    return distance;
-  }
-
-  /*
-   * Compute distance metrics for a fault.
-   */
-  static List<GmmInput> hangingWallDistances(
-      double[] rValues,
-      GmmInput inputModel) {
-
-    /* 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.zTop + v;
-
-    /* Distance range over which site is normal to fault plane */
-    double rCutLo = tan(δ) * inputModel.zTop;
-    double rCutHi = tan(δ) * zBot + h;
-
-    /* rRup values corresponding to cutoffs above */
-    double rRupLo = Maths.hypot(inputModel.zTop, rCutLo);
-    double rRupHi = Maths.hypot(zBot, rCutHi - h);
-
-    List<GmmInput> gmmInputs = new ArrayList<>(rValues.length);
-    GmmInput.Builder gmmBuilder = GmmInput.builder().fromCopy(inputModel);
-
-    for (double r : rValues) {
-      double rJB = (r < 0) ? -r : (r < h) ? 0.0 : r - h;
-      double rRup = (r < rCutLo)
-          ? hypot(r, inputModel.zTop)
-          : (r > rCutHi)
-              ? hypot(r - h, zBot)
-              : rRupScaled(r, rCutLo, rCutHi, rRupLo, rRupHi);
-      gmmBuilder.distances(rJB, rRup, r);
-      gmmInputs.add(gmmBuilder.build());
-    }
-
-    return gmmInputs;
-  }
-
-  /*
-   * 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/Hazard2018.java b/src/main/java/gov/usgs/earthquake/nshmp/Hazard2018.java
index 0602e143eda282efe701635b60681459bea0061f..1c68fa0373773537185b6635aa1e0e382c39853d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/Hazard2018.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/Hazard2018.java
@@ -42,6 +42,7 @@ import gov.usgs.earthquake.nshmp.model.HazardModel;
  *
  * @author U.S. Geological Survey
  */
+@Deprecated
 public class Hazard2018 {
 
   /**
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/HazardCalc.java b/src/main/java/gov/usgs/earthquake/nshmp/HazardCalc.java
index 9234da417b608a1d2a750f71f19af5f876ed985a..dd7defad54d8d72a9ebefbc5e98d65cd85f93a83 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/HazardCalc.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/HazardCalc.java
@@ -46,21 +46,23 @@ public class HazardCalc {
    * At a minimum, the path to a model directory and the site(s) at which to
    * perform calculations must be specified. Under the 2-argument scenario,
    * model initialization and calculation configuration settings are drawn from
-   * the config file that <i>must</i> reside at the root of the model directory.
-   * Sites may be defined as a string, a CSV file, or a GeoJSON file.
+   * the deafult configuration accompanying and located at the root of the model
+   * directory. Sites may be defined as a string, a CSV file, or a GeoJSON file.
    *
    * <p>To override any default or calculation configuration settings included
    * with the model, supply the path to another configuration file as a third
    * argument.
    *
-   * <p>Please refer to the nshmp-haz <a
-   * href="https://github.com/usgs/nshmp-haz/wiki" target="_top">wiki</a> for
-   * comprehensive descriptions of source models, configuration files, site
-   * files, and hazard calculations.
+   * <p>Refer to the nshmp-haz <a
+   * href="https://code.usgs.gov/ghsc/nshmp/nshmp-haz-v2/-/wikis"
+   * target="_top">wiki</a> for comprehensive descriptions of source models,
+   * configuration files, site files, and hazard calculations.
    *
-   * @see <a href="https://github.com/usgs/nshmp-haz/wiki/Building-&-Running"
+   * @see <a
+   *      href="https://code.usgs.gov/ghsc/nshmp/nshmp-haz-v2/-/wikis/Building-&-Running"
    *      target="_top"> nshmp-haz wiki</a>
-   * @see <a href="https://github.com/usgs/nshmp-haz/tree/master/etc/examples"
+   * @see <a
+   *      href="https://code.usgs.gov/ghsc/nshmp/nshmp-haz-v2/-/tree/master/etc/examples"
    *      target="_top"> example calculations</a>
    */
   public static void main(String[] args) {
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/ResponseSpectra.java b/src/main/java/gov/usgs/earthquake/nshmp/ResponseSpectra.java
deleted file mode 100644
index 3e2e6f35404a9027ee7929b2b434e15fb4af0362..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/ResponseSpectra.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package gov.usgs.earthquake.nshmp;
-
-import static com.google.common.base.StandardSystemProperty.LINE_SEPARATOR;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-
-import gov.usgs.earthquake.nshmp.gmm.Gmm;
-import gov.usgs.earthquake.nshmp.gmm.GmmInput;
-import gov.usgs.earthquake.nshmp.gmm.GroundMotionModel;
-import gov.usgs.earthquake.nshmp.gmm.Imt;
-import gov.usgs.earthquake.nshmp.gmm.ScalarGroundMotion;
-
-/**
- * Entry point for computing deterministic response spectra.
- *
- * <p>In addition to a {@code main()} method, several utility methods are
- * provided for different target users. For instance
- * {@link #groundMotion(Gmm, Imt, GmmInput)} and
- * {@link #spectrum(Gmm, GmmInput)} are convenient for use within Matlab as they
- * return simple data container objects that are automatically converted to
- * Matlab structs and arrays. {@link #spectra(Set, GmmInput, boolean)} returns a
- * more complex result and is for use with web services.
- *
- * @author U.S. Geological Survey
- */
-@Deprecated
-public class ResponseSpectra {
-
-  private static final double PGA_PERIOD = 0.001;
-
-  /**
-   * Compute the median ground motion and its standard deviation for a specified
-   * {@link GroundMotionModel}, intensity measure type ({@link Imt} ), and
-   * source and site parameterization ({@link GmmInput}).
-   *
-   * <p>{@code enum} types are identified in matlab as e.g. {@link Gmm#ASK_14}.
-   *
-   * @param model to use
-   * @param imt intensity measure type (e.g. {@code PGA}, {@code SA1P00})
-   * @param source and site parameterization
-   * @return a two-element double[] containing the natural log of the median
-   *         ground motion and its standard deviation
-   */
-  public static double[] groundMotion(Gmm model, Imt imt, GmmInput source) {
-    ScalarGroundMotion sgm = model.instance(imt).calc(source);
-    return new double[] { sgm.mean(), sgm.sigma() };
-  }
-
-  /**
-   * Compute a spectrum of ground motions and their standard deviations for a
-   * specified {@link GroundMotionModel} and source and site parameterization (
-   * {@link GmmInput}). All spectral periods supported by the model are
-   * returned.
-   *
-   * <p>This method is intended for use with Matlab, which converts
-   * {@code Result} to a struct automatically.
-   *
-   * <p>{@code enum} types are identified in matlab as e.g. {@link Gmm#ASK_14}.
-   *
-   * @param model to use
-   * @param input source and site parameterization
-   * @return a Result
-   */
-  public static Result spectrum(Gmm model, GmmInput input) {
-    Set<Imt> imts = model.responseSpectrumIMTs();
-    Result spectrum = new Result(imts.size());
-    int i = 0;
-    for (Imt imt : imts) {
-      ScalarGroundMotion sgm = model.instance(imt).calc(input);
-      spectrum.periods[i] = imt.period();
-      spectrum.means[i] = sgm.mean();
-      spectrum.sigmas[i] = sgm.sigma();
-      i++;
-    }
-    return spectrum;
-  }
-
-  /** The result produced by calling {@link #spectrum(Gmm, GmmInput)}. */
-  public static class Result {
-
-    /** Spectral periods. */
-    public final double[] periods;
-
-    /** Ground motion means. */
-    public final double[] means;
-
-    /** Ground motion sigmas. */
-    public final double[] sigmas;
-
-    Result(int size) {
-      periods = new double[size];
-      means = new double[size];
-      sigmas = new double[size];
-    }
-  }
-
-  /**
-   * 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 MultiResult} data container
-   */
-  public static MultiResult spectra(Set<Gmm> gmms, GmmInput input, boolean commonImts) {
-
-    Map<Gmm, List<Double>> periodMap = Maps.newEnumMap(Gmm.class);
-    Map<Gmm, List<Double>> meanMap = Maps.newEnumMap(Gmm.class);
-    Map<Gmm, List<Double>> sigmaMap = Maps.newEnumMap(Gmm.class);
-
-    /*
-     * 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);
-    ImmutableList<Double> periods = ImmutableList.<Double> builder()
-        .add(PGA_PERIOD)
-        .addAll(Imt.periods(saImts))
-        .build();
-
-    for (Gmm gmm : gmms) {
-      if (!commonImts) {
-        saImts = gmm.responseSpectrumIMTs();
-        periods = ImmutableList.<Double> builder()
-            .add(PGA_PERIOD)
-            .addAll(Imt.periods(saImts))
-            .build();
-      }
-      ImmutableList.Builder<Double> means = ImmutableList.builder();
-      ImmutableList.Builder<Double> sigmas = ImmutableList.builder();
-
-      ScalarGroundMotion pgaGm = gmm.instance(Imt.PGA).calc(input);
-      means.add(pgaGm.mean());
-      sigmas.add(pgaGm.sigma());
-
-      for (Imt imt : saImts) {
-        ScalarGroundMotion sgm = gmm.instance(imt).calc(input);
-        means.add(sgm.mean());
-        sigmas.add(sgm.sigma());
-      }
-      periodMap.put(gmm, periods);
-      meanMap.put(gmm, means.build());
-      sigmaMap.put(gmm, sigmas.build());
-    }
-
-    return new MultiResult(
-        Maps.immutableEnumMap(periodMap),
-        Maps.immutableEnumMap(meanMap),
-        Maps.immutableEnumMap(sigmaMap));
-  }
-
-  /** The result of calling {@link #spectra(Set, GmmInput, boolean)}. */
-  public static class MultiResult {
-
-    /** Spectral periods. */
-    public final Map<Gmm, List<Double>> periods;
-
-    /** Map of ground motion means. */
-    public final Map<Gmm, List<Double>> means;
-
-    /** Map of ground motion sigmas. */
-    public final Map<Gmm, List<Double>> sigmas;
-
-    MultiResult(
-        Map<Gmm, List<Double>> periods,
-        Map<Gmm, List<Double>> means,
-        Map<Gmm, List<Double>> sigmas) {
-      this.periods = periods;
-      this.means = means;
-      this.sigmas = sigmas;
-    }
-  }
-
-  /**
-   * Entry point for computing deterministic response spectra from the command
-   * line. Quite a few arguments are required to specify the GroundMotionModel
-   * to use and parameterize the earthquake source and site of interest. Example
-   * usage:
-   *
-   * <pre>
-   * java -cp nshmp-haz.jar org.opensha.programs.DeterministicSpectra ...
-   *   ... ASK_14 6.5 10.0 10.3 10.0 90.0 14.0 0.5 7.5 0.0 760.0 true NaN NaN
-   * </pre>
-   *
-   * @param args
-   *        {@code [Gmm  mag rJB  rRup rX dip width zTop zHyp rake vs30 vsInf z1p0 z2p5]}
-   */
-  public static void main(String[] args) {
-    String result = calcMain(args);
-    System.out.println(result);
-    System.exit(0);
-  }
-
-  private static String calcMain(String[] args) {
-    if (args.length != 14) {
-      System.err.println(USAGE);
-      System.exit(1);
-    }
-    Gmm gmm = Gmm.valueOf(args[0]);
-    GmmInput input = GmmInput.builder()
-        .mag(Double.valueOf(args[1]))
-        .rJB(Double.valueOf(args[2]))
-        .rRup(Double.valueOf(args[3]))
-        .rX(Double.valueOf(args[4]))
-        .dip(Double.valueOf(args[5]))
-        .width(Double.valueOf(args[6]))
-        .zTop(Double.valueOf(args[7]))
-        .zHyp(Double.valueOf(args[8]))
-        .rake(Double.valueOf(args[9]))
-        .vs30(Double.valueOf(args[10]))
-        .vsInf(Boolean.valueOf(args[11]))
-        .z1p0(Double.valueOf(args[12]))
-        .z2p5(Double.valueOf(args[13]))
-        .build();
-    Result result = spectrum(gmm, input);
-    StringBuilder sb = new StringBuilder();
-    sb.append("periods=").append(Arrays.toString(result.periods));
-    sb.append(LINE_SEPARATOR.value());
-    sb.append("means=").append(Arrays.toString(result.means));
-    sb.append(LINE_SEPARATOR.value());
-    sb.append("sigmas=").append(Arrays.toString(result.sigmas));
-    return sb.toString();
-  }
-
-  private static final String USAGE = "DeterministicSpectra usage:" +
-      LINE_SEPARATOR.value() +
-      LINE_SEPARATOR.value() +
-      "command: java -cp nshmp-haz.jar org.opensha.programs.DeterministicSpectra Gmm mag rJB rRup rX dip width zTop zHyp rake vs30 vsInf z1p0 z2p5" +
-      LINE_SEPARATOR.value() +
-      "example: java -cp nshmp-haz.jar org.opensha.programs.DeterministicSpectra ASK_14 6.5 10.0 10.3 10.0 90.0 14.0 0.5 7.5 0.0 760.0 true NaN NaN" +
-      LINE_SEPARATOR.value() +
-      LINE_SEPARATOR.value() +
-      "  - For more details, see: http://usgs.github.io/nshmp-haz/docs/gov/usgs/earthquake/nshmp/programs/DeterministicSpectra.html";
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
index 5ba9a19fc1bec57f5bd3f45801f2ab846c3b19a5..74f7fc8119cee26e214e36b29dbdc5d926cefa76 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultSliceLambda.java
@@ -46,7 +46,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  *
  * The results are written to S3 as map.csv bucket.
  */
-@SuppressWarnings("unused")
 public class HazardResultSliceLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
index d7ece57af667f4fc877c12ec4a8759cd84822399..1d7db3b60f456792d2aa9ea96b98221a6b078cbe 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsMetadataLambda.java
@@ -43,7 +43,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  * AWS Lambda function to list all hazard results in the nshmp-hazout S3 bucket
  * that contain a map.csv file.
  */
-@SuppressWarnings("unused")
 public class HazardResultsMetadataLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
index f48d7babebb87882844c5f7dcfe8d41c24163153..ac5925f3eab869984ad50c92b9bde09d3b01ca3c 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/aws/HazardResultsSlicerLambda.java
@@ -39,7 +39,6 @@ import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
  *
  * @see HazardResultSliceLambda
  */
-@SuppressWarnings("unused")
 public class HazardResultsSlicerLambda implements RequestStreamHandler {
 
   private static final AmazonS3 S3 = AmazonS3ClientBuilder.defaultClient();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/etc/GmmParams.java b/src/main/java/gov/usgs/earthquake/nshmp/etc/GmmParams.java
deleted file mode 100644
index 1bf78215682ff0582cb34fdf0a95a9f721b18390..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/etc/GmmParams.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package gov.usgs.earthquake.nshmp.etc;
-
-@SuppressWarnings("javadoc")
-public class GmmParams {
-  public double Mw;
-  public double rJB;
-  public double rRup;
-  public double rX;
-  public double dip;
-  public double width;
-  public double zTop;
-  public double zHyp;
-  public double rake;
-  public double vs30;
-  public boolean vsInf;
-  public double z1p0;
-  public double z2p5;
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMat.java b/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMat.java
deleted file mode 100644
index 48ad5d38fee8ace623c512d869a69997a4a64824..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMat.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package gov.usgs.earthquake.nshmp.etc;
-
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-@SuppressWarnings("javadoc")
-public class HazMat {
-
-  /*
-   * Developer notes:
-   *
-   * Mathworks has gone out of its way to make it more and more difficult to use
-   * Java in Matlab as time goes on, despite it being a first-class citizen.
-   * Specifically, the Matlab classpath includes a dizzying number of 3rd party
-   * libraries, many of which are now well out of date. The problem posed to
-   * nshmp-haz is the inclusion of v.15 of Google Guava (this, one can only
-   * determine by unpacking the included google-collections.jar as they haven't
-   * bothered to update the name of the dependency) whereas the current Guava
-   * release is v.23. The aggressive deprecation and removal of bad, unused, or
-   * superceeded code by Google has resulted in significant class and method
-   * variations within Guava over 8 update cycles. nshmp-haz will not remove
-   * it's dependency on Guava, but putting nshmp-haz early on the Matlab
-   * classpath causes Matlab to crash as it can't find (now missing) methods in
-   * Guava.
-   *
-   * The unsatisfactory but functional workaround is to use a custom class
-   * loader that, once we want to use nshmp-haz classes, scans nshmp-haz.jar
-   * before looking in the matlab classpath. This approach is messy in that the
-   * sole point of entry is this class, which delegates to HazMatHelper (loaded
-   * with the custom class loader) and the methods of which must be accessed via
-   * reflection.
-   *
-   * Note that if nshmp-haz moves to Java 8, which will probably occur sooner
-   * rather than later, the custom class loader will also have to have Java 8 on
-   * it's classpath. Sigh.
-   */
-
-  private static final List<Class<?>> INPUT_CLASSES = Arrays.asList(new Class<?>[] {
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      double.class,
-      boolean.class,
-      double.class,
-      double.class });
-
-  private static final Class<?>[] MEAN_CLASSES;
-  private static final Class<?>[] SPECTRUM_CLASSES;
-
-  static {
-    /* Build custom class arrays needed to call methods via reflection. */
-    List<Class<?>> classes = new ArrayList<>();
-    classes.add(String.class);
-    classes.addAll(INPUT_CLASSES);
-    SPECTRUM_CLASSES = classes.toArray(new Class[INPUT_CLASSES.size() + 1]);
-    classes.add(0, String.class);
-    MEAN_CLASSES = classes.toArray(new Class[INPUT_CLASSES.size() + 2]);
-  }
-
-  private Object hazMatImpl;
-
-  HazMat(Object hazMatImpl) {
-    this.hazMatImpl = hazMatImpl;
-  }
-
-  public double[] gmmMean(String gmm, String imt, GmmParams in) {
-    try {
-      Method method = hazMatImpl.getClass().getMethod("gmmMean", MEAN_CLASSES);
-      return (double[]) method.invoke(hazMatImpl,
-          gmm,
-          imt,
-          in.Mw,
-          in.rJB,
-          in.rRup,
-          in.rX,
-          in.dip,
-          in.width,
-          in.zTop,
-          in.zHyp,
-          in.rake,
-          in.vs30,
-          in.vsInf,
-          in.z1p0,
-          in.z2p5);
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  public HazMatSpectrum gmmSpectrum(String gmm, GmmParams in) {
-    try {
-      Method method = hazMatImpl.getClass().getMethod("gmmSpectrum", SPECTRUM_CLASSES);
-      double[][] result = (double[][]) method.invoke(hazMatImpl,
-          gmm,
-          in.Mw,
-          in.rJB,
-          in.rRup,
-          in.rX,
-          in.dip,
-          in.width,
-          in.zTop,
-          in.zHyp,
-          in.rake,
-          in.vs30,
-          in.vsInf,
-          in.z1p0,
-          in.z2p5);
-      HazMatSpectrum spectrum = new HazMatSpectrum();
-      spectrum.periods = result[0];
-      spectrum.means = result[1];
-      spectrum.sigmas = result[2];
-      return spectrum;
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  public static HazMat init(String nshmpHazPath) {
-    try {
-      URL nshmpHazUrl = Paths.get(nshmpHazPath).toUri().toURL();
-      List<URL> classpath = new ArrayList<>();
-      classpath.add(nshmpHazUrl);
-      ClassLoader loader = new ParentLastURLClassLoader(classpath);
-      Class<?> clazz = loader.loadClass(HazMatImpl.class.getName());
-      return new HazMat(clazz.newInstance());
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMatImpl.java b/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMatImpl.java
deleted file mode 100644
index 4e94f2005448339bd55d3f957f4b78ad38720932..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMatImpl.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package gov.usgs.earthquake.nshmp.etc;
-
-import java.util.Set;
-
-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.gmm.ScalarGroundMotion;
-
-@SuppressWarnings("javadoc")
-public class HazMatImpl {
-
-  public double[] gmmMean(
-      String gmmStr,
-      String imtStr,
-      double Mw,
-      double rJB,
-      double rRup,
-      double rX,
-      double dip,
-      double width,
-      double zTop,
-      double zHyp,
-      double rake,
-      double vs30,
-      boolean vsInf,
-      double z1p0,
-      double z2p5) {
-
-    GmmInput input = toInput(
-        Mw,
-        rJB, rRup, rX,
-        dip, width, zTop, zHyp, rake,
-        vs30, vsInf, z1p0, z2p5);
-    Gmm gmm = Gmm.valueOf(gmmStr);
-    Imt imt = Imt.valueOf(imtStr);
-    ScalarGroundMotion sgm = gmm.instance(imt).calc(input);
-    return new double[] { sgm.mean(), sgm.sigma() };
-  }
-
-  public double[][] gmmSpectrum(
-      String gmmStr,
-      double Mw,
-      double rJB,
-      double rRup,
-      double rX,
-      double dip,
-      double width,
-      double zTop,
-      double zHyp,
-      double rake,
-      double vs30,
-      boolean vsInf,
-      double z1p0,
-      double z2p5) {
-
-    GmmInput input =
-        toInput(
-            Mw,
-            rJB, rRup, rX,
-            dip, width, zTop, zHyp, rake,
-            vs30, vsInf, z1p0, z2p5);
-    Gmm gmm = Gmm.valueOf(gmmStr);
-    return gmmSpectrum(gmm, input);
-  }
-
-  private double[][] gmmSpectrum(Gmm gmm, GmmInput input) {
-    Set<Imt> imts = gmm.responseSpectrumIMTs();
-    double[][] spectrum = new double[3][imts.size()];
-    int i = 0;
-    for (Imt imt : imts) {
-      ScalarGroundMotion sgm = gmm.instance(imt).calc(input);
-      spectrum[0][i] = imt.period();
-      spectrum[1][i] = sgm.mean();
-      spectrum[2][i] = sgm.sigma();
-      i++;
-    }
-    return spectrum;
-  }
-
-  private static GmmInput toInput(
-      double Mw,
-      double rJB,
-      double rRup,
-      double rX,
-      double dip,
-      double width,
-      double zTop,
-      double zHyp,
-      double rake,
-      double vs30,
-      boolean vsInf,
-      double z1p0,
-      double z2p5) {
-
-    return GmmInput.builder()
-        .mag(Mw)
-        .rJB(rJB)
-        .rRup(rRup)
-        .rX(rX)
-        .dip(dip)
-        .width(width)
-        .zTop(zTop)
-        .zHyp(zHyp)
-        .rake(rake)
-        .vs30(vs30)
-        .vsInf(vsInf)
-        .z1p0(z1p0)
-        .z2p5(z2p5)
-        .build();
-  }
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMatSpectrum.java b/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMatSpectrum.java
deleted file mode 100644
index e3703a11fc2fe6a790669c4711b182cfb3718a91..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/etc/HazMatSpectrum.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package gov.usgs.earthquake.nshmp.etc;
-
-import static gov.usgs.earthquake.nshmp.Text.NEWLINE;
-
-import java.util.Arrays;
-
-@SuppressWarnings("javadoc")
-public class HazMatSpectrum {
-
-  public double[] periods;
-  public double[] means;
-  public double[] sigmas;
-
-  @Override
-  public String toString() {
-    return new StringBuilder("HazMatSpectrum: ")
-        .append(NEWLINE)
-        .append("  Periods: ").append(Arrays.toString(periods)).append(NEWLINE)
-        .append("    Means: ").append(Arrays.toString(means)).append(NEWLINE)
-        .append("   Sigmas: ").append(Arrays.toString(sigmas)).append(NEWLINE)
-        .toString();
-  }
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/etc/ParentLastURLClassLoader.java b/src/main/java/gov/usgs/earthquake/nshmp/etc/ParentLastURLClassLoader.java
deleted file mode 100644
index 91cc441601b33dbafb7971eb809b5aff8b72bb9c..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/etc/ParentLastURLClassLoader.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package gov.usgs.earthquake.nshmp.etc;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.List;
-
-class ParentLastURLClassLoader extends ClassLoader {
-
-  private ChildURLClassLoader childClassLoader;
-
-  ParentLastURLClassLoader(List<URL> classpath) {
-    super(Thread.currentThread().getContextClassLoader());
-    URL[] urls = classpath.toArray(new URL[classpath.size()]);
-    childClassLoader = new ChildURLClassLoader(urls, new FindClassClassLoader(this.getParent()));
-  }
-
-  /* Class permits calls to protected Classloader.findClass(). */
-  private static class FindClassClassLoader extends ClassLoader {
-
-    public FindClassClassLoader(ClassLoader parent) {
-      super(parent);
-    }
-
-    @Override
-    public Class<?> findClass(String name) throws ClassNotFoundException {
-      return super.findClass(name);
-    }
-  }
-
-  /*
-   * This class delegates (child then parent) the protected findClass() method
-   * of a URLClassLoader.
-   */
-  private static class ChildURLClassLoader extends URLClassLoader {
-
-    private FindClassClassLoader realParent;
-
-    public ChildURLClassLoader(URL[] urls, FindClassClassLoader realParent) {
-      super(urls, null);
-      this.realParent = realParent;
-    }
-
-    @Override
-    public Class<?> findClass(String name) throws ClassNotFoundException {
-      try {
-        // try to use the URLClassLoader findClass
-        return super.findClass(name);
-      } catch (ClassNotFoundException e) {
-        // otherwise ask the real parent classloader to load the class
-        return realParent.loadClass(name);
-      }
-    }
-  }
-
-  @Override
-  protected synchronized Class<?> loadClass(String name, boolean resolve)
-      throws ClassNotFoundException {
-    try {
-      // try to find a class inside the child classloader
-      return childClassLoader.findClass(name);
-    } catch (ClassNotFoundException e) {
-      // then try the parent
-      return super.loadClass(name, resolve);
-    }
-  }
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/package-info.java b/src/main/java/gov/usgs/earthquake/nshmp/package-info.java
deleted file mode 100644
index 8b3a8acf7856ebbbd793cac9654ce30a8cd0d441..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Entry points for conducting probabilisitic seismic hazard analyses (PSHA).
- */
-package gov.usgs.earthquake.nshmp;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
index 1cd89db28610eb0b868e9673ebd956cc73128b15..712fb6fc69510fc100414f5069edbcce2892dfab 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/CybershakeSite.java
@@ -8,7 +8,6 @@ import gov.usgs.earthquake.nshmp.geo.Location;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum CybershakeSite implements NamedLocation {
 
   /*
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NehrpSiteClass.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NehrpSiteClass.java
deleted file mode 100644
index e7c0697cc901804d02b5a7c9d9435fc1941dfa50..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NehrpSiteClass.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package gov.usgs.earthquake.nshmp.site;
-
-/**
- * Placeholder enum for likely move to Nehrp site class identifier instead of
- * Vs30.
- *
- * <p>These site class identifiers map to NEHRP site clases, but the intent is
- * that they can be used more generally for models in other parts of the world
- * where the GMMs are not necessarily parameterized in terms of vs30 to define
- * site response. For instance, NZ/JP site classes might use A, B, C, and D as a
- * proxy for the local I, II, III, and IV identifiers. In the U.S., models will
- * need to specify the Vs30 value that each site class corresponds to. Although
- * the values were consistent over prior models, now that multiple site classes
- * are supported (in 2018) across the entire U.S., there have been changes
- * proposed for balloting by the BSSC to make the Vs30 definitions of site
- * classes consistent in how they are calculated.
- *
- * @author U.S. Geological Survey
- */
-enum SiteClass {
-
-  /*
-   * Notes on calculation of Vs30 for site class:
-   *
-   * Question: Why is it that the soil shear wave velocity shown in the Unified
-   * Hazard Tool is not equal to the average of the values shown in ASCE 7-10
-   * table 20.3-1?
-   *
-   * For instance: 259 m/s (Site Class D), from the Unified Hazard Tool, is not
-   * equal to (600 ft/s + 1200 ft/s)/2 * .3048 = 274 m/s
-   *
-   * Answer (Sanaz): we take the geometric mean: sqrt(1200*600)*0.3048 =
-   * 258.6314 , which rounds to 259m/s.
-   *
-   *
-   */
-
-  /* OLD Vs30, NEW Vs30 */
-
-  /* 2000 2000 */
-  A,
-
-  /* 1500 1500 (new) */
-  AB,
-
-  /* 1150 1080 */
-  B,
-
-  /* 760 760 */
-  BC,
-
-  /* 537 530 */
-  C,
-
-  /* 360 365 */
-  CD,
-
-  /* 259 260 */
-  D,
-
-  /* 180 185 */
-  DE,
-
-  /* 150 150 (new) */
-  E,
-
-  ;
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
index 16e84e249d88a21f0fb798b5d0bc1f4c71cd2cdb..9699ecaf03a92b0273da3528b82b5e70fc955e96 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpPolygon.java
@@ -7,7 +7,6 @@ import gov.usgs.earthquake.nshmp.geo.LocationList;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NshmpPolygon {
 
   CEUS_CLIP(Data.CEUS_CLIP, "Central & Eastern US Map Extents"),
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
index 370ad713fdd5330c95cdcff74ef8219aadf173a1..2455bd64b52c8ea1e98ba93b84f4cb0b1d1b3f0d 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NshmpSite.java
@@ -18,7 +18,6 @@ import gov.usgs.earthquake.nshmp.internal.UsRegion;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NshmpSite implements NamedLocation {
 
   // TODO move this and other nshmp specific classes to nshmp-haz
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java b/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
index 0aba72dce5ca47cc2b92fc9d00c5d4854f82ceea..c28d33560db41ca95acd50fe5e679328a24d75ef 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/site/NuregSite.java
@@ -11,7 +11,6 @@ import gov.usgs.earthquake.nshmp.internal.UsRegion;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public enum NuregSite implements NamedLocation {
 
   CENTRAL_IL(-90.000, 40.000),
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
index 73942632e385a63c037ed4738c8d3f850bd5587d..d678f3a50bf0d8f62addb22fb17ad04777a6aa30 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/HazardController.java
@@ -1,11 +1,13 @@
 package gov.usgs.earthquake.nshmp.www;
 
+import java.util.Optional;
+
 import javax.annotation.Nullable;
 import javax.inject.Inject;
 
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet;
 import gov.usgs.earthquake.nshmp.www.services.HazardService;
-import gov.usgs.earthquake.nshmp.www.services.HazardService.Query;
+import gov.usgs.earthquake.nshmp.www.services.HazardService.QueryParameters;
 
 import io.micronaut.http.HttpRequest;
 import io.micronaut.http.HttpResponse;
@@ -69,21 +71,24 @@ public class HazardController {
   @ApiResponse(
       description = "Hazard curves",
       responseCode = "200")
-  @Get(uri = "{?longitude,latitude,vs30}")
+  @Get // (uri = "{?longitude,latitude,vs30}")
   public HttpResponse<String> doGetHazard(
       HttpRequest<?> request,
       @Schema(
           required = true,
           minimum = "-360",
-          maximum = "360") @QueryValue @Nullable Double longitude,
+          maximum = "360") @QueryValue @Nullable Optional<Double> longitude,
       @Schema(
           required = true,
           minimum = "-90",
-          maximum = "90") @QueryValue @Nullable Double latitude,
-      @Schema(required = true) @QueryValue @Nullable Integer vs30) {
-    var urlHelper = servlet.urlHelper(request);
-    var query = new Query(longitude, latitude, vs30);
-    return HazardService.handleDoGetHazard(query, urlHelper);
+          maximum = "90") @QueryValue @Nullable Optional<Double> latitude,
+      @Schema(
+          required = true) @QueryValue @Nullable Optional<Integer> vs30) {
+
+    var query = new QueryParameters(longitude, latitude, vs30);
+    return HazardService.handleDoGetHazard(
+        query,
+        servlet.urlHelper(request));
   }
 
   /**
@@ -107,15 +112,17 @@ public class HazardController {
       @Schema(
           required = true,
           minimum = "-360",
-          maximum = "360") @PathVariable @Nullable Double longitude,
+          maximum = "360") @PathVariable @Nullable Optional<Double> longitude,
       @Schema(
           required = true,
           minimum = "-90",
-          maximum = "90") @PathVariable @Nullable Double latitude,
-      @Schema(required = true) @PathVariable @Nullable Integer vs30) {
-    var urlHelper = servlet.urlHelper(request);
-    var query = new Query(longitude, latitude, vs30);
-    return HazardService.handleDoGetHazard(query, urlHelper);
-  }
+          maximum = "90") @PathVariable @Nullable Optional<Double> latitude,
+      @Schema(
+          required = true) @PathVariable @Nullable Optional<Integer> vs30) {
 
+    var query = new QueryParameters(longitude, latitude, vs30);
+    return HazardService.handleDoGetHazard(
+        query,
+        servlet.urlHelper(request));
+  }
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
deleted file mode 100644
index 2dbafe63bfc3d5feafd33547007231d80f0ff011..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constrained.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-/**
- * Interface implemented by enum parameters that impose restrictions on other
- * parameter choices.
- */
-@SuppressWarnings("javadoc")
-public interface Constrained {
-  public Constraints constraints();
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java
deleted file mode 100644
index 449d3c7b84eaeb1dfcfb235fc02b7b3841f53457..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Constraints.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-/**
- * Marker interface for supported parameter lists and ; individual enums provide
- * concrete implementations.
- */
-public interface Constraints {}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/DoubleParameter.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/DoubleParameter.java
index e182d6db80c2474bac602244b7a92a6b0fb18304..f38749853663d6a04568990e0c628a2f63e1058e 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/DoubleParameter.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/DoubleParameter.java
@@ -1,29 +1,16 @@
 package gov.usgs.earthquake.nshmp.www.meta;
 
-import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
-
-@SuppressWarnings({ "javadoc", "unused" })
 public final class DoubleParameter {
 
-  private final String label;
-  private final ParamType type;
-  private final Values values;
-
-  public DoubleParameter(String label, ParamType type, double min, double max) {
-    this.label = label;
-    this.type = type;
-    this.values = new Values(min, max);
-  }
-
-  private final static class Values {
-
-    final double minimum;
-    final double maximum;
+  private final String name;
+  private final String units;
+  private final double min;
+  private final double max;
 
-    Values(double min, double max) {
-      this.minimum = min;
-      this.maximum = max;
-    }
+  public DoubleParameter(String name, String units, double min, double max) {
+    this.name = name;
+    this.units = units;
+    this.min = min;
+    this.max = max;
   }
-
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
index d5b961201f5bc96f1c8f3814db20581756a669c9..271a99e4341a04164a5f85c259336d8f47c128e1 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/MetaUtil.java
@@ -17,12 +17,10 @@ import com.google.gson.JsonSerializer;
 
 import gov.usgs.earthquake.nshmp.Maths;
 import gov.usgs.earthquake.nshmp.calc.Site;
-import gov.usgs.earthquake.nshmp.calc.Vs30;
 import gov.usgs.earthquake.nshmp.gmm.GmmInput;
 import gov.usgs.earthquake.nshmp.gmm.GmmInput.Field;
 import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 
-@SuppressWarnings("javadoc")
 public final class MetaUtil {
 
   public static <E extends Enum<E>> List<String> enumsToNameList(
@@ -41,32 +39,16 @@ public final class MetaUtil {
     @Override
     public JsonElement serialize(E src, Type type, JsonSerializationContext context) {
 
-      String value = (src instanceof Vs30) ? src.name().substring(3) : src.name();
-      int displayOrder = src.ordinal();
-
       JsonObject jObj = new JsonObject();
       jObj.addProperty("id", src.ordinal());
-      jObj.addProperty("value", value);
+      jObj.addProperty("value", src.name());
       jObj.addProperty("display", src.toString());
-      jObj.addProperty("displayorder", displayOrder);
-
-      if (src instanceof Region) {
-        Region region = (Region) src;
-        jObj.addProperty("minlatitude", region.minlatitude);
-        jObj.addProperty("maxlatitude", region.maxlatitude);
-        jObj.addProperty("minlongitude", region.minlongitude);
-        jObj.addProperty("maxlongitude", region.maxlongitude);
-
-        jObj.addProperty("uiminlatitude", region.uiminlatitude);
-        jObj.addProperty("uimaxlatitude", region.uimaxlatitude);
-        jObj.addProperty("uiminlongitude", region.uiminlongitude);
-        jObj.addProperty("uimaxlongitude", region.uimaxlongitude);
-      }
+      jObj.addProperty("displayorder", src.ordinal());
 
-      if (src instanceof Constrained) {
-        Constrained cSrc = (Constrained) src;
-        jObj.add("supports", context.serialize(cSrc.constraints()));
-      }
+      // if (src instanceof Constrained) {
+      // Constrained cSrc = (Constrained) src;
+      // jObj.add("supports", context.serialize(cSrc.constraints()));
+      // }
 
       return jObj;
     }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
index 992aa92c7267bc7e009e0079e4b07106098f83c4..a358619db2cf21c444bd231f70358a4756e4167f 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Metadata.java
@@ -1,23 +1,19 @@
 package gov.usgs.earthquake.nshmp.www.meta;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.base.Throwables;
-import com.google.gson.annotations.SerializedName;
 
 import gov.usgs.earthquake.nshmp.geo.Coordinates;
-import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.www.services.ServletUtil;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 
 /**
  * Service metadata, parameterization, and constraint strings, in JSON format.
  */
-@SuppressWarnings("javadoc")
 public final class Metadata {
 
   static final String NSHMP_HAZ_URL = "https://code.usgs.gov/ghsc/nshmp/nshmp-haz";
 
-  @SuppressWarnings("unused")
   private static class Default {
 
     final String status;
@@ -33,48 +29,43 @@ public final class Metadata {
       this.status = Status.USAGE.toString();
       this.description = description;
       this.syntax = syntax;
-      this.server = serverData(1, new Timer());
+      this.server = serverData(1, Stopwatch.createStarted());
       this.parameters = parameters;
     }
   }
 
-  public static Object serverData(int threads, Timer timer) {
+  public static Object serverData(int threads, Stopwatch timer) {
     return new Server(threads, timer);
   }
 
-  @SuppressWarnings("unused")
   private static class Server {
 
     final int threads;
-    final String servlet;
-    final String calc;
+    final String timer;
+    final String version;
 
-    @SerializedName("nshmp-haz")
-    final Component nshmpHaz = NSHMP_HAZ_COMPONENT;
-
-    Server(int threads, Timer timer) {
+    Server(int threads, Stopwatch timer) {
       this.threads = threads;
-      this.servlet = timer.servletTime();
-      this.calc = timer.calcTime();
+      this.timer = timer.toString();
+      this.version = "TODO where to get version?";
     }
 
-    static Component NSHMP_HAZ_COMPONENT = new Component(
-        NSHMP_HAZ_URL,
-        Versions.NSHMP_HAZ_VERSION);
-
-    static final class Component {
-
-      final String url;
-      final String version;
-
-      Component(String url, String version) {
-        this.url = url;
-        this.version = version;
-      }
-    }
+    // static Component NSHMP_HAZ_COMPONENT = new Component(
+    // NSHMP_HAZ_URL,
+    // Versions.NSHMP_HAZ_VERSION);
+    //
+    // static final class Component {
+    //
+    // final String url;
+    // final String version;
+    //
+    // Component(String url, String version) {
+    // this.url = url;
+    // this.version = version;
+    // }
+    // }
   }
 
-  @SuppressWarnings("unused")
   public static class DefaultParameters {
 
     // final EnumParameter<Edition> edition;
@@ -95,14 +86,14 @@ public final class Metadata {
       // EnumSet.allOf(Region.class));
 
       longitude = new DoubleParameter(
-          "Longitude (in decimal degrees)",
-          ParamType.NUMBER,
+          "Longitude",
+          "°",
           Coordinates.LON_RANGE.lowerEndpoint(),
           Coordinates.LON_RANGE.upperEndpoint());
 
       latitude = new DoubleParameter(
-          "Latitude (in decimal degrees)",
-          ParamType.NUMBER,
+          "Latitude",
+          "°",
           Coordinates.LAT_RANGE.lowerEndpoint(),
           Coordinates.LAT_RANGE.upperEndpoint());
     }
@@ -133,7 +124,6 @@ public final class Metadata {
     return ServletUtil.GSON.toJson(error);
   }
 
-  @SuppressWarnings("unused")
   private static class Error {
 
     final String status = Status.ERROR.toString();
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Region.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Region.java
deleted file mode 100644
index 8dd32654c3c15aa1c5b8dbfb4747d667425eab16..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/Region.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-public enum Region {
-
-  AK(
-      "Alaska",
-      new double[] { 48.0, 72.0 },
-      new double[] { -200.0, -125.0 },
-      new double[] { 48.0, 72.0 },
-      new double[] { -200.0, -125.0 }),
-
-  CONUS(
-      "Conterminous US",
-      new double[] { 24.6, 50.0 },
-      new double[] { -125.0, -65.0 },
-      new double[] { 24.6, 50.0 },
-      new double[] { -125.0, -65.0 }),
-
-  HI(
-      "Hawaii",
-      new double[] { 18.0, 23.0 },
-      new double[] { -161.0, -154.0 },
-      new double[] { 18.0, 23.0 },
-      new double[] { -161.0, -154.0 });
-
-  public final String label;
-
-  public final double minlatitude;
-  public final double maxlatitude;
-  public final double minlongitude;
-  public final double maxlongitude;
-
-  public final double uiminlatitude;
-  public final double uimaxlatitude;
-  public final double uiminlongitude;
-  public final double uimaxlongitude;
-
-  private Region(
-      String label,
-      double[] latRange,
-      double[] lonRange,
-      double[] uiLatRange,
-      double[] uiLonRange) {
-
-    this.label = label;
-
-    this.minlatitude = latRange[0];
-    this.maxlatitude = latRange[1];
-    this.minlongitude = lonRange[0];
-    this.maxlongitude = lonRange[1];
-
-    this.uiminlatitude = uiLatRange[0];
-    this.uimaxlatitude = uiLatRange[1];
-    this.uiminlongitude = uiLonRange[0];
-    this.uimaxlongitude = uiLonRange[1];
-  }
-
-  @Override
-  public String toString() {
-    return label;
-  }
-
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/RegionConstraints.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/RegionConstraints.java
deleted file mode 100644
index 8a7d6434ac8eeb9e7bb9a95ec0d068bdac3cfb05..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/RegionConstraints.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package gov.usgs.earthquake.nshmp.www.meta;
-
-import java.util.List;
-import java.util.Set;
-
-import gov.usgs.earthquake.nshmp.calc.Vs30;
-import gov.usgs.earthquake.nshmp.gmm.Imt;
-
-@SuppressWarnings("unused")
-class RegionConstraints implements Constraints {
-
-  private final List<String> imt;
-  private final List<String> vs30;
-
-  RegionConstraints(Set<Imt> imts, Set<Vs30> vs30s) {
-    // converting to Strings here, otherwise EnumSerializer will be used
-    // and we want a compact list of (possible modified) enum.name()s
-    this.imt = MetaUtil.enumsToNameList(imts);
-    this.vs30 = MetaUtil.enumsToStringList(vs30s, vs30 -> vs30.name().substring(3));
-  }
-}
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/package-info.java b/src/main/java/gov/usgs/earthquake/nshmp/www/meta/package-info.java
deleted file mode 100644
index ea198d9021ea597574e4079cd33275773279ff4c..0000000000000000000000000000000000000000
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/meta/package-info.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Web-service metadata support classes.
- *
- * <p>Classes in this package largely provide support for web services used on
- * the public facing USGS website. Services that are not public facing may use a
- * simpler metadata structure defined within the service class itself (e.g.
- * {@link gov.usgs.earthquake.nshmp.www.SpectraService}.
- */
-package gov.usgs.earthquake.nshmp.www.meta;
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
index 041c215af3e46b84bfa13450fa9e394f87780aac..2f744fe8631b0191a04d5db8ca49e9232e589208 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/DeaggEpsilonService.java
@@ -11,13 +11,13 @@ import java.util.Properties;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableList;
 import com.google.common.io.Resources;
 
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.Deaggregation;
 import gov.usgs.earthquake.nshmp.calc.Site;
-import gov.usgs.earthquake.nshmp.calc.Vs30;
 import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
@@ -28,7 +28,6 @@ import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.DeaggEpsilonController;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpRequest;
@@ -81,8 +80,8 @@ public final class DeaggEpsilonService {
       }
 
       query.checkValues();
-      var data = new RequestData(query, Vs30.fromValue(query.vs30));
-      var response = process(data, timer, urlHelper);
+      var data = new RequestData(query, query.vs30);
+      var response = process(data, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -109,11 +108,11 @@ public final class DeaggEpsilonService {
 
   private static Response<RequestData, ResponseData> process(
       RequestData data,
-      Timer timer,
       UrlHelper urlHelper)
       throws InterruptedException, ExecutionException {
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
+    var timer = Stopwatch.createStarted();
     var hazard = ServicesUtil.calcHazard(configFunction, siteFunction);
     var deagg = Deaggregation.atImls(hazard, data.imtImls, ServletUtil.CALC_EXECUTOR);
     return new ResultBuilder()
@@ -182,37 +181,36 @@ public final class DeaggEpsilonService {
       return Site.builder()
           .location(Location.create(data.longitude, data.latitude))
           .basinDataProvider(data.basin ? basinUrl : null)
-          .vs30(data.vs30.value())
+          .vs30(data.vs30)
           .build();
     }
   }
 
-  static final class RequestData extends HazardService.RequestData {
+  static final class RequestData extends HazardService.RequestDataOld {
     final EnumMap<Imt, Double> imtImls;
     final boolean basin;
 
-    RequestData(Query query, Vs30 vs30) {
+    RequestData(Query query, double vs30) {
       super(query, vs30);
       imtImls = query.imtImls;
       basin = query.basin;
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class ResponseMetadata {
-    final List<SourceModel> models;
+    final SourceModel models;
     final double longitude;
     final double latitude;
     final String imt;
     final double iml;
-    final Vs30 vs30;
+    final double vs30;
     final String rlabel = "Closest Distance, rRup (km)";
     final String mlabel = "Magnitude (Mw)";
     final String εlabel = "% Contribution to Hazard";
     final Object εbins;
 
     ResponseMetadata(Deaggregation deagg, RequestData request, Imt imt) {
-      this.models = request.models;
+      this.models = new SourceModel(ServletUtil.model());
       this.longitude = request.longitude;
       this.latitude = request.latitude;
       this.imt = imt.toString();
@@ -222,7 +220,6 @@ public final class DeaggEpsilonService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class ResponseData {
     final Object server;
     final List<DeaggResponse> deaggs;
@@ -233,7 +230,6 @@ public final class DeaggEpsilonService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class DeaggResponse {
     final ResponseMetadata metadata;
     final Object data;
@@ -246,7 +242,7 @@ public final class DeaggEpsilonService {
 
   static final class ResultBuilder {
     UrlHelper urlHelper;
-    Timer timer;
+    Stopwatch timer;
     RequestData request;
     Deaggregation deagg;
 
@@ -260,7 +256,7 @@ public final class DeaggEpsilonService {
       return this;
     }
 
-    ResultBuilder timer(Timer timer) {
+    ResultBuilder timer(Stopwatch timer) {
       this.timer = timer;
       return this;
     }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
index 7e9f7d33348230bfd40ac6baa28787d4326ece7b..0a7d816d4fcb7a83c9f3f511a0c4199447fb8924 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/HazardService.java
@@ -1,5 +1,6 @@
 package gov.usgs.earthquake.nshmp.www.services;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static gov.usgs.earthquake.nshmp.calc.HazardExport.curvesBySource;
 
@@ -7,15 +8,18 @@ import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 
+import com.google.common.base.Stopwatch;
+
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.Hazard;
 import gov.usgs.earthquake.nshmp.calc.Site;
-import gov.usgs.earthquake.nshmp.calc.Vs30;
 import gov.usgs.earthquake.nshmp.data.MutableXySequence;
 import gov.usgs.earthquake.nshmp.data.XySequence;
+import gov.usgs.earthquake.nshmp.geo.Coordinates;
 import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
@@ -25,11 +29,10 @@ import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.model.SourceType;
 import gov.usgs.earthquake.nshmp.www.HazardController;
+import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
-import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpResponse;
@@ -59,7 +62,7 @@ public final class HazardService {
    */
   public static HttpResponse<String> handleDoGetUsage(UrlHelper urlHelper) {
     try {
-      var usage = new SourceServices.ResponseData();
+      var usage = new RequestMetadata(ServletUtil.model());// SourceServices.ResponseData();
       var response = new Response<>(Status.USAGE, NAME, urlHelper.url, usage, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
@@ -75,17 +78,17 @@ public final class HazardService {
    * @param query The query
    * @param urlHelper The URL helper
    */
-  public static HttpResponse<String> handleDoGetHazard(Query query, UrlHelper urlHelper) {
-    try {
-      var timer = ServletUtil.timer();
+  public static HttpResponse<String> handleDoGetHazard(
+      QueryParameters query,
+      UrlHelper urlHelper) {
 
-      if (query.isNull()) {
+    try {
+      if (query.isEmpty()) {
         return handleDoGetUsage(urlHelper);
       }
-
-      query.checkValues();
-      var data = new RequestData(query, Vs30.fromValue(query.vs30));
-      var response = process(data, timer, urlHelper);
+      query.checkParameters();
+      var data = new RequestData(query);
+      var response = process(data, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -95,16 +98,18 @@ public final class HazardService {
 
   static Response<RequestData, ResponseData> process(
       RequestData data,
-      Timer timer,
-      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+      UrlHelper urlHelper)
+      throws InterruptedException, ExecutionException {
+
     var configFunction = new ConfigFunction();
     var siteFunction = new SiteFunction(data);
+    var stopwatch = Stopwatch.createStarted();
     var hazard = ServicesUtil.calcHazard(configFunction, siteFunction);
 
     return new ResultBuilder()
         .hazard(hazard)
         .requestData(data)
-        .timer(timer)
+        .timer(stopwatch)
         .urlHelper(urlHelper)
         .build();
   }
@@ -129,60 +134,124 @@ public final class HazardService {
       return Site.builder()
           .basinDataProvider(config.siteData.basinDataProvider)
           .location(Location.create(data.longitude, data.latitude))
-          .vs30(data.vs30.value())
+          .vs30(data.vs30)
           .build();
     }
   }
 
-  public static class Query extends ServiceQueryData {
-    Integer vs30;
+  public static class QueryParameters {
 
-    public Query(Double longitude, Double latitude, Integer vs30) {
-      super(longitude, latitude);
+    Optional<Double> longitude;
+    Optional<Double> latitude;
+    Optional<Integer> vs30;
+
+    public QueryParameters(
+        Optional<Double> longitude,
+        Optional<Double> latitude,
+        Optional<Integer> vs30) {
+
+      this.longitude = longitude;
+      this.latitude = latitude;
       this.vs30 = vs30;
     }
 
-    @Override
-    public boolean isNull() {
-      return super.isNull() && vs30 == null;
+    public boolean isEmpty() {
+      return longitude.isEmpty() && latitude.isEmpty() && vs30.isEmpty();
     }
 
-    @Override
-    public void checkValues() {
-      super.checkValues();
-      WsUtils.checkValue(Key.VS30, vs30);
+    public void checkParameters() {
+      checkParameter(longitude, "longitude");
+      checkParameter(latitude, "latitude");
+      checkParameter(vs30, "vs30");
     }
   }
 
-  static class RequestData extends ServiceRequestData {
-    final Vs30 vs30;
+  private static void checkParameter(Object param, String id) {
+    checkNotNull(param, "Missing parameter: %s", id);
+    // TODO check range here
+  }
 
-    RequestData(Query query, Vs30 vs30) {
-      super(query);
-      this.vs30 = vs30;
+  /* Service request and model metadata */
+  static class RequestMetadata {
+
+    final SourceModel model;
+    final DoubleParameter longitude;
+    final DoubleParameter latitude;
+    final DoubleParameter vs30;
+
+    RequestMetadata(HazardModel model) {
+      this.model = new SourceModel(model);
+      // TODO need min max from model
+      longitude = new DoubleParameter(
+          "Longitude",
+          "°",
+          Coordinates.LON_RANGE.lowerEndpoint(),
+          Coordinates.LON_RANGE.upperEndpoint());
+
+      latitude = new DoubleParameter(
+          "Latitude",
+          "°",
+          Coordinates.LAT_RANGE.lowerEndpoint(),
+          Coordinates.LAT_RANGE.upperEndpoint());
+
+      vs30 = new DoubleParameter(
+          "Latitude",
+          "m/s",
+          150,
+          1500);
     }
   }
 
-  @SuppressWarnings("unused")
-  private static final class ResponseMetadata {
-    final List<SourceModel> models;
-    final double latitude;
+  static class RequestData {
+
     final double longitude;
-    final Imt imt;
-    final Vs30 vs30;
+    final double latitude;
+    final double vs30;
+
+    RequestData(QueryParameters query) {
+      this.longitude = query.longitude.orElseThrow();
+      this.latitude = query.latitude.orElseThrow();
+      this.vs30 = query.vs30.orElseThrow();
+    }
+  }
+
+  private static final class ResponseMetadata {
+    // final SourceModel model;
+    // final double latitude;
+    // final double longitude;
+    // final double vs30;
+    final String imt;
     final String xlabel = "Ground Motion (g)";
     final String ylabel = "Annual Frequency of Exceedence";
 
-    ResponseMetadata(RequestData request, Imt imt) {
-      models = SourceModel.getList();
-      latitude = request.latitude;
-      longitude = request.longitude;
-      this.imt = imt;
-      vs30 = request.vs30;
+    ResponseMetadata(Imt imt) {
+      // model = new SourceModel(ServletUtil.model());
+      // latitude = data.latitude;
+      // longitude = data.longitude;
+      // vs30 = data.vs30;
+      this.imt = imtShortLabel(imt);
+    }
+  }
+
+  private static String imtShortLabel(Imt imt) {
+    if (imt.equals(Imt.PGA) || imt.equals(Imt.PGV)) {
+      return imt.name();
+    } else if (imt.isSA()) {
+      return imt.period() + " s";
+    }
+    return imt.toString();
+  }
+
+  @Deprecated
+  static class RequestDataOld extends ServiceRequestData {
+    final double vs30;
+
+    RequestDataOld(Query query, double vs30) {
+      super(query);
+      this.vs30 = vs30;
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class ResponseData {
     final Object server;
     final List<HazardResponse> hazards;
@@ -193,7 +262,6 @@ public final class HazardService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class HazardResponse {
     final ResponseMetadata metadata;
     final List<Curve> data;
@@ -204,7 +272,6 @@ public final class HazardService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class Curve {
     final String component;
     final XySequence values;
@@ -218,14 +285,16 @@ public final class HazardService {
   private static final String TOTAL_KEY = "Total";
 
   private static final class ResultBuilder {
+
     UrlHelper urlHelper;
-    Timer timer;
+    Stopwatch timer;
     RequestData request;
 
     Map<Imt, Map<SourceType, MutableXySequence>> componentMaps;
     Map<Imt, MutableXySequence> totalMap;
 
     ResultBuilder hazard(Hazard hazardResult) {
+      // TODO necessary??
       checkState(totalMap == null, "Hazard has already been added to this builder");
 
       componentMaps = new EnumMap<>(Imt.class);
@@ -234,10 +303,11 @@ public final class HazardService {
       var typeTotalMaps = curvesBySource(hazardResult);
 
       for (var imt : hazardResult.curves().keySet()) {
-        // total curve
+
+        /* Total curve for IMT. */
         XySequence.addToMap(imt, totalMap, hazardResult.curves().get(imt));
 
-        // component curves
+        /* Source component curves for IMT. */
         var typeTotalMap = typeTotalMaps.get(imt);
         var componentMap = componentMaps.get(imt);
 
@@ -259,7 +329,7 @@ public final class HazardService {
       return this;
     }
 
-    ResultBuilder timer(Timer timer) {
+    ResultBuilder timer(Stopwatch timer) {
       this.timer = timer;
       return this;
     }
@@ -273,7 +343,7 @@ public final class HazardService {
       var hazards = new ArrayList<HazardResponse>();
 
       for (Imt imt : totalMap.keySet()) {
-        var responseData = new ResponseMetadata(request, imt);
+        var responseData = new ResponseMetadata(imt);
         var curves = new ArrayList<Curve>();
 
         // total curve
@@ -294,4 +364,26 @@ public final class HazardService {
       return new Response<>(Status.SUCCESS, NAME, request, response, urlHelper);
     }
   }
+
+  @Deprecated
+  public static class Query extends ServiceQueryData {
+    Integer vs30;
+
+    public Query(Double longitude, Double latitude, Integer vs30) {
+      super(longitude, latitude);
+      this.vs30 = vs30;
+    }
+
+    @Override
+    public boolean isNull() {
+      return super.isNull() && vs30 == null;
+    }
+
+    @Override
+    public void checkValues() {
+      super.checkValues();
+      WsUtils.checkValue(ServicesUtil.Key.VS30, vs30);
+    }
+  }
+
 }
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
index 6058b4220fd70540bb32f69361e1acf0349b0f2a..071f31da57f77db510374c9c6c1104a4fafe9153 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/RateService.java
@@ -6,8 +6,10 @@ import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.ListenableFuture;
 
+import gov.usgs.earthquake.nshmp.Maths;
 import gov.usgs.earthquake.nshmp.calc.CalcConfig;
 import gov.usgs.earthquake.nshmp.calc.EqRate;
 import gov.usgs.earthquake.nshmp.calc.Site;
@@ -15,9 +17,7 @@ import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
 import gov.usgs.earthquake.nshmp.internal.www.Response;
 import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
-import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
-import gov.usgs.earthquake.nshmp.mfd.Mfds;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.RateController;
 import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
@@ -26,7 +26,6 @@ import gov.usgs.earthquake.nshmp.www.meta.Metadata.DefaultParameters;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.Key;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceQueryData;
 import gov.usgs.earthquake.nshmp.www.services.ServicesUtil.ServiceRequestData;
-import gov.usgs.earthquake.nshmp.www.services.ServletUtil.Timer;
 
 import io.micronaut.http.HttpResponse;
 
@@ -88,7 +87,7 @@ public final class RateService {
 
       query.checkValues();
       var requestData = new RequestData(query);
-      var response = processRequest(service, requestData, urlHelper, timer);
+      var response = processRequest(service, requestData, urlHelper);
       var svcResponse = ServletUtil.GSON.toJson(response);
       return HttpResponse.ok(svcResponse);
     } catch (Exception e) {
@@ -105,8 +104,8 @@ public final class RateService {
   static Response<RequestData, ResponseData> processRequest(
       Service service,
       RequestData data,
-      UrlHelper urlHelper,
-      Timer timer) throws InterruptedException, ExecutionException {
+      UrlHelper urlHelper) throws InterruptedException, ExecutionException {
+    var timer = Stopwatch.createStarted();
     var rates = calc(service, data);
     var responseData = new ResponseData(new ResponseMetadata(service, data), rates, timer);
     return new Response<>(Status.SUCCESS, service.name, data, responseData, urlHelper);
@@ -124,10 +123,11 @@ public final class RateService {
      * probability service has been called.
      */
 
-    for (var model : ServletUtil.hazardModels()) {
-      var rate = process(service, model, site, data.distance, data.timespan);
-      futureRates.add(rate);
-    }
+    // for (var model : ServletUtil.hazardModels()) {
+    var model = ServletUtil.model();
+    var rate = process(service, model, site, data.distance, data.timespan);
+    futureRates.add(rate);
+    // }
 
     var rates = futureRates.stream()
         .map((future) -> {
@@ -235,7 +235,6 @@ public final class RateService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class ResponseMetadata {
     final double latitude;
     final double longitude;
@@ -255,13 +254,12 @@ public final class RateService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static final class ResponseData {
     final Object server;
     final ResponseMetadata metadata;
     final List<Sequence> data;
 
-    ResponseData(ResponseMetadata metadata, EqRate rates, Timer timer) {
+    ResponseData(ResponseMetadata metadata, EqRate rates, Stopwatch timer) {
       server = Metadata.serverData(ServletUtil.THREAD_COUNT, timer);
       this.metadata = metadata;
       this.data = buildSequence(rates);
@@ -300,7 +298,6 @@ public final class RateService {
    * TODO would rather use this a general container for mfds and hazard curves.
    * See HazardService.Curve
    */
-  @SuppressWarnings("unused")
   private static class Sequence {
     final String component;
     final List<Double> xvalues;
@@ -313,7 +310,6 @@ public final class RateService {
     }
   }
 
-  @SuppressWarnings("unused")
   private static class Usage {
     final String description;
     final List<String> syntax;
@@ -323,35 +319,33 @@ public final class RateService {
     private Usage(Service service, DefaultParameters parameters) {
       description = service.description;
       this.syntax = service.syntax;
-      server = Metadata.serverData(1, ServletUtil.timer());
+      server = Metadata.serverData(1, Stopwatch.createStarted());
       this.parameters = parameters;
     }
   }
 
-  @SuppressWarnings("unused")
   private static class RateParameters extends DefaultParameters {
     final DoubleParameter distance;
 
     RateParameters() {
       super();
       distance = new DoubleParameter(
-          "Cutoff distance (in km)",
-          ParamType.NUMBER,
+          "Cutoff distance",
+          "km",
           0.01,
           1000.0);
     }
   }
 
-  @SuppressWarnings("unused")
   private static class ProbabilityParameters extends RateParameters {
     final DoubleParameter timespan;
 
     ProbabilityParameters() {
       timespan = new DoubleParameter(
-          "Forecast time span (in years)",
-          ParamType.NUMBER,
-          Mfds.TIMESPAN_RANGE.lowerEndpoint(),
-          Mfds.TIMESPAN_RANGE.upperEndpoint());
+          "Forecast time span",
+          "years",
+          Maths.TIMESPAN_RANGE.lowerEndpoint(),
+          Maths.TIMESPAN_RANGE.upperEndpoint());
     }
   }
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
index 43f07c8d0a28aee06a48c07fc22ef94fdcd9a4e6..7efcfbc9826c2b052d9fd038e618804cc3ab6445 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServicesUtil.java
@@ -1,10 +1,10 @@
 package gov.usgs.earthquake.nshmp.www.services;
 
-import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import com.google.gson.GsonBuilder;
 
@@ -17,7 +17,6 @@ import gov.usgs.earthquake.nshmp.internal.www.Response;
 import gov.usgs.earthquake.nshmp.internal.www.WsUtils;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.services.SourceServices.SourceModel;
 
 import io.micronaut.http.HttpResponse;
 
@@ -38,7 +37,8 @@ class ServicesUtil {
   static Hazard calcHazard(
       Function<HazardModel, CalcConfig> configFunction,
       Function<CalcConfig, Site> siteFunction) throws InterruptedException, ExecutionException {
-    var futuresList = ServletUtil.hazardModels().stream()
+    // TODO reduce for singleton model
+    var futuresList = Stream.of(ServletUtil.model())
         .map(model -> {
           var config = configFunction.apply(model);
           var site = siteFunction.apply(config);
@@ -58,7 +58,9 @@ class ServicesUtil {
     return Hazard.merge(hazards);
   }
 
+  @Deprecated
   static class ServiceQueryData implements ServiceQuery {
+
     public final Double longitude;
     public final Double latitude;
 
@@ -79,13 +81,13 @@ class ServicesUtil {
     }
   }
 
+  @Deprecated
   static class ServiceRequestData {
-    public final List<SourceModel> models;
+
     public final double longitude;
     public final double latitude;
 
     public ServiceRequestData(ServiceQueryData query) {
-      models = SourceModel.getList();
       longitude = query.longitude;
       latitude = query.latitude;
     }
@@ -117,6 +119,7 @@ class ServicesUtil {
     }
   }
 
+  @Deprecated
   private static interface ServiceQuery {
     boolean isNull();
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
index 5eb10bff5983ffa4c96cb830f2ad337d7c125ace..ca44830476be7e89c0aa7dc1d861f3898444dfca 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/ServletUtil.java
@@ -2,23 +2,16 @@ package gov.usgs.earthquake.nshmp.www.services;
 
 import static java.lang.Runtime.getRuntime;
 
-import java.io.IOException;
 import java.lang.reflect.Type;
 import java.net.URI;
 import java.net.URL;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.FileSystems;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -34,12 +27,10 @@ import com.google.gson.JsonSerializer;
 
 import gov.usgs.earthquake.nshmp.calc.Site;
 import gov.usgs.earthquake.nshmp.calc.ValueFormat;
-import gov.usgs.earthquake.nshmp.calc.Vs30;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
 import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
 import gov.usgs.earthquake.nshmp.www.meta.MetaUtil;
-import gov.usgs.earthquake.nshmp.www.meta.Region;
 
 import io.micronaut.context.annotation.Value;
 import io.micronaut.context.event.ShutdownEvent;
@@ -70,7 +61,9 @@ public class ServletUtil {
   @Value("${nshmp-haz.model-path}")
   private Path modelPath;
 
-  private static List<HazardModel> HAZARD_MODELS = new ArrayList<>();
+  // private static List<HazardModel> HAZARD_MODELS = new ArrayList<>();
+
+  private static HazardModel HAZARD_MODEL;
   private static final String MODEL_INFO = "model-info.json";
 
   static {
@@ -79,9 +72,7 @@ public class ServletUtil {
     CALC_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(THREAD_COUNT));
     TASK_EXECUTOR = Executors.newSingleThreadExecutor();
     GSON = new GsonBuilder()
-        .registerTypeAdapter(Region.class, new MetaUtil.EnumSerializer<Region>())
         .registerTypeAdapter(Imt.class, new MetaUtil.EnumSerializer<Imt>())
-        .registerTypeAdapter(Vs30.class, new MetaUtil.EnumSerializer<Vs30>())
         .registerTypeAdapter(ValueFormat.class, new MetaUtil.EnumSerializer<ValueFormat>())
         .registerTypeAdapter(Double.class, new MetaUtil.DoubleSerializer())
         .registerTypeAdapter(ParamType.class, new MetaUtil.ParamTypeSerializer())
@@ -93,8 +84,12 @@ public class ServletUtil {
         .create();
   }
 
-  static List<HazardModel> hazardModels() {
-    return List.copyOf(HAZARD_MODELS);
+  // static List<HazardModel> hazardModels() {
+  // return List.copyOf(HAZARD_MODELS);
+  // }
+
+  static HazardModel model() {
+    return HAZARD_MODEL;
   }
 
   @EventListener
@@ -105,13 +100,15 @@ public class ServletUtil {
 
   @EventListener
   void startup(StartupEvent event) {
-    try {
-      var modelFinder = new ModelFinder();
-      Files.walkFileTree(modelPath, modelFinder);
-      modelFinder.paths().forEach(path -> HAZARD_MODELS.add(loadModel(path)));
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    HAZARD_MODEL = loadModel(modelPath);
+    // TODO should model path just be libs/model
+    // try {
+    // var modelFinder = new ModelFinder();
+    // Files.walkFileTree(modelPath, modelFinder);
+    // modelFinder.paths().forEach(path -> HAZARD_MODELS.add(loadModel(path)));
+    // } catch (IOException e) {
+    // throw new RuntimeException(e);
+    // }
   }
 
   private HazardModel loadModel(Path path) {
@@ -165,6 +162,7 @@ public class ServletUtil {
    * Simple timer object. The servlet timer just runs. The calculation timer can
    * be started later.
    */
+  @Deprecated
   public static final class Timer {
     Stopwatch servlet = Stopwatch.createStarted();
     Stopwatch calc = Stopwatch.createUnstarted();
@@ -183,28 +181,28 @@ public class ServletUtil {
     }
   }
 
-  private static class ModelFinder extends SimpleFileVisitor<Path> {
-    private List<Path> paths;
-
-    ModelFinder() {
-      paths = new ArrayList<>();
-    }
-
-    List<Path> paths() {
-      return List.copyOf(paths);
-    }
-
-    @Override
-    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
-      var fileName = path.getFileName();
-
-      if (fileName != null && fileName.toString().equals(MODEL_INFO)) {
-        paths.add(path.getParent());
-      }
-
-      return FileVisitResult.CONTINUE;
-    }
-  }
+  // private static class ModelFinder extends SimpleFileVisitor<Path> {
+  // private List<Path> paths;
+  //
+  // ModelFinder() {
+  // paths = new ArrayList<>();
+  // }
+  //
+  // List<Path> paths() {
+  // return List.copyOf(paths);
+  // }
+  //
+  // @Override
+  // public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
+  // var fileName = path.getFileName();
+  //
+  // if (fileName != null && fileName.toString().equals(MODEL_INFO)) {
+  // paths.add(path.getParent());
+  // }
+  //
+  // return FileVisitResult.CONTINUE;
+  // }
+  // }
 
   private static class PathConverter implements JsonSerializer<Path> {
 
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
index 1a1d6ff2e997831aff815aa024d74aac0002b229..4773a3c8026e137f9e333301737ec5d87e6f9f56 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/services/SourceServices.java
@@ -1,32 +1,22 @@
 package gov.usgs.earthquake.nshmp.www.services;
 
-import java.lang.reflect.Type;
-import java.util.EnumSet;
-import java.util.List;
+import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
 
+import com.google.common.base.Stopwatch;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
 
-import gov.usgs.earthquake.nshmp.calc.CalcConfig;
-import gov.usgs.earthquake.nshmp.calc.Vs30;
 import gov.usgs.earthquake.nshmp.gmm.Gmm;
 import gov.usgs.earthquake.nshmp.gmm.Imt;
+import gov.usgs.earthquake.nshmp.gmm.NehrpSiteClass;
 import gov.usgs.earthquake.nshmp.internal.www.NshmpMicronautServlet.UrlHelper;
 import gov.usgs.earthquake.nshmp.internal.www.Response;
-import gov.usgs.earthquake.nshmp.internal.www.meta.EnumParameter;
 import gov.usgs.earthquake.nshmp.internal.www.meta.ParamType;
 import gov.usgs.earthquake.nshmp.internal.www.meta.Status;
 import gov.usgs.earthquake.nshmp.model.HazardModel;
-import gov.usgs.earthquake.nshmp.www.meta.DoubleParameter;
 import gov.usgs.earthquake.nshmp.www.meta.MetaUtil;
 import gov.usgs.earthquake.nshmp.www.meta.Metadata;
-import gov.usgs.earthquake.nshmp.www.meta.Region;
 
 import io.micronaut.http.HttpResponse;
 
@@ -36,7 +26,6 @@ import io.micronaut.http.HttpResponse;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("unused")
 public class SourceServices {
 
   private static final String NAME = "Source Model";
@@ -50,8 +39,6 @@ public class SourceServices {
     GSON = new GsonBuilder()
         .registerTypeAdapter(Imt.class, new MetaUtil.EnumSerializer<Imt>())
         .registerTypeAdapter(ParamType.class, new MetaUtil.ParamTypeSerializer())
-        .registerTypeAdapter(Vs30.class, new MetaUtil.EnumSerializer<Vs30>())
-        .registerTypeAdapter(Region.class, new RegionSerializer())
         .disableHtmlEscaping()
         .serializeNulls()
         .setPrettyPrinting()
@@ -76,60 +63,55 @@ public class SourceServices {
   public static class ResponseData {
     final String description;
     final Object server;
-    final Parameters parameters;
+    // final Parameters parameters;
 
     public ResponseData() {
       this.description = "Installed source model listing";
-      this.server = Metadata.serverData(ServletUtil.THREAD_COUNT, ServletUtil.timer());
-      this.parameters = new Parameters();
+      this.server = Metadata.serverData(ServletUtil.THREAD_COUNT, Stopwatch.createStarted());
+      // this.parameters = new Parameters();
     }
   }
 
-  static class Parameters {
-    List<SourceModel> models;
-    EnumParameter<Region> region;
-    DoubleParameter returnPeriod;
-    EnumParameter<Vs30> vs30;
-
-    Parameters() {
-      models = ServletUtil.hazardModels().stream()
-          .map(SourceModel::new)
-          .collect(Collectors.toList());
-
-      region = new EnumParameter<>(
-          "Region",
-          ParamType.STRING,
-          EnumSet.allOf(Region.class));
-
-      returnPeriod = new DoubleParameter(
-          "Return period (in years)",
-          ParamType.NUMBER,
-          100.0,
-          1e6);
-
-      vs30 = new EnumParameter<Vs30>(
-          "Vs30",
-          ParamType.STRING,
-          EnumSet.allOf(Vs30.class));
-    }
-  }
+  // static class Parameters {
+  // List<SourceModel> models;
+  // DoubleParameter returnPeriod;
+  // DoubleParameter vs30;
+  //
+  // Parameters() {
+  // models = ServletUtil.hazardModels().stream()
+  // .map(SourceModel::new)
+  // .collect(Collectors.toList());
+  //
+  // returnPeriod = new DoubleParameter(
+  // "Return period",
+  // "years",
+  // 100.0,
+  // 1e6);
+  //
+  // vs30 = new DoubleParameter(
+  // "Vs30",
+  // "m/s",
+  // 150,
+  // 1500);
+  // }
+  // }
 
   public static class SourceModel {
-    String display;
+    String name;
     Set<Gmm> gmms;
-    CalcConfig config;
+    Map<NehrpSiteClass, Double> siteClasses;
 
-    private SourceModel(HazardModel model) {
-      display = model.name();
+    SourceModel(HazardModel model) {
+      name = model.name();
       gmms = model.gmms();
-      config = model.config();
+      siteClasses = model.siteClasses();
     }
 
-    public static List<SourceModel> getList() {
-      return ServletUtil.hazardModels().stream()
-          .map(SourceModel::new)
-          .collect(Collectors.toList());
-    }
+    // public static List<SourceModel> getList() {
+    // return ServletUtil.hazardModels().stream()
+    // .map(SourceModel::new)
+    // .collect(Collectors.toList());
+    // }
   }
 
   enum Attributes {
@@ -162,26 +144,4 @@ public class SourceServices {
       return name().toLowerCase();
     }
   }
-
-  // TODO align with enum serializer if possible; consider service attribute
-  // enum
-  // TODO test removal of ui-min/max-lon/lat
-  static final class RegionSerializer implements JsonSerializer<Region> {
-
-    @Override
-    public JsonElement serialize(Region region, Type typeOfSrc, JsonSerializationContext context) {
-      var json = new JsonObject();
-
-      json.addProperty(Attributes.VALUE.toLowerCase(), region.name());
-      json.addProperty(Attributes.DISPLAY.toLowerCase(), region.toString());
-
-      json.addProperty(Attributes.MINLATITUDE.toLowerCase(), region.minlatitude);
-      json.addProperty(Attributes.MAXLATITUDE.toLowerCase(), region.maxlatitude);
-      json.addProperty(Attributes.MINLONGITUDE.toLowerCase(), region.minlongitude);
-      json.addProperty(Attributes.MAXLONGITUDE.toLowerCase(), region.maxlongitude);
-
-      return json;
-    }
-  }
-
 }
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
index 6864f0aec64ee546c7cfee39761ab3ca9de852a4..25f4935f56f7b858cfffb487bfe86555c6e1c4e9 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsLarge.java
@@ -44,7 +44,6 @@ package gov.usgs.earthquake.nshmp;
  * @see NshmTestsSmall
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public class NshmTestsLarge {
 
   // private static final List<String> COUS_REGION_IDS = ImmutableList.of("wus",
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
index 26dcf4527bdd771a5bcf56e83388c66b3c99e0d6..c85c84aa311babefc937377d80993f59f9de145f 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/NshmTestsSmall.java
@@ -27,7 +27,6 @@ package gov.usgs.earthquake.nshmp;
  *
  * @author U.S. Geological Survey
  */
-@SuppressWarnings("javadoc")
 public class NshmTestsSmall {
 
   // /*
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java b/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
index 46274746a6c36c931df020a798eeeee54d6769a0..8ffeefca020c785ec60bcc40a02c1ff11e12e95e 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/programs/HazardCurveTest.java
@@ -3,7 +3,6 @@ package gov.usgs.earthquake.nshmp.programs;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-@SuppressWarnings("javadoc")
 public class HazardCurveTest {
 
   @BeforeEach
diff --git a/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java b/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
index 866975eec275b372c8a8ab464c81369fa3762d5b..d6da4edd245eb088762d09055ff7a8054b2a36ab 100644
--- a/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
+++ b/src/test/java/gov/usgs/earthquake/nshmp/site/NshmpSiteTests.java
@@ -59,7 +59,6 @@ import gov.usgs.earthquake.nshmp.geo.Location;
 import gov.usgs.earthquake.nshmp.internal.UsRegion;
 import gov.usgs.earthquake.nshmp.site.NshmpSite.StateComparator;
 
-@SuppressWarnings("javadoc")
 public class NshmpSiteTests {
 
   @Test