package org.autoplot.jythonsupport; import java.awt.Color; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.text.ParseException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.autoplot.datasource.DataSetURI; import org.autoplot.datasource.FileSystemUtil; import org.das2.datum.Datum; import org.das2.datum.DatumRange; import org.das2.datum.Units; import org.python.core.Py; import org.python.core.PyArray; import org.python.core.PyDictionary; import org.das2.qds.QubeDataSetIterator; import org.python.core.PyFloat; import org.python.core.PyFunction; import org.python.core.PyInteger; import org.python.core.PyJavaInstance; import org.python.core.PyList; import org.python.core.PyLong; import org.python.core.PyNone; import org.python.core.PyObject; import org.python.core.PyString; import org.python.core.PyTuple; import org.das2.qds.DDataSet; import org.das2.qds.DataSetUtil; import org.das2.qds.MutablePropertyDataSet; import org.das2.qds.QDataSet; import org.autoplot.datasource.URISplit; import org.das2.datum.InconvertibleUnitsException; import org.das2.datum.UnitsConverter; import org.das2.datum.UnitsUtil; import org.das2.jythoncompletion.JavadocLookup; import org.das2.qds.SemanticOps; import org.das2.qds.ops.Ops; import org.das2.qds.util.DataSetBuilder; import org.das2.util.JsonUtil; import org.das2.util.filesystem.FileSystem; import org.das2.util.monitor.ProgressMonitor; import org.json.JSONException; import org.json.JSONObject; /** * Contains operations that are only available to Jython code, and is dependent * on the jython libraries. * * @author jbf */ public class JythonOps { private static final Logger logger= Logger.getLogger("jython"); /** * Apply the Python function, typically a lambda function, to each * element of the dataset. For example: *
* * @param ds the dataset to which the function is applied * @param f the function * @return the dataset with the function applied */ public static QDataSet applyLambda(QDataSet ds, PyFunction f ) { QubeDataSetIterator it = new QubeDataSetIterator(ds); DDataSet result = DDataSet.create(DataSetUtil.qubeDims(ds)); while (it.hasNext()) { it.next(); double d = it.getValue(ds); PyFloat r = (PyFloat) f.__call__(new PyFloat(d)); it.putValue( result, r.getValue() ); } return result; } /** * Apply the Python function, typically a two-argument lambda function, to each * element of the dataset. For example: *{@code * xx= dindgen( 6 ) * yy= applyLambda( xx, lambda x : x**2 ) * plot( xx, yy ) *}
* * @param ds1 the dataset to which the function is applied * @param ds2 the dataset to which the function is applied * @param f the function * @return the dataset with the function applied */ public static QDataSet applyLambda( QDataSet ds1, QDataSet ds2, PyFunction f ) { QubeDataSetIterator it = new QubeDataSetIterator(ds1); DDataSet result = DDataSet.create(DataSetUtil.qubeDims(ds1)); while (it.hasNext()) { it.next(); double d1 = it.getValue(ds1); double d2 = it.getValue(ds2); PyFloat r = (PyFloat) f.__call__( new PyFloat(d1), new PyFloat(d2) ); it.putValue( result, r.getValue() ); } return result; } /** * Apply the Python function, typically a three-argument lambda function, to each * element of the dataset. For example: *{@code * xx= dindgen( 6 ) * yy= ones( 6 ) * yy= applyLambda( xx, yy, lambda x,y : x+y ) * plot( xx, yy ) *}
* * @param ds1 the dataset to which the function is applied * @param ds2 the dataset to which the function is applied * @param ds3 the dataset to which the function is applied * @param f the function * @return the dataset with the function applied */ public static QDataSet applyLambda( QDataSet ds1, QDataSet ds2, QDataSet ds3, PyFunction f ) { QubeDataSetIterator it = new QubeDataSetIterator(ds1); DDataSet result = DDataSet.create(DataSetUtil.qubeDims(ds1)); while (it.hasNext()) { it.next(); double d1 = it.getValue(ds1); double d2 = it.getValue(ds2); double d3 = it.getValue(ds3); PyFloat r = (PyFloat) f.__call__( new PyFloat(d1), new PyFloat(d2), new PyFloat(d3) ); it.putValue( result, r.getValue() ); } return result; } // public static QDataSet coerce( PyObject arg0 ) { // System.err.println("======================================================"); // System.err.println("coerce( PyObject ) command that makes a QDataSet is deprecated--use coerceToDs( PyObject ) instead."); // System.err.println("native python coerce command will be available soon. Contact faden @ cottagesystems.com if you need assistance."); // System.err.println(" sleeping for 3 seconds."); // System.err.println("======================================================"); // try { // Thread.sleep(3000); // } catch (InterruptedException ex) { // Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex); // } // return coerceToDs( arg0 ); // } /** * @deprecated use dataset command. * @param arg0 * @return */ public static QDataSet coerceToDs( PyObject arg0 ) { return dataset( arg0 ); } /** * coerce a python array or list into a QDataSet. * @param arg0 Python object or Datum * @return QDataSet * @see org.das2.qds.ops.Ops#dataset(java.lang.Object) */ public static QDataSet dataset( PyObject arg0 ) { if ( arg0 instanceof PyQDataSet ) { return ((PyQDataSet)arg0).rods; } else if ( arg0 instanceof PyDatum ) { return DataSetUtil.asDataSet( ((PyDatum)arg0).datum ); } else if ( arg0 instanceof PyList ) { return PyQDataSetAdapter.adaptList( (PyList)arg0 ) ; } else if ( arg0 instanceof PyArray ) { return PyQDataSetAdapter.adaptArray( (PyArray) arg0 ); } else if ( arg0 instanceof PyTuple ) { return PyQDataSetAdapter.adaptTuple( (PyTuple) arg0 ); } else if ( arg0 instanceof PyInteger ) { return DataSetUtil.asDataSet( ((Double)arg0.__tojava__( Double.class )).doubleValue() ); } else if ( arg0 instanceof PyLong ) { return DataSetUtil.asDataSet( ((Double)arg0.__tojava__( Double.class )).doubleValue() ); } else if ( arg0 instanceof PyFloat ) { return DataSetUtil.asDataSet( ((Double)arg0.__tojava__( Double.class )).doubleValue() ); } else if ( arg0 instanceof PyJavaInstance && ( ((PyJavaInstance)arg0).__tojava__(Datum.class) instanceof Datum ) ) { return DataSetUtil.asDataSet( (Datum)((PyJavaInstance)arg0).__tojava__(org.das2.datum.Datum.class) ); } else if ( arg0 instanceof PyJavaInstance && ( ((PyJavaInstance)arg0).__tojava__(DatumRange.class) instanceof DatumRange ) ) { return DataSetUtil.asDataSet( (DatumRange)((PyJavaInstance)arg0).__tojava__(org.das2.datum.DatumRange.class) ); } else if ( arg0 instanceof PyJavaInstance && ( ((PyJavaInstance)arg0).__tojava__(QDataSet.class) instanceof QDataSet ) ) { return DataSetUtil.asDataSet( ((PyJavaInstance)arg0).__tojava__(QDataSet.class) ); } else if ( arg0 instanceof PyString ) { try { return Ops.dataset(arg0.toString()); } catch (IllegalArgumentException ex) { throw Py.SyntaxError( "unable to parse string: "+arg0 ); } } else if ( arg0 instanceof PyNone ) { // In python code, support test like "ds!=None" return null; } else { throw Py.TypeError("JythonOps is unable to coerce "+arg0+" to QDataSet"); } } /** * coerce Python objects like arrays Lists and Arrays into a QDataSet. * @param arg0 a PyQDataSet, PyList, PyArray, PyTuple, PyInteger, PyLong, PyFloat, Datum, DatumRange, or String. * @param u unit context * @return the dataset * @see Ops#dataset(java.lang.Object, org.das2.datum.Units) */ public static QDataSet dataset( PyObject arg0, Units u ) { if ( arg0 instanceof PyQDataSet ) { QDataSet result= ((PyQDataSet)arg0).rods; return Ops.dataset( result, u ); } else if ( arg0 instanceof PyList ) { PyList pl= (PyList)arg0; DataSetBuilder builder= new DataSetBuilder( 1, pl.__len__() ); for ( int i=0; i{@code * xx= dindgen( 6 ) * yy= ones( 6 ) * yy= applyLambda( xx, yy, lambda x,y : x+y ) * plot( xx, yy ) *}
* @param syspath the list of folders to search, should be sys.path. * @param path the path to add, which should be a jar file, possibly contained within a zip on an http site. * @param mon monitor for the download. * @return the name of the folder or jar file added. * @see https://sourceforge.net/p/autoplot/feature-requests/584/, which shows example use. * @see #findJavaPathRoots(org.das2.util.filesystem.FileSystem) * @throws IOException * @throws URISyntaxException */ public static String addToSearchPath( PyList syspath, String path, ProgressMonitor mon ) throws IOException, URISyntaxException { return addToSearchPath( syspath, path, null, mon ); } /** * download the jar file resource, unpack it, and add it to the search path. Note * such scripts will not work with Webstart releases! The code is only * loaded once per session, so Autoplot must be restarted if the library is updated. * * Here is an example use: *{@code *import sys *addToSearchPath( sys.path, 'http://www-us.apache.org/dist//commons/math/binaries/commons-math3-3.6.1-bin.zip/commons-math3-3.6.1/commons-math3-3.6.1.jar', monitor ) *from org.apache.commons.math3.distribution import BetaDistribution *beta= BetaDistribution(2,5) * *xx= linspace(0,1.0,100) *yy= zeros(100) *for i in indgen(100): * yy[i]= beta.density(xx[i].value()) *#yy= map( xx, beta.density ) *plot( xx, yy ) *}
* @param syspath the list of folders to search, should be sys.path. * @param path the path to add, which should be a jar file, possibly contained within a zip on an http site. * @param docPath the path containing javadocs, useful programmatically for completions. * @param mon monitor for the download. * @return the name of the folder or jar file added. * @see https://sourceforge.net/p/autoplot/feature-requests/584/ which shows example use. * @see #findJavaPathRoots(org.das2.util.filesystem.FileSystem) * @throws IOException * @throws URISyntaxException */ public static String addToSearchPath( PyList syspath, String path, String docPath, ProgressMonitor mon ) throws IOException, URISyntaxException { if ( System.getProperty("javawebstart.version")!=null ) { logger.warning("Jython addToSearchPath will probably fail because this is not supported with Webstart."); } if ( path.endsWith(".jar") ) { File jarFile; try { jarFile= FileSystemUtil.doDownload( path, mon ); } catch ( IOException e ) { jarFile= DataSetURI.downloadResourceAsTempFile( DataSetURI.getURL(path),mon); } File destDir= FileSystem.settings().getLocalCacheDir(); destDir= new File( destDir, "jar" ); String ss= path.replace("://", "/"); destDir= new File( destDir, ss ); org.das2.util.filesystem.FileSystemUtil.unzipFile( jarFile, destDir); syspath.insert( 0, new PyString(destDir.toString()) ); if ( docPath!=null ) { List{@code *import sys *addToSearchPath( sys.path, 'http://www-us.apache.org/dist//commons/math/binaries/commons-math3-3.6.1-bin.zip/commons-math3-3.6.1/commons-math3-3.6.1.jar', monitor ) *from org.apache.commons.math3.distribution import BetaDistribution *beta= BetaDistribution(2,5) * *xx= linspace(0,1.0,100) *yy= zeros(100) *for i in indgen(100): * yy[i]= beta.density(xx[i].value()) *#yy= map( xx, beta.density ) *plot( xx, yy ) *}