def buildSpiralPolyDataItem(drawOpts): xmin, xmax, ymin, ymax = drawOpts['vp'] color = drawOpts['color'] lineWidth = drawOpts['lineWidth'] stippleType = drawOpts['stippleType'] spiralPoints = [[0.1, 0.1], [0.1, 0.9], [0.9, 0.9], [0.9, 0.2], [0.2, 0.2], [0.2, 0.8], [0.8, 0.8], [0.8, 0.3], [0.3, 0.3], [0.3, 0.7], [0.7, 0.7], [0.7, 0.4], [0.4, 0.4], [0.4, 0.6], [0.6, 0.6], [0.6, 0.5]] xformedPoints = [[ affine(p[0], 0.0, 1.0, xmin, xmax), affine(p[1], 0.0, 1.0, ymin, ymax), 0.0 ] for p in spiralPoints] pd = vtk.vtkPolyData() pd.Allocate(50) pts = vtk.vtkPoints() for pt in xformedPoints: pts.InsertNextPoint(pt) pd.SetPoints(pts) numpts = len(xformedPoints) pd.InsertNextCell(vtk.VTK_POLY_LINE, numpts, [idx for idx in range(numpts)]) colors = vtk.vtkUnsignedCharArray() colors.SetNumberOfComponents(4) colors.SetNumberOfTuples(1) colors.SetTuple4(0, color[0], color[1], color[2], 255) # Specify line width floatValue = vtk.vtkFloatArray() floatValue.SetNumberOfComponents(1) floatValue.SetName("LineWidth") floatValue.InsertNextValue(lineWidth) pd.GetFieldData().AddArray(floatValue) # Specify stipple pattern intValue = vtk.vtkIntArray() intValue.SetNumberOfComponents(1) intValue.SetName("StippleType") intValue.InsertNextValue(stippleType) pd.GetFieldData().AddArray(intValue) item = vtk.vtkPolyDataItem() item.SetPolyData(pd) item.SetMappedColors(colors) item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) item.SetVisible(True) return item
def _plotInternal(self): """Overrides baseclass implementation.""" # Special case for custom boxfills: if self._gm.boxfill_type != "custom": self._plotInternalBoxfill() else: self._plotInternalCustomBoxfill() if self._maskedDataMapper is not None: self._mappers.insert(0, self._maskedDataMapper) plotting_dataset_bounds = self.getPlottingBounds() x1, x2, y1, y2 = plotting_dataset_bounds if self._vtkGeoTransform: x1 = self._vtkDataSetBoundsNoMask[0] x2 = self._vtkDataSetBoundsNoMask[1] y1 = self._vtkDataSetBoundsNoMask[2] y2 = self._vtkDataSetBoundsNoMask[3] drawAreaBounds = vcs2vtk.computeDrawAreaBounds([x1, x2, y1, y2], self._context_flipX, self._context_flipY) else: drawAreaBounds = vcs2vtk.computeDrawAreaBounds([x1, x2, y1, y2]) # And now we need actors to actually render this thing actors = [] cti = 0 ctj = 0 _colorMap = self.getColorMap() _style = self._gm.fillareastyle vp = self._resultDict.get('ratio_autot_viewport', [ self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2 ]) fareapixelspacing, fareapixelscale = self._patternSpacingAndScale() # view and interactive area view = self._context().contextView area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) [renWinWidth, renWinHeight] = self._context().renWin.GetSize() # vp = vcs2vtk.adjustBounds(vp, 0.9, 0.9) geom = vtk.vtkRecti(int(round(vp[0] * renWinWidth)), int(round(vp[2] * renWinHeight)), int(round((vp[1] - vp[0]) * renWinWidth)), int(round((vp[3] - vp[2]) * renWinHeight))) vcs2vtk.configureContextArea(area, drawAreaBounds, geom) midx = 0 for mapper in self._mappers: act = vtk.vtkActor() act.SetMapper(mapper) mapper.Update() poly = mapper.GetInput() if _style == "solid": if self._needsCellData: attrs = poly.GetCellData() else: attrs = poly.GetPointData() data = attrs.GetScalars() deleteColors = False if data: lut = mapper.GetLookupTable() range = mapper.GetScalarRange() lut.SetRange(range) mappedColors = lut.MapScalars(data, vtk.VTK_COLOR_MODE_DEFAULT, 0) deleteColors = True else: loc = 'point' numTuples = poly.GetNumberOfPoints() if self._needsCellData: loc = 'cell' numTuples = poly.GetNumberOfCells() msg = 'WARNING: boxfill pipeline: poly does not have Scalars' msg = msg + 'array on {0} data, using solid color'.format( loc) print(msg) color = [0, 0, 0, 255] mappedColors = vcs2vtk.generateSolidColorArray( numTuples, color) mappedColors.SetName('Colors') item = vtk.vtkPolyDataItem() item.SetPolyData(poly) if self._needsCellData: item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) else: item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_POINT_DATA) item.SetMappedColors(mappedColors) if deleteColors: mappedColors.FastDelete() area.GetDrawAreaItem().AddItem(item) if mapper is self._maskedDataMapper: actors.append([ item, self._maskedDataMapper, plotting_dataset_bounds ]) else: actors.append([item, plotting_dataset_bounds]) if mapper is not self._maskedDataMapper: if self._gm.boxfill_type == "custom": # Patterns/hatches creation for custom boxfill plots patact = None tmpColors = self._customBoxfillArgs["tmpColors"] if ctj >= len(tmpColors[cti]): ctj = 0 cti += 1 # Since pattern creation requires a single color, assuming the first c = self.getColorIndexOrRGBA(_colorMap, tmpColors[cti][ctj]) patact = fillareautils.make_patterned_polydata( poly, fillareastyle=_style, fillareaindex=self._customBoxfillArgs["tmpIndices"] [cti], fillareacolors=c, fillareaopacity=self._customBoxfillArgs["tmpOpacities"] [cti], fillareapixelspacing=fareapixelspacing, fillareapixelscale=fareapixelscale, size=self._context().renWin.GetSize(), screenGeom=self._context().renWin.GetSize()) ctj += 1 if patact is not None: patMapper = patact.GetMapper() patMapper.Update() patPoly = patMapper.GetInput() patItem = vtk.vtkPolyDataItem() patItem.SetPolyData(patPoly) patItem.SetScalarMode( vtk.VTK_SCALAR_MODE_USE_CELL_DATA) colorArray = patPoly.GetCellData().GetArray('Colors') patItem.SetMappedColors(colorArray) area.GetDrawAreaItem().AddItem(patItem) actors.append([patItem, plotting_dataset_bounds]) midx += 1 self._resultDict["vtk_backend_actors"] = actors z, t = self.getZandT() kwargs = { "vtk_backend_grid": self._vtkDataSet, "dataset_bounds": self._vtkDataSetBounds, "plotting_dataset_bounds": plotting_dataset_bounds, "vtk_dataset_bounds_no_mask": self._vtkDataSetBoundsNoMask, "vtk_backend_geo": self._vtkGeoTransform, "vtk_backend_draw_area_bounds": drawAreaBounds, "vtk_backend_viewport_scale": [self._context_xScale, self._context_yScale] } if ("ratio_autot_viewport" in self._resultDict): kwargs["ratio_autot_viewport"] = vp self._resultDict.update(self._context().renderTemplate( self._template, self._data1, self._gm, t, z, **kwargs)) if getattr(self._gm, "legend", None) is not None: self._contourLabels = self._gm.legend if self._gm.ext_1: if isinstance(self._contourLevels[0], list): if numpy.less(abs(self._contourLevels[0][0]), 1.e20): # Ok we need to add the ext levels self._contourLevels.insert( 0, [-1.e20, self._contourLevels[0][0]]) else: if numpy.less(abs(self._contourLevels[0]), 1.e20): # need to add an ext self._contourLevels.insert(0, -1.e20) if self._gm.ext_2: if isinstance(self._contourLevels[-1], list): if numpy.less(abs(self._contourLevels[-1][1]), 1.e20): # need ext self._contourLevels.append( [self._contourLevels[-1][1], 1.e20]) else: if numpy.less(abs(self._contourLevels[-1]), 1.e20): # need exts self._contourLevels.append(1.e20) # Do not pass patterning parameters for color bar rendering if the # boxfill type is non-custom patternArgs = {} if self._gm.boxfill_type == "custom": patternArgs['style'] = self._gm.fillareastyle patternArgs['index'] = self._gm.fillareaindices patternArgs['opacity'] = self._gm.fillareaopacity # Compensate for the different viewport size of the colorbar patternArgs['pixelspacing'] = [ int(fareapixelspacing[0] / (vp[1] - vp[0])), int(fareapixelspacing[1] / (vp[3] - vp[2])) ] patternArgs['pixelscale'] = fareapixelscale / (vp[1] - vp[0]) self._resultDict.update(self._context().renderColorBar( self._template, self._contourLevels, self._contourColors, self._contourLabels, self.getColorMap(), **patternArgs)) projection = vcs.elements["projection"][self._gm.projection] kwargs['xaxisconvert'] = self._gm.xaxisconvert kwargs['yaxisconvert'] = self._gm.yaxisconvert if self._data1.getAxis(-1).isLongitude() and self._data1.getAxis( -2).isLatitude(): self._context().plotContinents( self._plot_kargs.get("continents", self._useContinents), plotting_dataset_bounds, projection, self._dataWrapModulo, vp, self._template.data.priority, **kwargs)
area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) drawAreaBounds = vtk.vtkRectd(0.0, 0.0, 1.0, 1.0) vp = [0.0500000007451, 0.949999988079, 0.259999990463, 0.860000014305] screenGeometry = vtk.vtkRecti(int(vp[0] * width), int(vp[2] * height), int((vp[1] - vp[0]) * width), int((vp[3] - vp[2]) * height)) for obj in polyDataList: pd = obj['poly'] col = obj['color'] item = vtk.vtkPolyDataItem() item.SetPolyData(pd) item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) mappedColors = vtk.vtkUnsignedCharArray() mappedColors.SetNumberOfComponents(4) mappedColors.SetNumberOfTuples(pd.GetNumberOfCells()) for i in range(pd.GetNumberOfCells()): mappedColors.SetTuple4(i, *col) item.SetMappedColors(mappedColors) item.SetVisible(True) area.GetDrawAreaItem().AddItem(item) lastItem = vtk.vtkPolyDataItem() pd, colors = buildPolyDataItemMixed()
def buildSpiralPolyDataItem(drawOpts): xmin, xmax, ymin, ymax = drawOpts['vp'] color = drawOpts['color'] lineWidth = drawOpts['lineWidth'] stippleType = drawOpts['stippleType'] spiralPoints = [ [0.1, 0.1], [0.1, 0.9], [0.9, 0.9], [0.9, 0.2], [0.2, 0.2], [0.2, 0.8], [0.8, 0.8], [0.8, 0.3], [0.3, 0.3], [0.3, 0.7], [0.7, 0.7], [0.7, 0.4], [0.4, 0.4], [0.4, 0.6], [0.6, 0.6], [0.6, 0.5] ] xformedPoints = [[ affine(p[0], 0.0, 1.0, xmin, xmax), affine(p[1], 0.0, 1.0, ymin, ymax), 0.0 ] for p in spiralPoints] pd = vtk.vtkPolyData() pd.Allocate(50) pts = vtk.vtkPoints() for pt in xformedPoints: pts.InsertNextPoint(pt) pd.SetPoints(pts) numpts = len(xformedPoints) pd.InsertNextCell(vtk.VTK_POLY_LINE, numpts, [idx for idx in range(numpts)]) colors = vtk.vtkUnsignedCharArray() colors.SetNumberOfComponents(4) colors.SetNumberOfTuples(1) colors.SetTuple4(0, color[0], color[1], color[2], 255) # Specify line width floatValue = vtk.vtkFloatArray() floatValue.SetNumberOfComponents(1) floatValue.SetName("LineWidth") floatValue.InsertNextValue(lineWidth) pd.GetFieldData().AddArray(floatValue) # Specify stipple pattern intValue = vtk.vtkIntArray() intValue.SetNumberOfComponents(1) intValue.SetName("StippleType") intValue.InsertNextValue(stippleType) pd.GetFieldData().AddArray(intValue) item = vtk.vtkPolyDataItem() item.SetPolyData(pd) item.SetMappedColors(colors) item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) item.SetVisible(True) return item
def _plotInternal(self): prepedContours = self._prepContours() tmpLevels = prepedContours["tmpLevels"] tmpIndices = prepedContours["tmpIndices"] tmpColors = prepedContours["tmpColors"] tmpOpacities = prepedContours["tmpOpacities"] style = self._gm.fillareastyle fareapixelspacing, fareapixelscale = self._patternSpacingAndScale() mappers = [] luts = [] geos = [] wholeDataMin, wholeDataMax = vcs.minmax(self._data1) plotting_dataset_bounds = self.getPlottingBounds() x1, x2, y1, y2 = plotting_dataset_bounds # We need to do the convertion thing _convert = self._gm.yaxisconvert _func = vcs.utils.axisConvertFunctions[_convert]["forward"] y1 = _func(y1) y2 = _func(y2) _convert = self._gm.xaxisconvert _func = vcs.utils.axisConvertFunctions[_convert]["forward"] x1 = _func(x1) x2 = _func(x2) _colorMap = self.getColorMap() for i, l in enumerate(tmpLevels): # Ok here we are trying to group together levels can be, a join # will happen if: next set of levels contnues where one left off # AND pattern is identical # TODO this should really just be a single polydata that is # colored by scalars: for j, color in enumerate(tmpColors[i]): mapper = vtk.vtkPolyDataMapper() lut = vtk.vtkLookupTable() th = vtk.vtkThreshold() th.ThresholdBetween(l[j], l[j + 1]) # th.SetInputConnection(self._vtkPolyDataFilter.GetOutputPort()) th.SetInputData(self._vtkDataSetFittedToViewport) geoFilter2 = vtk.vtkDataSetSurfaceFilter() geoFilter2.SetInputConnection(th.GetOutputPort()) # Make the polydata output available here for patterning later geoFilter2.Update() geos.append(geoFilter2) mapper.SetInputConnection(geoFilter2.GetOutputPort()) lut.SetNumberOfTableValues(1) r, g, b, a = self.getColorIndexOrRGBA(_colorMap, color) if style == 'solid': tmpOpacity = tmpOpacities[j] if tmpOpacity is None: tmpOpacity = a / 100. else: tmpOpacity = tmpOpacities[j] / 100. lut.SetTableValue(0, r / 100., g / 100., b / 100., tmpOpacity) else: lut.SetTableValue(0, 1., 1., 1., 0.) mapper.SetLookupTable(lut) mapper.SetScalarRange(l[j], l[j + 1]) luts.append([lut, [l[j], l[j + 1], True]]) # Store the mapper only if it's worth it? # Need to do it with the whole slab min/max for animation # purposes if not (l[j + 1] < wholeDataMin or l[j] > wholeDataMax): mappers.append(mapper) self._resultDict["vtk_backend_luts"] = luts if len(geos) > 0: self._resultDict["vtk_backend_geofilters"] = geos if self._maskedDataMapper is not None: # Note that this is different for meshfill -- others prepend. mappers.append(self._maskedDataMapper) wireColor = [0, 0, 0, 255] # Add a second mapper for wireframe meshfill: if self._gm.mesh: lineMappers = [] for polyMapper in mappers: edgeFilter = vtk.vtkExtractEdges() edgeFilter.SetInputConnection( polyMapper.GetInputConnection(0, 0)) lineMapper = vtk.vtkPolyDataMapper() lineMapper.SetInputConnection(edgeFilter.GetOutputPort(0)) lineMapper._useWireFrame = True lineMappers.append(lineMapper) mappers.extend(lineMappers) # And now we need actors to actually render this thing actors = [] vp = self._resultDict.get('ratio_autot_viewport', [ self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2 ]) cti = 0 ctj = 0 # view and interactive area view = self._context().contextView area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) adjusted_plotting_bounds = vcs2vtk.getProjectedBoundsForWorldCoords( plotting_dataset_bounds, self._gm.projection) drawAreaBounds = vcs2vtk.computeDrawAreaBounds( adjusted_plotting_bounds) [renWinWidth, renWinHeight] = self._context().renWin.GetSize() geom = vtk.vtkRecti(int(round(vp[0] * renWinWidth)), int(round(vp[2] * renWinHeight)), int(round((vp[1] - vp[0]) * renWinWidth)), int(round((vp[3] - vp[2]) * renWinHeight))) vcs2vtk.configureContextArea(area, drawAreaBounds, geom) for mapper in mappers: act = vtk.vtkActor() act.SetMapper(mapper) mapper.Update() poly = mapper.GetInput() item = None wireframe = False if hasattr(mapper, "_useWireFrame"): wireframe = True if wireframe: item = vtk.vtkPolyDataItem() item.SetPolyData(poly) colorArray = vtk.vtkUnsignedCharArray() colorArray.SetNumberOfComponents(4) for i in range(poly.GetNumberOfCells()): colorArray.InsertNextTypedTuple(wireColor) item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) item.SetMappedColors(colorArray) area.GetDrawAreaItem().AddItem(item) elif style == "solid": if self._needsCellData: attrs = poly.GetCellData() else: attrs = poly.GetPointData() data = attrs.GetScalars() deleteColors = False if data: lut = mapper.GetLookupTable() scalarRange = mapper.GetScalarRange() lut.SetRange(scalarRange) mappedColors = lut.MapScalars(data, vtk.VTK_COLOR_MODE_DEFAULT, 0) deleteColors = True else: loc = 'point' numTuples = poly.GetNumberOfPoints() if self._needsCellData: loc = 'cell' numTuples = poly.GetNumberOfCells() msg = 'WARNING: meshfill pipeline: poly does not have Scalars ' msg = msg + 'array on {0} data, using solid color'.format( loc) print(msg) color = [0, 0, 0, 255] mappedColors = vcs2vtk.generateSolidColorArray( numTuples, color) mappedColors.SetName('Colors') item = vtk.vtkPolyDataItem() item.SetPolyData(poly) if self._needsCellData: item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) else: item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_POINT_DATA) item.SetMappedColors(mappedColors) if deleteColors: mappedColors.FastDelete() area.GetDrawAreaItem().AddItem(item) # TODO See comment in boxfill. if item is not None: if mapper is self._maskedDataMapper: actors.append([ item, self._maskedDataMapper, plotting_dataset_bounds ]) else: actors.append([item, plotting_dataset_bounds]) if mapper is not self._maskedDataMapper: if not wireframe: # Since pattern creation requires a single color, assuming the # first if ctj >= len(tmpColors[cti]): ctj = 0 cti += 1 c = self.getColorIndexOrRGBA(_colorMap, tmpColors[cti][ctj]) patact = fillareautils.make_patterned_polydata( poly, fillareastyle=style, fillareaindex=tmpIndices[cti], fillareacolors=c, fillareaopacity=tmpOpacities[cti], fillareapixelspacing=fareapixelspacing, fillareapixelscale=fareapixelscale, size=self._context().renWin.GetSize(), screenGeom=self._context().renWin.GetSize()) ctj += 1 if patact is not None: actors.append([patact, plotting_dataset_bounds]) patMapper = patact.GetMapper() patMapper.Update() patPoly = patMapper.GetInput() patItem = vtk.vtkPolyDataItem() patItem.SetPolyData(patPoly) patItem.SetScalarMode( vtk.VTK_SCALAR_MODE_USE_CELL_DATA) colorArray = patPoly.GetCellData().GetArray('Colors') patItem.SetMappedColors(colorArray) area.GetDrawAreaItem().AddItem(patItem) actors.append([patItem, plotting_dataset_bounds]) z, t = self.getZandT() self._resultDict["vtk_backend_actors"] = actors kwargs = { "vtk_backend_grid": self._vtkDataSet, "dataset_bounds": self._vtkDataSetBounds, "plotting_dataset_bounds": plotting_dataset_bounds, "vtk_dataset_bounds_no_mask": self._vtkDataSetBoundsNoMask, "vtk_backend_geo": self._vtkGeoTransform, "vtk_backend_draw_area_bounds": drawAreaBounds, "vtk_backend_viewport_scale": [self._context_xScale, self._context_yScale] } if ("ratio_autot_viewport" in self._resultDict): kwargs["ratio_autot_viewport"] = vp self._resultDict.update(self._context().renderTemplate( self._template, self._data1, self._gm, t, z, X=numpy.arange(min(x1, x2), max(x1, x2) * 1.1, abs(x2 - x1) / 10.), Y=numpy.arange(min(y1, y2), max(y1, y2) * 1.1, abs(y2 - y1) / 10.), **kwargs)) legend = getattr(self._gm, "legend", None) if self._gm.ext_1: if isinstance(self._contourLevels[0], list): if numpy.less(abs(self._contourLevels[0][0]), 1.e20): # Ok we need to add the ext levels self._contourLevels.insert( 0, [-1.e20, self._contourLevels[0][0]]) else: if numpy.less(abs(self._contourLevels[0]), 1.e20): # need to add an ext self._contourLevels.insert(0, -1.e20) if self._gm.ext_2: if isinstance(self._contourLevels[-1], list): if numpy.less(abs(self._contourLevels[-1][1]), 1.e20): # need ext self._contourLevels.append( [self._contourLevels[-1][1], 1.e20]) else: if numpy.less(abs(self._contourLevels[-1]), 1.e20): # need exts self._contourLevels.append(1.e20) patternArgs = {} patternArgs['style'] = self._gm.fillareastyle patternArgs['index'] = self._gm.fillareaindices if patternArgs['index'] is None: patternArgs['index'] = [ 1, ] # Compensate for the different viewport size of the colorbar patternArgs['opacity'] = self._gm.fillareaopacity patternArgs['pixelspacing'] = [ int(fareapixelspacing[0] / (vp[1] - vp[0])), int(fareapixelspacing[1] / (vp[3] - vp[2])) ] patternArgs['pixelscale'] = fareapixelscale / (vp[1] - vp[0]) self._resultDict.update(self._context().renderColorBar( self._template, self._contourLevels, self._contourColors, legend, self.getColorMap(), **patternArgs)) projection = vcs.elements["projection"][self._gm.projection] kwargs['xaxisconvert'] = self._gm.xaxisconvert kwargs['yaxisconvert'] = self._gm.yaxisconvert self._context().plotContinents( self._plot_kargs.get("continents", self._useContinents), plotting_dataset_bounds, projection, self._dataWrapModulo, vp, self._template.data.priority, **kwargs)
def _plotInternal(self): """Overrides baseclass implementation.""" # Preserve time and z axis for plotting these inof in rendertemplate projection = vcs.elements["projection"][self._gm.projection] zaxis, taxis = self.getZandT() # Streamline color if (not self._gm.coloredbyvector): ln_tmp = self._gm.linetype if ln_tmp is None: ln_tmp = "default" try: ln_tmp = vcs.getline(ln_tmp) lwidth = ln_tmp.width[0] # noqa lcolor = ln_tmp.color[0] lstyle = ln_tmp.type[0] # noqa except Exception: lstyle = "solid" # noqa lwidth = 1. # noqa lcolor = [0., 0., 0., 100.] if self._gm.linewidth is not None: lwidth = self._gm.linewidth # noqa if self._gm.linecolor is not None: lcolor = self._gm.linecolor # The unscaled continent bounds were fine in the presence of axis # conversion, so save them here continentBounds = vcs2vtk.computeDrawAreaBounds( self._vtkDataSetBoundsNoMask, self._context_flipX, self._context_flipY) # Only scaling the data in the presence of axis conversion changes # the seed points in any other cases, and thus results in plots # different from the baselines but still fundamentally sound, it # seems. Always scaling the data results in no differences in the # plots between Context2D and the old baselines. # Transform the input data T = vtk.vtkTransform() T.Scale(self._context_xScale, self._context_yScale, 1.) self._vtkDataSetFittedToViewport = vcs2vtk.applyTransformationToDataset( T, self._vtkDataSetFittedToViewport) self._vtkDataSetBoundsNoMask = self._vtkDataSetFittedToViewport.GetBounds( ) polydata = self._vtkDataSetFittedToViewport plotting_dataset_bounds = self.getPlottingBounds() x1, x2, y1, y2 = plotting_dataset_bounds vp = self._resultDict.get('ratio_autot_viewport', [ self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2 ]) # view and interactive area view = self._context().contextView area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) drawAreaBounds = vcs2vtk.computeDrawAreaBounds( self._vtkDataSetBoundsNoMask, self._context_flipX, self._context_flipY) [renWinWidth, renWinHeight] = self._context().renWin.GetSize() geom = vtk.vtkRecti(int(round(vp[0] * renWinWidth)), int(round(vp[2] * renWinHeight)), int(round((vp[1] - vp[0]) * renWinWidth)), int(round((vp[3] - vp[2]) * renWinHeight))) vcs2vtk.configureContextArea(area, drawAreaBounds, geom) dataLength = polydata.GetLength() if (not self._gm.evenlyspaced): # generate random seeds in a circle centered in the center of # the bounding box for the data. # by default vtkPointSource uses a global random source in vtkMath which is # seeded only once. It makes more sense to seed a random sequence each time you draw # the streamline plot. pointSequence = vtk.vtkMinimalStandardRandomSequence() pointSequence.SetSeedOnly(1177) # replicate the seed from vtkMath seed = vtk.vtkPointSource() seed.SetNumberOfPoints(self._gm.numberofseeds) seed.SetCenter(polydata.GetCenter()) seed.SetRadius(dataLength / 2.0) seed.SetRandomSequence(pointSequence) seed.Update() seedData = seed.GetOutput() # project all points to Z = 0 plane points = seedData.GetPoints() for i in range(0, points.GetNumberOfPoints()): p = list(points.GetPoint(i)) p[2] = 0 points.SetPoint(i, p) if (self._gm.integratortype == 0): integrator = vtk.vtkRungeKutta2() elif (self._gm.integratortype == 1): integrator = vtk.vtkRungeKutta4() else: if (self._gm.evenlyspaced): warnings.warn( "You cannot use RungeKutta45 for evenly spaced streamlines." "Using RungeKutta4 instead") integrator = vtk.vtkRungeKutta4() else: integrator = vtk.vtkRungeKutta45() if (self._gm.evenlyspaced): streamer = vtk.vtkEvenlySpacedStreamlines2D() startseed = self._gm.startseed \ if self._gm.startseed else polydata.GetCenter() streamer.SetStartPosition(startseed) streamer.SetSeparatingDistance(self._gm.separatingdistance) streamer.SetSeparatingDistanceRatio( self._gm.separatingdistanceratio) streamer.SetClosedLoopMaximumDistance( self._gm.closedloopmaximumdistance) else: # integrate streamlines on normalized vector so that # IntegrationTime stores distance streamer = vtk.vtkStreamTracer() streamer.SetSourceData(seedData) streamer.SetIntegrationDirection(self._gm.integrationdirection) streamer.SetMinimumIntegrationStep(self._gm.minimumsteplength) streamer.SetMaximumIntegrationStep(self._gm.maximumsteplength) streamer.SetMaximumError(self._gm.maximumerror) streamer.SetMaximumPropagation(dataLength * self._gm.maximumstreamlinelength) streamer.SetInputData(polydata) streamer.SetInputArrayToProcess(0, 0, 0, 0, "vector") streamer.SetIntegrationStepUnit(self._gm.integrationstepunit) streamer.SetInitialIntegrationStep(self._gm.initialsteplength) streamer.SetMaximumNumberOfSteps(self._gm.maximumsteps) streamer.SetTerminalSpeed(self._gm.terminalspeed) streamer.SetIntegrator(integrator) # add arc_length to streamlines arcLengthFilter = vtk.vtkAppendArcLength() arcLengthFilter.SetInputConnection(streamer.GetOutputPort()) arcLengthFilter.Update() streamlines = arcLengthFilter.GetOutput() # glyph seed points contour = vtk.vtkContourFilter() contour.SetInputConnection(arcLengthFilter.GetOutputPort()) contour.SetValue(0, 0.001) if (streamlines.GetNumberOfPoints()): r = streamlines.GetPointData().GetArray("arc_length").GetRange() numberofglyphsoneside = self._gm.numberofglyphs // 2 for i in range(1, numberofglyphsoneside): contour.SetValue(i, r[1] / numberofglyphsoneside * i) else: warnings.warn( "No streamlines created. " "The 'startseed' parameter needs to be inside the domain and " "not over masked data.") contour.SetInputArrayToProcess(0, 0, 0, 0, "arc_length") # arrow glyph source glyph2DSource = vtk.vtkGlyphSource2D() glyph2DSource.SetGlyphTypeToTriangle() glyph2DSource.SetRotationAngle(-90) glyph2DSource.SetFilled(self._gm.filledglyph) # arrow glyph adjustment transform = vtk.vtkTransform() transform.Scale(1., self._gm.glyphbasefactor, 1.) transformFilter = vtk.vtkTransformFilter() transformFilter.SetInputConnection(glyph2DSource.GetOutputPort()) transformFilter.SetTransform(transform) transformFilter.Update() glyphLength = transformFilter.GetOutput().GetLength() # drawing the glyphs at the seed points glyph = vtk.vtkGlyph2D() glyph.SetInputConnection(contour.GetOutputPort()) glyph.SetInputArrayToProcess(1, 0, 0, 0, "vector") glyph.SetSourceData(transformFilter.GetOutput()) glyph.SetScaleModeToDataScalingOff() glyph.SetScaleFactor(dataLength * self._gm.glyphscalefactor / glyphLength) glyph.SetColorModeToColorByVector() glyphMapper = vtk.vtkPolyDataMapper() glyphActor = vtk.vtkActor() mapper = vtk.vtkPolyDataMapper() act = vtk.vtkActor() glyph.Update() glyphDataset = glyph.GetOutput() streamer.Update() lineDataset = streamer.GetOutput() deleteLineColors = False deleteGlyphColors = False # color the streamlines and glyphs cmap = self.getColorMap() if (self._gm.coloredbyvector): numLevels = len(self._contourLevels) - 1 while len(self._contourColors) < numLevels: self._contourColors.append(self._contourColors[-1]) lut = vtk.vtkLookupTable() lut.SetNumberOfTableValues(numLevels) for i in range(numLevels): r, g, b, a = self.getColorIndexOrRGBA(cmap, self._contourColors[i]) lut.SetTableValue(i, r / 100., g / 100., b / 100., a / 100.) lut.SetVectorModeToMagnitude() if numpy.allclose(self._contourLevels[0], -1.e20): lmn = self._vectorRange[0] else: lmn = self._contourLevels[0][0] if numpy.allclose(self._contourLevels[-1], 1.e20): lmx = self._vectorRange[1] else: lmx = self._contourLevels[-1][-1] lut.SetRange(lmn, lmx) mapper.ScalarVisibilityOn() mapper.SetLookupTable(lut) mapper.UseLookupTableScalarRangeOn() mapper.SetScalarModeToUsePointFieldData() mapper.SelectColorArray("vector") lineAttrs = lineDataset.GetPointData() lineData = lineAttrs.GetArray("vector") if lineData and numLevels: lineColors = lut.MapScalars(lineData, vtk.VTK_COLOR_MODE_DEFAULT, 0) deleteLineColors = True else: print( 'WARNING: streamline pipeline cannot map scalars for "lineData", using solid color' ) numTuples = lineDataset.GetNumberOfPoints() color = [0, 0, 0, 255] lineColors = vcs2vtk.generateSolidColorArray(numTuples, color) glyphMapper.ScalarVisibilityOn() glyphMapper.SetLookupTable(lut) glyphMapper.UseLookupTableScalarRangeOn() glyphMapper.SetScalarModeToUsePointFieldData() glyphMapper.SelectColorArray("VectorMagnitude") glyphAttrs = glyphDataset.GetPointData() glyphData = glyphAttrs.GetArray("VectorMagnitude") if glyphData and numLevels: glyphColors = lut.MapScalars(glyphData, vtk.VTK_COLOR_MODE_DEFAULT, 0) deleteGlyphColors = True else: print( 'WARNING: streamline pipeline cannot map scalars for "glyphData", using solid color' ) numTuples = glyphDataset.GetNumberOfPoints() color = [0, 0, 0, 255] glyphColors = vcs2vtk.generateSolidColorArray(numTuples, color) else: mapper.ScalarVisibilityOff() glyphMapper.ScalarVisibilityOff() if isinstance(lcolor, (list, tuple)): r, g, b, a = lcolor else: r, g, b, a = cmap.index[lcolor] act.GetProperty().SetColor(r / 100., g / 100., b / 100.) glyphActor.GetProperty().SetColor(r / 100., g / 100., b / 100.) fixedColor = [ int((r / 100.) * 255), int((g / 100.) * 255), int((b / 100.) * 255), 255 ] numTuples = lineDataset.GetNumberOfPoints() lineColors = vcs2vtk.generateSolidColorArray(numTuples, fixedColor) numTuples = glyphDataset.GetNumberOfPoints() glyphColors = vcs2vtk.generateSolidColorArray( numTuples, fixedColor) # Add the streamlines lineItem = vtk.vtkPolyDataItem() lineItem.SetPolyData(lineDataset) lineItem.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_POINT_DATA) lineItem.SetMappedColors(lineColors) if deleteLineColors: lineColors.FastDelete() area.GetDrawAreaItem().AddItem(lineItem) # Add the glyphs glyphItem = vtk.vtkPolyDataItem() glyphItem.SetPolyData(glyphDataset) glyphItem.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_POINT_DATA) glyphItem.SetMappedColors(glyphColors) if deleteGlyphColors: glyphColors.FastDelete() area.GetDrawAreaItem().AddItem(glyphItem) plotting_dataset_bounds = self.getPlottingBounds() vp = self._resultDict.get('ratio_autot_viewport', [ self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2 ]) kwargs = { 'vtk_backend_grid': self._vtkDataSet, 'dataset_bounds': self._vtkDataSetBounds, 'plotting_dataset_bounds': plotting_dataset_bounds, "vtk_dataset_bounds_no_mask": self._vtkDataSetBoundsNoMask, 'vtk_backend_geo': self._vtkGeoTransform, "vtk_backend_draw_area_bounds": continentBounds, "vtk_backend_viewport_scale": [self._context_xScale, self._context_yScale] } if ('ratio_autot_viewport' in self._resultDict): kwargs["ratio_autot_viewport"] = vp self._resultDict.update(self._context().renderTemplate( self._template, self._data1, self._gm, taxis, zaxis, **kwargs)) if (self._gm.coloredbyvector): self._resultDict.update(self._context().renderColorBar( self._template, self._contourLevels, self._contourColors, None, self.getColorMap())) kwargs['xaxisconvert'] = self._gm.xaxisconvert kwargs['yaxisconvert'] = self._gm.yaxisconvert if self._data1.getAxis(-1).isLongitude() and self._data1.getAxis( -2).isLatitude(): self._context().plotContinents( self._plot_kargs.get("continents", self._useContinents), plotting_dataset_bounds, projection, self._dataWrapModulo, vp, self._template.data.priority, **kwargs) self._resultDict["vtk_backend_actors"] = [[ lineItem, plotting_dataset_bounds ]] self._resultDict["vtk_backend_luts"] = [[None, None]]
def _plotInternal(self): """Overrides baseclass implementation.""" tmpLevels = [] tmpColors = [] tmpLineWidths = [] tmpLineTypes = [] linewidth = self._gm.linewidths self.extendAttribute(linewidth, default=1.0) linetype = self._gm.linetypes self.extendAttribute(linetype, default='solid') plotting_dataset_bounds = self.getPlottingBounds() x1, x2, y1, y2 = plotting_dataset_bounds for i, lv_tmp in enumerate(self._contourLevels): if i == 0: W = linewidth[i] S = linetype[i] C = [self._contourColors[i]] if lv_tmp == 1.e20: L = [-1.e20] else: L = [lv_tmp] else: if W == linewidth[i] and S == linetype[i]: # Ok same style and width, lets keep going L.append(lv_tmp) C.append(self._contourColors[i]) else: tmpLevels.append(L) tmpColors.append(C) tmpLineWidths.append(W) tmpLineTypes.append(S) L = [lv_tmp] C = [self._contourColors[i]] W = linewidth[i] S = linetype[i] tmpLevels.append(L) tmpColors.append(C) tmpLineWidths.append(W) tmpLineTypes.append(S) cots = [] textprops = [] luts = [] actors = [] mappers = [] if self._gm.label and (self._gm.text or self._gm.textcolors): # Text objects: if self._gm.text: texts = self._gm.text while len(texts) < len(self._contourLevels): texts.append(texts[-1]) else: texts = [None] * len(self._contourLevels) # Custom colors: if self._gm.textcolors: colorOverrides = self._gm.textcolors while len(colorOverrides) < len(self._contourLevels): colorOverrides.append(colorOverrides[-1]) else: colorOverrides = [None] * len(self._gm.text) # Custom background colors and opacities: backgroundColors = self._gm.labelbackgroundcolors if backgroundColors: while len(backgroundColors) < len(self._contourLevels): backgroundColors.append(backgroundColors[-1]) backgroundOpacities = self._gm.labelbackgroundopacities if backgroundOpacities: while len(backgroundOpacities) < len(self._contourLevels): backgroundOpacities.append(backgroundOpacities[-1]) else: backgroundOpacities = [100.0 for lev in self._contourLevels] countLevels = 0 vp = self._resultDict.get( 'ratio_autot_viewport', [self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2]) # view and interactive area view = self._context().contextView area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) adjusted_plotting_bounds = vcs2vtk.getProjectedBoundsForWorldCoords( plotting_dataset_bounds, self._gm.projection) drawAreaBounds = vcs2vtk.computeDrawAreaBounds(adjusted_plotting_bounds) [renWinWidth, renWinHeight] = self._context().renWin.GetSize() geom = vtk.vtkRecti(int(round(vp[0] * renWinWidth)), int(round(vp[2] * renWinHeight)), int(round((vp[1] - vp[0]) * renWinWidth)), int(round((vp[3] - vp[2]) * renWinHeight))) vcs2vtk.configureContextArea(area, drawAreaBounds, geom) # FIXME: This render call is needed to work around a bug somewhere in the # FIXME: vtkContextTransform code, where the transformation represented by # FIXME: Map[To|From]Scene() isn't set up properly until after a render call. self._context().renWin.Render() for i, l in enumerate(tmpLevels): numLevels = len(l) cot = vtk.vtkContourFilter() cot.SetInputData(self._vtkDataSetFittedToViewport) cot.SetNumberOfContours(numLevels) for n in range(numLevels): cot.SetValue(n, l[n]) # TODO remove update cot.Update() lut = vtk.vtkLookupTable() lut.SetNumberOfTableValues(len(tmpColors[i])) cmap = self.getColorMap() for n, col in enumerate(tmpColors[i]): r, g, b, a = self.getColorIndexOrRGBA(cmap, col) lut.SetTableValue(n, r / 100., g / 100., b / 100., a / 100.) # Setup isoline labels if self._gm.label: # Setup label mapping array: tpropMap = vtk.vtkDoubleArray() tpropMap.SetNumberOfComponents(1) tpropMap.SetNumberOfTuples(numLevels) for n, val in enumerate(l): tpropMap.SetTuple(n, [val]) # Prep text properties: tprops = vtk.vtkTextPropertyCollection() if self._gm.text or self._gm.textcolors: ttexts = texts[countLevels:(countLevels + len(l))] for idx, tc in enumerate(ttexts): if vcs.queries.istextcombined(tc): tt, to = tuple(tc.name.split(":::")) elif tc is None: tt = "default" to = "default" elif vcs.queries.istexttable(tc): tt = tc.name to = "default" elif vcs.queries.istextorientation(tc): to = tc.name tt = "default" elif isinstance(tc, str): sp = tc.split(":::") if len(sp) == 2: tt = sp[0] to = sp[1] else: # Hum don't know what do do with this if sp[0] in vcs.listelements("textcombined"): tc = vcs.gettextcombined(tc) tt, to = tuple(tc.name.split(":::")) elif sp[0] in vcs.listelements("textorientation"): to = sp[0] tt = "default" elif sp[0] in vcs.listelements("texttable"): tt = sp[0] to = "default" tt = vcs.createtexttable(None, tt) colorOverride = colorOverrides[countLevels + idx] if colorOverride is not None: tt.color = colorOverride tt = tt.name if backgroundColors is not None: texttbl = vcs.gettexttable(tt) texttbl.backgroundcolor = backgroundColors[countLevels + idx] if backgroundOpacities is not None: texttbl = vcs.gettexttable(tt) texttbl.backgroundopacity = backgroundOpacities[countLevels + idx] tprop = vtk.vtkTextProperty() vcs2vtk.prepTextProperty(tprop, self._context().renWin.GetSize(), to, tt, cmap=cmap) tprops.AddItem(tprop) if colorOverride is not None: del(vcs.elements["texttable"][tt]) else: # No text properties specified. Use the default: tprop = vtk.vtkTextProperty() vcs2vtk.prepTextProperty(tprop, self._context().renWin.GetSize(), cmap=cmap) tprop.SetBackgroundOpacity(1.0) tprops.AddItem(tprop) textprops.append(tprops) item = vtk.vtkLabeledContourPolyDataItem() item.SetTextProperties(tprops) item.SetTextPropertyMapping(tpropMap) item.SetLabelVisibility(1) item.SetSkipDistance(self._gm.labelskipdistance) mapper = vtk.vtkLabeledContourMapper() pdMapper = mapper.GetPolyDataMapper() luts.append([lut, [l[0], l[-1], False]]) else: # No isoline labels: item = vtk.vtkPolyDataItem() mapper = vtk.vtkPolyDataMapper() pdMapper = mapper luts.append([lut, [l[0], l[-1], False]]) pdMapper.SetLookupTable(lut) lut.SetRange(l[0], l[-1]) pdMapper.SetScalarRange(l[0], l[-1]) pdMapper.SetScalarModeToUsePointData() stripper = vtk.vtkStripper() stripper.SetInputConnection(cot.GetOutputPort()) mapper.SetInputConnection(stripper.GetOutputPort()) # TODO remove update, make pipeline stripper.Update() poly = stripper.GetOutput() mappers.append(mapper) cots.append(cot) if self._needsCellData: attrs = poly.GetCellData() scalarMode = vtk.VTK_SCALAR_MODE_USE_CELL_DATA else: attrs = poly.GetPointData() scalarMode = vtk.VTK_SCALAR_MODE_USE_POINT_DATA data = attrs.GetScalars() mappedColors = lut.MapScalars(data, vtk.VTK_COLOR_MODE_DEFAULT, 0) intValue = vtk.vtkIntArray() intValue.SetNumberOfComponents(1) intValue.SetName("StippleType") intValue.InsertNextValue(vcs2vtk.getStipple(tmpLineTypes[i])) poly.GetFieldData().AddArray(intValue) floatValue = vtk.vtkFloatArray() floatValue.SetNumberOfComponents(1) floatValue.SetName("LineWidth") floatValue.InsertNextValue(tmpLineWidths[i]) poly.GetFieldData().AddArray(floatValue) item.SetPolyData(poly) item.SetScalarMode(scalarMode) item.SetMappedColors(mappedColors) mappedColors.FastDelete() area.GetDrawAreaItem().AddItem(item) actors.append([item, plotting_dataset_bounds]) countLevels += len(l) if len(textprops) > 0: self._resultDict["vtk_backend_contours_labels_text_properties"] = \ textprops if len(luts) > 0: if self._gm.label: self._resultDict["vtk_backend_labeled_luts"] = luts else: self._resultDict["vtk_backend_luts"] = luts if len(cots) > 0: self._resultDict["vtk_backend_contours"] = cots if self._maskedDataMapper is not None: mappers.insert(0, self._maskedDataMapper) self._maskedDataMapper.Update() maskedData = self._maskedDataMapper.GetInput() maskedColors = vtk.vtkUnsignedCharArray() maskedColors.SetNumberOfComponents(4) for i in range(poly.GetNumberOfCells()): maskedColors.InsertNextTypedTuple([0, 0, 0, 255]) maskItem = vtk.vtkPolyDataItem() maskItem.SetPolyData(maskedData) maskItem.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) maskItem.SetMappedColors(maskedColors) area.GetDrawAreaItem().AddItem(maskItem) actors.append([maskItem, self._maskedDataMapper, plotting_dataset_bounds]) self._resultDict["vtk_backend_actors"] = actors z, t = self.getZandT() kwargs = { "vtk_backend_grid": self._vtkDataSet, "dataset_bounds": self._vtkDataSetBounds, "plotting_dataset_bounds": plotting_dataset_bounds, "vtk_dataset_bounds_no_mask": self._vtkDataSetBoundsNoMask, "vtk_backend_geo": self._vtkGeoTransform, "vtk_backend_draw_area_bounds": drawAreaBounds, "vtk_backend_viewport_scale": [ self._context_xScale, self._context_yScale ] } if ("ratio_autot_viewport" in self._resultDict): kwargs["ratio_autot_viewport"] = vp self._resultDict.update(self._context().renderTemplate( self._template, self._data1, self._gm, t, z, **kwargs)) projection = vcs.elements["projection"][self._gm.projection] kwargs['xaxisconvert'] = self._gm.xaxisconvert kwargs['yaxisconvert'] = self._gm.yaxisconvert if self._data1.getAxis(-1).isLongitude() and self._data1.getAxis(-2).isLatitude(): self._context().plotContinents(self._plot_kargs.get("continents", self._useContinents), plotting_dataset_bounds, projection, self._dataWrapModulo, vp, self._template.data.priority, **kwargs)
def _plotInternal(self): """Overrides baseclass implementation.""" preppedCountours = self._prepContours() tmpLevels = preppedCountours["tmpLevels"] tmpIndices = preppedCountours["tmpIndices"] tmpColors = preppedCountours["tmpColors"] tmpOpacities = preppedCountours["tmpOpacities"] style = self._gm.fillareastyle luts = [] cots = [] mappers = [] _colorMap = self.getColorMap() plotting_dataset_bounds = self.getPlottingBounds() x1, x2, y1, y2 = plotting_dataset_bounds fareapixelspacing, fareapixelscale = self._patternSpacingAndScale() for i, l in enumerate(tmpLevels): # Ok here we are trying to group together levels can be, a join # will happen if: next set of levels continues where one left off # AND pattern is identical mapper = vtk.vtkPolyDataMapper() lut = vtk.vtkLookupTable() cot = vtk.vtkBandedPolyDataContourFilter() cot.ClippingOn() # cot.SetInputData(self._vtkPolyDataFilter.GetOutput()) cot.SetInputData(self._vtkDataSetFittedToViewport) cot.SetNumberOfContours(len(l)) cot.SetClipTolerance(0.) for j, v in enumerate(l): cot.SetValue(j, v) cot.Update() cots.append(cot) mapper.SetInputConnection(cot.GetOutputPort()) lut.SetNumberOfTableValues(len(tmpColors[i])) for j, color in enumerate(tmpColors[i]): r, g, b, a = self.getColorIndexOrRGBA(_colorMap, color) if style == 'solid': tmpOpacity = tmpOpacities[j] if tmpOpacity is None: tmpOpacity = a / 100. else: tmpOpacity = tmpOpacities[j] / 100. lut.SetTableValue(j, r / 100., g / 100., b / 100., tmpOpacity) else: lut.SetTableValue(j, 1., 1., 1., 0.) luts.append([lut, [0, len(l) - 1, True]]) mapper.SetLookupTable(lut) minRange = 0 maxRange = len(l) - 1 if (i == 0 and self._scalarRange[0] < l[0]): # band 0 is from self._scalarRange[0] to l[0] # we don't show band 0 minRange += 1 mapper.SetScalarRange(minRange, maxRange) mapper.SetScalarModeToUseCellData() mappers.append(mapper) self._resultDict["vtk_backend_luts"] = luts if len(cots) > 0: self._resultDict["vtk_backend_contours"] = cots numLevels = len(self._contourLevels) if mappers == []: # ok didn't need to have special banded contours mapper = vtk.vtkPolyDataMapper() mappers = [mapper] # Colortable bit # make sure length match while len(self._contourColors) < len(self._contourLevels): self._contourColors.append(self._contourColors[-1]) lut = vtk.vtkLookupTable() lut.SetNumberOfTableValues(numLevels) for i in range(numLevels): r, g, b, a = self.getColorIndexOrRGBA(_colorMap, self._contourColors[i]) lut.SetTableValue(i, r / 100., g / 100., b / 100., a / 100.) mapper.SetLookupTable(lut) if numpy.allclose(self._contourLevels[0], -1.e20): lmn = self._min - 1. else: lmn = self._contourLevels[0] if numpy.allclose(self._contourLevels[-1], 1.e20): lmx = self._max + 1. else: lmx = self._contourLevels[-1] mapper.SetScalarRange(lmn, lmx) self._resultDict["vtk_backend_luts"] = [[lut, [lmn, lmx, True]]] if self._maskedDataMapper is not None: mappers.insert(0, self._maskedDataMapper) # And now we need actors to actually render this thing actors = [] ct = 0 vp = self._resultDict.get('ratio_autot_viewport', [self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2]) # view and interactive area view = self._context().contextView area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) adjusted_plotting_bounds = vcs2vtk.getProjectedBoundsForWorldCoords( plotting_dataset_bounds, self._gm.projection) drawAreaBounds = vcs2vtk.computeDrawAreaBounds(adjusted_plotting_bounds) [renWinWidth, renWinHeight] = self._context().renWin.GetSize() geom = vtk.vtkRecti(int(round(vp[0] * renWinWidth)), int(round(vp[2] * renWinHeight)), int(round((vp[1] - vp[0]) * renWinWidth)), int(round((vp[3] - vp[2]) * renWinHeight))) vcs2vtk.configureContextArea(area, drawAreaBounds, geom) for mapper in mappers: act = vtk.vtkActor() act.SetMapper(mapper) mapper.Update() poly = mapper.GetInput() if not poly: continue patact = None item = None if style == "solid": deleteColors = False attrs = poly.GetCellData() data = attrs.GetScalars() if data: lut = mapper.GetLookupTable() scalarRange = mapper.GetScalarRange() lut.SetRange(scalarRange) mappedColors = lut.MapScalars(data, vtk.VTK_COLOR_MODE_DEFAULT, 0) deleteColors = True else: print('WARNING: isofill pipeline: poly does not have Scalars array on cell data, using solid color') numTuples = poly.GetNumberOfCells() color = [0, 0, 0, 255] mappedColors = vcs2vtk.generateSolidColorArray(numTuples, color) scalarMode = vtk.VTK_SCALAR_MODE_USE_CELL_DATA item = vtk.vtkPolyDataItem() item.SetPolyData(poly) item.SetScalarMode(scalarMode) item.SetMappedColors(mappedColors) if deleteColors: mappedColors.FastDelete() area.GetDrawAreaItem().AddItem(item) if mapper is self._maskedDataMapper: actors.append([item, self._maskedDataMapper, plotting_dataset_bounds]) else: actors.append([item, plotting_dataset_bounds]) if mapper is not self._maskedDataMapper: # Since pattern creation requires a single color, assuming the first c = self.getColorIndexOrRGBA(_colorMap, tmpColors[ct][0]) patact = fillareautils.make_patterned_polydata(poly, fillareastyle=style, fillareaindex=tmpIndices[ct], fillareacolors=c, fillareaopacity=tmpOpacities[ct], fillareapixelspacing=fareapixelspacing, fillareapixelscale=fareapixelscale, size=self._context().renWin.GetSize(), screenGeom=[geom[2], geom[3]], vpScale=[self._context_xScale, self._context_yScale]) if patact is not None: patMapper = patact.GetMapper() patMapper.Update() patPoly = patMapper.GetInput() patItem = vtk.vtkPolyDataItem() patItem.SetPolyData(patPoly) patItem.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) colorArray = patPoly.GetCellData().GetArray('Colors') patItem.SetMappedColors(colorArray) area.GetDrawAreaItem().AddItem(patItem) actors.append([patItem, plotting_dataset_bounds]) # increment the count ct += 1 self._resultDict["vtk_backend_actors"] = actors z, t = self.getZandT() kwargs = { "vtk_backend_grid": self._vtkDataSet, "dataset_bounds": self._vtkDataSetBounds, "plotting_dataset_bounds": plotting_dataset_bounds, "vtk_dataset_bounds_no_mask": self._vtkDataSetBoundsNoMask, "vtk_backend_geo": self._vtkGeoTransform, "vtk_backend_draw_area_bounds": drawAreaBounds, "vtk_backend_viewport_scale": [ self._context_xScale, self._context_yScale ] } if ("ratio_autot_viewport" in self._resultDict): kwargs["ratio_autot_viewport"] = vp self._resultDict.update(self._context().renderTemplate( self._template, self._data1, self._gm, t, z, **kwargs)) legend = getattr(self._gm, "legend", None) if self._gm.ext_1: if isinstance(self._contourLevels[0], list): if numpy.less(abs(self._contourLevels[0][0]), 1.e20): # Ok we need to add the ext levels self._contourLevels.insert( 0, [-1.e20, self._contourLevels[0][0]]) else: if numpy.less(abs(self._contourLevels[0]), 1.e20): # need to add an ext self._contourLevels.insert(0, -1.e20) if self._gm.ext_2: if isinstance(self._contourLevels[-1], list): if numpy.less(abs(self._contourLevels[-1][1]), 1.e20): # need ext self._contourLevels.append([self._contourLevels[-1][1], 1.e20]) else: if numpy.less(abs(self._contourLevels[-1]), 1.e20): # need exts self._contourLevels.append(1.e20) # Compensate for the different viewport size of the colorbar legendpixspacing = [int(fareapixelspacing[0] / (vp[1] - vp[0])), int(fareapixelspacing[1] / (vp[3] - vp[2]))] legendpixscale = fareapixelscale / (vp[1] - vp[0]) self._resultDict.update( self._context().renderColorBar(self._template, self._contourLevels, self._contourColors, legend, self.getColorMap(), style=style, index=self._gm.fillareaindices, opacity=self._gm.fillareaopacity, pixelspacing=legendpixspacing, pixelscale=legendpixscale)) projection = vcs.elements["projection"][self._gm.projection] kwargs['xaxisconvert'] = self._gm.xaxisconvert kwargs['yaxisconvert'] = self._gm.yaxisconvert if self._data1.getAxis(-1).isLongitude() and self._data1.getAxis(-2).isLatitude(): self._context().plotContinents(self._plot_kargs.get("continents", self._useContinents), plotting_dataset_bounds, projection, self._dataWrapModulo, vp, self._template.data.priority, **kwargs)
def _plotInternal(self): """Overrides baseclass implementation.""" # Preserve time and z axis for plotting these inof in rendertemplate projection = vcs.elements["projection"][self._gm.projection] zaxis, taxis = self.getZandT() scale = 1.0 if self._vtkGeoTransform is not None: lat = None lon = None latAccessor = self._data1.getLatitude() lonAccessor = self._data1.getLongitude() if latAccessor: lat = latAccessor[:] if lonAccessor: lon = lonAccessor[:] newv = vtk.vtkDoubleArray() newv.SetNumberOfComponents(3) newv.InsertTypedTuple(0, [lon.min(), lat.min(), 0]) newv.InsertTypedTuple(1, [lon.max(), lat.max(), 0]) vcs2vtk.projectArray(newv, projection, self._vtkDataSetBounds) dimMin = [0, 0, 0] dimMax = [0, 0, 0] newv.GetTypedTuple(0, dimMin) newv.GetTypedTuple(1, dimMax) maxDimX = max(dimMin[0], dimMax[0]) maxDimY = max(dimMin[1], dimMax[1]) if lat.max() != 0.0: scale = abs((maxDimY / lat.max())) if lon.max() != 0.0: temp = abs((maxDimX / lon.max())) if scale < temp: scale = temp else: scale = 1.0 # Vector attempt ltp_tmp = self._gm.linetype if ltp_tmp is None: ltp_tmp = "default" try: ltp_tmp = vcs.getline(ltp_tmp) lwidth = ltp_tmp.width[0] # noqa lcolor = ltp_tmp.color[0] lstyle = ltp_tmp.type[0] # noqa except Exception: lstyle = "solid" # noqa lwidth = 1. # noqa lcolor = [0., 0., 0., 100.] if self._gm.linewidth is not None: lwidth = self._gm.linewidth # noqa if self._gm.linecolor is not None: lcolor = self._gm.linecolor arrow = vtk.vtkGlyphSource2D() arrow.SetGlyphTypeToArrow() arrow.SetOutputPointsPrecision(vtk.vtkAlgorithm.DOUBLE_PRECISION) arrow.FilledOff() plotting_dataset_bounds = self.getPlottingBounds() x1, x2, y1, y2 = plotting_dataset_bounds vp = self._resultDict.get('ratio_autot_viewport', [ self._template.data.x1, self._template.data.x2, self._template.data.y1, self._template.data.y2 ]) # The unscaled continent bounds were fine in the presence of axis # conversion, so save them here adjusted_plotting_bounds = vcs2vtk.getProjectedBoundsForWorldCoords( plotting_dataset_bounds, self._gm.projection) continentBounds = vcs2vtk.computeDrawAreaBounds( adjusted_plotting_bounds) # Transform the input data T = vtk.vtkTransform() T.Scale(self._context_xScale, self._context_yScale, 1.) self._vtkDataSetFittedToViewport = vcs2vtk.applyTransformationToDataset( T, self._vtkDataSetFittedToViewport) self._vtkDataSetBoundsNoMask = self._vtkDataSetFittedToViewport.GetBounds( ) polydata = self._vtkDataSetFittedToViewport # view and interactive area view = self._context().contextView area = vtk.vtkInteractiveArea() view.GetScene().AddItem(area) drawAreaBounds = vcs2vtk.computeDrawAreaBounds( self._vtkDataSetBoundsNoMask, self._context_flipX, self._context_flipY) [renWinWidth, renWinHeight] = self._context().renWin.GetSize() geom = vtk.vtkRecti(int(round(vp[0] * renWinWidth)), int(round(vp[2] * renWinHeight)), int(round((vp[1] - vp[0]) * renWinWidth)), int(round((vp[3] - vp[2]) * renWinHeight))) vcs2vtk.configureContextArea(area, drawAreaBounds, geom) # polydata = tmpMapper.GetInput() plotting_dataset_bounds = self.getPlottingBounds() vectors = polydata.GetPointData().GetVectors() if self._gm.scaletype == 'constant' or\ self._gm.scaletype == 'constantNNormalize' or\ self._gm.scaletype == 'constantNLinear': scaleFactor = scale * self._gm.scale else: scaleFactor = 1.0 glyphFilter = vtk.vtkGlyph2D() glyphFilter.SetInputArrayToProcess(1, 0, 0, 0, "vector") glyphFilter.SetSourceConnection(arrow.GetOutputPort()) glyphFilter.SetVectorModeToUseVector() # Rotate arrows to match vector data: glyphFilter.OrientOn() glyphFilter.ScalingOn() glyphFilter.SetScaleModeToScaleByVector() maxNormInVp = None minNormInVp = None # Find the min and max vector magnitudes (minNorm, maxNorm) = vectors.GetRange(-1) if maxNorm == 0: maxNorm = 1.0 if self._gm.scaletype == 'normalize' or self._gm.scaletype == 'linear' or\ self._gm.scaletype == 'constantNNormalize' or self._gm.scaletype == 'constantNLinear': if self._gm.scaletype == 'normalize' or self._gm.scaletype == 'constantNNormalize': scaleFactor /= maxNorm if self._gm.scaletype == 'linear' or self._gm.scaletype == 'constantNLinear': noOfComponents = vectors.GetNumberOfComponents() scalarArray = vtk.vtkDoubleArray() scalarArray.SetNumberOfComponents(1) scalarArray.SetNumberOfValues(vectors.GetNumberOfTuples()) oldRange = maxNorm - minNorm oldRange = 1.0 if oldRange == 0.0 else oldRange # New range min, max. newRangeValues = self._gm.scalerange newRange = newRangeValues[1] - newRangeValues[0] for i in range(0, vectors.GetNumberOfTuples()): norm = vtk.vtkMath.Norm(vectors.GetTuple(i), noOfComponents) newValue = (((norm - minNorm) * newRange) / oldRange) + newRangeValues[0] scalarArray.SetValue(i, newValue) polydata.GetPointData().SetScalars(scalarArray) maxNormInVp = newRangeValues[1] * scaleFactor minNormInVp = newRangeValues[0] * scaleFactor # Scale to vector magnitude: # NOTE: Currently we compute our own scaling factor since VTK does # it by clamping the values > max to max and values < min to min # and not remap the range. glyphFilter.SetScaleModeToScaleByScalar() if (maxNormInVp is None): maxNormInVp = maxNorm * scaleFactor # minNormInVp is left None, as it is displayed only for linear scaling. cmap = self.getColorMap() if isinstance(lcolor, (list, tuple)): r, g, b, a = lcolor else: r, g, b, a = cmap.index[lcolor] # act.GetProperty().SetColor(r / 100., g / 100., b / 100.) vtk_color = [int((c / 100.) * 255) for c in [r, g, b, a]] # Using the scaled data, set the glyph filter input glyphFilter.SetScaleFactor(scaleFactor) glyphFilter.SetInputData(polydata) glyphFilter.Update() # and set the arrows to be rendered. data = glyphFilter.GetOutput() floatValue = vtk.vtkFloatArray() floatValue.SetNumberOfComponents(1) floatValue.SetName("LineWidth") floatValue.InsertNextValue(lwidth) data.GetFieldData().AddArray(floatValue) item = vtk.vtkPolyDataItem() item.SetPolyData(data) item.SetScalarMode(vtk.VTK_SCALAR_MODE_USE_CELL_DATA) colorArray = vtk.vtkUnsignedCharArray() colorArray.SetNumberOfComponents(4) for i in range(data.GetNumberOfCells()): colorArray.InsertNextTypedTuple(vtk_color) item.SetMappedColors(colorArray) area.GetDrawAreaItem().AddItem(item) kwargs = { 'vtk_backend_grid': self._vtkDataSet, 'dataset_bounds': self._vtkDataSetBounds, 'plotting_dataset_bounds': plotting_dataset_bounds, "vtk_dataset_bounds_no_mask": self._vtkDataSetBoundsNoMask, 'vtk_backend_geo': self._vtkGeoTransform, "vtk_backend_draw_area_bounds": continentBounds, "vtk_backend_viewport_scale": [self._context_xScale, self._context_yScale] } if ('ratio_autot_viewport' in self._resultDict): kwargs["ratio_autot_viewport"] = vp self._resultDict.update(self._context().renderTemplate( self._template, self._data1, self._gm, taxis, zaxis, **kwargs)) # assume that self._data1.units has the proper vector units unitString = None if (hasattr(self._data1, 'units')): unitString = self._data1.units if self._vtkGeoTransform: worldWidth = self._vtkDataSetBoundsNoMask[ 1] - self._vtkDataSetBoundsNoMask[0] else: worldWidth = self._vtkDataSetBounds[1] - self._vtkDataSetBounds[0] worldToViewportXScale = (vp[1] - vp[0]) / worldWidth maxNormInVp *= worldToViewportXScale if (minNormInVp): minNormInVp *= worldToViewportXScale vcs.utils.drawVectorLegend(self._context().canvas, self._template.legend, lcolor, lstyle, lwidth, unitString, maxNormInVp, maxNorm, minNormInVp, minNorm, reference=self._gm.reference) kwargs['xaxisconvert'] = self._gm.xaxisconvert kwargs['yaxisconvert'] = self._gm.yaxisconvert if self._data1.getAxis(-1).isLongitude() and self._data1.getAxis( -2).isLatitude(): self._context().plotContinents( self._plot_kargs.get("continents", self._useContinents), plotting_dataset_bounds, projection, self._dataWrapModulo, vp, self._template.data.priority, **kwargs) self._resultDict["vtk_backend_actors"] = [[ item, plotting_dataset_bounds ]] self._resultDict["vtk_backend_glyphfilters"] = [glyphFilter] self._resultDict["vtk_backend_luts"] = [[None, None]]