@@ -771,6 +771,7 @@ export interface ISimulationExperimentViewSettings {
const props = defineProps<{
settings: ISimulationExperimentViewSettings;
+ voiId: string;
voiName: string;
voiUnit: string;
allModelParameters: string[];
@@ -783,7 +784,7 @@ const emit = defineEmits<{
}>();
const DEFAULT_TAB = 'interactive';
-const DEFAULT_INTERACTIVE_TAB = 'modelInputs';
+const DEFAULT_INTERACTIVE_TAB = 'simulationInputs';
const simulationSettingsIssuesPopup = vue.ref<{ toggle: (event: Event) => void } | null>(null);
const solversSettingsIssuesPopup = vue.ref<{ toggle: (event: Event) => void } | null>(null);
@@ -884,7 +885,6 @@ const uiJsonIssues = vue.computed(() => {
return validateUiJson(localSettings.value.interactive.uiJson);
});
-const voiNameId = props.voiName.split('/').slice(-1)[0];
function plotTraceCount(plot: locApi.IUiJsonOutputPlot): number {
return 1 + (plot.additionalTraces?.length ?? 0);
@@ -998,8 +998,8 @@ function removePossibleValue(inputIndex: number, possibleValueIndex: number) {
function addSimulationData() {
localSettings.value.interactive.uiJson.output.data.push({
- id: voiNameId,
- name: props.voiName
+ id: `simulation_data`,
+ name: 'component/variable'
});
}
@@ -1012,7 +1012,7 @@ function addPlot() {
localSettings.value.interactive.uiJson.output.plots.push({
name: '',
xAxisTitle: '',
- xValue: voiNameId,
+ xValue: props.voiId,
yAxisTitle: '',
yValue: 'y_id',
additionalTraces: []
@@ -1033,7 +1033,7 @@ function addTrace(plotIndex: number) {
}
plot.additionalTraces.push({
- xValue: voiNameId,
+ xValue: props.voiId,
yValue: 'y_id'
});
}
@@ -1058,7 +1058,7 @@ function removeTrace(plotIndex: number, traceIndex: number) {
plot.yValue = firstAdditionalTrace.yValue;
} else {
plot.name = undefined;
- plot.xValue = voiNameId;
+ plot.xValue = props.voiId;
plot.yValue = 'y_id';
}
diff --git a/src/renderer/src/components/views/SimulationExperimentView.vue b/src/renderer/src/components/views/SimulationExperimentView.vue
index 906bb31c..cf1c5750 100644
--- a/src/renderer/src/components/views/SimulationExperimentView.vue
+++ b/src/renderer/src/components/views/SimulationExperimentView.vue
@@ -227,7 +227,8 @@
(!!props.uiJson);
const interactiveLiveUpdatesEnabled = vue.ref(true);
const interactiveSettingsVisible = vue.ref(false);
-const interactiveUiJson = vue.ref(initialUiJson());
-const interactiveUiJsonEmpty = vue.computed(() => {
- return (
- interactiveUiJson.value.input.length === 0 &&
- interactiveUiJson.value.output.data.length === 0 &&
- interactiveUiJson.value.output.plots.length === 0 &&
- interactiveUiJson.value.parameters.length === 0
- );
-});
const interactiveFile = props.file;
const interactiveDocument = interactiveFile.document();
const interactiveUniformTimeCourse = interactiveDocument.simulation(0) as locApi.SedUniformTimeCourse;
@@ -500,6 +492,28 @@ let interactiveInstance = interactiveDocument.instantiate();
let interactiveInstanceTask = interactiveInstance.task(0);
const interactiveAllModelParameters = vue.ref([]);
const interactiveEditableModelParameters = vue.ref([]);
+const interactiveVoiName = vue.ref(interactiveInstanceTask.voiName());
+const interactiveVoiId = vue.ref(interactiveVoiName.value.split('/')[1]);
+const interactiveUiJson = vue.ref(initialUiJson());
+const interactiveUiJsonEmpty = vue.computed(() => {
+ if (
+ interactiveUiJson.value.input.length === 0 &&
+ interactiveUiJson.value.output.plots.length === 0 &&
+ interactiveUiJson.value.parameters.length === 0
+ ) {
+ if (interactiveUiJson.value.output.data.length === 0) {
+ return true;
+ }
+
+ if (interactiveUiJson.value.output.data.length === 1) {
+ const data = interactiveUiJson.value.output.data[0];
+
+ return data.id === interactiveVoiId.value && data.name === interactiveVoiName.value;
+ }
+ }
+
+ return false;
+});
const interactiveMath = mathjs.create(mathjs.all ?? {}, {});
const interactiveModel = interactiveDocument.model(0);
const interactiveData = vue.ref([]);
@@ -596,10 +610,17 @@ function initialUiJson(): locApi.IUiJson {
return JSON.parse(JSON.stringify(props.uiJson));
}
+ // No UI JSON provided, so we create a default one with the VOI as a default simulation data.
+
return {
input: [],
output: {
- data: [],
+ data: [
+ {
+ id: interactiveVoiId.value,
+ name: interactiveVoiName.value
+ }
+ ],
plots: []
},
parameters: []
diff --git a/src/renderer/src/components/widgets/GraphPanelWidget.vue b/src/renderer/src/components/widgets/GraphPanelWidget.vue
index 40fcbefb..a9752b34 100644
--- a/src/renderer/src/components/widgets/GraphPanelWidget.vue
+++ b/src/renderer/src/components/widgets/GraphPanelWidget.vue
@@ -415,55 +415,47 @@ function themeData(): IThemeData {
};
}
-interface IAxesData {
- xaxis: {
- tickangle: number;
- automargin: boolean;
- title: {
- font: {
- size: number;
- };
- text?: string;
- standoff: number;
- };
+interface IAxesDataAxis {
+ automargin: boolean;
+ tickangle: number;
+ tickfont: {
+ size: number;
};
- yaxis: {
- tickangle: number;
- automargin: boolean;
- title: {
- font: {
- size: number;
- };
- text?: string;
- standoff: number;
- };
+ title: {
+ standoff: number;
+ text?: string;
};
}
+interface IAxesData {
+ xaxis: IAxesDataAxis;
+ yaxis: IAxesDataAxis;
+}
+
function axesData(): IAxesData {
- const axisTitleFontSize = 10;
+ const axisTickFontSize = 10;
return {
xaxis: {
- tickangle: 0,
automargin: true,
+ tickangle: 0,
+ tickfont: {
+ size: axisTickFontSize
+ },
title: {
- font: {
- size: axisTitleFontSize
- },
- text: props.data.xAxisTitle,
- standoff: 8
+ standoff: 8,
+ text: props.data.xAxisTitle
}
},
yaxis: {
- tickangle: 0,
automargin: true,
+ tickangle: 0,
+ tickfont: {
+ size: axisTickFontSize
+ },
title: {
- font: {
- size: axisTitleFontSize
- },
- text: props.data.yAxisTitle,
- standoff: 8
+ standoff: 8,
+ text: props.data.yAxisTitle
}
}
};
diff --git a/src/renderer/src/components/widgets/InputWidget.vue b/src/renderer/src/components/widgets/InputWidget.vue
index 56625b84..92caabcb 100644
--- a/src/renderer/src/components/widgets/InputWidget.vue
+++ b/src/renderer/src/components/widgets/InputWidget.vue
@@ -19,7 +19,7 @@
@update:model-value="inputTextValueUpdated"
/>
@@ -45,6 +45,17 @@ let oldValue = value.value;
const discreteValue = vue.ref(
props.possibleValues?.find((possibleValue) => possibleValue.value === value.value)
);
+const compStepValue = vue.computed(() => {
+ if (props.stepValue !== undefined) {
+ return props.stepValue;
+ }
+
+ if (props.maximumValue !== undefined && props.minimumValue !== undefined) {
+ return 0.01 * (props.maximumValue - props.minimumValue);
+ }
+
+ return 1;
+});
vue.watch(
() => value.value,