001/* Plot sequences. 002 003 @Copyright (c) 1998-2014 The Regents of the University of California. 004 All rights reserved. 005 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the 009 above copyright notice and the following two paragraphs appear in all 010 copies of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION 2 026 COPYRIGHTENDKEY 027 */ 028package ptolemy.actor.lib.gui; 029 030import ptolemy.actor.TypedIOPort; 031import ptolemy.actor.lib.SequenceActor; 032import ptolemy.data.DoubleToken; 033import ptolemy.data.IntToken; 034import ptolemy.data.expr.Parameter; 035import ptolemy.data.type.BaseType; 036import ptolemy.kernel.CompositeEntity; 037import ptolemy.kernel.util.Attribute; 038import ptolemy.kernel.util.IllegalActionException; 039import ptolemy.kernel.util.NameDuplicationException; 040import ptolemy.plot.PlotInterface; 041 042/////////////////////////////////////////////////////////////////// 043//// SequencePlotter 044 045/** 046 A sequence plotter. This plotter contains an instance of the Plot 047 class from the Ptolemy plot package as a public member. Data at 048 the input, which can consist of any number of channels, are plotted 049 on this instance. Each channel is plotted as a separate data set. 050 The horizontal axis represents the count of the iterations, scaled 051 by the <i>xUnit</i> parameter. The horizontal increment between 052 samples is given by the <i>xUnit</i> parameter. 053 Its default value is 1.0. The horizontal value 054 of the first sample is given by the <i>xInit</i> parameter. 055 Its default value is 0.0. The input is of type DoubleToken. 056 057 @author Edward A. Lee, Bart Kienhuis 058 @version $Id$ 059 @since Ptolemy II 1.0 060 @Pt.ProposedRating Green (eal) 061 @Pt.AcceptedRating Green (cxh) 062 */ 063public class SequencePlotter extends Plotter implements SequenceActor { 064 /** Construct an actor with the given container and name. 065 * @param container The container. 066 * @param name The name of this actor. 067 * @exception IllegalActionException If the actor cannot be contained 068 * by the proposed container. 069 * @exception NameDuplicationException If the container already has an 070 * actor with this name. 071 */ 072 public SequencePlotter(CompositeEntity container, String name) 073 throws IllegalActionException, NameDuplicationException { 074 super(container, name); 075 076 // Create the input port and make it a multiport. 077 input = new TypedIOPort(this, "input", true, false); 078 input.setMultiport(true); 079 input.setTypeEquals(BaseType.DOUBLE); 080 081 // set the parameters 082 xInit = new Parameter(this, "xInit", new DoubleToken(0.0)); 083 xInit.setTypeEquals(BaseType.DOUBLE); 084 xUnit = new Parameter(this, "xUnit", new DoubleToken(1.0)); 085 xUnit.setTypeEquals(BaseType.DOUBLE); 086 087 // Initialize the parameters. 088 // We used to call attributeChanged() here, but FindBugs 089 // reports "Uninitialized read of field method called from constructor of superclass" 090 // in derived classes. 091 _xInit = ((DoubleToken) xInit.getToken()).doubleValue(); 092 _xUnit = ((DoubleToken) xUnit.getToken()).doubleValue(); 093 } 094 095 /////////////////////////////////////////////////////////////////// 096 //// ports and parameters //// 097 098 /** Input port, which has type DoubleToken. */ 099 public TypedIOPort input; 100 101 /** The increment of the X axis. */ 102 public Parameter xUnit; 103 104 /** The start point of the X axis. */ 105 public Parameter xInit; 106 107 /////////////////////////////////////////////////////////////////// 108 //// public methods //// 109 110 /** Notification that an attribute has changed. 111 * @param attribute The attribute that changed. 112 * @exception IllegalActionException If the expression of the 113 * attribute cannot be parsed or cannot be evaluated. 114 */ 115 @Override 116 public void attributeChanged(Attribute attribute) 117 throws IllegalActionException { 118 if (attribute == xInit) { 119 _xInit = ((DoubleToken) xInit.getToken()).doubleValue(); 120 } else { 121 if (attribute == xUnit) { 122 _xUnit = ((DoubleToken) xUnit.getToken()).doubleValue(); 123 } else { 124 super.attributeChanged(attribute); 125 } 126 } 127 } 128 129 /** Reset the x axis counter, and call the base class. 130 * Also, clear the datasets that this actor will use. 131 * @exception IllegalActionException If the parent class throws it. 132 */ 133 @Override 134 public void initialize() throws IllegalActionException { 135 super.initialize(); 136 _xValue = _xInit; 137 138 int width = input.getWidth(); 139 _connected = new boolean[width]; 140 for (int i = 0; i < width; i++) { 141 _connected[i] = true; 142 } 143 } 144 145 /** Read at most one token from each input channel and plot it as 146 * a function of the iteration number, scaled by <i>xUnit</i>. 147 * The first point is plotted at the horizontal position given by 148 * <i>xInit</i>. The increments on the position are given by 149 * <i>xUnit</i>. The input data are plotted in postfire() to 150 * ensure that the data have settled. 151 * @exception IllegalActionException If there is no director, 152 * or if the base class throws it. 153 * @return True if it is OK to continue. 154 */ 155 @Override 156 public boolean postfire() throws IllegalActionException { 157 int width = input.getWidth(); 158 int offset = ((IntToken) startingDataset.getToken()).intValue(); 159 160 for (int i = width - 1; i >= 0; i--) { 161 if (input.hasToken(i)) { 162 DoubleToken curToken = (DoubleToken) input.get(i); 163 if (curToken.isNil()) { 164 _connected[i] = false; 165 } else { 166 double curValue = curToken.doubleValue(); 167 168 // NOTE: We assume the superclass ensures this 169 // cast is safe. 170 171 ((PlotInterface) plot).addPoint(i + offset, _xValue, 172 curValue, _connected[i]); 173 _connected[i] = true; 174 } 175 } 176 } 177 178 _xValue += _xUnit; 179 return super.postfire(); 180 } 181 182 /////////////////////////////////////////////////////////////////// 183 //// protected members //// 184 185 /** X axis counter. */ 186 protected double _xValue; 187 188 /** Start of the X axis counter. */ 189 protected double _xInit; 190 191 /** Increment of the X axis counter. */ 192 protected double _xUnit; 193 194 /////////////////////////////////////////////////////////////////// 195 //// private members //// 196 197 /** An array of booleans, where if an element is true, then the 198 * next point that is plotted for that channel will be connected. 199 * If a channel receives a nil token, then the value for the 200 * corresponding element will be false, meaning the next point will 201 * not be connected to the previous point. 202 */ 203 boolean[] _connected; 204}