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] 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