def draw(self, state, plotCoordinates, plotDefinitions, performanceTable): """Draw the plot element. This stage consists of creating an SVG image of the pre-computed data. @type state: ad-hoc Python object @param state: State information that persists long enough to use quantities computed in C{prepare} in the C{draw} stage. This is a work-around of lxml's refusal to let its Python instances maintain C{self} and it is unrelated to DataTableState. @type plotCoordinates: PlotCoordinates @param plotCoordinates: The coordinate system in which this plot element will be placed. @type plotDefinitions: PlotDefinitions @type plotDefinitions: The dictionary of key-value pairs that forms the <defs> section of the SVG document. @type performanceTable: PerformanceTable @param performanceTable: Measures and records performance (time and memory consumption) of the drawing process. @rtype: SvgBinding @return: An SVG fragment representing the fully drawn plot element. """ svg = SvgBinding.elementMaker svgId = self.get("svgId") if svgId is None: output = svg.g() else: output = svg.g(id=svgId) if not hasattr(plotCoordinates, "zmin"): return output performanceTable.begin("PlotHeatMap draw") xbins = state.xbins xlow = state.xlow xhigh = state.xhigh ybins = state.ybins ylow = state.ylow yhigh = state.yhigh reddata = NP("empty", len(state.zdata), dtype=NP.uint8) greendata = NP("empty", len(state.zdata), dtype=NP.uint8) bluedata = NP("empty", len(state.zdata), dtype=NP.uint8) alphadata = NP("empty", len(state.zdata), dtype=NP.uint8) if len(plotCoordinates.gradient) == 0: offsets = [0.0, 1.0] reds = [255, 0] greens = [255, 0] blues = [255, 255] alphas = [255, 255] else: offsets = [float(g["offset"]) for g in plotCoordinates.gradient] reds = [ min(int(math.floor(256 * float(g["red"]))), 255) for g in plotCoordinates.gradient ] greens = [ min(int(math.floor(256 * float(g["green"]))), 255) for g in plotCoordinates.gradient ] blues = [ min(int(math.floor(256 * float(g["blue"]))), 255) for g in plotCoordinates.gradient ] alphas = [ min(int(math.floor(256 * float(g.get("opacity", 1.0)))), 255) for g in plotCoordinates.gradient ] if not plotCoordinates.zlog: normalized = NP( NP(state.zdata - plotCoordinates.zmin) / (plotCoordinates.zmax - plotCoordinates.zmin)) else: normalized = NP( NP( NP("log10", state.zdata) - NP("log10", plotCoordinates.zmin)) / NP( NP("log10", plotCoordinates.zmax) - NP("log10", plotCoordinates.zmin))) for index in xrange(len(offsets) - 1): if index == 0: under = NP(normalized < offsets[index]) reddata[under] = reds[index] greendata[under] = greens[index] bluedata[under] = blues[index] alphadata[under] = alphas[index] if index == len(offsets) - 2: over = NP(normalized >= offsets[index + 1]) reddata[over] = reds[index + 1] greendata[over] = greens[index + 1] bluedata[over] = blues[index + 1] alphadata[over] = alphas[index + 1] selection = NP(normalized >= offsets[index]) NP("logical_and", selection, NP(normalized < offsets[index + 1]), selection) subset = NP(NP(normalized[selection]) - offsets[index]) norm = 1. / (offsets[index + 1] - offsets[index]) reddata[selection] = NP( "array", NP( NP(subset * ((reds[index + 1] - reds[index]) * norm)) + reds[index]), dtype=NP.uint8) greendata[selection] = NP( "array", NP( NP(subset * ((greens[index + 1] - greens[index]) * norm)) + greens[index]), dtype=NP.uint8) bluedata[selection] = NP( "array", NP( NP(subset * ((blues[index + 1] - blues[index]) * norm)) + blues[index]), dtype=NP.uint8) alphadata[selection] = NP( "array", NP( NP(subset * ((alphas[index + 1] - alphas[index]) * norm)) + alphas[index]), dtype=NP.uint8) badpixels = NP("isnan", normalized) NP("logical_or", badpixels, NP("isinf", normalized), badpixels) if state.zmask is not None: NP("logical_or", badpixels, NP(state.zmask != defs.VALID), badpixels) alphadata[badpixels] = 0 X1, Y1 = plotCoordinates(xlow, ylow) X2, Y2 = plotCoordinates(xhigh, yhigh) onePixelBeyondBorder = self.get("onePixelBeyondBorder", defaultFromXsd=True, convertType=True) if onePixelBeyondBorder: Xwidth = (X2 - X1) / xbins Yheight = (Y1 - Y2) / ybins X1 -= Xwidth X2 += Xwidth Y1 += Yheight Y2 -= Yheight arrayToPng = ArrayToPng() arrayToPng.putdata(xbins, ybins, reddata, greendata, bluedata, alphadata, flipy=True, onePixelBeyondBorder=onePixelBeyondBorder) output.append( svg.image( **{ defs.XLINK_HREF: "data:image/png;base64," + arrayToPng.b64encode(), "x": repr(X1), "y": repr(Y2), "width": repr(X2 - X1), "height": repr(Y1 - Y2), "image-rendering": self.get("imageRendering", defaultFromXsd=True), "preserveAspectRatio": "none" })) performanceTable.end("PlotHeatMap draw") return output
if makingImage: betterMask = mask > 0 for i in xrange(rgbDouble.shape[0]): numpy.logical_and(betterMask, rgbDouble[i,:,:] > 0.0, betterMask) reddata = numpy.maximum(numpy.minimum(numpy.uint8(rgbDouble[0,:,:].T/rgbDouble[0,:,:].max() * 255.0), 255), 0) greendata = numpy.maximum(numpy.minimum(numpy.uint8(rgbDouble[1,:,:].T/rgbDouble[1,:,:].max() * 255.0), 255), 0) bluedata = numpy.maximum(numpy.minimum(numpy.uint8(rgbDouble[2,:,:].T/rgbDouble[2,:,:].max() * 255.0), 255), 0) alphadata = numpy.uint8(betterMask.T * 255) reddata = numpy.reshape(reddata, rgbDouble.shape[1] * rgbDouble.shape[2]) greendata = numpy.reshape(greendata, rgbDouble.shape[1] * rgbDouble.shape[2]) bluedata = numpy.reshape(bluedata, rgbDouble.shape[1] * rgbDouble.shape[2]) alphadata = numpy.reshape(alphadata, rgbDouble.shape[1] * rgbDouble.shape[2]) arrayToPng = ArrayToPng() arrayToPng.putdata(rgbDouble.shape[1], rgbDouble.shape[2], reddata, greendata, bluedata, alphadata, flipy=False, onePixelBeyondBorder=False) attrib = {"version": "1.1", "width": "100%", "height": "100%", "preserveAspectRatio": "xMidYMin meet"} attrib["viewBox"] = "0 0 %d %d" % (rgbDouble.shape[2], rgbDouble.shape[1]) attrib["style"] = "fill: none; stroke: black; stroke-linejoin: miter; stroke-width: 2; text-anchor: middle;" attrib["font-family"] = "DejaVu Sans Condensed, DejaVu Sans, Lucida Sans Unicode, Lucida Sans, Helvetica, Sans, sans-serif" attrib["font-weight"] = "normal" imagePlot = SVG.svg(SVG.g(), **attrib) imageGroup = imagePlot[0] imageGroup.append(SVG.image(**{defs.XLINK_HREF: "data:image/png;base64," + arrayToPng.b64encode(), "x": "0", "y": "0", "width": repr(rgbDouble.shape[1]), "height": repr(rgbDouble.shape[2])})) getLngLat = utilities.makeGetLngLat(imageValue["metadata"]) wavelengths = imageValue["metadata"]["bandWavelength"] bandNames = imageValue["metadata"]["bandNames"]
def draw(self, state, plotCoordinates, plotDefinitions, performanceTable): """Draw the plot element. This stage consists of creating an SVG image of the pre-computed data. @type state: ad-hoc Python object @param state: State information that persists long enough to use quantities computed in C{prepare} in the C{draw} stage. This is a work-around of lxml's refusal to let its Python instances maintain C{self} and it is unrelated to DataTableState. @type plotCoordinates: PlotCoordinates @param plotCoordinates: The coordinate system in which this plot element will be placed. @type plotDefinitions: PlotDefinitions @type plotDefinitions: The dictionary of key-value pairs that forms the <defs> section of the SVG document. @type performanceTable: PerformanceTable @param performanceTable: Measures and records performance (time and memory consumption) of the drawing process. @rtype: SvgBinding @return: An SVG fragment representing the fully drawn plot element. """ svg = SvgBinding.elementMaker svgId = self.get("svgId") if svgId is None: output = svg.g() else: output = svg.g(id=svgId) if not hasattr(plotCoordinates, "zmin"): return output performanceTable.begin("PlotHeatMap draw") xbins = state.xbins xlow = state.xlow xhigh = state.xhigh ybins = state.ybins ylow = state.ylow yhigh = state.yhigh reddata = NP("empty", len(state.zdata), dtype=NP.uint8) greendata = NP("empty", len(state.zdata), dtype=NP.uint8) bluedata = NP("empty", len(state.zdata), dtype=NP.uint8) alphadata = NP("empty", len(state.zdata), dtype=NP.uint8) if len(plotCoordinates.gradient) == 0: offsets = [0.0, 1.0] reds = [255, 0] greens = [255, 0] blues = [255, 255] alphas = [255, 255] else: offsets = [float(g["offset"]) for g in plotCoordinates.gradient] reds = [min(int(math.floor(256*float(g["red"]))), 255) for g in plotCoordinates.gradient] greens = [min(int(math.floor(256*float(g["green"]))), 255) for g in plotCoordinates.gradient] blues = [min(int(math.floor(256*float(g["blue"]))), 255) for g in plotCoordinates.gradient] alphas = [min(int(math.floor(256*float(g.get("opacity", 1.0)))), 255) for g in plotCoordinates.gradient] if not plotCoordinates.zlog: normalized = NP(NP(state.zdata - plotCoordinates.zmin) / (plotCoordinates.zmax - plotCoordinates.zmin)) else: normalized = NP(NP(NP("log10", state.zdata) - NP("log10", plotCoordinates.zmin))/NP(NP("log10", plotCoordinates.zmax) - NP("log10", plotCoordinates.zmin))) for index in xrange(len(offsets) - 1): if index == 0: under = NP(normalized < offsets[index]) reddata[under] = reds[index] greendata[under] = greens[index] bluedata[under] = blues[index] alphadata[under] = alphas[index] if index == len(offsets) - 2: over = NP(normalized >= offsets[index + 1]) reddata[over] = reds[index + 1] greendata[over] = greens[index + 1] bluedata[over] = blues[index + 1] alphadata[over] = alphas[index + 1] selection = NP(normalized >= offsets[index]) NP("logical_and", selection, NP(normalized < offsets[index + 1]), selection) subset = NP(NP(normalized[selection]) - offsets[index]) norm = 1. / (offsets[index + 1] - offsets[index]) reddata[selection] = NP("array", NP(NP(subset * ((reds[index + 1] - reds[index]) * norm)) + reds[index]), dtype=NP.uint8) greendata[selection] = NP("array", NP(NP(subset * ((greens[index + 1] - greens[index]) * norm)) + greens[index]), dtype=NP.uint8) bluedata[selection] = NP("array", NP(NP(subset * ((blues[index + 1] - blues[index]) * norm)) + blues[index]), dtype=NP.uint8) alphadata[selection] = NP("array", NP(NP(subset * ((alphas[index + 1] - alphas[index]) * norm)) + alphas[index]), dtype=NP.uint8) badpixels = NP("isnan", normalized) NP("logical_or", badpixels, NP("isinf", normalized), badpixels) if state.zmask is not None: NP("logical_or", badpixels, NP(state.zmask != defs.VALID), badpixels) alphadata[badpixels] = 0 X1, Y1 = plotCoordinates(xlow, ylow) X2, Y2 = plotCoordinates(xhigh, yhigh) onePixelBeyondBorder = self.get("onePixelBeyondBorder", defaultFromXsd=True, convertType=True) if onePixelBeyondBorder: Xwidth = (X2 - X1) / xbins Yheight = (Y1 - Y2) / ybins X1 -= Xwidth X2 += Xwidth Y1 += Yheight Y2 -= Yheight arrayToPng = ArrayToPng() arrayToPng.putdata(xbins, ybins, reddata, greendata, bluedata, alphadata, flipy=True, onePixelBeyondBorder=onePixelBeyondBorder) output.append(svg.image(**{defs.XLINK_HREF: "data:image/png;base64," + arrayToPng.b64encode(), "x": repr(X1), "y": repr(Y2), "width": repr(X2 - X1), "height": repr(Y1 - Y2), "image-rendering": self.get("imageRendering", defaultFromXsd=True), "preserveAspectRatio": "none"})) performanceTable.end("PlotHeatMap draw") return output