services/app.service.ts
Entrypoint to store for response spectra application.
SharedService
Properties |
|
Methods |
|
Accessors |
constructor(formBuilder: FormBuilder, nshmpService: NshmpService, spinnerService: SpinnerService, route: ActivatedRoute, location: LocationService)
|
||||||||||||||||||
Defined in services/app.service.ts:93
|
||||||||||||||||||
Parameters :
|
addValidators |
addValidators()
|
Defined in services/app.service.ts:155
|
Add validators to form controls.
Returns :
void
|
calcHypocenterDepth | ||||||
calcHypocenterDepth(form: FormGroupControls<FormControls>)
|
||||||
Defined in services/app.service.ts:205
|
||||||
Calculate the hypocenter depth from form field values.
Parameters :
Returns :
void
|
calcPathParameters | ||||||
calcPathParameters(form: FormGroupControls<FormControls>)
|
||||||
Defined in services/app.service.ts:223
|
||||||
Calculate the GMM path parameters from form fields.
Parameters :
Returns :
void
|
callService |
callService()
|
Defined in services/app.service.ts:276
|
Calls the Gmm distance service.
Returns :
void
|
createPlots |
createPlots()
|
Defined in services/app.service.ts:301
|
Create plots based on current state and form group.
Returns :
void
|
defaultFormValues |
defaultFormValues()
|
Defined in services/app.service.ts:310
|
Default values for control panel.
Returns :
FormControls
|
defaultPlots |
defaultPlots()
|
Defined in services/app.service.ts:341
|
Returns the default plots.
Returns :
Map<string, SpectraPlot>
|
Private handleServiceResponses | ||||||
handleServiceResponses(serviceResponses: GmmSpectraResponse[])
|
||||||
Defined in services/app.service.ts:514
|
||||||
Parameters :
Returns :
void
|
Private handleUsageResponse | ||||||
handleUsageResponse(usageResponse: GmmSpectraUsage)
|
||||||
Defined in services/app.service.ts:539
|
||||||
Parameters :
Returns :
void
|
init |
init()
|
Defined in services/app.service.ts:429
|
Initialize the application.
Returns :
void
|
Private initialFormSet |
initialFormSet()
|
Defined in services/app.service.ts:558
|
Returns :
void
|
initialState |
initialState()
|
Defined in services/app.service.ts:447
|
Application initial state.
Returns :
AppState
|
Private plotInfo | ||||||||||||||||
plotInfo(gmmSeries: GmmSeries
|
||||||||||||||||
Defined in services/app.service.ts:641
|
||||||||||||||||
Plot info.
Parameters :
Returns :
{ hoverTemplate: {}; symbol: {}; }
|
resetControlPanel |
resetControlPanel()
|
Defined in services/app.service.ts:464
|
Reset the control panel.
Returns :
void
|
resetPlotSettings |
resetPlotSettings()
|
Defined in services/app.service.ts:473
|
Reset the plot settings.
Returns :
void
|
resetState |
resetState()
|
Defined in services/app.service.ts:483
|
Reset the state.
Returns :
void
|
Private serviceResponseToPlotData | ||||||||||||
serviceResponseToPlotData(state: AppState, form: FormGroupControls<FormControls>)
|
||||||||||||
Defined in services/app.service.ts:667
|
||||||||||||
Transform Gmm distance service responses to plots.
Parameters :
Returns :
Map<string, SpectraPlot>
|
Private toGmmResponses | ||||||||
toGmmResponses(responses: GmmSpectraResponse[])
|
||||||||
Defined in services/app.service.ts:722
|
||||||||
Convert service response to GMM response.
Parameters :
Returns :
gmmUtils.GmmResponse[]
|
Private toRadians | ||||||||
toRadians(value: number)
|
||||||||
Defined in services/app.service.ts:764
|
||||||||
Convert degrees to radians.
Parameters :
Returns :
number
|
Private updateControl | ||||||||||||||||||||
updateControl(control: FormControl
|
||||||||||||||||||||
Defined in services/app.service.ts:775
|
||||||||||||||||||||
Update state control form.
Parameters :
Returns :
void
|
Private updatePathFormValues | ||||||||||||
updatePathFormValues(form: FormGroupControls<FormControls>, path: literal type)
|
||||||||||||
Defined in services/app.service.ts:798
|
||||||||||||
Update form state with path values.
Parameters :
Returns :
void
|
updateState | ||||||||
updateState(state: Partial<AppState>)
|
||||||||
Defined in services/app.service.ts:507
|
||||||||
Update state.
Parameters :
Returns :
void
|
Private updateUrl |
updateUrl()
|
Defined in services/app.service.ts:813
|
Returns :
void
|
Private usageFormValues | ||||||||
usageFormValues(parameters: GmmSpectraUsageParameters)
|
||||||||
Defined in services/app.service.ts:853
|
||||||||
Returns the default from values from parameters.
Parameters :
Returns :
FormControls
|
Private baseUrl |
Default value : environment.webServices.data.url
|
Defined in services/app.service.ts:82
|
nshmp-ws base URL |
Readonly formGroup |
Default value : this.formBuilder.group({
...this.defaultFormValues(),
gmmSource: [],
MwMulti: [],
vs30Multi: [],
}) as FormGroupControls<FormControls>
|
Defined in services/app.service.ts:86
|
Private serviceUrl |
Default value : `${this.baseUrl}${environment.webServices.data.services.gmmSpectra}`
|
Defined in services/app.service.ts:84
|
GMM service URL |
Readonly state |
Default value : signal<AppState>(this.initialState())
|
Defined in services/app.service.ts:93
|
serviceCallInfo |
getserviceCallInfo()
|
Defined in services/app.service.ts:111
|
Returns service call info observable.
Returns :
Signal<ServiceCallInfo>
|
serviceResponse |
getserviceResponse()
|
Defined in services/app.service.ts:118
|
Returns the Gmm distance service responses.
Returns :
Signal<GmmSpectraResponse[]>
|
sigmaPlotState |
getsigmaPlotState()
|
Defined in services/app.service.ts:125
|
Returns the mean plot state.
Returns :
Signal<SpectraPlot>
|
spectraPlotState |
getspectraPlotState()
|
Defined in services/app.service.ts:132
|
Returns the mean plot state.
Returns :
Signal<SpectraPlot>
|
supportedImts |
getsupportedImts()
|
Defined in services/app.service.ts:139
|
Returns supported IMTs observable.
Returns :
Signal<EnumParameterValues[]>
|
usage |
getusage()
|
Defined in services/app.service.ts:146
|
Returns the Gmm distance usage response.
Returns :
Signal<GmmSpectraUsage>
|
import {Location as LocationService} from '@angular/common';
import {HttpParams} from '@angular/common/http';
import {computed, Injectable, Signal, signal} from '@angular/core';
import {
AbstractControl,
FormBuilder,
FormControl,
Validators,
} from '@angular/forms';
import {ActivatedRoute} from '@angular/router';
import {
GmmAppQuery,
gmmUtils,
MultiSelectableParam,
} from '@ghsc/nshmp-lib-ng/gmm';
import {
FormGroupControls,
NshmpService,
nshmpUtils,
ServiceCallInfo,
SpinnerService,
} from '@ghsc/nshmp-lib-ng/nshmp';
import {
NshmpPlot,
NshmpPlotSettings,
PlotOptions,
plotUtils,
} from '@ghsc/nshmp-lib-ng/plot';
import {Maths} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/calc';
import {
GmmGroupType,
GmmSeries,
GmmSpectraResponse,
GmmSpectraUsage,
GmmSpectraUsageParameters,
SpectraData,
TreeValues,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws/gmm-services';
import {EnumParameterValues} from '@ghsc/nshmp-utils-ts/libs/nshmp-ws-utils/metadata';
import {environment} from 'projects/nshmp-apps/src/environments/environment';
import {AppServiceModel} from 'projects/nshmp-apps/src/shared/models/app-service.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 {FormControls} from '../models/form-controls.model';
import {SpectraPlot} from '../models/spectra-plot.model';
import {AppState} from '../models/state.model';
interface Query extends GmmAppQuery {
/** Whether to derive path paramaeters */
derivePathParams: string;
/** Whether to use hangin wall */
hangingWall: string;
/** Rake */
rake: string;
/** Rake button values */
rakeButton: string;
/** Joyner-Boore Distance */
rJB: string;
/** Rupture Distance */
rRup: string;
/** Distance X */
rX: string;
/** Hypocentral Depth */
zHyp: string;
/** Whether hypocenter is centered */
zHypCentered: string;
}
/**
* Entrypoint to store for response spectra application.
*/
@Injectable({
providedIn: 'root',
})
export class AppService
extends SharedService
implements AppServiceModel<AppState, FormControls>
{
/** nshmp-ws base URL */
private baseUrl = environment.webServices.data.url;
/** GMM service URL */
private serviceUrl = `${this.baseUrl}${environment.webServices.data.services.gmmSpectra}`;
readonly formGroup = this.formBuilder.group({
...this.defaultFormValues(),
gmmSource: [],
MwMulti: [],
vs30Multi: [],
}) as FormGroupControls<FormControls>;
readonly state = signal<AppState>(this.initialState());
constructor(
private formBuilder: FormBuilder,
private nshmpService: NshmpService,
private spinnerService: SpinnerService,
private route: ActivatedRoute,
private location: LocationService,
) {
super();
this.addValidators();
this.formGroup.controls.gmmSource.setValue([]);
this.formGroup.controls.showEpistemicUncertainty.disable();
}
/**
* Returns service call info observable.
*/
get serviceCallInfo(): Signal<ServiceCallInfo> {
return computed(() => this.state().serviceCallInfo);
}
/**
* Returns the Gmm distance service responses.
*/
get serviceResponse(): Signal<GmmSpectraResponse[]> {
return computed(() => this.state().serviceResponses);
}
/**
* Returns the mean plot state.
*/
get sigmaPlotState(): Signal<SpectraPlot> {
return computed(() => this.state().plots?.get(gmmUtils.PlotType.SIGMA));
}
/**
* Returns the mean plot state.
*/
get spectraPlotState(): Signal<SpectraPlot> {
return computed(() => this.state().plots?.get(gmmUtils.PlotType.MEANS));
}
/**
* Returns supported IMTs observable.
*/
get supportedImts(): Signal<EnumParameterValues[]> {
return computed(() => this.state().supportedImts);
}
/**
* Returns the Gmm distance usage response.
*/
get usage(): Signal<GmmSpectraUsage> {
return computed(() => this.state().usageResponse);
}
/**
* Add validators to form controls.
*
* @param form The form group
*/
addValidators(): void {
const required = (control: AbstractControl) => Validators.required(control);
this.formGroup.controls.derivePathParams.addValidators(required);
this.formGroup.controls.dip.addValidators(required);
this.formGroup.controls.gmmSource.addValidators(required);
this.formGroup.controls.hangingWall.addValidators(required);
this.formGroup.controls.multiSelectableParam.addValidators(required);
this.formGroup.controls.Mw.addValidators(required);
this.formGroup.controls.vs30.addValidators(required);
this.formGroup.controls.width.addValidators(required);
this.formGroup.controls.zTor.addValidators(required);
this.formGroup.controls.rake.addValidators(required);
this.formGroup.controls.rJB.addValidators(required);
this.formGroup.controls.rRup.addValidators(required);
this.formGroup.controls.rX.addValidators(required);
this.formGroup.controls.vs30.addValidators(required);
this.formGroup.controls.width.addValidators(required);
this.formGroup.controls.zTor.addValidators(required);
this.formGroup.controls.MwMulti.addValidators(control => {
if (
this.formGroup.getRawValue().multiSelectableParam ===
MultiSelectableParam.MW
) {
return Validators.required(control);
} else {
return Validators.nullValidator(control);
}
});
this.formGroup.controls.vs30Multi.addValidators(control => {
if (
this.formGroup.getRawValue().multiSelectableParam ===
MultiSelectableParam.VS30
) {
return Validators.required(control);
} else {
return Validators.nullValidator(control);
}
});
this.formGroup.updateValueAndValidity();
}
/**
* Calculate the hypocenter depth from form field values.
*
* @param state The application state
*/
calcHypocenterDepth(form: FormGroupControls<FormControls>): void {
const values = form.getRawValue();
if (!values.zHypCentered) {
return;
}
const dip = this.toRadians(values.dip);
const zHyp = values.zTor + (Math.sin(dip) * values.width) / 2.0;
this.updateControl(form.controls.zHyp, zHyp, values.zHypCentered);
}
/**
* Calculate the GMM path parameters from form fields.
*
* @param state Application state
*/
calcPathParameters(form: FormGroupControls<FormControls>): void {
const values = form.getRawValue();
if (!values.derivePathParams) {
return;
}
const rX = values.rX;
const zTor = values.zTor;
const footwall = !values.hangingWall;
let rRup = Math.hypot(rX, zTor);
if (footwall) {
this.updatePathFormValues(form, {rJB: Math.abs(rX), rRup, rX});
return;
}
const δ = this.toRadians(values.dip);
const W = values.width;
const sinδ = Math.sin(δ);
const cosδ = Math.cos(δ);
const Wx = W * cosδ;
const Wz = W * sinδ;
const rJB = Math.max(0.0, rX - Wx);
const h1 = zTor / cosδ;
const rCut1 = h1 * sinδ;
if (rX < rCut1) {
this.updatePathFormValues(form, {rJB, rRup, rX});
return;
}
const zBot = zTor + Wz;
const h2 = zBot / cosδ;
const rCut2 = Wx + h2 * sinδ;
if (rX >= rCut2) {
rRup = Math.hypot(zBot, rJB);
this.updatePathFormValues(form, {rJB, rRup, rX});
return;
}
/*
* Linear scaling of distance normal
* to top and bottom of fault.
*/
rRup = h1 + (h2 - h1) * ((rX - rCut1) / (rCut2 - rCut1));
this.updatePathFormValues(form, {rJB, rRup, rX});
}
/**
* Calls the Gmm distance service.
*/
callService(): void {
if (this.formGroup.invalid) {
return;
}
const spinnerRef = this.spinnerService.show(SpinnerService.MESSAGE_SERVICE);
const urls = gmmUtils.serviceEndpoints(
this.serviceUrl,
this.formGroup.getRawValue(),
this.formGroup.getRawValue().multiSelectableParam,
);
this.nshmpService
.callServices$<GmmSpectraResponse>(urls)
.pipe(catchError((error: Error) => this.nshmpService.throwError$(error)))
.subscribe(serviceResponses => {
this.handleServiceResponses(serviceResponses);
spinnerRef.close();
});
}
/**
* Create plots based on current state and form group.
*/
createPlots(): void {
this.updateState({
plots: this.serviceResponseToPlotData(this.state(), this.formGroup),
});
}
/**
* Default values for control panel.
*/
defaultFormValues(): FormControls {
return {
derivePathParams: true,
dip: null,
gmmGroupType: GmmGroupType.ACTIVE_CRUST,
gmmSource: [],
hangingWall: true,
multiSelectableParam: MultiSelectableParam.GMM,
Mw: null,
MwMulti: [],
rake: 0,
rakeButton: 0,
rJB: null,
rRup: null,
rX: null,
showEpistemicUncertainty: false,
vs30: null,
vs30Multi: [],
width: null,
z1p0: null,
z2p5: null,
zHyp: null,
zHypCentered: true,
zSed: null,
zTor: null,
};
}
/**
* 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.
*/
init(): void {
const spinnerRef = this.spinnerService.show(
SpinnerService.MESSAGE_METADATA,
);
this.nshmpService
.callService$<GmmSpectraUsage>(this.serviceUrl)
.pipe(catchError((error: Error) => this.nshmpService.throwError$(error)))
.subscribe(usageResponse => {
this.handleUsageResponse(usageResponse);
this.initialFormSet();
spinnerRef.close();
});
}
/**
* Application initial state.
*/
initialState(): AppState {
return {
plots: this.defaultPlots(),
serviceCallInfo: {
serviceCalls: [],
serviceName: 'Response Spectra',
usage: [],
},
serviceResponses: [],
supportedImts: [],
usageResponse: null,
};
}
/**
* Reset the control panel.
*/
resetControlPanel(): void {
this.formGroup.reset(
this.usageFormValues(this.state().usageResponse.response.parameters),
);
}
/**
* Reset the plot settings.
*/
resetPlotSettings(): void {
super.resetPlotSettings({
currentPlots: this.state().plots,
defaultPlots: this.defaultPlots(),
});
}
/**
* Reset the state.
*/
resetState(): void {
const serviceCallInfo = gmmUtils.serviceCallInfo({
multiSelectableParam: this.formGroup.getRawValue().multiSelectableParam,
serviceName: this.state().serviceCallInfo.serviceName,
serviceResponses: this.state().serviceResponses,
serviceUrl: this.serviceUrl,
values: this.formGroup.getRawValue(),
});
this.updateState({
serviceCallInfo,
serviceResponses: null,
});
this.formGroup.controls.showEpistemicUncertainty.disable();
this.createPlots();
}
/**
* Update state.
*
* @param state Partial new state to update
*/
updateState(state: Partial<AppState>): void {
this.state.set({
...this.state(),
...state,
});
}
private handleServiceResponses(serviceResponses: GmmSpectraResponse[]): void {
const means = serviceResponses.map(s => s.response.means);
const sigmas = serviceResponses.map(s => s.response.sigmas);
const hasLogicTree = gmmUtils.hasTree([...means, ...sigmas]);
if (hasLogicTree) {
this.formGroup.controls.showEpistemicUncertainty.enable();
} else {
this.formGroup.controls.showEpistemicUncertainty.disable();
}
this.updateState({
serviceCallInfo: gmmUtils.serviceCallInfo({
multiSelectableParam: this.formGroup.getRawValue().multiSelectableParam,
serviceName: this.state().serviceCallInfo.serviceName,
serviceResponses,
serviceUrl: this.serviceUrl,
values: this.formGroup.getRawValue(),
}),
serviceResponses,
});
this.createPlots();
}
private handleUsageResponse(usageResponse: GmmSpectraUsage): void {
const parameters = usageResponse.response.parameters;
const values = this.usageFormValues(parameters);
this.formGroup.patchValue({
...values,
});
const serviceCallInfo: ServiceCallInfo = {
...this.state().serviceCallInfo,
usage: [this.serviceUrl],
};
this.updateState({
serviceCallInfo,
usageResponse,
});
}
private initialFormSet(): void {
const query = this.route.snapshot.queryParams as Query;
const defaultValues = this.formGroup.getRawValue();
const parameters = this.usage().response.parameters;
const gmmSource = gmmUtils.queryToGmmSource(query.gmm, parameters);
this.formGroup.patchValue({
multiSelectableParam:
query?.multiSelectableParam ?? defaultValues.multiSelectableParam,
});
this.formGroup.patchValue({
derivePathParams: nshmpUtils.queryParseBoolean(
defaultValues.derivePathParams,
query.derivePathParams,
),
dip: nshmpUtils.queryParseNumber(defaultValues.dip, query?.dip),
gmmGroupType: query?.gmmGroupType ?? defaultValues.gmmGroupType,
gmmSource,
hangingWall: nshmpUtils.queryParseBoolean(
defaultValues.hangingWall,
query?.hangingWall,
),
Mw: nshmpUtils.queryParseNumber(defaultValues.Mw, query?.Mw),
MwMulti: nshmpUtils
.queryStringToArray(query?.MwMulti)
.map(mw => Number.parseFloat(mw)),
rake: nshmpUtils.queryParseNumber(defaultValues.rake, query?.rake),
rakeButton:
query?.rakeButton &&
(query.rakeButton === '-90' ||
query.rakeButton === '0' ||
query.rakeButton === '90')
? (Number.parseFloat(query.rakeButton) as 90) || 0 || -90
: defaultValues.rakeButton,
rJB: nshmpUtils.queryParseNumber(defaultValues.rJB, query?.rJB),
rRup: nshmpUtils.queryParseNumber(defaultValues.rRup, query?.rRup),
rX: nshmpUtils.queryParseNumber(defaultValues.rX, query?.rX),
showEpistemicUncertainty: nshmpUtils.queryParseBoolean(
defaultValues.showEpistemicUncertainty,
query?.showEpistemicUncertainty,
),
vs30: nshmpUtils.queryParseNumber(defaultValues.vs30, query?.vs30),
vs30Multi: nshmpUtils
.queryStringToArray(query?.vs30Multi)
.map(vs30 => Number.parseFloat(vs30)),
width: nshmpUtils.queryParseNumber(defaultValues.width, query?.width),
z1p0: nshmpUtils.queryParseNumber(defaultValues.z1p0, query?.z1p0),
z2p5: nshmpUtils.queryParseNumber(defaultValues.z2p5, query?.z2p5),
zHyp: nshmpUtils.queryParseNumber(defaultValues.zHyp, query?.zHyp),
zHypCentered: nshmpUtils.queryParseBoolean(
defaultValues.zHypCentered,
query?.zHypCentered,
),
zSed: nshmpUtils.queryParseNumber(defaultValues.zSed, query?.zSed),
zTor: nshmpUtils.queryParseNumber(defaultValues.zTor, query?.zTor),
});
if (
this.formGroup.value.multiSelectableParam === MultiSelectableParam.MW ||
this.formGroup.value.multiSelectableParam === MultiSelectableParam.VS30
) {
this.formGroup.patchValue({
gmmSource: gmmSource.length > 0 ? [gmmSource.pop()] : [],
});
}
if (this.formGroup.valid) {
this.callService();
} else {
this.formGroup.markAsDirty();
}
this.formGroup.valueChanges.subscribe(() => this.updateUrl());
}
/**
* Plot info.
*
* @param xUnit X axis unit
* @param yUnit Y axis unit
*/
private plotInfo(
gmmSeries: GmmSeries<SpectraData, TreeValues>[],
xUnit: string,
yUnit: string,
) {
let hoverTemplate: string[] = [];
let symbol: string[] = [];
if (gmmSeries.length > 0) {
hoverTemplate = gmmSeries[0].data.sa.xs.map(
() => `%{x} ${xUnit}, %{y} ${yUnit}`,
);
symbol = gmmSeries[0].data.sa.xs.map(() => 'circle');
}
return {
hoverTemplate,
symbol,
};
}
/**
* Transform Gmm distance service responses to plots.
*
* @param state The application state
*/
private serviceResponseToPlotData(
state: AppState,
form: FormGroupControls<FormControls>,
): Map<string, SpectraPlot> {
if (
state.serviceResponses === null ||
state.serviceResponses?.length === 0
) {
return this.defaultPlots();
}
const plots = new Map<string, SpectraPlot>();
const meanPlot = state.plots.get(gmmUtils.PlotType.MEANS);
const sigmaPlot = state.plots.get(gmmUtils.PlotType.SIGMA);
const formValues = form.getRawValue();
const xValues = state.serviceResponses
.map(serviceResponse =>
serviceResponse.response.means.data.map(data => data.data.sa.xs),
)
.reduce((prev, curr) => [...prev, ...curr])
.reduce((prev, curr) => {
return [...prev, ...curr.filter(p => !prev.includes(p))];
})
.sort((a, b) => a - b);
const responses = this.toGmmResponses(state.serviceResponses);
const gmmPlots = gmmUtils.spectraResponsesToPlots({
meanPlot,
multiSelectableParam: formValues.multiSelectableParam,
responses,
showEpistemicUncertainty: formValues.showEpistemicUncertainty,
sigmaPlot,
});
plots.set(gmmUtils.PlotType.MEANS, {
...meanPlot,
plotData: gmmPlots.means,
xValues,
});
plots.set(gmmUtils.PlotType.SIGMA, {
...sigmaPlot,
plotData: gmmPlots.sigmas,
xValues,
});
return plots;
}
/**
* Convert service response to GMM response.
*
* @param responses The spectra responses
*/
private toGmmResponses(
responses: GmmSpectraResponse[],
): gmmUtils.GmmResponse<SpectraData, TreeValues>[] {
const gmmResponses = responses.map(serviceResponse => {
const means = serviceResponse.response.means;
const sigmas = serviceResponse.response.sigmas;
const meanData = this.plotInfo(means.data, 's', 'g');
const sigmaData = this.plotInfo(sigmas.data, 's', '𝞂');
const gmmResponse: gmmUtils.GmmResponse<SpectraData, TreeValues> = {
input: serviceResponse.request.input,
meanPlotConfig: {
...meanData,
},
response: {
means: {
...means,
data: means.data,
},
sigmas: {
...sigmas,
data: sigmas.data,
},
},
sigmaPlotConfig: {
...sigmaData,
},
};
return gmmResponse;
});
return gmmResponses;
}
/**
* Convert degrees to radians.
*
* @param value The value in degrees
* @returns
*/
private toRadians(value: number): number {
return value ? (value * Math.PI) / 180.0 : value;
}
/**
* Update state control form.
*
* @param control The form control state
* @param value Value to set
* @param disabled Whether control is disabled
*/
private updateControl(
control: FormControl<number>,
value: number,
disabled = false,
): void {
const precision = 3;
value = value ? Maths.round(value, precision) : value;
if (!isNaN(value) && control.value !== value) {
control.setValue(value);
}
if (disabled) {
control.disable();
}
}
/**
* Update form state with path values.
*
* @param state Application state
* @param path Path parameters
*/
private updatePathFormValues(
form: FormGroupControls<FormControls>,
path: {
rJB: number;
rRup: number;
rX: number;
},
): void {
const values = form.getRawValue();
this.updateControl(form.controls.rJB, path.rJB, values.derivePathParams);
this.updateControl(form.controls.rRup, path.rRup, values.derivePathParams);
this.updateControl(form.controls.rX, path.rX);
}
private updateUrl(): void {
const value = this.formGroup.getRawValue();
const query: Query = {
derivePathParams: value.derivePathParams?.toString(),
dip: value.dip?.toString(),
gmm: gmmUtils.gmmSourceToQuery(value.gmmSource),
gmmGroupType: value.gmmGroupType,
hangingWall: value.hangingWall?.toString(),
multiSelectableParam: value.multiSelectableParam,
Mw: value.Mw?.toString(),
MwMulti: value.MwMulti?.map(mw => mw.toString()),
rake: value.rake?.toString(),
rakeButton: value.rakeButton?.toString(),
rJB: value.rJB?.toString(),
rRup: value.rRup?.toString(),
rX: value.rX?.toString(),
showEpistemicUncertainty: value.showEpistemicUncertainty.toString(),
vs30: value.vs30?.toString(),
vs30Multi: value.vs30Multi?.map(vs30 => vs30.toString()),
width: value.width?.toString(),
z1p0: value.z1p0?.toString(),
z2p5: value.z2p5?.toString(),
zHyp: value.zHyp?.toString(),
zHypCentered: value.zHypCentered?.toString(),
zSed: value.zSed?.toString(),
zTor: value.zTor?.toString(),
};
this.location.replaceState(
apps().gmm.spectra.routerLink,
new HttpParams().appendAll({...query}).toString(),
);
}
/**
* Returns the default from values from parameters.
*
* @param parameters The service parameters
*/
private usageFormValues(parameters: GmmSpectraUsageParameters): FormControls {
return {
...this.defaultFormValues(),
dip: parameters.dip.value as number,
Mw: parameters.Mw.value as number,
MwMulti: [],
rake: parameters.rake.value as number,
rJB: parameters.rJB.value as number,
rRup: parameters.rRup.value as number,
rX: parameters.rX.value as number,
vs30: parameters.vs30.value as number,
vs30Multi: [],
width: parameters.width.value as number,
z1p0: parameters.z1p0.value as number,
z2p5: parameters.z2p5.value as number,
zHyp: parameters.zHyp.value as number,
zHypCentered: true,
zTor: parameters.zTor.value as number,
};
}
}