From 3b9d46edb477e416ac77428917febc9a43a82356 Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Wed, 6 Nov 2024 09:06:50 -0700
Subject: [PATCH 1/5] use plot expansion panel

---
 .../plot-settings-panel.component.html        |  26 +-
 .../plot-settings-panel.component.ts          |  20 +-
 .../plot-settings-panel.component.html        |  21 +-
 .../plot-settings-panel.component.ts          |  64 +---
 .../plot-settings-panel.component.html        |  16 +-
 .../plot-settings-panel.component.ts          | 127 +++-----
 .../dynamic-compare/services/app.service.ts   | 298 +++++++++---------
 7 files changed, 222 insertions(+), 350 deletions(-)

diff --git a/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.html
index 7ca879a46..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,25 +1 @@
-<div class="height-full overflow-scroll padding-bottom-2">
-  <mat-accordion multi>
-    @for (settings of plots(); track $index) {
-      <mat-expansion-panel>
-        <mat-expansion-panel-header>
-          <mat-panel-title>
-            {{ settings.plot.label }} Settings
-          </mat-panel-title>
-        </mat-expansion-panel-header>
-
-        <nshmp-lib-ng-plot-settings
-          [plot]="settings.plot"
-          [showLabel]="false"
-          (updatedPlot)="settings.updatePlot($event)"
-        />
-
-        <nshmp-lib-ng-plot-reset-plot-setting
-          [resetDisabled]="settings.plot.settingsForm.pristine"
-          [defaultPlotSetting]="settings.defaultPlotSetting"
-          [plotSettings]="settings.plot.settingsForm"
-        />
-      </mat-expansion-panel>
-    }
-  </mat-accordion>
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts
index 5fb2e7692..10fabb886 100644
--- a/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,33 +1,21 @@
 import {Component, computed, Signal} from '@angular/core';
-import {MatExpansionModule} from '@angular/material/expansion';
 import {
-  NshmpLibNgPlotResetPlotSettingComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
-  NshmpPlotSettings,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {AppService} from '../../services/app.service';
 
-interface PlotSetting {
-  defaultPlotSetting: NshmpPlotSettings;
-  plot: NshmpPlot;
-  updatePlot: (plot: NshmpPlot) => void;
-}
-
 @Component({
-  imports: [
-    MatExpansionModule,
-    NshmpLibNgPlotResetPlotSettingComponent,
-    NshmpLibNgPlotSettingsComponent,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  plots: Signal<PlotSetting[]> = computed(() => {
+  plots: Signal<PlotSettingsPlots[]> = computed(() => {
     const plots = this.service.plots();
     const defaultPlots = this.service.defaultPlots();
 
diff --git a/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.html
index 3174bc6b0..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,20 +1 @@
-<div class="height-full overflow-auto">
-  <mat-accordion multi>
-    @for (panel of panels; track panel) {
-      <mat-expansion-panel expanded>
-        <mat-expansion-panel-header>
-          <mat-panel-title>{{ panel.title }}</mat-panel-title>
-        </mat-expansion-panel-header>
-        <nshmp-lib-ng-plot-settings
-          [plot]="panel.plot()"
-          (updatedPlot)="updatePlot($event)"
-        />
-      </mat-expansion-panel>
-    }
-  </mat-accordion>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetPlotSettings()"
-    [resetDisabled]="resetDisabled"
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.ts
index 4aba1029c..3b2ae1691 100644
--- a/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/dev/gmm/hanging-wall-effects/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,68 +1,36 @@
-import {Component, computed, OnDestroy} from '@angular/core';
+import {Component, computed, Signal} from '@angular/core';
 import {
-  MatAccordion,
-  MatExpansionPanel,
-  MatExpansionPanelHeader,
-  MatExpansionPanelTitle,
-} from '@angular/material/expansion';
-import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
-  PlotSettingsPanel,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
-import {Subscription} from 'rxjs';
 
-import {Plots} from '../../models/state.model';
+import {defaultPlots, Plots} from '../../models/state.model';
 import {AppService} from '../../services/app.service';
 
 @Component({
-  imports: [
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    NshmpLibNgPlotSettingsComponent,
-    MatAccordion,
-    MatExpansionPanel,
-    MatExpansionPanelHeader,
-    MatExpansionPanelTitle,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
-export class PlotSettingsPanelComponent implements OnDestroy {
-  /** Ground motion plot */
-  groundMotionPlot = computed(() => {
-    this.settingsFormSubscription?.unsubscribe();
+export class PlotSettingsPanelComponent {
+  plots: Signal<PlotSettingsPlots[]> = computed(() => {
     const plot = this.service.state().plots.get(Plots.GROUND_MOTION);
-
-    this.settingsFormSubscription = plot.settingsForm.valueChanges.subscribe(
-      () => {
-        this.resetDisabled =
-          plot.settingsForm.pristine && plot.settingsForm.untouched;
-      }
-    );
-
-    return plot;
+    const defaultPlot = defaultPlots().get(Plots.GROUND_MOTION);
+
+    return [
+      {
+        defaultPlotSetting: defaultPlot.settingsForm.getRawValue(),
+        plot,
+        updatePlot: plot => this.updatePlot(plot),
+      },
+    ];
   });
 
-  panels: PlotSettingsPanel[] = [
-    {
-      id: Plots.GROUND_MOTION,
-      plot: this.groundMotionPlot,
-      title: 'Ground Motion Plot Settings',
-    },
-  ];
-
-  resetDisabled = true;
-  private settingsFormSubscription = new Subscription();
-
   constructor(public service: AppService) {}
 
-  ngOnDestroy(): void {
-    this.settingsFormSubscription.unsubscribe();
-  }
-
   updatePlot(plot: NshmpPlot): void {
     this.service.updatePlot(plot, Plots.GROUND_MOTION);
   }
diff --git a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.html
index 5decb453b..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,15 +1 @@
-<div class="height-full overflow-auto">
-  <mat-accordion multi>
-    @for (panel of panels; track panel) {
-      <mat-expansion-panel>
-        <mat-expansion-panel-header>
-          <mat-panel-title>{{ panel.title }}</mat-panel-title>
-        </mat-expansion-panel-header>
-        <nshmp-lib-ng-plot-settings
-          [plot]="panel.plot()"
-          (updatedPlot)="updatePlot(panel.id, $event)"
-        />
-      </mat-expansion-panel>
-    }
-  </mat-accordion>
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.ts
index d2c363f74..0ef6ed3a3 100644
--- a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,15 +1,8 @@
-import {AsyncPipe} from '@angular/common';
 import {Component, computed} from '@angular/core';
 import {
-  MatAccordion,
-  MatExpansionPanel,
-  MatExpansionPanelHeader,
-  MatExpansionPanelTitle,
-} from '@angular/material/expansion';
-import {
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
-  PlotSettingsPanel,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {Plots} from '../../models/state.model';
@@ -19,81 +12,61 @@ import {AppService} from '../../services/app.service';
  * Settings for all plots.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotSettingsComponent,
-    MatAccordion,
-    MatExpansionPanel,
-    MatExpansionPanelHeader,
-    MatExpansionPanelTitle,
-    AsyncPipe,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  /** Hazard plot data */
-  private hazardPlot = computed(() => this.service.plots().get(Plots.HAZARD));
-
-  /** Hazard components plot data */
-  private hazardComponentsPlot = computed(() =>
-    this.service.plots().get(Plots.HAZARD_COMPONENTS)
-  );
-
-  /** Hazard % diff plot data */
-  private hazardDiffPlot = computed(() =>
-    this.service.plots().get(Plots.HAZARD_DIFFERENCES)
-  );
-
-  /** Spectra components plot data */
-  private spectraComponentsPlot = computed(() =>
-    this.service.plots().get(Plots.SPECTRUM_COMPONENTS)
-  );
-
-  /** Spectra % diff plot data */
-  private spectraDiffPlot = computed(() =>
-    this.service.plots().get(Plots.SPECTRUM_DIFFERENCES)
-  );
-
-  /** Spectra plot data */
-  private spectraPlot = computed(() =>
-    this.service.plots().get(Plots.SPECTRUM)
-  );
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const defaultPlots = this.service.plots();
 
-  /** The panels with plot settings */
-  panels: PlotSettingsPanel[] = [
-    {
-      id: Plots.HAZARD,
-      plot: this.hazardPlot,
-      title: 'Hazard Curves Plot Settings',
-    },
-    {
-      id: Plots.HAZARD_DIFFERENCES,
-      plot: this.hazardDiffPlot,
-      title: 'Hazard % Difference Plot Settings',
-    },
-    {
-      id: Plots.SPECTRUM,
-      plot: this.spectraPlot,
-      title: 'Spectra Plot Settings',
-    },
-    {
-      id: Plots.SPECTRUM_DIFFERENCES,
-      plot: this.spectraDiffPlot,
-      title: 'Spectra % Difference Plot Settings',
-    },
-    {
-      id: Plots.HAZARD_COMPONENTS,
-      plot: this.hazardComponentsPlot,
-      title: 'Hazard Component Curves Plot Settings',
-    },
-    {
-      id: Plots.SPECTRUM_COMPONENTS,
-      plot: this.spectraComponentsPlot,
-      title: 'Spectra Component Curves Plot Settings',
-    },
-  ];
+    return [
+      {
+        defaultPlotSetting: defaultPlots
+          .get(Plots.HAZARD)
+          .settingsForm.getRawValue(),
+        plot: defaultPlots.get(Plots.HAZARD),
+        updatePlot: plot => this.updatePlot(Plots.HAZARD, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(Plots.HAZARD_DIFFERENCES)
+          .settingsForm.getRawValue(),
+        plot: defaultPlots.get(Plots.HAZARD_DIFFERENCES),
+        updatePlot: plot => this.updatePlot(Plots.HAZARD_DIFFERENCES, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(Plots.SPECTRUM)
+          .settingsForm.getRawValue(),
+        plot: defaultPlots.get(Plots.SPECTRUM),
+        updatePlot: plot => this.updatePlot(Plots.SPECTRUM, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(Plots.SPECTRUM_COMPONENTS)
+          .settingsForm.getRawValue(),
+        plot: defaultPlots.get(Plots.SPECTRUM_DIFFERENCES),
+        updatePlot: plot => this.updatePlot(Plots.SPECTRUM_DIFFERENCES, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(Plots.HAZARD_COMPONENTS)
+          .settingsForm.getRawValue(),
+        plot: defaultPlots.get(Plots.HAZARD_COMPONENTS),
+        updatePlot: plot => this.updatePlot(Plots.HAZARD_COMPONENTS, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(Plots.SPECTRUM_COMPONENTS)
+          .settingsForm.getRawValue(),
+        plot: defaultPlots.get(Plots.SPECTRUM_COMPONENTS),
+        updatePlot: plot => this.updatePlot(Plots.SPECTRUM_COMPONENTS, plot),
+      },
+    ];
+  });
 
   constructor(private service: AppService) {}
 
diff --git a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/app.service.ts b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/app.service.ts
index 864fbcf00..6e6a78a10 100644
--- a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/app.service.ts
@@ -57,21 +57,6 @@ interface Query {
   vs30: string;
 }
 
-const plotOptions: PlotOptions = {
-  layout: {
-    aspectRatio: hazardUtils.HAZARD_ASPECT_RATIO,
-  },
-};
-
-const diffPlotOptions: PlotOptions = {
-  layout: {
-    aspectRatio: '3:1',
-    yaxis: {
-      range: [-100, 100],
-      type: 'linear',
-    },
-  },
-};
 /**
  * Entrypoint to store for dynamic hazard compare application.
  */
@@ -252,6 +237,52 @@ export class AppService
       });
   }
 
+  /**
+   * Combine hazard usages with same region with common parameters.
+   *
+   * @param usages The usages with same region
+   */
+  combineUsages(usages: HazardUsageResponse[]): HazardUsageResponse {
+    const gmms = usages.map(usage => usage.response.model.gmms);
+    const imts = usages.map(usage => usage.response.model.imts);
+    const siteClasses = this.findCommonSiteClasses(
+      usages.map(usage => usage.response.model.siteClasses)
+    );
+    const usage = [...usages].shift();
+
+    const combinedUsage: HazardUsageResponse = {
+      ...usage,
+      response: {
+        latitude: {
+          ...usage.response.latitude,
+          max: Math.min(...usages.map(usage => usage.response.latitude.max)),
+          min: Math.max(...usages.map(usage => usage.response.latitude.min)),
+        },
+        longitude: {
+          ...usage.response.longitude,
+          max: Math.min(...usages.map(usage => usage.response.longitude.max)),
+          min: Math.max(...usages.map(usage => usage.response.longitude.min)),
+        },
+        model: {
+          bounds: usage.response.model.bounds,
+          gmms: gmms.reduce((previous, current) =>
+            previous.filter(gmm => current.includes(gmm))
+          ),
+          imts: this.findCommonImts(imts),
+          name: 'Combined usage',
+          siteClasses,
+        },
+        vs30: {
+          ...usage.response.vs30,
+          max: Math.min(...usages.map(usage => usage.response.vs30.max)),
+          min: Math.max(...usages.map(usage => usage.response.vs30.min)),
+        },
+      },
+    };
+
+    return combinedUsage;
+  }
+
   createPlots(): void {
     const plots = this.responseToPlots(this.state(), this.formGroup);
     this.updateState({plots});
@@ -270,6 +301,16 @@ export class AppService
     };
   }
 
+  /**
+   * Returns the default plots with settings.
+   */
+  defaultPlots(): Map<string, NshmpPlot> {
+    const plots = new Map<string, NshmpPlot>();
+    this.setHazardPlots(plots);
+    this.setSpectraPlots(plots);
+    return plots;
+  }
+
   /**
    * Initialize applicaiton.
    */
@@ -438,6 +479,47 @@ export class AppService
     control.addValidators(control => Validators.required(control));
   }
 
+  /**
+   * Returns the common imts form array of parameters.
+   *
+   * @param imts The imt parameters
+   */
+  private findCommonImts(imts: Parameter[][]): Parameter[] {
+    return imts.reduce((previous, current) =>
+      previous.filter(previousParameter =>
+        current
+          .map(currentParameter => currentParameter.value)
+          .includes(previousParameter.value)
+      )
+    );
+  }
+
+  /**
+   * Returns the common site classes based on keys from an array of site class
+   * records.
+   *
+   * @param siteClasses The site classes
+   */
+  private findCommonSiteClasses(
+    siteClasses: Record<string, number>[]
+  ): Record<string, number> {
+    const allSiteClasses = siteClasses.reduce((previous, current) => ({
+      ...previous,
+      ...current,
+    }));
+
+    const startingKeys = Object.keys(siteClasses.shift());
+
+    const keys = siteClasses.reduce((commonKeys, item) => {
+      return commonKeys.filter(key => Object.keys(item).includes(key));
+    }, startingKeys);
+
+    const commonSiteClasses: Record<string, number> = {};
+    keys.forEach(key => (commonSiteClasses[key] = allSiteClasses[key]));
+
+    return commonSiteClasses;
+  }
+
   /**
    * Returns the combined usage from model and comparable model.
    *
@@ -605,94 +687,6 @@ export class AppService
     return spectra;
   }
 
-  /**
-   * Returns the URL to call for a specific model.
-   *
-   * @param model The NSHM to call
-   * @param formValues The control panel form values
-   * @param nshmServices The NSHM service metadata
-   */
-  private serviceCallUrl(
-    model: NshmId,
-    formValues: ControlForm,
-    nshmServices: NshmMetadata[]
-  ): string {
-    const {latitude, longitude, vs30} = formValues;
-    const service = nshmServices.find(service => service.model === model);
-    return `${service.url}${this.serviceEndpoint}/${longitude}/${latitude}/${vs30}`;
-  }
-
-  private updateUrl(): void {
-    const value = this.formGroup.getRawValue();
-
-    const query: Query = {
-      imt: value.imt,
-      latitude: value.latitude?.toString(),
-      longitude: value.longitude?.toString(),
-      maxDirection: String(value.maxDirection),
-      model: value.model,
-      modelCompare: value.modelCompare,
-      returnPeriod: value.returnPeriod?.toString(),
-      siteClass: value.siteClass,
-      truncate: String(value.truncate),
-      vs30: value.vs30?.toString(),
-    };
-
-    this.router
-      .navigate([devApps().hazard.dynamicCompare.routerLink], {
-        queryParams: {
-          ...query,
-        },
-      })
-      .catch((error: Error) => this.nshmpService.throwError$(error));
-  }
-
-  /**
-   * Combine hazard usages with same region with common parameters.
-   *
-   * @param usages The usages with same region
-   */
-  combineUsages(usages: HazardUsageResponse[]): HazardUsageResponse {
-    const gmms = usages.map(usage => usage.response.model.gmms);
-    const imts = usages.map(usage => usage.response.model.imts);
-    const siteClasses = this.findCommonSiteClasses(
-      usages.map(usage => usage.response.model.siteClasses)
-    );
-    const usage = [...usages].shift();
-
-    const combinedUsage: HazardUsageResponse = {
-      ...usage,
-      response: {
-        latitude: {
-          ...usage.response.latitude,
-          max: Math.min(...usages.map(usage => usage.response.latitude.max)),
-          min: Math.max(...usages.map(usage => usage.response.latitude.min)),
-        },
-        longitude: {
-          ...usage.response.longitude,
-          max: Math.min(...usages.map(usage => usage.response.longitude.max)),
-          min: Math.max(...usages.map(usage => usage.response.longitude.min)),
-        },
-        model: {
-          bounds: usage.response.model.bounds,
-          gmms: gmms.reduce((previous, current) =>
-            previous.filter(gmm => current.includes(gmm))
-          ),
-          imts: this.findCommonImts(imts),
-          name: 'Combined usage',
-          siteClasses,
-        },
-        vs30: {
-          ...usage.response.vs30,
-          max: Math.min(...usages.map(usage => usage.response.vs30.max)),
-          min: Math.max(...usages.map(usage => usage.response.vs30.min)),
-        },
-      },
-    };
-
-    return combinedUsage;
-  }
-
   /**
    * Create the plots.
    *
@@ -721,54 +715,20 @@ export class AppService
   }
 
   /**
-   * Returns the common imts form array of parameters.
-   *
-   * @param imts The imt parameters
-   */
-  private findCommonImts(imts: Parameter[][]): Parameter[] {
-    return imts.reduce((previous, current) =>
-      previous.filter(previousParameter =>
-        current
-          .map(currentParameter => currentParameter.value)
-          .includes(previousParameter.value)
-      )
-    );
-  }
-
-  /**
-   * Returns the common site classes based on keys from an array of site class
-   * records.
+   * Returns the URL to call for a specific model.
    *
-   * @param siteClasses The site classes
-   */
-  private findCommonSiteClasses(
-    siteClasses: Record<string, number>[]
-  ): Record<string, number> {
-    const allSiteClasses = siteClasses.reduce((previous, current) => ({
-      ...previous,
-      ...current,
-    }));
-
-    const startingKeys = Object.keys(siteClasses.shift());
-
-    const keys = siteClasses.reduce((commonKeys, item) => {
-      return commonKeys.filter(key => Object.keys(item).includes(key));
-    }, startingKeys);
-
-    const commonSiteClasses: Record<string, number> = {};
-    keys.forEach(key => (commonSiteClasses[key] = allSiteClasses[key]));
-
-    return commonSiteClasses;
-  }
-
-  /**
-   * Returns the default plots with settings.
+   * @param model The NSHM to call
+   * @param formValues The control panel form values
+   * @param nshmServices The NSHM service metadata
    */
-  private defaultPlots(): Map<string, NshmpPlot> {
-    const plots = new Map<string, NshmpPlot>();
-    this.setHazardPlots(plots);
-    this.setSpectraPlots(plots);
-    return plots;
+  private serviceCallUrl(
+    model: NshmId,
+    formValues: ControlForm,
+    nshmServices: NshmMetadata[]
+  ): string {
+    const {latitude, longitude, vs30} = formValues;
+    const service = nshmServices.find(service => service.model === model);
+    return `${service.url}${this.serviceEndpoint}/${longitude}/${latitude}/${vs30}`;
   }
 
   /**
@@ -902,4 +862,44 @@ export class AppService
       }),
     });
   }
+
+  private updateUrl(): void {
+    const value = this.formGroup.getRawValue();
+
+    const query: Query = {
+      imt: value.imt,
+      latitude: value.latitude?.toString(),
+      longitude: value.longitude?.toString(),
+      maxDirection: String(value.maxDirection),
+      model: value.model,
+      modelCompare: value.modelCompare,
+      returnPeriod: value.returnPeriod?.toString(),
+      siteClass: value.siteClass,
+      truncate: String(value.truncate),
+      vs30: value.vs30?.toString(),
+    };
+
+    this.router
+      .navigate([devApps().hazard.dynamicCompare.routerLink], {
+        queryParams: {
+          ...query,
+        },
+      })
+      .catch((error: Error) => this.nshmpService.throwError$(error));
+  }
 }
+
+const plotOptions: PlotOptions = {
+  layout: {
+    aspectRatio: hazardUtils.HAZARD_ASPECT_RATIO,
+  },
+};
+const diffPlotOptions: PlotOptions = {
+  layout: {
+    aspectRatio: '3:1',
+    yaxis: {
+      range: [-100, 100],
+      type: 'linear',
+    },
+  },
+};
-- 
GitLab


From 9b312a92d6b46ca7e0f41f0fa044b68070393225 Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Thu, 7 Nov 2024 14:24:24 -0700
Subject: [PATCH 2/5] switch to iusing expansion panels component

---
 .../plot-settings-panel.component.ts          |  4 +-
 .../plot-settings-panel.component.html        | 17 +-----
 .../plot-settings-panel.component.ts          | 26 +++++---
 .../plot-settings-panel.component.html        | 19 +-----
 .../plot-settings-panel.component.ts          | 28 +++++----
 .../plot-settings-panel.component.html        | 27 +-------
 .../plot-settings-panel.component.ts          | 48 ++++++++-------
 .../plot-settings-panel.component.html        | 27 +-------
 .../plot-settings-panel.component.ts          | 50 +++++++--------
 .../plot-settings-panel.component.html        | 21 +------
 .../plot-settings-panel.component.ts          | 57 ++++++++---------
 .../plot-settings-panel.component.html        | 21 +------
 .../plot-settings-panel.component.ts          | 61 ++++++++-----------
 .../plot-settings-panel.component.html        | 21 +------
 .../plot-settings-panel.component.ts          | 39 +++++-------
 15 files changed, 159 insertions(+), 307 deletions(-)

diff --git a/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts
index 10fabb886..b2b7859cd 100644
--- a/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/designmaps/rtgm/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,4 +1,4 @@
-import {Component, computed, Signal} from '@angular/core';
+import {Component, computed} from '@angular/core';
 import {
   NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
@@ -15,7 +15,7 @@ import {AppService} from '../../services/app.service';
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  plots: Signal<PlotSettingsPlots[]> = computed(() => {
+  plots = computed<PlotSettingsPlots[]>(() => {
     const plots = this.service.plots();
     const defaultPlots = this.service.defaultPlots();
 
diff --git a/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.html
index 0c6afcf47..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,16 +1 @@
-<div class="height-full overflow-auto">
-  <!-- Exceedance plot settings -->
-  <nshmp-lib-ng-plot-settings
-    class="exceedance-settings"
-    [plot]="plot()"
-    (updatedPlot)="updatePlot($event)"
-  />
-
-  <div class="padding-y-3"></div>
-
-  <!-- Reset button -->
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetSettings()"
-    [resetDisabled]="plot().settingsForm.pristine"
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.ts
index b9cb06304..655368072 100644
--- a/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,9 +1,8 @@
-import {AsyncPipe} from '@angular/common';
-import {Component} from '@angular/core';
+import {Component, computed} from '@angular/core';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {Plots} from '../../models/plots.model';
@@ -13,11 +12,7 @@ import {AppService} from '../../services/app.service';
  * Plot settings control panel for the exceedance plot.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotSettingsComponent,
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    AsyncPipe,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
@@ -26,6 +21,19 @@ import {AppService} from '../../services/app.service';
 export class PlotSettingsPanelComponent {
   plot = this.service.plot;
 
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const plot = this.service.plot();
+    const defaultPlot = this.service.defaultPlots().get(Plots.EXCEEDANCE);
+
+    return [
+      {
+        defaultPlotSetting: defaultPlot.settingsForm.getRawValue(),
+        plot,
+        updatePlot: plot => this.updatePlot(plot),
+      },
+    ];
+  });
+
   constructor(public service: AppService) {}
 
   updatePlot(plot: NshmpPlot): void {
diff --git a/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.html
index 347425a11..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,18 +1 @@
-<div class="height-full overflow-auto">
-  @if (meanPlot()) {
-    <nshmp-lib-ng-plot-settings
-      class="distance-settings"
-      [plot]="meanPlot()"
-      (updatedPlot)="updatePlot($event)"
-    />
-  }
-
-  <div class="padding-y-3"></div>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetPlotSettings()"
-    [resetDisabled]="
-      meanPlotSettings()?.pristine && meanPlotSettings()?.untouched
-    "
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.ts
index 31f959434..836282f07 100644
--- a/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/gmm/distance/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,10 +1,9 @@
-import {AsyncPipe} from '@angular/common';
 import {Component, computed} from '@angular/core';
 import {gmmUtils} from '@ghsc/nshmp-lib-ng/gmm';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {AppService} from '../../services/app.service';
@@ -13,22 +12,27 @@ import {AppService} from '../../services/app.service';
  * Plot settings panel.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    NshmpLibNgPlotSettingsComponent,
-    AsyncPipe,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  /** Plot data */
-  meanPlot = this.service.meanPlotState;
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const plot = this.service.meanPlotState();
+    const defaultPlot = this.service
+      .defaultPlots()
+      .get(gmmUtils.PlotType.MEANS);
 
-  /** Plot settings */
-  meanPlotSettings = computed(() => this.service.meanPlotState()?.settingsForm);
+    return [
+      {
+        defaultPlotSetting: defaultPlot.settingsForm.getRawValue(),
+        plot,
+        updatePlot: plot => this.updatePlot(plot),
+      },
+    ];
+  });
 
   constructor(public service: AppService) {}
 
diff --git a/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.html
index 548aa51cb..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,26 +1 @@
-<div class="height-full overflow-auto">
-  @if (meanPlot()) {
-    <nshmp-lib-ng-plot-settings
-      [plot]="meanPlot()"
-      (updatedPlot)="updatePlot(PlotIds.MEANS, $event)"
-      class="mean-settings"
-    />
-  }
-
-  @if (sigmaPlot()) {
-    <nshmp-lib-ng-plot-settings
-      [plot]="sigmaPlot()"
-      (updatedPlot)="updatePlot(PlotIds.SIGMA, $event)"
-      class="sigma-settings"
-    />
-  }
-
-  <div class="padding-y-2"></div>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetPlotSettings()"
-    [resetDisabled]="
-      meanPlotSettings().pristine && sigmaPlotSettings().pristine
-    "
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.ts
index 7e809c808..6e7152f33 100644
--- a/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/gmm/magnitude/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,10 +1,9 @@
-import {AsyncPipe} from '@angular/common';
 import {Component, computed} from '@angular/core';
 import {gmmUtils} from '@ghsc/nshmp-lib-ng/gmm';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {AppService} from '../../services/app.service';
@@ -13,32 +12,35 @@ import {AppService} from '../../services/app.service';
  * Plot settings form fields.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    NshmpLibNgPlotSettingsComponent,
-    AsyncPipe,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  PlotIds = gmmUtils.PlotType;
-
-  /** Mean plot state */
-  meanPlot = this.service.meanPlotState;
-
-  /** Mean plot settings */
-  meanPlotSettings = computed(() => this.service.meanPlotState().settingsForm);
-
-  /** Sigma plot state */
-  sigmaPlot = this.service.sigmaPlotState;
-
-  /** Sigma plot settings */
-  sigmaPlotSettings = computed(
-    () => this.service.sigmaPlotState().settingsForm
-  );
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const meanPlot = this.service.meanPlotState();
+    const sigmaPlot = this.service.sigmaPlotState();
+    const defaultPlots = this.service.defaultPlots();
+
+    return [
+      {
+        defaultPlotSetting: defaultPlots
+          .get(gmmUtils.PlotType.MEANS)
+          .settingsForm.getRawValue(),
+        plot: meanPlot,
+        updatePlot: plot => this.updatePlot(gmmUtils.PlotType.MEANS, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(gmmUtils.PlotType.SIGMA)
+          .settingsForm.getRawValue(),
+        plot: sigmaPlot,
+        updatePlot: plot => this.updatePlot(gmmUtils.PlotType.SIGMA, plot),
+      },
+    ];
+  });
 
   constructor(public service: AppService) {}
 
diff --git a/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.html
index 3765a8198..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,26 +1 @@
-<div class="height-full overflow-auto">
-  @if (spectraPlot()) {
-    <nshmp-lib-ng-plot-settings
-      class="spectra-settings"
-      [plot]="spectraPlot()"
-      (updatedPlot)="updatePlot(PlotIds.MEANS, $event)"
-    />
-  }
-
-  @if (sigmaPlot()) {
-    <nshmp-lib-ng-plot-settings
-      class="sigma-settings"
-      [plot]="sigmaPlot()"
-      (updatedPlot)="updatePlot(PlotIds.SIGMA, $event)"
-    />
-  }
-
-  <div class="padding-y-3"></div>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetPlotSettings()"
-    [resetDisabled]="
-      spectraPlotSettings()?.pristine && sigmaPlotSettings()?.pristine
-    "
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.ts
index b757d7201..fcc18567e 100644
--- a/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/gmm/spectra/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,9 +1,8 @@
-import {AsyncPipe} from '@angular/common';
 import {Component, computed} from '@angular/core';
 import {gmmUtils} from '@ghsc/nshmp-lib-ng/gmm';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {SpectraPlot} from '../../models/spectra-plot.model';
@@ -13,34 +12,35 @@ import {AppService} from '../../services/app.service';
  * Plot settings form fields.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    NshmpLibNgPlotSettingsComponent,
-    AsyncPipe,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  PlotIds = gmmUtils.PlotType;
-
-  /** Mean plot state */
-  spectraPlot = this.service.spectraPlotState;
-
-  /** Mean plot settings */
-  spectraPlotSettings = computed(
-    () => this.service.spectraPlotState().settingsForm
-  );
-
-  /** Sigma plot state */
-  sigmaPlot = this.service.sigmaPlotState;
-
-  /** Sigma plot settings */
-  sigmaPlotSettings = computed(
-    () => this.service.sigmaPlotState().settingsForm
-  );
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const meanPlot = this.service.spectraPlotState();
+    const sigmaPlot = this.service.sigmaPlotState();
+    const defaultPlots = this.service.defaultPlots();
+
+    return [
+      {
+        defaultPlotSetting: defaultPlots
+          .get(gmmUtils.PlotType.MEANS)
+          .settingsForm.getRawValue(),
+        plot: meanPlot,
+        updatePlot: plot => this.updatePlot(gmmUtils.PlotType.MEANS, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(gmmUtils.PlotType.SIGMA)
+          .settingsForm.getRawValue(),
+        plot: sigmaPlot,
+        updatePlot: plot => this.updatePlot(gmmUtils.PlotType.SIGMA, plot),
+      },
+    ];
+  });
 
   constructor(public service: AppService) {}
 
diff --git a/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.html
index 6270e04fa..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,20 +1 @@
-<div class="height-full overflow-auto">
-  <mat-accordion multi>
-    @for (panel of panels; track panel) {
-      <mat-expansion-panel expanded>
-        <mat-expansion-panel-header>
-          <mat-panel-title>{{ panel.title }}</mat-panel-title>
-        </mat-expansion-panel-header>
-        <nshmp-lib-ng-plot-settings
-          [plot]="panel.plot()"
-          (updatedPlot)="updatePlot(panel.id, $event)"
-        />
-      </mat-expansion-panel>
-    }
-  </mat-accordion>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetSettings()"
-    [resetDisabled]="hazardSettings()?.pristine && spectrumSettings()?.pristine"
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.ts
index d789abad4..890bf8620 100644
--- a/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/hazard/dynamic/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,11 +1,9 @@
-import {Component} from '@angular/core';
-import {MatExpansionModule} from '@angular/material/expansion';
-import {HazardPlots} from '@ghsc/nshmp-lib-ng/hazard';
+import {Component, computed} from '@angular/core';
+import {HazardPlots, hazardUtils} from '@ghsc/nshmp-lib-ng/hazard';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
-  PlotSettingsPanel,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {AppService} from '../../services/app.service';
@@ -14,38 +12,35 @@ import {AppService} from '../../services/app.service';
  * Plot settings panel.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotSettingsComponent,
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    MatExpansionModule,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  /** Hazard plot state */
-  hazardPlot = this.service.hazardPlotState;
-  /** Hazard plot settings */
-  hazardSettings = this.service.hazardPlotSettings;
-  /** Spectra plot state */
-  spectrumPlot = this.service.spectrumPlotState;
-  /** Spectra plot settings */
-  spectrumSettings = this.service.spectrumPlotSettings;
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const hazardPlot = this.service.hazardPlotState();
+    const spectrumPlot = this.service.spectrumPlotState();
+    const defaultPlots = hazardUtils.hazardDefaultPlots();
 
-  panels: PlotSettingsPanel[] = [
-    {
-      id: HazardPlots.HAZARD,
-      plot: this.hazardPlot,
-      title: 'Hazard Curves Plot Settings',
-    },
-    {
-      id: HazardPlots.SPECTRUM,
-      plot: this.spectrumPlot,
-      title: 'Spectra Plot Settings',
-    },
-  ];
+    return [
+      {
+        defaultPlotSetting: defaultPlots
+          .get(HazardPlots.HAZARD)
+          .settingsForm.getRawValue(),
+        plot: hazardPlot,
+        updatePlot: plot => this.updatePlot(HazardPlots.HAZARD, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(HazardPlots.SPECTRUM)
+          .settingsForm.getRawValue(),
+        plot: spectrumPlot,
+        updatePlot: plot => this.updatePlot(HazardPlots.SPECTRUM, plot),
+      },
+    ];
+  });
 
   constructor(public service: AppService) {}
 
diff --git a/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.html
index 6270e04fa..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,20 +1 @@
-<div class="height-full overflow-auto">
-  <mat-accordion multi>
-    @for (panel of panels; track panel) {
-      <mat-expansion-panel expanded>
-        <mat-expansion-panel-header>
-          <mat-panel-title>{{ panel.title }}</mat-panel-title>
-        </mat-expansion-panel-header>
-        <nshmp-lib-ng-plot-settings
-          [plot]="panel.plot()"
-          (updatedPlot)="updatePlot(panel.id, $event)"
-        />
-      </mat-expansion-panel>
-    }
-  </mat-accordion>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetSettings()"
-    [resetDisabled]="hazardSettings()?.pristine && spectrumSettings()?.pristine"
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.ts
index 8e1db4460..429ecc2e5 100644
--- a/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/hazard/static/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,12 +1,9 @@
-import {AsyncPipe} from '@angular/common';
-import {Component} from '@angular/core';
-import {MatExpansionModule} from '@angular/material/expansion';
-import {HazardPlots} from '@ghsc/nshmp-lib-ng/hazard';
+import {Component, computed} from '@angular/core';
+import {HazardPlots, hazardUtils} from '@ghsc/nshmp-lib-ng/hazard';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
-  PlotSettingsPanel,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {AppService} from '../../services/app.service';
@@ -15,41 +12,35 @@ import {AppService} from '../../services/app.service';
  * Plot settings panel.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotSettingsComponent,
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    AsyncPipe,
-    MatExpansionModule,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  /** Hazard plot state */
-  private hazardPlot = this.service.hazardPlotState;
-  /** Spectra plot state */
-  private spectrumPlot = this.service.spectrumPlotState;
-
-  /** Hazard plot settings */
-  hazardSettings = this.service.hazardPlotSettings;
-  /** Spectra plot settings */
-  spectrumSettings = this.service.spectrumPlotSettings;
-
-  panels: PlotSettingsPanel[] = [
-    {
-      id: HazardPlots.HAZARD,
-      plot: this.hazardPlot,
-      title: 'Hazard Curves Plot Settings',
-    },
-    {
-      id: HazardPlots.SPECTRUM,
-      plot: this.spectrumPlot,
-      title: 'Spectra Plot Settings',
-    },
-  ];
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const hazardPlot = this.service.hazardPlotState();
+    const spectrumPlot = this.service.spectrumPlotState();
+    const defaultPlots = hazardUtils.hazardDefaultPlots();
 
+    return [
+      {
+        defaultPlotSetting: defaultPlots
+          .get(HazardPlots.HAZARD)
+          .settingsForm.getRawValue(),
+        plot: hazardPlot,
+        updatePlot: plot => this.updatePlot(HazardPlots.HAZARD, plot),
+      },
+      {
+        defaultPlotSetting: defaultPlots
+          .get(HazardPlots.SPECTRUM)
+          .settingsForm.getRawValue(),
+        plot: spectrumPlot,
+        updatePlot: plot => this.updatePlot(HazardPlots.SPECTRUM, plot),
+      },
+    ];
+  });
   constructor(public service: AppService) {}
 
   updatePlot(id: string, plot: NshmpPlot): void {
diff --git a/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.html b/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.html
index e6ec58479..04a8e478c 100644
--- a/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.html
+++ b/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.html
@@ -1,20 +1 @@
-<div class="height-full overflow-auto">
-  <mat-accordion multi>
-    @for (panel of panels; track panel) {
-      <mat-expansion-panel expanded>
-        <mat-expansion-panel-header>
-          <mat-panel-title>{{ panel.title }}</mat-panel-title>
-        </mat-expansion-panel-header>
-        <nshmp-lib-ng-plot-settings
-          [plot]="panel.plot()"
-          (updatedPlot)="updatePlot(panel.id, $event)"
-        />
-      </mat-expansion-panel>
-    }
-  </mat-accordion>
-
-  <nshmp-lib-ng-plot-reset-plot-settings
-    (resetClick)="service.resetSettings()"
-    [resetDisabled]="mfdSettings()?.pristine"
-  />
-</div>
+<nshmp-lib-ng-plot-settings-expansion-panel [plots]="plots()" />
diff --git a/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.ts b/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.ts
index 0b1a20257..78562d0eb 100644
--- a/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.ts
+++ b/projects/nshmp-apps/src/app/source/mfd/components/plot-settings-panel/plot-settings-panel.component.ts
@@ -1,11 +1,8 @@
-import {AsyncPipe} from '@angular/common';
-import {Component} from '@angular/core';
-import {MatExpansionModule} from '@angular/material/expansion';
+import {Component, computed} from '@angular/core';
 import {
-  NshmpLibNgPlotResetPlotSettingsComponent,
-  NshmpLibNgPlotSettingsComponent,
+  NshmpLibNgPlotSettingsExpansionPanelComponent,
   NshmpPlot,
-  PlotSettingsPanel,
+  PlotSettingsPlots,
 } from '@ghsc/nshmp-lib-ng/plot';
 
 import {Plots} from '../../models/plots.model';
@@ -15,31 +12,25 @@ import {AppService} from '../../services/app.service';
  * Plot settings panel.
  */
 @Component({
-  imports: [
-    NshmpLibNgPlotSettingsComponent,
-    NshmpLibNgPlotResetPlotSettingsComponent,
-    AsyncPipe,
-    MatExpansionModule,
-  ],
+  imports: [NshmpLibNgPlotSettingsExpansionPanelComponent],
   selector: 'app-plot-settings-panel',
   standalone: true,
   styleUrl: './plot-settings-panel.component.scss',
   templateUrl: './plot-settings-panel.component.html',
 })
 export class PlotSettingsPanelComponent {
-  /** MFD plot state */
-  private mfdPlot = this.service.mfdPlotState;
+  plots = computed<PlotSettingsPlots[]>(() => {
+    const plot = this.service.mfdPlotState();
+    const defaultPlot = this.service.defaultPlots().get(Plots.MFD);
 
-  /** MFD plot settings state */
-  mfdSettings = this.service.mfdPlotSettings;
-
-  panels: PlotSettingsPanel[] = [
-    {
-      id: Plots.MFD,
-      plot: this.mfdPlot,
-      title: 'MFD Plot Settings',
-    },
-  ];
+    return [
+      {
+        defaultPlotSetting: defaultPlot.settingsForm.getRawValue(),
+        plot,
+        updatePlot: plot => this.updatePlot(Plots.MFD, plot),
+      },
+    ];
+  });
 
   constructor(public service: AppService) {}
 
-- 
GitLab


From 76a41ea3d7e0d1c364a619e10c55fb755a9589c5 Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Thu, 7 Nov 2024 14:24:55 -0700
Subject: [PATCH 3/5] make default plots public

---
 .../services/app.service.ts                   | 103 +++++-----
 .../app/gmm/distance/services/app.service.ts  |  62 +++---
 .../app/gmm/magnitude/services/app.service.ts | 146 ++++++-------
 .../app/gmm/spectra/services/app.service.ts   | 176 ++++++++--------
 .../app/source/mfd/services/app.service.ts    | 193 +++++++++---------
 5 files changed, 340 insertions(+), 340 deletions(-)

diff --git a/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/services/app.service.ts b/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/services/app.service.ts
index 2787b5439..00d2d501f 100644
--- a/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/dev/math/exceedance-explorer/services/app.service.ts
@@ -34,7 +34,6 @@ export class AppService
   readonly formGroup = this.formBuilder.group<ControlForm>(
     this.defaultFormValues()
   );
-
   readonly state = signal<AppState>(this.initialState());
 
   constructor(private formBuilder: FormBuilder) {
@@ -98,6 +97,57 @@ export class AppService
     };
   }
 
+  defaultPlots(): Map<string, NshmpPlot> {
+    const plots = new Map<string, NshmpPlot>();
+
+    const plotOptions: PlotOptions = {
+      layout: {
+        legend: {
+          bordercolor: ' #a9aeb1',
+          borderwidth: 1,
+          x: 0.01,
+          y: 0.1,
+          yanchor: 'bottom',
+        },
+        yaxis: {
+          range: [0, 1],
+          tickmode: 'auto',
+          type: 'linear',
+        },
+      },
+    };
+
+    const plotData = plotUtils.defaultPlot({
+      id: 'exceedance-explorer',
+      mobileOptions: {
+        ...plotOptions,
+        layout: {
+          ...plotOptions.layout,
+          margin: {
+            b: 50,
+          },
+        },
+      },
+      options: {...plotOptions},
+      title: 'Exceedance',
+      xLabel: 'Ground Motion (g)',
+      yLabel: 'Annual Frequency of Exceedence',
+    });
+
+    const settingsForm: NshmpPlotSettings = {
+      config: plotData.config,
+      layout: plotUtils.plotlyLayoutToSettings(plotData.layout),
+    };
+
+    plots.set(Plots.EXCEEDANCE, {
+      label: 'Exceedance',
+      plotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup(settingsForm),
+    });
+
+    return plots;
+  }
+
   /**
    * Exceedance X values for plot.
    */
@@ -241,55 +291,4 @@ export class AppService
       y: yValues.map(y => Maths.round(y * values.rate, 4)),
     };
   }
-
-  private defaultPlots(): Map<string, NshmpPlot> {
-    const plots = new Map<string, NshmpPlot>();
-
-    const plotOptions: PlotOptions = {
-      layout: {
-        legend: {
-          bordercolor: ' #a9aeb1',
-          borderwidth: 1,
-          x: 0.01,
-          y: 0.1,
-          yanchor: 'bottom',
-        },
-        yaxis: {
-          range: [0, 1],
-          tickmode: 'auto',
-          type: 'linear',
-        },
-      },
-    };
-
-    const plotData = plotUtils.defaultPlot({
-      id: 'exceedance-explorer',
-      mobileOptions: {
-        ...plotOptions,
-        layout: {
-          ...plotOptions.layout,
-          margin: {
-            b: 50,
-          },
-        },
-      },
-      options: {...plotOptions},
-      title: 'Exceedance',
-      xLabel: 'Ground Motion (g)',
-      yLabel: 'Annual Frequency of Exceedence',
-    });
-
-    const settingsForm: NshmpPlotSettings = {
-      config: plotData.config,
-      layout: plotUtils.plotlyLayoutToSettings(plotData.layout),
-    };
-
-    plots.set(Plots.EXCEEDANCE, {
-      label: 'Exceedance',
-      plotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup(settingsForm),
-    });
-
-    return plots;
-  }
 }
diff --git a/projects/nshmp-apps/src/app/gmm/distance/services/app.service.ts b/projects/nshmp-apps/src/app/gmm/distance/services/app.service.ts
index 28e81a3f0..15e16e663 100644
--- a/projects/nshmp-apps/src/app/gmm/distance/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/gmm/distance/services/app.service.ts
@@ -206,6 +206,37 @@ export class AppService
     };
   }
 
+  /**
+   * Returns the default plots.
+   */
+  defaultPlots(): Map<string, NshmpPlot> {
+    const plots = new Map<string, NshmpPlot>();
+
+    const meansPlotData = plotUtils.defaultPlot({
+      id: gmmUtils.PlotType.MEANS,
+      options: {
+        layout: {
+          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
+        },
+      },
+      title: 'Ground Motion vs. Distance',
+      xLabel: 'Distance (km)',
+      yLabel: 'Median ground motion (g)',
+    });
+
+    const meansPlotSettingsForm: NshmpPlotSettings = {
+      config: meansPlotData.config,
+      layout: plotUtils.plotlyLayoutToSettings(meansPlotData.layout),
+    };
+    plots.set(gmmUtils.PlotType.MEANS, {
+      label: 'Means',
+      plotData: meansPlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup(meansPlotSettingsForm),
+    });
+
+    return new Map(plots);
+  }
+
   /**
    * Initialize the application.
    */
@@ -310,37 +341,6 @@ export class AppService
     };
   }
 
-  /**
-   * Returns the default plots.
-   */
-  private defaultPlots(): Map<string, NshmpPlot> {
-    const plots = new Map<string, NshmpPlot>();
-
-    const meansPlotData = plotUtils.defaultPlot({
-      id: gmmUtils.PlotType.MEANS,
-      options: {
-        layout: {
-          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
-        },
-      },
-      title: 'Ground Motion vs. Distance',
-      xLabel: 'Distance (km)',
-      yLabel: 'Median ground motion (g)',
-    });
-
-    const meansPlotSettingsForm: NshmpPlotSettings = {
-      config: meansPlotData.config,
-      layout: plotUtils.plotlyLayoutToSettings(meansPlotData.layout),
-    };
-    plots.set(gmmUtils.PlotType.MEANS, {
-      label: 'Means',
-      plotData: meansPlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup(meansPlotSettingsForm),
-    });
-
-    return new Map(plots);
-  }
-
   private handleServiceResponses(
     serviceResponses: GmmDistanceResponse[]
   ): void {
diff --git a/projects/nshmp-apps/src/app/gmm/magnitude/services/app.service.ts b/projects/nshmp-apps/src/app/gmm/magnitude/services/app.service.ts
index 2fd233423..3f25429b0 100644
--- a/projects/nshmp-apps/src/app/gmm/magnitude/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/gmm/magnitude/services/app.service.ts
@@ -217,6 +217,79 @@ export class AppService
     };
   }
 
+  /**
+   * Returns the default plots.
+   */
+  defaultPlots(): Map<string, NshmpPlot> {
+    const plots = new Map<string, NshmpPlot>();
+
+    const plotOptions: PlotOptions = {
+      layout: {
+        xaxis: {
+          nticks: 10,
+          range: [Math.log10(5), Math.log10(8)],
+        },
+        yaxis: {
+          range: [Math.log10(0.001), Math.log10(3)],
+        },
+      },
+    };
+
+    const meanPlotData = plotUtils.defaultPlot({
+      id: gmmUtils.PlotType.MEANS,
+      mobileOptions: {...plotOptions},
+      options: {
+        ...plotOptions,
+        layout: {
+          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
+          ...plotOptions.layout,
+        },
+      },
+      title: 'Ground Motion vs. Magnitude',
+      xLabel: 'Magnitude',
+      yLabel: 'Median ground motion (g)',
+    });
+
+    const sigmaPlotData = plotUtils.defaultPlot({
+      id: gmmUtils.PlotType.SIGMA,
+      mobileOptions: {...plotOptions},
+      options: {
+        ...plotOptions,
+        layout: {
+          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
+          ...plotOptions.layout,
+        },
+      },
+      title: 'Standard Deviation',
+      xLabel: 'Magnitude',
+      yLabel: 'Standard deviation',
+    });
+
+    /** Default mean settings */
+    const meanSettingsForm: NshmpPlotSettings = {
+      config: meanPlotData.config,
+      layout: plotUtils.plotlyLayoutToSettings(meanPlotData.layout),
+    };
+
+    /** Default sigma settings */
+    const sigmaSettingsForm: NshmpPlotSettings = {
+      config: sigmaPlotData.config,
+      layout: plotUtils.plotlyLayoutToSettings(sigmaPlotData.layout),
+    };
+    plots.set(gmmUtils.PlotType.MEANS, {
+      label: 'Response Spectra',
+      plotData: meanPlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup(meanSettingsForm),
+    });
+    plots.set(gmmUtils.PlotType.SIGMA, {
+      label: 'Standard Deviation',
+      plotData: sigmaPlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup(sigmaSettingsForm),
+    });
+
+    return new Map(plots);
+  }
+
   /**
    * Initialize the application.
    */
@@ -303,79 +376,6 @@ export class AppService
     });
   }
 
-  /**
-   * Returns the default plots.
-   */
-  private defaultPlots(): Map<string, NshmpPlot> {
-    const plots = new Map<string, NshmpPlot>();
-
-    const plotOptions: PlotOptions = {
-      layout: {
-        xaxis: {
-          nticks: 10,
-          range: [Math.log10(5), Math.log10(8)],
-        },
-        yaxis: {
-          range: [Math.log10(0.001), Math.log10(3)],
-        },
-      },
-    };
-
-    const meanPlotData = plotUtils.defaultPlot({
-      id: gmmUtils.PlotType.MEANS,
-      mobileOptions: {...plotOptions},
-      options: {
-        ...plotOptions,
-        layout: {
-          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
-          ...plotOptions.layout,
-        },
-      },
-      title: 'Ground Motion vs. Magnitude',
-      xLabel: 'Magnitude',
-      yLabel: 'Median ground motion (g)',
-    });
-
-    const sigmaPlotData = plotUtils.defaultPlot({
-      id: gmmUtils.PlotType.SIGMA,
-      mobileOptions: {...plotOptions},
-      options: {
-        ...plotOptions,
-        layout: {
-          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
-          ...plotOptions.layout,
-        },
-      },
-      title: 'Standard Deviation',
-      xLabel: 'Magnitude',
-      yLabel: 'Standard deviation',
-    });
-
-    /** Default mean settings */
-    const meanSettingsForm: NshmpPlotSettings = {
-      config: meanPlotData.config,
-      layout: plotUtils.plotlyLayoutToSettings(meanPlotData.layout),
-    };
-
-    /** Default sigma settings */
-    const sigmaSettingsForm: NshmpPlotSettings = {
-      config: sigmaPlotData.config,
-      layout: plotUtils.plotlyLayoutToSettings(sigmaPlotData.layout),
-    };
-    plots.set(gmmUtils.PlotType.MEANS, {
-      label: 'Response Spectra',
-      plotData: meanPlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup(meanSettingsForm),
-    });
-    plots.set(gmmUtils.PlotType.SIGMA, {
-      label: 'Standard Deviation',
-      plotData: sigmaPlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup(sigmaSettingsForm),
-    });
-
-    return new Map(plots);
-  }
-
   private handleServiceResponses(
     serviceResponses: GmmMagnitudeResponse[]
   ): void {
diff --git a/projects/nshmp-apps/src/app/gmm/spectra/services/app.service.ts b/projects/nshmp-apps/src/app/gmm/spectra/services/app.service.ts
index df47b0b27..869346cef 100644
--- a/projects/nshmp-apps/src/app/gmm/spectra/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/gmm/spectra/services/app.service.ts
@@ -333,6 +333,94 @@ export class AppService
     };
   }
 
+  /**
+   * Returns the default plots.
+   */
+  defaultPlots(): Map<string, SpectraPlot> {
+    const plots = new Map<string, NshmpPlot>();
+
+    const plotOptions: PlotOptions = {
+      layout: {
+        xaxis: {
+          range: [Math.log10(0.075), Math.log10(12)],
+        },
+        yaxis: {
+          range: [Math.log10(0.001), Math.log10(3)],
+        },
+      },
+    };
+
+    /** Default mean plot data */
+    const meanPlotData = plotUtils.defaultPlot({
+      id: gmmUtils.PlotType.MEANS,
+      mobileOptions: {...plotOptions},
+      options: {
+        ...plotOptions,
+        layout: {
+          ...plotOptions.layout,
+          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
+        },
+      },
+      title: 'Medians',
+      xLabel: 'Period (s)',
+      yLabel: 'Median ground motion (g)',
+    });
+
+    /** Default sigma plot data */
+    const sigmaPlotData = plotUtils.defaultPlot({
+      id: gmmUtils.PlotType.SIGMA,
+      mobileOptions: {
+        ...plotOptions,
+        layout: {
+          ...plotOptions.layout,
+          yaxis: {
+            ...plotOptions.layout.yaxis,
+            range: [0, 1.5],
+          },
+        },
+      },
+      options: {
+        ...plotOptions,
+        layout: {
+          ...plotOptions.layout,
+          aspectRatio: gmmUtils.SIGMA_ASPECT_RATIO,
+          yaxis: {
+            ...plotOptions.layout.yaxis,
+            range: [0, 1.5],
+          },
+        },
+      },
+      title: 'Standard Deviations',
+      xLabel: 'Period (s)',
+      yLabel: 'Standard deviation',
+    });
+
+    /** Default mean settings */
+    const meanSettingsForm: NshmpPlotSettings = {
+      config: meanPlotData.config,
+      layout: plotUtils.plotlyLayoutToSettings(meanPlotData.layout),
+    };
+
+    /** Default sigma settings */
+    const sigmaSettingsForm: NshmpPlotSettings = {
+      config: sigmaPlotData.config,
+      layout: plotUtils.plotlyLayoutToSettings(sigmaPlotData.layout),
+    };
+    plots.set(gmmUtils.PlotType.MEANS, {
+      label: 'Response Spectra',
+      plotData: meanPlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup(meanSettingsForm),
+    });
+
+    plots.set(gmmUtils.PlotType.SIGMA, {
+      label: 'Standard Deviation',
+      plotData: sigmaPlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup(sigmaSettingsForm),
+    });
+
+    return new Map(plots);
+  }
+
   /**
    * Initialize the application.
    */
@@ -421,94 +509,6 @@ export class AppService
     });
   }
 
-  /**
-   * Returns the default plots.
-   */
-  private defaultPlots(): Map<string, SpectraPlot> {
-    const plots = new Map<string, NshmpPlot>();
-
-    const plotOptions: PlotOptions = {
-      layout: {
-        xaxis: {
-          range: [Math.log10(0.075), Math.log10(12)],
-        },
-        yaxis: {
-          range: [Math.log10(0.001), Math.log10(3)],
-        },
-      },
-    };
-
-    /** Default mean plot data */
-    const meanPlotData = plotUtils.defaultPlot({
-      id: gmmUtils.PlotType.MEANS,
-      mobileOptions: {...plotOptions},
-      options: {
-        ...plotOptions,
-        layout: {
-          ...plotOptions.layout,
-          aspectRatio: gmmUtils.MEAN_ASPECT_RATIO,
-        },
-      },
-      title: 'Medians',
-      xLabel: 'Period (s)',
-      yLabel: 'Median ground motion (g)',
-    });
-
-    /** Default sigma plot data */
-    const sigmaPlotData = plotUtils.defaultPlot({
-      id: gmmUtils.PlotType.SIGMA,
-      mobileOptions: {
-        ...plotOptions,
-        layout: {
-          ...plotOptions.layout,
-          yaxis: {
-            ...plotOptions.layout.yaxis,
-            range: [0, 1.5],
-          },
-        },
-      },
-      options: {
-        ...plotOptions,
-        layout: {
-          ...plotOptions.layout,
-          aspectRatio: gmmUtils.SIGMA_ASPECT_RATIO,
-          yaxis: {
-            ...plotOptions.layout.yaxis,
-            range: [0, 1.5],
-          },
-        },
-      },
-      title: 'Standard Deviations',
-      xLabel: 'Period (s)',
-      yLabel: 'Standard deviation',
-    });
-
-    /** Default mean settings */
-    const meanSettingsForm: NshmpPlotSettings = {
-      config: meanPlotData.config,
-      layout: plotUtils.plotlyLayoutToSettings(meanPlotData.layout),
-    };
-
-    /** Default sigma settings */
-    const sigmaSettingsForm: NshmpPlotSettings = {
-      config: sigmaPlotData.config,
-      layout: plotUtils.plotlyLayoutToSettings(sigmaPlotData.layout),
-    };
-    plots.set(gmmUtils.PlotType.MEANS, {
-      label: 'Response Spectra',
-      plotData: meanPlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup(meanSettingsForm),
-    });
-
-    plots.set(gmmUtils.PlotType.SIGMA, {
-      label: 'Standard Deviation',
-      plotData: sigmaPlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup(sigmaSettingsForm),
-    });
-
-    return new Map(plots);
-  }
-
   private handleServiceResponses(serviceResponses: GmmSpectraResponse[]): void {
     const means = serviceResponses.map(s => s.response.means);
     const sigmas = serviceResponses.map(s => s.response.sigmas);
diff --git a/projects/nshmp-apps/src/app/source/mfd/services/app.service.ts b/projects/nshmp-apps/src/app/source/mfd/services/app.service.ts
index 5dea22443..9d95d18d7 100644
--- a/projects/nshmp-apps/src/app/source/mfd/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/source/mfd/services/app.service.ts
@@ -99,6 +99,7 @@ export class AppService
   readonly formGroup = this.formBuilder.group<ControlForm>(
     this.defaultFormValues()
   );
+
   /** Application state */
   readonly state = signal<AppState>(this.initialState());
 
@@ -262,6 +263,102 @@ export class AppService
     };
   }
 
+  /**
+   * Returns the default plots.
+   */
+  defaultPlots(): Map<string, NshmpPlot> {
+    const plots = new Map<string, NshmpPlot>();
+
+    const logicTreeOptions: PlotOptions = {
+      layout: {
+        aspectRatio: undefined,
+        margin: {
+          b: 10,
+          l: 10,
+          r: 10,
+        },
+      },
+    };
+
+    const plotOptions: PlotOptions = {
+      layout: {
+        xaxis: {
+          nticks: 10,
+          range: [6.5, 7.7],
+          type: 'linear',
+        },
+        yaxis: {
+          type: 'log',
+        },
+      },
+    };
+
+    /** Default logic tree plot data */
+    const logicTreePlotData: PlotlyPlot = {
+      ...plotUtils.defaultPlot({
+        id: 'mfd-logic-tree',
+        mobileOptions: {...logicTreeOptions},
+        options: {...logicTreeOptions},
+        title: 'MFD Logic Tree',
+        xLabel: '',
+        yLabel: '',
+      }),
+      data: [
+        {
+          labels: ['Logic Tree Branches'],
+          parents: [''],
+          type: 'treemap',
+        },
+      ],
+    };
+
+    /** Default MFD plot data */
+    const mfdPlotData = plotUtils.defaultPlot({
+      id: 'mfd-plot',
+      mobileOptions: {
+        ...plotOptions,
+        layout: {
+          ...plotOptions.layout,
+          aspectRatio: '1:1',
+        },
+      },
+      options: {
+        ...plotOptions,
+        layout: {
+          ...plotOptions.layout,
+          legend: {
+            font: {
+              size: 11,
+            },
+          },
+        },
+      },
+      title: 'Magnitude Frequency Distribution',
+      xLabel: 'Magnitude',
+      yLabel: 'Rate (yr<sup>-1</sup>)',
+    });
+
+    plots.set(Plots.MFD, {
+      label: 'MFD',
+      plotData: mfdPlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup({
+        config: mfdPlotData.config,
+        layout: plotUtils.plotlyLayoutToSettings(mfdPlotData.layout),
+      }),
+    });
+
+    plots.set(Plots.LOGIC_TREE, {
+      label: Plots.LOGIC_TREE,
+      plotData: logicTreePlotData,
+      settingsForm: plotUtils.plotSettingsToFormGroup({
+        config: logicTreePlotData.config,
+        layout: plotUtils.plotlyLayoutToSettings(logicTreePlotData.layout),
+      }),
+    });
+
+    return plots;
+  }
+
   /**
    * Return the feault source to use from settings groups.
    *
@@ -447,102 +544,6 @@ export class AppService
     return `${serviceUrl}/${sourceTree}`;
   }
 
-  /**
-   * Returns the default plots.
-   */
-  private defaultPlots(): Map<string, NshmpPlot> {
-    const plots = new Map<string, NshmpPlot>();
-
-    const logicTreeOptions: PlotOptions = {
-      layout: {
-        aspectRatio: undefined,
-        margin: {
-          b: 10,
-          l: 10,
-          r: 10,
-        },
-      },
-    };
-
-    const plotOptions: PlotOptions = {
-      layout: {
-        xaxis: {
-          nticks: 10,
-          range: [6.5, 7.7],
-          type: 'linear',
-        },
-        yaxis: {
-          type: 'log',
-        },
-      },
-    };
-
-    /** Default logic tree plot data */
-    const logicTreePlotData: PlotlyPlot = {
-      ...plotUtils.defaultPlot({
-        id: 'mfd-logic-tree',
-        mobileOptions: {...logicTreeOptions},
-        options: {...logicTreeOptions},
-        title: 'MFD Logic Tree',
-        xLabel: '',
-        yLabel: '',
-      }),
-      data: [
-        {
-          labels: ['Logic Tree Branches'],
-          parents: [''],
-          type: 'treemap',
-        },
-      ],
-    };
-
-    /** Default MFD plot data */
-    const mfdPlotData = plotUtils.defaultPlot({
-      id: 'mfd-plot',
-      mobileOptions: {
-        ...plotOptions,
-        layout: {
-          ...plotOptions.layout,
-          aspectRatio: '1:1',
-        },
-      },
-      options: {
-        ...plotOptions,
-        layout: {
-          ...plotOptions.layout,
-          legend: {
-            font: {
-              size: 11,
-            },
-          },
-        },
-      },
-      title: 'Magnitude Frequency Distribution',
-      xLabel: 'Magnitude',
-      yLabel: 'Rate (yr<sup>-1</sup>)',
-    });
-
-    plots.set(Plots.MFD, {
-      label: 'MFD',
-      plotData: mfdPlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup({
-        config: mfdPlotData.config,
-        layout: plotUtils.plotlyLayoutToSettings(mfdPlotData.layout),
-      }),
-    });
-
-    plots.set(Plots.LOGIC_TREE, {
-      label: Plots.LOGIC_TREE,
-      plotData: logicTreePlotData,
-      settingsForm: plotUtils.plotSettingsToFormGroup({
-        config: logicTreePlotData.config,
-        layout: plotUtils.plotlyLayoutToSettings(logicTreePlotData.layout),
-      }),
-    });
-
-    return plots;
-  }
-
   /**
    * Return the matching setting group from a {@link MfdSource#tectonicSettings}.
    *
-- 
GitLab


From 921e0e8a4e1e75d64cdecd2ede9a06eb21552c4d Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Thu, 7 Nov 2024 16:00:22 -0700
Subject: [PATCH 4/5] use color length

---
 .../src/app/designmaps/rtgm/services/app.service.ts           | 4 ++--
 .../hazard/dynamic-compare/services/hazard-plots.service.ts   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/projects/nshmp-apps/src/app/designmaps/rtgm/services/app.service.ts b/projects/nshmp-apps/src/app/designmaps/rtgm/services/app.service.ts
index 0b11d9762..1f6f3523c 100644
--- a/projects/nshmp-apps/src/app/designmaps/rtgm/services/app.service.ts
+++ b/projects/nshmp-apps/src/app/designmaps/rtgm/services/app.service.ts
@@ -490,7 +490,7 @@ export class AppService
     const colors = this.colorScale(iterations);
 
     iterations.forEach((iteration, index) => {
-      const color = colors[index % iterations.length];
+      const color = colors[index % colors.length];
 
       const fragilityXy: XySequence = {
         xs: imls,
@@ -602,7 +602,7 @@ export class AppService
     const colors = this.colorScale(iterations);
 
     iterations.forEach((iteration, index) => {
-      const color = colors[index % iterations.length];
+      const color = colors[index % colors.length];
 
       const name =
         index === iterations.length - 1
diff --git a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/hazard-plots.service.ts b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/hazard-plots.service.ts
index 7ec681590..67dba0653 100644
--- a/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/hazard-plots.service.ts
+++ b/projects/nshmp-apps/src/app/dev/hazard/dynamic-compare/services/hazard-plots.service.ts
@@ -383,7 +383,7 @@ export class HazardPlotsService {
     let count = 0;
 
     return hazardCurves.map(data => {
-      const color = colors[count++ % hazardCurves.length];
+      const color = colors[count++ % colors.length];
 
       const xy = hazardUtils.updateXySequence(
         options.form,
-- 
GitLab


From 8071e065847a13f8e2512bd1f41db550b45b34ed Mon Sep 17 00:00:00 2001
From: Brandon Clayton <bclayton@usgs.gov>
Date: Fri, 8 Nov 2024 12:14:06 -0700
Subject: [PATCH 5/5] update deps

---
 package-lock.json | 8 ++++----
 package.json      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 15beffb4b..03a0f8b26 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,7 +21,7 @@
         "@asymmetrik/ngx-leaflet": "^18.0.1",
         "@compodoc/compodoc": "^1.1.25",
         "@ghsc/disagg-d3": "^0.13.0",
-        "@ghsc/nshmp-lib-ng": "^18.20.1",
+        "@ghsc/nshmp-lib-ng": "^18.20.2",
         "@ghsc/nshmp-template": "^18.0.3",
         "@ghsc/nshmp-utils-ts": "^3.11.1",
         "angular-plotly.js": "^6.0.0",
@@ -4315,9 +4315,9 @@
       }
     },
     "node_modules/@ghsc/nshmp-lib-ng": {
-      "version": "18.20.1",
-      "resolved": "https://code.usgs.gov/api/v4/projects/12416/packages/npm/@ghsc/nshmp-lib-ng/-/@ghsc/nshmp-lib-ng-18.20.1.tgz",
-      "integrity": "sha1-Fl7/qeQj4hVkE99jiJYQQE3on3Q=",
+      "version": "18.20.2",
+      "resolved": "https://code.usgs.gov/api/v4/projects/12416/packages/npm/@ghsc/nshmp-lib-ng/-/@ghsc/nshmp-lib-ng-18.20.2.tgz",
+      "integrity": "sha1-IphheXnX0ZjUYmu+7o1x/Pv0oVk=",
       "dependencies": {
         "tslib": "^2.3.0"
       },
diff --git a/package.json b/package.json
index 2d98cd09a..18c9dd2ac 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
     "@asymmetrik/ngx-leaflet": "^18.0.1",
     "@compodoc/compodoc": "^1.1.25",
     "@ghsc/disagg-d3": "^0.13.0",
-    "@ghsc/nshmp-lib-ng": "^18.20.1",
+    "@ghsc/nshmp-lib-ng": "^18.20.2",
     "@ghsc/nshmp-template": "^18.0.3",
     "@ghsc/nshmp-utils-ts": "^3.11.1",
     "angular-plotly.js": "^6.0.0",
-- 
GitLab