001/* Factory that creates the schedule plotter.
002
003@Copyright (c) 2008-2015 The Regents of the University of California.
004All rights reserved.
005
006Permission is hereby granted, without written agreement and without
007license or royalty fees, to use, copy, modify, and distribute this
008software and its documentation for any purpose, provided that the
009above copyright notice and the following two paragraphs appear in all
010copies of this software.
011
012IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016SUCH DAMAGE.
017
018THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023ENHANCEMENTS, OR MODIFICATIONS.
024
025                                                PT_COPYRIGHT_VERSION_2
026                                                COPYRIGHTENDKEY
027
028
029 */
030package ptolemy.actor.gui;
031
032import java.awt.Frame;
033import java.util.HashMap;
034import java.util.List;
035
036import ptolemy.actor.ActorExecutionAspect;
037import ptolemy.actor.ExecutionAspectListener;
038import ptolemy.kernel.util.IllegalActionException;
039import ptolemy.kernel.util.InternalErrorException;
040import ptolemy.kernel.util.NameDuplicationException;
041import ptolemy.kernel.util.NamedObj;
042import ptolemy.plot.Plot;
043
044/** Factory that creates the plotter for the schedule of actors on a
045 *  resource scheduler.
046 *
047 * @author Patricia Derler
048   @version $Id$
049   @since Ptolemy II 10.0
050
051   @Pt.ProposedRating Red (derler)
052   @Pt.AcceptedRating Red (derler)
053 */
054public class ExecutionAspectPlotterEditorFactory extends EditorFactory
055        implements ExecutionAspectListener {
056
057    /**
058     * Constructs a SchedulePlotter$SchedulePlotterEditorFactory object.
059     *
060     * @param container
061     *                The container.
062     * @param name
063     *                The name of the factory.
064     * @exception IllegalActionException
065     *                    If the factory is not of an acceptable attribute
066     *                    for the container.
067     * @exception NameDuplicationException
068     *                    If the name coincides with an attribute already in
069     *                    the container.
070     */
071    public ExecutionAspectPlotterEditorFactory(NamedObj container, String name)
072            throws IllegalActionException, NameDuplicationException {
073        super(container, name);
074    }
075
076    /** The plot displayed by this ScheduleFactory. */
077    public Plot plot;
078
079    /**
080     * Create an editor for configuring the specified object with the
081     * specified parent window.
082     *
083     * @param object
084     *                The object to configure.
085     * @param parent
086     *                The parent window, or null if there is none.
087     */
088    @Override
089    public void createEditor(NamedObj object, Frame parent) {
090        try {
091            Configuration configuration = ((TableauFrame) parent)
092                    .getConfiguration();
093
094            //object.getContainer();
095
096            plot = new Plot();
097            plot.setTitle("Execution Time Monitor");
098            plot.setButtons(true);
099            plot.setMarksStyle("none");
100            plot.setXLabel("platform time");
101            plot.setYLabel("actor ID");
102
103            // We put the plotter as a sub-effigy of the toplevel effigy,
104            // so that it closes when the model is closed.
105            Effigy effigy = Configuration.findEffigy(toplevel());
106            String name = "plotterEffigy" + String.valueOf(id++);
107            PlotEffigy schedulePlotterEffigy = new PlotEffigy(effigy, name);
108            schedulePlotterEffigy.setPlot(plot);
109            schedulePlotterEffigy.setModel(this.getContainer());
110            schedulePlotterEffigy.identifier
111                    .setExpression("Execution Time Monitor");
112
113            configuration.createPrimaryTableau(schedulePlotterEffigy);
114
115            plot.setVisible(true);
116
117            if (_actors != null) {
118                _initPlot();
119            }
120        } catch (Throwable throwable) {
121            throw new InternalErrorException(object, throwable,
122                    "Cannot create Schedule Plotter");
123        }
124    }
125
126    /** Plot a new execution event for an actor (i.e. an actor
127     *  started/finished execution, was preempted or resumed).
128     * @param actor The actor.
129     * @param physicalTime The physical time when this scheduling event occurred.
130     * @param scheduleEvent The scheduling event.
131     */
132    @Override
133    public void event(final NamedObj actor, double physicalTime,
134            ExecutionEventType scheduleEvent) {
135        if (plot == null) {
136            return;
137        }
138
139        double x = physicalTime;
140        int actorDataset = _actors.indexOf(actor);
141        if (actorDataset == -1) {
142            return; // actor is not being monitored
143        }
144        if (scheduleEvent == null) {
145            if (_previousY.get(actor) == null) {
146                _previousY.put(actor, (double) actorDataset);
147            }
148            plot.addPoint(actorDataset, x, _previousY.get(actor), true);
149            _previousY.put(actor, (double) actorDataset);
150        } else if (scheduleEvent == ExecutionEventType.START) {
151            plot.addPoint(actorDataset, x, _previousY.get(actor), true);
152            plot.addPoint(actorDataset, x, actorDataset + 0.6, true);
153            _previousY.put(actor, actorDataset + 0.6);
154        } else if (scheduleEvent == ExecutionEventType.STOP) {
155            if (_previousY.get(actor) != actorDataset) {
156                plot.addPoint(actorDataset, x, actorDataset + 0.6, true);
157                plot.addPoint(actorDataset, x, actorDataset, true);
158            }
159            _previousY.put(actor, (double) actorDataset);
160        } else if (scheduleEvent == ExecutionEventType.PREEMPTED) {
161            plot.addPoint(actorDataset, x, actorDataset + 0.6, true);
162            plot.addPoint(actorDataset, x, actorDataset + 0.4, true);
163            _previousY.put(actor, actorDataset + 0.4);
164        }
165        plot.fillPlot();
166        plot.repaint();
167    }
168
169    /** Initialize plot.
170     *  @param actors Actors scheduled by the resource scheduler associated with
171     *    this plot.
172     *  @param scheduler Resource Scheduler associated with this plot.
173     */
174    @Override
175    public void initialize(List<NamedObj> actors,
176            ActorExecutionAspect scheduler) {
177        _actors = actors;
178        _scheduler = scheduler;
179        if (plot != null) {
180            _initPlot();
181        }
182    }
183
184    /** Contains the actors inside a ptides platform (=platforms). */
185    protected List<NamedObj> _actors;
186
187    /** Initialize legend.
188     */
189    private void _initPlot() {
190        plot.clearLegends();
191        plot.clear(false);
192        plot.addLegend(_actors.size() - 1, _scheduler.getName());
193        _previousY.put((NamedObj) _scheduler,
194                Double.valueOf(_actors.size() - 1));
195        plot.clear(false);
196        plot.clearLegends();
197
198        for (NamedObj actor : _actors) {
199            plot.addLegend(_actors.indexOf(actor), actor.getName());
200            event(actor, 0.0, null);
201            _previousY.put(actor, Double.valueOf(_actors.indexOf(actor)));
202        }
203        plot.doLayout();
204    }
205
206    /** The resource scheduler associated with this plot.
207     */
208    private ActorExecutionAspect _scheduler;
209
210    /** Previous positions of the actor data set. */
211    private HashMap<NamedObj, Double> _previousY = new HashMap<NamedObj, Double>();
212
213    /** This static variable is increased by 1 every time a new
214     *  SchedulePlotter is generated. The id is assigned as a unique
215     *  id to every schedule plotter.
216     */
217    private static int id = 1;
218}