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)
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
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
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)