diff --git a/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java b/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java
index 5e130b953a54a06d53d9ffe4fc85110c3e7ee322..ae96cbd6cce450cdc7f2c8025096930652ff0ac3 100644
--- a/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java
+++ b/src/main/java/gov/usgs/earthquake/nshmp/gmm/NgaEast.java
@@ -342,7 +342,9 @@ public abstract class NgaEast implements GroundMotionModel {
 
   /* Implementation of sammons map models. */
   static class NgaEast_2018 extends NgaEast {
+
     static final String NAME = NgaEast.NAME + " (2018)";
+
     static final int MODEL_COUNT = 17;
     static final String[] MEAN_IDS = IntStream.range(1, MODEL_COUNT + 1)
         .mapToObj(i -> "Sammons" + i)
@@ -396,16 +398,30 @@ public abstract class NgaEast implements GroundMotionModel {
       super(imt);
     }
 
+    /*
+     * Developer notes: The current implementation assumes a reference site
+     * condition of Vs30 = 590 m/s. This means that we apply the full Chapman &
+     * Guo PSA ratio if Vs30 = 590 and scale it by the ratio of the site term at
+     * the target Vs30 to the reference Vs30.
+     */
     @Override
     public LogicTree<GroundMotion> calc(GmmInput in) {
-      double cpa = Double.isNaN(in.zSed)
-          ? 0.0
-          : log(ChapmanGuo_2021.cpaPsaRatio(imt, in.zSed, in.Mw, in.rJB));
+      boolean cpa = !Double.isNaN(in.zSed);
+      double fCpa = cpa
+          ? log(ChapmanGuo_2021.cpaPsaRatio(imt, in.zSed, in.Mw, in.rJB))
+          : 0.0;
       Position p = tables[0].position(in.rRup, in.Mw);
       double[] μs = new double[MODEL_COUNT];
       for (int i = 0; i < MODEL_COUNT; i++) {
         double μ = tables[i].get(p);
-        μs[i] = μ + cpa;
+        double μPga = exp(pgaTables[i].get(p));
+        SiteAmp.Value fSite = siteAmp.calc(μPga, in.vs30);
+        if (cpa) {
+          SiteAmp.Value fCpaRef = siteAmp.calc(μPga, ChapmanGuo_2021.VS_REF);
+          double cpaScale = fSite.siteAmp / fCpaRef.siteAmp;
+          fCpa *= cpaScale;
+        }
+        μs[i] = fSite.apply(μ) + fCpa;
       }
       double[] σs = new double[] {
           sigmaEpri(in.Mw),
@@ -452,6 +468,7 @@ public abstract class NgaEast implements GroundMotionModel {
     final Map<Gmm, GroundMotionTable> tables;
     final Map<Gmm, GroundMotionTable> pgaTables;
     final ShahjoueiPezeshk_2016 sp16;
+    final ShahjoueiPezeshk_2016 sp16pga;
     final SiteAmp siteAmp;
 
     static {
@@ -481,6 +498,8 @@ public abstract class NgaEast implements GroundMotionModel {
       this.tables = getImtTables(imt);
       this.pgaTables = getImtTables(Imt.PGA);
       this.sp16 = (ShahjoueiPezeshk_2016) Gmm.NGA_EAST_SEED_SP16.instance(imt);
+      this.sp16pga = (ShahjoueiPezeshk_2016) Gmm.NGA_EAST_SEED_SP16.instance(Imt.PGA);
+
       this.siteAmp = new SiteAmp(imt);
     }
 
@@ -499,15 +518,18 @@ public abstract class NgaEast implements GroundMotionModel {
       for (int i = 0; i < GMMS.size(); i++) {
         Gmm seed = GMMS.get(i);
         if (seed == Gmm.NGA_EAST_SEED_SP16) {
-          μs[i] = GroundMotions.combine(sp16.calc(in)).mean();
+          double μ = sp16.calcMeanRock(in.Mw, in.rRup);
+          double μPga = exp(sp16pga.calcMeanRock(in.Mw, in.rRup));
+          SiteAmp.Value fSite = siteAmp.calc(μPga, in.vs30);
+          μs[i] = fSite.apply(μ);
         } else if (imt == Imt.PGV && noPgvSeeds.contains(seed)) {
           // site is included when calling individual seed
           μs[i] = UsgsPgvSupport.calcAB20Pgv(seed, in).mean();
         } else {
-          double μRock = tables.get(seed).get(p);
+          double μ = tables.get(seed).get(p);
           double μPga = exp(pgaTables.get(seed).get(p));
           SiteAmp.Value fSite = siteAmp.calc(μPga, in.vs30);
-          μs[i] = fSite.apply(μRock);
+          μs[i] = fSite.apply(μ);
         }
       }
       double[] σs = new double[] {
@@ -519,6 +541,19 @@ public abstract class NgaEast implements GroundMotionModel {
     }
   }
 
+  public static void main(String[] args) {
+    // Gmm gmm = Gmm.NGA_EAST_SEED_SP16;
+    Gmm gmm = Gmm.NGA_EAST_SEEDS_2018;
+    // Gmm gmm = Gmm.NGA_EAST_SEED_SP16;
+    GmmInput in = GmmInput.builder().withDefaults().build();
+    LogicTree<GroundMotion> gms = gmm.instance(Imt.PGA).calc(in);
+    System.out.println(gms);
+    gms.forEach(gm -> System.out.println(gm.id() + ": " + gm.value()));
+    GroundMotion gm = GroundMotions.combine(gms);
+    System.out.println(gm);
+
+  }
+
   /*
    * Updated NGA-East for use in the 2023 nshm-conus update. This model includes
    * (1) the final published nonlinear site amplification model of Hshash et al.
@@ -536,21 +571,34 @@ public abstract class NgaEast implements GroundMotionModel {
     @Override
     public LogicTree<GroundMotion> calc(GmmInput in) {
       GmmInput inRock = GmmInput.builder().fromCopy(in).vs30(3000).build();
-      double cpa = Double.isNaN(in.zSed)
-          ? 0.0
-          : log(ChapmanGuo_2021.cpaPsaRatio(imt, in.zSed, in.Mw, in.rJB));
+      boolean cpa = !Double.isNaN(in.zSed);
+      double fCpa = cpa
+          ? log(ChapmanGuo_2021.cpaPsaRatio(imt, in.zSed, in.Mw, in.rJB))
+          : 0.0;
       Position p = tables.values().iterator().next().position(in.rRup, in.Mw);
       double[] μs = new double[GMMS.size()];
       for (int i = 0; i < GMMS.size(); i++) {
         Gmm seed = GMMS.get(i);
+
+        double μ;
+        double μPga;
+
         if (seed == Gmm.NGA_EAST_SEED_SP16) {
-          μs[i] = GroundMotions.combine(sp16.calc(inRock)).mean() + cpa;
+          μ = sp16.calcMeanRock(in.Mw, in.rRup);
+          μPga = sp16pga.calcMeanRock(in.Mw, in.rRup);
         } else if (imt == Imt.PGV && noPgvSeeds.contains(seed)) {
-          // use custom input to ensure hard rock from seeds
-          μs[i] = UsgsPgvSupport.calcAB20Pgv(seed, inRock).mean() + cpa;
+          // note rock input; TODO this doesn't really work as the PGV
+          // is conditioned on vs30 so site should already be applied
+          μ = UsgsPgvSupport.calcAB20Pgv(seed, inRock).mean();
+          μPga = exp(pgaTables.get(seed).get(p));
         } else {
-          μs[i] = tables.get(seed).get(p) + cpa;
+          μ = tables.get(seed).get(p);
+          μPga = exp(pgaTables.get(seed).get(p));
         }
+        SiteAmp.Value fSite = siteAmp.calc(μPga, in.vs30);
+        double cpaScale = cpa ? cpaScale(μPga, fSite) : 0.0;
+        μs[i] = fSite.apply(μ) + fCpa * cpaScale;
+
       }
       double[] σs = new double[] {
           sigmaEpri(in.Mw),
@@ -559,6 +607,11 @@ public abstract class NgaEast implements GroundMotionModel {
           MEAN_IDS, μs, MEAN_WTS,
           SIGMA_IDS, σs, SIGMA_WTS);
     }
+
+    private double cpaScale(double μPga, SiteAmp.Value fSite) {
+      SiteAmp.Value fCpaRef = siteAmp.calc(μPga, ChapmanGuo_2021.VS_REF);
+      return fSite.siteAmp / fCpaRef.siteAmp;
+    }
   }
 
   static abstract class Seed extends NgaEast {