Main Page | Packages | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MeasurementStep.java

Go to the documentation of this file.
00001 /*
00002  * MeasurementStep.java
00003  *
00004  * Copyright (C) 2005 Project SQUID, http://www.cs.helsinki.fi/group/squid/
00005  *
00006  * This file is part of Ikayaki.
00007  *
00008  * Ikayaki is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Ikayaki is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Ikayaki; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00021  */
00022 
00023 package ikayaki;
00024 
00025 import org.w3c.dom.Document;
00026 import org.w3c.dom.Element;
00027 import org.w3c.dom.NodeList;
00028 
00029 import javax.vecmath.Matrix3d;
00030 import javax.vecmath.Vector3d;
00031 import java.util.ArrayList;
00032 import java.util.Date;
00033 import java.util.Iterator;
00034 import java.util.List;
00035 
00036 import static ikayaki.MeasurementStep.State.*;
00037 
00048 public class MeasurementStep implements Iterable<MeasurementResult> {
00049 
00053     private final Project project;
00054 
00058     private State state = State.READY;
00059 
00064     private Date timestamp = null;
00065 
00070     private double stepValue = -1.0;
00071 
00075     private double mass = -1.0;
00076 
00080     private double volume = -1.0;
00081 
00086     private double susceptibility = -1.0;
00087 
00091     private final List<MeasurementResult> results = new ArrayList<MeasurementResult>();
00092 
00096     public MeasurementStep() {
00097         project = null;
00098     }
00099 
00105     public MeasurementStep(Project project) {
00106         this.project = project;
00107     }
00108 
00116     public MeasurementStep(Element element) {
00117         this(element, null);
00118     }
00119 
00128     public MeasurementStep(Element element, Project project) {
00129         if (element == null) {
00130             throw new NullPointerException();
00131         }
00132         this.project = project;
00133         String s;
00134 
00135         // verify tag name
00136         if (!element.getTagName().equals("step")) {
00137             throw new IllegalArgumentException("Invalid tag name: " + element.getTagName());
00138         }
00139         
00140         // get stepValue, mass, volume
00141         s = element.getAttribute("stepvalue");
00142         try {
00143             double stepValue = Double.parseDouble(s);
00144             if (element.getAttribute("done").equals("1")) {
00145                 if (stepValue < 0.0) {
00146                     stepValue = -1.0;
00147                 }
00148                 this.stepValue = stepValue;     // for completed steps, bypass the degausser limits
00149             } else {
00150                 setStepValue(stepValue);
00151             }
00152         } catch (NumberFormatException e) {
00153             throw new IllegalArgumentException("Invalid stepvalue: " + s, e);
00154         }
00155         s = element.getAttribute("mass");
00156         try {
00157             setMass(Double.parseDouble(s));
00158         } catch (NumberFormatException e) {
00159             throw new IllegalArgumentException("Invalid mass: " + s, e);
00160         }
00161         s = element.getAttribute("volume");
00162         try {
00163             setVolume(Double.parseDouble(s));
00164         } catch (NumberFormatException e) {
00165             throw new IllegalArgumentException("Invalid volume: " + s, e);
00166         }
00167         s = element.getAttribute("susceptibility");
00168         try {
00169             setSusceptibility(Double.parseDouble(s));
00170         } catch (NumberFormatException e) {
00171             throw new IllegalArgumentException("Invalid susceptibility: " + s, e);
00172         }
00173 
00174         // get results
00175         NodeList results = element.getElementsByTagName("result");
00176         for (int i = 0; i < results.getLength(); i++) {
00177             Element result = (Element) results.item(i);
00178             this.results.add(new MeasurementResult(result));
00179         }
00180 
00181         // get state, must be done after getting results
00182         if (element.getAttribute("done").equals("1")) {
00183             state = DONE;
00184         } else {
00185             state = READY;
00186         }
00187 
00188         // get timestamp, must be done after getting results
00189         s = element.getAttribute("timestamp");
00190         if (s.equals("")) {
00191             timestamp = null;
00192         } else {
00193             try {
00194                 timestamp = new Date(Long.parseLong(s));
00195             } catch (NumberFormatException e) {
00196                 throw new IllegalArgumentException("Invalid timestamp: " + s, e);
00197             }
00198         }
00199 
00200         // check that state, timestamp and results are consistent
00201         if (state.isDone()) {
00202             if (timestamp == null || this.results.size() == 0) {
00203                 throw new IllegalArgumentException("Inconsistent state");
00204             }
00205         } else {
00206             if (timestamp != null || this.results.size() > 0) {
00207                 throw new IllegalArgumentException("Inconsistent state");
00208             }
00209         }
00210 
00211         // finalize
00212         updateTransforms();
00213     }
00214 
00220     public synchronized Element getElement(Document document) {
00221         Element element = document.createElement("step");
00222 
00223         if (results.size() == 0) {
00224             element.setAttribute("done", "0");
00225             element.setAttribute("timestamp", "");
00226         } else {
00227             element.setAttribute("done", "1");
00228             element.setAttribute("timestamp", Long.toString(timestamp.getTime()));
00229         }
00230         element.setAttribute("stepvalue", Double.toString(stepValue));
00231         element.setAttribute("mass", Double.toString(mass));
00232         element.setAttribute("volume", Double.toString(volume));
00233         element.setAttribute("susceptibility", Double.toString(susceptibility));
00234 
00235         for (MeasurementResult result : results) {
00236             element.appendChild(result.getElement(document));
00237         }
00238 
00239         return element;
00240     }
00241 
00245     public void save() {
00246         if (project != null) {
00247             project.save();
00248         }
00249     }
00250 
00254     public synchronized Project getProject() {
00255         return project;
00256     }
00257 
00261     public synchronized State getState() {
00262         return state;
00263     }
00264 
00268     public synchronized Date getTimestamp() {
00269         if (!state.isDone()) {
00270             return null;
00271         }
00272         if (timestamp == null) {
00273             return null;
00274         } else {
00275             return (Date) timestamp.clone();
00276         }
00277     }
00278 
00283     public synchronized double getStepValue() {
00284         return stepValue;
00285     }
00286 
00295     public synchronized void setStepValue(double stepValue) {
00296         if (state != READY) {
00297             throw new IllegalStateException("Unable to set stepValue, state is: " + state);
00298         }
00299         if (stepValue < 0.0) {
00300             stepValue = -1.0;
00301         }
00302         if (getProject() != null && getProject().getType() == Project.Type.AF) {
00303 
00304             // positive values must be equal or greater to DegausserMinimumField
00305             if (stepValue > 0.0 && stepValue < Settings.getDegausserMinimumField()) {
00306                 stepValue = Settings.getDegausserMinimumField();
00307             }
00308 
00309             // there must not be more decimals than DegausserMinimumFieldIncrement allows
00310             if (stepValue > 0.0) {
00311                 double inc = Settings.getDegausserMinimumFieldIncrement();
00312                 stepValue = stepValue / inc;
00313                 stepValue = (int) (Math.round(stepValue)) * inc;
00314             }
00315 
00316             // the value must be less or equal to DegausserMaximumField
00317             stepValue = Math.min(stepValue, Settings.getDegausserMaximumField());
00318         }
00319         this.stepValue = stepValue;
00320         save();
00321     }
00322 
00327     public synchronized double getMass() {
00328         return mass;
00329     }
00330 
00334     public synchronized void setMass(double mass) {
00335         if (mass < 0.0) {
00336             mass = -1.0;
00337         }
00338         this.mass = mass;
00339         save();
00340     }
00341 
00346     public synchronized double getVolume() {
00347         return volume;
00348     }
00349 
00353     public synchronized void setVolume(double volume) {
00354         if (volume < 0.0) {
00355             volume = -1.0;
00356         }
00357         this.volume = volume;
00358         save();
00359     }
00360 
00365     public synchronized double getSusceptibility() {
00366         return susceptibility;
00367     }
00368 
00372     public synchronized void setSusceptibility(double susceptibility) {
00373         if (susceptibility < 0.0) {
00374             susceptibility = -1.0;
00375         }
00376         this.susceptibility = susceptibility;
00377         save();
00378     }
00379 
00384     protected synchronized void updateTransforms() {
00385         Matrix3d transform = null;
00386         if (project != null) {
00387             transform = project.getTransform();
00388         }
00389         for (MeasurementResult result : results) {
00390             result.applyFixes(this);
00391             result.setTransform(transform);
00392         }
00393     }
00394 
00398     public synchronized int getResults() {
00399         return results.size();
00400     }
00401 
00409     public synchronized MeasurementResult getResult(int index) {
00410         return results.get(index);
00411     }
00412 
00424     public synchronized void addResult(MeasurementResult result) {
00425         if (result == null) {
00426             throw new NullPointerException();
00427         }
00428         if (state.isDone()) {
00429             throw new IllegalStateException("Unable to add results, state is: " + state);
00430         }
00431 
00432         setMeasuring();
00433         if (results.size() == 0 && (getProject() == null || !getProject().isHolderCalibration())) {
00434             // holder calibration value for all except the holder calibration project itself
00435             MeasurementResult holder = Settings.getHolderCalibration();
00436             if (holder != null) {
00437                 results.add(holder);
00438             }
00439         }
00440         results.add(result);
00441         timestamp = new Date();
00442         updateTransforms();
00443         save();
00444     }
00445 
00451     public synchronized void setMeasuring() {
00452         if (state.isDone()) {
00453             throw new IllegalStateException("Unable set state to MEASURING, state is: " + state);
00454         }
00455         state = MEASURING;
00456         save();
00457     }
00458 
00464     public synchronized void setDone() {
00465         if (!state.isDone()) {
00466             // if the measurement was aborted before any steps were measured, return to an unmeasured state
00467             if (getResults() == 0) {
00468                 state = READY;
00469             } else {
00470                 state = DONE_RECENTLY;
00471             }
00472             updateTransforms();     // need to update NOISE fixes
00473             save();
00474         }
00475     }
00476 
00481     public synchronized Vector3d getHolder() {
00482         Vector3d v = new Vector3d();
00483         int count = 0;
00484         if (getProject() != null && getProject().isHolderCalibration()) {
00485             return v;
00486         }
00487         for (MeasurementResult result : results) {
00488             if (result.getType() != MeasurementResult.Type.HOLDER) {
00489                 continue;
00490             }
00491             // all rotations are assumed to be 0
00492             v.add(result.getRawVector());
00493             count++;
00494         }
00495         if (count > 0) {
00496             v.scale(1.0 / count);
00497         }
00498         return v;
00499     }
00500 
00505     public synchronized Vector3d getNoise() {
00506         Vector3d v = new Vector3d();
00507         int count = 0;
00508         for (MeasurementResult result : results) {
00509             if (result.getType() != MeasurementResult.Type.NOISE) {
00510                 continue;
00511             }
00512             // all rotations are assumed to be 0
00513             v.add(result.getRawVector());
00514             count++;
00515         }
00516         if (count > 0) {
00517             v.scale(1.0 / count);
00518         }
00519         return v;
00520     }
00521 
00525     public Iterator<MeasurementResult> iterator() {
00526         final MeasurementStep step = this;
00527 
00528         return new Iterator<MeasurementResult>() {
00529 
00530             private int next = 0;
00531 
00532             public boolean hasNext() {
00533                 return next < step.getResults();
00534             }
00535 
00536             public MeasurementResult next() {
00537                 return step.getResult(next++);
00538             }
00539 
00540             public void remove() {
00541                 throw new UnsupportedOperationException();
00542             }
00543         };
00544     }
00545 
00549     public enum State {
00550         READY(false), MEASURING(false), DONE_RECENTLY(true), DONE(true);
00551 
00552         private boolean done;
00553 
00554         private State(boolean done) {
00555             this.done = done;
00556         }
00557 
00561         public boolean isDone() {
00562             return done;
00563         }
00564     }
00565 }

Generated on Fri May 6 16:00:32 2005 for Squid by  doxygen 1.4.1