@abi-software/simulationvuer 2.0.20 → 3.0.0
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/dist/quill-CuAVUOyy-B7CbeCk7.js +7527 -0
- package/dist/simulationvuer.js +50987 -20263
- package/dist/simulationvuer.umd.cjs +5194 -49
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/App.vue +1 -1
- package/src/components/SimulationVuer.vue +96 -97
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abi-software/simulationvuer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"serve": "vite serve --host --force",
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@abi-software/plotvuer": "1.0.7",
|
|
21
|
+
"@opencor/opencor": "^0.20251112.0",
|
|
21
22
|
"element-plus": "2.8.4",
|
|
22
23
|
"jsonschema": "^1.4.0",
|
|
23
|
-
"mathjs": "^13.0.2",
|
|
24
24
|
"unplugin-vue-components": "^0.26.0",
|
|
25
25
|
"vue": "^3.4.21"
|
|
26
26
|
},
|
package/src/App.vue
CHANGED
|
@@ -174,7 +174,6 @@ export default {
|
|
|
174
174
|
top: 8px;
|
|
175
175
|
right: 8px;
|
|
176
176
|
width: 192px;
|
|
177
|
-
height: 48px;
|
|
178
177
|
border: 2px dashed #8300bf;
|
|
179
178
|
background-color: #f9f2fc;
|
|
180
179
|
color: #8300bf;
|
|
@@ -227,6 +226,7 @@ a {
|
|
|
227
226
|
|
|
228
227
|
div.app {
|
|
229
228
|
text-align: center;
|
|
229
|
+
margin-bottom: 8px;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
h3 {
|
|
@@ -1,53 +1,58 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="simulation-vuer" v-loading="showUserMessage" :element-loading-text="userMessage">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
<div class="main
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<div class="buttons-container">
|
|
22
|
-
<div class="primary-button" v-if="!libopencorSet">
|
|
23
|
-
<el-button type="primary" size="small" @click="startSimulation()">Run Simulation</el-button>
|
|
24
|
-
</div>
|
|
25
|
-
<div class="secondary-button" v-if="uuid">
|
|
26
|
-
<el-button size="small" @click="runOnOsparc()">Run on oSPARC</el-button>
|
|
3
|
+
<div class="container" v-if="opencorOmexFile === null">
|
|
4
|
+
<p v-if="!hasValidSimulationUiInfo && !showUserMessage" class="default error"><span class="error">Error:</span> {{ errorMessage }}.</p>
|
|
5
|
+
<div class="main" v-if="hasValidSimulationUiInfo">
|
|
6
|
+
<div class="main-left" :class="{'with-buttons': !libopencorSet || uuid}">
|
|
7
|
+
<p class="default name" v-if="!libopencorSet">{{ name }}</p>
|
|
8
|
+
<el-divider v-if="!libopencorSet"></el-divider>
|
|
9
|
+
<p class="default input-parameters">Input parameters</p>
|
|
10
|
+
<div class="input scrollbar">
|
|
11
|
+
<SimulationVuerInput v-for="(input, index) in simulationUiInfo.input"
|
|
12
|
+
ref="simInput"
|
|
13
|
+
:defaultValue="input.defaultValue"
|
|
14
|
+
:key="`input-${index}`"
|
|
15
|
+
:name="input.name"
|
|
16
|
+
:maximumValue="input.maximumValue"
|
|
17
|
+
:minimumValue="input.minimumValue"
|
|
18
|
+
:possibleValues="input.possibleValues"
|
|
19
|
+
:stepValue="input.stepValue"
|
|
20
|
+
/>
|
|
27
21
|
</div>
|
|
28
|
-
<div class="
|
|
29
|
-
<
|
|
22
|
+
<div class="buttons-container">
|
|
23
|
+
<div class="primary-button" v-if="!libopencorSet">
|
|
24
|
+
<el-button type="primary" size="small" @click="startSimulation()">Run Simulation</el-button>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="secondary-button" v-if="uuid">
|
|
27
|
+
<el-button size="small" @click="runOnOsparc()">Run on oSPARC</el-button>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="secondary-button" v-if="!libopencorSet">
|
|
30
|
+
<el-button size="small" @click="viewDataset()">View Dataset</el-button>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="secondary-button" v-if="libopencorSet && idType === 'pmr_path'">
|
|
33
|
+
<el-button size="small" @click="viewWorkspace()">View Workspace</el-button>
|
|
34
|
+
</div>
|
|
35
|
+
<p class="default note" v-if="uuid">Additional parameters are available on oSPARC</p>
|
|
30
36
|
</div>
|
|
31
|
-
<div class="secondary-button" v-if="libopencorSet && idType === 'pmr_path'">
|
|
32
|
-
<el-button size="small" @click="viewWorkspace()">View Workspace</el-button>
|
|
33
|
-
</div>
|
|
34
|
-
<p class="default note" v-if="uuid">Additional parameters are available on oSPARC</p>
|
|
35
37
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
<div class="main-right" ref="output" v-show="isSimulationValid">
|
|
39
|
+
<PlotVuer v-for="(_outputPlot, index) in simulationUiInfo.output.plots"
|
|
40
|
+
:key="`output-${index}`"
|
|
41
|
+
:metadata="plotMetadata(index)"
|
|
42
|
+
:data-source="{ data: simulationResults[index] }"
|
|
43
|
+
:plotLayout="layout[index]"
|
|
44
|
+
:plotType="'plotly-only'"
|
|
45
|
+
:selectorUi="false"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="main-right" v-show="!isSimulationValid">
|
|
49
|
+
<p class="default error"><span class="error">Error:</span> <span v-html="errorMessage"></span>.</p>
|
|
50
|
+
</div>
|
|
49
51
|
</div>
|
|
50
52
|
</div>
|
|
53
|
+
<div v-else class="opencor">
|
|
54
|
+
<OpenCOR :omex="opencorOmexFile" theme="light" />
|
|
55
|
+
</div>
|
|
51
56
|
</div>
|
|
52
57
|
</template>
|
|
53
58
|
|
|
@@ -61,9 +66,9 @@ import { validJson } from "./json.js";
|
|
|
61
66
|
import libOpenCOR from "https://mapcore-demo.org/current/opencor-wasm/0.0.3/libopencor.js";
|
|
62
67
|
import { markRaw } from "vue";
|
|
63
68
|
import { create, all } from "mathjs";
|
|
69
|
+
import OpenCOR from '@opencor/opencor';
|
|
70
|
+
import '@opencor/opencor/style.css';
|
|
64
71
|
|
|
65
|
-
const LIBOPENCOR_SOLVER = "libOpenCOR";
|
|
66
|
-
const OSPARC_SOLVER = "oSPARC";
|
|
67
72
|
const PMR_URL = "https://models.physiomeproject.org/";
|
|
68
73
|
|
|
69
74
|
const math = create(all, {});
|
|
@@ -79,8 +84,6 @@ const IdType = Object.freeze({
|
|
|
79
84
|
* SimulationVuer
|
|
80
85
|
*/
|
|
81
86
|
export default {
|
|
82
|
-
LIBOPENCOR_SOLVER: LIBOPENCOR_SOLVER,
|
|
83
|
-
OSPARC_SOLVER: OSPARC_SOLVER,
|
|
84
87
|
name: "SimulationVuer",
|
|
85
88
|
components: {
|
|
86
89
|
PlotVuer,
|
|
@@ -88,6 +91,7 @@ export default {
|
|
|
88
91
|
ElButton,
|
|
89
92
|
ElDivider,
|
|
90
93
|
ElLoading,
|
|
94
|
+
OpenCOR,
|
|
91
95
|
},
|
|
92
96
|
props: {
|
|
93
97
|
/**
|
|
@@ -158,6 +162,7 @@ export default {
|
|
|
158
162
|
model: undefined,
|
|
159
163
|
name: null,
|
|
160
164
|
opencorBasedSimulation: true,
|
|
165
|
+
opencorOmexFile: null,
|
|
161
166
|
output: undefined,
|
|
162
167
|
perfectScollbarOptions: {
|
|
163
168
|
suppressScrollX: true,
|
|
@@ -741,57 +746,9 @@ export default {
|
|
|
741
746
|
xmlhttp.send();
|
|
742
747
|
});
|
|
743
748
|
} else if (this.idType === IdType.DATASET_URL) {
|
|
744
|
-
this.
|
|
745
|
-
this.showUserMessage = true;
|
|
746
|
-
|
|
747
|
-
// Retrieve the COMBINE archive, extract the simulation UI JSON file from
|
|
748
|
-
// it and then build the simulation UI.
|
|
749
|
-
|
|
750
|
-
this.$nextTick(() => {
|
|
751
|
-
const xmlhttp = new XMLHttpRequest();
|
|
752
|
-
|
|
753
|
-
xmlhttp.open("GET", this.id);
|
|
754
|
-
xmlhttp.responseType = "arraybuffer";
|
|
755
|
-
xmlhttp.onreadystatechange = () => {
|
|
756
|
-
if (xmlhttp.readyState === 4) {
|
|
757
|
-
if (xmlhttp.status === 200) {
|
|
758
|
-
libOpenCOR().then((libopencor) => {
|
|
759
|
-
this.extractAndBuildSimulationUi(libopencor, new Uint8Array(xmlhttp.response));
|
|
760
|
-
});
|
|
761
|
-
} else {
|
|
762
|
-
this.errorMessage = "the COMBINE archive could not be retrieved";
|
|
763
|
-
this.showUserMessage = false;
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
xmlhttp.send();
|
|
768
|
-
});
|
|
749
|
+
this.opencorOmexFile = this.id;
|
|
769
750
|
} else if (this.idType === IdType.PMR_PATH) {
|
|
770
|
-
this.
|
|
771
|
-
this.showUserMessage = true;
|
|
772
|
-
|
|
773
|
-
// Retrieve the COMBINE archive, extract the simulation UI JSON file from
|
|
774
|
-
// it and then build the simulation UI.
|
|
775
|
-
|
|
776
|
-
this.$nextTick(() => {
|
|
777
|
-
const xmlhttp = new XMLHttpRequest();
|
|
778
|
-
|
|
779
|
-
xmlhttp.open("POST", this.apiLocation + "/pmr_file");
|
|
780
|
-
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
781
|
-
xmlhttp.onreadystatechange = () => {
|
|
782
|
-
if (xmlhttp.readyState === 4) {
|
|
783
|
-
if (xmlhttp.status === 200) {
|
|
784
|
-
libOpenCOR().then((libopencor) => {
|
|
785
|
-
this.extractAndBuildSimulationUi(libopencor, Uint8Array.from(atob(xmlhttp.response), (c) => c.charCodeAt(0)));
|
|
786
|
-
});
|
|
787
|
-
} else {
|
|
788
|
-
this.errorMessage = "the COMBINE archive chould not be retrieved from PMR";
|
|
789
|
-
this.showUserMessage = false;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
xmlhttp.send(JSON.stringify({ path: this.id }));
|
|
794
|
-
});
|
|
751
|
+
this.opencorOmexFile = PMR_URL + this.id;
|
|
795
752
|
} else {
|
|
796
753
|
// Extract the simulation UI JSON file from the COMBINE archive and build
|
|
797
754
|
// the simulation UI.
|
|
@@ -848,6 +805,22 @@ export default {
|
|
|
848
805
|
}
|
|
849
806
|
}
|
|
850
807
|
|
|
808
|
+
:deep(.p-floatlabel:has(input:focus)) label, :deep(.p-floatlabel:has(input:-webkit-autofill)) label, :deep(.p-floatlabel:has(textarea:focus)) label, :deep(.p-floatlabel:has(.p-inputwrapper-focus)) label {
|
|
809
|
+
color: #8300BF;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
:deep(.p-inputtext:enabled:focus) {
|
|
813
|
+
border-color: #8300BF;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
:deep(.p-select:not(.p-disabled).p-focus) {
|
|
817
|
+
border-color: #8300BF;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
:deep(.p-slider-range) {
|
|
821
|
+
background-color: #8300BF;
|
|
822
|
+
}
|
|
823
|
+
|
|
851
824
|
div.input {
|
|
852
825
|
display: flex;
|
|
853
826
|
flex-direction: column;
|
|
@@ -866,6 +839,10 @@ div.input {
|
|
|
866
839
|
flex-shrink: 0;
|
|
867
840
|
}
|
|
868
841
|
|
|
842
|
+
div.container {
|
|
843
|
+
height: 100%;
|
|
844
|
+
}
|
|
845
|
+
|
|
869
846
|
div.main {
|
|
870
847
|
display: grid;
|
|
871
848
|
--mainLeftWidth: 243px;
|
|
@@ -929,6 +906,10 @@ div.main-right.x9 > .plotvuer_parent {
|
|
|
929
906
|
height: 0;
|
|
930
907
|
}
|
|
931
908
|
|
|
909
|
+
div.opencor {
|
|
910
|
+
height: 100%;
|
|
911
|
+
}
|
|
912
|
+
|
|
932
913
|
div.primary-button,
|
|
933
914
|
div.secondary-button {
|
|
934
915
|
display: flex;
|
|
@@ -1035,3 +1016,21 @@ span.error {
|
|
|
1035
1016
|
}
|
|
1036
1017
|
}
|
|
1037
1018
|
</style>
|
|
1019
|
+
|
|
1020
|
+
<style>
|
|
1021
|
+
/* Note: not sure why, but the following rules need to be global!? */
|
|
1022
|
+
|
|
1023
|
+
.p-select-option:not(.p-select-option-selected):not(.p-disabled).p-focus {
|
|
1024
|
+
background: #F5F7FA;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
.p-select-option.p-select-option-selected.p-focus {
|
|
1028
|
+
background: #F5F7FA;
|
|
1029
|
+
color: #8300BF;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
.p-select-option.p-select-option-selected {
|
|
1033
|
+
background: white;
|
|
1034
|
+
color: #8300BF;
|
|
1035
|
+
}
|
|
1036
|
+
</style>
|