Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
117 changes: 113 additions & 4 deletions src/components/WorkspaceDetailView.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed } from 'vue';
import { computed, ref } from 'vue';
import NormalizedBarChart from 'src/components/charts/NormalizedBarChart.vue';
import PieChart from 'src/components/charts/PieChart.vue';
import StackedChart from 'src/components/charts/StackedChart.vue';
Expand All @@ -11,6 +11,7 @@ import ChannelListItem from 'src/components/ChannelListItem.vue';
import NormFactorListItem from 'src/components/NormFactorListItem.vue';
import { useWorkspaceStore } from 'src/stores/workspace';
import CorrelationChart from 'src/components/charts/CorrelationChart.vue';
import SystematicChart from 'src/components/charts/SystematicChart.vue';

const props = defineProps<{
id: number;
Expand All @@ -25,6 +26,32 @@ const height = computed(() => {
Math.max(2 * 100, 25 * workspace_store.number_of_processes) + 150
);
});

const modifier_filter = ref('');
const current = ref(1);
const syst_plots_per_page = 5;

const modifiers_to_display = computed(() => {
// get type of modifier in any region and for any sample
// (it does not matter which because in this step we only
// want to filter out lumi, staterror, normfactor)
const types =
workspace_store.channels[0].modifier_types[
workspace_store.channels[0].samples[0].name
];
const systematic_variations = workspace_store.modifier_names.filter(
(item) =>
!(
types[item] === 'lumi' ||
types[item] === 'staterror' ||
types[item] === 'normfactor'
)
);
// afterwards, filter by name
return systematic_variations.filter((item) =>
item.includes(modifier_filter.value)
);
});
</script>

<template>
Expand Down Expand Up @@ -110,12 +137,13 @@ const height = computed(() => {
</q-expansion-item>
<q-separator inset></q-separator>
<q-expansion-item switch-toggle-side label="Data-MC Comparisons">
<HorizontalScrollArea height="550">
<HorizontalScrollArea height="650">
<StackedChart
v-for="(channel, channel_index) in workspace_store.channels"
:key="channel.name"
:id="id"
:channel_index="channel_index"
:postfit="false"
/>
</HorizontalScrollArea>
</q-expansion-item>
Expand All @@ -127,15 +155,92 @@ const height = computed(() => {
/>
</q-expansion-item>
<q-separator inset></q-separator>
<q-expansion-item
switch-toggle-side
label="Systematic Uncertainty Chart"
>
<div class="row">
<q-input
filled
bottom-slots
label="Filter by name"
type="text"
v-model="modifier_filter"
hide-bottom-space
style="margin-right: 1em"
></q-input>
<q-pagination
v-model="current"
:max="
Math.floor(modifiers_to_display.length / syst_plots_per_page) +
1
"
input
size="xl"
/>
</div>
<div
class="column"
v-for="modifier_name in modifiers_to_display.slice(
(current - 1) * syst_plots_per_page,
current * syst_plots_per_page
)"
:key="modifier_name"
>
<h3 style="text-align: center">{{ modifier_name }}</h3>
<HorizontalScrollArea height="550">
<div
class="row"
v-for="(channel, channel_index) in workspace_store.channels"
:key="channel.name"
>
<SystematicChart
:id="id"
:channel_index="channel_index"
:modifier_name="modifier_name"
/>
</div>
</HorizontalScrollArea>
</div>
<div class="row">
<q-input
filled
bottom-slots
label="Filter by name"
type="text"
v-model="modifier_filter"
hide-bottom-space
style="margin-right: 1em"
></q-input>
<q-pagination
v-model="current"
:max="Math.floor(modifiers_to_display.length / 10) + 1"
input
size="xl"
/>
</div>
</q-expansion-item>
<q-separator inset></q-separator>
<q-expansion-item switch-toggle-side label="Fit Results">
<q-btn
@click="workspace_store.get_fit_results()"
:loading="workspace_store.fitting"
:disable="workspace_store.fitting || workspace_store.fitted"
>Fit Workspace</q-btn
:disable="workspace_store.fitting"
>{{
workspace_store.fitted ? 'Reset to fit results' : 'Fit Workspace'
}}</q-btn
>
<div v-if="workspace_store.fitted" class="row justify-around">
<PullChart :id="id" />
<div>
<StackedChart
v-for="(channel, channel_index) in workspace_store.channels"
:key="channel.name"
:id="id"
:channel_index="channel_index"
:postfit="true"
/>
</div>
<CorrelationChart :id="id" />
</div>
</q-expansion-item>
Expand All @@ -152,4 +257,8 @@ const height = computed(() => {
h2 {
font-size: 2.5em;
}

h3 {
font-size: 1.8em;
}
</style>
6 changes: 3 additions & 3 deletions src/components/charts/NormalizedBarChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ const offset =

// create strings for path of axes
const y_ticks = [
...Array(workspace_store.channels.length)
.fill(0)
.map((_, i) => (i + 0.5) * bar_height + (i + 1) * padding),
...workspace_store.channels.map(
(_, i) => (i + 0.5) * bar_height + (i + 1) * padding
),
];
const yaxis_path = axis_path(0, 0, offset, y_ticks, false, true);

Expand Down
2 changes: 1 addition & 1 deletion src/components/charts/PieChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const height = computed(() => {
:style="
'width: ' +
3 * radius +
'px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; display: inline-block;'
'px; overflow: hidden; white-space: nowrap; text-align: center; text-overflow: ellipsis; display: inline-block;'
"
:title="channel.title"
>
Expand Down
43 changes: 5 additions & 38 deletions src/components/charts/PullChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const workspace_store = useWorkspaceStore(props.id)();
const height_per_entry = 25;

const height = computed(() => {
return workspace_store.fitresults.labels.length * height_per_entry + 100;
return workspace_store.nps.labels.length * height_per_entry + 100;
});

const sigma_width = 125;
Expand All @@ -38,7 +38,7 @@ const x_ticks = [
const xaxis_path = axis_path(
ylabel_offset,
height.value - 100,
4 * sigma_width + ylabel_offset,
four_sigma_width + ylabel_offset,
x_ticks,
true,
true
Expand Down Expand Up @@ -75,50 +75,17 @@ const xaxis_path = axis_path(
stroke-dasharray="8"
/>
<template
v-for="(np, np_index) in workspace_store.fitresults.labels"
v-for="(np, np_index) in workspace_store.nps.labels"
:key="np"
>
<PullChartEntry
:id="id"
:y="np_index * height_per_entry + height_per_entry / 2"
:x_offset="two_sigma_width + ylabel_offset"
:sigma_width="sigma_width"
:np_name="np"
:bestfit="workspace_store.fitresults.bestfit[np_index]"
:uncertainty="workspace_store.fitresults.uncertainty[np_index]"
:np_index="np_index"
:isnothighlighted="!ishighlighted(np_index)"
/>
<!-- transparent rectangle on top of each NP to highlight on mouseover -->
<rect
:x="-ylabel_width"
:y="np_index * height_per_entry"
:height="height_per_entry"
:width="width"
fill-opacity="0"
stroke-opacity="0"
stroke="black"
@mouseover="highlight(np_index)"
@mouseleave="unhighlight"
:class="{
ishighlighted: np_index === highlighted_index,
}"
>
<title>
{{
'NP' +
np +
': ' +
round_to_n_digits(
workspace_store.fitresults.bestfit[np_index],
3
) +
' &#177; ' +
round_to_n_digits(
workspace_store.fitresults.uncertainty[np_index] * 1000,
3
)
}}
</title>
</rect>
</template>
<path fill="none" stroke="black" :d="xaxis_path"></path>
<text
Expand Down
84 changes: 77 additions & 7 deletions src/components/charts/PullChartEntry.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,56 @@
<script setup lang="ts">
defineProps<{
np_name: string;
import { useWorkspaceStore } from 'src/stores/workspace';
import { computed, ref, watch } from 'vue';

const props = defineProps<{
id: number;
np_index: number;
y: number;
x_offset: number;
bestfit: number;
sigma_width: number;
uncertainty: number;
isnothighlighted: boolean;
}>();

const workspace_store = useWorkspaceStore(props.id)();

const bestfit = computed(() => {
return workspace_store.nps.bestfit[props.np_index];
});
const uncertainty = computed(() => {
return workspace_store.nps.uncertainty[props.np_index];
});

// need to watch the bestfit props in case we want to reset the values
watch(bestfit, (newValue) => {
x_position.value = props.x_offset + newValue * props.sigma_width;
});

const np_name = workspace_store.nps.labels[props.np_index];
const is_dragging = ref(false);
const x_position = ref(props.x_offset + bestfit.value * props.sigma_width);
const start_x = ref(0);

function startDrag(event: MouseEvent): void {
is_dragging.value = true;
start_x.value = event.clientX;
}

function drag(event: MouseEvent): void {
if (!is_dragging.value) return;
const delta = event.clientX - start_x.value;
const new_position = x_position.value + delta;
x_position.value = Math.max(
props.x_offset - 2 * props.sigma_width,
Math.min(props.x_offset + 2 * props.sigma_width, new_position)
);
workspace_store.nps.bestfit[props.np_index] =
(x_position.value - props.x_offset) / props.sigma_width;
start_x.value = event.clientX;
}

function endDrag(): void {
is_dragging.value = false;
}
</script>

<template>
Expand All @@ -21,20 +64,43 @@ defineProps<{
{{ np_name }}
</text>
<circle
:cx="x_offset + bestfit * sigma_width"
:cx="x_position"
:cy="y"
fill="black"
r="5"
:class="{ isnothighlighted: isnothighlighted }"
/>
<line
:x1="x_offset + Math.max(bestfit - uncertainty, -2) * sigma_width"
:x2="x_offset + Math.min(bestfit + uncertainty, 2) * sigma_width"
:x1="
Math.max(
x_position - uncertainty * sigma_width,
x_offset - 2 * sigma_width
)
"
:x2="
Math.min(
x_position + uncertainty * sigma_width,
x_offset + 2 * sigma_width
)
"
:y1="y"
:y2="y"
stroke="black"
:class="{ isnothighlighted: isnothighlighted }"
/>
<rect
:x="x_offset - 2 * sigma_width"
:y="y - 12.5"
:height="25"
:width="4 * sigma_width"
fill-opacity="0"
stroke-opacity="0"
stroke="black"
@mousedown="startDrag"
@mousemove="drag"
@mouseup="endDrag"
class="nprect"
/>
</template>

<style scoped>
Expand All @@ -52,4 +118,8 @@ text.isnothighlighted {
fill: grey;
transition: fill 0.5s ease;
}

rect.nprect:hover {
cursor: ew-resize;
}
</style>
Loading