diff --git a/README.md b/README.md
index 7d6cd23f2816cfcb25e19be12205a915cd368b72..942d8dbf55b61eb3c3cf482a2cd9a9fabc447588 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,10 @@
 # nshmp-ws
 
+*nshmp-ws* provides web service access to ground motion models (GMMs) used in USGS National Seismic
+Hazard Models (NSHMs).
+
+[TOC]
+
 ## Running the Services
 
 ### Gradle
@@ -8,42 +13,46 @@ To run the services with Gradle:
 
 ```bash
 ./gradlew run
+# or './gradlew run -t' to recompile and relaunch when code changes
 ```
 
-Services are then avialable on <http://localhost:8080/>
-
-To have the services automatically recompile when changes are made locally to the source
-code, run:
-
-```bash
-./gradlew run -t
-```
-
-### Jar file
-
-The services can be run from the JAR file:
+Alternatively, the services can be run from the JAR file:
 
 ```bash
 ./gradlew assemble
 java -jar build/libs/nshmp-ws-all.jar
 ```
 
-Services are then avialable on <http://localhost:8080/>
+After startup, web services and documentation are available at <http://localhost:8080/>.
+
+#### Customizing Code
 
-Note: By default the web services use the
-[nshm-fault-sections](https://code.usgs.gov/ghsc/nshmp/nshm-fault-sections) repository in the `libs`
-directory in the root of this project and such the `java -jar` command should also be run
-in the root of the project. To run the JAR file from anywhere the path to the fault sections
-should be specified:
+Whereas *nshmp-ws* contains code to run web services, ground motion model (GMM) calculations
+are handled in the dependent library [*nshmp-lib*](https://code.usgs.gov/ghsc/nshmp/nshmp-lib).
+To use a local, modified version of *nshmp-lib*, set an environment variable
+`NSHMP_LIB_LOCAL=true` and *nshmp-ws* will look for *nshmp-lib* in a directory adjacent to
+*nshmp-ws*. If *nshmp-lib* is located somewhere else, modify the path specified in
+[`gradle/dependencies.gradle`](../../gradle/dependencies.gradle). When using a local version
+of *nshmp-lib*, first build the *nshmp-lib* project using `./gradlew fatJar` so that
+required dependencies are included.
+
+Summary of steps to check out and start running code for local development:
 
 ```bash
-./gradlew assemble
-java -jar path/to/nshmp-ws-all.jar --faults-path=path/to/nshm-fault-sections
+# --> Set a NSHMP_LIB_LOCAL=true environment variable on your system
+cd yourProjectDirectory
+git clone https://code.usgs.gov/ghsc/nshmp/nshmp-lib.git
+cd nshmp-lib
+./gradlew fatJar
+cd ..
+git clone https://code.usgs.gov/ghsc/nshmp/nshmp-ws.git
+cd nshmp-ws
+./gradlew run
 ```
 
 ### Docker
 
-### Run from GitLab Registry
+#### Run from GitLab Registry
 
 The nshmp-ws application may be run as a Docker container.
 
@@ -73,108 +82,10 @@ http://localhost:8080/nshmp/data/fault-sections
 
 The `PORT` should be replaced with the same value to start the container.
 
-### Build Docker Locally
+#### Build Docker Locally
 
 A Docker image can also be created locally:
 
 ```bash
 docker build -t <tag name> .
 ```
-
-## Fault Sections Service
-
-### Fault Sections Service: Usage
-
-* /nshmp/data/fault-sections
-
-### Obtaining fault sections
-
-See [nshm-fault-sections](https://code.usgs.gov/ghsc/nshmp/nshm-fault-sections)
-for information on groups and ids.
-
-#### By Group
-
-* Format: /nshmp/data/fault-sections?group={String}&raw={Boolean}
-* Format: /nshmp/data/{group}/{raw}
-* Example: /nshmp/data/fault-sections?group=CA
-* Example: /nshmp/data/fault-sections?group=CA&group=NV&group=...
-* Example: /nshmp/data/fault-sections/CA
-
-Where `group` can either be a
-[`UsRegion`](https://earthquake.usgs.gov/nshmp/docs/nshmp-lib/gov/usgs/earthquake/nshmp/internal/UsRegion.html)
-or [`FaultGroup`](https://code.usgs.gov/ghsc/nshmp/nshmp-ws/-/blob/main/src/main/java/gov/usgs/earthquake/nshmp/www/fault/FaultGroup.java).
-
-By default the `raw` flag is set to `false`, when set to `true` the response is pure GeoJSON
-
-#### By ID
-
-* Format: /nshmp/data/fault-sections?id={Integer}&raw={Boolean}
-* Example: /nshmp/data/fault-sections?id=1
-* Example: /nshmp/data/fault-sections?id=1&id=2&id=...
-
-* Format: /nshmp/data/fault-sections/{id}/{raw}
-* Example: /nshmp/data/fault-sections/1
-
-### Local Development
-
-The [fault sections repository](https://code.usgs.gov/ghsc/nshmp/nshm-fault-sections)
-repository is downloaded from a tagged version, see [gradle.properties](gradle.properties)
-`nshmFaultSectionsTag` for tagged version used, and stored in the libs directory.
-
-To, instead, point to a local version of the fault sections repository update the
-gradle.properties file, either in this project or under `$GRADLE_USER_HOME`/gradle.properties
-(defaults to `$USER_HOME/.gradle`), with the following:
-
-```bash
-faultSectionsEnv = DEV
-```
-
-Run `./gradlew clean` to clean up the libs directory and make a symbolinc link from the
-fault sections repository to the libs directory.
-Example:
-
-```bash
-cd libs
-ln -s ../nshm-fault-sections .
-```
-
-## GPS Data Service
-
-GPS data service provides access to the GPS datasets used for each NSHM. All velocities are
-in units of mm/yr and the vertical component, if available, is positive up.
-
-### GPS Data Service: Usage
-
-Datasets are selected by model:
-
-* `CONUS_2014_UCERF`
-* `CONUS_2014_WUS`
-* `AK_2020`
-* `HI_2020`
-
-Data format is one of the following:
-
-* `CSV` (default)
-* `JSON` (GeoJSON feature collection embedded in JSON response)
-* `RAW_JSON` (GeoJSON feature collection)
-
-#### GPS Data: Query-based
-
-* Format: /nshmp/data/gps?model={MODEL}&format={FORMAT}
-* Example: /nshmp/data/gps?model=HI_2020&format=CSV
-
-#### GPS Data: Slash-delimited based
-
-* Format: /nshmp/data/gps/{MODEL}/{FORMAT}
-* Example: /nshmp/data/gps/HI_2020/JSON
-
-### Geodesy Process
-
-TODO: expand process description
-
-* In house multi-modeling capability
-* Curate/update strain vector fields
-* Connectivity in fault models
-* Data transfer
-  * Modifications to fault models required by geodetic modelers need to be communicated back to NSHM
-* slip rate uncertainties
diff --git a/etc/matlab/README.md b/etc/matlab/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d0f7324ef0ea44d34dda33f8a4ce09c55850405a
--- /dev/null
+++ b/etc/matlab/README.md
@@ -0,0 +1,7 @@
+# Using Ground Motion Models (GMMs) from Matlab
+
+The scripts in this directory provide examples of how to access web services for NSHM GMMs.
+
+Users are *strongly* encouraged to run the web services locally so as to not overburden USGS
+servers. See the [README](../../README.md) at the root of this repository for instructions on
+how to do so.
diff --git a/etc/matlab/ResponseSpectrum.m b/etc/matlab/ResponseSpectrum.m
new file mode 100644
index 0000000000000000000000000000000000000000..a3d0b7b67790c26d625db792f79ac8b807419ea7
--- /dev/null
+++ b/etc/matlab/ResponseSpectrum.m
@@ -0,0 +1,156 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Ground motion model (GMM) response spectra plots
+%
+% Author: Peter Powers (pmpowers@usgs.gov)
+%
+% Updated: 01/19/2023
+%
+% This script demonstrates how to call web services for the ground motion
+% models implemented in USGS National Sesmic Hazard Models and plot the
+% results. A JSON web service response is automatically converted to a
+% struct by the Matlab webread() function. This script shows how to plot
+% the GMMs requested and optionally the underlying models of epistemic
+% uncertainty.
+%
+% Users are STRONGLY encouraged to run the web services locally so as to
+% not overburden USGS servers. See the repository README for details on how
+% to do so: https://code.usgs.gov/ghsc/nshmp/nshmp-ws
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Plot a figure of GMM reponse spectra and epistemic uncertainty
+
+clearvars
+
+% The root url for the response spectra web service
+urlbase = "https://earthquake.usgs.gov/ws/nshmp/data/gmm/spectra?";
+
+% If you are running nshmp-haz locally, use this URL:
+% urlbase = "http://localhost:8080/gmm/spectra?";
+
+% Struct of ground motion model parameters
+in.Mw = 7.5;
+in.dip = 90;
+in.rake = 0;
+in.width = 15;
+in.rJB = 50;
+in.rRup = 50;
+in.rX = 50;
+in.vs30 = 760;
+in.zHyp = 7.5;
+in.zTor = 10;
+
+figure
+plot_handles = [];
+
+% Set to true to show epistemic branches
+epi = false;
+
+gmms_2023 = ["ASK_14" "BSSA_14" "CB_14" "CY_14"];
+means = readSpectra(urlbase, gmms_2023, in).response.means.data;
+plotGmms(means, in, epi);
+
+%% Shared Functions
+
+function plotGmms(gmm_data, in, epi)
+
+    plot_handles = [];
+    legend_labels = {};
+
+    % loop means_new response array
+    for j = 1 : length(gmm_data) 
+    
+        gmm_xs = gmm_data(j).data.xs;
+        gmm_ys = gmm_data(j).data.ys;
+        gmm_tree = gmm_data(j).tree;
+
+        % if 0.01 absent use PGA (0.001 is used for PGA)
+        if gmm_xs(1) == 0.001 && gmm_xs(2) ~= 0.01
+            gmm_xs(1) = 0.01;
+        end
+
+        % Plot the total spectrum
+        ph = loglog(gmm_xs, gmm_ys, ...
+            'LineWidth',3, ...
+            'LineStyle','-');
+        
+        color = get(ph,'Color');
+        hold on;
+        
+        plot_handles = [plot_handles ph];
+        legend_labels{end+1} = gmm_data(j).label;
+        
+        % Plot epistemic spectra, if present
+        if epi && ~isempty(gmm_tree)
+            for k = 1 : length(gmm_tree)
+                id = gmm_tree(k).id;
+                epi_ys = gmm_tree(k).values;
+                
+                phe = loglog(gmm_xs, epi_ys, ...
+                    'LineWidth',1, ...
+                    'LineStyle',':', ...
+                    'Color',color); 
+
+                plot_handles = [plot_handles phe];
+                legend_labels{end+1} = [gmm_data(j).label ' ' id];
+            end
+        end
+    end
+    
+    grid on
+
+    xlabel('Spectral Period (s)','FontSize',16)
+    ylabel('Median Ground Motion (g)','FontSize',16)
+    title(['M',num2str(in.Mw),', ',num2str(in.rRup),'km'],'FontSize',20)
+    xlim([0.01 10]);
+
+    set(gca,'FontSize',20);
+    set(gca,'XTick',[0.01 0.1 1 10]);
+    set(gca,'XTickLabel',{'0.01','0.1','1','10'});
+    
+    legend( ...
+        plot_handles,legend_labels, ...
+        'Location','southwest', ...
+        'Interpreter', 'none');
+end
+
+% Read reponse spectra from a NSHM web service for the supplied
+% ground motion models (GMMs) and GMM input parameters
+function response = readSpectra(urlbase, gmms, in)
+
+url = urlbase;
+for i = 1 : size(gmms, 2)
+    if i == 1
+        url = url + "gmm=" + gmms(i);
+    else
+        url = url + "&gmm=" + gmms(i);
+    end
+end
+url = url + ...
+    "&Mw=" + num2str(in.Mw) + ...
+    "&dip=" + num2str(in.dip) + ...
+    "&rake=" + num2str(in.rake) + ...
+    "&width=" + num2str(in.width) + ...
+    "&rJB=" + num2str(in.rJB) + ...
+    "&rRup=" + num2str(in.rRup) + ...
+    "&rX=" + num2str(in.rX) + ...
+    "&vs30=" + num2str(in.vs30) + ...
+    "&zHyp=" + num2str(in.zHyp) + ...
+    "&zTop=" + num2str(in.zTor);
+
+if isfield(in, 'z2p5')
+    url = url + num2str(in.z2p5);
+end
+
+if isfield(in, 'z1p0')
+    url = url + num2str(in.z1p0);
+end
+
+if isfield(in, 'zSed')
+    url = url + num2str(in.zSed);
+end
+
+response = webread(url);
+
+end
diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle
index d0d01e3b1934f7fbb434eb632008d6bab26d1a68..b5b539c6ac1ede9282867d329829fc0977fe01be 100644
--- a/gradle/dependencies.gradle
+++ b/gradle/dependencies.gradle
@@ -1,7 +1,12 @@
-
 dependencies {
+
   // NSHMP
-  implementation "ghsc:nshmp-lib:${nshmpLibVersion}"
+  System.out.println(System.getenv("NSHMP_LIB_LOCAL"))
+  if (System.getenv("NSHMP_LIB_LOCAL") == "true") {
+    implementation files("../nshmp-lib/build/libs/nshmp-lib.jar")
+  } else {
+    implementation "ghsc:nshmp-lib:${nshmpLibVersion}"
+  }
   implementation "ghsc:nshmp-ws-utils:${nshmpWsUtilsVersion}"
 
   // Micronaut
diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
index 405dd2042d9af5e18ac45f39af99038cdd2739d3..1e3a6516eb01e642d1df16fe650f26d9d327277c 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/www/gmm/GmmCalc.java
@@ -91,7 +91,7 @@ class GmmCalc {
         .map(Branch::id)
         .collect(Collectors.toList());
 
-    double[] xs = xValues.stream().mapToDouble(Double::valueOf).toArray();
+    double[] xs = xValues.stream().mapToDouble(Double::doubleValue).toArray();
     double[] μs = new double[xValues.size()];
     double[] σs = new double[xValues.size()];