@abi-software/simulationvuer 0.5.0 → 0.5.1
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 +457 -662
- package/dist/simulationvuer.common.js.map +1 -1
- package/dist/simulationvuer.css +1 -1
- package/dist/simulationvuer.umd.js +457 -662
- 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 +1 -1
- package/src/.DS_Store +0 -0
- package/src/App.vue +10 -8
- package/src/components/SimulationVuer.vue +85 -141
- package/src/components/SimulationVuerInput.vue +150 -0
- package/src/components/common.js +7 -7
- package/src/components/json.js +3 -0
- package/src/components/ui.js +37 -230
- package/vue.config.js +1 -2
- package/src/components/configuration.js +0 -139
package/src/components/ui.js
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
import Vue from "vue";
|
|
2
1
|
import { evaluateValue } from "./common.js";
|
|
3
2
|
|
|
4
|
-
export function
|
|
3
|
+
export function initialiseUi(parent) {
|
|
4
|
+
// Initialise some input-related data.
|
|
5
|
+
|
|
5
6
|
let index = -1;
|
|
7
|
+
let isPreviousDiscrete = true;
|
|
8
|
+
|
|
9
|
+
parent.simulationUiInformation.input.forEach((input) => {
|
|
10
|
+
let isDiscrete = input.possibleValues !== undefined;
|
|
11
|
+
|
|
12
|
+
parent.firstScalarInput[++index] = !isDiscrete && isPreviousDiscrete;
|
|
13
|
+
|
|
14
|
+
isPreviousDiscrete = isDiscrete;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Initialise some output-related data.
|
|
6
18
|
|
|
7
|
-
parent.
|
|
19
|
+
parent.simulationUiInformation.output.data.forEach((data) => {
|
|
8
20
|
parent.simulationDataId[data.id] = data.name;
|
|
9
21
|
});
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
index = -1;
|
|
24
|
+
|
|
25
|
+
parent.simulationUiInformation.output.plots.forEach((outputPlot) => {
|
|
12
26
|
++index;
|
|
13
27
|
|
|
14
28
|
parent.layout[index] = {
|
|
@@ -34,240 +48,33 @@ export function prepareForUi(parent) {
|
|
|
34
48
|
});
|
|
35
49
|
}
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
`,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const VueInputNumber = Vue.extend({
|
|
44
|
-
methods: {
|
|
45
|
-
emitSynchroniseSliderAndInputNumber: function(value) {
|
|
46
|
-
this.$emit("synchroniseSliderAndInputNumber", this.index, value);
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
props: {
|
|
50
|
-
disabled: Boolean,
|
|
51
|
-
index: Number,
|
|
52
|
-
maximumValue: Number,
|
|
53
|
-
minimumValue: Number,
|
|
54
|
-
parent: Object,
|
|
55
|
-
vModel: Number,
|
|
56
|
-
},
|
|
57
|
-
template: `
|
|
58
|
-
<el-input-number class="scalar" size="mini" v-model="vModel" :controls="false" :disabled="disabled" :max="maximumValue" :min="minimumValue" @change="emitSynchroniseSliderAndInputNumber" />
|
|
59
|
-
`,
|
|
60
|
-
});
|
|
51
|
+
export function finaliseUi(parent) {
|
|
52
|
+
// Finalise our UI, but only if we haven't already done so, we are mounted,
|
|
53
|
+
// and we have some valid simulation UI information.
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
classes: String,
|
|
65
|
-
label: String,
|
|
66
|
-
},
|
|
67
|
-
template: `
|
|
68
|
-
<p :class="classes">{{ label }}</p>
|
|
69
|
-
`,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const VueSelect = Vue.extend({
|
|
73
|
-
methods: {
|
|
74
|
-
emitSelectionChanged: function(value) {
|
|
75
|
-
this.$emit("selectionChanged", this.index, value);
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
props: {
|
|
79
|
-
index: Number,
|
|
80
|
-
parent: Object,
|
|
81
|
-
possibleValues: Array,
|
|
82
|
-
vModel: Number,
|
|
83
|
-
},
|
|
84
|
-
template: `
|
|
85
|
-
<el-select class="discrete" popper-class="discrete-popper" size="mini" v-model="vModel" :popper-append-to-body="false" @change="emitSelectionChanged">
|
|
86
|
-
<el-option v-for="possibleValue in possibleValues" :key="possibleValue.value" :label="possibleValue.name" :value="possibleValue.value" />
|
|
87
|
-
</el-select>
|
|
88
|
-
`,
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const VueSlider = Vue.extend({
|
|
92
|
-
methods: {
|
|
93
|
-
emitSynchroniseSliderAndInputNumber: function(value) {
|
|
94
|
-
this.$emit("synchroniseSliderAndInputNumber", this.index, value);
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
props: {
|
|
98
|
-
disabled: Boolean,
|
|
99
|
-
index: Number,
|
|
100
|
-
maximumValue: Number,
|
|
101
|
-
parent: Object,
|
|
102
|
-
vModel: Number,
|
|
103
|
-
},
|
|
104
|
-
template: `
|
|
105
|
-
<el-slider v-model="vModel" :disabled="disabled" :max="maximumValue" :show-input="false" :show-tooltip="false" @input="emitSynchroniseSliderAndInputNumber" />
|
|
106
|
-
`,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
export default class Ui {
|
|
110
|
-
discreteElements = [];
|
|
111
|
-
scalarElements = [];
|
|
112
|
-
|
|
113
|
-
setVueAttributes(root, element) {
|
|
114
|
-
root.attributes.forEach((attribute) => {
|
|
115
|
-
element.setAttribute(attribute.nodeName, attribute.nodeValue);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
element.children.forEach((childElement) => {
|
|
119
|
-
this.setVueAttributes(root, childElement);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
addVueElement(root, parent, element) {
|
|
124
|
-
element.$mount();
|
|
125
|
-
|
|
126
|
-
this.setVueAttributes(root, element.$el);
|
|
127
|
-
|
|
128
|
-
parent.appendChild(element.$el);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
selectionChanged() {
|
|
132
|
-
// Enable/disable all the scalar elements.
|
|
55
|
+
if (!parent.hasFinalisedUi && parent.isMounted && parent.hasValidSimulationUiInformation) {
|
|
56
|
+
// Configure the PlotVuer's.
|
|
133
57
|
|
|
134
|
-
|
|
58
|
+
parent.$refs.output.classList.add("x" + parent.simulationUiInformation.output.plots.length);
|
|
135
59
|
|
|
136
|
-
|
|
137
|
-
let enabled = scalarElement.enabled;
|
|
60
|
+
// Make sure that our UI is up to date.
|
|
138
61
|
|
|
139
|
-
|
|
140
|
-
let disabled = !evaluateValue(ui, enabled);
|
|
62
|
+
updateUi(parent);
|
|
141
63
|
|
|
142
|
-
|
|
143
|
-
scalarElement.input_number.disabled = disabled;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
64
|
+
parent.hasFinalisedUi = true;
|
|
146
65
|
}
|
|
66
|
+
}
|
|
147
67
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
this.parent.scalarElements[index].slider.vModel = value;
|
|
153
|
-
this.parent.scalarElements[index].input_number.vModel = value;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
constructor(parent) {
|
|
157
|
-
// Generate the UI for the input fields.
|
|
158
|
-
|
|
159
|
-
let inputRoot = parent.$refs.input;
|
|
160
|
-
let isPreviousDiscrete = true;
|
|
161
|
-
let slidersAndFieldsContainer = undefined;
|
|
162
|
-
let firstScalarInput = true;
|
|
163
|
-
let discreteElementIndex = -1;
|
|
164
|
-
let scalarElementIndex = -1;
|
|
165
|
-
|
|
166
|
-
parent.json.input.forEach((input) => {
|
|
167
|
-
// Determine whether we are dealing with a discrete or a scalar input.
|
|
168
|
-
|
|
169
|
-
let isDiscrete = input.possibleValues !== undefined;
|
|
170
|
-
|
|
171
|
-
// Determine our element mode and create a container for our sliders and
|
|
172
|
-
// input numbers, if needed.
|
|
173
|
-
|
|
174
|
-
if (!isDiscrete && isPreviousDiscrete) {
|
|
175
|
-
slidersAndFieldsContainer = new VueContainer();
|
|
176
|
-
|
|
177
|
-
this.addVueElement(inputRoot, inputRoot, slidersAndFieldsContainer);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
isPreviousDiscrete = isDiscrete;
|
|
181
|
-
|
|
182
|
-
// Add the Label.
|
|
183
|
-
|
|
184
|
-
let label = new VueLabel({
|
|
185
|
-
propsData: {
|
|
186
|
-
classes: "default " + (isDiscrete?"discrete":firstScalarInput?"first-scalar":"scalar"),
|
|
187
|
-
label: input.name,
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
this.addVueElement(inputRoot, isDiscrete?inputRoot:slidersAndFieldsContainer.$el, label);
|
|
192
|
-
|
|
193
|
-
firstScalarInput = isDiscrete;
|
|
194
|
-
|
|
195
|
-
// Add a drop-down list or a slider and a text box depending on whether
|
|
196
|
-
// we are dealing with a discrete or a scalar input.
|
|
197
|
-
|
|
198
|
-
if (isDiscrete) {
|
|
199
|
-
// Add the drop-down list.
|
|
200
|
-
|
|
201
|
-
++discreteElementIndex;
|
|
202
|
-
|
|
203
|
-
let select = new VueSelect({
|
|
204
|
-
propsData: {
|
|
205
|
-
index: discreteElementIndex,
|
|
206
|
-
parent: this,
|
|
207
|
-
possibleValues: input.possibleValues,
|
|
208
|
-
vModel: input.defaultValue,
|
|
209
|
-
},
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
this.addVueElement(inputRoot, inputRoot, select);
|
|
213
|
-
|
|
214
|
-
select.$on("selectionChanged", this.selectionChanged);
|
|
215
|
-
|
|
216
|
-
// Keep track of the select and its id.
|
|
217
|
-
|
|
218
|
-
this.discreteElements[discreteElementIndex] = {
|
|
219
|
-
id: input.id,
|
|
220
|
-
select: select,
|
|
221
|
-
};
|
|
222
|
-
} else {
|
|
223
|
-
// Add the slider and input number.
|
|
224
|
-
|
|
225
|
-
++scalarElementIndex;
|
|
226
|
-
|
|
227
|
-
let slider = new VueSlider({
|
|
228
|
-
propsData: {
|
|
229
|
-
index: scalarElementIndex,
|
|
230
|
-
maximumValue: input.maximumValue,
|
|
231
|
-
parent: this,
|
|
232
|
-
vModel: input.defaultValue,
|
|
233
|
-
},
|
|
234
|
-
});
|
|
235
|
-
let inputNumber = new VueInputNumber({
|
|
236
|
-
propsData: {
|
|
237
|
-
index: scalarElementIndex,
|
|
238
|
-
maximumValue: input.maximumValue,
|
|
239
|
-
minimumValue: input.minimumValue,
|
|
240
|
-
parent: this,
|
|
241
|
-
vModel: input.defaultValue,
|
|
242
|
-
},
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
this.addVueElement(inputRoot, slidersAndFieldsContainer.$el, slider);
|
|
246
|
-
this.addVueElement(inputRoot, slidersAndFieldsContainer.$el, inputNumber);
|
|
247
|
-
|
|
248
|
-
slider.$on("synchroniseSliderAndInputNumber", this.synchroniseSliderAndInputNumber);
|
|
249
|
-
inputNumber.$on("synchroniseSliderAndInputNumber", this.synchroniseSliderAndInputNumber);
|
|
68
|
+
export function updateUi(parent) {
|
|
69
|
+
// Enable/disable all the elements.
|
|
70
|
+
// Note: we do this using $nextTick() to be ensure that the UI has been fully
|
|
71
|
+
// mounted.
|
|
250
72
|
|
|
251
|
-
|
|
73
|
+
parent.$nextTick(() => {
|
|
74
|
+
let index = -1;
|
|
252
75
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
id: input.id,
|
|
256
|
-
input_number: inputNumber,
|
|
257
|
-
slider: slider,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
76
|
+
parent.simulationUiInformation.input.forEach((input) => {
|
|
77
|
+
parent.$children[++index].enabled = (input.enabled === undefined)?true:evaluateValue(parent, input.enabled);
|
|
260
78
|
});
|
|
261
|
-
|
|
262
|
-
// Configure the PlotVuer's.
|
|
263
|
-
// Note: the PlotVuer's are created in SimulationVuer.vue since we can't
|
|
264
|
-
// create them dynamically. So, all we need to do here is to configure
|
|
265
|
-
// them.
|
|
266
|
-
|
|
267
|
-
parent.$refs.output.classList.add("x" + parent.json.output.plots.length);
|
|
268
|
-
|
|
269
|
-
// Enable/disable all the elements by pretending that a selection changed.
|
|
270
|
-
|
|
271
|
-
this.selectionChanged();
|
|
272
|
-
}
|
|
79
|
+
});
|
|
273
80
|
}
|
package/vue.config.js
CHANGED
|
@@ -1,139 +0,0 @@
|
|
|
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
|
-
}
|