Skip to content

Commit

Permalink
Merge pull request #176 from mrc-ide/mrc-4522
Browse files Browse the repository at this point in the history
mrc-4522 Allow user-specified parameter values in Sensitivity
  • Loading branch information
EmmaLRussell authored Aug 30, 2023
2 parents c1f0103 + 7d45e46 commit fdd2ab9
Show file tree
Hide file tree
Showing 14 changed files with 371 additions and 95 deletions.
111 changes: 72 additions & 39 deletions app/static/src/app/components/options/EditParamSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,6 @@
</select>
</div>
</div>
<div class="row mt-2" id="edit-scale-type">
<div class="col-6">
<label class="col-form-label">Scale type</label>
</div>
<div class="col-6">
<select class="form-select" v-model="settingsInternal.scaleType">
<option v-for="scale in scaleValues" :key="scale">{{scale}}</option>
</select>
</div>
<div class="col-6">
</div>
</div>
<div class="row mt-2" id="edit-variation-type">
<div class="col-6">
<label class="col-form-label">Variation type</label>
Expand All @@ -40,6 +28,18 @@
</select>
</div>
</div>
<div v-if="settingsInternal.variationType !== 'Custom'" class="row mt-2" id="edit-scale-type">
<div class="col-6">
<label class="col-form-label">Scale type</label>
</div>
<div class="col-6">
<select class="form-select" v-model="settingsInternal.scaleType">
<option v-for="scale in scaleValues" :key="scale">{{scale}}</option>
</select>
</div>
<div class="col-6">
</div>
</div>
<div v-if="settingsInternal.variationType === 'Percentage'" class="row mt-2" id="edit-percent">
<div class="col-6">
<label class="col-form-label">Variation (%)</label>
Expand All @@ -49,35 +49,45 @@
@update="(n) => settingsInternal.variationPercentage = n"></numeric-input>
</div>
</div>
<template v-else>
<div class="row mt-2" id="edit-from">
<div class="col-6">
<label class="col-form-label">From</label>
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeFrom"
@update="(n) => settingsInternal.rangeFrom = n"></numeric-input>
</div>
<div v-if="settingsInternal.variationType === 'Range'" class="row mt-2" id="edit-from">
<div class="col-6">
<label class="col-form-label">From</label>
</div>
<div class="row mt-2 text-muted" id="param-central">
<div class="col-6">
Central value
</div>
<div class="col-6">
{{ centralValue }}
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeFrom"
@update="(n) => settingsInternal.rangeFrom = n"></numeric-input>
</div>
<div class="row mt-2" id="edit-to">
</div>
<div v-if="['Range', 'Custom'].includes(settingsInternal.variationType)"
class="row mt-2 text-muted" id="param-central">
<div class="col-6">
Central value
</div>
<div class="col-6">
{{ centralValue }}
</div>
</div>
<div v-if="settingsInternal.variationType === 'Range'" class="row mt-2" id="edit-to">
<div class="col-6">
<label class="col-form-label">To</label>
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeTo"
@update="(n) => settingsInternal.rangeTo = n"></numeric-input>
</div>
</div>
<template v-if="settingsInternal.variationType === 'Custom'">
<div id="edit-values" class="row mt-2">
<div class="col-6">
<label class="col-form-label">To</label>
<label class="col-form-label">Values</label>
</div>
<div class="col-6">
<numeric-input :value="settingsInternal.rangeTo"
@update="(n) => settingsInternal.rangeTo = n"></numeric-input>
<tag-input :tags="settingsInternal.customValues" :numeric-only="true" @update="updateUserValues">
</tag-input>
</div>
</div>
</template>
<div class="row mt-2" id="edit-runs">
<div v-if="settingsInternal.variationType !== 'Custom'" id="edit-runs" class="row mt-2">
<div class="col-6">
<label class="col-form-label">Number of runs</label>
</div>
Expand All @@ -91,7 +101,8 @@
<error-info :error="batchParsError"></error-info>
</div>
</div>
<sensitivity-param-values :batch-pars="batchPars"></sensitivity-param-values>
<sensitivity-param-values v-if="settingsInternal.variationType !== 'Custom'" :batch-pars="batchPars">
</sensitivity-param-values>
</div>
<div class="modal-footer">
<button class="btn btn-primary"
Expand Down Expand Up @@ -123,6 +134,7 @@ import NumericInput from "./NumericInput.vue";
import SensitivityParamValues from "./SensitivityParamValues.vue";
import { generateBatchPars } from "../../utils";
import ErrorInfo from "../ErrorInfo.vue";
import TagInput from "./TagInput.vue";
export default defineComponent({
name: "EditParamSettings.vue",
Expand All @@ -135,7 +147,8 @@ export default defineComponent({
components: {
ErrorInfo,
NumericInput,
SensitivityParamValues
SensitivityParamValues,
TagInput
},
setup(props, { emit }) {
const store = useStore();
Expand All @@ -161,13 +174,32 @@ export default defineComponent({
const centralValue = computed(() => store.state.run.parameterValues[settingsInternal.parameterToVary!]);
const paramValues = computed(() => store.state.run.parameterValues);
const batchParsResult = computed(() => generateBatchPars(store.state, settingsInternal, paramValues.value));
const batchPars = computed(() => batchParsResult.value.batchPars);
const batchParsError = computed(() => batchParsResult.value.error);
const batchParsResult = computed(() => {
if (settingsInternal.variationType === SensitivityVariationType.Custom) {
return null;
}
return generateBatchPars(store.state, settingsInternal, paramValues.value);
});
const batchPars = computed(() => batchParsResult.value?.batchPars);
const batchParsError = computed(() => {
if (settingsInternal.variationType === SensitivityVariationType.Custom) {
// Minimum of two custom values
return settingsInternal.customValues.length < 2
? { error: "Invalid settings", detail: "Must include at least 2 traces in the batch" } : null;
}
return batchParsResult.value?.error;
});
const updateUserValues = (newValues: number[]) => {
// sort and remove duplicates
settingsInternal.customValues = newValues;
};
const close = () => { emit("close"); };
const updateSettings = () => {
store.commit(`sensitivity/${SensitivityMutation.SetParamSettings}`, { ...settingsInternal });
// sort custom values
const customValues = settingsInternal.customValues.sort((a, b) => a - b);
store.commit(`sensitivity/${SensitivityMutation.SetParamSettings}`,
{ ...settingsInternal, customValues });
close();
};
Expand All @@ -180,6 +212,7 @@ export default defineComponent({
centralValue,
batchPars,
batchParsError,
updateUserValues,
close,
updateSettings
};
Expand Down
15 changes: 11 additions & 4 deletions app/static/src/app/components/options/SensitivityOptions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
<button class="btn btn-primary mb-4 float-end" @click="toggleEdit(true)">Edit</button>
<ul>
<li><strong>Parameter:</strong> {{settings.parameterToVary}}</li>
<li><strong>Scale Type:</strong> {{ settings.scaleType }}</li>
<li><strong>Variation Type:</strong> {{ settings.variationType }}</li>
<li v-if="settings.variationType !== 'Custom'"><strong>Scale Type:</strong> {{ settings.scaleType }}</li>
<li v-if="settings.variationType === 'Percentage'">
<strong>Variation (%):</strong> {{ settings.variationPercentage }}
</li>
<template v-else>
<template v-if="settings.variationType === 'Range'">
<li><strong>From:</strong> {{ settings.rangeFrom }}</li>
<li><strong>To:</strong> {{ settings.rangeTo }}</li>
</template>
<li><strong>Number of runs:</strong> {{ settings.numberOfRuns}}</li>
<li v-if="settings.variationType === 'Custom'">
<strong>Values:</strong>
{{ settings.customValues.join(", ") }}
</li>
<li v-if="settings.variationType !== 'Custom'">
<strong>Number of runs:</strong> {{ settings.numberOfRuns}}
</li>
</ul>
<sensitivity-param-values :batch-pars="batchPars"></sensitivity-param-values>
<sensitivity-param-values v-if="settings.variationType !== 'Custom'" :batch-pars="batchPars">
</sensitivity-param-values>
</div>
<hr/>
<sensitivity-plot-options></sensitivity-plot-options>
Expand Down
43 changes: 33 additions & 10 deletions app/static/src/app/components/options/TagInput.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<template>
<vue-tags-input style="border-color: #d7dce1;"
v-model="currentTag"
:tags="computedTags"
:placeholder="'...'"
:validate="validate"
:add-tag-on-blur="true"
:add-tag-on-keys="[13, ',', 32, ':']"
@on-error="handleError"
@on-tags-changed="handleTagsChanged"/>
</template>
<script lang="ts">
import {
PropType, computed, defineComponent, watch
PropType, computed, defineComponent, watch, ref
} from "vue";
import VueTagsInput from "vue3-tags-input";
import { useStore } from "vuex";
Expand All @@ -20,11 +22,18 @@ export default defineComponent({
VueTagsInput
},
props: {
tags: Array as PropType<Tag[] | null>
tags: Array as PropType<Tag[] | null>,
numericOnly: {
type: Boolean,
required: false,
default: false
}
},
setup(props, { emit }) {
const store = useStore();
const currentTag = ref("");
const paramValues = computed(() => store.state.run.parameterValues);
watch(paramValues, () => {
Expand All @@ -39,7 +48,7 @@ export default defineComponent({
}
const cleanTags = props.tags.filter((tag) => {
if (typeof tag === "number") return true;
return paramValues.value[tag] !== undefined;
return !props.numericOnly && paramValues.value[tag] !== undefined;
});
return cleanTags.map((tag) => {
if (typeof tag === "number") return `${tag}`;
Expand All @@ -56,19 +65,26 @@ export default defineComponent({
return paramValues.value && tag in paramValues.value;
};
const handleError = () => {
// remove duplicate current tag
currentTag.value = "";
};
const handleTagsChanged = (tags: string[]) => {
const parsedTags = tags.map((tag) => {
if (isNumeric(tag)) {
return parseFloat(tag);
}
if (tag.includes(":")) {
const variableTag = tag.split(":");
const varId = variableTag[0];
if (isParameterName(varId)) {
return varId;
if (!props.numericOnly) {
if (tag.includes(":")) {
const variableTag = tag.split(":");
const varId = variableTag[0];
if (isParameterName(varId)) {
return varId;
}
} else if (isParameterName(tag)) {
return tag;
}
} else if (isParameterName(tag)) {
return tag;
}
return undefined;
});
Expand All @@ -90,7 +106,9 @@ export default defineComponent({
};
return {
currentTag,
computedTags,
handleError,
handleTagsChanged,
validate
};
Expand All @@ -105,4 +123,9 @@ export default defineComponent({
.v3ti-tag .v3ti-remove-tag {
text-decoration: none !important;
}
.v3ti-new-tag--error {
text-decoration: none !important;
color: #000 !important;
}
</style>
3 changes: 2 additions & 1 deletion app/static/src/app/store/sensitivity/sensitivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const defaultState: SensitivityState = {
variationPercentage: 10,
rangeFrom: 0,
rangeTo: 0,
numberOfRuns: 10
numberOfRuns: 10,
customValues: []
},
plotSettings: {
plotType: SensitivityPlotType.TraceOverTime,
Expand Down
6 changes: 4 additions & 2 deletions app/static/src/app/store/sensitivity/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export enum SensitivityScaleType {

export enum SensitivityVariationType {
Percentage = "Percentage",
Range = "Range"
Range = "Range",
Custom = "Custom"
}

export interface SensitivityParameterSettings {
Expand All @@ -18,7 +19,8 @@ export interface SensitivityParameterSettings {
variationPercentage: number,
rangeFrom: number,
rangeTo: number,
numberOfRuns: number
numberOfRuns: number,
customValues: number[]
}

export enum SensitivityPlotType {
Expand Down
Loading

0 comments on commit fdd2ab9

Please sign in to comment.