Exemplo n.º 1
0
    def __init__(self,
                 dataArray,
                 title=None,
                 usrAttribs=dict(),
                 root=None,
                 newWindow=True):

        # Creating the default root within the __init__ call somehow
        # causes the root variable to persist and only a single root to be
        # created for multiple scenes. To avoid this we use the explicit
        # None initialization
        if root == None:
            root = VisusGroup.construct()
            #root = VisusSceneNode.construct()

        # Create a root node
        self._root = root
        # self._root.drawBoundingBox(False)

        # Create the attributes
        self._attribs = dict()

        # Create the extractor, data description and update attribs
        self.setData(dataArray, usrAttribs)

        # Attach the extractor to the root
        self._root.attachSubTree(self._extractor, True)

        self._extractor.propagateUpwards(VISUS_GLOBALTIME_TYPEID)

        # Create the drawing window
        if newWindow:
            print "Creating new window of root ", root
            createWindow(self._root)

        # Create the node for the slice of data
        self._orthoSlice = VisusOrthogonalSlice.construct()

        # Connect the output of the extractor to the input of each slice node
        if not self._orthoSlice.connectInput(self._extractor):
            raise RuntimeError("unable to connect extractor1 as slice input")

        # Attach the ortho slice to the root as a subtree
        self._extractor.attachSubTree(self._orthoSlice)

        # Inherit/Share the data request
        # Now that we have positioned the slices where we want them we want
        # to freeze their position. To do this we simply uninherit the data
        self._orthoSlice.inherit(VisusSharedDataRequest.typeIndex(), True)

        # This should be done autmoatically in the SliceNode
        # Set the correct bounding box for the slice
        # request = VisusDataRequest()
        # self._orthoSlice.getValue(request)
        # self._orthoSlice.setValue(request.queryRegion())

        # Set the colormap
        #self.setColorMap(ice())
        self.setColorMap(bgry())

        # Draw the bounding boxes of the slice
        self._orthoSlice.drawBoundingBox(True)

        # Set up the annotations for the colorbar etc
        self.setAnnote()

        # Add the world map
        world_map = self.loadWorldMap()

        # And parse it as a collection of polylines. A VisusIndexedData
        # object stores an array of n-dimensional points (n being 2 in this
        # case) and a set of elements defined as ordered lists of indices
        # into this array. Therefore, each contour of the world map is
        # parsed as a single element
        outlines = VisusIndexedData(2)
        for m in world_map:
            outlines.constructElement(m)

        # Once the data is constructed we create a display node designed to visualize it
        self._map = VisusIndexedDisplay.construct()

        # And load the data.
        self._map.loadData(outlines, 0)

        # Move the map to the top of the data set so that is it always above the slice
        matrix = translationMatrix(0, 0, 0)
        self._map.getValue(matrix)
        matrix = matrix * translationMatrix(0, 0, 0.01)

        # This is a really ugly hack to adjust for the [0,360] [-180,180] ambiguity
        if self._bbox[0] > -90:
            matrix = matrix * translationMatrix(180, 0, 0)

        self._map.setValue(matrix)

        # Attach the map as child of the extractor. Note, that from this moment
        # on the map will inherit all transformations from the extractor and
        # thus "stick" to the extractor if it is moved or rotated
        self._orthoSlice.attachSubTree(self._map)
        #self._extractor.attachSubTree(self._map)

        # Add a title to the scene
        if (title == None):
            if "name" in self._attribs:
                title = self._attribs["name"].replace("_", " ")
            else:
                title = "Title"

        font = VisusFont()
        font.fontSize(12)
        self._title = VisusLabelNode.construct()
        self._title.text(title)
        self._title.setValue(font)
        self._title.position(0, 0.92)
        self._root.attachSubTree(self._title, True)
Exemplo n.º 2
0
def cartesianSlice(data=None,**keywords):

  """

    This function constructs a default ViSUS scene displaying a single
    z-slice through a regular block of data. The user can either pass a
    cdms2 array using the data attribute or enter the necessary
    information into the vcdat gui. If no data attribute is present the
    function will try to extract the necessary information from the gui
    and if that fails an empty scene will be displayed.

    The scene contains multiple \"nodes\" each of which can be
    manipulated using the keyboard and mouse. Som basic commands are

    Tab : Switch node
    Middle Mouse button : Pan scene
    Left Mouse button : Rotate scene
    Right Mouse button : Zoom in and out


    Usage: cartesianSlice(DataArray, keyword=value,...) where DataArray
    can be a standard numpy array, a cdms type data set, or
    \"None\". The function will attempt to extract a number of
    attributes from the given data or the gui each of which can be
    overridden by the user by passing it explicitly. Possible keywords
    are:

    name     : Verbal description of the data set or variable (used in the title)
    var_name : Short name of the variable  
    domain   : Physical domain of the data set represented as
               [[min_x,max_x],[min_y,max_y],[min_z,max_z]]. If
               the data is only two- or one-dimensional the extra
               dimensions will be assumed to be [0,0]
    samples  : The number of samples in each dimension represented
               as [samples_x, samples_y, samples_z, samples_t]. For
               lower dimensional data the additional dimensions will
               be set to 1, e.g. a time-dependent 2D array would be
               [dim_x,dim_y,1,dim_t]
    units    : VisusUnit identfier describing the natural coordinate
               system of the data (e.g. cartesian length, polar
               coordinates, etc.) All possible values can be found in
               VisusUnits.h
    range    : Local function range of the data. Note, that percentages
               and fractions will automatically get a range of [0,100]
               and [0,1] respectively.
    time     : The cdtime.Comptime of the first time step in data
    """
  
  # If the user did not pass in an array try to extract one from the
  # gui
  if data is None:
    data = guiDefinedData()
    
  attributes = keywords
  try:
    
    # Unless the user has explicitly specified different units we
    # treat the domain as a length box
    if "units" not in attributes:
      attributes["units"] = VISUS_METERS

    # Try to infer as many data attributes as you can and return a
    # string describing/defining the data in the ViSUS internal format
    data_description = constructDataDescriptor(data,attributes)
  except:
    print "Could not parse data. Unknown format"
    raise

  # Create a font to be used in all the nodes that render text
  font = VisusFont()
  font.fontSize(6)
  
  # Construct a root node for the scene graph hierarchy. This node is
  # mainly used for the global transformation (e.g. rotating the
  # complete scene) and is a convinient way to collect independent
  # nodes (nodes that should have no ancestor-descendend
  # relationship. Note, the use of the construct function rather than
  # a standard "constructor." ViSUS uses a smart pointer / reference
  # counting scheme which requires this.
  root = VisusGroup.construct()

  # To have a convinient reference point we want to display the
  # bounding box of the root node which will automatically adjust to
  # include the bounding box of all child nodes.  
  root.drawBoundingBox(True)

  # Create two points that will form the left lower and right upper
  # corner of the data bounding box
  left = VectorDouble(3)
  right= VectorDouble(3)

  # Create a ViSUS data source based on the data description created earlier
  source = VisusDataSourceFactory.make(data_description)
  if not source.isValid():
    raise RuntimeError("Problem loading data set")

  # Get the bounding box of the data whose value may or may not depend
  # on data attributes such as units. In particular, if this
  # information was available the bounding box will be given in
  # pyhsical units rather than in index space
  source.domainBoundingBox(left,right)
  bbox = VisusBoundingBox()
  bbox.set(left,right);
  
  # The ViSUS system is based on data "requests" that describe a
  # particular piece of data that should be displayed. The data
  # requests can be manipulated through the user interface or
  # directly. However, here we want to create a sensible default
  # request to see a portion of our data.
  
  # First, we create an empty request 
  request = VisusDataRequest()

  # Second, we construct an array that describes the length in each
  # dimension of the box of data we want to extract in whatever units
  # the data source uses (typically physical space).
  extent = VectorDouble(3)  
  extent[0] = (right[0] - left[0]) # We want to see all of the x-coordinate
  extent[1] = (right[1] - left[1]) # and all of the y-coordinate 
  extent[2] = 0  # But we want to look at a plane so the z extend is 0

  # And we pass the extent information into the request
  request.extent(extent)

  # Second, we need to position our extent box in the data
  # set. Initially, the extent will be centered around the origin. To
  # see the middle of the data we want translate our request to the
  # center of the data's bounding box

  # So we create the corresponding transformation matrix
  matrix = translationMatrix((left[0]+right[0])/2,
                             (left[1]+right[1])/2,
                             (left[2]+right[2])/2,
                             )
  # And pass this matrix to the request
  request.transformation(matrix)
  
  # Third, we want to indicate to the ViSUS system that we are
  # really interested in a 2D slice of the data (rather than a
  # degenerate volume) as slices are a special case and implement some
  # special user interactions
  request.requestType(VISUS_2D_REQUEST);

  # Finally, we describe the resolution at which we want to see our
  # data. The resolution is defined in terms ofo sub-sampling
  # "strides" where a stride of 1 defines the full resolution data a
  # stride of 2, the data sub-sampled by a factor of 2 etc.. Strides
  # must be powers of two but can be independently set for each
  # dimension. Furthermore, for large data it can be useful to
  # progressively refine the data starting at some higher strides /
  # coarser resolution, ending at some lower strides / finer
  # resolution. This preserves interactivity while still providing
  # high resolution data if the request remains unchanged long enough

  # Since, for default scenes we expect the data to be small we only
  # want to see the highest resolution
  start = [ 1, 1, 1 ]
  end   = [ 1, 1, 1 ]
  request.setStrides(start,end)
  

  # Armed with the description of the data and the request we just
  # constructed we create a scene graph node that will extract the
  # data for us. This node, will continuously test its current request
  # and update the data accordingly. Therefore, one could adapt the
  # scene by simply passing different requests to this node (which is
  # what the graphical user interface does on mouse movements or
  # keyboard commands)
  
  # Create a producer node specialized to extract and axis aligned
  # bounding box from a data set. As before with the root node the
  # node must be explicitly constructed.
  extractor = VisusAxisAlignedExtractor.construct()

  # Set the data to extract our data from
  extractor.setValue(data_description)
  extractor.setValue(request) # Our default request
  extractor.setValue(bbox); # And the bounding box 
  extractor.drawBoundingBox(False);


  # Now that we have a node that will extract the data we want to see
  # we construct another node to visualize the slice

  # We want to view an axis aligned slice of the data an the
  # appropriate visualization node is one for orthogonal slices
  slice = VisusOrthogonalSlice.construct()

  # Now we connect the output of the extractor to the input of the
  # visualization node
  if not slice.connectInput(extractor):
    raise RuntimeError("unable to connect extractor as slice input")

  # For reasons internal to the underpinnings of the ViSUS system the
  # visualization node must know about the current data request. The
  # simplest way of achieving this is to attach the slice node as
  # child to the extractor 
  extractor.attachSubTree(slice,True)

  # and to inherit/share the request 
  slice.inherit(VisusSharedDataRequest.typeIndex(),True)

  # In this configuration the slice node will naturally draw the data
  # at the position of the data request which is the natural
  # place. However, by manipulating the transformation matrix of the
  # slice node we could draw the data anywhere in space / on the screen
   
  # Instead of the default greyscale color map we want to use a
  # typical red-to-blue map
  color_map = banded()
  slice.setValue(color_map)

  # In order to see the slice even if it contains no data (if the
  # request has been moved outside the data set, or the data is
  # extremly large) we draw the bounding box of the slice
  slice.drawBoundingBox(True);

  # Now, we want to create labeled tickmarks to give the user a notion
  # of the data range. 

  # Create a tickmark node that by default will create tickmarks along
  # the x-axis of its bounding box
  xTickMarks = VisusTickMarks.construct()

  # ViSUS uses "axis" to control the labels of images, graphs, and
  # also tickmarks. Here we get the current axis 
  axis = xTickMarks.axis()
  axis.legendText("longitude") # Set the label 
  axis.labelFont(font)         # and font
  xTickMarks.axis(axis)        # and update the axis

  # Finally, we attach the tickmarks node as a child to the
  # extractor. By default a tickmarks node inherits the bounding box
  # of its parent and thus this node will now annotate the x-axis of
  # our data set
  extractor.attachSubTree(xTickMarks,True)
  
  # Create tickmarks for the y-axis in an identical fashion
  yTickMarks = VisusTickMarks.construct()
  
  # Except that now we must name the axis explicitly 
  yTickMarks.direction(TM_Y_AXIS)
  axis = yTickMarks.axis() 
  axis.legendText("latitude")
  axis.labelFont(font)
  yTickMarks.axis(axis)
  extractor.attachSubTree(yTickMarks,True)
  
  # Finally, we attach the whole subtree that renders the data plus
  # annotation to the root node
  root.attachSubTree(extractor,True)


  # To further enhance the scene we want to add the continental
  # outlines on top of the slice

  # First, we load the cdat internal world map 
  world_map = loadWorldMap()

  # And parse it as a collection of polylines. A VisusIndexedData
  # object stores an array of n-dimensional points (n being 2 in this
  # case) and a set of elements defined as ordered lists of indices
  # into this array. Therefore, each contour of the world map is
  # parsed as a single element
  outlines = VisusIndexedData(2)
  for m in world_map:
    outlines.constructElement(m)

  # Once the data is constructed we create a display node designed to visualize it
  map = VisusIndexedDisplay.construct()

  # And load the data. 
  map.loadData(outlines,0)

  # The cdat world map is given within (-180,-90)x(180,90). However,
  # in order to display the normal lat,long, elev data easily in
  # cartesian space we told ViSUS the data units are meters (meaning
  # general distance) which will draw (0,0)x(360,180). To adjust the
  # map to the slice we therefore must shift it
  #map.getValue(matrix);
  #matrix = matrix * translationMatrix(180,90,0.01)
  #map.setValue(matrix)

  # Attach the map as child of the extractor. Note, that from this moment
  # on the map will inherit all transformations from the extractor and
  # thus "stick" to the extractor if it is moved or rotated
  extractor.attachSubTree(map)
  
  # Lastly, we attach more annotations to the scene

  # A VisusLabelNode is a general one line text of arbitrary font and
  # size. First, we create a title string using the variable name if
  # we found one
  label_node = VisusLabelNode.construct()
  title = "Variable: " + attributes["name"].replace("_"," ")
  label_node.text(title)
  label_node.setValue(font)

  # Positions of labels are given relative to the screen size
  label_node.position(-1,+0.8)
  root.attachSubTree(label_node,True)

  # If our data set is time-dependent we attach a label that displays
  # the current time step
  if "time" in attributes:
    time_node = VisusLabelNode.construct()
    t = attributes["time"]
    title = "Date: %02d/%02d/%04d" % (t.month,t.day,t.year)
    time_node.text(title)
    time_node.setValue(font)
    time_node.position(0.6,-0.95)
    root.attachSubTree(time_node,True)

  # A VisusColorBar displays a bar with a color map on the inside and
  # allows us to attach tickmarks and labels
  color_bar = VisusColorBar.construct()

  # As before fopr the tickmark node we modify the labels via the Axis construct
  axis = color_bar.axis()

  # If we found a variable name we use it as label
  if "var_name" in attributes:
    axis.legendText(attributes["var_name"])
    
  # If we found a range we use it as well. 
  if "range" in attributes:
    axis.minValue(float(attributes["range"][0]))
    axis.maxValue(float(attributes["range"][1]))
    
  font.fontSize(4)
  axis.legendFont(font)
  axis.labelFont(font)
  color_bar.position(-1.2,-0.8)
  color_bar.axis(axis)

  # Finally, attach the color bar to the slice and make sure it
  # inherits its colormap from there
  slice.attachSubTree(color_bar,True)
  #color_bar.inherit(VisusSharedColorMap.typeIndex(),True)
  color_bar.inherit(8,True)


  # Lastly we must make sure that we actually see the data on the
  # screen which means we need to make sure that the data is scaled
  # and translated appropriately. (Alternatively, once can think of
  # this step as setting up the viewpoint of our virtual camera.

  # Using the current bounding box of the scene we adapt a default box
  # to the aspect ratios of of our scene and use it as our "world
  # coordinate system"  
  world_box = constructWorldBox(bbox)
  root.setValue(bbox)

  # Now we make sure that the data is drawn in our standard coordinate
  # system
  root.mapToWorldBox(world_box)

  # Finally, most climate data contains significantly more samples in
  # x/y than in z. Since, for the cartesian slice we effecticely draw
  # the data in index space since is inconvinient as the volume wille
  # very "flat." To compensate for this we simply scale the z
  # coordinate of our system
  root.getValue(matrix)
  matrix = matrix * scaleMatrix(1,1,10)
  root.setValue(matrix)

  # As the final step we create ourselfs a window to display the scene
  # graph hanging under the root node
  createWindow(root)
  
  return root,data_description
Exemplo n.º 3
0
def cartesianSlice(data=None, **keywords):
    """

    This function constructs a default ViSUS scene displaying a single
    z-slice through a regular block of data. The user can either pass a
    cdms2 array using the data attribute or enter the necessary
    information into the vcdat gui. If no data attribute is present the
    function will try to extract the necessary information from the gui
    and if that fails an empty scene will be displayed.

    The scene contains multiple \"nodes\" each of which can be
    manipulated using the keyboard and mouse. Som basic commands are

    Tab : Switch node
    Middle Mouse button : Pan scene
    Left Mouse button : Rotate scene
    Right Mouse button : Zoom in and out


    Usage: cartesianSlice(DataArray, keyword=value,...) where DataArray
    can be a standard numpy array, a cdms type data set, or
    \"None\". The function will attempt to extract a number of
    attributes from the given data or the gui each of which can be
    overridden by the user by passing it explicitly. Possible keywords
    are:

    name     : Verbal description of the data set or variable (used in the title)
    var_name : Short name of the variable  
    domain   : Physical domain of the data set represented as
               [[min_x,max_x],[min_y,max_y],[min_z,max_z]]. If
               the data is only two- or one-dimensional the extra
               dimensions will be assumed to be [0,0]
    samples  : The number of samples in each dimension represented
               as [samples_x, samples_y, samples_z, samples_t]. For
               lower dimensional data the additional dimensions will
               be set to 1, e.g. a time-dependent 2D array would be
               [dim_x,dim_y,1,dim_t]
    units    : VisusUnit identfier describing the natural coordinate
               system of the data (e.g. cartesian length, polar
               coordinates, etc.) All possible values can be found in
               VisusUnits.h
    range    : Local function range of the data. Note, that percentages
               and fractions will automatically get a range of [0,100]
               and [0,1] respectively.
    time     : The cdtime.Comptime of the first time step in data
    """

    # If the user did not pass in an array try to extract one from the
    # gui
    if data is None:
        data = guiDefinedData()

    attributes = keywords
    try:

        # Unless the user has explicitly specified different units we
        # treat the domain as a length box
        if "units" not in attributes:
            attributes["units"] = VISUS_METERS

        # Try to infer as many data attributes as you can and return a
        # string describing/defining the data in the ViSUS internal format
        data_description = constructDataDescriptor(data, attributes)
    except:
        print "Could not parse data. Unknown format"
        raise

    # Create a font to be used in all the nodes that render text
    font = VisusFont()
    font.fontSize(6)

    # Construct a root node for the scene graph hierarchy. This node is
    # mainly used for the global transformation (e.g. rotating the
    # complete scene) and is a convinient way to collect independent
    # nodes (nodes that should have no ancestor-descendend
    # relationship. Note, the use of the construct function rather than
    # a standard "constructor." ViSUS uses a smart pointer / reference
    # counting scheme which requires this.
    root = VisusGroup.construct()

    # To have a convinient reference point we want to display the
    # bounding box of the root node which will automatically adjust to
    # include the bounding box of all child nodes.
    root.drawBoundingBox(True)

    # Create two points that will form the left lower and right upper
    # corner of the data bounding box
    left = VectorDouble(3)
    right = VectorDouble(3)

    # Create a ViSUS data source based on the data description created earlier
    source = VisusDataSourceFactory.make(data_description)
    if not source.isValid():
        raise RuntimeError("Problem loading data set")

    # Get the bounding box of the data whose value may or may not depend
    # on data attributes such as units. In particular, if this
    # information was available the bounding box will be given in
    # pyhsical units rather than in index space
    source.domainBoundingBox(left, right)
    bbox = VisusBoundingBox()
    bbox.set(left, right)

    # The ViSUS system is based on data "requests" that describe a
    # particular piece of data that should be displayed. The data
    # requests can be manipulated through the user interface or
    # directly. However, here we want to create a sensible default
    # request to see a portion of our data.

    # First, we create an empty request
    request = VisusDataRequest()

    # Second, we construct an array that describes the length in each
    # dimension of the box of data we want to extract in whatever units
    # the data source uses (typically physical space).
    extent = VectorDouble(3)
    extent[0] = (right[0] - left[0])  # We want to see all of the x-coordinate
    extent[1] = (right[1] - left[1])  # and all of the y-coordinate
    extent[2] = 0  # But we want to look at a plane so the z extend is 0

    # And we pass the extent information into the request
    request.extent(extent)

    # Second, we need to position our extent box in the data
    # set. Initially, the extent will be centered around the origin. To
    # see the middle of the data we want translate our request to the
    # center of the data's bounding box

    # So we create the corresponding transformation matrix
    matrix = translationMatrix(
        (left[0] + right[0]) / 2,
        (left[1] + right[1]) / 2,
        (left[2] + right[2]) / 2,
    )
    # And pass this matrix to the request
    request.transformation(matrix)

    # Third, we want to indicate to the ViSUS system that we are
    # really interested in a 2D slice of the data (rather than a
    # degenerate volume) as slices are a special case and implement some
    # special user interactions
    request.requestType(VISUS_2D_REQUEST)

    # Finally, we describe the resolution at which we want to see our
    # data. The resolution is defined in terms ofo sub-sampling
    # "strides" where a stride of 1 defines the full resolution data a
    # stride of 2, the data sub-sampled by a factor of 2 etc.. Strides
    # must be powers of two but can be independently set for each
    # dimension. Furthermore, for large data it can be useful to
    # progressively refine the data starting at some higher strides /
    # coarser resolution, ending at some lower strides / finer
    # resolution. This preserves interactivity while still providing
    # high resolution data if the request remains unchanged long enough

    # Since, for default scenes we expect the data to be small we only
    # want to see the highest resolution
    start = [1, 1, 1]
    end = [1, 1, 1]
    request.setStrides(start, end)

    # Armed with the description of the data and the request we just
    # constructed we create a scene graph node that will extract the
    # data for us. This node, will continuously test its current request
    # and update the data accordingly. Therefore, one could adapt the
    # scene by simply passing different requests to this node (which is
    # what the graphical user interface does on mouse movements or
    # keyboard commands)

    # Create a producer node specialized to extract and axis aligned
    # bounding box from a data set. As before with the root node the
    # node must be explicitly constructed.
    extractor = VisusAxisAlignedExtractor.construct()

    # Set the data to extract our data from
    extractor.setValue(data_description)
    extractor.setValue(request)  # Our default request
    extractor.setValue(bbox)
    # And the bounding box
    extractor.drawBoundingBox(False)

    # Now that we have a node that will extract the data we want to see
    # we construct another node to visualize the slice

    # We want to view an axis aligned slice of the data an the
    # appropriate visualization node is one for orthogonal slices
    slice = VisusOrthogonalSlice.construct()

    # Now we connect the output of the extractor to the input of the
    # visualization node
    if not slice.connectInput(extractor):
        raise RuntimeError("unable to connect extractor as slice input")

    # For reasons internal to the underpinnings of the ViSUS system the
    # visualization node must know about the current data request. The
    # simplest way of achieving this is to attach the slice node as
    # child to the extractor
    extractor.attachSubTree(slice, True)

    # and to inherit/share the request
    slice.inherit(VisusSharedDataRequest.typeIndex(), True)

    # In this configuration the slice node will naturally draw the data
    # at the position of the data request which is the natural
    # place. However, by manipulating the transformation matrix of the
    # slice node we could draw the data anywhere in space / on the screen

    # Instead of the default greyscale color map we want to use a
    # typical red-to-blue map
    color_map = banded()
    slice.setValue(color_map)

    # In order to see the slice even if it contains no data (if the
    # request has been moved outside the data set, or the data is
    # extremly large) we draw the bounding box of the slice
    slice.drawBoundingBox(True)

    # Now, we want to create labeled tickmarks to give the user a notion
    # of the data range.

    # Create a tickmark node that by default will create tickmarks along
    # the x-axis of its bounding box
    xTickMarks = VisusTickMarks.construct()

    # ViSUS uses "axis" to control the labels of images, graphs, and
    # also tickmarks. Here we get the current axis
    axis = xTickMarks.axis()
    axis.legendText("longitude")  # Set the label
    axis.labelFont(font)  # and font
    xTickMarks.axis(axis)  # and update the axis

    # Finally, we attach the tickmarks node as a child to the
    # extractor. By default a tickmarks node inherits the bounding box
    # of its parent and thus this node will now annotate the x-axis of
    # our data set
    extractor.attachSubTree(xTickMarks, True)

    # Create tickmarks for the y-axis in an identical fashion
    yTickMarks = VisusTickMarks.construct()

    # Except that now we must name the axis explicitly
    yTickMarks.direction(TM_Y_AXIS)
    axis = yTickMarks.axis()
    axis.legendText("latitude")
    axis.labelFont(font)
    yTickMarks.axis(axis)
    extractor.attachSubTree(yTickMarks, True)

    # Finally, we attach the whole subtree that renders the data plus
    # annotation to the root node
    root.attachSubTree(extractor, True)

    # To further enhance the scene we want to add the continental
    # outlines on top of the slice

    # First, we load the cdat internal world map
    world_map = loadWorldMap()

    # And parse it as a collection of polylines. A VisusIndexedData
    # object stores an array of n-dimensional points (n being 2 in this
    # case) and a set of elements defined as ordered lists of indices
    # into this array. Therefore, each contour of the world map is
    # parsed as a single element
    outlines = VisusIndexedData(2)
    for m in world_map:
        outlines.constructElement(m)

    # Once the data is constructed we create a display node designed to visualize it
    map = VisusIndexedDisplay.construct()

    # And load the data.
    map.loadData(outlines, 0)

    # The cdat world map is given within (-180,-90)x(180,90). However,
    # in order to display the normal lat,long, elev data easily in
    # cartesian space we told ViSUS the data units are meters (meaning
    # general distance) which will draw (0,0)x(360,180). To adjust the
    # map to the slice we therefore must shift it
    #map.getValue(matrix);
    #matrix = matrix * translationMatrix(180,90,0.01)
    #map.setValue(matrix)

    # Attach the map as child of the extractor. Note, that from this moment
    # on the map will inherit all transformations from the extractor and
    # thus "stick" to the extractor if it is moved or rotated
    extractor.attachSubTree(map)

    # Lastly, we attach more annotations to the scene

    # A VisusLabelNode is a general one line text of arbitrary font and
    # size. First, we create a title string using the variable name if
    # we found one
    label_node = VisusLabelNode.construct()
    title = "Variable: " + attributes["name"].replace("_", " ")
    label_node.text(title)
    label_node.setValue(font)

    # Positions of labels are given relative to the screen size
    label_node.position(-1, +0.8)
    root.attachSubTree(label_node, True)

    # If our data set is time-dependent we attach a label that displays
    # the current time step
    if "time" in attributes:
        time_node = VisusLabelNode.construct()
        t = attributes["time"]
        title = "Date: %02d/%02d/%04d" % (t.month, t.day, t.year)
        time_node.text(title)
        time_node.setValue(font)
        time_node.position(0.6, -0.95)
        root.attachSubTree(time_node, True)

    # A VisusColorBar displays a bar with a color map on the inside and
    # allows us to attach tickmarks and labels
    color_bar = VisusColorBar.construct()

    # As before fopr the tickmark node we modify the labels via the Axis construct
    axis = color_bar.axis()

    # If we found a variable name we use it as label
    if "var_name" in attributes:
        axis.legendText(attributes["var_name"])

    # If we found a range we use it as well.
    if "range" in attributes:
        axis.minValue(float(attributes["range"][0]))
        axis.maxValue(float(attributes["range"][1]))

    font.fontSize(4)
    axis.legendFont(font)
    axis.labelFont(font)
    color_bar.position(-1.2, -0.8)
    color_bar.axis(axis)

    # Finally, attach the color bar to the slice and make sure it
    # inherits its colormap from there
    slice.attachSubTree(color_bar, True)
    #color_bar.inherit(VisusSharedColorMap.typeIndex(),True)
    color_bar.inherit(8, True)

    # Lastly we must make sure that we actually see the data on the
    # screen which means we need to make sure that the data is scaled
    # and translated appropriately. (Alternatively, once can think of
    # this step as setting up the viewpoint of our virtual camera.

    # Using the current bounding box of the scene we adapt a default box
    # to the aspect ratios of of our scene and use it as our "world
    # coordinate system"
    world_box = constructWorldBox(bbox)
    root.setValue(bbox)

    # Now we make sure that the data is drawn in our standard coordinate
    # system
    root.mapToWorldBox(world_box)

    # Finally, most climate data contains significantly more samples in
    # x/y than in z. Since, for the cartesian slice we effecticely draw
    # the data in index space since is inconvinient as the volume wille
    # very "flat." To compensate for this we simply scale the z
    # coordinate of our system
    root.getValue(matrix)
    matrix = matrix * scaleMatrix(1, 1, 10)
    root.setValue(matrix)

    # As the final step we create ourselfs a window to display the scene
    # graph hanging under the root node
    createWindow(root)

    return root, data_description
Exemplo n.º 4
0
  def __init__( self, dataArray, title=None, usrAttribs=dict(), root=None,
                newWindow = True):

    # Creating the default root within the __init__ call somehow
    # causes the root variable to persist and only a single root to be
    # created for multiple scenes. To avoid this we use the explicit
    # None initialization
    if root == None:
      root = VisusGroup.construct()
      #root = VisusSceneNode.construct()
    
    # Create a root node
    self._root = root
   # self._root.drawBoundingBox(False)  
    
    # Create the attributes
    self._attribs = dict()

    # Create the extractor, data description and update attribs 
    self.setData(dataArray, usrAttribs)

    # Attach the extractor to the root
    self._root.attachSubTree(self._extractor, True)

    self._extractor.propagateUpwards(VISUS_GLOBALTIME_TYPEID);

    # Create the drawing window
    if newWindow:
      print "Creating new window of root ", root
      createWindow(self._root)

    # Create the node for the slice of data
    self._orthoSlice = VisusOrthogonalSlice.construct()

    # Connect the output of the extractor to the input of each slice node
    if not self._orthoSlice.connectInput(self._extractor):
      raise RuntimeError("unable to connect extractor1 as slice input")
  
    # Attach the ortho slice to the root as a subtree
    self._extractor.attachSubTree(self._orthoSlice)

    # Inherit/Share the data request
    # Now that we have positioned the slices where we want them we want
    # to freeze their position. To do this we simply uninherit the data
    self._orthoSlice.inherit(VisusSharedDataRequest.typeIndex(),True)

    # This should be done autmoatically in the SliceNode
    # Set the correct bounding box for the slice
    # request = VisusDataRequest()
    # self._orthoSlice.getValue(request)
    # self._orthoSlice.setValue(request.queryRegion())
  
    # Set the colormap
    #self.setColorMap(ice())
    self.setColorMap(bgry())
    
    # Draw the bounding boxes of the slice
    self._orthoSlice.drawBoundingBox(True) 

    # Set up the annotations for the colorbar etc
    self.setAnnote()

    # Add the world map
    world_map = self.loadWorldMap()

    # And parse it as a collection of polylines. A VisusIndexedData
    # object stores an array of n-dimensional points (n being 2 in this
    # case) and a set of elements defined as ordered lists of indices
    # into this array. Therefore, each contour of the world map is
    # parsed as a single element
    outlines = VisusIndexedData(2)
    for m in world_map:
      outlines.constructElement(m)
      
    # Once the data is constructed we create a display node designed to visualize it
    self._map = VisusIndexedDisplay.construct()

    # And load the data. 
    self._map.loadData(outlines,0)
    
    # Move the map to the top of the data set so that is it always above the slice
    matrix = translationMatrix(0,0,0)
    self._map.getValue(matrix)
    matrix = matrix * translationMatrix(0,0,0.01)

    # This is a really ugly hack to adjust for the [0,360] [-180,180] ambiguity
    if self._bbox[0] > -90:
      matrix = matrix * translationMatrix(180,0,0)

    self._map.setValue(matrix)

    # Attach the map as child of the extractor. Note, that from this moment
    # on the map will inherit all transformations from the extractor and
    # thus "stick" to the extractor if it is moved or rotated
    self._orthoSlice.attachSubTree(self._map)
    #self._extractor.attachSubTree(self._map)

    # Add a title to the scene
    if(title==None):
      if "name" in self._attribs:
        title = self._attribs["name"].replace("_", " ")
      else:
        title = "Title"

    font = VisusFont()
    font.fontSize(12);
    self._title = VisusLabelNode.construct()
    self._title.text(title)
    self._title.setValue(font)
    self._title.position( 0, 0.92)
    self._root.attachSubTree(self._title,True)