@abi-software/simulationvuer 3.0.12 → 3.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -10
- package/dist/index.html +10 -6
- package/dist/simulationvuer.js +11550 -11445
- package/dist/simulationvuer.umd.cjs +101 -101
- package/dist/style.css +1 -1
- package/package.json +19 -7
- package/public/index.html +10 -6
- package/src/App.vue +161 -46
- package/src/assets/_variables.scss +13 -11
- package/src/assets/styles.scss +2 -2
- package/src/components/SimulationVuer.vue +225 -111
- package/src/components/SimulationVuerInput.vue +2 -1
- package/src/components/common.js +19 -8
- package/src/components/index.js +2 -4
- package/src/components/json.js +144 -73
- package/src/main.js +2 -1
- package/vite.config.js +11 -6
- package/vuese-generator.js +77 -80
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="simulation-vuer"
|
|
4
|
+
v-loading="showUserMessage"
|
|
5
|
+
:element-loading-text="userMessage"
|
|
6
|
+
>
|
|
3
7
|
<div class="container" v-if="opencorOmexFile === null">
|
|
4
|
-
<p
|
|
8
|
+
<p
|
|
9
|
+
v-if="!hasValidSimulationUiInfo && !showUserMessage"
|
|
10
|
+
class="default error"
|
|
11
|
+
>
|
|
12
|
+
<span class="error">Error:</span> {{ errorMessage }}.
|
|
13
|
+
</p>
|
|
5
14
|
<div class="main" v-if="hasValidSimulationUiInfo">
|
|
6
|
-
<div class="main-left" :class="{'with-buttons': uuid}">
|
|
15
|
+
<div class="main-left" :class="{ 'with-buttons': uuid }">
|
|
7
16
|
<p class="default name">{{ name }}</p>
|
|
8
17
|
<el-divider></el-divider>
|
|
9
18
|
<p class="default input-parameters">Input parameters</p>
|
|
10
19
|
<div class="input scrollbar">
|
|
11
|
-
<SimulationVuerInput
|
|
20
|
+
<SimulationVuerInput
|
|
21
|
+
v-for="(input, index) in simulationUiInfo.input"
|
|
12
22
|
ref="simInput"
|
|
13
23
|
:defaultValue="input.defaultValue"
|
|
14
24
|
:key="`input-${index}`"
|
|
@@ -21,19 +31,28 @@
|
|
|
21
31
|
</div>
|
|
22
32
|
<div class="buttons-container">
|
|
23
33
|
<div class="primary-button">
|
|
24
|
-
<el-button type="primary" size="small" @click="startSimulation()"
|
|
34
|
+
<el-button type="primary" size="small" @click="startSimulation()"
|
|
35
|
+
>Run Simulation</el-button
|
|
36
|
+
>
|
|
25
37
|
</div>
|
|
26
38
|
<div class="secondary-button" v-if="uuid">
|
|
27
|
-
<el-button size="small" @click="runOnOsparc()"
|
|
39
|
+
<el-button size="small" @click="runOnOsparc()"
|
|
40
|
+
>Run on oSPARC</el-button
|
|
41
|
+
>
|
|
28
42
|
</div>
|
|
29
43
|
<div class="secondary-button">
|
|
30
|
-
<el-button size="small" @click="viewDataset()"
|
|
44
|
+
<el-button size="small" @click="viewDataset()"
|
|
45
|
+
>View Dataset</el-button
|
|
46
|
+
>
|
|
31
47
|
</div>
|
|
32
|
-
<p class="default note" v-if="uuid">
|
|
48
|
+
<p class="default note" v-if="uuid">
|
|
49
|
+
Additional parameters are available on oSPARC
|
|
50
|
+
</p>
|
|
33
51
|
</div>
|
|
34
52
|
</div>
|
|
35
53
|
<div class="main-right" ref="output" v-show="isSimulationValid">
|
|
36
|
-
<PlotVuer
|
|
54
|
+
<PlotVuer
|
|
55
|
+
v-for="(_outputPlot, index) in simulationUiInfo.output.plots"
|
|
37
56
|
:key="`output-${index}`"
|
|
38
57
|
:metadata="plotMetadata(index)"
|
|
39
58
|
:data-source="{ data: simulationResults[index] }"
|
|
@@ -43,7 +62,19 @@
|
|
|
43
62
|
/>
|
|
44
63
|
</div>
|
|
45
64
|
<div class="main-right" v-show="!isSimulationValid">
|
|
46
|
-
<p class="default error"
|
|
65
|
+
<p class="default error">
|
|
66
|
+
<span class="error">Error:</span>
|
|
67
|
+
{{ errorMessage }}
|
|
68
|
+
<span v-if="errorStatus">
|
|
69
|
+
(<a
|
|
70
|
+
:href="`https://httpstatuses.com/${errorStatus}`"
|
|
71
|
+
target="_blank"
|
|
72
|
+
rel="noopener noreferrer"
|
|
73
|
+
>
|
|
74
|
+
{{ errorStatus }} </a
|
|
75
|
+
>) </span
|
|
76
|
+
>.
|
|
77
|
+
</p>
|
|
47
78
|
</div>
|
|
48
79
|
</div>
|
|
49
80
|
</div>
|
|
@@ -61,23 +92,25 @@
|
|
|
61
92
|
<script>
|
|
62
93
|
import { PlotVuer } from "@abi-software/plotvuer";
|
|
63
94
|
import "@abi-software/plotvuer/dist/style.css";
|
|
64
|
-
import
|
|
65
|
-
import
|
|
95
|
+
import OpenCOR from "@opencor/opencor";
|
|
96
|
+
import "@opencor/opencor/style.css";
|
|
97
|
+
|
|
98
|
+
import { ElButton, ElDivider } from "element-plus";
|
|
99
|
+
import { create, all } from "mathjs";
|
|
100
|
+
|
|
66
101
|
import { evaluateValue, finaliseUi, OPENCOR_SOLVER_NAME } from "./common.js";
|
|
67
102
|
import { validJson } from "./json.js";
|
|
68
|
-
import
|
|
69
|
-
import OpenCOR from '@opencor/opencor';
|
|
70
|
-
import '@opencor/opencor/style.css';
|
|
103
|
+
import SimulationVuerInput from "./SimulationVuerInput.vue";
|
|
71
104
|
|
|
72
105
|
const PMR_URL = "https://models.physiomeproject.org/";
|
|
73
106
|
|
|
74
107
|
const math = create(all, {});
|
|
75
108
|
|
|
76
109
|
const IdType = Object.freeze({
|
|
77
|
-
DATASET_ID:
|
|
78
|
-
DATASET_URL:
|
|
79
|
-
PMR_PATH:
|
|
80
|
-
RAW_COMBINE_ARCHIVE:
|
|
110
|
+
DATASET_ID: "dataset_id",
|
|
111
|
+
DATASET_URL: "dataset_url",
|
|
112
|
+
PMR_PATH: "pmr_path",
|
|
113
|
+
RAW_COMBINE_ARCHIVE: "raw_combine_archive",
|
|
81
114
|
});
|
|
82
115
|
|
|
83
116
|
function isWebProtocol(urlString) {
|
|
@@ -101,7 +134,6 @@ export default {
|
|
|
101
134
|
SimulationVuerInput,
|
|
102
135
|
ElButton,
|
|
103
136
|
ElDivider,
|
|
104
|
-
ElLoading,
|
|
105
137
|
OpenCOR,
|
|
106
138
|
},
|
|
107
139
|
props: {
|
|
@@ -144,14 +176,17 @@ export default {
|
|
|
144
176
|
if (idType === IdType.DATASET_ID) {
|
|
145
177
|
const xmlhttp = new XMLHttpRequest();
|
|
146
178
|
|
|
147
|
-
xmlhttp.open("GET", this.apiLocation
|
|
179
|
+
xmlhttp.open("GET", `${this.apiLocation}/sim/dataset/${this.id}`);
|
|
148
180
|
xmlhttp.onreadystatechange = () => {
|
|
149
181
|
if (xmlhttp.readyState === 4) {
|
|
150
182
|
if (xmlhttp.status === 200) {
|
|
151
183
|
const datasetInfo = JSON.parse(xmlhttp.responseText);
|
|
152
184
|
|
|
153
185
|
this.name = datasetInfo.name;
|
|
154
|
-
this.uuid =
|
|
186
|
+
this.uuid =
|
|
187
|
+
datasetInfo.study !== undefined
|
|
188
|
+
? datasetInfo.study.uuid
|
|
189
|
+
: undefined;
|
|
155
190
|
}
|
|
156
191
|
}
|
|
157
192
|
};
|
|
@@ -160,6 +195,7 @@ export default {
|
|
|
160
195
|
|
|
161
196
|
return {
|
|
162
197
|
errorMessage: "",
|
|
198
|
+
errorStatus: null,
|
|
163
199
|
fileManager: undefined,
|
|
164
200
|
hasFinalisedUi: false,
|
|
165
201
|
hasValidSimulationUiInfo: false,
|
|
@@ -191,40 +227,48 @@ export default {
|
|
|
191
227
|
/**
|
|
192
228
|
* @public
|
|
193
229
|
* Add a data subscription.
|
|
194
|
-
* @
|
|
230
|
+
* @param `subscription`
|
|
195
231
|
*/
|
|
196
232
|
addDataSubscription(subscription) {
|
|
197
233
|
// Check that the subscription is valid.
|
|
198
234
|
|
|
199
|
-
if (!subscription || typeof subscription !==
|
|
200
|
-
console.
|
|
235
|
+
if (!subscription || typeof subscription !== "object") {
|
|
236
|
+
console.warn(
|
|
237
|
+
"SimulationVuer: addDataSubscription: subscription must be an object.",
|
|
238
|
+
);
|
|
201
239
|
|
|
202
240
|
return;
|
|
203
241
|
}
|
|
204
242
|
|
|
205
243
|
// Check that the subscription has the expected ID.
|
|
206
244
|
|
|
207
|
-
const EXPECTED_ID =
|
|
245
|
+
const EXPECTED_ID = "nz.ac.auckland.simulation-data-request";
|
|
208
246
|
const EXPECTED_MAJOR_VERSION = 0;
|
|
209
247
|
|
|
210
248
|
if (subscription.id !== EXPECTED_ID) {
|
|
211
|
-
console.warn(
|
|
249
|
+
console.warn(
|
|
250
|
+
`SimulationVuer: addDataSubscription: invalid ID (expected '${EXPECTED_ID}' but got '${subscription.id}').`,
|
|
251
|
+
);
|
|
212
252
|
|
|
213
253
|
return;
|
|
214
254
|
}
|
|
215
255
|
|
|
216
256
|
// Check that the version is valid and compatible with what we expect.
|
|
217
257
|
|
|
218
|
-
if (typeof subscription.version !==
|
|
219
|
-
console.warn(
|
|
258
|
+
if (typeof subscription.version !== "string") {
|
|
259
|
+
console.warn(
|
|
260
|
+
`SimulationVuer: addDataSubscription: missing or non-string version ('${subscription.version}').`,
|
|
261
|
+
);
|
|
220
262
|
|
|
221
263
|
return;
|
|
222
264
|
}
|
|
223
265
|
|
|
224
|
-
const versionParts = subscription.version.split(
|
|
266
|
+
const versionParts = subscription.version.split(".");
|
|
225
267
|
|
|
226
268
|
if (versionParts.length < 1 || !/^[0-9]+$/.test(versionParts[0])) {
|
|
227
|
-
console.warn(
|
|
269
|
+
console.warn(
|
|
270
|
+
`SimulationVuer: addDataSubscription: malformed version ('${subscription.version}').`,
|
|
271
|
+
);
|
|
228
272
|
|
|
229
273
|
return;
|
|
230
274
|
}
|
|
@@ -232,13 +276,17 @@ export default {
|
|
|
232
276
|
const subscriptionMajorVersion = parseInt(versionParts[0], 10);
|
|
233
277
|
|
|
234
278
|
if (Number.isNaN(subscriptionMajorVersion)) {
|
|
235
|
-
console.warn(
|
|
279
|
+
console.warn(
|
|
280
|
+
`SimulationVuer: addDataSubscription: could not parse the major version from ('${subscription.version}')`,
|
|
281
|
+
);
|
|
236
282
|
|
|
237
283
|
return;
|
|
238
284
|
}
|
|
239
285
|
|
|
240
286
|
if (subscriptionMajorVersion !== EXPECTED_MAJOR_VERSION) {
|
|
241
|
-
console.warn(
|
|
287
|
+
console.warn(
|
|
288
|
+
`SimulationVuer: addDataSubscription: version mismatch (expected v${EXPECTED_MAJOR_VERSION}.y.z but got v${subscription.version}).`,
|
|
289
|
+
);
|
|
242
290
|
|
|
243
291
|
return;
|
|
244
292
|
}
|
|
@@ -249,23 +297,25 @@ export default {
|
|
|
249
297
|
const missing = [];
|
|
250
298
|
|
|
251
299
|
if (payload.windowId == null) {
|
|
252
|
-
missing.push(
|
|
300
|
+
missing.push("windowId");
|
|
253
301
|
}
|
|
254
302
|
|
|
255
303
|
if (payload.ownerId == null) {
|
|
256
|
-
missing.push(
|
|
304
|
+
missing.push("ownerId");
|
|
257
305
|
}
|
|
258
306
|
|
|
259
307
|
if (!payload.component) {
|
|
260
|
-
missing.push(
|
|
308
|
+
missing.push("component");
|
|
261
309
|
}
|
|
262
310
|
|
|
263
311
|
if (!payload.variable) {
|
|
264
|
-
missing.push(
|
|
312
|
+
missing.push("variable");
|
|
265
313
|
}
|
|
266
314
|
|
|
267
315
|
if (missing.length) {
|
|
268
|
-
console.warn(
|
|
316
|
+
console.warn(
|
|
317
|
+
`SimulationVuer: addDataSubscription: payload missing fields: ${missing.join(", ")}.`,
|
|
318
|
+
);
|
|
269
319
|
|
|
270
320
|
return;
|
|
271
321
|
}
|
|
@@ -280,52 +330,69 @@ export default {
|
|
|
280
330
|
const modelParameters = [];
|
|
281
331
|
|
|
282
332
|
if (subscription.payload?.withVOI) {
|
|
283
|
-
modelParameters.push(
|
|
333
|
+
modelParameters.push("VOI");
|
|
284
334
|
}
|
|
285
335
|
|
|
286
|
-
modelParameters.push(
|
|
336
|
+
modelParameters.push(
|
|
337
|
+
`${subscription.payload?.component}/${subscription.payload?.variable}`,
|
|
338
|
+
);
|
|
287
339
|
|
|
288
340
|
this.$refs.opencorRef?.trackSimulationData(modelParameters);
|
|
289
341
|
},
|
|
290
342
|
/**
|
|
291
343
|
* @public
|
|
292
344
|
* Remove a data subscription.
|
|
293
|
-
* @
|
|
345
|
+
* @param `subscriptionId`
|
|
294
346
|
*/
|
|
295
347
|
removeDataSubscription(subscriptionId) {
|
|
296
348
|
// Ask OpenCOR to stop tracking the simulation data associated with the subscription's component and variable (and
|
|
297
349
|
// the VOI, if requested and unless it's requested by another subscription).
|
|
298
350
|
|
|
299
|
-
const subscription = this.activeSubscriptions.find(
|
|
300
|
-
|
|
301
|
-
|
|
351
|
+
const subscription = this.activeSubscriptions.find(
|
|
352
|
+
(activeSubscription) => {
|
|
353
|
+
return activeSubscription.windowId === subscriptionId;
|
|
354
|
+
},
|
|
355
|
+
);
|
|
302
356
|
|
|
303
357
|
if (!subscription) {
|
|
304
|
-
console.warn(
|
|
358
|
+
console.warn(
|
|
359
|
+
`SimulationVuer: removeDataSubscription: no active subscription found for id ${subscriptionId}.`,
|
|
360
|
+
);
|
|
305
361
|
|
|
306
362
|
return;
|
|
307
363
|
}
|
|
308
364
|
|
|
309
|
-
const isVoiTrackedByAnotherSubscription = this.activeSubscriptions.some(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
365
|
+
const isVoiTrackedByAnotherSubscription = this.activeSubscriptions.some(
|
|
366
|
+
(activeSubscription) => {
|
|
367
|
+
return (
|
|
368
|
+
activeSubscription.windowId !== subscriptionId &&
|
|
369
|
+
activeSubscription.withVOI
|
|
370
|
+
);
|
|
371
|
+
},
|
|
372
|
+
);
|
|
373
|
+
const isModelParameterTrackedByAnotherSubscription =
|
|
374
|
+
this.activeSubscriptions.some((activeSubscription) => {
|
|
375
|
+
return (
|
|
376
|
+
activeSubscription.windowId !== subscriptionId &&
|
|
377
|
+
activeSubscription.component === subscription.component &&
|
|
378
|
+
activeSubscription.variable === subscription.variable
|
|
379
|
+
);
|
|
380
|
+
});
|
|
319
381
|
|
|
320
|
-
if (
|
|
382
|
+
if (
|
|
383
|
+
!isVoiTrackedByAnotherSubscription ||
|
|
384
|
+
!isModelParameterTrackedByAnotherSubscription
|
|
385
|
+
) {
|
|
321
386
|
const modelParameters = [];
|
|
322
387
|
|
|
323
388
|
if (subscription.withVOI && !isVoiTrackedByAnotherSubscription) {
|
|
324
|
-
modelParameters.push(
|
|
389
|
+
modelParameters.push("VOI");
|
|
325
390
|
}
|
|
326
391
|
|
|
327
392
|
if (!isModelParameterTrackedByAnotherSubscription) {
|
|
328
|
-
modelParameters.push(
|
|
393
|
+
modelParameters.push(
|
|
394
|
+
`${subscription.component}/${subscription.variable}`,
|
|
395
|
+
);
|
|
329
396
|
}
|
|
330
397
|
|
|
331
398
|
if (modelParameters.length) {
|
|
@@ -335,14 +402,16 @@ export default {
|
|
|
335
402
|
|
|
336
403
|
// Remove the subscription from our list of active subscriptions.
|
|
337
404
|
|
|
338
|
-
this.activeSubscriptions = this.activeSubscriptions.filter(
|
|
339
|
-
|
|
340
|
-
|
|
405
|
+
this.activeSubscriptions = this.activeSubscriptions.filter(
|
|
406
|
+
(activeSubscription) => {
|
|
407
|
+
return activeSubscription.windowId !== subscriptionId;
|
|
408
|
+
},
|
|
409
|
+
);
|
|
341
410
|
},
|
|
342
411
|
/**
|
|
343
412
|
* @public
|
|
344
413
|
* Let the outside world know that we have received some simulation data from OpenCOR by emitting a `data-notification` event.
|
|
345
|
-
* @
|
|
414
|
+
* @param `event`
|
|
346
415
|
*/
|
|
347
416
|
onSimulationData(event) {
|
|
348
417
|
const simulationData = event.simulationData || {};
|
|
@@ -352,31 +421,33 @@ export default {
|
|
|
352
421
|
const modelParameter = `${activeSubscription.component}/${activeSubscription.variable}`;
|
|
353
422
|
|
|
354
423
|
if (simulationData[modelParameter] == null) {
|
|
355
|
-
console.warn(
|
|
424
|
+
console.warn(
|
|
425
|
+
`SimulationVuer: onSimulationData: no data for ${modelParameter}.`,
|
|
426
|
+
);
|
|
356
427
|
|
|
357
428
|
return;
|
|
358
429
|
}
|
|
359
430
|
|
|
360
431
|
const data = {
|
|
361
|
-
y:
|
|
432
|
+
y: simulationData[modelParameter],
|
|
362
433
|
title: `${activeSubscription.component}.${activeSubscription.variable}`,
|
|
363
434
|
};
|
|
364
435
|
|
|
365
436
|
if (activeSubscription.withVOI) {
|
|
366
437
|
if (simulationData.VOI == null) {
|
|
367
|
-
console.warn(
|
|
438
|
+
console.warn("SimulationVuer: onSimulationData: no data for VOI.");
|
|
368
439
|
|
|
369
440
|
return;
|
|
370
441
|
} else {
|
|
371
|
-
voi ??=
|
|
442
|
+
voi ??= simulationData.VOI;
|
|
372
443
|
|
|
373
444
|
data.x = voi;
|
|
374
445
|
}
|
|
375
446
|
}
|
|
376
447
|
|
|
377
|
-
this.$emit(
|
|
378
|
-
id:
|
|
379
|
-
version:
|
|
448
|
+
this.$emit("data-notification", {
|
|
449
|
+
id: "nz.ac.auckland.simulation-data-response",
|
|
450
|
+
version: "0.1.0",
|
|
380
451
|
payload: {
|
|
381
452
|
windowId: activeSubscription.windowId,
|
|
382
453
|
ownerId: activeSubscription.ownerId,
|
|
@@ -388,7 +459,7 @@ export default {
|
|
|
388
459
|
/**
|
|
389
460
|
* @public
|
|
390
461
|
* Generate the metadata associated with the plot which `index` is given.
|
|
391
|
-
* @
|
|
462
|
+
* @param `index`
|
|
392
463
|
*/
|
|
393
464
|
plotMetadata(index) {
|
|
394
465
|
return {
|
|
@@ -403,7 +474,7 @@ export default {
|
|
|
403
474
|
/**
|
|
404
475
|
* @public
|
|
405
476
|
* Build the simulation UI using `simulationUiInfo`, a JSON object that describes the contents of the simulation UI.
|
|
406
|
-
* @
|
|
477
|
+
* @param `simulationUiInfo`
|
|
407
478
|
*/
|
|
408
479
|
buildSimulationUi(simulationUiInfo) {
|
|
409
480
|
// Keep track of the simulation UI information.
|
|
@@ -423,7 +494,7 @@ export default {
|
|
|
423
494
|
// Retrieve and keep track of the solver to be used for the simulation.
|
|
424
495
|
|
|
425
496
|
this.simulationUiInfo.simulation.solvers.forEach((solver) => {
|
|
426
|
-
if (
|
|
497
|
+
if (solver.if === undefined || evaluateValue(this, solver.if)) {
|
|
427
498
|
this.solver = solver;
|
|
428
499
|
}
|
|
429
500
|
});
|
|
@@ -493,6 +564,25 @@ export default {
|
|
|
493
564
|
finaliseUi(this);
|
|
494
565
|
});
|
|
495
566
|
},
|
|
567
|
+
/**
|
|
568
|
+
* @private
|
|
569
|
+
* Open the given `url` in a new browser tab, making sure to do so safely.
|
|
570
|
+
* @param `url`
|
|
571
|
+
*/
|
|
572
|
+
openUrl(url) {
|
|
573
|
+
const a = document.createElement("a");
|
|
574
|
+
|
|
575
|
+
a.href = url;
|
|
576
|
+
a.target = "_blank";
|
|
577
|
+
a.rel = "noopener noreferrer";
|
|
578
|
+
a.style.display = "none";
|
|
579
|
+
|
|
580
|
+
document.body.appendChild(a);
|
|
581
|
+
|
|
582
|
+
a.click();
|
|
583
|
+
|
|
584
|
+
document.body.removeChild(a);
|
|
585
|
+
},
|
|
496
586
|
/**
|
|
497
587
|
* @public
|
|
498
588
|
* Run the simulation-based dataset directly on oSPARC. Not all simulation-based datasets can be run directly on
|
|
@@ -500,7 +590,7 @@ export default {
|
|
|
500
590
|
* method.
|
|
501
591
|
*/
|
|
502
592
|
runOnOsparc() {
|
|
503
|
-
|
|
593
|
+
this.openUrl(`https://osparc.io/study/${this.uuid}`);
|
|
504
594
|
},
|
|
505
595
|
/**
|
|
506
596
|
* @public
|
|
@@ -508,7 +598,7 @@ export default {
|
|
|
508
598
|
* clicked, calls this method.
|
|
509
599
|
*/
|
|
510
600
|
viewDataset() {
|
|
511
|
-
|
|
601
|
+
this.openUrl(`https://sparc.science/datasets/${this.id}?type=dataset`);
|
|
512
602
|
},
|
|
513
603
|
/**
|
|
514
604
|
* @public
|
|
@@ -517,8 +607,7 @@ export default {
|
|
|
517
607
|
*/
|
|
518
608
|
viewWorkspace() {
|
|
519
609
|
const url = PMR_URL + this.id;
|
|
520
|
-
|
|
521
|
-
window.open(url.substring(0, url.lastIndexOf("/")), "_blank");
|
|
610
|
+
this.openUrl(url.substring(0, url.lastIndexOf("/")));
|
|
522
611
|
},
|
|
523
612
|
/**
|
|
524
613
|
* @public
|
|
@@ -556,7 +645,7 @@ export default {
|
|
|
556
645
|
*/
|
|
557
646
|
retrieveRequest() {
|
|
558
647
|
const request = {
|
|
559
|
-
solver: this.solver
|
|
648
|
+
solver: this.solver,
|
|
560
649
|
};
|
|
561
650
|
|
|
562
651
|
if (this.opencorBasedSimulation) {
|
|
@@ -565,11 +654,15 @@ export default {
|
|
|
565
654
|
json_config: {},
|
|
566
655
|
};
|
|
567
656
|
|
|
568
|
-
if (
|
|
569
|
-
|
|
657
|
+
if (
|
|
658
|
+
this.simulationUiInfo.simulation.opencor.endingPoint !== undefined &&
|
|
659
|
+
this.simulationUiInfo.simulation.opencor.pointInterval !== undefined
|
|
660
|
+
) {
|
|
570
661
|
request.opencor.json_config.simulation = {
|
|
571
|
-
"Ending point":
|
|
572
|
-
|
|
662
|
+
"Ending point":
|
|
663
|
+
this.simulationUiInfo.simulation.opencor.endingPoint,
|
|
664
|
+
"Point interval":
|
|
665
|
+
this.simulationUiInfo.simulation.opencor.pointInterval,
|
|
573
666
|
};
|
|
574
667
|
}
|
|
575
668
|
|
|
@@ -592,13 +685,13 @@ export default {
|
|
|
592
685
|
* @public
|
|
593
686
|
* Process the simulation results retrieved by `checkSimulation`. The simulation results are post-processed, if
|
|
594
687
|
* needed, and then readied for use by `PlotVuer`.
|
|
595
|
-
* @
|
|
688
|
+
* @param `results`
|
|
596
689
|
*/
|
|
597
690
|
processSimulationResults(results) {
|
|
598
691
|
// Convert, if needed, the results to a JSON format that is compatible
|
|
599
692
|
// with our OpenCOR results.
|
|
600
693
|
|
|
601
|
-
if (typeof
|
|
694
|
+
if (typeof results === "string") {
|
|
602
695
|
const SPACES = /[ \t]+/g;
|
|
603
696
|
const lines = results.trim().split("\n");
|
|
604
697
|
const iMax = lines[0].trim().split(SPACES).length;
|
|
@@ -646,26 +739,27 @@ export default {
|
|
|
646
739
|
/**
|
|
647
740
|
* @public
|
|
648
741
|
* Show an HTTP issue using the given `xmlhttp`.
|
|
649
|
-
* @
|
|
742
|
+
* @param `xmlhttp`
|
|
650
743
|
*/
|
|
651
744
|
showHttpIssue(xmlhttp) {
|
|
652
745
|
this.isSimulationValid = false;
|
|
653
746
|
this.showUserMessage = false;
|
|
654
|
-
this.errorMessage = xmlhttp.statusText.toLowerCase()
|
|
747
|
+
this.errorMessage = xmlhttp.statusText.toLowerCase();
|
|
748
|
+
this.errorStatus = xmlhttp.status;
|
|
655
749
|
},
|
|
656
750
|
/**
|
|
657
751
|
* @public
|
|
658
752
|
* Check the progress of the simulation using the given `data`, a JSON object that contains the simulation job ID,
|
|
659
753
|
* as well as the solver name and version. This method is first called by `startSimulation` and then every second by
|
|
660
754
|
* itself until the simulation is finished.
|
|
661
|
-
* @
|
|
755
|
+
* @param `data`
|
|
662
756
|
*/
|
|
663
757
|
checkSimulation(data) {
|
|
664
758
|
// Check the simulation.
|
|
665
759
|
|
|
666
760
|
const xmlhttp = new XMLHttpRequest();
|
|
667
761
|
|
|
668
|
-
xmlhttp.open("POST", this.apiLocation
|
|
762
|
+
xmlhttp.open("POST", `${this.apiLocation}/check_simulation`);
|
|
669
763
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
670
764
|
xmlhttp.onreadystatechange = () => {
|
|
671
765
|
if (xmlhttp.readyState === 4) {
|
|
@@ -687,13 +781,14 @@ export default {
|
|
|
687
781
|
|
|
688
782
|
let that = this;
|
|
689
783
|
|
|
690
|
-
setTimeout(
|
|
784
|
+
setTimeout(() => {
|
|
691
785
|
that.checkSimulation(data);
|
|
692
786
|
}, 1000);
|
|
693
787
|
}
|
|
694
788
|
} else {
|
|
695
789
|
this.showUserMessage = false;
|
|
696
790
|
this.errorMessage = response.description;
|
|
791
|
+
this.errorStatus = null;
|
|
697
792
|
}
|
|
698
793
|
} else {
|
|
699
794
|
this.showHttpIssue(xmlhttp);
|
|
@@ -719,7 +814,7 @@ export default {
|
|
|
719
814
|
|
|
720
815
|
const xmlhttp = new XMLHttpRequest();
|
|
721
816
|
|
|
722
|
-
xmlhttp.open("POST", this.apiLocation
|
|
817
|
+
xmlhttp.open("POST", `${this.apiLocation}/start_simulation`);
|
|
723
818
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
724
819
|
xmlhttp.onreadystatechange = () => {
|
|
725
820
|
if (xmlhttp.readyState === 4) {
|
|
@@ -733,6 +828,7 @@ export default {
|
|
|
733
828
|
} else {
|
|
734
829
|
this.showUserMessage = false;
|
|
735
830
|
this.errorMessage = response.description;
|
|
831
|
+
this.errorStatus = null;
|
|
736
832
|
}
|
|
737
833
|
} else {
|
|
738
834
|
this.showHttpIssue(xmlhttp);
|
|
@@ -755,7 +851,10 @@ export default {
|
|
|
755
851
|
this.$nextTick(() => {
|
|
756
852
|
const xmlhttp = new XMLHttpRequest();
|
|
757
853
|
|
|
758
|
-
xmlhttp.open(
|
|
854
|
+
xmlhttp.open(
|
|
855
|
+
"GET",
|
|
856
|
+
`${this.apiLocation}/simulation_ui_file/${this.id}`,
|
|
857
|
+
);
|
|
759
858
|
xmlhttp.onreadystatechange = () => {
|
|
760
859
|
if (xmlhttp.readyState === 4) {
|
|
761
860
|
this.showUserMessage = false;
|
|
@@ -765,7 +864,9 @@ export default {
|
|
|
765
864
|
this.buildSimulationUi(JSON.parse(xmlhttp.responseText));
|
|
766
865
|
});
|
|
767
866
|
} else {
|
|
768
|
-
this.errorMessage =
|
|
867
|
+
this.errorMessage =
|
|
868
|
+
"the simulation dataset could not be retrieved";
|
|
869
|
+
this.errorStatus = null;
|
|
769
870
|
}
|
|
770
871
|
}
|
|
771
872
|
};
|
|
@@ -774,8 +875,9 @@ export default {
|
|
|
774
875
|
} else if (this.idType === IdType.DATASET_URL) {
|
|
775
876
|
this.opencorOmexFile = this.id;
|
|
776
877
|
} else if (this.idType === IdType.PMR_PATH) {
|
|
777
|
-
this.opencorOmexFile = PMR_URL
|
|
778
|
-
} else {
|
|
878
|
+
this.opencorOmexFile = `${PMR_URL}${this.id}`;
|
|
879
|
+
} else {
|
|
880
|
+
// IdType.RAW_COMBINE_ARCHIVE
|
|
779
881
|
this.opencorOmexFile = this.id;
|
|
780
882
|
}
|
|
781
883
|
},
|
|
@@ -795,10 +897,10 @@ export default {
|
|
|
795
897
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
796
898
|
<style scoped lang="scss">
|
|
797
899
|
.simulation-vuer {
|
|
798
|
-
--el-color-primary: #
|
|
799
|
-
--el-color-primary-light-7: #
|
|
800
|
-
--el-color-primary-light-8: #
|
|
801
|
-
--el-color-primary-light-9: #
|
|
900
|
+
--el-color-primary: #8300bf;
|
|
901
|
+
--el-color-primary-light-7: #dab3ec;
|
|
902
|
+
--el-color-primary-light-8: #e6ccf2;
|
|
903
|
+
--el-color-primary-light-9: #f3e6f9;
|
|
802
904
|
}
|
|
803
905
|
|
|
804
906
|
:deep(.el-button:hover) {
|
|
@@ -812,12 +914,12 @@ export default {
|
|
|
812
914
|
|
|
813
915
|
:deep(.el-loading-spinner) {
|
|
814
916
|
.path {
|
|
815
|
-
stroke: #
|
|
917
|
+
stroke: #8300bf;
|
|
816
918
|
}
|
|
817
919
|
|
|
818
920
|
i,
|
|
819
921
|
.el-loading-text {
|
|
820
|
-
color: #
|
|
922
|
+
color: #8300bf;
|
|
821
923
|
}
|
|
822
924
|
}
|
|
823
925
|
|
|
@@ -825,23 +927,23 @@ export default {
|
|
|
825
927
|
:deep(.p-floatlabel:has(input:-webkit-autofill)) label,
|
|
826
928
|
:deep(.p-floatlabel:has(textarea:focus)) label,
|
|
827
929
|
:deep(.p-floatlabel:has(.p-inputwrapper-focus)) label {
|
|
828
|
-
color: #
|
|
930
|
+
color: #8300bf;
|
|
829
931
|
}
|
|
830
932
|
|
|
831
933
|
:deep(.p-inputtext:enabled:focus) {
|
|
832
|
-
|
|
934
|
+
border-color: #8300bf;
|
|
833
935
|
}
|
|
834
936
|
|
|
835
937
|
:deep(.p-progressbar-value) {
|
|
836
|
-
background-color: #
|
|
938
|
+
background-color: #8300bf !important;
|
|
837
939
|
}
|
|
838
940
|
|
|
839
941
|
:deep(.p-select:not(.p-disabled).p-focus) {
|
|
840
|
-
|
|
942
|
+
border-color: #8300bf;
|
|
841
943
|
}
|
|
842
944
|
|
|
843
945
|
:deep(.p-slider-range) {
|
|
844
|
-
background-color: #
|
|
946
|
+
background-color: #8300bf;
|
|
845
947
|
}
|
|
846
948
|
|
|
847
949
|
div.input {
|
|
@@ -1045,21 +1147,33 @@ span.error {
|
|
|
1045
1147
|
|
|
1046
1148
|
.p-contextmenu-item-label,
|
|
1047
1149
|
.p-select-option-label {
|
|
1048
|
-
|
|
1049
|
-
|
|
1150
|
+
font-family:
|
|
1151
|
+
Inter,
|
|
1152
|
+
-apple-system,
|
|
1153
|
+
BlinkMacSystemFont,
|
|
1154
|
+
"Segoe UI",
|
|
1155
|
+
Roboto,
|
|
1156
|
+
Oxygen,
|
|
1157
|
+
Ubuntu,
|
|
1158
|
+
Cantarell,
|
|
1159
|
+
"Fira Sans",
|
|
1160
|
+
"Droid Sans",
|
|
1161
|
+
"Helvetica Neue",
|
|
1162
|
+
sans-serif;
|
|
1163
|
+
font-size: 0.875rem;
|
|
1050
1164
|
}
|
|
1051
1165
|
|
|
1052
1166
|
.p-select-option:not(.p-select-option-selected):not(.p-disabled).p-focus {
|
|
1053
|
-
|
|
1167
|
+
background: #f5f7fa !important;
|
|
1054
1168
|
}
|
|
1055
1169
|
|
|
1056
1170
|
.p-select-option.p-select-option-selected.p-focus {
|
|
1057
|
-
|
|
1058
|
-
|
|
1171
|
+
background: #f5f7fa !important;
|
|
1172
|
+
color: #8300bf !important;
|
|
1059
1173
|
}
|
|
1060
1174
|
|
|
1061
1175
|
.p-select-option.p-select-option-selected {
|
|
1062
|
-
|
|
1063
|
-
|
|
1176
|
+
background: white !important;
|
|
1177
|
+
color: #8300bf !important;
|
|
1064
1178
|
}
|
|
1065
1179
|
</style>
|