Re: newbie- can I make a bar graph?

Thanks for your quick response. I'm sorry, though- but I'm still
confused. I think perhaps I did not make it clear what I want to do. I
just want to take example P2_03 on the visAD tutorial page:

and draw the sample points as bars instead of dots. The top of each bar
would be at the y (height) value of the point and the bottom of each bar
would be at y = 0. All I meant about the "midpoint" stuff was that if
barwidth = 1 then 0.5 of the bar would be to the left of the x (time)
position and 0.5 of the bar would be to the right of the x position. In
other words, the upper left corner of each bar would be at coordinate (x
- 0.5, y) and the lower right corner of the bar shape would be at (x +
0.5, 0). In this case, I don't think we need the third RealType ("dif")
in your example. Right?

I also didn't understand the section of code where you set up the
shapes. Why do you have to generate the Linear1DSet of samples when you
already have all the sample data you need? Which leads to a more general
question- is VisAD not a good program for plotting/charting discrete
data? Is it much better suited for continuous functions? 

Anyway, here is my modified version of example P2_03 as I attempt to
draw the points as bars. The only section that's different from the one
on the web page is the "set up shapes" section (and the fact that I made
the heightMap range start at 0 instead of -10, which shouldn't matter
much). I guess my biggest problem is that I don't know how to get the
bar shapes to draw. I know I'm missing code to do that, but I'm not
quite sure what it should be. I don't even understand how the example in
the tutorial knew to draw dots as opposed to a line connecting the
points in the previous tutorial example. Any help is greatly
appreciated! Here is my code, followed by your prev. email for
reference. You may want to just scroll down to my "set up shapes"
section. THANK YOU!!

VisAD Tutorial
Copyright (C) 2000 Ugo Taddei

// Import needed classes

import visad.*;
import visad.java2d.DisplayImplJ2D;
import java.rmi.RemoteException;
import java.awt.*;
import javax.swing.*;

  VisAD Tutorial example 2_03
  Data are organized as MathType ( index  -> ( time, height )  ) and 
  represent some points from the parabola of the previous example
  Data are indexed (time, height) points and get depicted as such.
  Run program with java P2_03 

public class P2_03Bar{

  // Declare variables
  // The quantities to be displayed in x- and y-axes: time and height,
  // Our index is alos a RealType
  private RealType time, height, index;
  // A Tuple, to pack time and height together
  private RealTupleType t_h_tuple;
  // The function ( time(i), height(i) ), where i = index, 
  // represented by ( index -> ( time, height) )
  // ( time, height) are a Tuple, so we have a FunctionType
  // from index to a tuple
  private FunctionType func_i_tuple; 
  // Our Data values, the points, are now indexed by the Set

  private Set index_set;

  // The Data class FlatField, which will hold time and height data.
  // time data are implicitely given by the Set time_set
  private FlatField vals_ff;  
  // The DataReference from the data to display
  private DataReferenceImpl data_ref;

  // The 2D display, and its the maps
  private DisplayImpl display;
  private ScalarMap timeMap, heightMap;
  public P2_03Bar (String []args)
    throws RemoteException, VisADException {

    // Create the quantities
    // x and y are measured in SI meters
    // Use RealType(String name, Unit u,  Set set), set is null
    time = new RealType("time", SI.second, null);
    height = new RealType("height", SI.meter, null);
    // Organize time and height in a Tuple
    t_h_tuple = new RealTupleType( time, height);
    // Index has no unit, just a name
    index = new RealType("index");
    // Create a FunctionType ( index -> ( time, height) )
    // Use FunctionType(MathType domain, MathType range) 
    func_i_tuple = new FunctionType( index, t_h_tuple);
    // Create the x_set, with 5 values, but this time using a
    // Integer1DSet(MathType type, int length) 
    index_set = new Integer1DSet(index, 5);
    // These are our actual data values for time and height
    // Note that these values correspond to the parabola of the 
    // previous examples. The y (height) values are the same, but the x
    // are now given given.
    float[][] point_vals = new float[][]{{-3.0f, -1.5f, 0.0f, 1.5f,
                                         {0.0f, 33.75f, 45.0f, 33.75f, 0.0f,} };
    // Create a FlatField, that is the Data class for the samples 
    // Use FlatField(FunctionType type, Set domain_set)
    vals_ff = new FlatField( func_i_tuple, index_set);
     // and put the height values above in it
    vals_ff.setSamples( point_vals ); 
    // Create Display and its maps
    // A 2D display
    display = new DisplayImplJ2D("display1");
    // Get display's graphics mode control and draw scales
    GraphicsModeControl dispGMC = (GraphicsModeControl)
    // Create the ScalarMaps: quantity time is to be displayed along
    // and height along YAxis
    // Use ScalarMap(ScalarType scalar, DisplayRealType display_scalar) 
    timeMap = new ScalarMap( time, Display.XAxis );
    heightMap = new ScalarMap( height, Display.YAxis );

    // Add maps to display
    display.addMap( timeMap );
    display.addMap( heightMap );
    // Scale heightMap. This will scale the y-axis, because heightMap
has DisplayRealType YAXIS
    // We simply choose the range from -4 to 4 for the x-axis
    // and -10.0 to 50.0 for
    timeMap.setRange( -4.0, 4.0);
    heightMap.setRange( 0.0, 50.0);
    // Create a data reference and set the FlatField as our data 
    data_ref = new DataReferenceImpl("data_ref");
    data_ref.setData( vals_ff );

    ///////////////////// set up shapes /////////////////////

    // can't do this- get class cast exception because it's not a 
    // ShapeControl, it's a visad.java2d.ProjectionControlJ2D.
    // So how do I get the control?
    //ShapeControl control = (ShapeControl) heightMap.getControl();

    float barWidth = 1f;
    int nPts = point_vals[1].length;
    VisADQuadArray[] shapes = new VisADQuadArray[nPts];
    for (int i=0; i<nPts; i++) {
        shapes[i] = new VisADQuadArray();
        shapes[i].vertexCount = 4;
        float hw = 0.5f * barWidth;
        float x = point_vals[0][i];
        float y = point_vals[1][i];
        shapes[i].coordinates = new float[]
        {x - hw, y, 0.0f,  x + hw, y, 0.0f,  
         x + hw, y, 0.0f,  x - hw, y, 0.0f};

    // how do I draw these shapes? Do I just call this once I get 
    // a valid ShapeControl object? :
    // control.setShapes(shape)

    ///////////////////// end set up shapes /////////////////////
    // Add reference to display
    display.addReference( data_ref );

    // Create application window, put display into it 
    JFrame jframe = new JFrame("VisAD Tutorial example 2_03Bar");
    // Set window size and make it visible
    jframe.setSize(300, 300);
  public static void main(String[] args)
    throws RemoteException, VisADException
    new P2_03Bar(args);

} //end of Visad Tutorial example 2_03

"From: Bill Hibbard " wrote:
> Hi Jen,
> > Hi. I am new to VisAD but it seems really great. Problem is, it's so
> > powerful that I'm having trouble figuring out the simple stuff. I've
> > been looking at the (very helpful) tutorial at:
> >
> >
> >
> > I want to do a plot similar to the one in example P2_03 or P2_04, but
> > insead of points to represent the data I would like bars. I want to make
> > a bar graph, where the bottom of each bar is at a certain point on the x
> > axis (in this example, maybe the midpoint of each bar would be at its
> > corresponding x value) and the top of each bar is at the height of the
> > corresponding y value. Do I have to make a VisADQuadArray for every bar
> > I want or is there a simpler solution? Does anybody have/know of a
> > simple Bar Chart example in 2d or 3d using VisAD?
> You can probably do this using ScalarMaps to Display.Shape.
> Say you have a FlatField 'field' with MathType
> (index -> (mid, top)) and you want the midpoint of bars at
> mid values and tops of bars at top values.
> You can probably do this using ScalarMaps to Display.Shape.
> Say you have a FlatField 'field' with MathType
> (index -> (mid, top)) and you want the midpoint of bars at
> mid values and tops of bars at top values.  Then do
> something like:
>   // create new_field with (top - mid) values
>   RealType dif = new RealType("dif");
>   RealTupleType range = new RealTupleType(mid, top, dif);
>   FunctionType new_func = new FunctionType(index, range);
>   Set set = field.getDomainSet();
>   int length = set.getLength();
>   float[][] old_values = field.getFloats();
>   float[][] new_values = new float[3][length];
>   new_values[0] = old_values[0];
>   new_values[1] = old_values[1];
>   float min_mid = Float.MAXIMUM_VALUE;
>   float max_mid = Float.MINIMUM_VALUE;
>   float max_dif = Float.MINIMUM_VALUE;
>   for (int i=0; i<length; i++) {
>     if (new_values[0][i] < min_mid) min_mid = new_values[0][i];
>     if (new_values[0][i] > max_mid) max_mid = new_values[0][i];
>     new_values[2][i] = new_values[1][i] - new_values[0][i];
>     if (new_values[2][i] > max_mid) max_mid = new_values[2][i];
>   }
>   FlatField new_field = new FlatField(new_func, set);
>   new_field.setSamples(new_values);
>   // some tuning values for display
>   float dif_resolution = ...; // desired resolution of dif values
>   int ndifs = 1 + (int) (max_dif / dif_resolution); // # of dif samples
>   float width = ...; // width of bar (e.g., 0.02f)
>   // set up Scalarmaps for display
>   display.addMap(new ScalarMap(index, Display.XAxis));
>   ScalarMap mid_map = new ScalarMap(mid, Display.YAxis);
>   display.addMap(mid_map);
>   mid_map.setRange(min_mid, max_mid);
>   display.addMap(new ScalarMap(mid, Display.YAxis));
>   ScalarMap dif_map = new ScalarMap(dif, Display.Shape);
>   display.addMap(dif_map);
>   // set up shapes
>   ShapeControl control = (ShapeControl) dif_map.getControl();
>   Linear1DSet dif_set = new Linear1DSet(dif, 0.0, max_dif, ndifs);
>   float[][] difs = dif_set.getSamples();
>   VisADQuadArray[] dif_shapes = new VisADQuadArray[ndifs];
>   for (int i=0; i<ndifs; i++) {
>     dif_shapes[i] = new VisADQuadArray();
>     dif_shapes[i].vertexCount = 4;
>     float hw = 0.5f * width;
>     float hh = 0.5f * difs[0][i] * (2.0f / (max_mid - min_mid));
>     dif_shapes[i].coordinates = new float[]
>       {hw, hh, 0.0f,  -hw, hh, 0.0f,  -hw, -hh, 0.0f,  hw, -hh, 0.0f};
>   }
>   control.setShapeSet(dif_set);
>   control.setShapes(dif_shapes);
> I haven't tested this, so it may have bugs, but its the general
> idea.
> Cheers,
> Bill
> ----------------------------------------------------------
> Bill Hibbard, SSEC, 1225 W. Dayton St., Madison, WI  53706
> hibbard@xxxxxxxxxxxxxxxxx  608-263-4427  fax: 608-263-6738

  • 2000 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the visad archives: