swarm-support
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Modifying EZGRAPH?


From: Benedikt Stefansson
Subject: Re: Modifying EZGRAPH?
Date: Sun, 14 Nov 1999 16:30:05 -0700

Doug Donalson wrote:

> I need to be able to define my own input stream for the X-axis.  The
> result is displayed as four lines.  Three of these are an "average"
> CSR and two lines representing a min and max envelope of a 95%
> confidence interval.  A data line is then compared to the CSR graph.
> (All four lines are plotted at once.)  The problem is that all four
> lines are plotted against the CSR "average" line so that needs to be
> my "time step".  Is this possible?

Trick is to use the Graph class directly, not the wrapper class EZGraph,
which assumes that the data is graphed against time.

In the following example I needed to graph a 'phase diagram'. The x,y
values where read from two seperate objects and then graphed against
each other. On top of the dynamically updated graph I wanted to draw
three axis - the X,Y which crossed at 0,0 and a 45 degree line through
the origin.

To be able to read the x,y data from two seperate objects I implemented
a class called ActiveGrapherXY (Swarm libs have an ActiveGraph class
which assumes that x,y datafeed is from the same object)

Although this is not exactly what you want the example shows how to:
    1) Create dynamically updated 2-D graphs which do not show time
series and take data from more than one object.
    2) Superimpose static data on a dynamic 2-D graph (the axis
elements)

I hope the example helps to figure things out, in your case you simply
need to add a few ActiveGrapherXY instances.

Note #1: In my example, to update the graph you send update messages to
items on the 'graphers' list as in:

[graphSchedule at: 0 createActionForEach: graphers   message: M(step)];

Note #2: MIN_X, MAX_X etc are constants which are defined as:

#define MIN_X -1.0   // Min x for graph
#define MAX_X  1.0   // Max y for graph
#define MIN_Y -1.0   // Min x for graph
#define MAX_Y  1.0   // Max y for graph

Code follows.

Regards,
Benedikt

<BEGIN>
  // Create the i vs v graph
  graph = [Graph createBegin: self];
  graph = [graph createEnd];

  [graph setTitle: "mean(i_t) vs. mean(v_t)"];
  [graph setRangesXMin: MIN_X Max: MAX_X YMin: MIN_Y Max: MAX_Y];
  [graph setAxisLabelsX: "mean(v_t)" Y: "mean(i_t)"];
  [graph pack];

  // Create a list of graphers for this graph
  graphers = [List create: self];
  color    = 0;

  // Make a sequence that displays mean(i) vs mean(v) on graph
  element = [graph createElement];
  [element setLabel: "mean"];
  [element setColor: graph_colors[color++]];

  grapher = [ActiveGrapherXY createBegin: self];
  [grapher setElement: element];
  [grapher setDataFeedX: [model get_averager_v] Y: [model
get_averager_i]];
  [grapher setProbedSelectorX: M(getAverage) Y: M(getAverage)];
  grapher = [grapher createEnd];

  [graphers addLast: grapher];

  // Also draw a horizontal, vertical and 45 degree line on the graph
  element = [graph createElement];
  [element setColor: "black"];
  [element setLabel: ""];
  [element addX: MIN_X Y: (MAX_Y - abs(MIN_Y))/2.0]; // Draws horizontal

  [element addX: MAX_X Y: (MAX_Y - abs(MIN_Y))/2.0]; // line in middle

  element = [graph createElement];
  [element setColor: "black"];
  [element setLabel: ""];
  [element addX: (MAX_X - abs(MIN_X))/2.0 Y: MIN_Y];  // Draws vertical
  [element addX: (MAX_X - abs(MIN_X))/2.0 Y: MAX_Y];  // line in middle

  element = [graph createElement];
  [element setColor: "black"];
  [element setLabel: ""];
  [element addX: MIN_X Y: MIN_Y];                    // Draws 45 degree
  [element addX: MAX_X Y: MAX_Y];                    // line on graph

<END>

<BEGIN>
// Utility class that knows how to probe two different objects
// to feed data to a graph element, used in displaying the i vs. v graph

@interface ActiveGrapherXY: SwarmObject
{
  SEL probedSelectorX;
  SEL probedSelectorY;
  id dataFeedX;
  id dataFeedY;
  id <MessageProbe> probeX;
  id <MessageProbe> probeY;
  id <GraphElement> element;
}

- setElement: (id <GraphElement>)ge;
- setDataFeedX: xFeed Y: yFeed;
- setProbedSelectorX: (SEL) xSel Y: (SEL) ySel;
- createEnd;
- step;

@end

@implementation ActiveGrapherXY

PHASE(Creating)

- setElement: (id <GraphElement>)ge
{
  // This is our connector with the actual graph
  element = ge;
  return self;
}

- setDataFeedX: xFeed Y: yFeed
{
  // Defines the object(s) that we call to get data
  dataFeedX = xFeed;
  dataFeedY = yFeed;
  return self;
}

- setProbedSelectorX: (SEL) xSel Y: (SEL) ySel
{
  // Defines the selector(s) that we use to call object(s)
  probedSelectorX = xSel;
  probedSelectorY = ySel;

  return self;
}

- createEnd
{
  if (element == nil || (dataFeedX == nil || dataFeedY == nil))
    [InvalidCombination raiseEvent: "ActiveGraph not initialized
properly"];

  // Create two message probe which can point to two different
  // objects with two different messages (although also a single object)

  probeX = [MessageProbe createBegin: [self getZone]];
  [probeX setProbedSelector: probedSelectorX];
  [probeX setProbedClass: [dataFeedX class]];
  probeX = [probeX createEnd];

  probeY = [MessageProbe createBegin: [self getZone]];
  [probeY setProbedSelector: probedSelectorY];
  [probeY setProbedClass: [dataFeedY class]];
  probeY = [probeY createEnd];

  [super createEnd];

  return self;
}

PHASE(Using)

// add a new x,y point to the graph element
- step
{
  [element addX: [probeX doubleDynamicCallOn: dataFeedX]
                        Y: [probeY doubleDynamicCallOn: dataFeedY]];

  return self;
}

@end
<END>




                  ==================================
   Swarm-Support is for discussion of the technical details of the day
   to day usage of Swarm.  For list administration needs (esp.
   [un]subscribing), please send a message to <address@hidden>
   with "help" in the body of the message.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]