Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task: funman output should be slightly more inline with designs #2316

Merged
merged 23 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c875f8f
temp
Tom-Szendrey Nov 22, 2023
b02ba85
Merge branch 'main' of https://github.com/DARPA-ASKEM/TERArium into T…
Tom-Szendrey Nov 23, 2023
9f24bdc
still need to add table. Need to chat abt func 1st
Tom-Szendrey Nov 26, 2023
b66151d
still a bit of prettying to do
Tom-Szendrey Nov 27, 2023
727c38a
Merge branch 'main' of https://github.com/DARPA-ASKEM/TERArium into T…
Tom-Szendrey Nov 27, 2023
1f7b2ce
do not use primevue chart
Tom-Szendrey Nov 27, 2023
a0fe36b
overflow to work
Tom-Szendrey Nov 27, 2023
1a521aa
removing unrequired fields
Tom-Szendrey Nov 27, 2023
03dd55c
svg changes to traj renderer
Tom-Szendrey Nov 27, 2023
b6b81c0
adding x axis
Tom-Szendrey Nov 27, 2023
74dbf34
removing some console.logs
Tom-Szendrey Nov 27, 2023
f23c366
use correct x and y scale
Tom-Szendrey Nov 27, 2023
641433e
removing a log
Tom-Szendrey Nov 27, 2023
e5ee201
scale changes depending on state selected
Tom-Szendrey Nov 27, 2023
cace879
minor change to axis
Tom-Szendrey Nov 27, 2023
8a81031
correction with left margin
Tom-Szendrey Nov 27, 2023
e0679cc
adding top margin
Tom-Szendrey Nov 27, 2023
c064798
oops i hide the run button
Tom-Szendrey Nov 28, 2023
9ac7a15
no more workflow event bus
Tom-Szendrey Nov 28, 2023
349126f
unused css
Tom-Szendrey Nov 28, 2023
ea8bfa1
changing order of params to include options last
Tom-Szendrey Nov 28, 2023
936f3da
correcting order of params for render traj
Tom-Szendrey Nov 28, 2023
ae6a7e1
Merge branch 'main' into TS/2233-funman-output
mwdchang Nov 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
<template>
<div class="section-row">
<label>Select Parameter One</label>
<Dropdown v-model="selectedParamOne" :options="parameterOptions"> </Dropdown>
<label>Trajectory State</label>
<Dropdown v-model="selectedTrajState" :options="modelStates"> </Dropdown>
</div>
<div class="section-row">
<label>Select Parameter Two</label>
<Dropdown v-model="selectedParamTwo" :options="parameterOptions"> </Dropdown>
</div>
<div class="section-row">
<label>Timestep</label>
<Dropdown v-model="timestep" :options="timestepOptions"> </Dropdown>
</div>
<div class="container">
<div ref="boxRef"></div>
<div ref="trajRef"></div>
<div ref="trajRef"></div>

<h4>Configuration parameters <i class="pi pi-info-circle" /></h4>
<p class="secondary-text">
Adjust parameter ranges to only include values in the green region or less.
</p>

<!-- TODO: add boxes modal per row https://github.com/DARPA-ASKEM/terarium/issues/1924 -->
<div class="variables-table">
<div class="variables-header">
<header
v-for="(title, index) in ['Parameter', 'Lower bound', 'Upper bound', '', '']"
:key="index"
>
{{ title }}
</header>
</div>
<div v-for="(column, index) in lastTrueBox?.bounds" :key="index">
<div class="variables-row" v-if="parameterOptions.includes(index.toString())">
<div>{{ index.toString() }}</div>
<div>{{ column?.lb }}</div>
<div>{{ column?.ub }}</div>
</div>
</div>
</div>
</template>

Expand All @@ -22,8 +35,7 @@ import { ref, onMounted, watch } from 'vue';
import {
getQueries,
processFunman,
renderFumanTrajectories,
renderFunmanBoundaryChart
renderFumanTrajectories
} from '@/services/models/funman-service';
import Dropdown from 'primevue/dropdown';

Expand All @@ -32,46 +44,49 @@ const props = defineProps<{
}>();

const parameterOptions = ref<string[]>([]);
const selectedParamOne = ref();
const selectedParamTwo = ref();
const selectedParam = ref();
const selectedTrajState = ref();
const modelStates = ref<string[]>();
const timestepOptions = ref();
const timestep = ref();
const boxRef = ref();
const trajRef = ref();
const boxId = 'box2';
const lastTrueBox = ref();

const initalizeParameters = async () => {
const funModel = await getQueries(props.funModelId);
parameterOptions.value = [];
funModel.model.petrinet.semantics.ode.parameters.map((ele) =>
parameterOptions.value.push(ele.id)
);
selectedParamOne.value = parameterOptions.value[0];
selectedParamTwo.value = parameterOptions.value[0];
selectedParam.value = parameterOptions.value[0];
timestepOptions.value = funModel.request.structure_parameters[0].schedules[0].timepoints;
timestep.value = timestepOptions.value[1];
const tempList: string[] = [];
funModel.model.petrinet.model.states.forEach((element) => {
tempList.push(element.id);
});
modelStates.value = tempList;
selectedTrajState.value = modelStates.value[0];

lastTrueBox.value = funModel.parameter_space.true_boxes.at(-1);
};

const renderGraph = async () => {
const funModel = await getQueries(props.funModelId);
const width = 800;
const height = 250;
const funModel = await getQueries(props.funModelId);
const processedData = processFunman(funModel);
renderFunmanBoundaryChart(
boxRef.value,
renderFumanTrajectories(
trajRef.value as HTMLElement,
processedData,
selectedParamOne.value,
selectedParamTwo.value,
timestep.value,
boxId,
selectedTrajState.value,
{
width,
height
}
);
renderFumanTrajectories(trajRef.value as HTMLElement, processedData, boxId, {
width,
height
});
};

onMounted(() => {
Expand All @@ -88,26 +103,54 @@ watch(

watch(
// Whenever user changes options rerender.
() => [selectedParamOne.value, selectedParamTwo.value, timestep.value],
() => [selectedParam.value, timestep.value, selectedTrajState.value],
async () => {
renderGraph();
}
);
</script>

<style scoped>
.container {
display: flex;
flex-direction: column;
gap: 1rem;
}

.section-row {
display: flex;
/* flex-direction: column; */
padding: 0.5rem 0rem;
align-items: center;
gap: 0.8125rem;
align-self: stretch;
}

.secondary-text {
color: var(--Text-Secondary, #667085);
/* Body Small/Regular */
font-size: 0.875rem;
font-style: normal;
font-weight: 400;
line-height: 1.3125rem; /* 150% */
letter-spacing: 0.01563rem;
}

.variables-table {
display: grid;
grid-template-columns: 1fr;
}

.variables-table div {
padding: 0.25rem;
}

.variables-row {
display: grid;
grid-template-columns: repeat(6, 1fr) 0.5fr;
grid-template-rows: 1fr 1fr;
border-top: 1px solid var(--surface-border);
}

.variables-header {
display: grid;
grid-template-columns: repeat(6, 1fr) 0.5fr;
}

header {
padding-right: 1rem;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import API from '@/api/api';
import { FunmanPostQueriesRequest } from '@/types/Types';
import * as d3 from 'd3';

interface FunmanProcessedData {
export interface FunmanProcessedData {
boxes: any[];
points: any[];
states: string[];
Expand Down Expand Up @@ -164,37 +164,89 @@ export const renderFumanTrajectories = (
element: HTMLElement,
processedData: FunmanProcessedData,
boxId: string,
state: string,
options: RenderOptions
) => {
Tom-Szendrey marked this conversation as resolved.
Show resolved Hide resolved
const width = options.width;
const height = options.height;
const topMargin = 10;
const rightMargin = 30;
const leftMargin = 30;
const bottomMargin = 30;
const { trajs, states } = processedData;

const elemSelection = d3.select(element);
d3.select(element).selectAll('*').remove();
const svg = elemSelection.append('svg').attr('width', width).attr('height', height);
const group = svg.append('g');

const points = trajs.filter((d: any) => d.boxId === boxId);

// Find max/min across timesteps
const xDomain = d3.extent(points.map((d) => d.timestep)) as [number, number];

// Find max/min across all state values
const yDomain = d3.extent(points.map((d) => states.map((s) => d[s])).flat()) as [number, number];
const yDomain = d3.extent(
points.map((d) => states.filter((s) => s === state).map((s) => d[s])).flat()
) as [number, number];

const xScale = d3
.scaleLinear()
.domain(xDomain)
.range([leftMargin, width - rightMargin]);

const yScale = d3
.scaleLinear()
.domain(yDomain)
.range([height - bottomMargin, topMargin]);

// Add the x-axis.
svg
.append('g')
.attr('transform', `translate(0,${height - bottomMargin})`)
.call(
d3
.axisBottom(xScale)
.ticks(width / 60)
.tickSizeOuter(0)
);

// Add the y-axis
svg
.append('g')
.attr('transform', `translate(${leftMargin},0)`)
.call(
d3
.axisLeft(yScale)
.ticks(height / 60)
.tickSizeOuter(0)
);

// Add label for x-axis
svg
.append('text')
.attr('class', 'x label')
.attr('text-anchor', 'end')
.attr('x', width / 2)
.attr('y', height - 2)
.text('Timestep');

const xScale = d3.scaleLinear().domain(xDomain).range([0, width]);
const yScale = d3.scaleLinear().domain(yDomain).range([height, 0]);
const pathFn = d3
.line<{ x: number; y: number }>()
.x((d) => xScale(d.x))
.y((d) => yScale(d.y))
.curve(d3.curveBasis);

states.forEach((s: string) => {
const path = points.map((p: any) => ({ x: p.timestep, y: p[s] }));
group.append('path').attr('d', pathFn(path)).style('stroke', '#888').style('fill', 'none');
});
states
.filter((s) => s === state)
.forEach((s: string) => {
const path = points.map((p: any) => ({ x: p.timestep, y: p[s] }));
svg
.append('g')
.append('path')
.attr('d', pathFn(path))
.style('stroke', '#888')
.style('fill', 'none');
});
};

const getBoxesDomain = (boxes: FunmanBox[]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ import Slider from 'primevue/slider';
import { FunmanPostQueriesRequest, Model, ModelConfiguration } from '@/types/Types';
import { getQueries, makeQueries } from '@/services/models/funman-service';
import { WorkflowNode } from '@/types/workflow';
import { workflowEventBus } from '@/services/workflow';
import teraConstraintGroupForm from '@/components/funman/tera-constraint-group-form.vue';
import teraFunmanOutput from '@/components/funman/tera-funman-output.vue';
import { getModelConfigurationById } from '@/services/model-configurations';
Expand All @@ -146,6 +145,8 @@ const props = defineProps<{
node: WorkflowNode<FunmanOperationState>;
}>();

const emit = defineEmits(['append-output-port', 'update-state']);

enum FunmanTabs {
wizard,
notebook
Expand Down Expand Up @@ -250,14 +251,11 @@ const getStatus = async (runId) => {

const updateOutputPorts = async (runId) => {
const portLabel = props.node.inputs[0].label;
workflowEventBus.emit('append-output-port', {
node: props.node,
port: {
id: uuidv4(),
label: `${portLabel} Result`,
type: FunmanOperation.outputs[0].type,
value: runId
}
emit('append-output-port', {
id: uuidv4(),
label: `${portLabel} Result`,
type: FunmanOperation.outputs[0].type,
value: runId
});
};

Expand All @@ -274,11 +272,7 @@ const addConstraintForm = () => {
}
state.constraintGroups.push(newGroup);

workflowEventBus.emitNodeStateChange({
workflowId: props.node.workflowId,
nodeId: props.node.id,
state
});
emit('update-state', state);
};

const deleteConstraintGroupForm = (data) => {
Expand All @@ -288,11 +282,7 @@ const deleteConstraintGroupForm = (data) => {
}
state.constraintGroups.splice(data.index, 1);

workflowEventBus.emitNodeStateChange({
workflowId: props.node.workflowId,
nodeId: props.node.id,
state
});
emit('update-state', state);
};

const updateConstraintGroupForm = (data) => {
Expand All @@ -302,11 +292,7 @@ const updateConstraintGroupForm = (data) => {
}
state.constraintGroups[data.index] = data.updatedConfig;

workflowEventBus.emitNodeStateChange({
workflowId: props.node.workflowId,
nodeId: props.node.id,
state
});
emit('update-state', state);
};

// Used to set requestStepList.
Expand Down Expand Up @@ -383,6 +369,7 @@ watch(
<style scoped>
.content {
display: flex;
height: 80%;
overflow: auto;
padding: 1rem 1.5rem 1rem 0rem;
align-items: flex-start;
Expand All @@ -402,7 +389,7 @@ watch(
flex-direction: column;
align-items: flex-start;
flex: 1 0 0;
align-self: stretch;
align-self: auto;
}
.container h1 {
color: var(--text-color-primary);
Expand Down