services/app.service.ts
Entrypoint to store for dynamic hazard compare application.
SharedService
Properties |
|
Methods |
|
Accessors |
constructor(formBuilder: FormBuilder, spinnerService: SpinnerService, nshmpService: NshmpService, hazardPlotsService: HazardPlotsService, spectraPlotsService: SpectraPlotsService, hazardService: HazardService, route: ActivatedRoute, location: LocationService)
|
|||||||||||||||||||||||||||
Defined in services/app.service.ts:80
|
|||||||||||||||||||||||||||
Parameters :
|
Private addRequiredValidator | ||||||
addRequiredValidator(control: AbstractControl)
|
||||||
Defined in services/app.service.ts:485
|
||||||
Parameters :
Returns :
void
|
addValidators |
addValidators()
|
Defined in services/app.service.ts:169
|
Returns :
void
|
callService |
callService()
|
Defined in services/app.service.ts:187
|
Call the hazard service.
Returns :
void
|
combineUsages | ||||||||
combineUsages(usages: HazardUsageResponse[])
|
||||||||
Defined in services/app.service.ts:252
|
||||||||
Combine hazard usages with same region with common parameters.
Parameters :
Returns :
HazardUsageResponse
|
createPlots |
createPlots()
|
Defined in services/app.service.ts:293
|
Returns :
void
|
defaultFormValues |
defaultFormValues()
|
Defined in services/app.service.ts:301
|
Initial state for the control panel,
Returns :
ControlForm
|
defaultPlots |
defaultPlots()
|
Defined in services/app.service.ts:314
|
Returns the default plots with settings.
Returns :
Map<string, NshmpPlot>
|
Private findCommonImts | ||||||||
findCommonImts(imts: Parameter[][])
|
||||||||
Defined in services/app.service.ts:494
|
||||||||
Returns the common imts form array of parameters.
Parameters :
Returns :
Parameter[]
|
Private findCommonSiteClasses | ||||||||
findCommonSiteClasses(siteClasses: Record
|
||||||||
Defined in services/app.service.ts:510
|
||||||||
Returns the common site classes based on keys from an array of site class records.
Parameters :
Returns :
Record<string, number>
|
Private getCombinedUsage | ||||||||||||||||
getCombinedUsage(usageResponses: Map
|
||||||||||||||||
Defined in services/app.service.ts:537
|
||||||||||||||||
Returns the combined usage from model and comparable model.
Parameters :
Returns :
HazardUsageResponse
|
Private getComparableModels |
getComparableModels()
|
Defined in services/app.service.ts:559
|
Returns the available models that are comparable to the select model.
Returns :
Parameter[]
|
Private getImt | ||||||||||||
getImt(query: string, defaultImt: Imt)
|
||||||||||||
Defined in services/app.service.ts:586
|
||||||||||||
Returns the IMT to use.
Parameters :
Returns :
Imt
|
Private getModel | ||||||||||||
getModel(query: string, defaultModel: NshmId)
|
||||||||||||
Defined in services/app.service.ts:598
|
||||||||||||
Returns the model to use.
Parameters :
Returns :
NshmId
|
Private getSiteClass | ||||||||||||
getSiteClass(query: string, defaultSiteClass: NehrpSiteClass)
|
||||||||||||
Defined in services/app.service.ts:611
|
||||||||||||
Returns the site class to use.
Parameters :
Returns :
NehrpSiteClass
|
init |
init()
|
Defined in services/app.service.ts:324
|
Initialize applicaiton.
Returns :
void
|
Private initialFormSet |
initialFormSet()
|
Defined in services/app.service.ts:622
|
Returns :
void
|
initialState |
initialState()
|
Defined in services/app.service.ts:357
|
Dynamic hazard compare initial state.
Returns :
AppState
|
onModelChange |
onModelChange()
|
Defined in services/app.service.ts:382
|
Returns the updated state for a model change.
Returns :
void
|
resetControlPanel |
resetControlPanel()
|
Defined in services/app.service.ts:415
|
Reset the control panel.
Returns :
void
|
resetSettings |
resetSettings()
|
Defined in services/app.service.ts:424
|
Reset the plot settings.
Returns :
void
|
resetState |
resetState()
|
Defined in services/app.service.ts:431
|
Returns :
void
|
Private responseSpectra | ||||||||||||
responseSpectra(hazardResponses: HazardResponse[], form: ControlForm)
|
||||||||||||
Defined in services/app.service.ts:681
|
||||||||||||
Create the response spectra for a specific model and for each source type available.
Parameters :
Returns :
Spectra[]
|
Private responseToPlots | ||||||||||||
responseToPlots(state: AppState, formGroup: FormGroupControls<ControlForm>)
|
||||||||||||
Defined in services/app.service.ts:706
|
||||||||||||
Create the plots.
Parameters :
Returns :
Map<string, NshmpPlot>
|
Private serviceCallUrl | ||||||||||||||||
serviceCallUrl(model: NshmId, formValues: ControlForm, nshmServices: NshmMetadata[])
|
||||||||||||||||
Defined in services/app.service.ts:735
|
||||||||||||||||
Returns the URL to call for a specific model.
Parameters :
Returns :
string
|
serviceCallUrls | ||||||||||||
serviceCallUrls(formValues: ControlForm, nshmServices: NshmMetadata[])
|
||||||||||||
Defined in services/app.service.ts:448
|
||||||||||||
Returns the URLs to call.
Parameters :
Returns :
string[]
|
Private setHazardPlots | ||||||||
setHazardPlots(plots: Map
|
||||||||
Defined in services/app.service.ts:750
|
||||||||
Creates and sets the default hazard plots.
Parameters :
Returns :
void
|
setLocation | ||||||||
setLocation(location: Location)
|
||||||||
Defined in services/app.service.ts:471
|
||||||||
Set the location form fields.
Parameters :
Returns :
void
|
Private setSpectraPlots | ||||||||
setSpectraPlots(plots: Map
|
||||||||
Defined in services/app.service.ts:816
|
||||||||
Creates and sets the default spectra plots.
Parameters :
Returns :
void
|
updateState | ||||||
updateState(state: Partial<AppState>)
|
||||||
Defined in services/app.service.ts:478
|
||||||
Parameters :
Returns :
void
|
Private updateUrl |
updateUrl()
|
Defined in services/app.service.ts:877
|
Returns :
void
|
Readonly formGroup |
Default value : this.formBuilder.group<ControlForm>(
this.defaultFormValues(),
)
|
Defined in services/app.service.ts:77
|
Private nshmpHazWs |
Default value : environment.webServices.nshmpHazWs
|
Defined in services/app.service.ts:73
|
nshmp-haz-ws web config |
Private serviceEndpoint |
Default value : this.nshmpHazWs.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:80
|
availableModels |
getavailableModels()
|
Defined in services/app.service.ts:99
|
Returns the available dynamic models.
Returns :
Signal<Parameter[]>
|
comparableModels |
getcomparableModels()
|
Defined in services/app.service.ts:106
|
Returns the models that can been compared with selected model.
Returns :
Signal<Parameter[]>
|
nshmService |
getnshmService()
|
Defined in services/app.service.ts:113
|
Returns the metadata of the NSHM observable.
Returns :
Signal<NshmMetadata>
|
plots |
getplots()
|
Defined in services/app.service.ts:124
|
Returns the
Returns :
Signal<Map<string, NshmpPlot>>
|
serviceCallInfo |
getserviceCallInfo()
|
Defined in services/app.service.ts:131
|
Returns the service call info.
Returns :
Signal<ServiceCallInfo>
|
serviceResponses |
getserviceResponses()
|
Defined in services/app.service.ts:138
|
Returns the service responses.
Returns :
Signal<ServiceResponses>
|
usage |
getusage()
|
Defined in services/app.service.ts:145
|
Return the usage for the selected model.
Returns :
Signal<HazardUsageResponse>
|
usageModelA |
getusageModelA()
|
Defined in services/app.service.ts:152
|
Return the usage for the selected model.
Returns :
Signal<HazardUsageResponse>
|
usageModelB |
getusageModelB()
|
Defined in services/app.service.ts:161
|
Return the usage for the selected model.
Returns :
Signal<HazardUsageResponse>
|
import {Location as LocationService} from '@angular/common';
import {HttpParams} from '@angular/common/http';
import {computed, Injectable, Signal, signal} from '@angular/core';
import {AbstractControl, FormBuilder, Validators} from '@angular/forms';
import {ActivatedRoute} from '@angular/router';
import {HazardService, hazardUtils} from '@ghsc/nshmp-lib-ng/hazard';
import {
FormGroupControls,
NshmpService,
ServiceCallInfo,
SpinnerService,
} from '@ghsc/nshmp-lib-ng/nshmp';
import {NshmpPlot, PlotOptions, plotUtils} from '@ghsc/nshmp-lib-ng/plot';
import {
HazardCalcResponse,
HazardRequestMetadata,
HazardResponse,
HazardUsageResponse,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-haz/www/hazard-service';
import {NshmMetadata} from '@ghsc/nshmp-utils-ts/libs/nshmp-haz/www/nshm-service';
import {Location} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/geo';
import {Imt, NehrpSiteClass} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/gmm';
import {
SourceType,
sourceTypeFromPascalCase,
sourceTypeToCapitalCase,
} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/model';
import {NshmId} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/nshm';
import {Parameter} 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 {devApps} from 'projects/nshmp-apps/src/shared/utils/applications.utils';
import {catchError, forkJoin, Observable} from 'rxjs';
import {
AppState,
ControlForm,
Plots,
ServiceResponses,
Spectra,
} from '../models/state.model';
import {HazardPlotsService} from './hazard-plots.service';
import {SpectraPlotsService} from './spectra-plots.service';
/**
* URL query.
*/
interface Query {
imt: string;
latitude: string;
longitude: string;
maxDirection: string;
model: string;
modelCompare: string;
returnPeriod: string;
siteClass: string;
truncate: string;
vs30: string;
}
/**
* Entrypoint to store for dynamic hazard compare application.
*/
@Injectable({
providedIn: 'root',
})
export class AppService
extends SharedService
implements AppServiceModel<AppState, ControlForm>
{
/** nshmp-haz-ws web config */
private nshmpHazWs = environment.webServices.nshmpHazWs;
/** Hazard endpoint */
private serviceEndpoint = this.nshmpHazWs.services.curveServices.hazard;
readonly formGroup = this.formBuilder.group<ControlForm>(
this.defaultFormValues(),
);
readonly state = signal<AppState>(this.initialState());
constructor(
private formBuilder: FormBuilder,
private spinnerService: SpinnerService,
private nshmpService: NshmpService,
private hazardPlotsService: HazardPlotsService,
private spectraPlotsService: SpectraPlotsService,
private hazardService: HazardService,
private route: ActivatedRoute,
private location: LocationService,
) {
super();
this.addValidators();
}
/**
* Returns the available dynamic models.
*/
get availableModels(): Signal<Parameter[]> {
return computed(() => this.state().availableModels);
}
/**
* Returns the models that can been compared with selected model.
*/
get comparableModels(): Signal<Parameter[]> {
return computed(() => this.state().comparableModels);
}
/**
* Returns the metadata of the NSHM observable.
*/
get nshmService(): Signal<NshmMetadata> {
return computed(() =>
this.state().nshmServices.find(
nshmService => nshmService.model === this.formGroup.getRawValue().model,
),
);
}
/**
* Returns the `Map` of the plots.
*/
get plots(): Signal<Map<string, NshmpPlot>> {
return computed(() => this.state().plots);
}
/**
* Returns the service call info.
*/
get serviceCallInfo(): Signal<ServiceCallInfo> {
return computed(() => this.state().serviceCallInfo);
}
/**
* Returns the service responses.
*/
get serviceResponses(): Signal<ServiceResponses> {
return computed(() => this.state().serviceResponses);
}
/**
* Return the usage for the selected model.
*/
get usage(): Signal<HazardUsageResponse> {
return computed(() => this.state().combinedUsage);
}
/**
* Return the usage for the selected model.
*/
get usageModelA(): Signal<HazardUsageResponse> {
return computed(() =>
this.state().usageResponses?.get(this.formGroup.getRawValue().model),
);
}
/**
* Return the usage for the selected model.
*/
get usageModelB(): Signal<HazardUsageResponse> {
return computed(() =>
this.state().usageResponses?.get(
this.formGroup.getRawValue().modelCompare,
),
);
}
addValidators(): void {
const controls = this.formGroup.controls;
this.addRequiredValidator(controls.imt);
this.addRequiredValidator(controls.latitude);
this.addRequiredValidator(controls.longitude);
this.addRequiredValidator(controls.model);
this.addRequiredValidator(controls.modelCompare);
this.addRequiredValidator(controls.vs30);
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}
<br>
(Could take 30+ seconds)
`,
);
const form = this.formGroup.getRawValue();
const modelUrl = this.serviceCallUrl(
form.model,
form,
this.state().nshmServices,
);
const modelCompareUrl = this.serviceCallUrl(
form.modelCompare,
form,
this.state().nshmServices,
);
const serviceCallInfo: ServiceCallInfo = {
...this.state().serviceCallInfo,
serviceCalls: [modelUrl, modelCompareUrl],
};
const calls: Observable<HazardCalcResponse>[] = [
modelUrl,
modelCompareUrl,
].map(url => this.nshmpService.callService$(url));
forkJoin(calls)
.pipe(catchError((error: Error) => this.nshmpService.throwError$(error)))
.subscribe(hazardResponses => {
if (hazardResponses.length !== 2) {
throw new Error('Does not contain two responses');
}
const modelA = hazardResponses[0];
const modelB = hazardResponses[1];
const serviceResponses: ServiceResponses = {
modelA: {
hazardResponse: modelA,
model: form.model,
spectra: this.responseSpectra(modelA.response.hazardCurves, form),
},
modelB: {
hazardResponse: modelB,
model: form.modelCompare,
spectra: this.responseSpectra(modelB.response.hazardCurves, form),
},
};
this.updateState({serviceCallInfo, serviceResponses});
this.createPlots();
spinnerRef.close();
});
}
/**
* 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});
}
/**
* Initial state for the control panel,
*/
defaultFormValues(): ControlForm {
return {
...hazardUtils.hazardDefaultFormValues(),
imt: Imt.PGA,
modelCompare: null,
sourceType: sourceTypeToCapitalCase(SourceType.TOTAL),
vs30: 760,
};
}
/**
* 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.
*/
init(): void {
this.spinnerService.show(SpinnerService.MESSAGE_METADATA);
this.hazardService
.dynamicNshms$<HazardRequestMetadata>(
`${this.nshmpHazWs.url}${this.nshmpHazWs.services.nshms}`,
this.serviceEndpoint,
)
.pipe(catchError((error: Error) => this.nshmpService.throwError$(error)))
.subscribe(({models, nshmServices, usageResponses}) => {
this.spinnerService.remove();
const serviceCallInfo: ServiceCallInfo = {
...this.state().serviceCallInfo,
usage: nshmServices.map(
service => `${service.url}${this.serviceEndpoint}`,
),
};
this.updateState({
availableModels: models,
nshmServices,
serviceCallInfo,
usageResponses,
});
this.onModelChange();
this.initialFormSet();
});
}
/**
* Dynamic hazard compare initial state.
*/
initialState(): AppState {
return {
availableModels: [],
combinedUsage: null,
comparableModels: [],
nshmServices: [],
plots: this.defaultPlots(),
serviceCallInfo: {
serviceCalls: [],
serviceName: 'Dynamic Hazard Curves',
usage: [],
},
serviceResponses: {
modelA: null,
modelB: null,
},
usageResponses: null,
};
}
/**
* Returns the updated state for a model change.
*
* @param state The current application state
*/
onModelChange(): void {
const comparableModels = this.getComparableModels();
const defaultComparableModel = [...comparableModels]?.pop()?.value ?? null;
const combinedUsage = this.getCombinedUsage(
this.state().usageResponses,
this.formGroup.getRawValue().model,
defaultComparableModel,
);
if (
this.formGroup.getRawValue().modelCompare !==
(defaultComparableModel as NshmId)
) {
this.formGroup.patchValue({
modelCompare: defaultComparableModel as NshmId,
});
}
this.updateState({
combinedUsage,
comparableModels,
plots: this.initialState().plots,
serviceCallInfo: {
...this.state().serviceCallInfo,
serviceCalls: [],
},
serviceResponses: this.initialState().serviceResponses,
});
}
/**
* Reset the control panel.
*/
resetControlPanel(): void {
this.formGroup.reset(this.defaultFormValues());
this.resetState();
this.onModelChange();
}
/**
* Reset the plot settings.
*/
resetSettings(): void {
super.resetPlotSettings({
currentPlots: this.state().plots,
defaultPlots: this.defaultPlots(),
});
}
resetState(): void {
this.updateState({
plots: this.initialState().plots,
serviceCallInfo: {
...this.state().serviceCallInfo,
serviceCalls: [],
},
});
}
/**
* Returns the URLs to call.
*
* @param formValues The control panel form values
* @param nshmServices The NSHM service metadata
* @param serviceEndpoint The service endpoint to call
*/
serviceCallUrls(
formValues: ControlForm,
nshmServices: NshmMetadata[],
): string[] {
const {imt, latitude, longitude, model, modelCompare, vs30} = formValues;
const services = [model, modelCompare].map(model =>
nshmServices.find(service => service.model === model),
);
const urls = services.map(
nshmService =>
`${nshmService.url}${this.serviceEndpoint}/${longitude}/${latitude}/${vs30}?imt=${imt}`,
);
return urls;
}
/**
* Set the location form fields.
*
* @param location The location
*/
setLocation(location: Location): void {
this.formGroup.patchValue({
latitude: location.latitude,
longitude: location.longitude,
});
}
updateState(state: Partial<AppState>): void {
this.state.set({
...this.state(),
...state,
});
}
private addRequiredValidator(control: AbstractControl): void {
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.
*
* @param usageResponses The usages
* @param model The current selected model
* @param comparableModel The current comparable model
*/
private getCombinedUsage(
usageResponses: Map<string, HazardUsageResponse>,
model: NshmId,
comparableModel: string | null,
): HazardUsageResponse {
let combinedUsage = usageResponses.get(model);
if (comparableModel !== null) {
combinedUsage = this.combineUsages([
usageResponses.get(model),
usageResponses.get(comparableModel),
]);
}
return combinedUsage;
}
/**
* Returns the available models that are comparable to the select model.
*
* @param state The application state
*/
private getComparableModels(): Parameter[] {
const formValues = this.formGroup.getRawValue();
const state = this.state();
const currentNshmService = state.nshmServices.find(
nshmService => nshmService.model === formValues.model,
);
const comparableServices = state.nshmServices.filter(
nshmService =>
nshmService.model !== currentNshmService.model &&
nshmService.project === currentNshmService.project,
);
return state.availableModels.filter(model =>
comparableServices.find(
service => service.model.toString() === model.value,
),
);
}
/**
* Returns the IMT to use.
*
* @param query The query value
* @param defaultImt The default IMT
*/
private getImt(query: string, defaultImt: Imt): Imt {
return (
Object.values(Imt).find(imt => imt.toString() === query) ?? defaultImt
);
}
/**
* Returns the model to use.
*
* @param query The query model
* @param defaultModel The default model
*/
private getModel(query: string, defaultModel: NshmId): NshmId {
return (
Object.values(NshmId).find(model => model.toString() === query) ??
defaultModel
);
}
/**
* Returns the site class to use.
*
* @param query The query value
* @param defaultSiteClass The default site class
*/
private getSiteClass(
query: string,
defaultSiteClass: NehrpSiteClass,
): NehrpSiteClass {
return (
Object.values(NehrpSiteClass).find(
siteClass => siteClass.toString() === query,
) ?? defaultSiteClass
);
}
private initialFormSet(): void {
const query = this.route.snapshot.queryParams as Query;
const defaultValues = this.defaultFormValues();
const formValues: ControlForm = {
commonReturnPeriods: defaultValues.commonReturnPeriods,
imt: this.getImt(query.imt, defaultValues.imt),
latitude: defaultValues.latitude,
longitude: defaultValues.longitude,
maxDirection:
query.maxDirection !== undefined
? (JSON.parse(query.maxDirection) as boolean)
: defaultValues.maxDirection,
model: this.getModel(query.model, defaultValues.model),
modelCompare: this.getModel(
query.modelCompare,
defaultValues.modelCompare,
),
returnPeriod: query.returnPeriod
? Number.parseInt(query.returnPeriod, 10)
: defaultValues.returnPeriod,
siteClass: this.getSiteClass(
query.siteClass,
defaultValues.siteClass as NehrpSiteClass,
),
sourceType: null,
truncate:
query.truncate !== undefined
? (JSON.parse(query.truncate) as boolean)
: defaultValues.truncate,
vs30: query.vs30 ? Number.parseFloat(query.vs30) : defaultValues.vs30,
};
this.formGroup.patchValue(formValues);
this.formGroup.patchValue({
latitude: query.latitude
? Number.parseFloat(query.latitude)
: defaultValues.latitude,
longitude: query.longitude
? Number.parseFloat(query.longitude)
: defaultValues.longitude,
});
if (this.formGroup.valid) {
this.nshmpService.selectPlotControl();
this.callService();
} else if (this.formGroup.getRawValue() !== defaultValues) {
this.formGroup.markAsDirty();
}
this.formGroup.valueChanges.subscribe(() => this.updateUrl());
}
/**
* Create the response spectra for a specific model and for each source type available.
*
* @param hazardResponses The hazard responses
* @param form The control form values
*/
private responseSpectra(
hazardResponses: HazardResponse[],
form: ControlForm,
): Spectra[] {
const spectra: Spectra[] = [];
const sourceTypes = [...hazardResponses]
.shift()
.data.map(data => data.component);
sourceTypes.forEach(sourceType => {
form.sourceType = sourceType;
spectra.push({
responseSpectra: hazardUtils.responseSpectra(hazardResponses, form),
sourceType: sourceTypeFromPascalCase(sourceType),
});
});
return spectra;
}
/**
* Create the plots.
*
* @param state The app state
*/
private responseToPlots(
state: AppState,
formGroup: FormGroupControls<ControlForm>,
): Map<string, NshmpPlot> {
if (
state.serviceResponses.modelA === null ||
state.serviceResponses.modelB === null
) {
return state.plots;
}
const hazardPlots = this.hazardPlotsService.createHazardPlots(
state,
formGroup,
);
const spectraPlots = this.spectraPlotsService.createSpectraPlots(
state,
formGroup,
);
return new Map([...hazardPlots.entries(), ...spectraPlots.entries()]);
}
/**
* 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}`;
}
/**
* Creates and sets the default hazard plots.
*
* @param plots The map of the plots to set
*/
private setHazardPlots(plots: Map<string, NshmpPlot>): void {
const hazardXLabel = 'Ground Motion (g)';
const hazardYLabel = 'Annual Frequency of Exceedence';
const hazardPlotData = plotUtils.defaultPlot({
id: 'hazard-curves',
mobileOptions: plotOptions,
options: plotOptions,
title: 'Hazard Curves',
xLabel: hazardXLabel,
yLabel: hazardYLabel,
});
plots.set(Plots.HAZARD, {
label: 'Hazard Curves',
plotData: hazardPlotData,
settingsForm: plotUtils.plotSettingsToFormGroup({
config: hazardPlotData.config,
layout: plotUtils.plotlyLayoutToSettings(hazardPlotData.layout),
}),
});
const hazardDiffPlotData = plotUtils.defaultPlot({
id: 'hazard-curves-differences',
mobileOptions: diffPlotOptions,
options: diffPlotOptions,
title: 'Hazard Curves: % Difference',
xLabel: 'Ground Motion (g)',
yLabel: '% Difference',
});
plots.set(Plots.HAZARD_DIFFERENCES, {
label: 'Hazard Curve Differences',
plotData: hazardDiffPlotData,
settingsForm: plotUtils.plotSettingsToFormGroup({
config: hazardDiffPlotData.config,
layout: plotUtils.plotlyLayoutToSettings(hazardDiffPlotData.layout),
}),
});
const hazardComponentsPlotData = plotUtils.defaultPlot({
id: 'hazard-component-curves',
mobileOptions: plotOptions,
options: plotOptions,
title: 'Hazard Components Curves',
xLabel: hazardXLabel,
yLabel: hazardYLabel,
});
plots.set(Plots.HAZARD_COMPONENTS, {
label: 'Hazard Component Curves',
plotData: hazardComponentsPlotData,
settingsForm: plotUtils.plotSettingsToFormGroup({
config: hazardComponentsPlotData.config,
layout: plotUtils.plotlyLayoutToSettings(
hazardComponentsPlotData.layout,
),
}),
});
}
/**
* Creates and sets the default spectra plots.
*
* @param plots The map of the plots to set
*/
private setSpectraPlots(plots: Map<string, NshmpPlot>): void {
const spectraXLabel = 'Spectral Period (s)';
const spectraYLabel = 'Ground Motion (g)';
const spectrumPlotData = plotUtils.defaultPlot({
id: 'response-spectrum',
mobileOptions: plotOptions,
options: plotOptions,
title: 'Uniform Hazard Response Spectra',
xLabel: spectraXLabel,
yLabel: spectraYLabel,
});
plots.set(Plots.SPECTRUM, {
label: 'Spectrum',
plotData: spectrumPlotData,
settingsForm: plotUtils.plotSettingsToFormGroup({
config: spectrumPlotData.config,
layout: plotUtils.plotlyLayoutToSettings(spectrumPlotData.layout),
}),
});
const spectrumDiffPlotData = plotUtils.defaultPlot({
id: 'spectrum-differences',
mobileOptions: diffPlotOptions,
options: diffPlotOptions,
title: 'Spectrum: % Difference',
xLabel: 'Spectral Period (s)',
yLabel: '% Difference',
});
plots.set(Plots.SPECTRUM_DIFFERENCES, {
label: 'Spectrum Differences',
plotData: spectrumDiffPlotData,
settingsForm: plotUtils.plotSettingsToFormGroup({
config: spectrumDiffPlotData.config,
layout: plotUtils.plotlyLayoutToSettings(spectrumDiffPlotData.layout),
}),
});
const spectraComponentsPlotData = plotUtils.defaultPlot({
id: 'spectra-component-curves',
mobileOptions: plotOptions,
options: plotOptions,
title: 'Spectra Components Curves',
xLabel: spectraXLabel,
yLabel: spectraYLabel,
});
plots.set(Plots.SPECTRUM_COMPONENTS, {
label: 'Spectra Component Curves',
plotData: spectraComponentsPlotData,
settingsForm: plotUtils.plotSettingsToFormGroup({
config: spectraComponentsPlotData.config,
layout: plotUtils.plotlyLayoutToSettings(
spectraComponentsPlotData.layout,
),
}),
});
}
private updateUrl(): void {
const value = this.formGroup.getRawValue();
const query: Query = {
imt: value.imt,
latitude: value.latitude.toFixed(),
longitude: value.longitude.toFixed(),
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.location.replaceState(
devApps().hazard.dynamicCompare.routerLink,
new HttpParams().appendAll({...query}).toString(),
);
}
}
const plotOptions: PlotOptions = {
layout: {
aspectRatio: hazardUtils.HAZARD_ASPECT_RATIO,
},
};
const diffPlotOptions: PlotOptions = {
layout: {
aspectRatio: '3:1',
yaxis: {
range: [-100, 100],
type: 'linear',
},
},
};