samer@0
|
1 /*
|
samer@0
|
2 * VVector.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2000, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 */
|
samer@0
|
11
|
samer@0
|
12 package samer.maths;
|
samer@0
|
13 import samer.core.*;
|
samer@0
|
14 import samer.core.util.*;
|
samer@0
|
15 import samer.tools.*;
|
samer@0
|
16 import java.awt.*;
|
samer@0
|
17 import java.awt.event.*;
|
samer@0
|
18 import java.util.*;
|
samer@0
|
19 import java.io.*;
|
samer@0
|
20 /**
|
samer@0
|
21 A Viewable Vec. The default viewer displays only
|
samer@0
|
22 the name and size of the vector, but the attached
|
samer@0
|
23 Agent allows creation of other types of viewer.
|
samer@0
|
24 */
|
samer@0
|
25
|
samer@0
|
26 public class VVector extends Viewable implements Vec, Agent, Saveable
|
samer@0
|
27 {
|
samer@0
|
28 Vec vec;
|
samer@0
|
29
|
samer@0
|
30 protected VVector() {}
|
samer@0
|
31
|
samer@0
|
32 public VVector(Node node, Vec v) {
|
samer@0
|
33 super(node); vec=v; setAgent(this);
|
samer@0
|
34 Shell.registerViewable(this);
|
samer@0
|
35 }
|
samer@0
|
36
|
samer@0
|
37 public VVector(Node node, double [] x) { this(node,new Vec.ForArray(x)); }
|
samer@0
|
38 public VVector(String nm, double [] x) { this(new Node(nm), x); }
|
samer@0
|
39 public VVector(String nm, int n) { this(new Node(nm), n); }
|
samer@0
|
40 public VVector(Node node, int n) {
|
samer@0
|
41 this(node,new Vec.ForArray(new double[n]));
|
samer@0
|
42 }
|
samer@0
|
43
|
samer@0
|
44 public void addSaver() { addAgent(new Saver(this,getNode())); }
|
samer@0
|
45
|
samer@0
|
46 // Vec implementation
|
samer@0
|
47 public Iterator iterator() { return vec.iterator(); }
|
samer@0
|
48 public int size() { return vec.size(); }
|
samer@0
|
49 public Mat mat() { return vec.mat(); }
|
samer@0
|
50 public double[] array() { return vec.array(); }
|
samer@0
|
51
|
samer@0
|
52 public Vec getVec() { return vec; }
|
samer@0
|
53 public Viewer getViewer()
|
samer@0
|
54 {
|
samer@0
|
55 BaseViewer vwr = new BaseViewer(this);
|
samer@0
|
56 StringBuffer buf=new StringBuffer();
|
samer@0
|
57
|
samer@0
|
58 buf.append(getLabel())
|
samer@0
|
59 .append(" (").append(vec.size())
|
samer@0
|
60 .append(")");
|
samer@0
|
61 vwr.setText(buf.toString());
|
samer@0
|
62
|
samer@0
|
63 return vwr;
|
samer@0
|
64 }
|
samer@0
|
65
|
samer@0
|
66 public void copyFrom(double[] y) { Mathx.copy(y,array()); changed(); }
|
samer@0
|
67 public void copyTo(double[] y) { Mathx.copy(array(),y); }
|
samer@0
|
68 // Saveable implementation
|
samer@0
|
69 public void save(OutputStream out) throws Exception {
|
samer@0
|
70 new ObjectOutputStream(out).writeObject(array());
|
samer@0
|
71 }
|
samer@0
|
72
|
samer@0
|
73 public void load(InputStream in) throws Exception {
|
samer@0
|
74 Object o=new ObjectInputStream(in).readObject();
|
samer@0
|
75 Mathx.copy((double [])o,array()); changed();
|
samer@0
|
76 }
|
samer@0
|
77
|
samer@0
|
78 /** Write the given Vec to a PrintWriter as one line of text,
|
samer@0
|
79 consisting of space delimited numbers. */
|
samer@0
|
80
|
samer@0
|
81 public void write(Writer w) { print(new PrintWriter(w)); }
|
samer@0
|
82 public void print(PrintWriter prn) {
|
samer@0
|
83 Vec.Iterator i=vec.iterator();
|
samer@0
|
84 prn.print(i.next());
|
samer@0
|
85 while (i.more()) {
|
samer@0
|
86 prn.print(' ');
|
samer@0
|
87 prn.print(i.next());
|
samer@0
|
88 }
|
samer@0
|
89 prn.println();
|
samer@0
|
90 prn.flush();
|
samer@0
|
91 }
|
samer@0
|
92
|
samer@0
|
93 /** Reads a line of numbers from the reader and stores in the Vec */
|
samer@0
|
94 public void read(Reader input) throws IOException
|
samer@0
|
95 {
|
samer@0
|
96 StreamTokenizer tok= new StreamTokenizer(new BufferedReader(input));
|
samer@0
|
97
|
samer@0
|
98 /*
|
samer@0
|
99 a) words are made from only +,-,.,e,E, or digits
|
samer@0
|
100 b) if other tokens may exist in a line, these are ignored
|
samer@0
|
101 c) if there is too much stuff on one line, the rest is discarded.
|
samer@0
|
102 d) if there aren't enough numbers, throw an exception.
|
samer@0
|
103 */
|
samer@0
|
104
|
samer@0
|
105 tok.resetSyntax();
|
samer@0
|
106 tok.wordChars('+','+');
|
samer@0
|
107 tok.wordChars('-','-');
|
samer@0
|
108 tok.wordChars('0','9');
|
samer@0
|
109 tok.wordChars('.','.');
|
samer@0
|
110 tok.wordChars('e','e');
|
samer@0
|
111 tok.wordChars('E','E');
|
samer@0
|
112 tok.commentChar('#');
|
samer@0
|
113 tok.commentChar(';');
|
samer@0
|
114 tok.commentChar('%');
|
samer@0
|
115 tok.whitespaceChars(0, ' ');
|
samer@0
|
116 tok.eolIsSignificant(true);
|
samer@0
|
117
|
samer@0
|
118 // Ignore initial empty lines
|
samer@0
|
119 while (tok.nextToken() == StreamTokenizer.TT_EOL);
|
samer@0
|
120 if (tok.ttype == StreamTokenizer.TT_EOF)
|
samer@0
|
121 throw new EOFException("EOF on vector read.");
|
samer@0
|
122
|
samer@0
|
123 double [] x=vec.array();
|
samer@0
|
124 int i=0;
|
samer@0
|
125
|
samer@0
|
126 // get first x.length words and convert to numbers
|
samer@0
|
127 do {
|
samer@0
|
128 if (tok.ttype==StreamTokenizer.TT_WORD)
|
samer@0
|
129 x[i++]=Double.parseDouble(tok.sval);
|
samer@0
|
130 } while (tok.nextToken()!=StreamTokenizer.TT_EOL && i<x.length);
|
samer@0
|
131 // !! what if EOF?
|
samer@0
|
132 if (i<(x.length-1)) throw new IOException("not enough numbers");
|
samer@0
|
133
|
samer@0
|
134 // now mop up rest of line
|
samer@0
|
135 while (tok.ttype!=StreamTokenizer.TT_EOL) tok.nextToken();
|
samer@0
|
136 changed();
|
samer@0
|
137 }
|
samer@0
|
138
|
samer@0
|
139 public void getCommands(Registry r) {
|
samer@0
|
140 r.add("zeros").add("negate").add("set").group();
|
samer@0
|
141 r.add("plotter")
|
samer@0
|
142 .add("image")
|
samer@0
|
143 .add("reshaped image")
|
samer@0
|
144 .add("trace")
|
samer@0
|
145 .add("image editor")
|
samer@0
|
146 .add("plotter editor")
|
samer@0
|
147 .add("multitrace");
|
samer@0
|
148 r.group();
|
samer@0
|
149 r.add("publish");
|
samer@0
|
150
|
samer@0
|
151 }
|
samer@0
|
152
|
samer@0
|
153 private void expose(Viewer v) { Shell.expose(v,"window"); }
|
samer@0
|
154
|
samer@0
|
155 public void execute(String cmd, Environment env) throws Exception
|
samer@0
|
156 {
|
samer@0
|
157 if (cmd.equals("zeros")) {
|
samer@0
|
158
|
samer@0
|
159 double [] x = vec.array();
|
samer@0
|
160 if (x!=null) Mathx.zero(x);
|
samer@0
|
161 else { // try using Mat interface instead
|
samer@0
|
162 Mat mat = vec.mat();
|
samer@0
|
163 if (mat!=null) for (int i=0; i<mat.width(); i++) mat.set(1,i,0);
|
samer@0
|
164 else throw new Exception("Vector inaccessible: "+getLabel());
|
samer@0
|
165 }
|
samer@0
|
166 changed();
|
samer@0
|
167
|
samer@0
|
168 } else if (cmd.equals("set")) {
|
samer@0
|
169
|
samer@0
|
170 double y=X._double(env.datum(),1);
|
samer@0
|
171 double [] x = vec.array();
|
samer@0
|
172 if (x!=null) Mathx.setAll(x,y);
|
samer@0
|
173 else { // try using Mat interface instead
|
samer@0
|
174 Mat mat = vec.mat();
|
samer@0
|
175 if (mat!=null) for (int i=0; i<mat.width(); i++) mat.set(1,i,y);
|
samer@0
|
176 else throw new Exception("Vector inaccessible: "+getLabel());
|
samer@0
|
177 }
|
samer@0
|
178 changed();
|
samer@0
|
179
|
samer@0
|
180 } else if (cmd.equals("negate")) {
|
samer@0
|
181
|
samer@0
|
182 double [] x = vec.array();
|
samer@0
|
183 if (x!=null) Mathx.negate(x);
|
samer@0
|
184 else { // try using Mat interface instead
|
samer@0
|
185 Mat mat = vec.mat();
|
samer@0
|
186 if (mat!=null) for (int i=0; i<mat.width(); i++) mat.set(1,i,-mat.get(1,i));
|
samer@0
|
187 else throw new Exception("Vector inaccessible: "+getLabel());
|
samer@0
|
188 }
|
samer@0
|
189 changed();
|
samer@0
|
190
|
samer@0
|
191 } else if (cmd.equals("plotter")) {
|
samer@0
|
192
|
samer@0
|
193 pushNode("plotter");
|
samer@0
|
194 expose(new VectorPlotter(this,getVec()));
|
samer@0
|
195 Shell.pop();
|
samer@0
|
196
|
samer@0
|
197 } else if (cmd.equals("plotter editor")) {
|
samer@0
|
198
|
samer@0
|
199 pushNode("editor.plotter");
|
samer@0
|
200 expose(new VectorEditor(this,getVec()));
|
samer@0
|
201 Shell.pop();
|
samer@0
|
202
|
samer@0
|
203 } else if (cmd.equals("image")) {
|
samer@0
|
204
|
samer@0
|
205 Node n=pushNode("image");
|
samer@0
|
206 expose(createVectorImage(n,vec.size(),1));
|
samer@0
|
207 Shell.pop();
|
samer@0
|
208
|
samer@0
|
209 } else if (cmd.equals("reshaped image")) {
|
samer@0
|
210
|
samer@0
|
211 Node n=pushNode("reshaped.image");
|
samer@0
|
212 int w=Shell.getInt("width",1);
|
samer@0
|
213 int h=Shell.getInt("height",vec.size());
|
samer@0
|
214 expose(createVectorImage( n, w, h));
|
samer@0
|
215 Shell.pop();
|
samer@0
|
216
|
samer@0
|
217 } else if (cmd.equals("image editor")) {
|
samer@0
|
218
|
samer@0
|
219 Node n=pushNode("editor.image");
|
samer@0
|
220
|
samer@0
|
221 final Shell.Window win = Shell.getWindow("window");
|
samer@0
|
222 final ImageViewer vwr = createVectorImage(n,vec.size(),1);
|
samer@0
|
223 final MatEditor editor = new MatEditor(mat(),vwr,this,vwr);
|
samer@0
|
224
|
samer@0
|
225 win.container().setLayout( new BorderLayout(6,6));
|
samer@0
|
226 win.container().add( vwr.getComponent(), "Center");
|
samer@0
|
227 // win.container().add( editor.setto.getViewer().getComponent(),"South");
|
samer@0
|
228 Shell.registerViewable(editor.setto);
|
samer@0
|
229 win.addWindowListener( new WindowAdapter() {
|
samer@0
|
230 public void windowClosing(WindowEvent e) {
|
samer@0
|
231 editor.detach();
|
samer@0
|
232 vwr.detach();
|
samer@0
|
233 win.dispose();
|
samer@0
|
234 }
|
samer@0
|
235 } );
|
samer@0
|
236 win.expose();
|
samer@0
|
237
|
samer@0
|
238 // vwr.exposeCommands(this);
|
samer@0
|
239
|
samer@0
|
240 Shell.pop();
|
samer@0
|
241
|
samer@0
|
242 } else if (cmd.equals("trace")) {
|
samer@0
|
243
|
samer@0
|
244 Node node=pushNode("trace");
|
samer@0
|
245 ImageSourceBase imgsrc=createImageSource(1,vec.size());
|
samer@0
|
246 expose(new ImageTrace(imgsrc,this));
|
samer@0
|
247 Shell.pop();
|
samer@0
|
248
|
samer@0
|
249 } else if (cmd.equals("multitrace")) {
|
samer@0
|
250
|
samer@0
|
251 Node node=pushNode("trace");
|
samer@0
|
252 expose(new VectorTraceObs(this,node));
|
samer@0
|
253 Shell.pop();
|
samer@0
|
254 } else if (cmd.equals("publish")) {
|
samer@0
|
255 Shell.put(X.string(env.datum(),node.fullName()),this);
|
samer@0
|
256 }
|
samer@0
|
257 }
|
samer@0
|
258
|
samer@0
|
259
|
samer@0
|
260 private Node pushNode(String nm) {
|
samer@0
|
261 Node n=new Node(nm,getNode());
|
samer@0
|
262 Shell.push(n);
|
samer@0
|
263 return n;
|
samer@0
|
264 }
|
samer@0
|
265
|
samer@0
|
266 private ImageSourceBase createImageSource(int w, int h)
|
samer@0
|
267 {
|
samer@0
|
268 // this chooses an ImageSource depending on
|
samer@0
|
269 // the capabilities of the Vec
|
samer@0
|
270 double [] array=array();
|
samer@0
|
271
|
samer@0
|
272 if (array!=null) {
|
samer@0
|
273 if (w>1) return new ArrayImageSource(array,w,h);
|
samer@0
|
274 else return new ArrayVImageSource(array);
|
samer@0
|
275 } else {
|
samer@0
|
276 return new IteratorImageSource(getVec(),w,h);
|
samer@0
|
277 }
|
samer@0
|
278 }
|
samer@0
|
279
|
samer@0
|
280 private ImageViewer createVectorImage( final Node n, int w, int h)
|
samer@0
|
281 {
|
samer@0
|
282
|
samer@0
|
283 /*
|
samer@0
|
284 The VImageViewer handles displaying the image of
|
samer@0
|
285 a supplied ImageSource, but this object handles
|
samer@0
|
286 scaling of the colour map to match the range of
|
samer@0
|
287 values in a Vec, accessed by iterator rather than
|
samer@0
|
288 array.
|
samer@0
|
289 */
|
samer@0
|
290 return new ImageViewer( createImageSource(w,h), this) {
|
samer@0
|
291 public void scale()
|
samer@0
|
292 {
|
samer@0
|
293 Vec.Iterator i=vec.iterator();
|
samer@0
|
294 double max, min, x;
|
samer@0
|
295
|
samer@0
|
296 min=max=i.next();
|
samer@0
|
297 while (i.more()) {
|
samer@0
|
298 x=i.next();
|
samer@0
|
299 if (x>max) max=x;
|
samer@0
|
300 if (x<min) min=x;
|
samer@0
|
301 }
|
samer@0
|
302
|
samer@0
|
303 getVMap().setDomain(min,max);
|
samer@0
|
304 getVMap().changed(this);
|
samer@0
|
305 }
|
samer@0
|
306 };
|
samer@0
|
307 }
|
samer@0
|
308 }
|
samer@0
|
309
|
samer@0
|
310
|
samer@0
|
311 class VectorTraceObs extends VectorTrace implements Observer {
|
samer@0
|
312 Observable obs;
|
samer@0
|
313 Node node;
|
samer@0
|
314
|
samer@0
|
315 VectorTraceObs(VVector v, Node n) {
|
samer@0
|
316 super(v);
|
samer@0
|
317 obs=v;
|
samer@0
|
318 node=n;
|
samer@0
|
319 }
|
samer@0
|
320
|
samer@0
|
321 public void attach() { super.attach(); obs.addObserver(this); }
|
samer@0
|
322 public void detach() { obs.deleteObserver(this); super.detach(); }
|
samer@0
|
323 public void update(Observable o, Object arg)
|
samer@0
|
324 {
|
samer@0
|
325 if (o==obs) {
|
samer@0
|
326 if (arg==Viewable.DISPOSING) {
|
samer@0
|
327 Shell.releaseViewer(this);
|
samer@0
|
328 } else {
|
samer@0
|
329 try { run(); }
|
samer@0
|
330 catch (Exception ex) {}
|
samer@0
|
331 }
|
samer@0
|
332 } else super.update(o,arg);
|
samer@0
|
333 }
|
samer@0
|
334 }
|