Skip to content

Commit

Permalink
feat(platform): added simulation types and algorithms to simulaton ov…
Browse files Browse the repository at this point in the history
…erview
  • Loading branch information
jonrkarr committed Oct 2, 2021
1 parent 38417ea commit 4c768e5
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 57 deletions.
Expand Up @@ -11,11 +11,11 @@
<div
*ngIf="projectMetadata.thumbnails.length"
class="thumbnails-column ragged-column"
fxFlex="20rem"
fxFlex="22rem"
fxFlex.lt-sm="100%"
>
<div class="thumbnails-container"
fxFlex="20rem"
fxFlex="22rem"
fxFlex.lt-sm="100%"
[class.single-thumbnail]="projectMetadata.thumbnails.length === 1"
>
Expand Down Expand Up @@ -92,16 +92,18 @@
<!-- End summary/text data-->

<!-- Simulation information -->
<div fxFlex="20rem" fxFlex.lt-sm="100%" class="simulation-column ragged-column">
<div fxFlex="22rem" fxFlex.lt-sm="100%" class="simulation-column ragged-column">
<biosimulations-text-page-side-bar-section *ngFor="let section of simulationRun" [heading]="section.title">
<ul class="icon-list">
<li *ngFor="let item of section.items">
<biosimulations-icon [icon]="item.icon"></biosimulations-icon>
<b>{{ item.title }}:</b>{{ ' ' }}
<a [href]="item.url" target="_blank" *ngIf="item.url; else noHref">{{ item.value | async }}</a>
<ng-template #noHref>{{ item.value | async }}</ng-template>
</li>
</ul>
<table class="icon-list">
<tr *ngFor="let item of section.items">
<th><biosimulations-icon [icon]="item.icon"></biosimulations-icon></th>
<td>
<b>{{ item.title }}:</b>{{ ' ' }}
<a [href]="item.url" target="_blank" *ngIf="item.url; else noHref">{{ item.value | async }}</a>
<ng-template #noHref>{{ item.value | async }}</ng-template>
</td>
</tr>
</table>
</biosimulations-text-page-side-bar-section>
</div>
<!-- End simulation information -->
Expand Down
Expand Up @@ -102,7 +102,9 @@

a {
color: $dark-primary-text;
text-decoration: underline;
&:hover {
text-decoration: underline;
}
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions apps/platform/src/app/projects/projects.service.ts
Expand Up @@ -9,7 +9,6 @@ import { HttpClient } from '@angular/common/http';
import { Endpoints } from '@biosimulations/config/common';
import { ProjectSummary, FormattedDate, SimulatorIdNameMap } from './datamodel';
import { UtilsService } from '@biosimulations/shared/services';
import { urls } from '@biosimulations/config/common';

@Injectable({
providedIn: 'root',
Expand Down Expand Up @@ -70,14 +69,14 @@ export class ProjectsService {
return response;
}

public getProjectSimulation(id: string): Observable<any> { // SimulationRun
public getSimulationRun(id: string): Observable<any> { // SimulationRun
const url = this.endpoints.getSimulationRunEndpoint(id);
const response = this.http.get<any>(url).pipe(shareReplay(1)); // SimulationRun
return response;
}

public getProjectSimulationLog(id: string): Observable<any> {
const endpoint = `${urls.dispatchApi}logs/${id}`;
public getSimulationRunLog(id: string): Observable<any> {
const endpoint = this.endpoints.getRunLogsEndpoint(id);
return this.http.get(endpoint);
}

Expand Down Expand Up @@ -139,14 +138,15 @@ export class ProjectsService {
}

public getSimulatorIdNameMap(): Observable<SimulatorIdNameMap> {
const endpoint = `${urls.simulatorsApi}simulators/latest`;
const endpoint = this.endpoints.getSimulatorsEndpoint(undefined, 'latest');
return this.http.get(endpoint).pipe(
shareReplay(1),
map((simulators: any): SimulatorIdNameMap => {
const idNameMap: SimulatorIdNameMap = {};
simulators.forEach((simulator: any): void => {
idNameMap[simulator.id] = simulator.name;
})
console.log(idNameMap)
return idNameMap;
}),
);
Expand Down
145 changes: 115 additions & 30 deletions apps/platform/src/app/projects/view/view.service.ts
@@ -1,13 +1,23 @@
import { Injectable } from '@angular/core';
import { map, Observable, pluck, shareReplay, of } from 'rxjs';
import { map, Observable, pluck, shareReplay, of, combineLatest } from 'rxjs';
import {
ArchiveMetadata,
LabeledIdentifier,
DescribedIdentifier,
CombineArchiveContentFormat,
FORMATS,
MODEL_FORMATS,
SEDML_FORMAT,
COMBINE_OMEX_FORMAT,
CombineArchive,
CombineArchiveContent,
SedDocumentReportsCombineArchiveContent,
SedDocument,
SedAbstractTask,
SedTask,
Ontologies,
KisaoTerm,
SimulationTypeBriefName,
} from '@biosimulations/datamodel/common';
import {
ArchiveMetadata as APIMetadata,
Expand All @@ -20,14 +30,18 @@ import { ProjectMetadata, Creator, Directory, File, List, ListItem } from './vie
import { UtilsService } from '@biosimulations/shared/services';
import { urls } from '@biosimulations/config/common';
import { BiosimulationsIcon } from '@biosimulations/shared/icons';
import { OntologyService } from '@biosimulations/ontology/client';

@Injectable({
providedIn: 'root',
})
export class ViewService {
formatMap!: {[uri: string]: CombineArchiveContentFormat};

public constructor(private service: ProjectsService) {
public constructor(
private service: ProjectsService,
private ontologyService: OntologyService,
) {
this.formatMap = {};
FORMATS.forEach((format: CombineArchiveContentFormat): void => {
this.formatMap[format.combineUri] = format;
Expand Down Expand Up @@ -213,44 +227,115 @@ export class ViewService {
}

public getFormattedSimulationRun(id: string): Observable<List[]> {
return this.service.getProjectSimulation(id).pipe(
map((simulationRun: any): List[] => { // SimulationRun
const methods: ListItem[] = [];
return combineLatest(
this.service.getSimulationRun(id),
this.service.getProjectSedmlContents(id),
this.service.getSimulationRunLog(id),
this.ontologyService.getTerms<KisaoTerm>(Ontologies.KISAO),
).pipe(
map((args: [any, CombineArchive, any, {[id: string]: KisaoTerm}]): List[] => { // SimulationRun
const simulationRun = args[0];
const sedmlArchive = args[1];
const log = args[2];
const kisaoIdTermMap = args[3];

const modelLanguageSedUrns = new Set<string>();
const simulationTypes = new Set<string>();
let simulationAlgorithms = new Set<string>();
sedmlArchive.contents.forEach((sedmlContent: CombineArchiveContent): void => {
const sedDoc: SedDocument = (sedmlContent as SedDocumentReportsCombineArchiveContent).location.value;
sedDoc.tasks.forEach((abstractTask: SedAbstractTask): void => {
if (abstractTask._type === 'SedTask') {
const task = abstractTask as SedTask;
modelLanguageSedUrns.add(task.model.language);
simulationTypes.add(task.simulation._type);
simulationAlgorithms.add(task.simulation.algorithm.kisaoId);
}
})
});

/* TODO: add tasks: simulation type, simulation algorithm
for () {
methods.push({
title: 'Tasks',
value: of('SED-ML'),
icon: 'code',
url: 'https://www.ebi.ac.uk/ols/ontologies/kisao/terms?iri=http%3A%2F%2Fwww.biomodels.net%2Fkisao%2FKISAO%23' + id
const loggedSimulationAlgorithms = new Set<string>();
log.sedDocuments?.forEach((sedDoc: any): void => {
sedDoc.tasks?.forEach((task: any): void => {
if (task?.algorithm && task?.algorithm in kisaoIdTermMap) {
loggedSimulationAlgorithms.add(task?.algorithm as string);
}
});
});

if (loggedSimulationAlgorithms.size) {
simulationAlgorithms = loggedSimulationAlgorithms;
}
*/

const formats: ListItem[] = [];
const methods: ListItem[] = [];

Array.from(simulationTypes)
.map((simulationType: string): any => {
return {
title: 'Simulation',
value: SimulationTypeBriefName[simulationType as keyof typeof SimulationTypeBriefName],
icon: 'simulator',
url: 'https://sed-ml.org/',
};
})
.sort((a: any, b: any): number => {
return a.value.localeCompare(b.value, undefined, { numeric: true });
})
.forEach((simulationType: any): void => {
simulationType.value = of(simulationType.value);
methods.push(simulationType as ListItem);
});

Array.from(simulationAlgorithms)
.map((kisaoId: string): any => {
return {
title: 'Algorithm',
value: kisaoIdTermMap[kisaoId].name,
icon: 'code',
url: 'https://www.ebi.ac.uk/ols/ontologies/kisao/terms?iri=http%3A%2F%2Fwww.biomodels.net%2Fkisao%2FKISAO%23' + kisaoId,
};
})
.sort((a: any, b: any): number => {
return a.value.localeCompare(b.value, undefined, { numeric: true });
})
.forEach((simulationAlgorithm: any): void => {
simulationAlgorithm.value = of(simulationAlgorithm.value);
methods.push(simulationAlgorithm as ListItem);
});

let formats: ListItem[] = [];
formats.push({
title: 'Project',
value: of('COMBINE/OMEX'),
icon: 'format',
icon: 'archive',
url: 'https://www.ebi.ac.uk/ols/ontologies/edam/terms?iri=http%3A%2F%2Fedamontology.org%2Fformat_3686'
});

/* TODO: add model format(s)
for () {
formats.push({
title: 'Model',
value: of('SBML'),
icon: 'format',
url: 'https://www.ebi.ac.uk/ols/ontologies/edam/terms?iri=http%3A%2F%2Fedamontology.org%2Fformat_3686'
});
}
*/
Array.from(modelLanguageSedUrns)
.map((modelLanguageSedUrn: any): any => {
for (const modelFormat of MODEL_FORMATS) {
if (modelLanguageSedUrn.startsWith(modelFormat.sedUrn)) {
return {
title: 'Model',
value: modelFormat.acronym || modelFormat.name,
icon: 'model',
url: modelFormat.url,
};
}
}
})
.sort((a: any, b: any): number => {
return a.value.localeCompare(b.value, undefined, { numeric: true });
})
.forEach((modelLanguage: any): void => {
modelLanguage.value = of(modelLanguage.value);
formats.push(modelLanguage as ListItem);
});

formats.push({
title: 'Simulation',
value: of('SED-ML'),
icon: 'format',
icon: 'simulation',
url: 'https://www.ebi.ac.uk/ols/ontologies/edam/terms?iri=http%3A%2F%2Fedamontology.org%2Fformat_3685'
});

Expand All @@ -276,7 +361,7 @@ export class ViewService {
url: `${urls.dispatch}/simulations/${id}`,
});

const durationSec = this.service.getProjectSimulationLog(simulationRun.id)
const durationSec = this.service.getSimulationRunLog(simulationRun.id)
.pipe(
pluck('duration'),
map((durationSec: number): string => UtilsService.formatDuration(durationSec)),
Expand Down Expand Up @@ -318,7 +403,7 @@ export class ViewService {

// return sections
const sections = [
{title: 'Simulation methods', items: methods},
{title: 'Modeling methods', items: methods},
{title: 'Modeling formats', items: formats},
{title: 'Simulation tools', items: tools},
{title: 'Simulation run', items: run},
Expand All @@ -331,7 +416,7 @@ export class ViewService {
}

public getFormattedProjectFiles(id: string): Observable<File[]> {
return this.service.getProjectSimulation(id).pipe(
return this.service.getSimulationRun(id).pipe(
map((simulationRun: any): File[] => { // SimulationRun
return [
{
Expand Down Expand Up @@ -490,7 +575,7 @@ export class ViewService {
}

public getFormattedOutputs(id: string): Observable<File[]> {
return this.service.getProjectSimulation(id).pipe(
return this.service.getSimulationRun(id).pipe(
map((simulationRun: any): File[] => { // SimulationRun
return [
{
Expand Down
14 changes: 6 additions & 8 deletions libs/config/common/src/lib/endpoints.ts
Expand Up @@ -9,6 +9,7 @@ import { environment } from '@biosimulations/shared/environments';

export class Endpoints {
private api: string;
private simulators_api: string;
private combine_api: string;
private simulationRuns: string;
private simulationRunResults: string;
Expand All @@ -28,24 +29,28 @@ export class Endpoints {
switch (env) {
case 'local':
this.api = 'http://localhost:3333';
this.simulators_api = '/simulators-api';
this.combine_api = '/combine-api';
this.storage_endpoint = 'https://files-dev.biosimulations.org/s3';
break;

case 'dev':
this.api = 'https://api.biosimulations.dev';
this.simulators_api = 'https://api.biosimulators.dev';
this.combine_api = 'https://combine.api.biosimulations.dev';
this.storage_endpoint = 'https://files-dev.biosimulations.org/s3';
break;

case 'stage':
this.api = 'https://api.biosimulations.dev';
this.simulators_api = 'https://api.biosimulators.dev';
this.combine_api = 'https://combine.api.biosimulations.dev';
this.storage_endpoint = 'https://files-dev.biosimulations.org/s3';
break;

case 'prod':
this.api = 'https://api.biosimulations.org';
this.simulators_api = 'https://api.biosimulators.org';
this.combine_api = 'https://combine.api.biosimulations.org';
this.storage_endpoint = 'https://files.biosimulations.org/s3';
break;
Expand All @@ -55,7 +60,7 @@ export class Endpoints {
this.simulationRunResults = `${this.api}/results`;
this.simulationRunMetadata = `${this.api}/metadata`;
this.simulationRuns = `${this.api}/runs`;
this.simulators = `${this.api}/simulators`;
this.simulators = `${this.simulators_api}/simulators`;
this.files = `${this.api}/files`;
this.combineFile = `${this.combine_api}/combine/file`;
}
Expand Down Expand Up @@ -263,13 +268,6 @@ export class Endpoints {
public getSimulatorsEndpoint(id?: string, version?: string): string {
id ? (id = `/${id}`) : (id = '');
version ? (version = `/${version}`) : (version = '');

if (version && !id) {
throw new Error(
'Cannot get a specific version of a simulator without an id',
);
}

return `${this.simulators}${id}${version}`;
}
}
2 changes: 1 addition & 1 deletion libs/datamodel/common/src/lib/common/modeling-formats.ts
Expand Up @@ -14,7 +14,7 @@ export interface ModelFormat {

export const MODEL_FORMATS: ModelFormat[] = [
{
name: 'BNGL',
name: 'BioNetGen Language',
acronym: 'BNGL',
edamId: 'format_3972',
sedUrn: 'urn:sedml:language:bngl',
Expand Down
6 changes: 6 additions & 0 deletions libs/datamodel/common/src/lib/core/algorithm.ts
Expand Up @@ -55,6 +55,12 @@ export enum SimulationTypeName {
SedUniformTimeCourseSimulation = 'SED uniform time course simulation',
}

export enum SimulationTypeBriefName {
SedOneStepSimulation = 'One step',
SedSteadyStateSimulation = 'Steady state',
SedUniformTimeCourseSimulation = 'Uniform time course',
}

/**
* Represents a parameter in a particular simulation algorith or method.
* id refers to the identifier used by some software package to reference parameter
Expand Down

0 comments on commit 4c768e5

Please sign in to comment.