Skip to content
Open
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
39 changes: 39 additions & 0 deletions frontend/src/renderer/components/plot/Heatmap2D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const Heatmap2D = ({
const [y, setY] = useState<number[]>([]);
const [z, setZ] = useState<(number | string)[][]>([]);
const plotRef = useRef<Plot | null>(null);
const [shouldForceRatio, setShouldForceRatio] = useState<boolean>(false);
const [layoutPlot, setLayoutPlot] = useState<Partial<Layout>>({
autosize: true,
scene: {
Expand All @@ -69,13 +70,17 @@ export const Heatmap2D = ({
exponentformat: 'power',
showexponent: 'all',
separatethousands: true,
scaleanchor: null,
scaleratio: null,
zeroline: false,
showgrid: itemDataGrid.displayGrid,
},
yaxis: {
exponentformat: 'power',
showexponent: 'all',
separatethousands: true,
zeroline: false,
showgrid: itemDataGrid.displayGrid,
},
modebar: {
orientation: 'v',
Expand All @@ -89,6 +94,40 @@ export const Heatmap2D = ({
const [title, setTitle] = useState(itemDataGrid.title);
const layoutPlotWidth = showSliders ? width * 0.8 : width;

/**
* Rule to determine if we have to force ratio
*/
useEffect(() => {
const getShouldForceRatio = () => {
let shoudForceRatioSwitchRule = false;
if (itemDataGrid.xyRatioRule === 'Force') {
shoudForceRatioSwitchRule = true;
} else if (itemDataGrid.xyRatioRule === 'Auto') {
const firstCoordinateUnit = itemDataGrid.coordinates.find(
(c) => c.axeIndex === 0,
)?.unit;
const secondCoordinateUnit = itemDataGrid.coordinates.find(
(c) => c.axeIndex === 1,
)?.unit;
shoudForceRatioSwitchRule =
!!firstCoordinateUnit && firstCoordinateUnit === secondCoordinateUnit;
}
setShouldForceRatio(shoudForceRatioSwitchRule);
};

getShouldForceRatio();
}, [itemDataGrid.xyRatioRule, itemDataGrid.coordinates]);

/**
* Update layout to force ratio or not
*/
Comment thread
mfiaudrin-epsyl marked this conversation as resolved.
useEffect(() => {
const updatedLayoutPlot = structuredClone(layoutPlot);
updatedLayoutPlot.xaxis.scaleanchor = shouldForceRatio ? 'y' : null;
updatedLayoutPlot.xaxis.scaleratio = shouldForceRatio ? 1 : null;
setLayoutPlot(updatedLayoutPlot);
}, [shouldForceRatio]);

/**
* Update the editable title when layout title change
*/
Expand Down
40 changes: 40 additions & 0 deletions frontend/src/renderer/components/plot/SimplePlotly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ export const SimplePlotly = ({
const coordsUsedInAxes: 1 | 2 = 1;
const { active, updatedConfiguration } = useIbexStore();
const SELECT_AXIS_HEIGHT = 40; // Height of the select axis component
const [shouldForceRatio, setShouldForceRatio] = useState<boolean>(false);
const [layoutPlot, setLayoutPlot] = useState<Partial<Layout>>({
xaxis: {
scaleanchor: null,
scaleratio: null,
title: {
font: {
family: 'Courier New, monospace',
Expand All @@ -69,6 +72,7 @@ export const SimplePlotly = ({
exponentformat: 'power',
showexponent: 'all',
separatethousands: true,
showgrid: itemDataGrid.displayGrid,
},
yaxis: {
title: {
Expand All @@ -85,12 +89,14 @@ export const SimplePlotly = ({
exponentformat: 'power',
showexponent: 'all',
separatethousands: true,
showgrid: itemDataGrid.displayGrid,
},
yaxis2: {
type: (itemDataGrid?.y2AxisData?.type as AxisType) || 'linear',
exponentformat: 'power',
showexponent: 'all',
separatethousands: true,
showgrid: itemDataGrid.displayGrid,
},
modebar: {
orientation: 'v',
Expand All @@ -117,6 +123,40 @@ export const SimplePlotly = ({
: width;
const customContainerRef = useRef<HTMLDivElement>(null);

/**
* Rule to determine if we have to force ratio
*/
useEffect(() => {
const getShouldForceRatio = () => {
let shoudForceRatioSwitchRule = false;
if (itemDataGrid.xyRatioRule === 'Force') {
shoudForceRatioSwitchRule = true;
} else if (itemDataGrid.xyRatioRule === 'Auto') {
const coordinateUnit = itemDataGrid.coordinates.find(
(c) => c.axeIndex === 0,
)?.unit;
const allPlotsHaveSameUnit = itemDataGrid.plot.every(
(plot) => plot.unit === itemDataGrid.plot[0]?.unit,
);
shoudForceRatioSwitchRule =
allPlotsHaveSameUnit && coordinateUnit === itemDataGrid.plot[0]?.unit;
}
setShouldForceRatio(shoudForceRatioSwitchRule);
};

getShouldForceRatio();
}, [itemDataGrid.xyRatioRule, itemDataGrid.coordinates, itemDataGrid.plot]);

/**
* Update layout to force ratio or not
*/
Comment thread
mfiaudrin-epsyl marked this conversation as resolved.
useEffect(() => {
const updatedLayoutPlot = structuredClone(layoutPlot);
updatedLayoutPlot.xaxis.scaleanchor = shouldForceRatio ? 'y' : null;
updatedLayoutPlot.xaxis.scaleratio = shouldForceRatio ? 1 : null;
setLayoutPlot(updatedLayoutPlot);
}, [shouldForceRatio]);

useEffect(() => {
// Check data entries to update axes titles when needed
const newDataEntries = [
Expand Down
1 change: 1 addition & 0 deletions frontend/src/renderer/layout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export function MainLayout() {
isTitleOverwritten: dataGrid.isTitleOverwritten,
displayErrorBand: dataGrid.displayErrorBand,
displayGrid: dataGrid.displayGrid,
xyRatioRule: dataGrid.xyRatioRule,
synchronizedGrids: dataGrid.synchronizedGrids,
downsampled_method: dataGrid?.downsampled_method,
downsampled_size: dataGrid?.downsampled_size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ export const CustomizeGlobal = ({
})
}
/>

<Select
label="Rule of axis ratios"
description="Select the rule of axis ratios"
placeholder="Select the rule of axis ratios"
data={['Auto', 'None', 'Force']}
value={customizedDataGrid?.xyRatioRule || 'Auto'}
onChange={(value: 'Auto' | 'None' | 'Force') =>
value &&
setCustomizedDataGrid({
...customizedDataGrid,
xyRatioRule: value,
})
}
maw={200}
/>
</Stack>
);
};
1 change: 1 addition & 0 deletions frontend/src/renderer/types/plot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export interface BaseDataGridPlot {
isTitleOverwritten: boolean;
displayErrorBand: boolean;
displayGrid: boolean;
xyRatioRule: 'Auto' | 'None' | 'Force';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop-down menu with these 3 options does not feel like the most friendly UI.
A simple boolean would be preferred here in the customization its square ratio or not. Auto shall just correspond of the value of this boolean while plotting the data for the first time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As during our discussion this morning it was raised that these three modes were present because they apply also in 1D plots and when we switch back and forth between 2D and 1D, maybe we can simplify and only have this costumisation option for 2D plots?

That way this option has no effect on 1D plots, where fixed ratio between x and y ticks is less of an issue.
The initial value of this boolean is decided with the first plot (if units are the same then it toggles fixed ratio for 2D) and latter impact further 2D plots in the same figure until the user customize the plot. On the other hand, if a first 2D plot has different units (like [s] vs [m]) then fixed ratio won't be forced in the figure, and could later be custonized by user.

If this (default value of the boolean depending on units of the first 2D plot in the figure) we can also decide to simplify and set a static default value (e.g. fixed ratio, so spatial planes will look nicer) and let the user unselect the option if she/he wants a plot that covers the entire figure.

For further reference and additional context, please see how this is handled in h5view with this small video:

myhdf5-ratio-2026-06-12_11.36.57.mp4

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your the proposed solution. I agree that if we apply the square ratio only for 2D plots, it will simplify the use of a boolean instead.

We just need to improve the solution to be compatible with the feature allowing to change of axis. In this case, units of x & y axis can change. So I am wondering what we should do.

I see 2 possibilities:

  1. When adding a new dataGrid, we initialise the square ratio boolean (true or false depending x & y units). No matter if we change of axis later, we will keep the square ratio as it was at the initialisation
  2. Or we update the square ratio boolean each time we update axis. So, in case the user has forced to keep ratio to true for instance, it will overwrite the keep ratio value by applying the unit rule each time we change of axis

Which one do you think will be the most appropriate for the users ?

From my point of view, I think the second option will be better because by changing axis, we always ensure the user have the expected ratio for visualisation. And then, it's up to him to update the ratio.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed this question: I would favor option 1, seems like a simpler implementation (maybe I'm wrong) and it avoids the case where the user is setting the ratio, and have to set it back each time he explore other axis and come back.

synchronizedGrids: synchronizedList;
downsampled_method?: string;
downsampled_size?: number;
Expand Down
1 change: 1 addition & 0 deletions frontend/src/renderer/utils/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const generateNewGrid = (
isTitleOverwritten: false,
displayErrorBand: true,
displayGrid: true,
xyRatioRule: 'Auto',
synchronizedGrids: { color: '', list: [] },
i: generateUuid(),
isEditing: true,
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/renderer/utils/plot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const plotData = (
downsampled_method: downsampled_method,
interpolated_method: interpolated_method,
plot: [...currentPlot, trace],
xyRatioRule: dataPlot?.xyRatioRule || 'Auto',
};
};

Expand Down Expand Up @@ -1381,6 +1382,7 @@ export async function plotNodeUriLoaded(

const dataGridUpdated = {
...dataGrid,
xyRatioRule: dataGrid?.xyRatioRule || 'Auto',
xAxisData: updatedXAxisData,
plot: updatedPlot,
} as DataGridPlot;
Expand Down
Loading