Skip to content

download plotly image as PNG #373

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

Merged
merged 2 commits into from
May 4, 2017
Merged
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
10 changes: 7 additions & 3 deletions src/firefly/js/charts/ChartUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
* Utilities related to charts
* Created by tatianag on 3/17/16.
*/
import {uniqueId, isUndefined, omitBy} from 'lodash';
import {get, uniqueId, isUndefined, omitBy} from 'lodash';

import {getAppOptions} from '../core/AppDataCntlr.js';
import {getTblById, getColumnIdx, getCellValue} from '../tables/TableUtil.js';
import {Expression} from '../util/expr/Expression.js';
import {logError} from '../util/WebUtil.js';

export const SCATTER = 'scatter';
export const HISTOGRAM = 'histogram';

export function isPlotly() {
return get(getAppOptions(), 'charts.chartEngine')==='plotly';
}

/**
* This method returns an object with the keys x,y,highlightedRow
Expand All @@ -24,7 +28,7 @@ export const HISTOGRAM = 'histogram';
* @param {string} tblId
* @returns {{x: number, y: number, rowIdx}}
*/
export const getHighlighted = function(xyPlotParams, tblId) {
export function getHighlighted(xyPlotParams, tblId) {

const tableModel = getTblById(tblId);
if (tableModel && xyPlotParams) {
Expand All @@ -46,7 +50,7 @@ export const getHighlighted = function(xyPlotParams, tblId) {
});
return highlighted;
}
};
}

/**
* This method returns the value of the column cell or an expression from multiple column cells in a given row
Expand Down
11 changes: 9 additions & 2 deletions src/firefly/js/charts/chartTypes/HistogramTblView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {HelpIcon} from '../../ui/HelpIcon.jsx';
import {ToolbarButton} from '../../ui/ToolbarButton.jsx';

import * as ChartsCntlr from '../ChartsCntlr.js';
import {isPlotly} from '../ChartUtil.js';
import {downloadChart} from '../ui/PlotlyWrapper.jsx';
import {HistogramOptions} from '../ui/HistogramOptions.jsx';
import {Histogram} from '../ui/Histogram.jsx';
import {getChartProperties, updateOnStoreChange, FilterEditorWrapper} from './TblView.jsx';
Expand All @@ -19,6 +21,7 @@ import OUTLINE_EXPAND from 'html/images/icons-2014/24x24_ExpandArrowsWhiteOutlin
import SETTINGS from 'html/images/icons-2014/24x24_GearsNEW.png';
import CLEAR_FILTERS from 'html/images/icons-2014/24x24_FilterOff_Circle.png';
import FILTER from 'html/images/icons-2014/24x24_Filter.png';
import SAVE from 'html/images/icons-2014/24x24_Save.png';
import LOADING from 'html/images/gxt/loading.gif';

export const HISTOGRAM_TBLVIEW = {
Expand All @@ -33,7 +36,7 @@ export const HISTOGRAM_TBLVIEW = {


function Chart(props) {
const {chartId, tblId, chartData, widthPx, heightPx, eventCallback} = props;
const {chartId, tblId, chartData, widthPx, heightPx} = props;
if (!TblUtil.isFullyLoaded(tblId) || !chartData || !heightPx || !widthPx) {
return (<div/>);
}
Expand Down Expand Up @@ -72,7 +75,6 @@ function Chart(props) {
xAxis={xAxis}
yAxis={yAxis}
xUnit={unit}
eventCallback={eventCallback}
chartId={chartId}

/>
Expand Down Expand Up @@ -133,6 +135,7 @@ Options.propTypes = {
optionsKey: PropTypes.string
};


function Toolbar({chartId, expandable, expandedMode, toggleOptions}) {
const {tableModel, help_id} = getChartProperties(chartId);
return (
Expand All @@ -150,6 +153,10 @@ function Toolbar({chartId, expandable, expandedMode, toggleOptions}) {
visible={true}
badgeCount={TblUtil.getFilterCount(tableModel)}
onClick={() => toggleOptions('filters')}/>
{isPlotly() && <img className='PanelToolbar__button'
title='Download the chart as a PNG image'
src={SAVE}
onClick={() => downloadChart(chartId)}/>}
<img className='PanelToolbar__button'
title='Chart options and tools'
src={SETTINGS}
Expand Down
11 changes: 9 additions & 2 deletions src/firefly/js/charts/chartTypes/ScatterTblView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {HelpIcon} from '../../ui/HelpIcon.jsx';
import {ToolbarButton} from '../../ui/ToolbarButton.jsx';

import * as ChartsCntlr from '../ChartsCntlr.js';
import {getHighlighted} from '../ChartUtil.js';
import {getHighlighted, isPlotly} from '../ChartUtil.js';
import {downloadChart} from '../ui/PlotlyWrapper.jsx';
import {setXYSelection, setZoom} from '../dataTypes/XYColsCDT.js';

import {showInfoPopup} from '../../ui/PopupUtil.jsx';
Expand All @@ -33,6 +34,7 @@ import ZOOM_ORIGINAL from 'html/images/icons-2014/Zoom1x-24x24-tmp.png';
import UNSELECT_ROWS from 'html/images/icons-2014/24x24_CheckmarkOff_Circle.png';
import CLEAR_FILTERS from 'html/images/icons-2014/24x24_FilterOff_Circle.png';
import FILTER from 'html/images/icons-2014/24x24_Filter.png';
import SAVE from 'html/images/icons-2014/24x24_Save.png';
import LOADING from 'html/images/gxt/loading.gif';


Expand Down Expand Up @@ -83,7 +85,8 @@ class ChartComp extends React.Component {
const sInfo = tableModel && tableModel.selectInfo;

return (
<XYPlot data={xyPlotData}
<XYPlot chartId={chartId}
data={xyPlotData}
desc=''
width={widthPx}
height={heightPx}
Expand Down Expand Up @@ -191,6 +194,10 @@ function Toolbar({chartId, expandable, expandedMode, toggleOptions}) {
visible={true}
badgeCount={TblUtil.getFilterCount(tableModel)}
onClick={() => toggleOptions('filters')}/>
{isPlotly() && <img className='PanelToolbar__button'
title='Download the chart as a PNG image'
src={SAVE}
onClick={() => downloadChart(chartId)}/>}
<img className='PanelToolbar__button'
title='Chart options and tools'
src={SETTINGS}
Expand Down
10 changes: 3 additions & 7 deletions src/firefly/js/charts/ui/Histogram.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/

import {get} from 'lodash';
import {getAppOptions} from '../../core/AppDataCntlr.js';
import {HistogramPlotly} from './HistogramPlotly.jsx';
import {HistogramHighcharts} from './HistogramHighcharts.jsx';
import {isPlotly} from '../ChartUtil.js';
import React from 'react';

export function Histogram(props) {
if (get(getAppOptions(), 'charts.chartEngine') !== 'plotly') {
return <HistogramHighcharts {...props}/>;
} else {
return <HistogramPlotly {...props} />;
}
const HistogramInstance = isPlotly() ? HistogramPlotly : HistogramHighcharts;
return <HistogramInstance {...props}/>;
}

3 changes: 2 additions & 1 deletion src/firefly/js/charts/ui/HistogramPlotly.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export class HistogramPlotly extends React.Component {
const {plotlyData, plotlyDivStyle, plotlyLayout}= this.chartingInfo;

return (
<PlotlyWrapper data={plotlyData} layout={plotlyLayout} style={plotlyDivStyle}
<PlotlyWrapper chartId={this.props.chartId} data={plotlyData} layout={plotlyLayout} style={plotlyDivStyle}
dataUpdate={dataUpdate}
layoutUpdate={layoutUpdate}
divUpdateCB={(div) => this.chart= div}
Expand All @@ -302,6 +302,7 @@ HistogramPlotly.defaultProps = {


HistogramPlotly.propTypes = {
chartId: PropTypes.string,
series: PropTypes.arrayOf(PropTypes.object), // array of objects with data, binColor, and name properties
xAxis: PropTypes.object,
yAxis: PropTypes.object,
Expand Down
26 changes: 21 additions & 5 deletions src/firefly/js/charts/ui/PlotlyWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
*/

import React, {Component, PropTypes} from 'react';
import {get} from 'lodash';
import {getPlotLy} from '../PlotlyConfig.js';
import {logError} from '../../util/WebUtil.js';
import Enum from 'enum';

const PLOTLY_BASE_ID= 'plotly-plot';
var counter= 0;



export const RenderType= new Enum([ 'RESIZE', 'UPDATE', 'RESTYLE', 'RELAYOUT', 'RESTYLE_AND_RELAYOUT', 'NEW_PLOT'],
{ ignoreCase: true });



const defaultConfig= {
displaylogo: false,
modeBarButtonsToRemove :[
Expand All @@ -25,6 +24,21 @@ const defaultConfig= {
]
};

export function downloadChart(chartId) {
getPlotLy().then( (Plotly) => {
const chartDiv = document.getElementById(chartId);
if (chartId && chartDiv) {
const filename = get(chartDiv, 'layout.title') || chartId;
Plotly.downloadImage(chartDiv, {
format: 'png',
filename
});
} else {
logError(`Image download has failed for chart id ${chartId}`);
}
});
}

export class PlotlyWrapper extends Component {

constructor(props) {
Expand Down Expand Up @@ -117,12 +131,13 @@ export class PlotlyWrapper extends Component {
}

render() {
const {style}= this.props;
const {chartId, style}= this.props;
// note: wrapper div is the target for the simulated click event
// when the original click event is lost and plotly_click is emitted instead
// chart image download relies on div id matching chartId
return (
<div>
<div id={this.id} style={style} ref={this.refUpdate}/>
<div id={chartId || this.id} style={style} ref={this.refUpdate}/>
</div>
);
}
Expand All @@ -131,6 +146,7 @@ export class PlotlyWrapper extends Component {


PlotlyWrapper.propTypes = {
chartId: PropTypes.string,
data: PropTypes.arrayOf(PropTypes.object),
style :PropTypes.object,
layout: PropTypes.object,
Expand Down
5 changes: 3 additions & 2 deletions src/firefly/js/charts/ui/XYPlot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import {get, omit} from 'lodash';
import shallowequal from 'shallowequal';
import React, {PropTypes} from 'react';
import {getAppOptions} from '../../core/AppDataCntlr.js';
import {isPlotly} from '../ChartUtil.js';
import {XYPlotHighcharts} from './XYPlotHighcharts.jsx';
import {XYPlotPlotly} from './XYPlotPlotly.jsx';
import {plotParamsShape, plotDataShape} from './XYPlotPropTypes.js';
Expand Down Expand Up @@ -221,13 +221,14 @@ export class XYPlot extends React.Component {
</div>
);
} else {
const XYPlotInstance= get(getAppOptions(), 'charts.chartEngine')==='plotly' ? XYPlotPlotly : XYPlotHighcharts;
const XYPlotInstance= isPlotly() ? XYPlotPlotly : XYPlotHighcharts;
return (<XYPlotInstance {...this.props}/>);
}
}
}

XYPlot.propTypes = {
chartId: PropTypes.string,
data: plotDataShape,
width: PropTypes.number,
height: PropTypes.number,
Expand Down
3 changes: 2 additions & 1 deletion src/firefly/js/charts/ui/XYPlotPlotly.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ export class XYPlotPlotly extends React.Component {

return (
<div style={{float: 'left'}}>
<PlotlyWrapper data={plotlyData} layout={plotlyLayout} style={plotlyDivStyle}
<PlotlyWrapper chartId={this.props.chartId} data={plotlyData} layout={plotlyLayout} style={plotlyDivStyle}
dataUpdateTraces={dataUpdateTraces}
dataUpdate={dataUpdate}
layoutUpdate={layoutUpdate}
Expand All @@ -799,6 +799,7 @@ export class XYPlotPlotly extends React.Component {
}

XYPlotPlotly.propTypes = {
chartId: PropTypes.string,
data: plotDataShape,
width: PropTypes.number,
height: PropTypes.number,
Expand Down