Skip to content

Commit 8247dc2

Browse files
authored
DM-11569: Plotly 3d bug fixes, merge pr #439
DM-11569 Plotly 3d bug fixes, support multiple heatmaps on the same XY scale
2 parents 465a5a2 + 0954762 commit 8247dc2

File tree

12 files changed

+130
-62
lines changed

12 files changed

+130
-62
lines changed

src/firefly/html/demo/ffapi-slate-test2.html

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,16 @@
7676
Add Some plotly Charts
7777
<ul>
7878
<li>
79-
<a href='javascript:loadNewCharts(0,0,2,2)'>Show new Plotly </a> <span class='smallCoords'>at row: 0, col: 4, w:2 h: 2</span>
79+
<a href='javascript:loadNewCharts(0,0,2,2)'>Show Scatter </a> <span class='smallCoords'>at row: 0, col: 4, w:2 h: 2</span>
8080
</li>
8181
<li>
82-
<a href='javascript:loadNewHeatmapCharts(2,0,2,3)'>Show new Heat Map </a> <span class='smallCoords'>at row: 2, col: 0, w:2 h: 3</span>
82+
<a href='javascript:loadNewHeatmapCharts(2,0,2,3)'>Show Heatmap </a> <span class='smallCoords'>at row: 2, col: 0, w:2 h: 3</span>
8383
</li>
8484
<li>
8585
<a href='javascript:loadHistogramCharts(2,2,2,3)'>Show Histogram</a> <span class='smallCoords'>at row: 2, col: 2, w:2 h: 3</span>
8686
</li>
8787
<li>
88-
<a href='javascript:load3DChart(2,4,2,3)'>3d Charts</a> <span class='smallCoords'>at row: 2, col: 4, w:2 h: 3</span>
88+
<a href='javascript:load3DChart(2,4,2,3)'>Show 3d Scatter</a> <span class='smallCoords'>at row: 2, col: 4, w:2 h: 3</span>
8989
</li>
9090
</ul>
9191

@@ -167,7 +167,7 @@
167167
y: "tables::wiseCatTbl,w2mpro-w3mpro",
168168
mode: 'markers',
169169
type: 'scatter',
170-
marker: {size: 4}
170+
marker: {size: 4, opacity: 0.5}
171171
};
172172

173173
var layoutS = {
@@ -209,20 +209,31 @@
209209
colorscale: 'Greens'
210210
}
211211
];
212+
// use firefly algorithm to create heatmap data
212213
var fireflyDataHM = [
213214
{dataType: 'fireflyHeatmap'},
214215
{dataType: 'fireflyHeatmap'},
215216
{dataType: 'fireflyHeatmap'}
216217
];
217-
218218
var layoutHM = {
219219
title: 'Magnitude-magnitude densities',
220220
xaxis: {title: 'w1 photometry (mag)'},
221221
yaxis: {title: ''}
222222
};
223+
// user boundaries - so that heatmaps will be calculated in the same XY space
224+
var fireflyLayoutHM = {
225+
xaxis: {
226+
min: 5,
227+
max: 20
228+
},
229+
yaxis: {
230+
min: 4,
231+
max: 18
232+
}
233+
};
223234

224235
firefly.getViewer().showPlot(
225-
{chartId: 'newChart2', layout: layoutHM, data: dataHM, fireflyData:fireflyDataHM },
236+
{chartId: 'newChart2', layout: layoutHM, data: dataHM, fireflyData:fireflyDataHM, fireflyLayout:fireflyLayoutHM},
226237
'heatMapContainer');
227238
}
228239

@@ -294,8 +305,6 @@
294305
var tfont = {size: 11};
295306
var layout3d = {
296307
title: 'Photometry in band 1, 2, 3',
297-
xaxis: {visible: false},
298-
yaxis: {visible: false},
299308
scene:{
300309
xaxis: {
301310
title: 'w1 (mag)',
@@ -376,7 +385,7 @@
376385
};
377386

378387
}
379-
388+
380389
</script>
381390

382391
<!-- to try a container: <script type="text/javascript" src="http://localhost:8090/firefly/firefly_loader.js"></script>-->
27 Bytes
Loading

src/firefly/java/edu/caltech/ipac/firefly/server/util/QueryUtil.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -790,13 +790,17 @@ public static DataGroup doDecimation(DataGroup dg, DecimateInfo decimateInfo) th
790790
}
791791

792792
if (doDecimation) {
793-
794793
boolean checkLimits = false;
795794
if (checkDeciLimits) {
796-
if (xDeciMin > xMin) { xMin = xDeciMin; checkLimits = true; }
797-
if (xDeciMax < xMax) { xMax = xDeciMax; checkLimits = true; }
798-
if (yDeciMin > yMin) { yMin = yDeciMin; checkLimits = true; }
799-
if (yDeciMax < yMax) { yMax = yDeciMax; checkLimits = true; }
795+
if (xDeciMin > xMin || xDeciMax < xMax || yDeciMin > yMin || yDeciMax < yMax) {
796+
checkLimits = true;
797+
}
798+
799+
// use boundaries provided in decimate info, if available
800+
if (!Double.isNaN(decimateInfo.getXMin())) { xMin = xDeciMin; }
801+
if (!Double.isNaN(decimateInfo.getXMax())) { xMax = xDeciMax; }
802+
if (!Double.isNaN(decimateInfo.getYMin())) { yMin = yDeciMin; }
803+
if (!Double.isNaN(decimateInfo.getYMax())) { yMax = yDeciMax; }
800804
}
801805

802806
if (outRows < deciEnableSize) {

src/firefly/js/charts/ChartUtil.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,16 @@ export function getPointIdx(traceData, rowIdx) {
279279
return rowIdxArray ? rowIdxArray.findIndex((e) => e == rowIdx) : rowIdx;
280280
}
281281

282+
export function isScatter2d(type) {
283+
return type.includes('scatter') && !type.endsWith('3d');
284+
}
285+
282286
export function getOptionsUI(chartId) {
283287
// based on chartData, determine what options to display
284288
const {data, fireflyData, activeTrace=0} = getChartData(chartId);
285289
const type = get(data, [activeTrace, 'type'], 'scatter');
286290
const dataType = get(fireflyData, [activeTrace, 'dataType'], '');
287-
if (type.includes('scatter')) {
291+
if (isScatter2d(type)) {
288292
return ScatterOptions;
289293
} else if (type === 'histogram') {
290294
return HistogramOptions;
@@ -300,7 +304,7 @@ export function getOptionsUI(chartId) {
300304
export function getToolbarUI(chartId, activeTrace=0) {
301305
const {data} = getChartData(chartId);
302306
const type = get(data, [activeTrace, 'type'], '');
303-
if (type.includes('scatter')) {
307+
if (isScatter2d(type)) {
304308
return ScatterToolbar;
305309
} else {
306310
return BasicToolbar;
@@ -318,8 +322,8 @@ export function clearChartConn({chartId}) {
318322

319323
export function newTraceFrom(data, selIndexes, newTraceProps) {
320324

321-
const sdata = cloneDeep(pick(data, ['x', 'y', 'error_x', 'error_y', 'text', 'marker', 'hoverinfo', 'firefly' ]));
322-
Object.assign(sdata, {showlegend: false, type: 'scatter', mode: 'markers'});
325+
const sdata = cloneDeep(pick(data, ['x', 'y', 'z', 'error_x', 'error_y', 'text', 'marker', 'hoverinfo', 'firefly' ]));
326+
Object.assign(sdata, {showlegend: false, type: get(data, 'type', 'scatter'), mode: 'markers'});
323327

324328
// walk through object and replace values where there's an array with only the selected indexes.
325329
function deepReplace(obj) {

src/firefly/js/charts/ChartsCntlr.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,13 @@ export function makeChartDataFetch (getChartDataType) {
313313

314314
function chartAdd(action) {
315315
return (dispatch) => {
316-
const {chartId, chartType, viewerId='main', data, fireflyData} = action.payload;
316+
const {chartId, chartType, viewerId='main', data, fireflyData, fireflyLayout} = action.payload;
317317
clearChartConn({chartId});
318318
dispatch(action);
319319
if (chartType === 'plot.ly') {
320320
dispatchAddViewer(viewerId,true,'plot2d',true);
321321
dispatchAddViewerItems(viewerId, [chartId], 'plot2d');
322-
handleTableSourceConnections({chartId, data, fireflyData});
322+
handleTableSourceConnections({chartId, data, fireflyData, fireflyLayout});
323323
}
324324
};
325325
}

src/firefly/js/charts/dataTypes/FireflyHeatmap.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ export function getTraceTSEntries({traceTS, chartId, traceNum}) {
2929
xyratio = xbins/ybins;
3030
}
3131

32-
//TODO: take into account zoom? and boundaries
33-
const {xmin, xmax, ymin, ymax} = {};
32+
//should we take into account zoom?
33+
const xmin = get(fireflyLayout, 'xaxis.min');
34+
const xmax = get(fireflyLayout, 'xaxis.max');
35+
const ymin = get(fireflyLayout, 'yaxis.min');
36+
const ymax = get(fireflyLayout, 'yaxis.max');
3437

3538
const options = {
3639
xColOrExpr: get(mappings, 'x'),

src/firefly/js/charts/dataTypes/FireflyScatter.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ function addOtherChanges({changes, xLabel, xTipLabel, xUnit, yLabel, yTipLabel,
155155
const yval = y[idx];
156156
const xerr = hasXErrors ? formatError(xval, xErr[idx], xErrLow[idx], xErrHigh[idx]) : '';
157157
const yerr = hasYErrors ? formatError(yval, yErr[idx], yErrLow[idx], yErrHigh[idx]) : '';
158-
return `<span> ${xTipLabel} = ${xval}${xerr} ${xUnit} <br>` +
159-
` ${yTipLabel} = ${yval}${yerr} ${yUnit} </span>`;
158+
return `<span> ${xTipLabel} = ${parseFloat(xval)}${xerr} ${xUnit} <br>` +
159+
` ${yTipLabel} = ${parseFloat(yval)}${yerr} ${yUnit} </span>`;
160160
});
161161
changes[`data.${traceNum}.text`] = text;
162162
changes[`data.${traceNum}.hoverinfo`] = 'text';

src/firefly/js/charts/ui/ChartPanel.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@
115115
.ChartToolbar__pan {
116116
background-image: url("/images/icons-2014/pan.png");
117117
}
118+
119+
.ChartToolbar__turntable {
120+
background-image: url("/images/turntable-tmp.png");
121+
}
122+
123+
.ChartToolbar__orbital {
124+
background-image: url("/images/orbital-tmp.png");
125+
}
126+
118127
.ChartToolbar__select {
119128
background-image: url("/images/icons-2014/select.png");
120129
}

src/firefly/js/charts/ui/PlotlyChartArea.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import shallowequal from 'shallowequal';
66
import {PlotlyWrapper} from './PlotlyWrapper.jsx';
77

88
import {dispatchChartUpdate, dispatchChartHighlighted, getChartData} from '../ChartsCntlr.js';
9+
import {isScatter2d} from '../ChartUtil.js';
910

1011
export class PlotlyChartArea extends PureComponent {
1112

@@ -63,8 +64,9 @@ export class PlotlyChartArea extends PureComponent {
6364
}
6465
const showlegend = data.length > 1;
6566
let pdata = data.map((e) => Object.assign({}, e)); // create shallow copy of data elements to avoid sharing x,y,z arrays
66-
if (!data[activeTrace] || get(data[activeTrace], 'type', '').includes('scatter')) {
67+
if (!data[activeTrace] || isScatter2d(get(data[activeTrace], 'type', ''))) {
6768
// highlight makes sense only for scatter at the moment
69+
// 3d scatter highlight and selected appear in front - not good: disable for the moment
6870
pdata = selected ? pdata.concat([selected]) : pdata;
6971
pdata = highlighted ? pdata.concat([highlighted]) : pdata;
7072
}

src/firefly/js/charts/ui/PlotlyToolbar.jsx

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ export class BasicToolbar extends SimpleComponent {
5656
//const {hasSelection, hasFilter, activeTrace, tbl_id, hasSelected, dragmode} = this.state;
5757
const {activeTrace, hasFilter, hasSelection, tbl_id, dragmode} = this.state;
5858

59-
const showSelectionPart = get(getChartData(chartId), `data.${activeTrace}.type`, '').includes('heatmap');
59+
const type = get(getChartData(chartId), `data.${activeTrace}.type`, '');
60+
const showSelectionPart = type.includes('heatmap');
61+
const is3d = type.endsWith('3d') || type === 'surface';
6062

6163
return (
6264
<div className='ChartToolbar'>
6365
<ActiveTraceSelect style={{marginRight: 20}} {...{chartId, activeTrace}}/>
64-
<DragModePart {...{chartId, tbl_id, dragmode}}/>
66+
<DragModePart {...{chartId, tbl_id, dragmode, hasSelectionMode: showSelectionPart, is3d}}/>
6567
{showSelectionPart && <div className='ChartToolbar__buttons' style={{margin: '0 5px'}}>
6668
{hasFilter && <ClearFilter {...{tbl_id}} />}
6769
{hasSelection && <FilterSelection {...{chartId}} />}
@@ -91,12 +93,14 @@ function SelectionPart({chartId, hasFilter, hasSelection, hasSelected, tbl_id})
9193
);
9294
}
9395

94-
function DragModePart({chartId, tbl_id, dragmode}) {
96+
function DragModePart({chartId, tbl_id, dragmode, hasSelectionMode, is3d}) {
9597
return (
9698
<div className='ChartToolbar__buttons' style={{margin: '0 5px'}}>
9799
<ZoomBtn {...{chartId, dragmode}} />
98100
<PanBtn {...{chartId, dragmode}} />
99-
{tbl_id && <SelectBtn {...{chartId, dragmode}} />}
101+
{is3d && <OrbitBtn {...{chartId, dragmode}} />}
102+
{is3d && <TurntableBtn {...{chartId, dragmode}} />}
103+
{tbl_id && hasSelectionMode && <SelectBtn {...{chartId, dragmode}} />}
100104
</div>
101105
);
102106
}
@@ -119,6 +123,24 @@ function PanBtn({style={}, chartId, dragmode}) {
119123
);
120124
}
121125

126+
function TurntableBtn({style={}, chartId, dragmode}) {
127+
const selected = dragmode === 'turntable' ? 'selected' : '';
128+
return (
129+
<div style={style} onClick={() => dispatchChartUpdate({chartId, changes:{'layout.dragmode': 'turntable', 'selection': undefined}})}
130+
title='Turntable rotation'
131+
className={`ChartToolbar__turntable ${selected}`}/>
132+
);
133+
}
134+
135+
function OrbitBtn({style={}, chartId, dragmode}) {
136+
const selected = dragmode === 'orbit' ? 'selected' : '';
137+
return (
138+
<div style={style} onClick={() => dispatchChartUpdate({chartId, changes:{'layout.dragmode': 'orbit', 'selection': undefined}})}
139+
title='Orbital rotation'
140+
className={`ChartToolbar__orbital ${selected}`}/>
141+
);
142+
}
143+
122144
function SelectBtn({style={}, chartId, dragmode}) {
123145
const selected = dragmode === 'select' ? 'selected' : '';
124146
return (
@@ -129,15 +151,21 @@ function SelectBtn({style={}, chartId, dragmode}) {
129151
}
130152

131153
function ResetZoomBtn({style={}, chartId}) {
132-
const {_original} = getChartData(chartId) || {};
154+
const {_original, layout} = getChartData(chartId) || {};
133155
const doClick = () => {
134-
// TODO: this only handles chart with 2 axes
156+
// 2d axes
135157
const changes = ['xaxis','yaxis'].reduce((pv, axis) => {
136-
pv[`layout.${axis}.autorange`] = get(_original, `layout.${axis}.autorange`, true);
137-
pv[`layout.${axis}.range`] = get(_original, `layout.${axis}.range`);
158+
if (get(layout, `${axis}`)) {
159+
pv[`layout.${axis}.autorange`] = get(_original, `layout.${axis}.autorange`, true);
160+
pv[`layout.${axis}.range`] = get(_original, `layout.${axis}.range`);
161+
}
138162
return pv;
139163
}, {});
140-
dispatchChartUpdate({chartId, changes});
164+
// 3d axes
165+
changes['layout.scene.camera'] = get(_original, 'layout.scene.camera', {});
166+
if (!isEmpty(changes)) {
167+
dispatchChartUpdate({chartId, changes});
168+
}
141169
};
142170
return (
143171
<div style={style} onClick={doClick}

0 commit comments

Comments
 (0)