src/org/math/plot/DataSelectTable.java

00001 /*
00002  * Created on 6 juil. 07 by richet
00003  */
00004 package org.math.plot;
00005 
00006 import java.awt.BorderLayout;
00007 import java.awt.Dimension;
00008 import java.awt.GridLayout;
00009 import java.awt.event.ActionEvent;
00010 import java.beans.PropertyChangeListener;
00011 import java.util.LinkedList;
00012 import java.util.Vector;
00013 
00014 import javax.swing.Action;
00015 import javax.swing.BorderFactory;
00016 import javax.swing.ButtonGroup;
00017 import javax.swing.JCheckBox;
00018 import javax.swing.JComponent;
00019 import javax.swing.JFrame;
00020 import javax.swing.JList;
00021 import javax.swing.JPanel;
00022 import javax.swing.JRadioButton;
00023 import javax.swing.JScrollPane;
00024 import javax.swing.JSlider;
00025 import javax.swing.JTable;
00026 import javax.swing.event.ChangeEvent;
00027 import javax.swing.event.ChangeListener;
00028 import javax.swing.event.ListSelectionEvent;
00029 import javax.swing.event.ListSelectionListener;
00030 import javax.swing.event.TableModelListener;
00031 import javax.swing.table.TableModel;
00032 
00033 import org.math.plot.utils.Array;
00034 
00039 public class DataSelectTable extends JPanel {
00040 
00041         private static final long serialVersionUID = 41918175232722331L;
00042 
00043         LinkedList<ParameterRow> rows;
00044 
00045         private Object[][] _data, _selecteddata;
00046 
00047         private LinkedList<Object[]> _tmpselecteddata;
00048 
00049         boolean dataUpdated = false;
00050 
00051         private int[] _tmpselectedIndex;
00052 
00053         private int _nbselected;
00054 
00055         private int[] _selectedindex;
00056 
00057         private String[] _parametersNames;
00058 
00059         private JTable _table;
00060 
00061         int _dimension;
00062 
00063         public DataSelectTable(Object[][] data, int dimension, String... parametersNames) {
00064                 _data = data;
00065                 _dimension = dimension;
00066 
00067                 _parametersNames = parametersNames;
00068 
00069                 if (_dimension > parametersNames.length)
00070                         throw new IllegalArgumentException("Number of parameters must be > to dimension=" + _dimension);
00071 
00072                 if (_dimension == 1)
00073                         buildRows(0);
00074                 else if (_dimension == 2)
00075                         buildRows(0, 1);
00076                 else if (_dimension == 3)
00077                         buildRows(0, 1, 2);
00078 
00079                 add(new JScrollPane(_table));
00080 
00081         }
00082 
00083         LinkedList<String> header;
00084 
00085         LinkedList<Class< ? >> columnclasses;
00086 
00087         class Model implements TableModel {
00088 
00089                 public Model(int... selectedaxis) {
00090 
00091                 }
00092 
00093                 public void setValueAt(Object value, int rowIndex, int columnIndex) {
00094                         // TODO Auto-generated method stub
00095 
00096                 }
00097 
00098                 public void removeTableModelListener(TableModelListener l) {
00099                         // TODO Auto-generated method stub
00100 
00101                 }
00102 
00103                 public boolean isCellEditable(int rowIndex, int columnIndex) {
00104                         // TODO Auto-generated method stub
00105                         return false;
00106                 }
00107 
00108                 public Object getValueAt(int rowIndex, int columnIndex) {
00109                         if (columnIndex == 0)
00110                                 return _parametersNames[rowIndex];
00111                         if (columnIndex == _dimension - 2)
00112                                 return rows.get(rowIndex).xaxis;
00113                         if (columnIndex == _dimension - 1)
00114                                 return rows.get(rowIndex).yaxis;
00115                         if (columnIndex == _dimension)
00116                                 return rows.get(rowIndex).zaxis;
00117 
00118                         return null;
00119                 }
00120 
00121                 public int getRowCount() {
00122                         return _parametersNames.length;
00123                 }
00124 
00125                 public String getColumnName(int columnIndex) {
00126                         return header.get(columnIndex);
00127                 }
00128 
00129                 public int getColumnCount() {
00130                         return header.size();
00131                 }
00132 
00133                 public Class< ? > getColumnClass(int columnIndex) {
00134                         return columnclasses.get(columnIndex);
00135                 }
00136 
00137                 public void addTableModelListener(TableModelListener l) {
00138                         // TODO Auto-generated method stub
00139 
00140                 }
00141 
00142         }
00143 
00144         void buildRows(int... selectedaxis) {
00145 
00146                 header = new LinkedList<String>();
00147                 header.add("Parameter");
00148                 if (_dimension <= 1)
00149                         header.add("X");
00150                 if (_dimension <= 2)
00151                         header.add("Y");
00152                 if (_dimension <= 3)
00153                         header.add("Z");
00154                 header.add("min");
00155                 header.add("<>");
00156                 header.add("=");
00157                 header.add("<>");
00158                 header.add("max");
00159 
00160                 columnclasses = new LinkedList<Class< ? >>();
00161                 columnclasses.add(String.class);
00162                 if (_dimension <= 1)
00163                         columnclasses.add(Boolean.class);
00164                 if (_dimension <= 2)
00165                         columnclasses.add(Boolean.class);
00166                 if (_dimension <= 3)
00167                         columnclasses.add(Boolean.class);
00168                 columnclasses.add(Double.class);
00169                 columnclasses.add(JSlider.class);
00170                 columnclasses.add(Boolean.class);
00171                 columnclasses.add(JSlider.class);
00172                 columnclasses.add(Double.class);
00173 
00174                 ButtonGroup xgrp = new ButtonGroup();
00175                 ButtonGroup ygrp = new ButtonGroup();
00176                 ButtonGroup zgrp = new ButtonGroup();
00177                 rows = new LinkedList<ParameterRow>();
00178                 for (int i = 0; i < _parametersNames.length; i++) {
00179                         rows.add(new ParameterRow(_parametersNames[i], getColumn(i, _data)));
00180 
00181                         rows.get(i).xaxis.setSelected(selectedaxis[0] == i);
00182                         if (selectedaxis.length >= 2)
00183                                 rows.get(i).yaxis.setSelected(selectedaxis[1] == i);
00184                         if (selectedaxis.length == 3)
00185                                 rows.get(i).zaxis.setSelected(selectedaxis[2] == i);
00186 
00187                         xgrp.add(rows.get(i).xaxis);
00188                         ygrp.add(rows.get(i).yaxis);
00189                         zgrp.add(rows.get(i).zaxis);
00190                 }
00191                 updateSelectedData();
00192         }
00193 
00194         public void setData(Object[][] data) {
00195                 if (data[0].length != _data[0].length)
00196                         throw new IllegalArgumentException("new data dimension is not consistent with previous one.");
00197                 _data = data;
00198 
00199                 int[] selectedaxis = new int[_dimension];
00200                 for (int i = 0; i < rows.size(); i++) {
00201                         if (rows.get(i).xaxis.isSelected())
00202                                 selectedaxis[0] = i;
00203                         if (selectedaxis.length >= 2)
00204                                 if (rows.get(i).yaxis.isSelected())
00205                                         selectedaxis[1] = i;
00206                         if (selectedaxis.length == 3)
00207                                 if (rows.get(i).zaxis.isSelected())
00208                                         selectedaxis[2] = i;
00209                         rows.remove(i);
00210                 }
00211 
00212                 dataUpdated = false;
00213                 buildRows(selectedaxis);
00214 
00215                 fireSelectedDataChanged("setData");
00216         }
00217 
00218         void updateSelectedData() {
00219                 if (dataUpdated)
00220                         return;
00221 
00222                 for (ParameterRow row : rows) {
00223                         boolean isaxis = row.xaxis.isSelected() || row.yaxis.isSelected() || row.zaxis.isSelected();
00224                         if (row._isNumber) {
00225                                 row.min.setEnabled(!isaxis);
00226                                 row.max.setEnabled(!isaxis);
00227                         } else
00228                                 row.list.setEnabled(!isaxis);
00229                         /*if (!isaxis)
00230                                 if (row._isNumber)
00231                                         row.name.setText(row._paramName + "=[" + row._kernelDoubleValues[row.min.getValue() - 1] + ","
00232                                                         + row._kernelDoubleValues[row.max.getValue() - 1] + "]");
00233                                 else
00234                                         row.name.setText(row._paramName + "={" + Array.cat(row.list.getSelectedValues()) + "}");
00235                         else
00236                                 row.name.setText(row._paramName);*/
00237                 }
00238 
00239                 _tmpselectedIndex = new int[_data.length];
00240                 _nbselected = 0;
00241                 _tmpselecteddata = new LinkedList<Object[]>();
00242                 for (int i = 0; i < _data.length; i++) {
00243                         boolean sel = true;
00244                         /*for (int j = 0; j < rows.length; j++) {
00245                                 ParameterRow row = rows[j];
00246                                 if (!row.xaxis.isSelected() && !row.yaxis.isSelected() && !row.zaxis.isSelected() && !row.check(_data[i][j]))
00247                                         sel = false;
00248                         }*/
00249 
00250                         if (sel) {
00251                                 _tmpselecteddata.add(_data[i]);
00252                                 _tmpselectedIndex[_nbselected] = i;
00253                                 _nbselected++;
00254                                 /*System.out.print("OK:");
00255                                 for (int j = 0; j < _tmpselecteddata.getLast().length; j++) 
00256                                         System.out.print(_tmpselecteddata.getLast()[j]+",");
00257                                 System.out.println("");*/
00258                         }
00259                 }
00260                 dataUpdated = true;
00261         }
00262 
00264         public void fireSelectedDataChanged(String from) {
00265                 System.out.println("fireSelectedDataChanged from " + from);
00266                 Object[][] sel = getSelectedFullData();
00267                 System.out.println("selected full data :");
00268                 System.out.println(Array.cat(_parametersNames));
00269                 if (sel.length > 0)
00270                         System.out.println(Array.cat(getSelectedFullData()));
00271 
00272                 sel = getSelectedProjectedData();
00273                 System.out.println("selected projected data :");
00274                 switch (_dimension) {
00275                 case 1:
00276                         System.out.println(Array.cat(new String[] { getSelectedXAxis() }));
00277                         break;
00278                 case 2:
00279                         System.out.println(Array.cat(new String[] { getSelectedXAxis(), getSelectedYAxis() }));
00280                         break;
00281                 case 3:
00282                         System.out.println(Array.cat(new String[] { getSelectedXAxis(), getSelectedYAxis(), getSelectedZAxis() }));
00283                         break;
00284                 }
00285                 if (sel.length > 0)
00286                         System.out.println(Array.cat(getSelectedProjectedData()));
00287 
00288         }
00289 
00291         public int[] getSelectedDataIndex() {
00292                 updateSelectedData();
00293                 _selectedindex = new int[_nbselected];
00294                 for (int i = 0; i < _nbselected; i++)
00295                         _selectedindex[i] = _tmpselectedIndex[i];
00296                 return _selectedindex;
00297         }
00298 
00300         public Object[][] getSelectedFullData() {
00301                 updateSelectedData();
00302                 _selecteddata = new Object[_tmpselecteddata.size()][_data[0].length];
00303                 for (int i = 0; i < _selecteddata.length; i++)
00304                         for (int j = 0; j < _selecteddata[i].length; j++)
00305                                 _selecteddata[i][j] = _tmpselecteddata.get(i)[j];
00306                 return _selecteddata;
00307         }
00308 
00310         public Object[][] getSelectedProjectedData() {
00311                 updateSelectedData();
00312                 int[] selextedaxis = getSelectedAxisIndex();
00313                 _selecteddata = new Object[_tmpselecteddata.size()][_dimension];
00314                 for (int i = 0; i < _selecteddata.length; i++)
00315                         for (int j = 0; j < _dimension; j++)
00316                                 _selecteddata[i][j] = _tmpselecteddata.get(i)[selextedaxis[j]];
00317                 return _selecteddata;
00318         }
00319 
00320         public int[] getSelectedAxisIndex() {
00321                 int[] selextedaxis = new int[_dimension];
00322                 updateSelectedData();
00323                 /*for (int i = 0; i < rows.length; i++) {
00324                         if (rows[i].xaxis.isSelected()) {
00325                                 //System.out.println("selextedaxis[0] =" + i);
00326                                 selextedaxis[0] = i;
00327                         }
00328                         if (rows[i].yaxis.isSelected()) {
00329                                 //System.out.println("selextedaxis[1] =" + i);
00330                                 selextedaxis[1] = i;
00331                         }
00332                         if (rows[i].zaxis.isSelected()) {
00333                                 //System.out.println("selextedaxis[2] =" + i);
00334                                 selextedaxis[2] = i;
00335                         }
00336                 }*/
00337                 return selextedaxis;
00338         }
00339 
00341         public String getSelectedXAxis() {
00342                 updateSelectedData();
00343                 for (ParameterRow row : rows)
00344                         if (row.xaxis.isSelected())
00345                                 return row._paramName;
00346                 return null;
00347         }
00348 
00350         public String getSelectedYAxis() {
00351                 updateSelectedData();
00352                 for (ParameterRow row : rows)
00353                         if (row.yaxis.isSelected())
00354                                 return row._paramName;
00355                 return null;
00356         }
00357 
00359         public String getSelectedZAxis() {
00360                 updateSelectedData();
00361                 for (ParameterRow row : rows)
00362                         if (row.zaxis.isSelected())
00363                                 return row._paramName;
00364                 return null;
00365         }
00366 
00367         static Object[] getColumn(int j, Object[][] mat) {
00368                 Object[] col = new Object[mat.length];
00369                 for (int i = 0; i < col.length; i++)
00370                         col[i] = mat[i][j];
00371                 return col;
00372         }
00373 
00374         class ParameterRow /*extends JPanel */{
00375 
00376                 //private static final long serialVersionUID = -7301434647336910071L;
00377 
00378                 String _paramName;
00379 
00380                 //JLabel name;
00381 
00382                 JRadioButton xaxis, yaxis, zaxis;
00383 
00384                 JComponent parameter;
00385 
00386                 JSlider min, max;
00387 
00388                 JCheckBox linkminmax;
00389 
00390                 JList list;
00391 
00392                 //Object[] _values;
00393 
00394                 Vector<Object> _kernelStringValues;
00395 
00396                 boolean _isNumber;
00397 
00398                 //double[] _dvalues;
00399 
00400                 double[] _kernelDoubleValues;
00401 
00402                 public ParameterRow(String paramName, Object[] values) {
00403                         _paramName = paramName;
00404                         _isNumber = Array.isDouble(values[0].toString());
00405 
00406                         if (!_isNumber) {
00407                                 _kernelStringValues = new Vector<Object>(values.length);
00408                                 for (int i = 0; i < values.length; i++)
00409                                         if (!_kernelStringValues.contains(values[i]))
00410                                                 _kernelStringValues.add(values[i]);
00411                         } else {
00412                                 Vector<Double> _tmpdvalues = new Vector<Double>(values.length);
00413                                 for (int i = 0; i < values.length; i++)
00414                                         if (!_tmpdvalues.contains(Double.valueOf(values[i].toString())))
00415                                                 _tmpdvalues.add(Double.valueOf(values[i].toString()));
00416 
00417                                 _kernelDoubleValues = new double[_tmpdvalues.size()];
00418                                 for (int i = 0; i < _kernelDoubleValues.length; i++)
00419                                         _kernelDoubleValues[i] = _tmpdvalues.get(i);
00420                         }
00421 
00422                         setLayout(new GridLayout(1, 2));
00423 
00424                         //name = new JLabel(_paramName);
00425                         //add(name, 0);
00426 
00427                         JPanel type = new JPanel(new BorderLayout());
00428 
00429                         JPanel XYZ = new JPanel(new GridLayout(_dimension, 1));
00430                         xaxis = new JRadioButton("X");
00431                         xaxis.addActionListener(new Action() {
00432                                 public void actionPerformed(ActionEvent e) {
00433                                         yaxis.setSelected(false);
00434                                         zaxis.setSelected(false);
00435                                         for (ParameterRow r : rows)
00436                                                 if (!r._paramName.equals(_paramName))
00437                                                         r.xaxis.setSelected(false);
00438                                         dataUpdated = false;
00439                                         fireSelectedDataChanged(_paramName + " xaxis");
00440                                 }
00441 
00442                                 public void setEnabled(boolean b) {
00443                                 }
00444 
00445                                 public void removePropertyChangeListener(PropertyChangeListener listener) {
00446                                 }
00447 
00448                                 public void putValue(String key, Object value) {
00449                                 }
00450 
00451                                 public boolean isEnabled() {
00452                                         return true;
00453                                 }
00454 
00455                                 public Object getValue(String key) {
00456                                         return null;
00457                                 }
00458 
00459                                 public void addPropertyChangeListener(PropertyChangeListener listener) {
00460                                 }
00461                         });
00462                         XYZ.add(xaxis);
00463                         yaxis = new JRadioButton("Y");
00464                         yaxis.addActionListener(new Action() {
00465                                 public void actionPerformed(ActionEvent e) {
00466                                         xaxis.setSelected(false);
00467                                         zaxis.setSelected(false);
00468                                         for (ParameterRow r : rows)
00469                                                 if (!r._paramName.equals(_paramName))
00470                                                         r.yaxis.setSelected(false);
00471                                         dataUpdated = false;
00472                                         fireSelectedDataChanged(_paramName + " yaxis");
00473 
00474                                 }
00475 
00476                                 public void setEnabled(boolean b) {
00477                                 }
00478 
00479                                 public void removePropertyChangeListener(PropertyChangeListener listener) {
00480                                 }
00481 
00482                                 public void putValue(String key, Object value) {
00483                                 }
00484 
00485                                 public boolean isEnabled() {
00486                                         return true;
00487                                 }
00488 
00489                                 public Object getValue(String key) {
00490                                         return null;
00491                                 }
00492 
00493                                 public void addPropertyChangeListener(PropertyChangeListener listener) {
00494                                 }
00495                         });
00496                         if (_dimension >= 2)
00497                                 XYZ.add(yaxis);
00498 
00499                         zaxis = new JRadioButton("Z");
00500                         zaxis.addActionListener(new Action() {
00501                                 public void actionPerformed(ActionEvent e) {
00502                                         xaxis.setSelected(false);
00503                                         yaxis.setSelected(false);
00504                                         for (ParameterRow r : rows)
00505                                                 if (!r._paramName.equals(_paramName))
00506                                                         r.zaxis.setSelected(false);
00507                                         dataUpdated = false;
00508                                         fireSelectedDataChanged(_paramName + " zaxis");
00509                                 }
00510 
00511                                 public void setEnabled(boolean b) {
00512                                 }
00513 
00514                                 public void removePropertyChangeListener(PropertyChangeListener listener) {
00515                                 }
00516 
00517                                 public void putValue(String key, Object value) {
00518                                 }
00519 
00520                                 public boolean isEnabled() {
00521                                         return true;
00522                                 }
00523 
00524                                 public Object getValue(String key) {
00525                                         return null;
00526                                 }
00527 
00528                                 public void addPropertyChangeListener(PropertyChangeListener listener) {
00529                                 }
00530                         });
00531                         if (_dimension == 3)
00532                                 XYZ.add(zaxis);
00533 
00534                         type.add(XYZ, BorderLayout.WEST);
00535 
00536                         if (_isNumber) {
00537                                 parameter = new JPanel();
00538                                 parameter.setLayout(new GridLayout(2, 1));
00539 
00540                                 min = new JSlider(1, _kernelDoubleValues.length, 1);
00541 
00542                                 min.setMinorTickSpacing(1);
00543                                 min.setSnapToTicks(true);
00544                                 min.setPaintTicks(true);
00545                                 max = new JSlider(1, _kernelDoubleValues.length, _kernelDoubleValues.length);
00546                                 max.setMinorTickSpacing(1);
00547                                 max.setSnapToTicks(true);
00548                                 max.setPaintTicks(true);
00549                                 min.addChangeListener(new ChangeListener() {
00550                                         public void stateChanged(ChangeEvent e) {
00551                                                 if (max.getValue() < min.getValue())
00552                                                         max.setValue(min.getValue());
00553                                                 dataUpdated = false;
00554                                                 fireSelectedDataChanged(_paramName + " min");
00555 
00556                                         }
00557                                 });
00558                                 max.addChangeListener(new ChangeListener() {
00559                                         public void stateChanged(ChangeEvent e) {
00560                                                 if (max.getValue() < min.getValue())
00561                                                         min.setValue(max.getValue());
00562                                                 dataUpdated = false;
00563                                                 fireSelectedDataChanged(_paramName + " max");
00564 
00565                                         }
00566                                 });
00567                                 parameter.add(min, 0);
00568                                 parameter.add(max, 1);
00569                         } else {
00570 
00571                                 list = new JList(_kernelStringValues);
00572                                 list.setSelectedIndices(buildIntSeq(0, _kernelStringValues.size() - 1));
00573                                 list.addListSelectionListener(new ListSelectionListener() {
00574                                         public void valueChanged(ListSelectionEvent e) {
00575                                                 dataUpdated = false;
00576                                                 fireSelectedDataChanged(_paramName + " list");
00577                                         }
00578                                 });
00579                                 parameter = new JScrollPane(list);
00580                         }
00581                         type.add(parameter, BorderLayout.CENTER);
00582                         add(type, 1);
00583 
00584                         setBorder(BorderFactory.createEtchedBorder());
00585                         setPreferredSize(new Dimension(400, 60));
00586 
00587                 }
00588 
00589                 int[] buildIntSeq(int min, int max) {
00590                         int[] seq = new int[max - min + 1];
00591                         for (int i = 0; i < seq.length; i++)
00592                                 seq[i] = min + i;
00593                         return seq;
00594                 }
00595 
00596                 boolean check(Object value) {
00597                         if (_isNumber) {
00598                                 double dval = Double.valueOf(value.toString());
00599                                 return (dval >= _kernelDoubleValues[min.getValue() - 1] && dval <= _kernelDoubleValues[max.getValue() - 1]);
00600                         } else {
00601                                 for (int i = 0; i < list.getSelectedIndices().length; i++) {
00602                                         if (_kernelStringValues.get(list.getSelectedIndices()[i]).equals(value))
00603                                                 return true;
00604                                 }
00605                                 return false;
00606                         }
00607                 }
00608 
00609         }
00610 
00611         public static void main(String[] args) {
00612                 final PlotPanel pp = new Plot3DPanel(PlotPanel.WEST);
00613                 pp.setPreferredSize(new Dimension(400, 400));
00614                 new FrameView(pp).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00615 
00616                 Object[][] data = { { 0, 0, 0, 0, "a0" }, { 1, 1, 1, 1, "a1" }, { 2, 2, 2, 2, "a2" }, { 3, 3, 3, 3, "a3" }, { 4, 3, 3, 3, "a3" }, { 5, 3, 3, 3, "a4" } };
00617 
00618                 DataSelectTable dsp = new DataSelectTable(data, 3, "x1", "x2", "x3", "x4", "x5") {
00619                         private static final long serialVersionUID = 1L;
00620 
00621                         @Override
00622                         public void fireSelectedDataChanged(String from) {
00623                                 super.fireSelectedDataChanged(from);
00624                                 pp.setAxisLabel(0, getSelectedXAxis());
00625                                 pp.setAxisLabel(1, getSelectedYAxis());
00626                                 pp.setAxisLabel(2, getSelectedZAxis());
00627 
00628                                 if (pp.getPlots().size() == 0)
00629                                         pp.addPlot("SCATTER", "data", pp.mapData(getSelectedProjectedData()));
00630                                 else {
00631                                         if (from.endsWith("axis")) {
00632                                                 pp.resetMapData();
00633                                                 pp.removeAllPlots();
00634                                                 pp.addPlot("SCATTER", "data", pp.mapData(getSelectedProjectedData()));
00635                                         } else
00636                                                 pp.getPlot(0).setData(pp.mapData(getSelectedProjectedData()));
00637                                 }
00638                                 //System.out.println(Array.cat(pp.getAxesScales()));
00639                         }
00640                 };
00641                 new FrameView(dsp).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00642 
00643                 /*try {
00644                         Thread.sleep(5000);
00645                 } catch (InterruptedException e) {
00646                         e.printStackTrace();
00647                 }
00648 
00649                 Object[][] data2 = { { 0, 0, 0, 0, "a0" }, { 1, 1, 1, 1, "a1" }, { 2, 2, 2, 2, "a2" }, { 3, 3, 3, 3, "a3" }, { 4, 3, 3, 3, "a3" },
00650                                 { 5, 3, 3, 3, "a4" }, { 5, 4, 3, 3, "a4" } };
00651                 dsp.setData(data2);*/
00652         }
00653 
00654 }

Generated on Wed Sep 5 21:44:01 2007 for jmathplot by  doxygen 1.5.1