services/app.service.ts
Entrypoint to store for dynamic hazard application.
SharedService
Properties |
|
Methods |
|
Accessors |
constructor(formBuilder: FormBuilder, spinnerService: SpinnerService, nshmpService: NshmpService, hazardService: HazardService, route: ActivatedRoute, location: LocationService)
|
|||||||||||||||||||||
Defined in services/app.service.ts:82
|
|||||||||||||||||||||
Parameters :
|
Private addRequiredValidator | ||||||
addRequiredValidator(control: AbstractControl)
|
||||||
Defined in services/app.service.ts:401
|
||||||
Parameters :
Returns :
void
|
addValidators |
addValidators()
|
Defined in services/app.service.ts:190
|
Returns :
void
|
callService |
callService()
|
Defined in services/app.service.ts:205
|
Call the hazard service.
Returns :
void
|
Private createHazardPlotData | ||||||||||||||||||||
createHazardPlotData(responseData: StaticResponseData
|
||||||||||||||||||||
Defined in services/app.service.ts:413
|
||||||||||||||||||||
Return hazard plot data from response data.
Parameters :
Returns :
PlotlyPlot
|
createPlots |
createPlots()
|
Defined in services/app.service.ts:242
|
Returns :
void
|
Private createResponseSpectra | |||||||||
createResponseSpectra(serviceResponse: StaticHazardResponse, formGroup: FormGroupControls
|
|||||||||
Defined in services/app.service.ts:481
|
|||||||||
Calculate the response spectrum for each site class.
Parameters :
Returns :
ResponseSpectra[]
|
Private createServiceEndpoint | |||||||||
createServiceEndpoint(serviceUrl: string, values: HazardControlForm)
|
|||||||||
Defined in services/app.service.ts:522
|
|||||||||
Parameters :
Returns :
string
|
defaultFormValues |
defaultFormValues()
|
Defined in services/app.service.ts:250
|
Returns the default form values.
Returns :
HazardControlForm
|
formServiceUrl | ||||||||||||||||||||
formServiceUrl(services: HazardWebServices
|
||||||||||||||||||||
Defined in services/app.service.ts:263
|
||||||||||||||||||||
Form the url to call.
Parameters :
Returns :
string
|
Private getResponseData | ||||||||||||
getResponseData(state: AppState, formGroup: FormGroupControls
|
||||||||||||
Defined in services/app.service.ts:535
|
||||||||||||
Returns the response data for a site class.
Parameters :
Returns :
StaticResponseData[]
|
Private hazardCurveMap | ||||||||||||
hazardCurveMap(responseData: StaticResponseData
|
||||||||||||
Defined in services/app.service.ts:554
|
||||||||||||
Return map of imt to xy sequence.
Parameters :
Returns :
Map<Imt, XySequence>
|
init |
init()
|
Defined in services/app.service.ts:276
|
Initialize applicaiton.
Returns :
void
|
Private initialFormSet |
initialFormSet()
|
Defined in services/app.service.ts:572
|
Returns :
void
|
initialState |
initialState()
|
Defined in services/app.service.ts:309
|
Static hazard app initial state
Returns :
AppState
|
resetControlPanel |
resetControlPanel()
|
Defined in services/app.service.ts:331
|
Reset the control panel.
Returns :
void
|
resetSettings |
resetSettings()
|
Defined in services/app.service.ts:339
|
Reset the plot settings.
Returns :
void
|
resetState |
resetState()
|
Defined in services/app.service.ts:346
|
Returns :
void
|
Private responseSpectrumPlotData | ||||||||||||||||||||
responseSpectrumPlotData(responseData: StaticResponseData
|
||||||||||||||||||||
Defined in services/app.service.ts:622
|
||||||||||||||||||||
Return the response spectrum plot data.
Parameters :
Returns :
PlotlyPlot
|
Private responseToPlots | ||||||||||||
responseToPlots(state: AppState, formGroup: FormGroupControls
|
||||||||||||
Defined in services/app.service.ts:737
|
||||||||||||
Transform the service response to plot data.
Parameters :
Returns :
Map<string, NshmpPlot>
|
Private returnPeriodPlotData | ||||||||||||
returnPeriodPlotData(plotData: Partial
|
||||||||||||
Defined in services/app.service.ts:784
|
||||||||||||
Returns the plot data for the return period.
Parameters :
Returns :
Partial<PlotData>
|
setLocation | ||||||||
setLocation(location: Location)
|
||||||||
Defined in services/app.service.ts:364
|
||||||||
Set the location form fields.
Parameters :
Returns :
void
|
staticHazardOnSiteClassChange | ||||||||||||
staticHazardOnSiteClassChange(state: AppState, formGroup: FormGroupControls
|
||||||||||||
Defined in services/app.service.ts:376
|
||||||||||||
Replot hazard curves when site class changes.
Parameters :
Returns :
Map<string, NshmpPlot>
|
Private staticService | ||||||||||||
staticService(services: HazardWebServices
|
||||||||||||
Defined in services/app.service.ts:813
|
||||||||||||
Returns the static service associated with a model
Parameters :
Returns :
HazardWebServiceConfig
|
updateState | ||||||
updateState(state: Partial<AppState>)
|
||||||
Defined in services/app.service.ts:387
|
||||||
Parameters :
Returns :
void
|
Private updateUrl |
updateUrl()
|
Defined in services/app.service.ts:820
|
Returns :
void
|
Private updateUsageUrl |
updateUsageUrl()
|
Defined in services/app.service.ts:827
|
Returns :
void
|
Readonly formGroup |
Default value : this.formBuilder.group<HazardControlForm>(
this.defaultFormValues(),
)
|
Defined in services/app.service.ts:77
|
Private nshmpWsStatic |
Default value : environment.webServices.nshmpWsStatic
|
Defined in services/app.service.ts:73
|
nshmp-haz-ws web config |
Private serviceEndpoint |
Default value : this.nshmpWsStatic.services.curveServices.hazard
|
Defined in services/app.service.ts:75
|
Hazard endpoint |
Readonly state |
Default value : signal<AppState>(this.initialState())
|
Defined in services/app.service.ts:82
|
Application state |
availableModels |
getavailableModels()
|
Defined in services/app.service.ts:99
|
Returns the available models.
Returns :
Signal<Parameter[]>
|
hazardPlotData |
gethazardPlotData()
|
Defined in services/app.service.ts:106
|
Returns the hazard plot data.
Returns :
Signal<PlotlyPlot>
|
hazardPlotSettings |
gethazardPlotSettings()
|
Defined in services/app.service.ts:113
|
Returns the hazard plot settings form.
Returns :
Signal<FormGroup<NshmpPlotSettingFormGroup>>
|
hazardPlotState |
gethazardPlotState()
|
Defined in services/app.service.ts:120
|
Returns the hazard plot.
Returns :
Signal<NshmpPlot>
|
nshmService |
getnshmService()
|
Defined in services/app.service.ts:127
|
Returns the metadata of the NSHM observable.
Returns :
Signal<StaticNshmMetadata>
|
plots |
getplots()
|
Defined in services/app.service.ts:135
|
responseSpectra |
getresponseSpectra()
|
Defined in services/app.service.ts:142
|
Returns the response spectra
Returns :
Signal<ResponseSpectra[]>
|
serviceCallInfo |
getserviceCallInfo()
|
Defined in services/app.service.ts:149
|
Returns the service call info.
Returns :
Signal<ServiceCallInfo>
|
serviceResponse |
getserviceResponse()
|
Defined in services/app.service.ts:156
|
Returns the disagg response.
Returns :
Signal<StaticHazardResponse>
|
spectrumPlotData |
getspectrumPlotData()
|
Defined in services/app.service.ts:163
|
Returns the spectrum plot data.
Returns :
Signal<PlotlyPlot>
|
spectrumPlotSettings |
getspectrumPlotSettings()
|
Defined in services/app.service.ts:170
|
Returns the spectrum plot settings form.
Returns :
Signal<FormGroup<NshmpPlotSettingFormGroup>>
|
spectrumPlotState |
getspectrumPlotState()
|
Defined in services/app.service.ts:177
|
Returns the response spectrum plot.
Returns :
Signal<NshmpPlot>
|
usage |
getusage()
|
Defined in services/app.service.ts:184
|
Return the usage for the selected model.
Returns :
Signal<StaticHazardUsage>
|
import {Location as LocationService} from '@angular/common';
import {HttpParams} from '@angular/common/http';
import {computed, Injectable, Signal, signal} from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormGroup,
Validators,
} from '@angular/forms';
import {ActivatedRoute} from '@angular/router';
import {
HazardAppQuery,
HazardControlForm,
HazardPlots,
HazardService,
hazardUtils,
ResponseSpectra,
ResponseSpectrum,
} from '@ghsc/nshmp-lib-ng/hazard';
import {
FormGroupControls,
NshmpService,
RETURN_PERIOD_VALUES,
returnPeriodAltName,
ServiceCallInfo,
SpinnerService,
} from '@ghsc/nshmp-lib-ng/nshmp';
import {
NshmpPlot,
NshmpPlotSettingFormGroup,
plotUtils,
} from '@ghsc/nshmp-lib-ng/plot';
import {Maths} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/calc';
import {XySequence} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/data';
import {Location} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/geo';
import {Imt, imtToPeriod} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/gmm';
import {NshmId} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/nshm';
import {
HazardResponseMetadata,
StaticHazardResponse,
StaticHazardUsage,
StaticResponseData,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws-static/hazard-service';
import {StaticNshmMetadata} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws-static/nshm-service';
import {Parameter} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws-utils/metadata';
import {PlotlyPlot} from '@ghsc/nshmp-utils-ts/libs/plotly';
import deepEqual from 'deep-equal';
import {PlotData} from 'plotly.js';
import {environment} from 'projects/nshmp-apps/src/environments/environment';
import {AppServiceModel} from 'projects/nshmp-apps/src/shared/models/app-service.model';
import {
HazardWebServiceConfig,
HazardWebServices,
StaticCurvesServices,
} from 'projects/nshmp-apps/src/shared/models/web-services.model';
import {SharedService} from 'projects/nshmp-apps/src/shared/services/shared.service';
import {apps} from 'projects/nshmp-apps/src/shared/utils/applications.utils';
import {catchError} from 'rxjs';
import {AppState} from '../models/state.model';
/**
* Entrypoint to store for dynamic hazard application.
*/
@Injectable({
providedIn: 'root',
})
export class AppService
extends SharedService
implements AppServiceModel<AppState, HazardControlForm>
{
/** nshmp-haz-ws web config */
private nshmpWsStatic = environment.webServices.nshmpWsStatic;
/** Hazard endpoint */
private serviceEndpoint = this.nshmpWsStatic.services.curveServices.hazard;
readonly formGroup = this.formBuilder.group<HazardControlForm>(
this.defaultFormValues(),
);
/** Application state */
readonly state = signal<AppState>(this.initialState());
constructor(
private formBuilder: FormBuilder,
private spinnerService: SpinnerService,
private nshmpService: NshmpService,
private hazardService: HazardService,
private route: ActivatedRoute,
private location: LocationService,
) {
super();
this.addValidators();
}
/**
* Returns the available models.
*/
get availableModels(): Signal<Parameter[]> {
return computed(() => this.state().availableModels);
}
/**
* Returns the hazard plot data.
*/
get hazardPlotData(): Signal<PlotlyPlot> {
return computed(() => this.hazardPlotState().plotData);
}
/**
* Returns the hazard plot settings form.
*/
get hazardPlotSettings(): Signal<FormGroup<NshmpPlotSettingFormGroup>> {
return computed(() => this.hazardPlotState().settingsForm);
}
/**
* Returns the hazard plot.
*/
get hazardPlotState(): Signal<NshmpPlot> {
return computed(() => this.state().plots.get(HazardPlots.HAZARD));
}
/**
* Returns the metadata of the NSHM observable.
*/
get nshmService(): Signal<StaticNshmMetadata> {
return computed(() =>
this.state().nshmServices.find(
nshmService => nshmService.model === this.formGroup.getRawValue().model,
),
);
}
get plots(): Signal<Map<string, NshmpPlot>> {
return computed(() => this.state().plots);
}
/**
* Returns the response spectra
*/
get responseSpectra(): Signal<ResponseSpectra[]> {
return computed(() => this.state().responseSpectra);
}
/**
* Returns the service call info.
*/
get serviceCallInfo(): Signal<ServiceCallInfo> {
return computed(() => this.state().serviceCallInfo);
}
/**
* Returns the disagg response.
*/
get serviceResponse(): Signal<StaticHazardResponse> {
return computed(() => this.state().serviceResponse);
}
/**
* Returns the spectrum plot data.
*/
get spectrumPlotData(): Signal<PlotlyPlot> {
return computed(() => this.spectrumPlotState().plotData);
}
/**
* Returns the spectrum plot settings form.
*/
get spectrumPlotSettings(): Signal<FormGroup<NshmpPlotSettingFormGroup>> {
return computed(() => this.spectrumPlotState().settingsForm);
}
/**
* Returns the response spectrum plot.
*/
get spectrumPlotState(): Signal<NshmpPlot> {
return computed(() => this.state().plots.get(HazardPlots.SPECTRUM));
}
/**
* Return the usage for the selected model.
*/
get usage(): Signal<StaticHazardUsage> {
return computed(() =>
this.state().usageResponses?.get(this.formGroup.getRawValue().model),
);
}
addValidators(): void {
const controls = this.formGroup.controls;
this.addRequiredValidator(controls.latitude);
this.addRequiredValidator(controls.longitude);
this.addRequiredValidator(controls.model);
this.addRequiredValidator(controls.returnPeriod);
controls.latitude.addValidators(this.validateNan());
controls.longitude.addValidators(this.validateNan());
}
/**
* Call the hazard service.
*/
callService(): void {
const spinnerRef = this.spinnerService.show(SpinnerService.MESSAGE_SERVICE);
const values = this.formGroup.getRawValue();
const service = this.state().nshmServices.find(
nshmService => nshmService.model === values.model,
);
const serviceUrl = `${service.url}${this.serviceEndpoint}`;
const url = this.createServiceEndpoint(serviceUrl, values);
this.nshmpService
.callService$<StaticHazardResponse>(url)
.pipe(
catchError((error: Error) => {
spinnerRef.close();
return this.nshmpService.throwError$(error);
}),
)
.subscribe(serviceResponse => {
spinnerRef.close();
this.updateState({
responseSpectra: this.createResponseSpectra(
serviceResponse,
this.formGroup,
),
serviceCallInfo: {
...this.state().serviceCallInfo,
serviceCalls: [url],
},
serviceResponse,
});
this.createPlots();
});
}
createPlots(): void {
const plots = this.responseToPlots(this.state(), this.formGroup);
this.updateState({plots});
}
/**
* Returns the default form values.
*/
defaultFormValues(): HazardControlForm {
return {
...hazardUtils.hazardDefaultFormValues(),
};
}
/**
* Form the url to call.
*
* @param model The model
* @param longitude The longitude
* @param latitude The latitude
*/
formServiceUrl(
services: HazardWebServices<StaticCurvesServices>,
model: NshmId,
longitude: number,
latitude: number,
): string {
const service = this.staticService(services, model);
return `${service.url}${services.services.hazard}/${longitude}/${latitude}`;
}
/**
* Initialize applicaiton.
*/
init(): void {
const spinnerRef = this.spinnerService.show(
SpinnerService.MESSAGE_METADATA,
);
this.hazardService
.staticNshms$(
`${this.nshmpWsStatic.url}${this.nshmpWsStatic.services.nshms}`,
this.serviceEndpoint,
)
.pipe(
catchError((error: Error) => {
spinnerRef.close();
return this.nshmpService.throwError$(error);
}),
)
.subscribe(({models, nshmServices, usageResponses}) => {
spinnerRef.close();
this.updateState({
availableModels: models,
nshmServices,
usageResponses,
});
this.updateUsageUrl();
this.initialFormSet();
});
}
/**
* Static hazard app initial state
*/
initialState(): AppState {
const usageResponses: Map<string, StaticHazardUsage> = new Map();
usageResponses.set(NshmId.CONUS_2018, null);
return {
availableModels: [],
nshmServices: [],
plots: hazardUtils.hazardDefaultPlots(),
responseSpectra: null,
serviceCallInfo: {
serviceCalls: [],
serviceName: 'Dynamic Hazard Curves',
usage: [],
},
serviceResponse: null,
usageResponses,
};
}
/**
* Reset the control panel.
*/
resetControlPanel(): void {
this.formGroup.reset(this.defaultFormValues());
this.resetState();
}
/**
* Reset the plot settings.
*/
resetSettings(): void {
super.resetPlotSettings({
currentPlots: this.state().plots,
defaultPlots: this.initialState().plots,
});
}
resetState(): void {
this.updateState({
plots: this.initialState().plots,
serviceCallInfo: {
...this.state().serviceCallInfo,
serviceCalls: [],
},
serviceResponse: null,
});
this.updateUsageUrl();
}
/**
* Set the location form fields.
*
* @param location The location
*/
setLocation(location: Location): void {
this.formGroup.patchValue({
latitude: location.latitude,
longitude: location.longitude,
});
}
/**
* Replot hazard curves when site class changes.
*
* @param state The current state
*/
staticHazardOnSiteClassChange(
state: AppState,
formGroup: FormGroupControls<HazardControlForm>,
): Map<string, NshmpPlot> {
if (state.serviceResponse) {
return this.responseToPlots(state, formGroup);
} else {
return state.plots;
}
}
updateState(state: Partial<AppState>): void {
const updatedState = {
...this.state(),
...state,
};
if (!deepEqual(updatedState, this.state())) {
this.state.set({
...this.state(),
...state,
});
}
}
private addRequiredValidator(control: AbstractControl): void {
control.addValidators(control => Validators.required(control));
}
/**
* Return hazard plot data from response data.
*
* @param responseData Service response data
* @param plot Plot
* @param form Form field values
* @param returnPeriod Return period
*/
private createHazardPlotData(
responseData: StaticResponseData<HazardResponseMetadata>[],
plot: NshmpPlot,
form: HazardControlForm,
returnPeriod: number,
): PlotlyPlot {
const staticResponseData = responseData.filter(
response => response.metadata.imt.value !== Imt.PGV.toString(),
);
let data = staticResponseData.map((response, index) => {
const imt = response.metadata.imt.value as Imt;
const label = imt === Imt.PGA ? imt : `${imtToPeriod(imt)} s`;
const xy = hazardUtils.updateXySequence(
form,
hazardUtils.cleanXySequence(response.data),
imt,
);
const plotlyData: Partial<PlotData> = {
hovertemplate: '%{x} g, %{y} AFE',
line: {
color: hazardUtils.color(index, staticResponseData.length),
},
mode: 'lines+markers',
name: label,
x: xy.xs,
y: xy.ys,
};
return plotlyData;
});
const metadata = [...responseData].shift().metadata;
const layout = plotUtils.updatePlotLabels({
layout: plot.plotData.layout,
xLabel: metadata.xLabel,
yLabel: metadata.yLabel,
});
const mobileLayout = plotUtils.updatePlotLabels({
layout: plot.plotData.mobileLayout,
xLabel: metadata.xLabel,
yLabel: metadata.yLabel,
});
data = [this.returnPeriodPlotData(data, returnPeriod), ...data];
return {
config: {
...plot.plotData.config,
},
data,
id: 'hazard-curves',
layout,
mobileConfig: {...plot.plotData.mobileConfig},
mobileLayout: {
...mobileLayout,
},
};
}
/**
* Calculate the response spectrum for each site class.
*
* @param state The current state
*/
private createResponseSpectra(
serviceResponse: StaticHazardResponse,
formGroup: FormGroupControls<HazardControlForm>,
): ResponseSpectra[] {
if (serviceResponse === null) {
return [];
}
const returnPeriodValue = formGroup.getRawValue().returnPeriod;
const hasReturnPeriod = RETURN_PERIOD_VALUES.includes(returnPeriodValue);
const returnPeriods = [...RETURN_PERIOD_VALUES];
if (!hasReturnPeriod) {
returnPeriods.unshift(returnPeriodValue);
}
return serviceResponse.response.map(serviceResponse => {
const hazardCurves: Map<Imt, XySequence> = this.hazardCurveMap(
serviceResponse,
formGroup.getRawValue(),
);
const spectra: ResponseSpectrum[] = returnPeriods.map(
(returnPeriod: number) => {
const spectrum = Maths.responseSpectrum(hazardCurves, returnPeriod);
return {
returnPeriod,
values: spectrum.ys,
};
},
);
return {
imts: [...hazardCurves.keys()],
responseSpectrum: spectra,
siteClass: serviceResponse[0].metadata.siteClass,
};
});
}
private createServiceEndpoint(
serviceUrl: string,
values: HazardControlForm,
): string {
const {longitude, latitude} = values;
return `${serviceUrl}/${longitude}/${latitude}`;
}
/**
* Returns the response data for a site class.
*
* @param state The current state
*/
private getResponseData(
state: AppState,
formGroup: FormGroupControls<HazardControlForm>,
): StaticResponseData<HazardResponseMetadata>[] {
const siteClass = formGroup.getRawValue().siteClass;
return state.serviceResponse
? state.serviceResponse.response.find(response => {
return response.find(data => data.metadata.siteClass === siteClass);
})
: null;
}
/**
* Return map of imt to xy sequence.
*
* @param responseData Service response data
* @param form Form field values
*/
private hazardCurveMap(
responseData: StaticResponseData<HazardResponseMetadata>[],
form: HazardControlForm,
): Map<Imt, XySequence> {
const hazardCurves: Map<Imt, XySequence> = new Map();
responseData.forEach(response => {
const imt = response.metadata.imt.value as Imt;
const xy = hazardUtils.updateXySequence(
form,
hazardUtils.cleanXySequence(response.data),
imt,
);
hazardCurves.set(imt, xy);
});
return hazardCurves;
}
private initialFormSet(): void {
this.formGroup.valueChanges.subscribe(() => this.updateUrl());
const query = this.route.snapshot.queryParams as HazardAppQuery;
const defaultValues = this.defaultFormValues();
const formValues: HazardControlForm = {
commonReturnPeriods: defaultValues.commonReturnPeriods,
latitude:
query.latitude !== undefined
? Number.parseFloat(query.latitude)
: defaultValues.latitude,
longitude:
query.longitude !== undefined
? Number.parseFloat(query.longitude)
: defaultValues.longitude,
maxDirection:
query.maxDirection !== undefined
? (JSON.parse(query.maxDirection) as boolean)
: defaultValues.maxDirection,
model: query.model !== undefined ? query.model : defaultValues.model,
returnPeriod:
query.returnPeriod !== undefined
? Number.parseInt(query.returnPeriod, 10)
: defaultValues.returnPeriod,
siteClass:
query.siteClass !== undefined
? query.siteClass
: defaultValues.siteClass,
truncate:
query.truncate !== undefined
? (JSON.parse(query.truncate) as boolean)
: defaultValues.truncate,
};
this.formGroup.patchValue(formValues);
if (this.formGroup.valid) {
this.nshmpService.selectPlotControl();
this.callService();
} else if (this.formGroup.getRawValue() !== defaultValues) {
this.formGroup.markAsDirty();
}
}
/**
* Return the response spectrum plot data.
*
* @param responseData The response data
*/
private responseSpectrumPlotData(
responseData: StaticResponseData<HazardResponseMetadata>[],
plot: NshmpPlot,
form: HazardControlForm,
returnPeriodValue: number,
): PlotlyPlot {
const hazardCurves = this.hazardCurveMap(responseData, form);
const imts: Imt[] = [];
responseData.forEach(response => {
imts.push(response.metadata.imt.value as Imt);
});
const lines: Partial<PlotData>[] = [];
const hasReturnPeriod = RETURN_PERIOD_VALUES.includes(returnPeriodValue);
const returnPeriods = [...RETURN_PERIOD_VALUES];
if (!hasReturnPeriod) {
returnPeriods.unshift(returnPeriodValue);
}
returnPeriods.forEach((returnPeriod, iReturnPeriod) => {
const spectrum = Maths.responseSpectrum(hazardCurves, returnPeriod);
let lineWidth = 2;
let markerSize = 7;
const color = hazardUtils.color(iReturnPeriod, returnPeriods.length);
if (returnPeriod === returnPeriodValue) {
lineWidth = 4;
markerSize = 12;
}
const spectraX: number[] = [];
const spectraY: number[] = [];
const scatters: Partial<PlotData>[] = [];
for (let iSpectrum = 0; iSpectrum < spectrum.xs.length; iSpectrum++) {
const imt = imts[iSpectrum];
if (imt === Imt.PGV) {
continue;
} else if (imt === Imt.PGA) {
scatters.push({
hovertemplate: '%{y} g',
legendgroup: imt,
marker: {
color,
size: markerSize,
symbol: 'square',
},
mode: 'markers',
name: imt,
showlegend: false,
x: [Math.min(...spectrum.xs.filter(x => x !== imtToPeriod(imt)))],
y: [spectrum.ys[iSpectrum]],
});
} else {
spectraX.push(spectrum.xs[iSpectrum]);
spectraY.push(spectrum.ys[iSpectrum]);
}
}
lines.push({
hovertemplate: '%{y} g',
line: {
color,
width: lineWidth,
},
marker: {
size: markerSize,
},
mode: 'lines+markers',
name: returnPeriodAltName[returnPeriod] ?? `${returnPeriod} yr`,
x: spectraX,
y: spectraY,
});
lines.push(...scatters);
});
const legendEntries: Partial<PlotData>[] = [
{
legendgroup: Imt.PGA,
marker: {
color: 'white',
line: {
width: 1.5,
},
size: 7,
symbol: 'square',
},
mode: 'markers',
name: 'PGA',
x: [-1],
y: [-1],
},
];
lines.push(...legendEntries);
return {
config: {...plot.plotData.config},
data: lines,
id: 'response-spectrum',
layout: {...plot.plotData.layout},
mobileConfig: {...plot.plotData.mobileConfig},
mobileLayout: {...plot.plotData.mobileLayout},
};
}
/**
* Transform the service response to plot data.
*
* @param state The current state
*/
private responseToPlots(
state: AppState,
formGroup: FormGroupControls<HazardControlForm>,
): Map<string, NshmpPlot> {
if (state.serviceResponse === null || state.serviceResponse === undefined) {
return state.plots;
}
const returnPeriod = formGroup.getRawValue().returnPeriod;
const responseData = this.getResponseData(state, formGroup);
const plots = new Map<string, NshmpPlot>();
const hazardPlot = state.plots.get(HazardPlots.HAZARD);
const spectrumPlot = state.plots.get(HazardPlots.SPECTRUM);
const hazardCurves = this.createHazardPlotData(
responseData,
hazardPlot,
formGroup.getRawValue(),
returnPeriod,
);
const spectrum = this.responseSpectrumPlotData(
responseData,
spectrumPlot,
formGroup.getRawValue(),
returnPeriod,
);
plots.set(HazardPlots.HAZARD, {
...hazardPlot,
plotData: hazardCurves,
});
plots.set(HazardPlots.SPECTRUM, {
...spectrumPlot,
plotData: spectrum,
});
return plots;
}
/**
* Returns the plot data for the return period.
*
* @param plotData The plot data
* @param returnPeriod The return period
*/
private returnPeriodPlotData(
plotData: Partial<PlotData>[],
returnPeriod: number,
): Partial<PlotData> {
const xMin = Math.min(
...plotData.map(xy => Math.min(...(xy.x as number[]))),
);
const xMax = Math.max(
...plotData.map(xy => Math.max(...(xy.x as number[]))),
);
return {
hoverinfo: 'none',
line: {
color: 'black',
},
mode: 'lines',
name: `${returnPeriod} yr.`,
x: [xMin, xMax],
y: [1 / returnPeriod, 1 / returnPeriod],
};
}
/**
* Returns the static service associated with a model
*
* @param service The static hazard services
* @param model The model
*/
private staticService(
services: HazardWebServices<StaticCurvesServices>,
model: NshmId,
): HazardWebServiceConfig {
return services.models.find(service => model === service.model);
}
private updateUrl(): void {
this.location.replaceState(
apps().hazard.static.routerLink,
new HttpParams().appendAll(this.formGroup.getRawValue()).toString(),
);
}
private updateUsageUrl() {
const nshmService = this.state().nshmServices.find(
nshm => nshm.model === this.formGroup.getRawValue().model,
);
this.updateState({
serviceCallInfo: {
...this.state().serviceCallInfo,
usage: [nshmService.url],
},
});
}
}