001/** 002 Create and return a window containing a 2D XY type chart plotting the specified data. 003 The window returned is initially hidden so that the user can customize the chart if 004 desired. To show the window, call the "setVisible(true)" method on the returned window 005 object. 006 007 @method PlotXYWindow plotXY(windowTitle, xArr1,yArr1,xArr2,yArr2,...) 008 @method PlotXYWindow plotXY(windowTitle, xList1,yList1,xList2,yList2,...) 009 @method PlotXYWindow plotXY(windowTitle, xVector1,yVector1,xVector2,yVector2,...) 010 @method PlotXYWindow plotXY(windowTitle, xDim, yDim, pointStr1,pointStr2,...) 011 @method PlotXYWindow plotXY(windowTitle, pointStr1,pointStr2,...) 012 */ 013package geomss.app.GeomSSCommands; 014 015import bsh.*; 016import geomss.geom.GeomPoint; 017import geomss.geom.GeomVector; 018import geomss.geom.PointString; 019import geomss.ui.PlotXYWindow; 020import jahuwaldt.js.datareader.ArrayParam; 021import jahuwaldt.js.datareader.DataCase; 022import jahuwaldt.js.datareader.DataSet; 023import jahuwaldt.js.param.Parameter; 024import java.util.HashMap; 025import java.util.List; 026import javax.measure.quantity.Dimensionless; 027import javax.measure.quantity.Length; 028import javax.measure.unit.Unit; 029 030public class plotXY { 031 032 public static String usage() { 033 return "usage: plotXY(windowTitle, xData1,yData1,xData2,yData2,...);"; 034 } 035 036 /** 037 * Implement plotXY( String windowTitle, double[]... arrayVarArg ) command. This 038 * version plots a list of pairs of Java arrays of doubles. 039 */ 040 public static PlotXYWindow invoke(Interpreter env, CallStack callstack, 041 String windowTitle, double[]... arrayVarArg) { 042 043 int numCols = arrayVarArg.length; 044 if (numCols % 2 != 0) 045 throw new IllegalArgumentException("X-Y data must be provided in pairs of arrays."); 046 int numCases = numCols / 2; 047 048 DataSet data = DataSet.newInstance(windowTitle); 049 for (int i = 0; i < numCols; ++i) { 050 int caseNum = i / 2 + 1; 051 double[] xData = arrayVarArg[i++]; 052 double[] yData = arrayVarArg[i]; 053 ArrayParam xArr = ArrayParam.valueOf("X", Dimensionless.UNIT, xData); 054 ArrayParam yArr = ArrayParam.valueOf("Y", Dimensionless.UNIT, yData); 055 DataCase aCase = DataCase.newInstance("Case #" + (numCases > 1 ? String.valueOf(caseNum) : "")); 056 aCase.add(xArr); 057 aCase.add(yArr); 058 data.add(aCase); 059 } 060 061 PlotXYWindow window = new PlotXYWindow(windowTitle, data); 062 return window; 063 } 064 065 /** 066 * Implement plotXY( String windowTitle, List... listVarArg ) command. This version 067 * plots a list of pairs of lists of Double or Parameter or GeomPoint or combinations. 068 */ 069 public static PlotXYWindow invoke(Interpreter env, CallStack callstack, 070 String windowTitle, List... listVarArg) { 071 072 int numCols = listVarArg.length; 073 if (numCols % 2 != 0) 074 throw new IllegalArgumentException("X-Y data must be provided in pairs of lists."); 075 int numCases = numCols / 2; 076 077 DataSet data = DataSet.newInstance(windowTitle); 078 for (int i = 0; i < numCols; ++i) { 079 int caseNum = i / 2 + 1; 080 List xData = listVarArg[i++]; 081 List yData = listVarArg[i]; 082 ArrayParam xArr = list2ArrayParam("X", xData); 083 ArrayParam yArr = list2ArrayParam("Y", yData); 084 DataCase aCase = DataCase.newInstance("Case #" + (numCases > 1 ? String.valueOf(caseNum) : "")); 085 aCase.add(xArr); 086 aCase.add(yArr); 087 data.add(aCase); 088 } 089 090 PlotXYWindow window = new PlotXYWindow(windowTitle, data); 091 return window; 092 } 093 094 /** 095 * Return true if the supplied list contains only Number objects. 096 */ 097 private static boolean isNumberList(List data) { 098 int size = data.size(); 099 for (int i = 0; i < size; ++i) { 100 if (!(data.get(i) instanceof Number)) 101 return false; 102 } 103 return true; 104 } 105 106 /** 107 * Return true if the supplied list contains only Parameter objects. 108 */ 109 private static boolean isParameterList(List data) { 110 int size = data.size(); 111 for (int i = 0; i < size; ++i) { 112 if (!(data.get(i) instanceof Parameter)) 113 return false; 114 } 115 return true; 116 } 117 118 /** 119 * Return true if the supplied list contains only GeomPoint objects. 120 */ 121 private static boolean isPointList(List data) { 122 int size = data.size(); 123 for (int i = 0; i < size; ++i) { 124 if (!(data.get(i) instanceof GeomPoint)) 125 return false; 126 } 127 return true; 128 } 129 130 /** 131 * Convert the input list of data into an ArrayParam object if possible. 132 */ 133 private static ArrayParam list2ArrayParam(String name, List data) { 134 if (isNumberList(data)) { 135 int size = data.size(); 136 double[] arr = new double[size]; 137 for (int i = size - 1; i >= 0; --i) 138 arr[i] = ((Number)data.get(i)).doubleValue(); 139 return ArrayParam.valueOf(name, Dimensionless.UNIT, arr); 140 141 } else if (isParameterList(data)) { 142 Unit unit = ((Parameter)data.get(0)).getUnit(); 143 int size = data.size(); 144 double[] arr = new double[size]; 145 for (int i = size - 1; i >= 0; --i) { 146 arr[i] = ((Parameter)data.get(i)).getValue(unit); 147 } 148 return ArrayParam.valueOf(name, unit, arr); 149 150 } else if (isPointList(data)) { 151 // Assume a 1D point (well, assume the X value is to be plotted anyway). 152 Unit unit = ((GeomPoint)data.get(0)).getUnit(); 153 int size = data.size(); 154 double[] arr = new double[size]; 155 for (int i = size - 1; i >= 0; --i) { 156 arr[i] = ((GeomPoint)data.get(i)).getValue(0, unit); 157 } 158 return ArrayParam.valueOf(name, unit, arr); 159 160 } 161 throw new IllegalArgumentException("Unknown data type in list."); 162 } 163 164 /** 165 * Implement plotXY( String windowTitle, GeomVector... vectorVarArg ) command. This 166 * version plots a list of pairs of GeomVector objects. 167 */ 168 public static PlotXYWindow invoke(Interpreter env, CallStack callstack, 169 String windowTitle, GeomVector... vectorVarArg) { 170 171 int numCols = vectorVarArg.length; 172 if (numCols % 2 != 0) 173 throw new IllegalArgumentException("X-Y data must be provided in pairs of vectors."); 174 int numCases = numCols / 2; 175 176 DataSet data = DataSet.newInstance(windowTitle); 177 for (int i = 0; i < numCols; ++i) { 178 int caseNum = i / 2 + 1; 179 GeomVector xData = vectorVarArg[i++]; 180 GeomVector yData = vectorVarArg[i]; 181 182 int size = xData.getPhyDimension(); 183 if (size < 1) 184 throw new IllegalArgumentException("Empty vector provided for pair #" + caseNum); 185 if (yData.getPhyDimension() != size) 186 throw new IllegalArgumentException("Vectors are different dimensions for pair #" + caseNum); 187 188 Unit xUnit = xData.getUnit(); 189 Unit yUnit = yData.getUnit(); 190 double[] x = new double[size]; 191 double[] y = new double[size]; 192 for (int j = size - 1; j >= 0; --j) { 193 x[j] = xData.getValue(j); 194 y[j] = yData.getValue(j); 195 } 196 197 String name = xData.getName(); 198 name = (name == null ? "X" : name); 199 ArrayParam xArr = ArrayParam.valueOf(name, xUnit, x); 200 name = yData.getName(); 201 name = (name == null ? "Y" : name); 202 ArrayParam yArr = ArrayParam.valueOf(name, yUnit, y); 203 DataCase aCase = DataCase.newInstance(name); 204 aCase.add(xArr); 205 aCase.add(yArr); 206 data.add(aCase); 207 } 208 209 PlotXYWindow window = new PlotXYWindow(windowTitle, data); 210 return window; 211 } 212 213 private static final HashMap<Integer, String> DIM_MAP; 214 215 static { 216 DIM_MAP = new HashMap(); 217 DIM_MAP.put(0, "X"); 218 DIM_MAP.put(1, "Y"); 219 DIM_MAP.put(2, "Z"); 220 } 221 222 /** 223 * Implement plotXY( String windowTitle, int xDim, int yDim, GeomVector... 224 * pointStrVarArg ) command. This version plots the specified dimensions of a list 225 * PointString objects each containing points with at least max(xDim,yDim) physical 226 * dimensions. 227 */ 228 public static PlotXYWindow invoke(Interpreter env, CallStack callstack, 229 String windowTitle, int xDim, int yDim, PointString... pointStrVarArg) { 230 231 int numCols = pointStrVarArg.length; 232 int minDim = Math.max(xDim, yDim); 233 234 DataSet data = DataSet.newInstance(windowTitle); 235 for (int i = 0; i < numCols; ++i) { 236 PointString pnts = pointStrVarArg[i]; 237 238 int size = pnts.size(); 239 if (size < 1) 240 throw new IllegalArgumentException("Empty PointString provided for string #" + (i + 1)); 241 if (pnts.getPhyDimension() < minDim) 242 throw new IllegalArgumentException("Dimensions to small for PointString #" + (i + 1)); 243 244 Unit unit = pnts.getUnit(); 245 double[] x = new double[size]; 246 double[] y = new double[size]; 247 for (int j = 0; j < size; ++j) { 248 GeomPoint pnt = (GeomPoint)pnts.get(j); 249 x[j] = pnt.getValue(xDim, unit); 250 y[j] = pnt.getValue(yDim, unit); 251 } 252 253 String label = DIM_MAP.get(xDim); 254 ArrayParam xArr = ArrayParam.valueOf((label == null ? "X" : label), unit, x); 255 label = DIM_MAP.get(yDim); 256 ArrayParam yArr = ArrayParam.valueOf((label == null ? "Y" : label), unit, y); 257 String caseName = pnts.getName(); 258 caseName = (caseName == null ? "Case #" + (i + 1) : caseName); 259 DataCase aCase = DataCase.newInstance(caseName); 260 aCase.add(xArr); 261 aCase.add(yArr); 262 data.add(aCase); 263 } 264 265 PlotXYWindow window = new PlotXYWindow(windowTitle, data); 266 return window; 267 } 268 269 /** 270 * Implement plotXY( String windowTitle, GeomVector... pointStrVarArg ) command. This 271 * version plots 2D points from a list PointString objects. 272 */ 273 public static PlotXYWindow invoke(Interpreter env, CallStack callstack, 274 String windowTitle, PointString... pointStrVarArg) { 275 return invoke(env, callstack, windowTitle, GeomPoint.X, GeomPoint.Y, pointStrVarArg); 276 } 277}