Newer
Older
(no author)
committed
#!/usr/bin/env python
# encoding: utf-8
"""
Plotting routines for different types of figures using matplotlib
Created by evas Dec 2009.
Copyright (c) 2009 University of Wisconsin SSEC. All rights reserved.
"""
from pylab import *
(no author)
committed
import matplotlib.cm as cm
(no author)
committed
import matplotlib.pyplot as plt
import matplotlib.colors as colors
(no author)
committed
from matplotlib.ticker import FormatStrFormatter
(no author)
committed
(no author)
committed
import numpy as np
(no author)
committed
from numpy import ma
(no author)
committed
import glance.graphics as maps
import glance.delta as delta
import glance.report as report
import glance.stats as statistics
(no author)
committed
LOG = logging.getLogger(__name__)
# TODO this value is being used to work around a problem with the contourf
# and how it handles range boundaries. Find a better solution if at all possible.
offsetToRange = 0.0000000000000000001
(no author)
committed
# make a custom medium grayscale color map for putting our bad data on top of
mediumGrayColorMapData = {
'red' : ((0.0, 1.00, 1.00),
(0.5, 0.60, 0.60),
(1.0, 0.20, 0.20)),
'green' : ((0.0, 1.00, 1.00),
(0.5, 0.60, 0.60),
(1.0, 0.20, 0.20)),
'blue' : ((0.0, 1.00, 1.00),
(0.5, 0.60, 0.60),
(1.0, 0.20, 0.20))
}
MEDIUM_GRAY_COLOR_MAP = colors.LinearSegmentedColormap('mediumGrayColorMap', mediumGrayColorMapData, 256)
(no author)
committed
# make an all green color map
greenColorMapData = {
'red' : ((0.0, 0.00, 0.00),
(1.0, 0.00, 0.00)),
'green' : ((0.0, 1.00, 1.00),
(1.0, 1.00, 1.00)),
'blue' : ((0.0, 0.00, 0.00),
(1.0, 0.00, 0.00))
}
greenColorMap = colors.LinearSegmentedColormap('greenColorMap', greenColorMapData, 256)
(no author)
committed
# todo, the use of the offset here is covering a problem with
(no author)
committed
# contourf hiding data exactly at the end of the range and should
# be removed if a better solution can be found
def _make_range(data_a, valid_a_mask, num_intervals, offset_to_range=0.0, data_b=None, valid_b_mask=None) :
(no author)
committed
"""
get an array with numbers representing the bounds of a set of ranges
that covers all the data present in data_a
(these may be used for plotting the data)
if an offset is passed, the outtermost range will be expanded by that much
if the b data is passed, a total range that encompasses both sets of
data will be used
"""
minVal = delta.min_with_mask(data_a, valid_a_mask)
maxVal = delta.max_with_mask(data_a, valid_a_mask)
(no author)
committed
# if we have a second set of data, include it in the min/max calculations
if (data_b is not None) :
minVal = min(delta.min_with_mask(data_b, valid_b_mask), minVal)
maxVal = max(delta.max_with_mask(data_b, valid_b_mask), maxVal)
(no author)
committed
minVal = minVal - offset_to_range
maxVal = maxVal + offset_to_range
return np.linspace(minVal, maxVal, num_intervals)
(no author)
committed
def _plot_tag_data_simple(tagData, axes) :
(no author)
committed
"""
This method will plot tag data listed as true in the
tagData mask on the current figure. It is assumed that
the correlation between the mask and the pixel coordinates
is exact (ie. no translation is needed).
The return will be the number of points plotted or
-1 if no valid tagData was given.
"""
(no author)
committed
numMismatchPoints = -1
(no author)
committed
# if there are "tag" masks, plot them over the existing map
if not (tagData is None) :
(no author)
committed
numMismatchPoints = sum(tagData)
(no author)
committed
(no author)
committed
# if we have mismatch points, we need to show them
if numMismatchPoints > 0:
(no author)
committed
# figure out how many bad points there are
totalNumPoints = tagData.size # the number of points
(no author)
committed
percentBad = (float(numMismatchPoints) / float(totalNumPoints)) * 100.0
LOG.debug('\t\tnumber of mismatch points: ' + str(numMismatchPoints))
LOG.debug('\t\tpercent of mismatch points: ' + str(percentBad))
(no author)
committed
(no author)
committed
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# get the current limits of the plot
tempXLim = axes.get_xlim()
tempYLim = axes.get_ylim()
# if there aren't a lot of points, plot them individually
if (numMismatchPoints < 50000) | ((numMismatchPoints < 200000) & (percentBad < 2.0)) :
(height, width) = tagData.shape
tempX = [ ]
tempY = [ ]
for h in range(height) :
for w in range(width) :
if tagData[h, w] :
tempX.append(w)
tempY.append(h)
pTemp = plot(tempX, tempY, '.', markersize=0.1, color='#00ff00')
# if there are a lot of points, plot them as an overall mask
else :
new_kwargs = {}
new_kwargs['cmap'] = greenColorMap
cleanTagData = ma.array(tagData, mask=~tagData)
pTemp = contourf(cleanTagData, **new_kwargs)
# make sure we haven't changed the limits of the plot
axes.set_xlim(tempXLim)
axes.set_ylim(tempYLim)
(no author)
committed
(no author)
committed
# display the number of mismatch points on the report if we were passed a set of tag data
mismatchPtString = '\n\nShowing ' + str(numMismatchPoints) + ' Mismatch Points'
(no author)
committed
# if our plot is more complex, add clarification
(no author)
committed
if numMismatchPoints > 0 :
mismatchPtString = mismatchPtString + ' in Green'
plt.xlabel(mismatchPtString)
(no author)
committed
(no author)
committed
return numMismatchPoints
(no author)
committed
def _plot_tag_data_mapped(bMap, tagData, x, y, addExplinationLabel=True) :
"""
This method will plot the tagged data listed as true in the tagData mask
on the current figure using the given basemap.
A message will also be added below the map describing the number of
points plotted, unless the addExplinationLabel variable is passed as False.
The return will be the number of points plotted or
-1 if no valid tagData was given.
(no author)
committed
numMismatchPoints = _plot_tag_data_mapped(bMap, tagData, x, y)
(no author)
committed
"""
(no author)
committed
numMismatchPoints = -1
(no author)
committed
# if there are "tag" masks, plot them over the existing map
if (tagData is not None) and (tagData.size > 0) :
(no author)
committed
# look at how many mismatch points we have
numMismatchPoints = sum(tagData)
(no author)
committed
neededHighlighting = False
(no author)
committed
if numMismatchPoints > 0 :
(no author)
committed
# pick out the cooridinates of the points we want to plot
newX = np.array(x[tagData])
newY = np.array(y[tagData])
# figure out how many bad points there are
totalNumPoints = x.size # the number of points
(no author)
committed
percentBad = (float(numMismatchPoints) / float(totalNumPoints)) * 100.0
LOG.debug('\t\tnumber of mismatch points: ' + str(numMismatchPoints))
LOG.debug('\t\tpercent of mismatch points: ' + str(percentBad))
(no author)
committed
# if there are very few points, make them easier to notice
# by plotting some colored circles underneath them
if (percentBad < 0.25) or (totalNumPoints < 20) :
neededHighlighting = True
p = bMap.plot(newX, newY, 'o', color='#993399', markersize=5)
elif (percentBad < 1.0) or (totalNumPoints < 200) :
neededHighlighting = True
p = bMap.plot(newX, newY, 'o', color='#993399', markersize=3)
(no author)
committed
# if there are way too many mismatch points, we can't use plot for this
if (numMismatchPoints > 1000000) :
(no author)
committed
new_kwargs = {}
new_kwargs['cmap'] = greenColorMap
(no author)
committed
cleanTagData = ma.array(tagData, mask=~tagData)
p = maps.show_x_y_data(x, y, bMap, data=cleanTagData, **new_kwargs)
(no author)
committed
else :
# plot our point on top of the existing figure
p = bMap.plot(newX, newY, '.', color='#00FF00', markersize=1)
if addExplinationLabel :
(no author)
committed
# display the number of mismatch points on the report if we were passed a set of tag data
(no author)
committed
# I'm not thrilled with this solution for getting it below the labels drawn by the basemap
# but I don't think there's a better one at the moment given matplotlib's workings
(no author)
committed
mismatchPtString = '\n\nShowing ' + str(numMismatchPoints) + ' Mismatch Points'
(no author)
committed
# if our plot is more complex, add clarification
(no author)
committed
if numMismatchPoints > 0 :
mismatchPtString = mismatchPtString + ' in Green'
(no author)
committed
if neededHighlighting :
(no author)
committed
mismatchPtString = mismatchPtString + '\nwith Purple Circles for Visual Clarity'
plt.xlabel(mismatchPtString)
(no author)
committed
(no author)
committed
return numMismatchPoints
(no author)
committed
# build a scatter plot of the x,y points
(no author)
committed
def create_scatter_plot(dataX, dataY, title, xLabel, yLabel, badMask=None, epsilon=None, units_x=None, units_y=None) :
(no author)
committed
"""
build a scatter plot of the data
if a bad mask is given the points selected by that mask will be plotted in a different color
if an epsilon is given the lines for +/- epsilon will be drawn on the plot
by default this plot uses blue for data points and red for data marked by the bad mask
"""
return create_complex_scatter_plot ([(dataX, dataY, badMask,
'b', 'r',
'within\nepsilon', 'outside\nepsilon')],
(no author)
committed
title, xLabel, yLabel, epsilon=epsilon, units_x=units_x, units_y=units_y)
(no author)
committed
(no author)
committed
def create_complex_scatter_plot(dataList, title, xLabel, yLabel, epsilon=None, units_x=None, units_y=None) :
(no author)
committed
"""
build a scatter plot with multiple data sets in different colors
the dataList parameter should be in the form:
[(set1), (set2), ... , (setN)]
where a set looks like:
(x data, y data, mask of bad points or None, matlab color code for display, matlab color code for 'bad' points, good label, bad label)
if a mask of bad points is given, it will be applyed to both the x and y data
at least one data set must be given or no image will be created.
"""
(no author)
committed
# make the figure
figure = plt.figure()
axes = figure.add_subplot(111)
(no author)
committed
# if we have no data, stop now
if (dataList is None) or (len(dataList) <= 0) :
return figure;
(no author)
committed
(no author)
committed
# look at the stuff in each of the data sets and plot that set
for dataX, dataY, badMask, goodColor, badColor, goodLabel, badLabel in dataList :
# if we have "bad" data to plot, pull it out
badX = None
badY = None
if (badMask != None) :
badX = dataX[badMask]
badY = dataY[badMask]
dataX = dataX[~badMask]
dataY = dataY[~badMask]
# the scatter plot of the good data
axes.plot(dataX, dataY, ',', color=goodColor, label=goodLabel)
# plot the bad data
(no author)
committed
numMismatchPts = 0
(no author)
committed
if (badX is not None) and (badY is not None) and (badMask is not None) :
(no author)
committed
numMismatchPts = badX.size
LOG.debug('\t\tplotting ' + str(numMismatchPts) + ' mismatch points in scatter plot.' )
if numMismatchPts > 0 :
(no author)
committed
axes.plot(badX, badY, ',', color=badColor, label=badLabel)
# draw some extra informational lines
_draw_x_equals_y_line(axes, epsilon=epsilon)
(no author)
committed
# make a key to explain our plot
# as long as things have been plotted with proper labels they should show up here
axes.legend(loc=0, markerscale=3.0) # Note: at the moment markerscale doesn't seem to work
(no author)
committed
# add the units to the x and y labels
tempXLabel = xLabel
tempYLabel = yLabel
if str.lower(str(units_x)) != "none" :
tempXLabel = tempXLabel + " in " + units_x
if str.lower(str(units_y)) != "none" :
tempYLabel = tempYLabel + " in " + units_y
(no author)
committed
# and some informational stuff
axes.set_title(title)
(no author)
committed
plt.xlabel(tempXLabel)
plt.ylabel(tempYLabel)
(no author)
committed
# format our axes so they display gracefully
yFormatter = FormatStrFormatter("%4.4g")
axes.yaxis.set_major_formatter(yFormatter)
xFormatter = FormatStrFormatter("%4.4g")
axes.xaxis.set_major_formatter(xFormatter)
return figure
(no author)
committed
# build a hexbin plot of the x,y points and show the density of the point distribution
(no author)
committed
def create_hexbin_plot(dataX, dataY, title, xLabel, yLabel, epsilon=None, units_x=None, units_y=None) :
(no author)
committed
# make the figure
figure = plt.figure()
axes = figure.add_subplot(111)
(no author)
committed
# for some reason, if you give the hexplot a data set that's all the same number it dies horribly
if ( ((dataX is None) or (len(dataX) <= 0)) or ((dataY is None) or (len(dataY) <= 0)) or
((dataX.max() == dataX.min()) and (dataY.max() == dataY.min())) ):
return figure
(no author)
committed
# the hexbin plot of the good data
plt.hexbin(dataX, dataY, bins='log', cmap=cm.jet)
plt.axis([dataX.min(), dataX.max(), dataY.min(), dataY.max()])
#heatmap, xedges, yedges = np.histogram2d(dataX, dataY, bins=100) #todo, testing
#heatmap = log(heatmap + 1)
#plt.imshow(heatmap, extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]], cmap=cm.jet)
(no author)
committed
# create a color bar
cb = plt.colorbar()
cb.set_label('log10 (count + 1)')
(no author)
committed
# draw some extra informational lines
_draw_x_equals_y_line(axes, color='w', epsilon=epsilon, epsilonColor='k')
(no author)
committed
# add the units to the x and y labels
tempXLabel = xLabel
tempYLabel = yLabel
if str.lower(str(units_x)) != "none" :
tempXLabel = tempXLabel + " in " + units_x
if str.lower(str(units_y)) != "none" :
tempYLabel = tempYLabel + " in " + units_y
(no author)
committed
# and some informational stuff
axes.set_title(title)
(no author)
committed
plt.xlabel(tempXLabel)
plt.ylabel(tempYLabel)
(no author)
committed
# format our axes so they display gracefully
yFormatter = FormatStrFormatter("%4.4g")
axes.yaxis.set_major_formatter(yFormatter)
xFormatter = FormatStrFormatter("%4.4g")
axes.xaxis.set_major_formatter(xFormatter)
return figure
(no author)
committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
def _draw_x_equals_y_line(axes, color='k', style='--', epsilon=None, epsilonColor='#00FF00', epsilonStyle='--') :
"""
Draw the x = y line using the axes and color/style given
If epsilon is not None, also draw the +/- epsilon lines,
if they fall in the graph
"""
# get the bounds for our calculations and so we can reset the viewing window later
xbounds = axes.get_xbound()
ybounds = axes.get_ybound()
# figure out the size of the ranges
xrange = xbounds[1] - xbounds[0]
yrange = ybounds[1] - ybounds[0]
# draw the x=y line
perfect = [max(xbounds[0], ybounds[0]), min(xbounds[1], ybounds[1])]
axes.plot(perfect, perfect, style, color=color, label='A = B')
# now draw the epsilon bound lines if they are visible and the lines won't be the same as A = B
if (not (epsilon is None)) and (epsilon > 0.0) and (epsilon < xrange) and (epsilon < yrange):
# plot the top line
axes.plot([perfect[0], perfect[1] - epsilon], [perfect[0] + epsilon, perfect[1]], epsilonStyle, color=epsilonColor, label='+/-epsilon')
# plot the bottom line
axes.plot([perfect[0] + epsilon, perfect[1]], [perfect[0], perfect[1] - epsilon], epsilonStyle, color=epsilonColor)
# reset the bounds
axes.set_xbound(xbounds)
axes.set_ybound(ybounds)
(no author)
committed
# build a histogram figure of the given data with the given title and number of bins
(no author)
committed
def create_histogram(data, bins, title, xLabel, yLabel, displayStats=False, units=None, rangeList=None) :
(no author)
committed
# make the figure
figure = plt.figure()
axes = figure.add_subplot(111)
if (data is None) or (len(data) <= 0) :
return figure
(no author)
committed
if rangeList is not None :
assert len(rangeList) == 2
assert rangeList[0] < rangeList[1]
(no author)
committed
# the histogram of the data
(no author)
committed
n, outBins, patches = plt.hist(data, bins, range=rangeList) # if rangeList is None the range won't be restricted
(no author)
committed
# format our axes so they display gracefully
yFormatter = FormatStrFormatter("%3.3g")
axes.yaxis.set_major_formatter(yFormatter)
xFormatter = FormatStrFormatter("%.4g")
axes.xaxis.set_major_formatter(xFormatter)
(no author)
committed
# add the units to the x and y labels
tempXLabel = xLabel
if str.lower(str(units)) != "none" :
tempXLabel = tempXLabel + " in " + units
(no author)
committed
# and some informational stuff
axes.set_title(title)
(no author)
committed
plt.xlabel(tempXLabel)
(no author)
committed
plt.ylabel(yLabel)
# if stats were passed in, put some of the information on the graph
# the location is in the form x, y (I think)
if displayStats :
# info on the basic stats
tempMask = ones(data.shape, dtype=bool)
tempStats = statistics.NumericalComparisonStatistics.basic_analysis(data, tempMask)
(no author)
committed
medianVal = tempStats['median_delta']
meanVal = tempStats['mean_delta']
stdVal = tempStats['std_val']
numPts = data.size
(no author)
committed
# info on the display of our statistics
xbounds = axes.get_xbound()
(no author)
committed
numBinsToUse = bins
(no author)
committed
xrange = xbounds[1] - xbounds[0]
binSize = xrange / float(numBinsToUse)
# build the display string
statText = ('%1.2e' % numPts) + ' data points'
statText = statText + '\n' + 'mean: ' + report.make_formatted_display_string(meanVal)
statText = statText + '\n' + 'median: ' + report.make_formatted_display_string(medianVal)
statText = statText + '\n' + 'std: ' + report.make_formatted_display_string(stdVal)
(no author)
committed
statText = statText + '\n\n' + 'intervals: ' + report.make_formatted_display_string(numBinsToUse)
statText = statText + '\n' + 'interval size ' + report.make_formatted_display_string(binSize)
(no author)
committed
# figure out where to place the text and put it on the figure
centerOfDisplay = xbounds[0] + (float(xrange) / 2.0)
xValToUse = 0.67
# if most of the values will be on the right, move our text to the left...
if (medianVal > centerOfDisplay) :
xValToUse = 0.17
figtext(xValToUse, 0.60, statText)
(no author)
committed
# make sure we didn't mess up the range if it's being restricted
# (this may be unnessicary, but it's a good extra precaution)
if rangeList is not None:
plt.xlim(rangeList)
(no author)
committed
return figure
# create a figure including our data mapped onto a map at the lon/lat given
# the colorMap parameter can be used to control the colors the figure is drawn in
# if any masks are passed in the tagData list they will be plotted as an overlays
# set on the existing image
def create_mapped_figure(data, latitude, longitude, baseMapInstance, boundingAxes, title,
invalidMask=None, colorMap=None, tagData=None,
(no author)
committed
dataRanges=None, dataRangeNames=None, dataRangeColors=None, units=None, **kwargs) :
(no author)
committed
# make a clean version of our lon/lat
latitudeClean = ma.array(latitude, mask=~invalidMask)
longitudeClean = ma.array(longitude, mask=~invalidMask)
# build the plot
figure = plt.figure()
axes = figure.add_subplot(111)
# build extra info to go to the map plotting function
kwargs = { }
# figure the range for the color bars
# this is controllable with the "dataRanges" parameter for discrete data display
if not (data is None) :
if dataRanges is None :
dataRanges = _make_range(data, ~invalidMask, 50, offset_to_range=offsetToRange)
(no author)
committed
else: # make sure the user range will not discard data TODO, find a better way to handle this
dataRanges[0] = dataRanges[0] - offsetToRange
dataRanges[len(dataRanges) - 1] = dataRanges[len(dataRanges) - 1] + offsetToRange
kwargs['levelsToUse'] = dataRanges
if dataRangeColors is not None :
kwargs['colors'] = dataRangeColors # add in the list of colors (may be None)
# if we've got a color map, pass it to the list of things we want to tell the plotting function
if not (colorMap is None) :
kwargs['cmap'] = colorMap
# draw our data placed on a map
maps.draw_basic_features(baseMapInstance, boundingAxes)
bMap, x, y = maps.show_lon_lat_data(longitudeClean, latitudeClean, baseMapInstance, data=data, **kwargs)
# and some informational stuff
axes.set_title(title)
# show a generic color bar
doLabelRanges = False
(no author)
committed
if data is not None :
(no author)
committed
# if there are specific requested labels, add them
if not (dataRangeNames is None) :
# if we don't have exactly the right number of range names to label the ranges
# then label the tick marks
if not (len(dataRangeNames) is (len(dataRanges) - 1)) :
cbar.ax.set_yticklabels(dataRangeNames)
else : # we will want to label the ranges themselves
cbar.ax.set_yticklabels(dataRangeNames) # todo, this line is temporary
doLabelRanges = True
(no author)
committed
else :
# add the units to the colorbar
if str.lower(str(units)) != "none" :
cbar.set_label(units)
(no author)
committed
(no author)
committed
numMismatchPoints = _plot_tag_data_mapped(bMap, tagData, x, y)
(no author)
committed
(no author)
committed
LOG.debug ('number of mismatch points: ' + str(numMismatchPoints))
(no author)
committed
(no author)
committed
# if we still need to label the ranges, do it now that our fake axis won't mess the mismatch points up
(no author)
committed
if doLabelRanges :
""" TODO get this working properly
fakeAx = plt.axes ([0.77, 0.05, 0.2, 0.9], frameon=False)
fakeAx.xaxis.set_visible(False)
fakeAx.yaxis.set_visible(False)
testRect = Rectangle((0, 0), 1, 1, fc="r")
legendKey = fakeAx.legend([testRect], ["r\n\n\n"], mode="expand", ncol=1, borderaxespad=0.)
"""
return figure
# create a figure including a quiver plot of our vector data mapped onto a map at the lon/lat
# given, the colorMap parameter can be used to control the colors the figure is drawn.
# if any masks are passed in the tagData list they will be plotted as an overlays
# set on the existing image
# TODO, this method has not been throughly tested
(no author)
committed
# TODO, this method needs an input colormap so the mismatch plot can be the right color
(no author)
committed
def create_quiver_mapped_figure(data, latitude, longitude, baseMapInstance, boundingAxes, title,
(no author)
committed
invalidMask=None, tagData=None, uData=None, vData=None, units=None, **kwargs) :
(no author)
committed
# make a clean version of our lon/lat/data
latitudeClean = latitude[~invalidMask]
longitudeClean = longitude[~invalidMask]
colorData = None
if (data is not None) :
colorData = data[~invalidMask]
uDataClean = None
vDataClean = None
if (uData is not None) and (vData is not None) :
uDataClean = uData[~invalidMask]
vDataClean = vData[~invalidMask]
tagDataClean = None
if tagData is not None :
tagDataClean = tagData[~invalidMask]
# build the plot
figure = plt.figure()
axes = figure.add_subplot(111)
# draw our data placed on a map
maps.draw_basic_features(baseMapInstance, boundingAxes)
(no author)
committed
bMap, x, y = maps.show_quiver_plot (longitudeClean, latitudeClean, baseMapInstance, (uDataClean, vDataClean), colordata=colorData)
(no author)
committed
# show the title
axes.set_title(title)
(no author)
committed
# make a color bar if we have color data
""" todo, currently this crashes glance because of an error in matplot lib
if colorData is not None :
cbar = plt.colorbar(format='%.3g')
# add the units to the colorbar
if str.lower(str(units)) != "none" :
cbar.set_label(units)
"""
numMismatchPoints = _plot_tag_data_mapped(bMap, tagDataClean, x, y)
(no author)
committed
return figure
def create_raw_image_plot(data, figureTitle, hideAxesLabels=True) :
"""
for drawing rgb and rgba images we want an uncomplicated version of this call
"""
# build the plot
figure = plt.figure()
axes = figure.add_subplot(111)
if (data is not None) :
# draw our data
im = plt.imshow(data)
# set the title
axes.set_title(figureTitle)
if hideAxesLabels :
axes.get_xaxis().set_visible(False)
axes.get_yaxis().set_visible(False)
return figure
def create_simple_figure(data, figureTitle, invalidMask=None, tagData=None,
colorMap=None, colorbarLimits=None, units=None,
drawColorbar=True) :
(no author)
committed
"""
create a simple figure showing the data given masked by the invalid mask
(no author)
committed
any tagData passed in will be interpreted as mismatch points on the image and plotted as a
(no author)
committed
filled contour overlay in green on the image
if a colorMap is given it will be used to plot the data,
if not the default colorMap for imshow will be used
"""
cleanData = ma.array(data, mask=invalidMask)
# build the plot
figure = plt.figure()
axes = figure.add_subplot(111)
# build extra info to go to the map plotting function
kwargs = { }
# if we've got a color map, pass it to the list of things we want to tell the plotting function
if not (colorMap is None) :
kwargs['cmap'] = colorMap
if colorMap is np.nan :
kwargs['cmap'] = None
(no author)
committed
(no author)
committed
if (data is not None) and (np.sum(invalidMask) < invalidMask.size) :
(no author)
committed
# draw our data
im = imshow(cleanData, **kwargs)
if drawColorbar :
# if our colorbar has limits set those
if colorbarLimits is not None :
LOG.debug("setting colorbar limits: " + str(colorbarLimits))
clim(vmin=colorbarLimits[0], vmax=colorbarLimits[-1])
# make a color bar
cbar = colorbar(format='%.3g')
# add the units to the colorbar
if str.lower(str(units)) != "none" :
cbar.set_label(units)
(no author)
committed
# and some informational stuff
axes.set_title(figureTitle)
(no author)
committed
numMismatchPoints = _plot_tag_data_simple(tagData, axes)
(no author)
committed
return figure
def create_line_plot_figure(dataList, figureTitle) :
"""
create a basic line plot of the data vs. it's index, ignoring any invalid data
if tagData is given, under-label those points with green circles
Each entry in the dataList should be a tupple containing:
(no author)
committed
(data, invalidMask, colorString, labelName, tagData, units)
(no author)
committed
The color string describes a color for plotting in matplotlib.
The label names will be used for the legend, which will be shown if there is
more than one set of data plotted or if there is tag data plotted. Invalid
masks, colors, and label names may be given as None, in which case no data
will be masked and a default label of "data#" (where # is an arbitrary
unique counter) will be used.
tagData may also be passed as None if tagging is not desired in the output.
(no author)
committed
units describes the units used to measure the data (such as mm or degrees)
and will be used to label the plot. units may be passed as None.
(no author)
committed
"""
# build the plot
figure = plt.figure()
axes = figure.add_subplot(111)
# plot each of the data sets
dataSetLabelNumber = 1
minTagPts = -1
maxTagPts = -1
plottedTagData = False
(no author)
committed
for dataSet, invalidMask, colorString, labelName, tagData, units in dataList :
(no author)
committed
# if we don't have these, set them to defaults
if invalidMask is None :
(no author)
committed
invalidMask = zeros(dataSet.size, dtype=bool)
(no author)
committed
if labelName is None :
labelName = 'data' + str(dataSetLabelNumber)
dataSetLabelNumber = dataSetLabelNumber + 1
if colorString is None:
colorString = ''
if (dataSet is not None) and (sum(invalidMask) < invalidMask.size) :
# if we don't have a real min yet, set it based on the size
if minTagPts < 0 :
minTagPts = dataSet.size + 1
(no author)
committed
indexData = ma.array(range(dataSet.size), mask=invalidMask.ravel())
cleanData = ma.array(dataSet.ravel(), mask=invalidMask.ravel())
(no author)
committed
# plot the tag data and gather information about it
if tagData is not None :
plottedTagData = True
(no author)
committed
numMismatchPoints = sum(tagData)
LOG.debug('\t\tnumber of mismatch points: ' + str(numMismatchPoints))
if numMismatchPoints < minTagPts:
minTagPts = numMismatchPoints
if numMismatchPoints > maxTagPts :
maxTagPts = numMismatchPoints
(no author)
committed
(no author)
committed
# if we have mismatch points, we need to show them
if numMismatchPoints > 0:
(no author)
committed
(no author)
committed
cleanTagData = ma.array(dataSet.ravel(), mask=~tagData.ravel() | invalidMask.ravel())
(no author)
committed
axes.plot(indexData, cleanTagData, 'yo', label='mismatch point')
if str.lower(str(units)) !="none" :
labelName = labelName + " in " + units
(no author)
committed
axes.plot(indexData, cleanData, '-' + colorString, label=labelName)
(no author)
committed
# display the number of mismatch points on the report if we were passed
(no author)
committed
# a set of tag data and we were able to compare it to some actual data
if (plottedTagData and (minTagPts >= 0) and (maxTagPts >=0)) :
(no author)
committed
mismatchPtString = '\nMarking '
(no author)
committed
if (minTagPts == maxTagPts) :
(no author)
committed
mismatchPtString = mismatchPtString + str(minTagPts) + ' Mismatch Points with Yellow Circles'
(no author)
committed
else :
(no author)
committed
mismatchPtString = (mismatchPtString + 'between ' + str(minTagPts) + ' and ' + str(maxTagPts) + ' Mismatch Points'
(no author)
committed
+ '\non the various data sets (using Yellow Circles)')
(no author)
committed
plt.xlabel(mismatchPtString)
(no author)
committed
if (len(dataList) > 1) or plottedTagData :
# make a key to explain our plot
# as long as things have been plotted with proper labels they should show up here
(no author)
committed
axes.legend(loc=0, markerscale=3.0) # Note: at the moment markerscale doesn't seem to work