Beispiel #1
0
    def in_display_plot(self, point, dp):
        #Normalize the point
        x, y = point
        w, h = self.interactor.GetRenderWindow().GetSize()
        if x > 1 or y > 1:
            point = (x / float(w), y / float(h))
            x, y = point

        if dp.g_type == "fillarea":
            fill = vcs.getfillarea(dp.g_name)
            info = editors.fillarea.inside_fillarea(fill, *point)
            if info is not None:
                self.clicked_info = info
                return fill
        elif dp.g_type == "line":
            l = vcs.getline(dp.g_name)
            # Uses screen_height to determine how much buffer space there is around the line
            info = editors.line.inside_line(l, *point, screen_height=h)
            if info is not None:
                self.clicked_info = info
                return l
        elif dp.g_type == "marker":
            m = vcs.getmarker(dp.g_name)
            info = editors.marker.inside_marker(m, point[0], point[1], w, h)
            if info is not None:
                self.clicked_info = info
                return m
        elif dp.g_type == "text":
            tc = vcs.gettextcombined(dp.g_name)
            info = editors.text.inside_text(tc, point[0], point[1], w, h)
            if info is not None:
                self.clicked_info = info
                return tc
        else:
            fudge = 5 / float(w)
            return in_template(point, t(dp.template), dp, (w, h), fudge=fudge)
Beispiel #2
0
    def in_display_plot(self, point, dp):
        #Normalize the point
        x, y = point
        w, h = self.interactor.GetRenderWindow().GetSize()
        if x > 1 or y > 1:
            point = (x / float(w), y / float(h))
            x, y = point

        if dp.g_type == "fillarea":
            fill = vcs.getfillarea(dp.g_name)
            info = editors.fillarea.inside_fillarea(fill, *point)
            if info is not None:
                self.clicked_info = info
                return fill
        elif dp.g_type == "line":
            l = vcs.getline(dp.g_name)
            # Uses screen_height to determine how much buffer space there is around the line
            info = editors.line.inside_line(l, *point, screen_height=h)
            if info is not None:
                self.clicked_info = info
                return l
        elif dp.g_type == "marker":
            m = vcs.getmarker(dp.g_name)
            info = editors.marker.inside_marker(m, point[0], point[1], w, h)
            if info is not None:
                self.clicked_info = info
                return m
        elif dp.g_type == "text":
            tc = vcs.gettextcombined(dp.g_name)
            info = editors.text.inside_text(tc, point[0], point[1], w, h)
            if info is not None:
                self.clicked_info = info
                return tc
        else:
            fudge = 5 / float(w)
            return in_template(point, t(dp.template), dp, (w, h), fudge=fudge)
Beispiel #3
0
    def plot(self, data1, data2, tmpl, gm, grid, transform):
        """Overrides baseclass implementation."""
        # Preserve time and z axis for plotting these inof in rendertemplate
        geo = None  # to make flake8 happy
        returned = {}
        taxis = data1.getTime()
        if data1.ndim > 2:
            zaxis = data1.getAxis(-3)
        else:
            zaxis = None

        # Ok get3 only the last 2 dims
        data1 = self._context().trimData2D(data1)
        data2 = self._context().trimData2D(data2)

        gridGenDict = vcs2vtk.genGridOnPoints(data1, gm, deep=False, grid=grid,
                                              geo=transform)
        for k in ['vtk_backend_grid', 'xm', 'xM', 'ym', 'yM', 'continents',
                  'wrap', 'geo']:
            exec("%s = gridGenDict['%s']" % (k, k))
        grid = gridGenDict['vtk_backend_grid']
        self._dataWrapModulo = gridGenDict['wrap']

        returned["vtk_backend_grid"] = grid
        returned["vtk_backend_geo"] = geo
        missingMapper = vcs2vtk.putMaskOnVTKGrid(data1, grid, None, False,
                                                 deep=False)

        # None/False are for color and cellData
        # (sent to vcs2vtk.putMaskOnVTKGrid)
        returned["vtk_backend_missing_mapper"] = (missingMapper, None, False)

        w = vcs2vtk.generateVectorArray(data1, data2, grid)

        grid.GetPointData().AddArray(w)

        # Vector attempt
        l = gm.line
        if l is None:
            l = "default"
        try:
            l = vcs.getline(l)
            lwidth = l.width[0]  # noqa
            lcolor = l.color[0]
            lstyle = l.type[0]  # noqa
        except:
            lstyle = "solid"  # noqa
            lwidth = 1.  # noqa
            lcolor = 0
        if gm.linewidth is not None:
            lwidth = gm.linewidth  # noqa
        if gm.linecolor is not None:
            lcolor = gm.linecolor

        arrow = vtk.vtkGlyphSource2D()
        arrow.SetGlyphTypeToArrow()
        arrow.FilledOff()

        glyphFilter = vtk.vtkGlyph2D()
        glyphFilter.SetInputData(grid)
        glyphFilter.SetInputArrayToProcess(1, 0, 0, 0, "vectors")
        glyphFilter.SetSourceConnection(arrow.GetOutputPort())
        glyphFilter.SetVectorModeToUseVector()

        # Rotate arrows to match vector data:
        glyphFilter.OrientOn()

        # Scale to vector magnitude:
        glyphFilter.SetScaleModeToScaleByVector()
        glyphFilter.SetScaleFactor(2. * gm.scale)

        # These are some unfortunately named methods. It does *not* clamp the
        # scale range to [min, max], but rather remaps the range
        # [min, max] --> [0, 1].
        glyphFilter.ClampingOn()
        glyphFilter.SetRange(0.01, 1.0)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(glyphFilter.GetOutputPort())
        act = vtk.vtkActor()
        act.SetMapper(mapper)

        cmap = self._context().canvas.getcolormapname()
        cmap = vcs.elements["colormap"][cmap]
        r, g, b = cmap.index[lcolor]
        act.GetProperty().SetColor(r / 100., g / 100., b / 100.)

        x1, x2, y1, y2 = vcs.utils.getworldcoordinates(gm, data1.getAxis(-1),
                                                       data1.getAxis(-2))

        act = vcs2vtk.doWrap(act, [x1, x2, y1, y2], self._dataWrapModulo)
        self._context().fitToViewport(act, [tmpl.data.x1, tmpl.data.x2,
                                            tmpl.data.y1, tmpl.data.y2],
                                      [x1, x2, y1, y2],
                                      priority=tmpl.data.priority,
                                      create_renderer=True)

        returned.update(
            self._context().renderTemplate(tmpl, data1, gm, taxis, zaxis))

        if self._context().canvas._continents is None:
            continents = False
        if continents:
            projection = vcs.elements["projection"][gm.projection]
            self._context().plotContinents(x1, x2, y1, y2, projection,
                                           self._dataWrapModulo, tmpl)

        returned["vtk_backend_actors"] = [[act, [x1, x2, y1, y2]]]
        returned["vtk_backend_glyphfilters"] = [glyphFilter]
        returned["vtk_backend_luts"] = [[None, None]]

        return returned
Beispiel #4
0
    def _plotInternal(self):
        """Overrides baseclass implementation."""
        # Preserve time and z axis for plotting these inof in rendertemplate
        projection = vcs.elements["projection"][self._gm.projection]
        taxis = self._originalData1.getTime()

        if self._originalData1.ndim > 2:
            zaxis = self._originalData1.getAxis(-3)
        else:
            zaxis = None

        # 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

        self._vtkPolyDataFilter.Update()
        polydata = self._vtkPolyDataFilter.GetOutput()

        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()
            streamer.SetStartPosition(self._gm.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()
        glyphMapper.SetInputConnection(glyph.GetOutputPort())
        glyphActor = vtk.vtkActor()
        glyphActor.SetMapper(glyphMapper)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(streamer.GetOutputPort())
        act = vtk.vtkActor()
        act.SetMapper(mapper)

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

            glyphMapper.ScalarVisibilityOn()
            glyphMapper.SetLookupTable(lut)
            glyphMapper.UseLookupTableScalarRangeOn()
            glyphMapper.SetScalarModeToUsePointFieldData()
            glyphMapper.SelectColorArray("VectorMagnitude")
        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.)

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

        dataset_renderer, xScale, yScale = self._context().fitToViewport(
            act,
            vp,
            wc=plotting_dataset_bounds,
            geoBounds=self._vtkDataSetBoundsNoMask,
            geo=self._vtkGeoTransform,
            priority=self._template.data.priority,
            create_renderer=True)
        glyph_renderer, xScale, yScale = self._context().fitToViewport(
            glyphActor,
            vp,
            wc=plotting_dataset_bounds,
            geoBounds=self._vtkDataSetBoundsNoMask,
            geo=self._vtkGeoTransform,
            priority=self._template.data.priority,
            create_renderer=False)

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

        if self._context().canvas._continents is None:
            self._useContinents = False
        if self._useContinents:
            continents_renderer, xScale, yScale = self._context(
            ).plotContinents(plotting_dataset_bounds, projection,
                             self._dataWrapModulo, vp,
                             self._template.data.priority, **kwargs)
        self._resultDict["vtk_backend_actors"] = [[
            act, plotting_dataset_bounds
        ]]
        self._resultDict["vtk_backend_luts"] = [[None, None]]
Beispiel #5
0
    def plot(self, data1, data2, tmpl, grid, transform):
        """Overrides baseclass implementation."""
        # Preserve time and z axis for plotting these inof in rendertemplate
        geo = None  # to make flake8 happy
        projection = vcs.elements["projection"][self._gm.projection]
        returned = {}
        taxis = data1.getTime()
        if data1.ndim > 2:
            zaxis = data1.getAxis(-3)
        else:
            zaxis = None

        # Ok get3 only the last 2 dims
        data1 = self._context().trimData2D(data1)
        data2 = self._context().trimData2D(data2)

        scale = 1.0
        lat = None
        lon = None

        latAccessor = data1.getLatitude()
        lonAccesrsor = data1.getLongitude()
        if latAccessor:
            lat = latAccessor[:]
        if lonAccesrsor:
            lon = lonAccesrsor[:]

        gridGenDict = vcs2vtk.genGridOnPoints(data1, self._gm, deep=False, grid=grid,
                                              geo=transform, data2=data2)

        data1 = gridGenDict["data"]
        data2 = gridGenDict["data2"]
        geo = gridGenDict["geo"]

        for k in ['vtk_backend_grid', 'xm', 'xM', 'ym', 'yM', 'continents',
                  'wrap', 'geo']:
            exec("%s = gridGenDict['%s']" % (k, k))
        grid = gridGenDict['vtk_backend_grid']
        self._dataWrapModulo = gridGenDict['wrap']

        if geo is not None:
            newv = vtk.vtkDoubleArray()
            newv.SetNumberOfComponents(3)
            newv.InsertTupleValue(0, [lon.min(), lat.min(), 0])
            newv.InsertTupleValue(1, [lon.max(), lat.max(), 0])

            vcs2vtk.projectArray(newv, projection,
                                 [gridGenDict['xm'], gridGenDict['xM'],
                                  gridGenDict['ym'], gridGenDict['yM']])
            dimMin = [0, 0, 0]
            dimMax = [0, 0, 0]

            newv.GetTupleValue(0, dimMin)
            newv.GetTupleValue(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

        returned["vtk_backend_grid"] = grid
        returned["vtk_backend_geo"] = geo
        missingMapper = vcs2vtk.putMaskOnVTKGrid(data1, grid, None, False,
                                                 deep=False)

        # None/False are for color and cellData
        # (sent to vcs2vtk.putMaskOnVTKGrid)
        returned["vtk_backend_missing_mapper"] = (missingMapper, None, False)

        w = vcs2vtk.generateVectorArray(data1, data2, grid)

        grid.GetPointData().AddArray(w)

        # Vector attempt
        l = self._gm.line
        if l is None:
            l = "default"
        try:
            l = vcs.getline(l)
            lwidth = l.width[0]  # noqa
            lcolor = l.color[0]
            lstyle = l.type[0]  # noqa
        except:
            lstyle = "solid"  # noqa
            lwidth = 1.  # noqa
            lcolor = 0
        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()

        glyphFilter = vtk.vtkGlyph2D()
        glyphFilter.SetInputData(grid)
        glyphFilter.SetInputArrayToProcess(1, 0, 0, 0, "vectors")
        glyphFilter.SetSourceConnection(arrow.GetOutputPort())
        glyphFilter.SetVectorModeToUseVector()

        # Rotate arrows to match vector data:
        glyphFilter.OrientOn()

        # Scale to vector magnitude:
        glyphFilter.SetScaleModeToScaleByVector()
        glyphFilter.SetScaleFactor(scale * 2.0 * self._gm.scale)

        # These are some unfortunately named methods. It does *not* clamp the
        # scale range to [min, max], but rather remaps the range
        # [min, max] --> [0, 1].
        glyphFilter.ClampingOn()
        glyphFilter.SetRange(0.01, 1.0)

        mapper = vtk.vtkPolyDataMapper()

        glyphFilter.Update()
        data = glyphFilter.GetOutput()

        mapper.SetInputData(data)
        act = vtk.vtkActor()
        act.SetMapper(mapper)

        cmap = self.getColorMap()
        r, g, b, a = cmap.index[lcolor]
        act.GetProperty().SetColor(r / 100., g / 100., b / 100.)

        x1, x2, y1, y2 = vcs.utils.getworldcoordinates(self._gm, data1.getAxis(-1),
                                                       data1.getAxis(-2))
        if geo is None:
            wc = [x1, x2, y1, y2]
        else:
            xrange = list(act.GetXRange())
            yrange = list(act.GetYRange())
            wc = [xrange[0], xrange[1], yrange[0], yrange[1]]

        act = vcs2vtk.doWrap(act, wc, self._dataWrapModulo)

        self._context().fitToViewport(act, [tmpl.data.x1, tmpl.data.x2,
                                            tmpl.data.y1, tmpl.data.y2],
                                      wc=wc,
                                      priority=tmpl.data.priority,
                                      create_renderer=True)

        returned.update(self._context().renderTemplate(tmpl, data1,
                                                       self._gm, taxis, zaxis))

        if self._context().canvas._continents is None:
            continents = False
        if continents:
            self._context().plotContinents(x1, x2, y1, y2, projection,
                                           self._dataWrapModulo, tmpl)

        returned["vtk_backend_actors"] = [[act, [x1, x2, y1, y2]]]
        returned["vtk_backend_glyphfilters"] = [glyphFilter]
        returned["vtk_backend_luts"] = [[None, None]]

        return returned
    def _plotInternal(self):
        """Overrides baseclass implementation."""
        # Preserve time and z axis for plotting these inof in rendertemplate
        projection = vcs.elements["projection"][self._gm.projection]
        taxis = self._originalData1.getTime()
        scaleFactor = 1.0

        if self._originalData1.ndim > 2:
            zaxis = self._originalData1.getAxis(-3)
        else:
            zaxis = None

        scale = 1.0
        lat = None
        lon = None

        latAccessor = self._data1.getLatitude()
        lonAccessor = self._data1.getLongitude()
        if latAccessor:
            lat = latAccessor[:]
        if lonAccessor:
            lon = lonAccessor[:]

        if self._vtkGeoTransform is not None:
            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
        l = self._gm.line
        if l is None:
            l = "default"
        try:
            l = vcs.getline(l)
            lwidth = l.width[0]  # noqa
            lcolor = l.color[0]
            lstyle = l.type[0]  # noqa
        except:
            lstyle = "solid"  # noqa
            lwidth = 1.  # noqa
            lcolor = 0
        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()

        polydata = self._vtkPolyDataFilter.GetOutput()
        vectors = polydata.GetPointData().GetVectors()

        if self._gm.scaletype == 'constant' or\
           self._gm.scaletype == 'constantNNormalize' or\
           self._gm.scaletype == 'constantNLinear':
            scaleFactor = scale * 2.0 * self._gm.scale
        else:
            scaleFactor = 1.0

        glyphFilter = vtk.vtkGlyph2D()
        glyphFilter.SetInputData(polydata)
        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()

        if self._gm.scaletype == 'normalize' or self._gm.scaletype == 'linear' or\
           self._gm.scaletype == 'constantNNormalize' or self._gm.scaletype == 'constantNLinear':

            # Find the min and max vector magnitudes
            maxNorm = vectors.GetMaxNorm()

            if maxNorm == 0:
                maxNorm = 1.0

            if self._gm.scaletype == 'normalize' or self._gm.scaletype == 'constantNNormalize':
                scaleFactor /= maxNorm

            if self._gm.scaletype == 'linear' or self._gm.scaletype == 'constantNLinear':
                minNorm = None
                maxNorm = None

                noOfComponents = vectors.GetNumberOfComponents()
                for i in range(0, vectors.GetNumberOfTuples()):
                    norm = vtk.vtkMath.Norm(vectors.GetTuple(i), noOfComponents)

                    if (minNorm is None or norm < minNorm):
                        minNorm = norm
                    if (maxNorm is None or norm > maxNorm):
                        maxNorm = norm

                if maxNorm == 0:
                    maxNorm = 1.0

                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)

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

        glyphFilter.SetScaleFactor(scaleFactor)

        mapper = vtk.vtkPolyDataMapper()

        glyphFilter.Update()
        data = glyphFilter.GetOutput()

        mapper.SetInputData(data)
        mapper.ScalarVisibilityOff()
        act = vtk.vtkActor()
        act.SetMapper(mapper)

        cmap = self.getColorMap()
        r, g, b, a = cmap.index[lcolor]
        act.GetProperty().SetColor(r / 100., g / 100., b / 100.)

        plotting_dataset_bounds = vcs2vtk.getPlottingBounds(
            vcs.utils.getworldcoordinates(self._gm,
                                          self._data1.getAxis(-1),
                                          self._data1.getAxis(-2)),
            self._vtkDataSetBounds, self._vtkGeoTransform)
        x1, x2, y1, y2 = plotting_dataset_bounds
        if self._vtkGeoTransform is None:
            wc = plotting_dataset_bounds
        else:
            xrange = list(act.GetXRange())
            yrange = list(act.GetYRange())
            wc = [xrange[0], xrange[1], yrange[0], yrange[1]]

        vp = self._resultDict.get('ratio_autot_viewport',
                                  [self._template.data.x1, self._template.data.x2,
                                   self._template.data.y1, self._template.data.y2])
        # look for previous dataset_bounds different than ours and
        # modify the viewport so that the datasets are alligned
        # Hack to fix the case when the user does not specify gm.datawc_...
        # if geo is None:
        #     for dp in vcs.elements['display'].values():
        #         if (hasattr(dp, 'backend')):
        #             prevWc = dp.backend.get('dataset_bounds', None)
        #             if (prevWc):
        #                 middleX = float(vp[0] + vp[1]) / 2.0
        #                 middleY = float(vp[2] + vp[3]) / 2.0
        #                 sideX = float(vp[1] - vp[0]) / 2.0
        #                 sideY = float(vp[3] - vp[2]) / 2.0
        #                 ratioX = float(prevWc[1] - prevWc[0]) / float(wc[1] - wc[0])
        #                 ratioY = float(prevWc[3] - prevWc[2]) / float(wc[3] - wc[2])
        #                 sideX = sideX / ratioX
        #                 sideY = sideY / ratioY
        #                 vp = [middleX - sideX, middleX + sideX, middleY - sideY, middleY + sideY]

        dataset_renderer, xScale, yScale = self._context().fitToViewport(
            act, vp,
            wc=wc,
            priority=self._template.data.priority,
            create_renderer=True)
        kwargs = {'vtk_backend_grid': self._vtkDataSet,
                  'dataset_bounds': self._vtkDataSetBounds,
                  'plotting_dataset_bounds': plotting_dataset_bounds,
                  'vtk_backend_geo': self._vtkGeoTransform}
        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._context().canvas._continents is None:
            self._useContinents = False
        if self._useContinents:
            continents_renderer, xScale, yScale = self._context().plotContinents(
                plotting_dataset_bounds, projection,
                self._dataWrapModulo, vp, self._template.data.priority,
                vtk_backend_grid=self._vtkDataSet,
                dataset_bounds=self._vtkDataSetBounds)
        self._resultDict["vtk_backend_actors"] = [[act, plotting_dataset_bounds]]
        self._resultDict["vtk_backend_glyphfilters"] = [glyphFilter]
        self._resultDict["vtk_backend_luts"] = [[None, None]]
Beispiel #7
0
    def plot(self, data1, data2, tmpl, gm, grid, transform):
        """Overrides baseclass implementation."""
        #Preserve time and z axis for plotting these inof in rendertemplate
        returned = {}
        taxis = data1.getTime()
        if data1.ndim > 2:
            zaxis = data1.getAxis(-3)
        else:
            zaxis = None

        data1 = self._context.trimData2D(data1) # Ok get3 only the last 2 dims
        data2 = self._context.trimData2D(data2)

        gridGenDict = vcs2vtk.genGridOnPoints(data1, gm, deep=False, grid=grid,
                                              geo=transform)
        for k in ['vtk_backend_grid', 'xm', 'xM', 'ym', 'yM', 'continents',
                  'wrap', 'geo']:
            exec("%s = gridGenDict['%s']" % (k, k))
        grid = gridGenDict['vtk_backend_grid']

        returned["vtk_backend_grid"] = grid
        returned["vtk_backend_geo"] = geo
        missingMapper = vcs2vtk.putMaskOnVTKGrid(data1, grid, None, False,
                                                 deep=False)

        # None/False are for color and cellData
        # (sent to vcs2vtk.putMaskOnVTKGrid)
        returned["vtk_backend_missing_mapper"] = (missingMapper, None, False)

        w = vcs2vtk.generateVectorArray(data1, data2, grid)

        grid.GetPointData().AddArray(w)

        ## Vector attempt
        l = gm.line
        if l is None:
            l = "default"
        try:
          l = vcs.getline(l)
          lwidth = l.width[0]
          lcolor = l.color[0]
          lstyle = l.type[0]
        except:
          lstyle = "solid"
          lwidth = 1.
          lcolor = 0
        if gm.linewidth is not None:
            lwidth = gm.linewidth
        if gm.linecolor is not None:
            lcolor = gm.linecolor

        grid = vcs2vtk.stripGrid(grid)

        arrow = vtk.vtkGlyphSource2D()
        arrow.SetGlyphTypeToArrow()
        arrow.FilledOff()

        glyphFilter = vtk.vtkGlyph2D()
        glyphFilter.SetInputData(grid)
        glyphFilter.SetInputArrayToProcess(1, 0, 0, 0, "vectors")
        glyphFilter.SetSourceConnection(arrow.GetOutputPort())
        glyphFilter.SetVectorModeToUseVector()

        # Rotate arrows to match vector data:
        glyphFilter.OrientOn()

        # Scale to vector magnitude:
        glyphFilter.SetScaleModeToScaleByVector()
        glyphFilter.SetScaleFactor(2. * gm.scale)

        # These are some unfortunately named methods. It does *not* clamp the
        # scale range to [min, max], but rather remaps the range
        # [min, max] --> [0, 1].
        glyphFilter.ClampingOn()
        glyphFilter.SetRange(0.01, 1.0)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(glyphFilter.GetOutputPort())
        act = vtk.vtkActor()
        act.SetMapper(mapper)

        cmap = vcs.elements["colormap"][self._context.canvas.getcolormapname()]
        r, g, b = cmap.index[lcolor]
        act.GetProperty().SetColor(r / 100.,g / 100.,b / 100.)

        x1, x2, y1, y2 = vcs.utils.getworldcoordinates(gm, data1.getAxis(-1),
                                                       data1.getAxis(-2))

        act = vcs2vtk.doWrap(act, [x1,x2,y1,y2], wrap)
        ren = self._context.fitToViewport(act, [tmpl.data.x1, tmpl.data.x2,
                                                tmpl.data.y1, tmpl.data.y2],
                                          [x1, x2, y1, y2],
                                          priority=tmpl.data.priority)

        returned.update(
              self._context.renderTemplate(tmpl, data1, gm, taxis, zaxis))

        if self._context.canvas._continents is None:
          continents = False
        if continents:
            projection = vcs.elements["projection"][gm.projection]
            self._context.plotContinents(x1, x2, y1, y2, projection, wrap, tmpl)

        returned["vtk_backend_actors"] = [[act, [x1,x2,y1,y2]],]
        returned["vtk_backend_glyphfilters"] = [glyphFilter,]
        returned["vtk_backend_luts"] = [[None, None],]

        return returned
Beispiel #8
0
    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]]
Beispiel #9
0
def spaghetti_plot(variables,
                   template=None,
                   min_y=None,
                   max_y=None,
                   left_label=None,
                   right_label=None,
                   tick_sides=None,
                   line="default",
                   marker="default",
                   x_labels="*",
                   y_labels="*",
                   canvas=None):
    """
    This file is ready to be imported by your scripts, and you can just call this function.

    Sample usage is below.

    variables: List of variables to plot
    template: The template to use as the base for the plot.
    min_y: If you want to adjust the y axis bounds, you can set a minimum value. Will be derived from data if not specified.
    max_y: If you want to adjust the y axis bounds, you can set a maximum value. Will be derived from data if not specified.
    left_label: Text to put on the left Y axis
    right_label: Text to put on the right Y axis
    tick_sides: A list of "left" or "right" values indicating which side of the chart you want the variable axes to be displayed.
    line: A line object or name of a line object used to describe the lines plotted. Set to None to hide.
    marker: A marker object or name of a marker object used to describe the markers plotted. Set to None to hide.
    x_labels: Dictionary for setting axis tick labels
    y_labels: Dictionary for setting axis tick labels
    """
    if canvas is None:
        canvas = vcs.init()

    if isinstance(template, (str, unicode)):
        template = vcs.gettemplate(template)

    if template is None:
        # Use our custom default template for 1ds
        template = vcs.createtemplate()
        # Shrink the template a bit
        template.scale(.78, "x")
        template.move(.02, "x")
        template.yname.x = .01
        template.data.y1 = .1
        template.box1.y1 = .1
        ticlen = template.xtic1.y2 - template.xtic1.y1
        template.xtic1.y1 = template.data.y1
        template.xtic1.y2 = template.xtic1.y1 + ticlen
        template.xtic2.priority = 0
        template.xlabel1.y = template.xtic1.y2 - .01
        template.legend.x1 = template.data.x2 + (1 - template.data.x2) / 3.
        template.legend.x2 = .95
        template.legend.y1 = template.data.y1
        template.legend.y2 = template.data.y2
        template.yname.y = (template.data.y1 + template.data.y2) / 2.
        template.xname.y = template.xlabel1.y - .05

    # The labels don't make any sense with multiple values; hide them.
    template.min.priority = 0
    template.max.priority = 0
    template.mean.priority = 0
    template.dataname.priority = 0
    templates = EzTemplate.oneD(len(variables), template=template)
    templates.x = canvas

    if tick_sides is None:
        tick_sides = ["left"] * len(variables)

    clean_ticks = []
    for t in tick_sides:
        if t.lower() not in ('left', 'right'):
            raise ValueError(
                "tick_sides must be a list of 'left' or 'right' values; found '%s'."
                % t)
        clean_ticks.append(t.lower())

    tick_sides = clean_ticks
    if len(tick_sides) < len(variables):
        tick_sides += tick_sides[-1:] * len(variables)

    # Store min/max per side for appropriate scaling
    min_vals = {"left": min_y, "right": min_y}
    if min_y is None:
        for i, var in enumerate(variables):
            v_min = min(var)
            min_y = min_vals[tick_sides[i]]
            if min_y is None or min_y > v_min:
                min_vals[tick_sides[i]] = v_min

    max_vals = {"left": max_y, "right": max_y}
    if max_y is None:
        for i, var in enumerate(variables):
            v_max = max(var)
            max_y = max_vals[tick_sides[i]]
            if max_y is None or max_y < v_max:
                max_vals[tick_sides[i]] = v_max

    if isinstance(line, (str, unicode)):
        line = vcs.getline(line)
    if isinstance(marker, (str, unicode)):
        marker = vcs.getmarker(marker)

    to_pad = []
    if line is not None:
        widths = line.width
        to_pad.append(widths)

        styles = line.type
        to_pad.append(styles)

        colors = line.color
        to_pad.append(colors)

    if marker is not None:
        markers = marker.type
        to_pad.append(markers)

        marker_colors = marker.color
        to_pad.append(marker_colors)

        marker_sizes = marker.size
        to_pad.append(marker_sizes)

    for padded in to_pad:
        if len(padded) < len(variables):
            padded += padded[-1:] * (len(variables) - len(padded))

    for n in range(len(variables)):
        gm = vcs.create1d()

        if line is not None:
            gm.line = styles[n]
            gm.linewidth = widths[n]
            gm.linecolor = colors[n]
        else:
            gm.linewidth = 0

        if marker is not None:
            gm.marker = markers[n]
            gm.markersize = marker_sizes[n]
            gm.markercolor = marker_colors[n]
        else:
            gm.marker = None

        gm.datawc_y1 = min_vals[tick_sides[n]]
        gm.datawc_y2 = max_vals[tick_sides[n]]

        template = templates.get(n)
        gm.xticlabels1 = x_labels
        if tick_sides[n] == "left":
            if tick_sides.index("left") == n:
                template.ylabel1.priority = 1
                if left_label is not None:
                    template.yname.priority = 0
                    left_text = vcs.createtext(
                        Tt_source=template.yname.texttable,
                        To_source=template.yname.textorientation)
                    left_text.x = template.yname.x
                    left_text.y = template.yname.y
                    left_text.string = [left_label]
                    templates.x.plot(left_text)
            else:
                template.ylabel1.priority = 0
                template.yname.priority = 0
            template.ylabel2.priority = 0
            gm.yticlabels1 = y_labels
            gm.yticlabels2 = ""
        else:
            template.ylabel1.priority = 0
            if tick_sides.index("right") == n:
                template.ylabel2.priority = 1
                if right_label is not None:
                    right_text = vcs.createtext(
                        Tt_source=template.yname.texttable,
                        To_source=template.yname.textorientation)
                    right_text.x = template.data.x2 + (template.data.x1 -
                                                       template.yname.x)
                    right_text.y = template.yname.y
                    right_text.string = [right_label]
                    templates.x.plot(right_text)
            else:
                template.ylabel2.priority = 0
            gm.yticlabels1 = ""
            gm.yticlabels2 = y_labels
        if n != 0:
            template.xlabel1.priority = 0
            template.xname.priority = 0

        var = variables[n]
        templates.x.plot(var, gm, template)
    return templates.x
Beispiel #10
0
    def _plotInternal(self):
        """Overrides baseclass implementation."""
        # Preserve time and z axis for plotting these inof in rendertemplate
        projection = vcs.elements["projection"][self._gm.projection]
        taxis = self._originalData1.getTime()
        scaleFactor = 1.0

        if self._originalData1.ndim > 2:
            zaxis = self._originalData1.getAxis(-3)
        else:
            zaxis = None

        scale = 1.0
        lat = None
        lon = None

        latAccessor = self._data1.getLatitude()
        lonAccessor = self._data1.getLongitude()
        if latAccessor:
            lat = latAccessor[:]
        if lonAccessor:
            lon = lonAccessor[:]

        if self._vtkGeoTransform is not None:
            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()

        polydata = self._vtkPolyDataFilter.GetOutput()
        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.SetInputData(polydata)
        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()

        glyphFilter.SetScaleFactor(scaleFactor)
        if (maxNormInVp is None):
            maxNormInVp = maxNorm * scaleFactor
            # minNormInVp is left None, as it is displayed only for linear scaling.

        mapper = vtk.vtkPolyDataMapper()

        glyphFilter.Update()
        data = glyphFilter.GetOutput()

        mapper.SetInputData(data)
        mapper.ScalarVisibilityOff()
        act = vtk.vtkActor()
        act.SetMapper(mapper)

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

        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
        ])
        dataset_renderer, xScale, yScale = self._context().fitToViewport(
            act,
            vp,
            wc=plotting_dataset_bounds,
            geoBounds=self._vtkDataSetBoundsNoMask,
            geo=self._vtkGeoTransform,
            priority=self._template.data.priority,
            create_renderer=True)
        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
        }
        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

        worldToViewportXScale = (vp[1] - vp[0]) /\
            (self._vtkDataSetBoundsNoMask[1] - self._vtkDataSetBoundsNoMask[0])
        maxNormInVp *= worldToViewportXScale
        if (minNormInVp):
            minNormInVp *= worldToViewportXScale
        vcs.utils.drawVectorLegend(self._context().canvas,
                                   self._template.legend, lcolor, lstyle,
                                   lwidth, unitString, maxNormInVp, maxNorm,
                                   minNormInVp, minNorm)

        if self._context().canvas._continents is None:
            self._useContinents = False
        if self._useContinents:
            continents_renderer, xScale, yScale = self._context(
            ).plotContinents(plotting_dataset_bounds, projection,
                             self._dataWrapModulo, vp,
                             self._template.data.priority, **kwargs)
        self._resultDict["vtk_backend_actors"] = [[
            act, plotting_dataset_bounds
        ]]
        self._resultDict["vtk_backend_glyphfilters"] = [glyphFilter]
        self._resultDict["vtk_backend_luts"] = [[None, None]]
  def plotVector(self,data1,data2,tmpl,gm,ren):
    self.setLayer(ren,tmpl.data.priority)
    ug,xm,xM,ym,yM,continents,wrap = vcs2vtk.genUnstructuredGrid(data1,data2,gm)
    if ug.IsA("vtkUnstructuredGrid"):
        c2p = vtk.vtkCellDataToPointData()
        c2p.SetInputData(ug)
        c2p.Update()
        #For contouring duplicate points seem to confuse it
        cln = vtk.vtkCleanUnstructuredGrid()
        cln.SetInputConnection(c2p.GetOutputPort())

    missingMapper = vcs2vtk.putMaskOnVTKGrid(data1,ug,None)

    u=numpy.ma.ravel(data1)
    v=numpy.ma.ravel(data2)
    sh = list(u.shape)
    sh.append(1)
    u = numpy.reshape(u,sh)
    v = numpy.reshape(v,sh)
    z = numpy.zeros(u.shape)
    w = numpy.concatenate((u,v),axis=1)
    w = numpy.concatenate((w,z),axis=1)
    w = VN.numpy_to_vtk(w,deep=True)
    w.SetName("vectors")
    ug.GetPointData().AddArray(w)
    ## Vector attempt
    arrow = vtk.vtkArrowSource()
    l = gm.line
    if l is None:
        l = "default"
    try:
      l = vcs.getline(l)
      lwidth = l.width[0]
      lcolor = l.color[0]
      lstyle = l.type[0]
    except:
      lstyle = "solid"
      lwidth = 1.
      lcolor = 0
    if gm.linewidth is not None:
        lwidth = gm.linewidth
    if gm.linecolor is not None:
        lcolor = gm.linecolor


    arrow.SetTipRadius(.1*lwidth)
    arrow.SetShaftRadius(.03*lwidth)
    arrow.Update()
    glyphFilter = vtk.vtkGlyph2D()
    glyphFilter.SetSourceConnection(arrow.GetOutputPort())
    glyphFilter.OrientOn()
    glyphFilter.SetVectorModeToUseVector()
    glyphFilter.SetInputArrayToProcess(1,0,0,0,"vectors")
    glyphFilter.SetScaleFactor(2.*gm.scale)
    if ug.IsA("vtkUnstructuredGrid"):
        glyphFilter.SetInputConnection(cln.GetOutputPort())
    else:
        glyphFilter.SetInputData(ug)

    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(glyphFilter.GetOutputPort())
    act = vtk.vtkActor()
    act.SetMapper(mapper)
    try:
      cmap = vcs.elements["colormap"][cmap]
    except:
      cmap = vcs.elements["colormap"][self.canvas.getcolormapname()]
    r,g,b = cmap.index[lcolor]
    act.GetProperty().SetColor(r/100.,g/100.,b/100.)
    x1,x2,y1,y2 = vcs2vtk.getRange(gm,xm,xM,ym,yM)
    act = vcs2vtk.doWrap(act,[x1,x2,y1,y2],wrap)
    vcs2vtk.fitToViewport(act,ren,[tmpl.data.x1,tmpl.data.x2,tmpl.data.y1,tmpl.data.y2],[x1,x2,y1,y2])
    if tmpl.data.priority!=0:
        ren.AddActor(act)
    self.renderTemplate(ren,tmpl,data1,gm)
    if self.canvas._continents is None:
      continents = False
    if continents:
        projection = vcs.elements["projection"][gm.projection]
        self.plotContinents(x1,x2,y1,y2,projection,wrap,ren,tmpl)
Beispiel #12
0
  def plotVector(self,data1,data2,tmpl,gm):
    ug,xm,xM,ym,yM,continents,wrap,geo,cellData = vcs2vtk.genGrid(data1,data2,gm)
    if cellData:
        c2p = vtk.vtkCellDataToPointData()
        c2p.SetInputData(ug)
        c2p.Update()
        #For contouring duplicate points seem to confuse it
        if ug.IsA("vtkUnstructuredGrid"):
            cln = vtk.vtkCleanUnstructuredGrid()
            cln.SetInputConnection(c2p.GetOutputPort())

    missingMapper = vcs2vtk.putMaskOnVTKGrid(data1,ug,None,cellData)

    u=numpy.ma.ravel(data1)
    v=numpy.ma.ravel(data2)
    sh = list(u.shape)
    sh.append(1)
    u = numpy.reshape(u,sh)
    v = numpy.reshape(v,sh)
    z = numpy.zeros(u.shape)
    w = numpy.concatenate((u,v),axis=1)
    w = numpy.concatenate((w,z),axis=1)
    w = VN.numpy_to_vtk(w,deep=True)
    w.SetName("vectors")
    ug.GetPointData().AddArray(w)
    ## Vector attempt
    arrow = vtk.vtkArrowSource()
    l = gm.line
    if l is None:
        l = "default"
    try:
      l = vcs.getline(l)
      lwidth = l.width[0]
      lcolor = l.color[0]
      lstyle = l.type[0]
    except:
      lstyle = "solid"
      lwidth = 1.
      lcolor = 0
    if gm.linewidth is not None:
        lwidth = gm.linewidth
    if gm.linecolor is not None:
        lcolor = gm.linecolor


    arrow.SetTipRadius(.1*lwidth)
    arrow.SetShaftRadius(.03*lwidth)
    arrow.Update()
    glyphFilter = vtk.vtkGlyph2D()
    glyphFilter.SetSourceConnection(arrow.GetOutputPort())
    glyphFilter.OrientOn()
    glyphFilter.SetVectorModeToUseVector()
    glyphFilter.SetInputArrayToProcess(1,0,0,0,"vectors")
    glyphFilter.SetScaleFactor(2.*gm.scale)
    if cellData:
        if ug.IsA("vtkUnstructuredGrid"):
            glyphFilter.SetInputConnection(cln.GetOutputPort())
        else:
            glyphFilter.SetInputConnection(c2p.GetOutputPort())
    else:
        glyphFilter.SetInputData(ug)

    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(glyphFilter.GetOutputPort())
    act = vtk.vtkActor()
    act.SetMapper(mapper)
    try:
      cmap = vcs.elements["colormap"][cmap]
    except:
      cmap = vcs.elements["colormap"][self.canvas.getcolormapname()]
    r,g,b = cmap.index[lcolor]
    act.GetProperty().SetColor(r/100.,g/100.,b/100.)
    x1,x2,y1,y2 = vcs2vtk.getRange(gm,xm,xM,ym,yM)
    act = vcs2vtk.doWrap(act,[x1,x2,y1,y2],wrap)
    ren=vtk.vtkRenderer()
    self.renWin.AddRenderer(ren)
    self.setLayer(ren,tmpl.data.priority)
    vcs2vtk.fitToViewport(act,ren,[tmpl.data.x1,tmpl.data.x2,tmpl.data.y1,tmpl.data.y2],[x1,x2,y1,y2])
    if tmpl.data.priority!=0:
        ren.AddActor(act)
    self.renderTemplate(tmpl,data1,gm)
    if self.canvas._continents is None:
      continents = False
    if continents:
        projection = vcs.elements["projection"][gm.projection]
        self.plotContinents(x1,x2,y1,y2,projection,wrap,tmpl)
Beispiel #13
0
def spaghetti_plot(variables, template=None, min_y=None, max_y=None, left_label=None, right_label=None, tick_sides=None, line="default", marker="default", x_labels="*", y_labels="*", canvas=None):
    """
    This file is ready to be imported by your scripts, and you can just call this function.

    Sample usage is below.

    variables: List of variables to plot
    template: The template to use as the base for the plot.
    min_y: If you want to adjust the y axis bounds, you can set a minimum value. Will be derived from data if not specified.
    max_y: If you want to adjust the y axis bounds, you can set a maximum value. Will be derived from data if not specified.
    left_label: Text to put on the left Y axis
    right_label: Text to put on the right Y axis
    tick_sides: A list of "left" or "right" values indicating which side of the chart you want the variable axes to be displayed.
    line: A line object or name of a line object used to describe the lines plotted. Set to None to hide.
    marker: A marker object or name of a marker object used to describe the markers plotted. Set to None to hide.
    x_labels: Dictionary for setting axis tick labels
    y_labels: Dictionary for setting axis tick labels
    """
    if canvas is None:
        canvas = vcs.init()

    if isinstance(template, (str, unicode)):
        template = vcs.gettemplate(template)

    if template is None:
        # Use our custom default template for 1ds
        template = vcs.createtemplate()
        # Shrink the template a bit
        template.scale(.78, "x")
        template.move(.02, "x")
        template.yname.x = .01
        template.data.y1 = .1
        template.box1.y1 = .1
        ticlen = template.xtic1.y2 - template.xtic1.y1
        template.xtic1.y1 = template.data.y1
        template.xtic1.y2 = template.xtic1.y1 + ticlen
        template.xtic2.priority = 0
        template.xlabel1.y = template.xtic1.y2 - .01
        template.legend.x1 = template.data.x2 + (1 - template.data.x2) / 3.
        template.legend.x2 = .95
        template.legend.y1 = template.data.y1
        template.legend.y2 = template.data.y2
        template.yname.y = (template.data.y1 + template.data.y2)/2.
        template.xname.y = template.xlabel1.y - .05

    # The labels don't make any sense with multiple values; hide them.
    template.min.priority = 0
    template.max.priority = 0
    template.mean.priority = 0
    template.dataname.priority = 0
    templates = EzTemplate.oneD(len(variables), template=template)
    templates.x = canvas

    if tick_sides is None:
        tick_sides = ["left"] * len(variables)

    clean_ticks = []
    for t in tick_sides:
        if t.lower() not in ('left', 'right'):
            raise ValueError("tick_sides must be a list of 'left' or 'right' values; found '%s'." % t)
        clean_ticks.append(t.lower())

    tick_sides = clean_ticks
    if len(tick_sides) < len(variables):
        tick_sides += tick_sides[-1:] * len(variables)

    # Store min/max per side for appropriate scaling
    min_vals = {"left": min_y, "right": min_y}
    if min_y is None:
        for i, var in enumerate(variables):
            v_min = min(var)
            min_y = min_vals[tick_sides[i]]
            if min_y is None or min_y > v_min:
                min_vals[tick_sides[i]] = v_min

    max_vals = {"left": max_y, "right": max_y}
    if max_y is None:
        for i, var in enumerate(variables):
            v_max = max(var)
            max_y = max_vals[tick_sides[i]]
            if max_y is None or max_y < v_max:
                max_vals[tick_sides[i]] = v_max

    if isinstance(line, (str, unicode)):
        line = vcs.getline(line)
    if isinstance(marker, (str, unicode)):
        marker = vcs.getmarker(marker)

    to_pad = []
    if line is not None:
        widths = line.width
        to_pad.append(widths)

        styles = line.type
        to_pad.append(styles)

        colors = line.color
        to_pad.append(colors)

    if marker is not None:
        markers = marker.type
        to_pad.append(markers)

        marker_colors = marker.color
        to_pad.append(marker_colors)

        marker_sizes = marker.size
        to_pad.append(marker_sizes)

    for padded in to_pad:
        if len(padded) < len(variables):
            padded += padded[-1:] * (len(variables) - len(padded))

    for n in range(len(variables)):
        gm = vcs.create1d()

        if line is not None:
            gm.line = styles[n]
            gm.linewidth = widths[n]
            gm.linecolor = colors[n]
        else:
            gm.linewidth = 0

        if marker is not None:
            gm.marker = markers[n]
            gm.markersize = marker_sizes[n]
            gm.markercolor = marker_colors[n]
        else:
            gm.marker = None

        gm.datawc_y1 = min_vals[tick_sides[n]]
        gm.datawc_y2 = max_vals[tick_sides[n]]

        template = templates.get(n)
        gm.xticlabels1 = x_labels
        if tick_sides[n] == "left":
            if tick_sides.index("left") == n:
                template.ylabel1.priority = 1
                if left_label is not None:
                    template.yname.priority = 0
                    left_text = vcs.createtext(Tt_source=template.yname.texttable, To_source=template.yname.textorientation)
                    left_text.x = template.yname.x
                    left_text.y = template.yname.y
                    left_text.string = [left_label]
                    templates.x.plot(left_text)
            else:
                template.ylabel1.priority = 0
                template.yname.priority = 0
            template.ylabel2.priority = 0
            gm.yticlabels1 = y_labels
            gm.yticlabels2 = ""
        else:
            template.ylabel1.priority = 0
            if tick_sides.index("right") == n:
                template.ylabel2.priority = 1
                if right_label is not None:
                    right_text = vcs.createtext(Tt_source=template.yname.texttable, To_source=template.yname.textorientation)
                    right_text.x = template.data.x2 + (template.data.x1 - template.yname.x)
                    right_text.y = template.yname.y
                    right_text.string = [right_label]
                    templates.x.plot(right_text)
            else:
                template.ylabel2.priority = 0
            gm.yticlabels1 = ""
            gm.yticlabels2 = y_labels
        if n != 0:
            template.xlabel1.priority = 0
            template.xname.priority = 0

        var = variables[n]
        templates.x.plot(var, gm, template)
    return templates.x
Beispiel #14
0
  def plotVector(self,data1,data2,tmpl,gm):
    #Preserve time and z axis for plotting these inof in rendertemplate
    taxis = data1.getTime()
    if data1.ndim>2:
        zaxis = data1.getAxis(-3)
    else:
        zaxis = None
    data1 = self.trimData2D(data1) # Ok get3 only the last 2 dims
    data2 = self.trimData2D(data2)
    ug,xm,xM,ym,yM,continents,wrap,geo = vcs2vtk.genGridOnPoints(data1,data2,gm,deep=False)
    missingMapper = vcs2vtk.putMaskOnVTKGrid(data1,ug,None,False,deep=False)

    u=numpy.ma.ravel(data1)
    v=numpy.ma.ravel(data2)
    sh = list(u.shape)
    sh.append(1)
    u = numpy.reshape(u,sh)
    v = numpy.reshape(v,sh)
    z = numpy.zeros(u.shape)
    w = numpy.concatenate((u,v),axis=1)
    w = numpy.concatenate((w,z),axis=1)

    # HACK The grid returned by vtk2vcs.genGrid is not the same size as the
    # data array. I'm not sure where the issue is...for now let's just zero-pad
    # data array so that we can at least test rendering until Charles gets
    # back from vacation:
    wLen = len(w)
    numPts = ug.GetNumberOfPoints()
    if wLen != numPts:
        warnings.warn("!!! Warning during vector plotting: Number of points does not "\
              "match the number of vectors to be glyphed (%s points vs %s "\
              "vectors). The vectors will be padded/truncated to match for "\
              "rendering purposes, but the resulting image should not be "\
              "trusted."%(numPts, wLen))
        newShape = (numPts,) + w.shape[1:]
        w = numpy.ma.resize(w, newShape)

    w = vcs2vtk.numpy_to_vtk_wrapper(w,deep=False)
    w.SetName("vectors")
    ug.GetPointData().AddArray(w)

    ## Vector attempt
    l = gm.line
    if l is None:
        l = "default"
    try:
      l = vcs.getline(l)
      lwidth = l.width[0]
      lcolor = l.color[0]
      lstyle = l.type[0]
    except:
      lstyle = "solid"
      lwidth = 1.
      lcolor = 0
    if gm.linewidth is not None:
        lwidth = gm.linewidth
    if gm.linecolor is not None:
        lcolor = gm.linecolor

    # Strip out masked points.
    if ug.IsA("vtkStructuredGrid"):
        if ug.GetCellBlanking():
            visArray = ug.GetCellVisibilityArray()
            visArray.SetName("BlankingArray")
            ug.GetCellData().AddArray(visArray)
            thresh = vtk.vtkThreshold()
            thresh.SetInputData(ug)
            thresh.ThresholdByUpper(0.5)
            thresh.SetInputArrayToProcess(0, 0, 0,
                                          "vtkDataObject::FIELD_ASSOCIATION_CELLS",
                                          "BlankingArray")
            thresh.Update()
            ug = thresh.GetOutput()
        elif ug.GetPointBlanking():
            visArray = ug.GetPointVisibilityArray()
            visArray.SetName("BlankingArray")
            ug.GetPointData().AddArray(visArray)
            thresh = vtk.vtkThreshold()
            thresh.SetInputData(ug)
            thresh.SetUpperThreshold(0.5)
            thresh.SetInputArrayToProcess(0, 0, 0,
                                          "vtkDataObject::FIELD_ASSOCIATION_POINTS",
                                          "BlankingArray")
            thresh.Update()
            ug = thresh.GetOutput()

    arrow = vtk.vtkGlyphSource2D()
    arrow.SetGlyphTypeToArrow()
    arrow.FilledOff()

    glyphFilter = vtk.vtkGlyph2D()
    glyphFilter.SetSourceConnection(arrow.GetOutputPort())
    glyphFilter.SetVectorModeToUseVector()

    # Rotate arrows to match vector data:
    glyphFilter.OrientOn()

    # Scale to vector magnitude:
    glyphFilter.SetScaleModeToScaleByVector()

    # These are some unfortunately named methods. It does *not* clamp the scale
    # range to [min, max], but rather remaps the range [min, max]-->[0,1]. Bump
    # up min so that near-zero vectors will not be rendered, as these tend to
    # come out randomly oriented.
    glyphFilter.ClampingOn()
    glyphFilter.SetRange(0.01, 1.0)

    glyphFilter.SetInputArrayToProcess(1,0,0,0,"vectors")
    glyphFilter.SetScaleFactor(2.*gm.scale)

    #if cellData:
    #    if ug.IsA("vtkUnstructuredGrid"):
    #        glyphFilter.SetInputConnection(cln.GetOutputPort())
    #    else:
    #        glyphFilter.SetInputConnection(c2p.GetOutputPort())
    #else:
    #    glyphFilter.SetInputData(ug)
    glyphFilter.SetInputData(ug)

    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(glyphFilter.GetOutputPort())
    act = vtk.vtkActor()
    act.SetMapper(mapper)
    try:
      cmap = vcs.elements["colormap"][cmap]
    except:
      cmap = vcs.elements["colormap"][self.canvas.getcolormapname()]
    r,g,b = cmap.index[lcolor]
    act.GetProperty().SetColor(r/100.,g/100.,b/100.)
    x1,x2,y1,y2 = vcs2vtk.getRange(gm,xm,xM,ym,yM)
    act = vcs2vtk.doWrap(act,[x1,x2,y1,y2],wrap)
    ren = self.createRenderer()
    self.renWin.AddRenderer(ren)
    self.setLayer(ren,tmpl.data.priority)
    vcs2vtk.fitToViewport(act,ren,[tmpl.data.x1,tmpl.data.x2,tmpl.data.y1,tmpl.data.y2],[x1,x2,y1,y2])
    if tmpl.data.priority!=0:
        ren.AddActor(act)
    self.renderTemplate(tmpl,data1,gm,taxis,zaxis)
    if self.canvas._continents is None:
      continents = False
    if continents:
        projection = vcs.elements["projection"][gm.projection]
        self.plotContinents(x1,x2,y1,y2,projection,wrap,tmpl)
Beispiel #15
0
def line(name):
    try:
        obj = vcs.getline(str(name))
    except:
        abort(404)
    return jsonify(vcs.utils.dumpToDict(obj)[0])
Beispiel #16
0
    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 test_vcs_read_old_scr(self):

        testfile = os.path.join("uvcdat-testdata", "data", "vcs", "old.scr")

        Ns = {}
        for k in vcs.elements.keys():
            Ns[k] = len(vcs.elements[k].keys())
        vcs.scriptrun(testfile)
        Ns2 = {}
        for k in vcs.elements.keys():
            Ns2[k] = len(vcs.elements[k].keys())

        diffs = {
            'projection': 0,
            'colormap': 53,
            'isofill': 187,
            'marker': 0,
            '3d_dual_scalar': 0,
            'texttable': 4,
            '3d_scalar': 0,
            'fillarea': 234,
            'font': 0,
            '3d_vector': 0,
            '1d': 9,
            'template': 43,
            'textcombined': 0,
            'textorientation': 3,
            'xvsy': 0,
            'xyvsy': 0,
            'isoline': 113,
            'boxfill': 239,
            'fontNumber': 0,
            'line': 21,
            'meshfill': 0,
            'yxvsx': 9,
            'taylordiagram': 0,
            'list': 26,
            'display': 0,
            'vector': 55,
            'scatter': 0,
            "streamline": 0
        }
        for k in vcs.elements.keys():
            print "---Checking number of new elements for", k
            self.assertEqual(diffs[k], Ns2[k] - Ns[k])

        gm = vcs.getisofill("pr_time_lat_1")
        self.assertEqual(gm.ymtics1, "lat5")
        self.assertTrue(gm.ext_2)
        self.assertEqual(gm.fillareastyle, "solid")
        self.assertEqual(
            gm.fillareacolors,
            [240, 240, 240, 28, 27, 26, 25, 23, 22, 21, 20, 19, 18, 16])
        gm = vcs.getboxfill("lon_lat_mjop05")
        self.assertEqual(gm.xmtics1, "lon5")
        self.assertEqual(gm.yticlabels1, "lat20")
        self.assertEqual(gm.datawc_x1, 30)
        self.assertEqual(gm.datawc_x2, 210.)
        self.assertEqual(gm.datawc_y1, -30)
        self.assertEqual(gm.datawc_y2, 30.)
        self.assertEqual(gm.level_1, -0.05)
        self.assertEqual(gm.level_2, 0.05)
        self.assertEqual(gm.color_1, 18)
        self.assertEqual(gm.color_2, 219)
        gm = vcs.getline("red_solid")
        self.assertEqual(gm.type, ['solid'])
        self.assertEqual(gm.color, [242])
        self.assertEqual(gm.width, [2.0])

        gm = vcs.getyxvsx("pr_lsfit_lat")
        self.assertEqual(gm.xmtics1, "lat5")
        self.assertEqual(gm.linecolor, 242)
        self.assertEqual(gm.linewidth, 2.)
        self.assertEqual(gm.datawc_x1, 30)
        self.assertEqual(gm.datawc_x2, -30.)
        self.assertEqual(gm.datawc_y1, -5.)
        self.assertEqual(gm.datawc_y2, 5.)
        gm = vcs.getisoline("div_anom")
        self.assertEqual(gm.xmtics1, "lon5")
        self.assertEqual(gm.xticlabels1, "lon15")
        self.assertEqual(gm.linetypes, [
            'dash', 'dash', 'dash', 'dash', 'solid', 'dash', 'dash', 'dash',
            'solid', 'solid', 'solid', 'solid', 'solid', 'solid', 'solid',
            'solid', 'solid'
        ])
        self.assertEqual(gm.linecolors, [
            241, 241, 241, 241, 242, 241, 241, 241, 1, 1, 1, 1, 1, 1, 1, 1, 1
        ])
        self.assertEqual(gm.linewidths, [
            1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
            1.0, 1.0, 1.0, 1.0
        ])
        gm = vcs.getvector("lon_lat_IO_5")
        self.assertEqual(gm.xmtics1, "lon5")
        self.assertEqual(gm.xticlabels1, "lon20")
        self.assertEqual(gm.linecolor, 242)
        self.assertEqual(gm.linewidth, 2.)
        self.assertEqual(gm.scale, 3)
        self.assertEqual(gm.reference, 5)
Beispiel #18
0
    def _plotInternal(self):
        """Overrides baseclass implementation."""
        # Preserve time and z axis for plotting these inof in rendertemplate
        projection = vcs.elements["projection"][self._gm.projection]
        taxis = self._originalData1.getTime()
        scaleFactor = 1.0

        if self._originalData1.ndim > 2:
            zaxis = self._originalData1.getAxis(-3)
        else:
            zaxis = None

        scale = 1.0
        lat = None
        lon = None

        latAccessor = self._data1.getLatitude()
        lonAccessor = self._data1.getLongitude()
        if latAccessor:
            lat = latAccessor[:]
        if lonAccessor:
            lon = lonAccessor[:]

        if self._vtkGeoTransform is not None:
            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
        l = self._gm.linetype
        if l is None:
            l = "default"
        try:
            l = vcs.getline(l)
            lwidth = l.width[0]  # noqa
            lcolor = l.color[0]
            lstyle = l.type[0]  # noqa
        except:
            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()

        polydata = self._vtkPolyDataFilter.GetOutput()
        vectors = polydata.GetPointData().GetVectors()

        if self._gm.scaletype == 'constant' or\
           self._gm.scaletype == 'constantNNormalize' or\
           self._gm.scaletype == 'constantNLinear':
            scaleFactor = scale * 2.0 * self._gm.scale
        else:
            scaleFactor = 1.0

        glyphFilter = vtk.vtkGlyph2D()
        glyphFilter.SetInputData(polydata)
        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()

        if self._gm.scaletype == 'normalize' or self._gm.scaletype == 'linear' or\
           self._gm.scaletype == 'constantNNormalize' or self._gm.scaletype == 'constantNLinear':

            # Find the min and max vector magnitudes
            maxNorm = vectors.GetMaxNorm()

            if maxNorm == 0:
                maxNorm = 1.0

            if self._gm.scaletype == 'normalize' or self._gm.scaletype == 'constantNNormalize':
                scaleFactor /= maxNorm

            if self._gm.scaletype == 'linear' or self._gm.scaletype == 'constantNLinear':
                minNorm = None
                maxNorm = None

                noOfComponents = vectors.GetNumberOfComponents()
                for i in range(0, vectors.GetNumberOfTuples()):
                    norm = vtk.vtkMath.Norm(vectors.GetTuple(i),
                                            noOfComponents)

                    if (minNorm is None or norm < minNorm):
                        minNorm = norm
                    if (maxNorm is None or norm > maxNorm):
                        maxNorm = norm

                if maxNorm == 0:
                    maxNorm = 1.0

                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)

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

        glyphFilter.SetScaleFactor(scaleFactor)

        mapper = vtk.vtkPolyDataMapper()

        glyphFilter.Update()
        data = glyphFilter.GetOutput()

        mapper.SetInputData(data)
        mapper.ScalarVisibilityOff()
        act = vtk.vtkActor()
        act.SetMapper(mapper)

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

        plotting_dataset_bounds = vcs2vtk.getPlottingBounds(
            vcs.utils.getworldcoordinates(self._gm, self._data1.getAxis(-1),
                                          self._data1.getAxis(-2)),
            self._vtkDataSetBounds, self._vtkGeoTransform)
        x1, x2, y1, y2 = plotting_dataset_bounds
        if self._vtkGeoTransform is None:
            wc = plotting_dataset_bounds
        else:
            xrange = list(act.GetXRange())
            yrange = list(act.GetYRange())
            wc = [xrange[0], xrange[1], yrange[0], yrange[1]]

        vp = self._resultDict.get('ratio_autot_viewport', [
            self._template.data.x1, self._template.data.x2,
            self._template.data.y1, self._template.data.y2
        ])
        # look for previous dataset_bounds different than ours and
        # modify the viewport so that the datasets are alligned
        # Hack to fix the case when the user does not specify gm.datawc_...
        # if geo is None:
        #     for dp in vcs.elements['display'].values():
        #         if (hasattr(dp, 'backend')):
        #             prevWc = dp.backend.get('dataset_bounds', None)
        #             if (prevWc):
        #                 middleX = float(vp[0] + vp[1]) / 2.0
        #                 middleY = float(vp[2] + vp[3]) / 2.0
        #                 sideX = float(vp[1] - vp[0]) / 2.0
        #                 sideY = float(vp[3] - vp[2]) / 2.0
        #                 ratioX = float(prevWc[1] - prevWc[0]) / float(wc[1] - wc[0])
        #                 ratioY = float(prevWc[3] - prevWc[2]) / float(wc[3] - wc[2])
        #                 sideX = sideX / ratioX
        #                 sideY = sideY / ratioY
        #                 vp = [middleX - sideX, middleX + sideX, middleY - sideY, middleY + sideY]

        dataset_renderer, xScale, yScale = self._context().fitToViewport(
            act,
            vp,
            wc=wc,
            priority=self._template.data.priority,
            create_renderer=True)
        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
        }
        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._context().canvas._continents is None:
            self._useContinents = False
        if self._useContinents:
            continents_renderer, xScale, yScale = self._context(
            ).plotContinents(plotting_dataset_bounds, projection,
                             self._dataWrapModulo, vp,
                             self._template.data.priority, **kwargs)
        self._resultDict["vtk_backend_actors"] = [[
            act, plotting_dataset_bounds
        ]]
        self._resultDict["vtk_backend_glyphfilters"] = [glyphFilter]
        self._resultDict["vtk_backend_luts"] = [[None, None]]