00001
00002
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.JLabel;
00021 import javax.swing.JList;
00022 import javax.swing.JPanel;
00023 import javax.swing.JRadioButton;
00024 import javax.swing.JScrollPane;
00025 import javax.swing.JSlider;
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
00031 import org.math.plot.utils.Array;
00032
00037 public class DataSelectPanel extends JPanel {
00038
00039 private static final long serialVersionUID = 419181752327223313L;
00040
00041 ParameterRow[] rows;
00042
00043 private Object[][] _data, _selecteddata;
00044
00045 private LinkedList<Object[]> _tmpselecteddata;
00046
00047 boolean dataUpdated = false;
00048
00049 private int[] _tmpselectedIndex;
00050
00051 private int _nbselected;
00052
00053 private int[] _selectedindex;
00054
00055 private String[] _parametersNames;
00056
00057
00058
00059 int _dimension;
00060
00061 public DataSelectPanel(Object[][] data, int dimension, String... parametersNames) {
00062 _data = data;
00063 _dimension = dimension;
00064
00065 _parametersNames = parametersNames;
00066
00067 if (_dimension > parametersNames.length)
00068 throw new IllegalArgumentException("Number of parameters must be > to dimension=" + _dimension);
00069
00070 setLayout(new GridLayout(_parametersNames.length , 1));
00071
00072
00073
00074
00075
00076
00077 if (_dimension == 1)
00078 buildRows(0);
00079 else if (_dimension == 2)
00080 buildRows(0, 1);
00081 else if (_dimension == 3)
00082 buildRows(0, 1, 2);
00083
00084 }
00085
00086 void buildRows(int... selectedaxis) {
00087 ButtonGroup xgrp = new ButtonGroup();
00088 ButtonGroup ygrp = new ButtonGroup();
00089 ButtonGroup zgrp = new ButtonGroup();
00090 rows = new ParameterRow[_parametersNames.length];
00091 for (int i = 0; i < _parametersNames.length; i++) {
00092 rows[i] = new ParameterRow(_parametersNames[i], getColumn(i, _data));
00093
00094 rows[i].xaxis.setSelected(selectedaxis[0] == i);
00095 if (selectedaxis.length >= 2)
00096 rows[i].yaxis.setSelected(selectedaxis[1] == i);
00097 if (selectedaxis.length == 3)
00098 rows[i].zaxis.setSelected(selectedaxis[2] == i);
00099
00100 xgrp.add(rows[i].xaxis);
00101 ygrp.add(rows[i].yaxis);
00102 zgrp.add(rows[i].zaxis);
00103
00104 add(rows[i]);
00105 }
00106 updateSelectedData();
00107 }
00108
00109 public void setData(Object[][] data) {
00110 if (data[0].length != _data[0].length)
00111 throw new IllegalArgumentException("new data dimension is not consistent with previous one.");
00112 _data = data;
00113
00114 int[] selectedaxis = new int[_dimension];
00115 for (int i = 0; i < rows.length; i++) {
00116 if (rows[i].xaxis.isSelected())
00117 selectedaxis[0] = i;
00118 if (selectedaxis.length >= 2)
00119 if (rows[i].yaxis.isSelected())
00120 selectedaxis[1] = i;
00121 if (selectedaxis.length == 3)
00122 if (rows[i].zaxis.isSelected())
00123 selectedaxis[2] = i;
00124 remove(rows[i]);
00125 }
00126
00127 dataUpdated = false;
00128 buildRows(selectedaxis);
00129
00130 fireSelectedDataChanged("setData");
00131 }
00132
00133 void updateSelectedData() {
00134 if (dataUpdated)
00135 return;
00136
00137 for (ParameterRow row : rows) {
00138 boolean isaxis = row.xaxis.isSelected() || row.yaxis.isSelected() || row.zaxis.isSelected();
00139 if (row._isNumber) {
00140 row.min.setEnabled(!isaxis);
00141 row.max.setEnabled(!isaxis);
00142 } else
00143 row.list.setEnabled(!isaxis);
00144 if (!isaxis)
00145 if (row._isNumber)
00146 row.name.setText(row._paramName + "=[" + row._kernelDoubleValues[row.min.getValue() - 1] + ","
00147 + row._kernelDoubleValues[row.max.getValue() - 1] + "]");
00148 else
00149 row.name.setText(row._paramName + "={" + Array.cat(row.list.getSelectedValues()) + "}");
00150 else
00151 row.name.setText(row._paramName);
00152 }
00153
00154 _tmpselectedIndex = new int[_data.length];
00155 _nbselected = 0;
00156 _tmpselecteddata = new LinkedList<Object[]>();
00157 for (int i = 0; i < _data.length; i++) {
00158 boolean sel = true;
00159 for (int j = 0; j < rows.length; j++) {
00160 ParameterRow row = rows[j];
00161 if (!row.xaxis.isSelected() && !row.yaxis.isSelected() && !row.zaxis.isSelected() && !row.check(_data[i][j]))
00162 sel = false;
00163 }
00164
00165 if (sel) {
00166 _tmpselecteddata.add(_data[i]);
00167 _tmpselectedIndex[_nbselected] = i;
00168 _nbselected++;
00169
00170
00171
00172
00173 }
00174 }
00175 dataUpdated = true;
00176 }
00177
00179 public void fireSelectedDataChanged(String from) {
00180 System.out.println("fireSelectedDataChanged from " + from);
00181 Object[][] sel = getSelectedFullData();
00182 System.out.println("selected full data :");
00183 System.out.println(Array.cat(_parametersNames));
00184 if (sel.length > 0)
00185 System.out.println(Array.cat(getSelectedFullData()));
00186
00187 sel = getSelectedProjectedData();
00188 System.out.println("selected projected data :");
00189 switch (_dimension) {
00190 case 1:
00191 System.out.println(Array.cat(new String[] { getSelectedXAxis() }));
00192 break;
00193 case 2:
00194 System.out.println(Array.cat(new String[] { getSelectedXAxis(), getSelectedYAxis() }));
00195 break;
00196 case 3:
00197 System.out.println(Array.cat(new String[] { getSelectedXAxis(), getSelectedYAxis(), getSelectedZAxis() }));
00198 break;
00199 }
00200 if (sel.length > 0)
00201 System.out.println(Array.cat(getSelectedProjectedData()));
00202
00203 }
00204
00206 public int[] getSelectedDataIndex() {
00207 updateSelectedData();
00208 _selectedindex = new int[_nbselected];
00209 for (int i = 0; i < _nbselected; i++)
00210 _selectedindex[i] = _tmpselectedIndex[i];
00211 return _selectedindex;
00212 }
00213
00215 public Object[][] getSelectedFullData() {
00216 updateSelectedData();
00217 _selecteddata = new Object[_tmpselecteddata.size()][_data[0].length];
00218 for (int i = 0; i < _selecteddata.length; i++)
00219 for (int j = 0; j < _selecteddata[i].length; j++)
00220 _selecteddata[i][j] = _tmpselecteddata.get(i)[j];
00221 return _selecteddata;
00222 }
00223
00225 public Object[][] getSelectedProjectedData() {
00226 updateSelectedData();
00227 int[] selextedaxis = getSelectedAxisIndex();
00228 _selecteddata = new Object[_tmpselecteddata.size()][_dimension];
00229 for (int i = 0; i < _selecteddata.length; i++)
00230 for (int j = 0; j < _dimension; j++)
00231 _selecteddata[i][j] = _tmpselecteddata.get(i)[selextedaxis[j]];
00232 return _selecteddata;
00233 }
00234
00235 public int[] getSelectedAxisIndex() {
00236 int[] selextedaxis = new int[_dimension];
00237 updateSelectedData();
00238 for (int i = 0; i < rows.length; i++) {
00239 if (rows[i].xaxis.isSelected()) {
00240
00241 selextedaxis[0] = i;
00242 }
00243 if (rows[i].yaxis.isSelected()) {
00244
00245 selextedaxis[1] = i;
00246 }
00247 if (rows[i].zaxis.isSelected()) {
00248
00249 selextedaxis[2] = i;
00250 }
00251 }
00252 return selextedaxis;
00253 }
00254
00256 public String getSelectedXAxis() {
00257 updateSelectedData();
00258 for (ParameterRow row : rows)
00259 if (row.xaxis.isSelected())
00260 return row._paramName;
00261 return null;
00262 }
00263
00265 public String getSelectedYAxis() {
00266 updateSelectedData();
00267 for (ParameterRow row : rows)
00268 if (row.yaxis.isSelected())
00269 return row._paramName;
00270 return null;
00271 }
00272
00274 public String getSelectedZAxis() {
00275 updateSelectedData();
00276 for (ParameterRow row : rows)
00277 if (row.zaxis.isSelected())
00278 return row._paramName;
00279 return null;
00280 }
00281
00282 static Object[] getColumn(int j, Object[][] mat) {
00283 Object[] col = new Object[mat.length];
00284 for (int i = 0; i < col.length; i++)
00285 col[i] = mat[i][j];
00286 return col;
00287 }
00288
00289 class ParameterRow extends JPanel {
00290
00291 private static final long serialVersionUID = -7301434647336910071L;
00292
00293 String _paramName;
00294
00295 JLabel name;
00296
00297 JRadioButton xaxis, yaxis, zaxis;
00298
00299 JComponent parameter;
00300
00301 JSlider min, max;
00302
00303 JCheckBox linkminmax;
00304
00305 JList list;
00306
00307
00308
00309 Vector<Object> _kernelStringValues;
00310
00311 boolean _isNumber;
00312
00313
00314
00315 double[] _kernelDoubleValues;
00316
00317 public ParameterRow(String paramName, Object[] values) {
00318 _paramName = paramName;
00319 _isNumber = Array.isDouble(values[0].toString());
00320
00321 if (!_isNumber) {
00322 _kernelStringValues = new Vector<Object>(values.length);
00323 for (int i = 0; i < values.length; i++)
00324 if (!_kernelStringValues.contains(values[i]))
00325 _kernelStringValues.add(values[i]);
00326 } else {
00327 Vector<Double> _tmpdvalues = new Vector<Double>(values.length);
00328 for (int i = 0; i < values.length; i++)
00329 if (!_tmpdvalues.contains(Double.valueOf(values[i].toString())))
00330 _tmpdvalues.add(Double.valueOf(values[i].toString()));
00331
00332 _kernelDoubleValues = new double[_tmpdvalues.size()];
00333 for (int i = 0; i < _kernelDoubleValues.length; i++)
00334 _kernelDoubleValues[i] = _tmpdvalues.get(i);
00335 }
00336
00337 setLayout(new GridLayout(1, 2));
00338
00339 name = new JLabel(_paramName);
00340 add(name, 0);
00341
00342 JPanel type = new JPanel(new BorderLayout());
00343
00344 JPanel XYZ = new JPanel(new GridLayout(_dimension, 1));
00345 xaxis = new JRadioButton("X");
00346 xaxis.addActionListener(new Action() {
00347 public void actionPerformed(ActionEvent e) {
00348 yaxis.setSelected(false);
00349 zaxis.setSelected(false);
00350 for (ParameterRow r : rows)
00351 if (!r._paramName.equals(_paramName))
00352 r.xaxis.setSelected(false);
00353 dataUpdated = false;
00354 fireSelectedDataChanged(_paramName + " xaxis");
00355 }
00356
00357 public void setEnabled(boolean b) {
00358 }
00359
00360 public void removePropertyChangeListener(PropertyChangeListener listener) {
00361 }
00362
00363 public void putValue(String key, Object value) {
00364 }
00365
00366 public boolean isEnabled() {
00367 return true;
00368 }
00369
00370 public Object getValue(String key) {
00371 return null;
00372 }
00373
00374 public void addPropertyChangeListener(PropertyChangeListener listener) {
00375 }
00376 });
00377 XYZ.add(xaxis);
00378 yaxis = new JRadioButton("Y");
00379 yaxis.addActionListener(new Action() {
00380 public void actionPerformed(ActionEvent e) {
00381 xaxis.setSelected(false);
00382 zaxis.setSelected(false);
00383 for (ParameterRow r : rows)
00384 if (!r._paramName.equals(_paramName))
00385 r.yaxis.setSelected(false);
00386 dataUpdated = false;
00387 fireSelectedDataChanged(_paramName + " yaxis");
00388
00389 }
00390
00391 public void setEnabled(boolean b) {
00392 }
00393
00394 public void removePropertyChangeListener(PropertyChangeListener listener) {
00395 }
00396
00397 public void putValue(String key, Object value) {
00398 }
00399
00400 public boolean isEnabled() {
00401 return true;
00402 }
00403
00404 public Object getValue(String key) {
00405 return null;
00406 }
00407
00408 public void addPropertyChangeListener(PropertyChangeListener listener) {
00409 }
00410 });
00411 if (_dimension >= 2)
00412 XYZ.add(yaxis);
00413
00414 zaxis = new JRadioButton("Z");
00415 zaxis.addActionListener(new Action() {
00416 public void actionPerformed(ActionEvent e) {
00417 xaxis.setSelected(false);
00418 yaxis.setSelected(false);
00419 for (ParameterRow r : rows)
00420 if (!r._paramName.equals(_paramName))
00421 r.zaxis.setSelected(false);
00422 dataUpdated = false;
00423 fireSelectedDataChanged(_paramName + " zaxis");
00424 }
00425
00426 public void setEnabled(boolean b) {
00427 }
00428
00429 public void removePropertyChangeListener(PropertyChangeListener listener) {
00430 }
00431
00432 public void putValue(String key, Object value) {
00433 }
00434
00435 public boolean isEnabled() {
00436 return true;
00437 }
00438
00439 public Object getValue(String key) {
00440 return null;
00441 }
00442
00443 public void addPropertyChangeListener(PropertyChangeListener listener) {
00444 }
00445 });
00446 if (_dimension == 3)
00447 XYZ.add(zaxis);
00448
00449 type.add(XYZ, BorderLayout.WEST);
00450
00451 if (_isNumber) {
00452 parameter = new JPanel();
00453 parameter.setLayout(new GridLayout(2, 1));
00454
00455 min = new JSlider(1, _kernelDoubleValues.length, 1);
00456
00457 min.setMinorTickSpacing(1);
00458 min.setSnapToTicks(true);
00459 min.setPaintTicks(true);
00460 max = new JSlider(1, _kernelDoubleValues.length, _kernelDoubleValues.length);
00461 max.setMinorTickSpacing(1);
00462 max.setSnapToTicks(true);
00463 max.setPaintTicks(true);
00464 min.addChangeListener(new ChangeListener() {
00465 public void stateChanged(ChangeEvent e) {
00466 if (max.getValue() < min.getValue())
00467 max.setValue(min.getValue());
00468 dataUpdated = false;
00469 fireSelectedDataChanged(_paramName + " min");
00470
00471 }
00472 });
00473 max.addChangeListener(new ChangeListener() {
00474 public void stateChanged(ChangeEvent e) {
00475 if (max.getValue() < min.getValue())
00476 min.setValue(max.getValue());
00477 dataUpdated = false;
00478 fireSelectedDataChanged(_paramName + " max");
00479
00480 }
00481 });
00482 parameter.add(min, 0);
00483 parameter.add(max, 1);
00484 } else {
00485
00486 list = new JList(_kernelStringValues);
00487 list.setSelectedIndices(buildIntSeq(0, _kernelStringValues.size() - 1));
00488 list.addListSelectionListener(new ListSelectionListener() {
00489 public void valueChanged(ListSelectionEvent e) {
00490 dataUpdated = false;
00491 fireSelectedDataChanged(_paramName + " list");
00492 }
00493 });
00494 parameter = new JScrollPane(list);
00495 }
00496 type.add(parameter, BorderLayout.CENTER);
00497 add(type, 1);
00498
00499 setBorder(BorderFactory.createEtchedBorder());
00500 setPreferredSize(new Dimension(400, 60));
00501
00502 }
00503
00504 int[] buildIntSeq(int min, int max) {
00505 int[] seq = new int[max - min + 1];
00506 for (int i = 0; i < seq.length; i++)
00507 seq[i] = min + i;
00508 return seq;
00509 }
00510
00511 boolean check(Object value) {
00512 if (_isNumber) {
00513 double dval = Double.valueOf(value.toString());
00514 return (dval >= _kernelDoubleValues[min.getValue() - 1] && dval <= _kernelDoubleValues[max.getValue() - 1]);
00515 } else {
00516 for (int i = 0; i < list.getSelectedIndices().length; i++) {
00517 if (_kernelStringValues.get(list.getSelectedIndices()[i]).equals(value))
00518 return true;
00519 }
00520 return false;
00521 }
00522 }
00523
00524 }
00525
00526 public static void main(String[] args) {
00527 final PlotPanel pp = new Plot3DPanel(PlotPanel.WEST);
00528 pp.setPreferredSize(new Dimension(400, 400));
00529 new FrameView(pp).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00530
00531 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" } };
00532
00533 DataSelectPanel dsp = new DataSelectPanel(data, 3, "x1", "x2", "x3", "x4", "x5") {
00534 private static final long serialVersionUID = 1L;
00535
00536 @Override
00537 public void fireSelectedDataChanged(String from) {
00538 super.fireSelectedDataChanged(from);
00539 pp.setAxisLabel(0, getSelectedXAxis());
00540 pp.setAxisLabel(1, getSelectedYAxis());
00541 pp.setAxisLabel(2, getSelectedZAxis());
00542
00543 if (pp.getPlots().size() == 0)
00544 pp.addPlot("SCATTER", "data", pp.mapData(getSelectedProjectedData()));
00545 else {
00546 if (from.endsWith("axis")) {
00547 pp.resetMapData();
00548 pp.removeAllPlots();
00549 pp.addPlot("SCATTER", "data", pp.mapData(getSelectedProjectedData()));
00550 } else
00551 pp.getPlot(0).setData(pp.mapData(getSelectedProjectedData()));
00552 }
00553
00554 }
00555 };
00556 new FrameView(dsp).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 }
00568
00569 }