You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{Component,OnDestroy,OnInit,ViewChild}from'@angular/core';import{ActivatedRoute,Params,Router}from'@angular/router';import{HttpClient}from'@angular/common/http';import{MatSidenav}from'@angular/material/sidenav';import{AbstractControl,FormArray,FormControl,UntypedFormArray,UntypedFormBuilder,UntypedFormControl,UntypedFormGroup,ValidationErrors,Validators,}from'@angular/forms';import{DispatchService}from'../../../services/dispatch/dispatch.service';import{SimulationService}from'../../../services/simulation/simulation.service';import{CombineApiService}from'../../../services/combine-api/combine-api.service';import{_IntrospectNewProject,CreateArchiveFromSedDoc,CustomizableSedDocumentData,FormStepData,IntrospectNewProject,OntologyTerm,OntologyTermsMap,SimulationProjectUtilData,SimulationProjectUtilLoaderService,SimulatorsData,SimulatorSpecs,SimulatorSpecsMap,}from'@biosimulations/simulation-project-utils';import{Simulation}from'../../../datamodel';import{ALGORITHM_SUBSTITUTION_POLICIES,AlgorithmSubstitution,AlgorithmSubstitutionPolicy,AlgorithmSubstitutionPolicyLevels,AlgorithmSummary,CombineArchiveSedDocSpecs,CombineArchiveSedDocSpecsContent,EnvironmentVariable,Purpose,ReRunQueryParams,SedDocument,SedModel,SedModelAttributeChangeasCommonAttributeChange,SedModelChange,SedSimulation,SimulationRun,SimulationRunStatus,SimulationType,}from'@biosimulations/datamodel/common';import{BIOSIMULATIONS_FORMATS}from'@biosimulations/ontology/extra-sources';import{Observable,Subscription}from'rxjs';import{ConfigService}from'@biosimulations/config/angular';import{MatSnackBar}from'@angular/material/snack-bar';import{FileInput}from'@biosimulations/material-file-input';import{CreateMaxFileSizeValidator,INTEGER_VALIDATOR}from'@biosimulations/shared/ui';import{SedModelAttributeChange,SedModelAttributeChangeTypeEnum,SedModelChangeasClientSedChange,SedTarget,}from'@biosimulations/combine-api-angular-client';// eslint-disable-next-line @nrwl/nx/enforce-module-boundariesimport{_SubmitFormData}from'../../../../../../../libs/simulation-project-utils/simulation-project-utils/src/lib/ui/create-project/create-project/project-submission';import{ViewService}from'@biosimulations/simulation-runs/service';import{Visualization,VisualizationList}from'@biosimulations/datamodel-simulation-runs';interfaceSimulatorIdNameDisabled{id: string;name: string;disabled: boolean;}interfaceSimulator{id: string;name: string;}interfaceSimulatorPolicy{minPolicy: AlgorithmSubstitutionPolicy;simulator: Simulator;}interfaceAlgorithm{id: string;name: string;simulatorPolicies: {[simulator: string]: SimulatorPolicy};disabled: boolean;}interfaceIntrospectionModelDataextendsFormStepData{modelFormat: string;modelFile?: string;modelUrl?: string;}interfaceIntrospectionMethodDataextendsFormStepData{frameworkId: string;simulationType: string;algorithmId: string;}interfaceArchiv
8000
eFormDataextendsFormStepData{modelFormat: string;modelFile?: string;modelUrl?: string;frameworkId: string;simulationType: string;algorithmId: string;}
@Component({selector: 'biosimulations-customize-simulation',templateUrl: './customize-simulation.component.html',styleUrls: ['./customize-simulation.component.scss'],})exportclassCustomizeSimulationComponentimplementsOnInit,OnDestroy{publicformGroup: UntypedFormGroup;publicvariablesFormGroup: UntypedFormGroup;// Form control option listspublicmodelFormats: OntologyTerm[]=[];publicsimulators: SimulatorIdNameDisabled[]=[];publicsimulatorVersions: string[]=[];publicsimulationAlgorithms: Algorithm[]=[];publicalgorithmSubstitutionPolicies: AlgorithmSubstitutionPolicy[];// Data loaded from configspublicexampleCombineArchivesUrl: string;publicemailUrl!: string;publicisReRun=false;publicneedsLicense=false;publicsimMethodData!: FormStepData;publicmodelData!: FormStepData;publicintrospectionData$!: Observable<CustomizableSedDocumentData>;publicoptions: SedModelAttributeChange[]=[];publicmodelChanges: UntypedFormGroup[]=[];publicsimParams!: ReRunQueryParams;publicuploadedSedDoc!: SedDocument;publiccontainsSimulationChanges=false;publicuseDropdown=true;publicoriginalModelChanges: SedModelChange[]=[];publicreRunId!: string;publicvizList: Visualization[]=[];publicviz$!: Observable<VisualizationList[]>;publicvisualization!: Visualization;publictriggerViz=false;publicgridLayout=false;publicgrid='grid';publicauto='auto';
@ViewChild('sidenav')sidenav!: MatSidenav;publicintrospectionBtnColor='var(--accent-darker-color)';publicviewBtnColor='var(--accent-darker-color)';publicviewToggleMsg!: string;// Lifecycle statepublicsubmitPushed=false;publicemailEnabled=false;publicfilteredRows: any[][]=[];publicisRtl=true;publicshouldDisplayCard=true;privatesubscriptions: Subscription[]=[];// Data loaded from networkprivatemodelFormatsMap?: OntologyTermsMap;privatesimulationAlgorithmsMap?: Record<string,Algorithm>;privatesimulatorSpecsMap?: SimulatorSpecsMap;publicconstructor(privateconfig: ConfigService,privaterouter: Router,privateformBuilder: UntypedFormBuilder,privatedispatchService: DispatchService,privatesimulationService: SimulationService,privatecombineApiService: CombineApiService,privatesnackBar: MatSnackBar,privateloader: SimulationProjectUtilLoaderService,privateactivateRoute: ActivatedRoute,privatehttpClient: HttpClient,privatesharedViewService: ViewService,){this.formGroup=this.formBuilder.group({projectFile: ['',[CreateMaxFileSizeValidator(config)]],projectUrl: ['',[]],modelFormats: ['',[]],simulationAlgorithms: ['',[]],simulationAlgorithmSubstitutionPolicy: [AlgorithmSubstitutionPolicyLevels.SAME_FRAMEWORK,[]],simulator: ['',[Validators.required]],simulatorVersion: ['',[Validators.required]],academicPurpose: [true],cpus: [1,[Validators.required,Validators.min(1),Validators.max(24),INTEGER_VALIDATOR]],memory: [8,[Validators.required,Validators.min(0),Validators.max(192)]],// in GBmaxTime: [20,[Validators.required,Validators.min(0),Validators.max(20*24*60)]],// in minname: ['',[Validators.required]],email: ['',[Validators.email]],emailConsent: [false],},{validators: this.formValidator.bind(this),},);this.algorithmSubstitutionPolicies=ALGORITHM_SUBSTITUTION_POLICIES.filter((policy)=>{constminPolicy=AlgorithmSubstitutionPolicyLevels.SAME_METHOD;constmaxPolicy=AlgorithmSubstitutionPolicyLevels.SAME_FRAMEWORK;returnpolicy.level>=minPolicy&&policy.level<=maxPolicy;});this.formGroup.controls.modelFormats.disable();this.formGroup.controls.simulationAlgorithms.disable();this.formGroup.controls.simulationAlgorithmSubstitutionPolicy.disable();this.formGroup.controls.simulator.disable();this.formGroup.controls.simulatorVersion.disable();constexampleCombineArchivesUrlTokens=['https://github.com',this.config.appConfig.exampleCombineArchives.repoOwnerName,'tree',this.config.appConfig.exampleCombineArchives.repoRef,config.appConfig.exampleCombineArchives.repoPath,];this.exampleCombineArchivesUrl=exampleCombineArchivesUrlTokens.join('/');this.emailUrl='mailto:'+config.email;this.variablesFormGroup=this.formBuilder.group({rows: this.formBuilder.array([]),selectedRowIndex: [null],parameterSelections: this.formBuilder.array([]),modelFiles: this.formBuilder.array([]),});}// Life cyclepublicngOnInit(): void{constloadObs=this.loader.loadSimulationUtilData();constloadSub=loadObs.subscribe(this.loadComplete.bind(this));this.subscriptions.push(loadSub);constuserEmailAddress=this.formGroup.value.email;this.formGroup.valueChanges.subscribe((values)=>{constcurrentEmailAddress=values.email;if(currentEmailAddress!=userEmailAddress){this.formGroup.value.emailConsent=true;}});this.changeBtnTooltip();}publicngOnDestroy(): void{this.subscriptions.forEach((subscription)=>subscription.unsubscribe());}publicrenderViz(visualization: Visualization): void{this.visualization=visualization;}publicsetupSearchFilter(index: number){constsearchControl=this.parameterSelections.at(index).get('searchControl')asFormControl;searchControl.valueChanges.subscribe((value)=>{this.filterRows(value,index);});}publictoggleSidenav(){this.sidenav.toggle();}publicfilterRows(searchValue: string,index: number): void{// TODO: complete this implementationconstrowsArray=this.rows.valueasArray<any>;if(!searchValue){this.filteredRows[index]=rowsArray;}else{this.filteredRows[index]=rowsArray.filter((row)=>row.name.toLowerCase().includes(searchValue.toLowerCase())||row.default.toString().toLowerCase().includes(searchValue.toLowerCase()),);}}publicnavigateToRun(): void{this.triggerViz=!this.triggerViz;this.gridLayout=!this.gridLayout;this.handleBtnColor();}privatehandleBtnColor(): void{if(this.triggerViz){this.introspectionBtnColor='var(--tertiary-darker-color)';}else{this.introspectionBtnColor='var(--accent-darker-color)';}}publicchangeParamsLayout(checked: boolean): void{console.log(`CHECKED: ${checked}`);if(checked){this.useDropdown=false;}else{this.useDropdown=true;}}publicchangeParamsLayoutButton(): void{this.useDropdown=!this.useDropdown;if(this.useDropdown){this.viewBtnColor='var(--accent-darker-color)';}else{this.viewBtnColor='var(--tertiary-darker-color)';}this.changeBtnTooltip();}privatechangeBtnTooltip(): void{if(this.useDropdown){this.viewToggleMsg='Toggle Grid View';}else{this.viewToggleMsg='Toggle Dropdown View';}}publicgetrows(): UntypedFormArray{returnthis.variablesFormGroup.get('rows')asUntypedFormArray;}publicgetSelectedRowNewValueControl(): FormControl{constindex=this.variablesFormGroup.get('selectedRowIndex')?.value;returnthis.rows.at(index).get('newValue')asFormControl;}publicaddParameterRow(modelChange: SedModelAttributeChange): void{if(modelChange.id!==null){constnewRow=this.formBuilder.group({name: [{value: modelChange.nameasstring,disabled: true}],default: [{value: +modelChange.newValue,disabled: true}],target: [modelChange.target],id: [modelChange.idasstring],_type: [modelChange._type],newValue: [''],});this.rows.push(newRow);this.modelChanges.push(newRow);}else{console.log('null id');}}publicenableEmail(checked: boolean): void{this.emailEnabled=checked;}publicclearOverrides(checked: boolean): void{/* Clear original simulation parameter changes/overrides if checked */if(checked){this.parameterSelections.removeAt(this.parameterSelections.length-1);constoriginalChange=this.uploadedSedDoc.models[0].changes.pop();this.originalModelChanges.push(originalChangeasSedModelChange);}else{this.originalModelChanges.forEach((change: SedModelChange): void=>{this.uploadedSedDoc.models[0].changes.push(changeasany);});}}publicsetAttributesFromQueryParams(): void{/* Set component attributes from Query params */this.activateRoute.queryParams.subscribe((params: ReRunQueryParams)=>{this.simParams=params;// TODO: set urls herethis.reRunId=params.runIdasstring;if(params.projectUrl){this.isReRun=true;}this.modelData={modelUrl: params.modelUrlasstring,modelFormat: params.modelFormatasstring,};this.simMethodData={simulationType: params.simulationTypeasSimulationType,framework: params.modelingFrameworkasstring,algorithm: params.simulationAlgorithmasstring,};this.needsLicense=(params.simulator?.includes('cobra')||params.simulator?.includes('rba'))asboolean;});consthandler=this.archiveError.bind(this);this.introspectionData$=IntrospectNewProject(this.httpClient,this.modelData,this.simMethodData,handler,)asObservable<CustomizableSedDocumentData>;}publicgetparameterSelections(): FormArray{returnthis.variablesFormGroup.get('parameterSelections')asFormArray;}publicgetDefault(index: number): any{constselectedRowIndex=this.parameterSelections.at(index).get('selectedRowIndex')?.value;returnselectedRowIndex!==null ? this.rows.at(selectedRowIndex).get('default')?.value : '';}publicaddNewParameterSelection(): void{constnewParameterSelection=this.formBuilder.group({selectedRowIndex: [null],searchControl: [''],newValue: [''],});this.parameterSelections.push(newParameterSelection);this.setupSearchFilter(this.parameterSelections.length-1);}publicgetNewValueControl(index: number): FormControl{returnthis.parameterSelections.at(index).get('newValue')asFormControl;}publicpopulateParamsForm(): void{/* Populate form with introspected data */this.introspectionData$.subscribe((data: CustomizableSedDocumentData)=>{data.modelChanges.forEach((change: ClientSedChange)=>{switch(change){casechangeasSedModelAttributeChange:
this.addParameterRow(change);}});});this.addNewParameterSelection();}publicisOptionSelected(idx: number,currentIndex: number): boolean{returnthis.parameterSelections.controls.some((control: any,i)=>{returni!==currentIndex&&control.value.selectedRowIndex===idx;});}privatearchiveError(): void{console.log(`error.`);}privateloadComplete(data: SimulationProjectUtilData): void{constcuratedAlgSubs: AlgorithmSubstitution[]=data.algorithmSubstitutions;constsimulatorsData: SimulatorsData=data.simulators;constparams: Params=data.params;this.simulatorSpecsMap=simulatorsData.simulatorSpecs;constalgSubs: AlgorithmSubstitution[]=curatedAlgSubs ? curatedAlgSubs : this.getBackupAlgSubs(simulatorsData);this.simulationAlgorithmsMap=this.getSimulationAlgorithmsMap(algSubs,simulatorsData);this.simulationAlgorithms=Object.values(this.simulationAlgorithmsMap);this.simulationAlgorithms.sort((a: Algorithm,b: Algorithm): number=>{returna.name.localeCompare(b.name,undefined,{numeric: true});});this.modelFormatsMap=simulatorsData.modelFormats;this.modelFormats=Object.values(this.modelFormatsMap);this.modelFormats.sort((a: OntologyTerm,b: OntologyTerm): number=>{returna.name.localeCompare(b.name,undefined,{numeric: true});});constsimulatorSpecs=Object.values(this.simulatorSpecsMap);this.simulators=simulatorSpecs.map((specs: SimulatorSpecs): SimulatorIdNameDisabled=>{return{id: specs.id,name: specs.name,disabled: false,};});this.simulators.sort((a: SimulatorIdNameDisabled,b: SimulatorIdNameDisabled): number=>{returna.name.localeCompare(b.name,undefined,{numeric: true});});// Enable select menusthis.formGroup.controls.modelFormats.enable();this.formGroup.controls.simulationAlgorithms.enable();this.formGroup.controls.simulator.enable();if(curatedAlgSubs){this.formGroup.controls.simulationAlgorithmSubstitutionPolicy.setValue(AlgorithmSubstitutionPolicyLevels.SAME_FRAMEWORK,);this.formGroup.controls.simulationAlgorithmSubstitutionPolicy.enable();}else{this.formGroup.controls.simulationAlgorithmSubstitutionPolicy.setValue(AlgorithmSubstitutionPolicyLevels.SAME_METHOD,);}this.setControlsFromParams(params,this.simulatorSpecsMap);// Gather introspection data and populate model formthis.setAttributesFromQueryParams();this.populateParamsForm();constviz$=this.sharedViewService.getVisualizations(this.reRunId);this.viz$=viz$;if(viz$){viz$.subscribe((value: VisualizationList[])=>{value.forEach((vizList: VisualizationList)=>{vizList.visualizations.forEach((visualization: Visualization)=>{this.vizList.push(visualization);});});});}}publicremoveModelChangeField(index: number): void{this.parameterSelections.removeAt(index);}// Form SubmissionpublicgatherModelChanges(): void{// TODO: more accurately handle the number of modelsconstsedModel: SedModel=this.uploadedSedDoc.models.pop()asSedModel;// get values from form gridif(!this.useDropdown){this.rows.controls.forEach((val: AbstractControl<any,any>,i: number)=>{constrowValueGroup=valasUntypedFormGroup;constnewVal=rowValueGroup.controls.newValue.value;if(newVal){this.containsSimulationChanges=true;constparamChange: SedModelAttributeChange={_type: rowValueGroup.controls._type.value,newValue: newVal,target: rowValueGroup.controls.target.value,id: rowValueGroup.controls.id.value,name: rowValueGroup.controls.name.value,};sedModel.changes.push(paramChange);}else{return;}});}else{// get values from dropdownconstallParams=this.getAllParameterSelections();this.containsSimulationChanges=allParams.length>=1;allParams.forEach((paramChange: SedModelAttributeChange,i: number)=>{sedModel.changes.push(paramChange);});}// update the uploaded documentthis.uploadedSedDoc.models.push(sedModel);}publicgetAllParameterSelections(): SedModelAttributeChange[]|any[]{returnthis.parameterSelections.controls.map((group: AbstractControl<any,any>)=>{constselectedIndex=group.get('selectedRowIndex')?.value;constselectedRow=selectedIndex!==null ? this.rows.at(selectedIndex).value : null;constnewValue=group.get('newValue')?.value;if(selectedRow&&newValue){constselection: SedModelAttributeChange={name: selectedRow.name,target: selectedRow.target,id: selectedRow.id,_type: selectedRow._type,newValue: newValue,};returnselectionasSedModelAttributeChange;}});}publiccreateNewArchive(queryParams: ReRunQueryParams): Observable<string>|null{consterrorHandler=this.archiveError.bind(this);constform=newFormData();form.append('modelUrl',queryParams.modelUrlasstring);form.append('modelingFramework',queryParams.modelingFrameworkasstring);form.append('simulationType',queryParams.simulationTypeasstring);form.append('simulationAlgorithm',queryParams.simulationAlgorithmasstring);constintrospectedSedDoc$=_IntrospectNewProject(this.httpClient,formasFormData,queryParams.modelUrlasstring,errorHandler,);constarchive=CreateArchiveFromSedDoc(this.uploadedSedDocasSedDocument,queryParams.modelUrlasstring,queryParams.modelFormatasstring,queryParams.modelFileasFile,queryParams.imageFileUrlsasstring[],);if(!archive){returnnull;}constformData=newFormData();formData.append('specs',JSON.stringify(archive));constarchiveSubmission$=_SubmitFormData(formData,this.httpClient,errorHandler);if(archiveSubmission$){console.log(`Archive submission successful!`);returnarchiveSubmission$;}else{console.log(`Not successfull`);returnnull;}}publichandleSimulationParams(): void{// 1. update this.uploadedSedDoc if there are changesthis.gatherModelChanges();if(!this.containsSimulationChanges){console.log(`No changes.`);return;}// 2. create a new archive using BOTH the rerun query params and the uploadedSedDocconstarchiveResponse$=this.createNewArchive(this.simParams)asObservable<string>;}publiconFormSubmit(): void{/* Create customized archive and Submit the form for simulation */this.submitPushed=true;// Read simulation params form and create a new archive if there are changes detectedthis.handleSimulationParams();// ***Existing content:if(!this.formGroup.valid){return;}constsimulator: string=this.formGroup.value.simulator;constsimulatorVersion: string=this.formGroup.value.simulatorVersion;constcpus: number=this.formGroup.value.cpus;constmemory: number=this.formGroup.value.memory;// in GBconstmaxTime: number=this.formGroup.value.maxTime;// in minconstenvVars: EnvironmentVariable[]=[];constpurpose: Purpose=this.formGroup.value.academicPurpose ? Purpose.academic : Purpose.other;constname: string=this.formGroup.value.name;constemail: string|null=this.formGroup.value.email||null;if(this.emailEnabled&&!email){this.snackBar.open('You must provide a valid email address when consenting to email communication.','Ok',{duration: 5000,});return;}letsimulationResponse: Observable<SimulationRun>;constprojectUrl: string=this.formGroup.value.projectUrl;if(projectUrl){simulationResponse=this.dispatchService.submitJobForURL(projectUrl,simulator,simulatorVersion,cpus,memory,maxTime,envVars,purpose,name,email,);}else{constfileInput: FileInput=this.formGroup.value.projectFile;constprojectFile: File=fileInput.files[0];simulationResponse=this.dispatchService.submitJobForFile(projectFile,simulator,simulatorVersion,cpus,memory,maxTime,envVars,purpose,name,email,);}constsub=simulationResponse.subscribe((data: SimulationRun)=>this.processSimulationResponse(data,name,simulator,simulatorVersion,cpus,memory,maxTime,envVars,purpose,email,),);this.subscriptions.push(sub);window.scrollTo(0,0);}// Algorithms gettersprivategetSimulationAlgorithmsMap(algSubs: AlgorithmSubstitution[],simulatorsData: SimulatorsData,): Record<string,Algorithm>{constsimulationAlgorithmsMap: Record<string,Algorithm>={};constfilteredSubs=algSubs.filter((sub)=>sub.minPolicy.level<=AlgorithmSubstitutionPolicyLevels.SAME_FRAMEWORK,);filteredSubs.forEach((algorithmSubstitution: AlgorithmSubstitution): void=>{constmainAlg=algorithmSubstitution.algorithms[0];constaltAlg=algorithmSubstitution.algorithms[1];constsubstitutionPolicy=algorithmSubstitution.minPolicy;// Ensure main and alt algorithms are both in the map.[mainAlg,altAlg].forEach((algorithm: AlgorithmSummary): void=>{if(algorithm.idinsimulationAlgorithmsMap){return;}simulationAlgorithmsMap[algorithm.id]={id: algorithm.id,name: algorithm.name,simulatorPolicies: {},disabled: false,};});constsimulatorsForMainAlgorithm=simulatorsData.simulationAlgorithms[mainAlg.id]?.simulators;simulatorsForMainAlgorithm.forEach((simulatorId: string): void=>{constsimulator={id: simulatorId,name: simulatorsData.simulatorSpecs[simulatorId].name,};// All simulators returned for the main algorithm can be used with the main algorithm when the// policy is at least SAME_METHOD (always).simulationAlgorithmsMap[mainAlg.id].simulatorPolicies[simulatorId]={minPolicy: {id: 'SAME_METHOD',name: 'Same method',level: AlgorithmSubstitutionPolicyLevels.ANY,_type: substitutionPolicy._type,},simulator: simulator,};// All simulators returned for the main algorithm can be used with the alt algorithm when the// policy is at least as lenient as the policy for which the alt algorithm can switch with the main// algorithm.constcurrentAltAlgPolicy=simulationAlgorithmsMap[altAlg.id].simulatorPolicies[simulatorId];if(!currentAltAlgPolicy||substitutionPolicy.level<currentAltAlgPolicy.minPolicy.level){simulationAlgorithmsMap[altAlg.id].simulatorPolicies[simulatorId]={minPolicy: substitutionPolicy,simulator: simulator,};}});});returnsimulationAlgorithmsMap;}privategetBackupAlgSubs(simulatorsData: SimulatorsData): AlgorithmSubstitution[]{constalgorithmEntries=Object.entries(simulatorsData.simulationAlgorithms);returnalgorithmEntries.map((keyVal: [string,OntologyTerm]): AlgorithmSubstitution=>{constalg: AlgorithmSummary={_type: 'Algorithm',id: keyVal[1].id,name: keyVal[1].name,};return{_type: 'KisaoAlgorithmSubstitution',algorithms: [alg,alg],//minPolicy: ALGORITHM_SUBSTITUTION_POLICIES[AlgorithmSubstitutionPolicyLevels.SAME_METHOD],minPolicy: ALGORITHM_SUBSTITUTION_POLICIES[AlgorithmSubstitutionPolicyLevels.ANY],};});}// Callbacks for control value updates.publicprojectControlUpdated(): void{consturlValue=this.formGroup.controls.projectUrl.value;constfileValue=this.formGroup.controls.projectFile.value?.files?.[0];if(!urlValue
8000
&&!fileValue){this.resetProjectErrors();return;}constprojectFileTooBig=this.formGroup.hasError('maxSize','projectFile');consturlAndFileSelected=this.formGroup.hasError('multipleProjects');if(projectFileTooBig||urlAndFileSelected){return;}constarchive=urlValue ? urlValue : fileValue;constsub=this.combineApiService.getSpecsOfSedDocsInCombineArchive(archive).subscribe(this.archiveSedDocSpecsLoaded.bind(this));this.subscriptions.push(sub);}publicsimulatorControlUpdated(): void{if(!this.simulatorSpecsMap){return;}this.simulatorVersions=this.simulatorSpecsMap[this.formGroup.controls.simulator.value]?.versions||[];this.formGroup.controls.simulatorVersion.enable();this.formGroup.controls.simulatorVersion.setValue(this.simulatorVersions?.[0]||'');}publiccontrolImpactingEligibleSimulatorsUpdated(): void{constsimulatorSpecsMap=this.simulatorSpecsMap;if(!simulatorSpecsMap){return;}constalgSubPolicy=this.formGroup.value.simulationAlgorithmSubstitutionPolicy;constloadedSimulatorIds=Object.keys(simulatorSpecsMap);// Simulator must be supported by each selected model and algorithm to be eligible.consteligibleSimulators=loadedSimulatorIds.filter((simulatorId)=>{constselectedModelFormatIds=this.formGroup.value.modelFormats;for(constmodelFormatIdofselectedModelFormatIds){constmodelSimulators=this.modelFormatsMap?.[modelFormatId]?.simulatorsasSet<string>;if(!modelSimulators||!modelSimulators.has(simulatorId)){returnfalse;}}constselectedSimulationAlgorithmIds=this.formGroup.value.simulationAlgorithms;for(constsimulationAlgorithmIdofselectedSimulationAlgorithmIds){constpoliciesBySimulatorId=this.simulationAlgorithmsMap?.[simulationAlgorithmId]?.simulatorPolicies;if(!policiesBySimulatorId){returnfalse;}letsimulatorIdsForAlgorithm=Object.keys(policiesBySimulatorId);simulatorIdsForAlgorithm=simulatorIdsForAlgorithm.filter((simulatorId)=>{constsimulatorPolicy=policiesBySimulatorId[simulatorId];returnsimulatorPolicy&&simulatorPolicy.minPolicy.level<=algSubPolicy;});if(!simulatorIdsForAlgorithm.includes(simulatorId)){returnfalse;}}returntrue;});// Disable input checkboxes for model formats that are supported by none of the eligible simulators.this.modelFormats.forEach((modelFormat: OntologyTerm): void=>{consteligibleForModelFormat=eligibleSimulators.filter((simulatorId)=>modelFormat.simulators.has(simulatorId),);modelFormat.disabled=eligibleForModelFormat.length==0;});// Disable input checkboxes for algorithms that are supported by none of the eligible simulators.this.simulationAlgorithms.forEach((simulationAlgorithm: Algorithm): void=>{letsimulatorIdsForAlgorithm=Object.keys(simulationAlgorithm.simulatorPolicies);simulatorIdsForAlgorithm=simulatorIdsForAlgorithm.filter((simulatorId)=>{constsimulatorPolicy=simulationAlgorithm.simulatorPolicies[simulatorId];returnsimulatorPolicy.minPolicy.level<=algSubPolicy;});consteligibleForAlgorithm=eligibleSimulators.filter((simulatorId)=>simulatorIdsForAlgorithm.includes(simulatorId),);simulationAlgorithm.disabled=eligibleForAlgorithm.length==0;});// Disable input checkboxes for all simulators that are not eligible.this.simulators.forEach((simulator: SimulatorIdNameDisabled): void=>{simulator.disabled=!eligibleSimulators.includes(simulator.id);if(simulator.disabled&&simulator.id===this.formGroup.value.simulator){this.formGroup.controls.simulator.setValue(null);}});if(eligibleSimulators.length===1){this.formGroup.controls.simulator.setValue(eligibleSimulators[0]);}}// Network callbacksprivatearchiveSedDocSpecsLoaded(sedDocSpecs?: CombineArchiveSedDocSpecs): void{constsimulationAlgorithmsMap=this.simulationAlgorithmsMap;if(!sedDocSpecs||!simulationAlgorithmsMap){return;}constmodelFormats=newSet<string>();constsimulationAlgorithms=newSet<string>();letspecsContainUnsupportedModel=false;letspecsContainUnsupportedAlgorithm=false;// Confirm that every model and algorithm within the sed doc spec is supported.sedDocSpecs.contents.forEach((content: CombineArchiveSedDocSpecsContent): void=>{constsedDoc: SedDocument=content.location.value;this.uploadedSedDoc=sedDoc;sedDoc.models.forEach((model: SedModel): void=>{letedamId: string|null=null;for(constmodelingFormatofBIOSIMULATIONS_FORMATS){constsedUrn=modelingFormat?.biosimulationsMetadata?.modelFormatMetadata?.sedUrn;if(!sedUrn||!modelingFormat.id||!model.language.startsWith(sedUrn)){continue;}edamId=modelingFormat.id;}if(edamId){modelFormats.add(edamId);}else{specsContainUnsupportedModel=true;}letapiChange: SedModelAttributeChange;model.changes.forEach((change: SedModelChange)=>{switch(change){casechangeasCommonAttributeChange:
console.log(`Common attribute change!`);apiChange={_type: SedModelAttributeChangeTypeEnum.SedModelAttributeChange,newValue: change.newValue,target: change.targetasSedTarget,id: change.idasstring,name: change.name,};this.addParameterRow(apiChange);}});});sedDoc.simulations.forEach((sim: SedSimulation): void=>{constkisaoId=sim.algorithm.kisaoId;if(kisaoIdinsimulationAlgorithmsMap){simulationAlgorithms.add(kisaoId);}else{specsContainUnsupportedAlgorithm=true;}});});this.setUnsupportedModelErrorIsShown(specsContainUnsupportedModel);this.setUnsupportedAlgorithmErrorIsShown(specsContainUnsupportedAlgorithm);this.formGroup.controls.modelFormats.setValue(Array.from(modelFormats));this.formGroup.controls.simulationAlgorithms.setValue(Array.from(simulationAlgorithms));this.controlImpactingEligibleSimulatorsUpdated();}privateprocessSimulationResponse(data: SimulationRun,name: string,simulator: string,simulatorVersion: string,cpus: number,memory: number,// in GBmaxTime: number,// min minenvVars: EnvironmentVariable[],purpose: Purpose,email: string|null,): void{constsimulationId=data.id;constsimulatorDigest=data.simulatorDigest;constsubmitted=newDate(data.submitted);constupdated=newDate(data.submitted);constsimulation: Simulation={id: simulationId,name: name,email: email||undefined,simulator: simulator,simulatorVersion: simulatorVersion,simulatorDigest: simulatorDigest,cpus: cpus,memory: memory,maxTime: maxTime,envVars: envVars,purpose: purpose,submittedLocally: true,status: SimulationRunStatus.QUEUED,runtime: undefined,submitted: submitted,updated: updated,};this.simulationService.storeNewLocalSimulation(simulation);this.router.navigate(['/runs',simulationId]);this.showFormSubmittedSnackbar();}// Error handlingpublicshouldShowNoProjectError(): boolean{returnthis.formGroup.hasError('noProject')&&this.submitPushed;}publicshouldShowUnsupportedModelError(): boolean{consthasUnsupportedModel=this.formGroup.hasError('unsupportedFormats','modelFormats');return(this.submitPushed||this.formGroup.controls.modelFormats.touched)&&hasUnsupportedModel;}publicshouldShowUnsupportedAlgorithmError(): boolean{consthasUnsupportedAlgorithm=this.formGroup.hasError('unsupportedAlgorithms','simulationAlgorithms');return(this.submitPushed||this.formGroup.controls.simulationAlgorithms.touched)&&hasUnsupportedAlgorithm;}publicshouldShowSimulatorRequiredError(): boolean{returnthis.submitPushed&&this.formGroup.hasError('required','simulator');}publicshouldShowSimulatorVersionRequiredError(): boolean{returnthis.submitPushed&&this.formGroup.hasError('required','simulatorVersion');}publicshouldShowNameRequiredError(): boolean{returnthis.submitPushed&&this.formGroup.hasError('required','name');}privateresetProjectErrors(): void{this.formGroup.controls.modelFormats.setErrors({unsupportedFormats: null});this.formGroup.controls.modelFormats.updateValueAndValidity();this.formGroup.controls.simulationAlgorithms.setErrors({unsupportedAlgorithms: null});this.formGroup.controls.simulationAlgorithms.updateValueAndValidity();}privatesetUnsupportedModelErrorIsShown(shown: boolean): void{if(shown){this.formGroup.controls.modelFormats.setErrors({unsupportedFormats: true});this.formGroup.controls.modelFormats.markAsTouched();}else{this.formGroup.controls.modelFormats.setErrors({unsupportedFormats: null});this.formGroup.controls.modelFormats.updateValueAndValidity();}}privatesetUnsupportedAlgorithmErrorIsShown(shown: boolean): void{if(shown){this.formGroup.controls.simulationAlgorithms.setErrors({unsupportedAlgorithms: true});this.formGroup.controls.simulationAlgorithms.markAsTouched();}else{this.formGroup.controls.simulationAlgorithms.setErrors({unsupportedAlgorithms: null});this.formGroup.controls.simulationAlgorithms.updateValueAndValidity();}}// Setters for preloading form controls from route paramsprivatesetControlsFromParams(params: Params,simulatorSpecsMap: SimulatorSpecsMap): void{if(!params){return;}this.setProject(params.projectUrl);this.setSimulator(params.simulator,params.simulatorVersion,simulatorSpecsMap);this.setCpuCount(params.cpus);this.setMemory(params.memory);this.setMaxTime(params.maxTime);this.setRunName(params.runName);this.setSimulationParams(params.simulationParams);}privatesetSimulationParams(simParams: any): void{// TODO: Update the model changes form.}privatesetProject(projectUrl: string): void{if(!projectUrl){return;}this.formGroup.controls.projectUrl.setValue(projectUrl);this.projectControlUpdated();}privatesetSimulator(simulator: string,simulatorVersion: string,simulatorSpecsMap: SimulatorSpecsMap): void{if(!simulator){return;}constnormalizedSimulator=simulator.toLowerCase();for(constsimulatorIdofObject.keys(simulatorSpecsMap)){if(simulatorId.toLowerCase()!==normalizedSimulator){continue;}this.formGroup.controls.simulator.setValue(simulatorId);this.simulatorControlUpdated();this.setSimulatorVersion(simulatorId,simulatorVersion,simulatorSpecsMap);break;}}privatesetSimulatorVersion(simulatorId: string,simulatorVersion: string,simulatorSpecsMap: SimulatorSpecsMap,): void{if(!simulatorVersion){return;}if(simulatorSpecsMap[simulatorId].versions.includes(simulatorVersion)){this.formGroup.controls.simulatorVersion.setValue(simulatorVersion);}}privatesetCpuCount(cpuCount: string): void{constcpuCountNum=Math.ceil(parseFloat(cpuCount));if(isNaN(cpuCountNum)||cpuCountNum<1){return;}this.formGroup.controls.cpus.setValue(cpuCount);}privatesetMemory(memory: string): void{constmemoryNum=parseFloat(memory);if(isNaN(memoryNum)||memoryNum<=0){return;}this.formGroup.controls.memory.setValue(memory);
6D47
}privatesetMaxTime(maxTime: string): void{constmaxTimeNum=parseFloat(maxTime);if(isNaN(maxTimeNum)||maxTimeNum<=0){return;}this.formGroup.controls.maxTime.setValue(maxTime);}privatesetRunName(runName: string): void{if(!runName){return;}this.formGroup.controls.name.setValue(runName);}// SnackbarsprivateshowFormSubmittedSnackbar(): void{this.snackBar.open(`Your simulation was submitted. `+'You can view the status of your simulation at this page '+'or from the "Your simulation runs page". '+'When your simulation completes, you will be able to '+'retrieve and visualize its results here.','Ok',{duration: 10000,},);}// Form ValidatorsprivateformValidator(formGroup: UntypedFormGroup): ValidationErrors|null{consterrors: ValidationErrors={};if(!formGroup.value.projectFile&&!formGroup.value.projectUrl){errors['noProject']=true;}if(formGroup.value.projectFile&&formGroup.value.projectUrl){errors['multipleProjects']=true;}if(this.emailEnabled){constemail=formGroup.controls.emailasUntypedFormControl;constemailConsent=formGroup.controls.emailConsentasUntypedFormControl;if(email.value&&!email.hasError('email')&&!emailConsent.value){errors['emailNotConsented']=true;}}returnObject.keys(errors).length ? errors : null;}}
The text was updated successfully, but these errors were encountered:
biosimulations/apps/platform/src/app/components/run/customize-simulation/customize-simulation.component.ts
Line 1082 in 06442f8
The text was updated successfully, but these errors were encountered: