package external; import java.awt.Color; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import org.das2.datum.DatumRange; import org.das2.graph.DasColorBar; import org.das2.graph.DefaultPlotSymbol; import org.das2.graph.PlotSymbol; import org.das2.graph.PsymConnector; import org.das2.util.ClassMap; import org.python.core.Py; import org.python.core.PyInteger; import org.python.core.PyObject; import org.python.core.PyString; import org.autoplot.RenderType; import org.autoplot.ScriptContext; import org.autoplot.datasource.DataSourceUtil; import org.autoplot.dom.Application; import org.autoplot.dom.CanvasUtil; import org.autoplot.dom.Column; import org.autoplot.dom.DataSourceFilter; import org.autoplot.dom.DomNode; import org.autoplot.dom.DomUtil; import org.autoplot.dom.Plot; import org.autoplot.dom.PlotElement; import org.autoplot.dom.Row; import org.das2.qds.QDataSet; import org.autoplot.jythonsupport.JythonOps; import org.autoplot.jythonsupport.PyQDataSetAdapter; import org.das2.datum.DatumRangeUtil; import org.das2.graph.FillStyle; import org.das2.graph.Renderer; import org.das2.graph.SeriesRenderer; import org.das2.qds.DataSetUtil; import org.das2.qds.ops.Ops; import org.das2.util.monitor.NullProgressMonitor; import org.python.core.PyJavaInstance; import org.python.core.PyList; import org.python.core.PyMethod; /** * new implementation of the plot command allows for keywords in the * Jython environment. *
{@code
 * plot( 0, ripples(20) )
 * plot( 1, ripples(20), color=Color.BLUE )
 * plot( 2, ripples(20), renderType='series>color=blue' )
 *}
* @see https://autoplot.org/help.plotCommand * @author jbf */ public class PlotCommand extends PyObject { private static final Logger logger= org.das2.util.LoggerManager.getLogger("autoplot"); public static final PyString __doc__ = new PyString("

plot([index],x,y,z,[named parameters])

" + "plot (or plotx) plots the data or URI for data on the canvas.\n" + "See https://autoplot.org/help.plotCommand
\n" + "
named parameters:\n" + "" + "\n" + " \n" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "
xlog ylog zlog explicitly set this axis to log (or linear when set equal to 0.).
[xyz]title set the label for the axis.
index plot index\n
title title for the plot\n
renderType explcitly set the render type, to scatter, series, nnSpectrogram, digital, etc\n
color the line colors.\n
fillColor the color when filling volumes.\n
colorTable the color table to use, like white_blue_black or black_red.\n
symbolSize set the point (pixel) size\n
symbolFill none, outline, or solid (solid is default)\n
lineWidth deprecated--the line thickness in points (pixels)\n
lineThick the line thickness in points (pixels)\n
lineStyle the line style, one of solid,none,dotfine,dashfine
symbol the symbol, e.g. dots triangles cross\n
isotropic constrain the ratio between the x and y axes.\n
legendLabel add label to the legend
title title for the plot\n
xpos override horizontal position of plot, eg. '50%+1em,100%-2em'\n
ypos override vertical position of plot, eg. '0%+1em,25%-2em', 0 is top\n
[xy]drawTickLabelsFalse turns off the x or y tick labels for the plot\n
[xy]tickValuesexplicitly control the tick locations.
[xyz]autoRangeHintshints to the autorange, see https://autoplot.org/AxisAutoRangeHints\n
rendereradd custom renderer, a class extending org.das2.graph.Renderer, see https://autoplot.org/CustomRenderers
rightAxisOfspecify a plot where a new plot with a new yaxis.
topAxisOfspecify a plot where a new plot with a new xaxis above.
overplotOfa plot or plot element with which this should share axes. Note something should reset the plot!
reset=Fsuppress autoranging, default is True" + "
"); public static final PyString __completions__; static { String text = new BufferedReader( new InputStreamReader( PlotCommand.class.getResourceAsStream("PlotCommand.json"), StandardCharsets.UTF_8) ) .lines().collect(Collectors.joining("\n")); __completions__= new PyString( text ); } private static QDataSet coerceIt( PyObject arg0 ) { Object o = arg0.__tojava__(QDataSet.class); if (o == null || o == Py.NoConversion) { return JythonOps.dataset(arg0); } else { QDataSet ds = (QDataSet) o; if (ds.rank() == 0) { // QDataSet library handles coerce logic. return ds; } else { return ds; } } } private static boolean booleanValue( PyObject arg0 ) { if ( arg0.isNumberType() ) { return arg0.__nonzero__(); } else { String s= String.valueOf(arg0); return s.equals("True") || s.equals("T") || s.equals("1"); } } /** * implement the python call. * @param args the "rightmost" elements are the keyword values. * @param keywords the names for the keywords. * @return Py.None */ @Override public PyObject __call__(PyObject[] args, String[] keywords) { PyObject False= Py.newBoolean(false); PyObject True= Py.newBoolean(true); FunctionSupport fs= new FunctionSupport( "plot", new String[] { "pos", "x", "y", "z", "xtitle", "xrange", "ytitle", "yrange", "ztitle", "zrange", "xscale", "yscale", "xlog", "ylog", "zlog", "title", "renderType", "color", "fillColor", "colorTable", "symbolSize","lineWidth","lineThick","lineStyle", "symsize","linewidth","linethick","linestyle", "legendLabel", "symbol", "symbolFill", "isotropic", "xpos", "ypos", "xdrawTickLabels", "ydrawTickLabels", "xautoRangeHints", "yautoRangeHints", "zautoRangeHints", "xtickValues", "ytickValues", "ztickValues", "renderer", "rightAxisOf", "topAxisOf", "overplotOf", "index", "reset" }, new PyObject[] { Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, False, False, False, Py.None, Py.None, Py.None,Py.None,Py.None, Py.None,Py.None,Py.None,Py.None, Py.None,Py.None,Py.None,Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, Py.None, True, } ); fs.args( args, keywords ); int nparm= args.length - keywords.length; if ( nparm==0 ) { logger.warning("args.length=0"); return Py.None; } int iplot=0; int nargs= nparm; boolean reset=true; // reset axis settings // If the first (zeroth) argument is an int, than this is the data source where the value should be inserted. Additional // data sources and plots will be added until there are enough. // this is an alias for the index argument. PyObject po0= args[0]; if ( po0 instanceof PyInteger ) { iplot= ((PyInteger)po0).getValue(); PyObject[] newArgs= new PyObject[args.length-1]; for ( int i=0; i pes= dom.getController().getPlotElementsFor( dom.getDataSourceFilters(iplot) ); pes.remove(pe); for ( PlotElement rm: pes ) { Plot prm= dom.getController().getPlotFor(rm); dom.getController().deletePlotElement(rm); if ( dom.getController().getPlotElementsFor(prm).isEmpty() ) { dom.getController().deletePlot(prm); } } } QDataSet[] qargs= new QDataSet[nargs]; if ( nargs==1 && po0 instanceof PyString ) { ScriptContext.plot( iplot, ((PyString) po0).toString()); } else if ( nargs==2 && po0 instanceof PyString && args[1] instanceof PyString ) { DatumRange drtr= DatumRangeUtil.parseTimeRangeValid(((PyString)args[1]).toString() ); try{ String uri= DataSourceUtil.setTimeRange( ((PyString) po0).toString(), drtr, new NullProgressMonitor() ); ScriptContext.plot( iplot, uri ); } catch ( IOException | URISyntaxException | ParseException ex ) { throw new RuntimeException(ex); } } else { for ( int i=0; i elements= dom.getController().getPlotElementsFor( dsf ); if ( elements.isEmpty() ) { logger.log(Level.WARNING, "no elements found for data at index={0}", iplot); return Py.None; } PlotElement element= elements.get(0); plot= dom.getController().getPlotFor(element); plot.setIsotropic(false); for ( int i=nparm; i0 ) { int ii= srenderType.indexOf('>'); if ( ii==-1 ) { renderControl= ""; } else { renderControl= srenderType.substring(ii+1); srenderType= srenderType.substring(0,ii); } RenderType rt= RenderType.valueOf(srenderType); element.setRenderType(rt); element.setRenderControl(renderControl); } } else if ( kw.equals("renderer") ) { Renderer r; if (val.__tojava__(Renderer.class) != Py.NoConversion) { Renderer oldRenderer= element.getController().getRenderer(); String control= oldRenderer.getControl(); r = (Renderer) val.__tojava__(Renderer.class); QDataSet ds1=null; switch (nargs) { case 1: ds1= qargs[0]; break; case 2: ds1= Ops.link( qargs[0], qargs[1] ); break; case 3: ds1= Ops.link( qargs[0], qargs[1], qargs[2] ); break; default: break; } PyObject doAuto= val.__findattr__( "doAutorange" ); if ( doAuto==null ) { doAuto= val.__findattr__( "autorange" ); } if ( doAuto!=null && doAuto!=Py.None && ds1!=null ) { PyObject range= ((PyMethod)doAuto).__call__(new PyQDataSetAdapter().adapt(ds1)); QDataSet rangeds= (QDataSet) range.__tojava__(QDataSet.class); plot.getXaxis().setRange( DataSetUtil.asDatumRange(rangeds.slice(0) ) ); if ( rangeds.length()>1 ) plot.getYaxis().setRange( DataSetUtil.asDatumRange(rangeds.slice(1) ) ); if ( rangeds.length()>2 ) plot.getZaxis().setRange( DataSetUtil.asDatumRange(rangeds.slice(2) ) ); } plot.getController().getDasPlot().removeRenderer(oldRenderer); plot.getController().getDasPlot().addRenderer(r); r.setDataSet(ds1); r.setColorBar((DasColorBar) plot.getZaxis().getController().getDasAxis()); element.getController().setRenderer(r); element.setRenderType(RenderType.internal); r.setControl(control); } else { logger.warning("no conversion for renderer"); } } else if ( kw.equals("legendLabel" ) ) { if ( !sval.equals("") ) { element.setLegendLabel(sval); element.setDisplayLegend(true); } } else if ( kw.equals("isotropic" ) ) { plot.setIsotropic(true); } else if ( kw.equals("xdrawTickLabels") ) { plot.getXaxis().setDrawTickLabels( booleanValue(val) ); } else if ( kw.equals("ydrawTickLabels") ) { plot.getYaxis().setDrawTickLabels( booleanValue(val) ); } else if ( kw.equals("xtickValues") ) { plot.getXaxis().setTickValues(sval); } else if ( kw.equals("ytickValues") ) { plot.getYaxis().setTickValues(sval); } else if ( kw.equals("ztickValues") ) { plot.getZaxis().setTickValues(sval); } else if ( kw.equals("xautoRangeHints") ) { plot.getXaxis().setAutoRangeHints( sval ); } else if ( kw.equals("yautoRangeHints") ) { plot.getYaxis().setAutoRangeHints( sval ); } else if ( kw.equals("zautoRangeHints") ) { plot.getZaxis().setAutoRangeHints( sval ); } } fplot= plot; fplotElement= element; } finally { dom.getController().changePerformed(this,this); } return new PyList( new PyObject[] { new PyJavaInstance(fplot), new PyJavaInstance(fplotElement) } ); } }