@abi-software/simulationvuer 0.4.4 → 0.5.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/simulationvuer.common.js +1047 -227
- package/dist/simulationvuer.common.js.map +1 -1
- package/dist/simulationvuer.css +1 -1
- package/dist/simulationvuer.umd.js +1047 -227
- package/dist/simulationvuer.umd.js.map +1 -1
- package/dist/simulationvuer.umd.min.js +1 -1
- package/dist/simulationvuer.umd.min.js.map +1 -1
- package/package.json +3 -2
- package/src/.DS_Store +0 -0
- package/src/App.vue +6 -4
- package/src/components/SimulationVuer.vue +138 -200
- package/src/components/common.js +29 -0
- package/src/components/configuration.js +139 -0
- package/src/components/json.js +373 -0
- package/src/components/ui.js +273 -0
- package/vue.config.js +2 -1
|
@@ -1,36 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="simulation-vuer" v-loading="simulationBeingComputed"
|
|
3
|
-
<p v-
|
|
4
|
-
<div class="main" v-
|
|
2
|
+
<div class="simulation-vuer" v-loading="simulationBeingComputed" element-loading-text="Loading simulation results...">
|
|
3
|
+
<p v-if="!hasValidJson" class="default error"><span class="error">Error:</span> an unknown or invalid model was provided.</p>
|
|
4
|
+
<div class="main" v-if="hasValidJson">
|
|
5
5
|
<div class="main-left">
|
|
6
|
-
<p class="default
|
|
7
|
-
<p class="default description">{{subtitle}}</p>
|
|
6
|
+
<p class="default title">{{title}}</p>
|
|
8
7
|
<el-divider></el-divider>
|
|
9
8
|
<p class="default input-parameters">Input parameters</p>
|
|
10
|
-
<div
|
|
11
|
-
<p class="default simulation-mode">Simulation mode</p>
|
|
12
|
-
<el-select class="simulation-mode" popper-class="simulation-mode-popper" :popper-append-to-body="false" v-model="simulationMode" size="mini" @change="simulationModeChanged()">
|
|
13
|
-
<el-option v-for="simulationMode in simulationModes" :key="simulationMode.value" :label="simulationMode.label" :value="simulationMode.value" />
|
|
14
|
-
</el-select>
|
|
15
|
-
<div class="sliders-and-fields">
|
|
16
|
-
<p class="default first-slider-and-field">Stimulation level</p>
|
|
17
|
-
<el-slider v-model="stimulationLevel" :max="10" :show-tooltip="false" :show-input="false" :disabled="simulationMode == 0" />
|
|
18
|
-
<el-input-number class="slider-and-field" v-model="stimulationLevel" size="mini" :controls="false" :min="0" :max="10" :disabled="simulationMode == 0" />
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
<div v-show="mode === 1">
|
|
22
|
-
<div class="sliders-and-fields">
|
|
23
|
-
<p class="default first-slider-and-field">Spike frequency</p>
|
|
24
|
-
<el-slider v-model="simulationSpikeFrequency" :max="1000" :show-tooltip="false" :show-input="false" />
|
|
25
|
-
<el-input-number class="slider-and-field" v-model="simulationSpikeFrequency" size="mini" :controls="false" :min="0" :max="1000" />
|
|
26
|
-
<p class="default slider-and-field">Spike number</p>
|
|
27
|
-
<el-slider v-model="simulationSpikeNumber" :max="30" :show-tooltip="false" :show-input="false" />
|
|
28
|
-
<el-input-number class="slider-and-field" v-model="simulationSpikeNumber" size="mini" :controls="false" :min="0" :max="30" />
|
|
29
|
-
<p class="default slider-and-field">Spike amplitude</p>
|
|
30
|
-
<el-slider v-model="simulationSpikeAmplitude" :max="30" :show-tooltip="false" :show-input="false" />
|
|
31
|
-
<el-input-number class="slider-and-field" v-model="simulationSpikeAmplitude" size="mini" :controls="false" :min="0" :max="30" />
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
9
|
+
<div ref="input" />
|
|
34
10
|
<div class="primary-button">
|
|
35
11
|
<el-button type="primary" size="mini" @click="runSimulation()">Run simulation</el-button>
|
|
36
12
|
</div>
|
|
@@ -40,14 +16,10 @@
|
|
|
40
16
|
<div class="secondary-button">
|
|
41
17
|
<el-button size="mini" @click="viewDataset()">View dataset</el-button>
|
|
42
18
|
</div>
|
|
43
|
-
<p class="default note">
|
|
44
|
-
</div>
|
|
45
|
-
<div class="main-right" v-if="mode === 0" v-show="simulationValid">
|
|
46
|
-
<PlotVuer :layout-input="simulationPotentialLayout" :dataInput="simulationPotentialData" :plotType="'plotly-only'" />
|
|
19
|
+
<p class="default note">Additional parameters are available on oSPARC</p>
|
|
47
20
|
</div>
|
|
48
|
-
<div class="main-right
|
|
49
|
-
<PlotVuer :layout-input="
|
|
50
|
-
<PlotVuer :layout-input="simulationPotentialLayout" :dataInput="simulationPotentialData" :plotType="'plotly-only'" />
|
|
21
|
+
<div class="main-right" ref="output" v-show="simulationValid">
|
|
22
|
+
<PlotVuer v-for="(outputPlot, index) in json.output.plots" :key="`output-${index}`" :layout-input="layout[index]" :dataInput="simulationData[index]" :plotType="'plotly-only'" />
|
|
51
23
|
</div>
|
|
52
24
|
<div class="main-right" v-show="!simulationValid">
|
|
53
25
|
<p class="default error"><span class="error">Error:</span> <span v-html="errorMessage"></span>.</p>
|
|
@@ -61,8 +33,11 @@ import Vue from "vue";
|
|
|
61
33
|
import { PlotVuer } from "@abi-software/plotvuer";
|
|
62
34
|
import "@abi-software/plotvuer/dist/plotvuer.css";
|
|
63
35
|
import { Aside, Button, Container, Divider, InputNumber, Loading, Main, Option, Select, Slider } from "element-ui";
|
|
64
|
-
|
|
65
|
-
|
|
36
|
+
import { jsonForNormalModel, jsonForCompositeModel } from "./configuration.js";
|
|
37
|
+
import { evaluateValue, evaluateSimulationValue } from "./common.js";
|
|
38
|
+
import { validJson } from "./json.js";
|
|
39
|
+
import Ui from "./ui.js";
|
|
40
|
+
import { prepareForUi } from "./ui.js";
|
|
66
41
|
|
|
67
42
|
Vue.use(Aside);
|
|
68
43
|
Vue.use(Button);
|
|
@@ -82,86 +57,27 @@ export default {
|
|
|
82
57
|
},
|
|
83
58
|
props: {
|
|
84
59
|
apiLocation: {
|
|
60
|
+
required: true,
|
|
85
61
|
type: String,
|
|
86
|
-
default: "",
|
|
87
62
|
},
|
|
88
63
|
entry: {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*/
|
|
92
|
-
entry: Object,
|
|
64
|
+
required: true,
|
|
65
|
+
type: Object,
|
|
93
66
|
},
|
|
94
67
|
},
|
|
95
|
-
data: function
|
|
96
|
-
let title = this.entry?this.entry.name:"";
|
|
97
|
-
let subtitle = this.entry?this.entry.description:"";
|
|
98
|
-
|
|
68
|
+
data: function() {
|
|
99
69
|
return {
|
|
100
|
-
mode: 0,
|
|
70
|
+
mode: 0, //---GRY--- TO BE DELETED!
|
|
71
|
+
json: {},
|
|
72
|
+
hasValidJson: true,
|
|
101
73
|
errorMessage: "",
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
simulationModes: [
|
|
106
|
-
{
|
|
107
|
-
label: "Normal sinus rhythm",
|
|
108
|
-
value: 0,
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
label: "Stellate stimulation",
|
|
112
|
-
value: 1,
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
label: "Vagal stimulation",
|
|
116
|
-
value: 2,
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
simulationSpikeLayout: {
|
|
120
|
-
xaxis: {
|
|
121
|
-
title: {
|
|
122
|
-
text: "Time (s)",
|
|
123
|
-
font: {
|
|
124
|
-
size: 10,
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
yaxis: {
|
|
129
|
-
title: {
|
|
130
|
-
text: "Spike amplitude",
|
|
131
|
-
font: {
|
|
132
|
-
size: 10,
|
|
133
|
-
},
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
simulationSpikeFrequency: 300,
|
|
138
|
-
simulationSpikeNumber: 10,
|
|
139
|
-
simulationSpikeAmplitude: 10, // The real value is 100 times smaller.
|
|
140
|
-
simulationSpikeData: NoSimulationData,
|
|
141
|
-
simulationPotentialLayout: {
|
|
142
|
-
xaxis: {
|
|
143
|
-
title: {
|
|
144
|
-
text: "Time (s)",
|
|
145
|
-
font: {
|
|
146
|
-
size: 10,
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
yaxis: {
|
|
151
|
-
title: {
|
|
152
|
-
text: "Membrane potential (mV)",
|
|
153
|
-
font: {
|
|
154
|
-
size: 10,
|
|
155
|
-
},
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
simulationPotentialData: NoSimulationData,
|
|
74
|
+
layout: [],
|
|
75
|
+
simulationData: [],
|
|
76
|
+
simulationDataId: {},
|
|
160
77
|
simulationBeingComputed: false,
|
|
161
|
-
simulationBeingComputedLabel: "Loading simulation results...",
|
|
162
78
|
simulationValid: true,
|
|
163
|
-
|
|
164
|
-
|
|
79
|
+
title: (this.entry !== undefined)?this.entry.name:"",
|
|
80
|
+
ui: null,
|
|
165
81
|
};
|
|
166
82
|
},
|
|
167
83
|
methods: {
|
|
@@ -171,65 +87,49 @@ export default {
|
|
|
171
87
|
viewDataset() {
|
|
172
88
|
window.open(this.entry.dataset, "_blank");
|
|
173
89
|
},
|
|
174
|
-
simulationModeChanged() {
|
|
175
|
-
this.simulationPotentialData = NoSimulationData;
|
|
176
|
-
this.simulationValid = true;
|
|
177
|
-
},
|
|
178
90
|
runSimulation() {
|
|
179
91
|
this.simulationBeingComputed = true;
|
|
180
92
|
|
|
181
|
-
|
|
93
|
+
let request = {
|
|
182
94
|
model_url: this.entry.resource,
|
|
183
|
-
json_config: {
|
|
184
|
-
output: ["Membrane/V"],
|
|
185
|
-
},
|
|
95
|
+
json_config: {},
|
|
186
96
|
};
|
|
187
97
|
|
|
188
98
|
// Specify the ending point and point interval for the normal mode (since
|
|
189
99
|
// our resource is a CellML file).
|
|
190
100
|
|
|
191
|
-
if (this.
|
|
192
|
-
request.json_config
|
|
193
|
-
"Ending point":
|
|
194
|
-
"Point interval":
|
|
101
|
+
if (this.json.simulation !== undefined) {
|
|
102
|
+
request.json_config.simulation = {
|
|
103
|
+
"Ending point": this.json.simulation.endingPoint,
|
|
104
|
+
"Point interval": this.json.simulation.pointInterval,
|
|
195
105
|
};
|
|
196
106
|
}
|
|
197
107
|
|
|
198
|
-
//
|
|
199
|
-
// Notes:
|
|
200
|
-
// - this.simulationMode:
|
|
201
|
-
// - 0: normal sinus rhythm;
|
|
202
|
-
// - 1: stellate stimulation; and
|
|
203
|
-
// - 2: vagal stimulation.
|
|
204
|
-
// - this.stimulationLevel has a value in [0; 10], but to compute ACh, we
|
|
205
|
-
// need a value in [0; 1].
|
|
206
|
-
|
|
207
|
-
if (this.simulationMode !== 0) {
|
|
208
|
-
request.json_config["parameters"] = {
|
|
209
|
-
"Rate_modulation_experiments/Iso_1_uM": 1.0,
|
|
210
|
-
"Rate_modulation_experiments/ACh": this.simulationMode === 1 ? (1.0 - 0.1 * this.stimulationLevel) * 22.0e-6 : 22.0e-6 + 0.1 * this.stimulationLevel * (38.0e-6 - 22.0e-6),
|
|
211
|
-
};
|
|
212
|
-
}
|
|
108
|
+
// Specify the simulation parameters.
|
|
213
109
|
|
|
214
|
-
|
|
110
|
+
if (this.json.parameters != undefined) {
|
|
111
|
+
request.json_config.parameters = {};
|
|
215
112
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
"Brain_stem/w_n": this.simulationSpikeNumber,
|
|
220
|
-
"Brain_stem/w_value": 0.01 * this.simulationSpikeAmplitude,
|
|
221
|
-
};
|
|
113
|
+
this.json.parameters.forEach((parameter) => {
|
|
114
|
+
request.json_config.parameters[parameter.name] = evaluateValue(this.ui, parameter.value);
|
|
115
|
+
});
|
|
222
116
|
}
|
|
223
117
|
|
|
224
|
-
//
|
|
118
|
+
// Specify what we want to retrieve.
|
|
119
|
+
|
|
120
|
+
if (this.json.output.data !== undefined) {
|
|
121
|
+
let index = -1;
|
|
225
122
|
|
|
226
|
-
|
|
227
|
-
|
|
123
|
+
request.json_config.output = [];
|
|
124
|
+
|
|
125
|
+
this.json.output.data.forEach((outputData) => {
|
|
126
|
+
request.json_config.output[++index] = outputData.name;
|
|
127
|
+
});
|
|
228
128
|
}
|
|
229
129
|
|
|
230
130
|
// Run the simulation.
|
|
231
131
|
|
|
232
|
-
|
|
132
|
+
let xmlhttp = new XMLHttpRequest();
|
|
233
133
|
|
|
234
134
|
xmlhttp.open("POST", this.apiLocation + "/simulation", true);
|
|
235
135
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
@@ -238,33 +138,32 @@ export default {
|
|
|
238
138
|
this.simulationBeingComputed = false;
|
|
239
139
|
|
|
240
140
|
if (xmlhttp.status === 200) {
|
|
241
|
-
|
|
141
|
+
let response = JSON.parse(xmlhttp.responseText);
|
|
242
142
|
|
|
243
143
|
this.simulationValid = response.status === "ok";
|
|
244
144
|
|
|
245
145
|
if (this.simulationValid) {
|
|
246
|
-
// Retrieve the
|
|
247
|
-
|
|
146
|
+
// Retrieve and post-process the simulation data.
|
|
147
|
+
|
|
148
|
+
let index = -1;
|
|
149
|
+
let iMax = response.results[this.simulationDataId[Object.keys(this.simulationDataId)[0]]].length;
|
|
150
|
+
|
|
151
|
+
this.json.output.plots.forEach((outputPlot) => {
|
|
152
|
+
let xValue = [];
|
|
153
|
+
let yValue = [];
|
|
248
154
|
|
|
249
|
-
|
|
250
|
-
|
|
155
|
+
for (let i = 0; i < iMax; ++i) {
|
|
156
|
+
xValue[i] = evaluateSimulationValue(this, response.results, outputPlot.xValue, i);
|
|
157
|
+
yValue[i] = evaluateSimulationValue(this, response.results, outputPlot.yValue, i);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.simulationData[++index] = [
|
|
251
161
|
{
|
|
252
|
-
x:
|
|
253
|
-
y:
|
|
254
|
-
return 100 * element;
|
|
255
|
-
}),
|
|
162
|
+
x: xValue,
|
|
163
|
+
y: yValue,
|
|
256
164
|
},
|
|
257
165
|
];
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Retrieve the potential data.
|
|
261
|
-
|
|
262
|
-
this.simulationPotentialData = [
|
|
263
|
-
{
|
|
264
|
-
x: response.results["environment/time"],
|
|
265
|
-
y: response.results["Membrane/V"],
|
|
266
|
-
},
|
|
267
|
-
];
|
|
166
|
+
});
|
|
268
167
|
} else {
|
|
269
168
|
this.errorMessage = response.description;
|
|
270
169
|
}
|
|
@@ -278,21 +177,40 @@ export default {
|
|
|
278
177
|
xmlhttp.send(JSON.stringify(request));
|
|
279
178
|
},
|
|
280
179
|
},
|
|
281
|
-
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
// - 0: normal mode; and
|
|
285
|
-
// - 1: composite mode.
|
|
180
|
+
created: function() {
|
|
181
|
+
// Manually (for now) specify the JSON configuration to be used by either
|
|
182
|
+
// the normal model or the composite model.
|
|
286
183
|
|
|
287
184
|
this.mode = -1;
|
|
288
185
|
|
|
289
|
-
if (this.entry) {
|
|
186
|
+
if (this.entry !== undefined) {
|
|
290
187
|
if (this.entry.resource === "https://models.physiomeproject.org/workspace/486/rawfile/55879cbc485e2d4c41f3dc6d60424b849f94c4ee/HumanSAN_Fabbri_Fantini_Wilders_Severi_2017.cellml") {
|
|
291
188
|
this.mode = 0;
|
|
189
|
+
this.json = jsonForNormalModel();
|
|
292
190
|
} else if (this.entry.resource === "https://models.physiomeproject.org/workspace/698/rawfile/f3fc911063ac72ed44e84c0c5af28df41c25d452/fabbri_et_al_based_composite_SAN_model.sedml") {
|
|
293
191
|
this.mode = 1;
|
|
192
|
+
this.json = jsonForCompositeModel();
|
|
294
193
|
}
|
|
295
194
|
}
|
|
195
|
+
|
|
196
|
+
// Make sure that the JSON configuration is valid.
|
|
197
|
+
|
|
198
|
+
this.hasValidJson = validJson(this.json);
|
|
199
|
+
|
|
200
|
+
if (!this.hasValidJson) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Prepare ourselves for the UI by initialising some data.
|
|
205
|
+
|
|
206
|
+
prepareForUi(this);
|
|
207
|
+
},
|
|
208
|
+
mounted: function() {
|
|
209
|
+
// Finish mounting by creating the UI for the given simulation dataset.
|
|
210
|
+
|
|
211
|
+
if (this.hasValidJson) {
|
|
212
|
+
this.ui = new Ui(this);
|
|
213
|
+
}
|
|
296
214
|
},
|
|
297
215
|
};
|
|
298
216
|
</script>
|
|
@@ -304,21 +222,21 @@ export default {
|
|
|
304
222
|
box-shadow: -3px 2px 4px #00000040;
|
|
305
223
|
}
|
|
306
224
|
>>> .el-divider {
|
|
307
|
-
margin: 8px 0;
|
|
225
|
+
margin: -8px 0 8px 0;
|
|
308
226
|
width: 191px;
|
|
309
227
|
}
|
|
310
|
-
>>> .el-input-number.
|
|
228
|
+
>>> .el-input-number.scalar {
|
|
311
229
|
margin-top: -8px;
|
|
312
230
|
width: 0;
|
|
313
231
|
height: 0;
|
|
314
232
|
}
|
|
315
|
-
>>> .el-input-number.
|
|
233
|
+
>>> .el-input-number.scalar .el-input {
|
|
316
234
|
width: 60px;
|
|
317
235
|
}
|
|
318
|
-
>>> .el-input-number.
|
|
236
|
+
>>> .el-input-number.scalar .el-input__inner:focus {
|
|
319
237
|
border-color: #8300bf;
|
|
320
238
|
}
|
|
321
|
-
>>> .el-select.
|
|
239
|
+
>>> .el-select.discrete {
|
|
322
240
|
margin-bottom: 16px;
|
|
323
241
|
}
|
|
324
242
|
>>> .el-slider {
|
|
@@ -332,20 +250,20 @@ export default {
|
|
|
332
250
|
>>> .el-slider__button {
|
|
333
251
|
border-color: #8300bf;
|
|
334
252
|
}
|
|
335
|
-
.
|
|
253
|
+
.discrete {
|
|
336
254
|
margin-left: 8px;
|
|
337
255
|
}
|
|
338
|
-
.
|
|
256
|
+
.discrete >>> .el-input__inner {
|
|
339
257
|
font-family: Asap, sans-serif;
|
|
340
258
|
}
|
|
341
|
-
.
|
|
342
|
-
.
|
|
259
|
+
.discrete >>> .el-input__inner:focus,
|
|
260
|
+
.discrete >>> .el-input.is-focus .el-input__inner {
|
|
343
261
|
border-color: #8300bf;
|
|
344
262
|
}
|
|
345
|
-
.
|
|
263
|
+
.discrete-popper .el-select-dropdown__item {
|
|
346
264
|
font-family: Asap, sans-serif;
|
|
347
265
|
}
|
|
348
|
-
.
|
|
266
|
+
.discrete-popper .el-select-dropdown__item.selected {
|
|
349
267
|
font-weight: normal;
|
|
350
268
|
color: #8300bf;
|
|
351
269
|
}
|
|
@@ -361,9 +279,33 @@ div.main-left {
|
|
|
361
279
|
height: 100%;
|
|
362
280
|
overflow: auto;
|
|
363
281
|
}
|
|
364
|
-
div.main-right.
|
|
282
|
+
div.main-right.x1 {
|
|
283
|
+
height: 100%;
|
|
284
|
+
}
|
|
285
|
+
div.main-right.x2 {
|
|
365
286
|
height: 50%;
|
|
366
287
|
}
|
|
288
|
+
div.main-right.x3 {
|
|
289
|
+
height: 33.333%;
|
|
290
|
+
}
|
|
291
|
+
div.main-right.x4 {
|
|
292
|
+
height: 25%;
|
|
293
|
+
}
|
|
294
|
+
div.main-right.x5 {
|
|
295
|
+
height: 20%;
|
|
296
|
+
}
|
|
297
|
+
div.main-right.x6 {
|
|
298
|
+
height: 16.667%;
|
|
299
|
+
}
|
|
300
|
+
div.main-right.x7 {
|
|
301
|
+
height: 14.286%;
|
|
302
|
+
}
|
|
303
|
+
div.main-right.x8 {
|
|
304
|
+
height: 12.5%;
|
|
305
|
+
}
|
|
306
|
+
div.main-right.x9 {
|
|
307
|
+
height: 11.111%;
|
|
308
|
+
}
|
|
367
309
|
>>> div.main-right div.controls {
|
|
368
310
|
height: 0;
|
|
369
311
|
}
|
|
@@ -413,39 +355,35 @@ p.default {
|
|
|
413
355
|
margin: 16px 0;
|
|
414
356
|
text-align: start;
|
|
415
357
|
}
|
|
416
|
-
p.description,
|
|
417
|
-
p.note {
|
|
418
|
-
font-size: 12px;
|
|
419
|
-
line-height: 16px;
|
|
420
|
-
}
|
|
421
|
-
p.description {
|
|
422
|
-
margin-top: -8px;
|
|
423
|
-
margin-bottom: 8px;
|
|
424
|
-
}
|
|
425
358
|
p.error {
|
|
426
359
|
margin-left: 16px;
|
|
427
360
|
}
|
|
428
|
-
p.first-
|
|
429
|
-
p.
|
|
361
|
+
p.first-scalar,
|
|
362
|
+
p.scalar {
|
|
430
363
|
grid-column-start: 1;
|
|
431
364
|
grid-column-end: 3;
|
|
432
365
|
margin-bottom: 8px;
|
|
433
366
|
}
|
|
434
|
-
p.
|
|
367
|
+
p.note {
|
|
368
|
+
font-size: 12px;
|
|
369
|
+
line-height: 16px;
|
|
370
|
+
}
|
|
371
|
+
p.title,
|
|
435
372
|
p.input-parameters {
|
|
436
373
|
margin-top: 0;
|
|
437
374
|
font-weight: 500 /* Medium */;
|
|
438
375
|
}
|
|
439
|
-
p.
|
|
376
|
+
p.title {
|
|
440
377
|
line-height: 20px;
|
|
441
378
|
}
|
|
442
|
-
p.
|
|
379
|
+
p.discrete {
|
|
380
|
+
margin-top: 0;
|
|
443
381
|
margin-bottom: 4px;
|
|
444
382
|
}
|
|
445
|
-
p.first-
|
|
383
|
+
p.first-scalar {
|
|
446
384
|
margin-top: 0;
|
|
447
385
|
}
|
|
448
|
-
p.
|
|
386
|
+
p.scalar {
|
|
449
387
|
margin-top: 6px;
|
|
450
388
|
}
|
|
451
389
|
span.error {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function doEvaluateValue(value, from, to) {
|
|
2
|
+
if (from !== undefined) {
|
|
3
|
+
let re = new RegExp(`\\b${ from }\\b`, 'g');
|
|
4
|
+
|
|
5
|
+
value = value.replace(re, to);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function evaluateValue(ui, value) {
|
|
12
|
+
ui.discreteElements.forEach((discreteElement) => {
|
|
13
|
+
value = doEvaluateValue(value, discreteElement.id, discreteElement.select.vModel);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
ui.scalarElements.forEach((scalarElement) => {
|
|
17
|
+
value = doEvaluateValue(value, scalarElement.id, scalarElement.input_number.vModel);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return Function("return " + value + ";")();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function evaluateSimulationValue(parent, results, value, i) {
|
|
24
|
+
parent.json.output.data.forEach((data) => {
|
|
25
|
+
value = doEvaluateValue(value, data.id, results[parent.simulationDataId[data.id]][i]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return Function("return " + value + ";")();
|
|
29
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export function jsonForNormalModel() {
|
|
2
|
+
return {
|
|
3
|
+
input: [
|
|
4
|
+
{
|
|
5
|
+
defaultValue: 0,
|
|
6
|
+
id: "sm",
|
|
7
|
+
name: "Simulation mode",
|
|
8
|
+
possibleValues: [
|
|
9
|
+
{
|
|
10
|
+
name: "Normal sinus rhythm",
|
|
11
|
+
value: 0,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "Stellate stimulation",
|
|
15
|
+
value: 1,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "Vagal stimulation",
|
|
19
|
+
value: 2,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
defaultValue: 0,
|
|
25
|
+
enabled: "(sm == 1) || (sm == 2)",
|
|
26
|
+
id: "sl",
|
|
27
|
+
maximumValue: 10,
|
|
28
|
+
minimumValue: 0,
|
|
29
|
+
name: "Stimulation level",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
output: {
|
|
33
|
+
data: [
|
|
34
|
+
{
|
|
35
|
+
id: "time",
|
|
36
|
+
name: "environment/time",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "vm",
|
|
40
|
+
name: "Membrane/V",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
plots: [
|
|
44
|
+
{
|
|
45
|
+
xAxisTitle: "Time (s)",
|
|
46
|
+
xValue: "time",
|
|
47
|
+
yAxisTitle: "Membrane potential (mV)",
|
|
48
|
+
yValue: "vm",
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
parameters: [
|
|
53
|
+
{
|
|
54
|
+
name: "Rate_modulation_experiments/Iso_1_uM",
|
|
55
|
+
value: "(sm == 0) ? 0.0 : 1.0",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "Rate_modulation_experiments/ACh",
|
|
59
|
+
value: "(sm == 0) ? 0.0 : (sm === 1) ? (1.0 - 0.1 * sl) * 22.0e-6 : 22.0e-6 + 0.1 * sl * (38.0e-6 - 22.0e-6)",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
simulation: {
|
|
63
|
+
endingPoint: 3.0,
|
|
64
|
+
pointInterval: 0.001,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function jsonForCompositeModel() {
|
|
70
|
+
return {
|
|
71
|
+
input: [
|
|
72
|
+
{
|
|
73
|
+
defaultValue: 300,
|
|
74
|
+
id: "sf",
|
|
75
|
+
maximumValue: 1000,
|
|
76
|
+
minimumValue: 0,
|
|
77
|
+
name: "Spike frequency",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
defaultValue: 10,
|
|
81
|
+
id: "sn",
|
|
82
|
+
maximumValue: 30,
|
|
83
|
+
minimumValue: 0,
|
|
84
|
+
name: "Spike number",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
defaultValue: 10,
|
|
88
|
+
id: "sa",
|
|
89
|
+
maximumValue: 30,
|
|
90
|
+
minimumValue: 0,
|
|
91
|
+
name: "Spike amplitude",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
output: {
|
|
95
|
+
data: [
|
|
96
|
+
{
|
|
97
|
+
id: "sa",
|
|
98
|
+
name: "Brain_stem/w",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: "time",
|
|
102
|
+
name: "environment/time",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "vm",
|
|
106
|
+
name: "Membrane/V",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
plots: [
|
|
110
|
+
{
|
|
111
|
+
xAxisTitle: "Time (s)",
|
|
112
|
+
xValue: "time",
|
|
113
|
+
yAxisTitle: "Spike amplitude",
|
|
114
|
+
yValue: "100.0 * sa",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
xAxisTitle: "Time (s)",
|
|
118
|
+
xValue: "time",
|
|
119
|
+
yAxisTitle: "Membrane potential (mV)",
|
|
120
|
+
yValue: "vm",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
parameters: [
|
|
125
|
+
{
|
|
126
|
+
name: "Brain_stem/t_period",
|
|
127
|
+
value: "sf",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "Brain_stem/w_n",
|
|
131
|
+
value: "sn",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "Brain_stem/w_value",
|
|
135
|
+
value: "0.01 * sa",
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
};
|
|
139
|
+
}
|