def __init__(self, dataArray, heightDataArray=[], isoDataArray=[], mask=0, title=None, usrAttribs=dict(), root=None, newWindow=True): mask = 1 # 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() # Create a root node (or get one from the user) self._root = root self._root.drawBoundingBox(False) # Create the attributes self._attribs = dict() # Create the heightattributes self._heightattribs = dict() # Create the iso attributes self._isoattribs = dict() # Set whether we mask the ocean, the land, or nothing self._mask = mask # Create a radius object self._radius = VisusEarthRadius() # Create an earth node self._earth = VisusEarthNode.construct() # Create a node for the background image self._bgEarth = VisusEarthNode.construct() # Set the radius of the earth self.setEarthRadius(100.0) # Set the data that we have self._haveHeightData = True if (len(heightDataArray) == 0): self._haveHeightData = False self._haveIsoData = True if (len(isoDataArray) == 0): self._haveIsoData = False # Create the extractor, data description and update attribs self.setData(dataArray, heightDataArray, isoDataArray, usrAttribs) # Attach the texture extractor to the earth self._earth.attachSubTree(self._extractortexture, True) # Add the isosurface if (self._haveIsoData): self._isosurface = self.addIso(self._extractoriso) # Set the isoValue self._isoValue = VisusIsoValue(40) self._isosurface.setValue(self._isoValue) # Attach the iso extractor to the earth self._earth.attachSubTree(self._extractoriso, True) # Attach the height extractor to the earth if (self._haveHeightData): self._earth.attachSubTree(self._extractorheight, True) # Finally attach the earth node to the root self._root.attachSubTree(self._earth, True) # Create the drawing window if newWindow: createWindow(self._root) # If masking is enabled, set it up if self._mask != 0: self.setUpMasking() # Connect the extractor which is a VisusProducer # (which is really a VisusAxisAlignedExtractor) if not self._earth.connectTexture(self._extractortexture): raise RuntimeError( "Unable to connect extractor as EarthNode input") # Connect the height extractor which is a VisusProducer # (which is really a VisusAxisAlignedExtractor) if (self._haveHeightData): if not self._earth.connectHeight(self._extractorheight): raise RuntimeError( "Unable to connect extractor as EarthNode input") # Set the earth as periodic self._earth.periodic(True) # Rotate the hole to the top self.rotateEarth(0.0, -1.0) # Set the colormap self.setColorMap(banded()) # Create the colorbar for the colormap self._colorBar = VisusColorBar.construct() # Set the annotations for the scene self.setAnnote() self._earth.attachSubTree(self._colorBar, True) self._colorBar.inherit(8, True) # Position the colorbar self._colorBar.position(-.5, -0.8) # 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._earth.attachSubTree(self._title) self._extractortexture.propagateUpwards(VISUS_GLOBALTIME_TYPEID)
def sphereSlice(data=None, **keywords): """ This function constructs a default ViSUS scene displaying a single z-slice through a regular block of data mapped onto the earth. 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: # 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() # 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) extractor.visible(False) # A VisusEarthNode behaves much like a VisusOrthogonalSlice (see # cartesianSlice) except that it expects the data to be # angle+elevation and maps the slice onto the sphere. earth = VisusEarthNode.construct() # Now we connect the output of the extractor to the input of the # visualization node if not earth.connectTexture(extractor): raise RuntimeError("unable to connect slice as earth 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(earth) # and to inherit/share the request earth.inherit(VisusSharedDataRequest.typeIndex(), True) # The default view displays the box [-10,-10,-10]x[10,10,10] so we # set the radius to 3 to get a reasonably size sphere. radius = VisusEarthRadius() radius.set(3.0) earth.setValue(radius) # Instead of the default greyscale color map we want to use a # typical red-to-blue map color_map = banded() earth.setValue(color_map) earth.periodic(True) # Finally, we attach the whole subtree that renders the data to the # root node root.attachSubTree(extractor) # 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 earth.attachSubTree(color_bar) #color_bar.inherit(VisusSharedColorMap.typeIndex(),True) color_bar.inherit(8, True) createWindow(root) return root, data_description
glutMouseFunc(mouse) glutKeyboardFunc(keyboard) glutMotionFunc(motion) glutIdleFunc(idle) # Create the default scene graph gBBox = VisusBoundingBox() gBBox.set(-5, -5, -5, 5, 5, 5) gRoot = VisusSceneNode.construct() gRoot.setValue(gBBox) gFocus = gRoot # Create Earth Radius radius = VisusEarthRadius() radius.set(3.0) # Create Earth earth = VisusEarthNode.construct() earth.setValue(radius) gRoot.attachSubTree(earth) gFocus = earth # Load Texture If Given if filename is not None: texture = VisusTexture() texture.loadPPM(filename) earth.loadData(texture, 0) # Run The Main glutMainLoop()
def sphereSlice(data=None,**keywords): """ This function constructs a default ViSUS scene displaying a single z-slice through a regular block of data mapped onto the earth. 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: # 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() # 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); extractor.visible(False) # A VisusEarthNode behaves much like a VisusOrthogonalSlice (see # cartesianSlice) except that it expects the data to be # angle+elevation and maps the slice onto the sphere. earth = VisusEarthNode.construct() # Now we connect the output of the extractor to the input of the # visualization node if not earth.connectTexture(extractor): raise RuntimeError("unable to connect slice as earth 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(earth) # and to inherit/share the request earth.inherit(VisusSharedDataRequest.typeIndex(),True) # The default view displays the box [-10,-10,-10]x[10,10,10] so we # set the radius to 3 to get a reasonably size sphere. radius = VisusEarthRadius() radius.set(3.0) earth.setValue(radius) # Instead of the default greyscale color map we want to use a # typical red-to-blue map color_map = banded() earth.setValue(color_map) earth.periodic(True) # Finally, we attach the whole subtree that renders the data to the # root node root.attachSubTree(extractor) # 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 earth.attachSubTree(color_bar) #color_bar.inherit(VisusSharedColorMap.typeIndex(),True) color_bar.inherit(8,True) createWindow(root) return root, data_description
def __init__( self, dataArray, heightDataArray=[], isoDataArray=[], mask=0, title=None, usrAttribs=dict(), root=None, newWindow = True): mask = 1 # 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() # Create a root node (or get one from the user) self._root = root self._root.drawBoundingBox(False) # Create the attributes self._attribs = dict() # Create the heightattributes self._heightattribs = dict() # Create the iso attributes self._isoattribs = dict() # Set whether we mask the ocean, the land, or nothing self._mask = mask # Create a radius object self._radius = VisusEarthRadius() # Create an earth node self._earth = VisusEarthNode.construct() # Create a node for the background image self._bgEarth = VisusEarthNode.construct() # Set the radius of the earth self.setEarthRadius(100.0) # Set the data that we have self._haveHeightData = True if(len(heightDataArray) == 0): self._haveHeightData = False self._haveIsoData = True if(len(isoDataArray)== 0): self._haveIsoData = False # Create the extractor, data description and update attribs self.setData(dataArray, heightDataArray, isoDataArray, usrAttribs) # Attach the texture extractor to the earth self._earth.attachSubTree(self._extractortexture, True) # Add the isosurface if(self._haveIsoData): self._isosurface = self.addIso(self._extractoriso) # Set the isoValue self._isoValue = VisusIsoValue(40) self._isosurface.setValue(self._isoValue) # Attach the iso extractor to the earth self._earth.attachSubTree(self._extractoriso, True) # Attach the height extractor to the earth if(self._haveHeightData): self._earth.attachSubTree(self._extractorheight, True) # Finally attach the earth node to the root self._root.attachSubTree(self._earth,True); # Create the drawing window if newWindow: createWindow(self._root) # If masking is enabled, set it up if self._mask != 0: self.setUpMasking() # Connect the extractor which is a VisusProducer # (which is really a VisusAxisAlignedExtractor) if not self._earth.connectTexture(self._extractortexture): raise RuntimeError("Unable to connect extractor as EarthNode input") # Connect the height extractor which is a VisusProducer # (which is really a VisusAxisAlignedExtractor) if(self._haveHeightData): if not self._earth.connectHeight(self._extractorheight): raise RuntimeError("Unable to connect extractor as EarthNode input") # Set the earth as periodic self._earth.periodic(True) # Rotate the hole to the top self.rotateEarth(0.0, -1.0) # Set the colormap self.setColorMap(banded()) # Create the colorbar for the colormap self._colorBar = VisusColorBar.construct() # Set the annotations for the scene self.setAnnote() self._earth.attachSubTree(self._colorBar, True) self._colorBar.inherit(8, True) # Position the colorbar self._colorBar.position(-.5,-0.8) # 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._earth.attachSubTree(self._title) self._extractortexture.propagateUpwards(VISUS_GLOBALTIME_TYPEID);
glutMotionFunc( motion ) glutIdleFunc( idle ) # Create the default scene graph gBBox = VisusBoundingBox() gBBox.set(-5,-5,-5,5,5,5) gRoot = VisusSceneNode.construct() gRoot.setValue(gBBox) gFocus = gRoot # Create Earth Radius radius = VisusEarthRadius() radius.set(3.0) # Create Earth earth = VisusEarthNode.construct() earth.setValue(radius) gRoot.attachSubTree(earth) gFocus = earth # Load Texture If Given if filename is not None: texture = VisusTexture() texture.loadPPM(filename) earth.loadData(texture, 0) # Run The Main glutMainLoop()