From 8a680e5ba7c395e5ebd4a7f45cf2b688beaaa3e7 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Thu, 23 Jan 2014 16:53:44 -0500 Subject: [PATCH 01/29] musicRTI: added range coords plotting, lat ytick formatting, disable terminator until further testing --- pydarn/plotting/musicPlot.py | 154 ++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 56 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index a99b5655..a628ef87 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -45,6 +45,7 @@ """ import numpy as np +import scipy as sp import datetime from matplotlib.collections import PolyCollection @@ -279,6 +280,7 @@ class musicRTI(object): * [**yBoundaryLimits**] (None or 2-element iterable of floats): Mark a region of range on the RTI plot. A green dashed horizontal line will be plotted at each of the boundary ranges. The region of time outside of the boundary will be shaded gray. If set to None, this will automatically be set to the gateLimits set in the metadata, if they exist. + * [**ytick_lat_format**] (str): %-style string format code for latitude y-tick labels * [**autoScale**] (bool): If True, automatically scale the color bar for good data visualization. Keyword scale must be None when using autoScale. * [**plotTerminator**] (bool): If True, overlay day/night terminator on the RTI plot. Every cell is evaluated for day/night and shaded accordingly. Therefore, terminator resolution will match the resolution of the RTI plot data. @@ -296,8 +298,8 @@ class musicRTI(object): Written by Nathaniel A. Frissell, Fall 2013 """ - def __init__(self,dataObject,dataSet='active',beam=7,xlim=None,ylim=None,axis=None,scale=None, plotZeros=False, - xBoundaryLimits=None, yBoundaryLimits=None, autoScale=False, plotTerminator=True, axvlines=None, + def __init__(self,dataObject,dataSet='active',beam=7,coords='gate',xlim=None,ylim=None,axis=None,scale=None, plotZeros=False, + xBoundaryLimits=None, yBoundaryLimits=None, ytick_lat_format = '.0f', autoScale=False, plotTerminator=True, axvlines=None, axvline_color='0.25', secondary_coords='lat', plot_info=True, plot_title=True, cbar_ticks=None, cbar_shrink=1.0, cbar_fraction=0.15, cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None, **kwArgs): @@ -336,16 +338,6 @@ def __init__(self,dataObject,dataSet='active',beam=7,xlim=None,ylim=None,axis=No if day_inx.size != 0: daylight[tm_inx,day_inx] = False -# The coords keyword needs to be tested better. For now, just allow 'gate' only. -# Even in 'gate' mode, the geographic latitudes are plotted along with gate. -# if coords == None and metadata.has_key('coords'): -# coords = metadata['coords'] -# -# if coords not in ['gate','range']: -# print 'Coords "%s" not supported for RTI plots. Using "gate".' % coords -# coords = 'gate' - coords = 'gate' - #Translate parameter information from short to long form. paramDict = getParamDict(metadata['param']) if paramDict.has_key('label'): @@ -386,7 +378,20 @@ def __init__(self,dataObject,dataSet='active',beam=7,xlim=None,ylim=None,axis=No scan = [] data = np.squeeze(currentData.data[:,beamInx,:]) - rnge = currentData.fov.gates +# The coords keyword needs to be tested better. For now, just allow 'gate' only. +# Even in 'gate' mode, the geographic latitudes are plotted along with gate. +# if coords == None and metadata.has_key('coords'): +# coords = metadata['coords'] +# + if coords not in ['gate','range']: + print 'Coords "%s" not supported for RTI plots. Using "gate".' % coords + coords = 'gate' + + if coords == 'gate': + rnge = currentData.fov.gates + elif coords == 'range': + rnge = currentData.fov.slantRFull[beam,:] + xvec = [matplotlib.dates.date2num(x) for x in currentData.time] for tm in range(nrTimes-1): for rg in range(nrGates-1): @@ -414,25 +419,25 @@ def __init__(self,dataObject,dataSet='active',beam=7,xlim=None,ylim=None,axis=No # Plot the terminator! ######################################################### if plotTerminator: - #Plot the SuperDARN data! - term_verts = [] - term_scan = [] - - rnge = currentData.fov.gates - xvec = [matplotlib.dates.date2num(x) for x in currentData.time] - for tm in range(nrTimes-1): - for rg in range(nrGates-1): - if daylight[tm,rg]: continue - term_scan.append(1) - - x1,y1 = xvec[tm+0],rnge[rg+0] - x2,y2 = xvec[tm+1],rnge[rg+0] - x3,y3 = xvec[tm+1],rnge[rg+1] - x4,y4 = xvec[tm+0],rnge[rg+1] - term_verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) - - term_pcoll = PolyCollection(np.array(term_verts),facecolors='0.45',linewidth=0,zorder=99,alpha=0.25) - axis.add_collection(term_pcoll,autolim=False) + print 'Terminator functionality is disabled until further testing is completed.' +# term_verts = [] +# term_scan = [] +# +# rnge = currentData.fov.gates +# xvec = [matplotlib.dates.date2num(x) for x in currentData.time] +# for tm in range(nrTimes-1): +# for rg in range(nrGates-1): +# if daylight[tm,rg]: continue +# term_scan.append(1) +# +# x1,y1 = xvec[tm+0],rnge[rg+0] +# x2,y2 = xvec[tm+1],rnge[rg+0] +# x3,y3 = xvec[tm+1],rnge[rg+1] +# x4,y4 = xvec[tm+0],rnge[rg+1] +# term_verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) +# +# term_pcoll = PolyCollection(np.array(term_verts),facecolors='0.45',linewidth=0,zorder=99,alpha=0.25) +# axis.add_collection(term_pcoll,autolim=False) ################################################################################ if axvlines is not None: @@ -449,36 +454,73 @@ def __init__(self,dataObject,dataSet='active',beam=7,xlim=None,ylim=None,axis=No if ylim == None: ylim = (np.min(rnge),np.max(rnge)) axis.set_ylim(ylim) - if secondary_coords == 'range': - axis.set_ylabel('Range Gate\n%s Slant Range [km]' % metadata['model']) - else: - axis.set_ylabel('Range Gate\nGeographic Latitude') - - yticks = axis.get_yticks() - ytick_str = [] - for tck in yticks: - txt = [] - txt.append('%d' % tck) - rg_inx = np.where(tck == currentData.fov.gates)[0] - if np.size(rg_inx) != 0: + # Y-axis labeling ############################################################## + if coords == 'gate': + if secondary_coords: if secondary_coords == 'range': - rang = currentData.fov.slantRCenter[beamInx,rg_inx] - if np.isfinite(rang): - txt.append('%d' % rang) - else: - txt.append('') + axis.set_ylabel('Range Gate\n%s Slant Range [km]' % metadata['model']) else: - lat = currentData.fov.latCenter[beamInx,rg_inx] - if np.isfinite(lat): - txt.append(u'%.1f$^o$' % lat) - else: + geo_mag = 'Geographic' if currentData.fov.coords == 'geo' else 'Magnetic' + axis.set_ylabel('Range Gate\n%s Latitude' % geo_mag) + + yticks = axis.get_yticks() + ytick_str = [] + for tck in yticks: + txt = [] + txt.append('%d' % tck) + + rg_inx = np.where(tck == currentData.fov.gates)[0] + if np.size(rg_inx) != 0: + if secondary_coords == 'range': + rang = currentData.fov.slantRCenter[beamInx,rg_inx] + if np.isfinite(rang): + txt.append('%d' % rang) + else: + txt.append('') + else: + lat = currentData.fov.latCenter[beamInx,rg_inx] + if np.isfinite(lat): + txt.append((u'%'+ytick_lat_format+'$^o$') % lat) + else: + txt.append('') + txt = '\n'.join(txt) + ytick_str.append(txt) + axis.set_yticklabels(ytick_str,rotation=90,ma='center') + else: + axis.set_ylabel('Range Gate') + elif coords == 'range': + if secondary_coords == 'lat': + # Use linear interpolation to get the latitude associated with a particular range. + # Make sure we only include finite values in the interpolation function. + finite_inx = np.where(np.isfinite(currentData.fov.latCenter[beam,:]))[0] + tmp_ranges = currentData.fov.slantRCenter[beam,:][finite_inx] + tmp_lats = currentData.fov.latCenter[beam,:][finite_inx] + tmp_fn = sp.interpolate.interp1d(tmp_ranges,tmp_lats) + + yticks = axis.get_yticks() + ytick_str = [] + for tck in yticks: + txt = [] + + # Append Latitude + try: + lat = tmp_fn(tck) + txt.append((u'%'+ytick_lat_format+'$^o$') % lat) + except: txt.append('') - txt = '\n'.join(txt) - ytick_str.append(txt) - axis.set_yticklabels(ytick_str,rotation=90,ma='center') + # Append Range + txt.append('%d' % tck) + txt = '\n'.join(txt) + ytick_str.append(txt) #Put both lat and range on same string + axis.set_yticklabels(ytick_str,rotation=90,ma='center') # Set yticklabels + # Label y-axis + geo_mag = 'Geographic' if currentData.fov.coords == 'geo' else 'Magnetic' + axis.set_ylabel('%s Latitude\n%s Slant Range [km]' % (geo_mag,metadata['model'])) + else: + axis.set_ylabel('%s Slant Range [km]' % metadata['model']) #Shade xBoundary Limits if xBoundaryLimits == None: From 6a59173130204ec5032b3150ede85f1296169d7f Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Thu, 23 Jan 2014 17:09:12 -0500 Subject: [PATCH 02/29] musicRTI: added yticks keyword --- pydarn/plotting/musicPlot.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index a628ef87..16126f18 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -280,6 +280,7 @@ class musicRTI(object): * [**yBoundaryLimits**] (None or 2-element iterable of floats): Mark a region of range on the RTI plot. A green dashed horizontal line will be plotted at each of the boundary ranges. The region of time outside of the boundary will be shaded gray. If set to None, this will automatically be set to the gateLimits set in the metadata, if they exist. + * [**yticks**] (list): Where to put the ticks on the y-axis. * [**ytick_lat_format**] (str): %-style string format code for latitude y-tick labels * [**autoScale**] (bool): If True, automatically scale the color bar for good data visualization. Keyword scale must be None when using autoScale. * [**plotTerminator**] (bool): If True, overlay day/night terminator on the RTI plot. Every cell is evaluated for day/night and shaded accordingly. Therefore, @@ -299,7 +300,7 @@ class musicRTI(object): Written by Nathaniel A. Frissell, Fall 2013 """ def __init__(self,dataObject,dataSet='active',beam=7,coords='gate',xlim=None,ylim=None,axis=None,scale=None, plotZeros=False, - xBoundaryLimits=None, yBoundaryLimits=None, ytick_lat_format = '.0f', autoScale=False, plotTerminator=True, axvlines=None, + xBoundaryLimits=None, yBoundaryLimits=None, yticks=None, ytick_lat_format = '.0f', autoScale=False, plotTerminator=True, axvlines=None, axvline_color='0.25', secondary_coords='lat', plot_info=True, plot_title=True, cbar_ticks=None, cbar_shrink=1.0, cbar_fraction=0.15, cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None, **kwArgs): @@ -455,6 +456,9 @@ def __init__(self,dataObject,dataSet='active',beam=7,coords='gate',xlim=None,yli ylim = (np.min(rnge),np.max(rnge)) axis.set_ylim(ylim) + if yticks != None: + axis.set_yticks(yticks) + # Y-axis labeling ############################################################## if coords == 'gate': if secondary_coords: From e41fec0f746bf61d086e0adb8eed15bdd9d57b1c Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 10:49:10 -0500 Subject: [PATCH 03/29] put shading behind data in musicRTI --- pydarn/plotting/musicPlot.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 16126f18..f2e27495 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -526,6 +526,7 @@ def __init__(self,dataObject,dataSet='active',beam=7,coords='gate',xlim=None,yli else: axis.set_ylabel('%s Slant Range [km]' % metadata['model']) + axis.set_ylim(ylim) #Shade xBoundary Limits if xBoundaryLimits == None: if currentData.metadata.has_key('timeLimits'): @@ -550,8 +551,10 @@ def __init__(self,dataObject,dataSet='active',beam=7,coords='gate',xlim=None,yli if yBoundaryLimits != None: gray = '0.75' - axis.axhspan(ylim[0],yBoundaryLimits[0],color=gray,zorder=150,alpha=0.5) - axis.axhspan(yBoundaryLimits[1],ylim[1],color=gray,zorder=150,alpha=0.5) +# axis.axhspan(ylim[0],yBoundaryLimits[0],color=gray,zorder=150,alpha=0.5) +# axis.axhspan(yBoundaryLimits[1],ylim[1],color=gray,zorder=150,alpha=0.5) + axis.axhspan(ylim[0],yBoundaryLimits[0],color=gray,zorder=1) + axis.axhspan(yBoundaryLimits[1],ylim[1],color=gray,zorder=1) axis.axhline(y=yBoundaryLimits[0],color='g',ls='--',lw=2,zorder=150) axis.axhline(y=yBoundaryLimits[1],color='g',ls='--',lw=2,zorder=150) From 7c33893114be4fe0fdde991b00ad4e8a8c398803 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 14:03:51 -0500 Subject: [PATCH 04/29] fixed bandpass filter 180 deg phase error --- pydarn/proc/music/music.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 491b52de..40790623 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -1104,6 +1104,7 @@ def __init__(self, dataObj, dataSet='active', numtaps=None, cutoff_low=None, cut if cutoff_high != None and cutoff_low != None: d = -(lp+hp) d[numtaps/2] = d[numtaps/2] + 1 + d = -1.*d #Needed to correct 180 deg phase shift. if cutoff_high == None and cutoff_low == None: print "WARNING!! You must define cutoff frequencies!" From 7fac6771c262d419fc238b531d7d1d2ca391b946 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 14:41:57 -0500 Subject: [PATCH 05/29] made musicRTI keywords more readable --- pydarn/plotting/musicPlot.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index f2e27495..17b9301e 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -299,10 +299,32 @@ class musicRTI(object): Written by Nathaniel A. Frissell, Fall 2013 """ - def __init__(self,dataObject,dataSet='active',beam=7,coords='gate',xlim=None,ylim=None,axis=None,scale=None, plotZeros=False, - xBoundaryLimits=None, yBoundaryLimits=None, yticks=None, ytick_lat_format = '.0f', autoScale=False, plotTerminator=True, axvlines=None, - axvline_color='0.25', secondary_coords='lat', plot_info=True, plot_title=True, cbar_ticks=None, cbar_shrink=1.0, cbar_fraction=0.15, - cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None, **kwArgs): + def __init__(self,dataObject, + dataSet = 'active', + beam = 7, + coords = 'gate', + xlim = None, + ylim = None, + axis = None, + scale = None, + plotZeros = False, + xBoundaryLimits = None, + yBoundaryLimits = None, + yticks = None, + ytick_lat_format = '.0f', + autoScale = False, + plotTerminator = True, + axvlines = None, + axvline_color = '0.25', + secondary_coords = 'lat', + plot_info = True, + plot_title = True, + cbar_ticks = None, + cbar_shrink = 1.0, + cbar_fraction = 0.15, + cbar_gstext_offset = -0.075, + cbar_gstext_fontsize = None, + **kwArgs): from scipy import stats from rti import plotFreq,plotNoise From 98186745d435108b4552296f20c33ca347e85767 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 15:06:18 -0500 Subject: [PATCH 06/29] added cmap_handling keyword to musicRTI --- pydarn/plotting/musicPlot.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 17b9301e..763e3d61 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -290,6 +290,8 @@ class musicRTI(object): * [**secondary_coords**] (str): Secondary coordate system for RTI plot y-axis ('lat' or 'range') * [**plot_info**] : If True, plot frequency/noise plots * [**plot_title**] : If True, plot the title information + * [**cmap_handling**] (str): 'superdarn' to use SuperDARN-style colorbars, 'matplotlib' for direct use of matplotlib's colorbars. + 'matplotlib' is recommended when using custom scales and the 'superdarn' mode is not providing a desirable result. * [**cbar_ticks**] (list): Where to put the ticks on the color bar. * [**cbar_shrink**] (float): fraction by which to shrink the colorbar * [**cbar_fraction**] (float): fraction of original axes to use for colorbar @@ -319,6 +321,7 @@ def __init__(self,dataObject, secondary_coords = 'lat', plot_info = True, plot_title = True, + cmap_handling = 'superdarn', cbar_ticks = None, cbar_shrink = 1.0, cbar_fraction = 0.15, @@ -428,11 +431,11 @@ def __init__(self,dataObject, x4,y4 = xvec[tm+0],rnge[rg+1] verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) - if (scale[0] >= -1 and scale[1] <= 1) or autoScale: + if (cmap_handling == 'matplotlib') or autoScale: cmap = matplotlib.cm.jet bounds = np.linspace(scale[0],scale[1],256) norm = matplotlib.colors.BoundaryNorm(bounds,cmap.N) - else: + elif cmap_handling == 'superdarn': colors = 'lasse' cmap,norm,bounds = utils.plotUtils.genCmap(param,scale,colors=colors) @@ -600,7 +603,7 @@ def __init__(self,dataObject, cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) cbar.set_label(cbarLabel) - if not cbar_ticks: + if cbar_ticks is None: labels = cbar.ax.get_yticklabels() labels[-1].set_visible(False) else: From ddf23590db76bbfb40a96f470a1940ab5471a93c Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 15:44:55 -0500 Subject: [PATCH 07/29] changed GS Mapped labeling on musicRTI, made musicFan keywords more readable --- pydarn/plotting/musicPlot.py | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 763e3d61..eab9b463 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -105,7 +105,18 @@ class musicFan(object): Written by Nathaniel A. Frissell, Fall 2013 """ - def __init__(self,dataObject,dataSet='active',time=None,axis=None,scale=None,autoScale=False, plotZeros=False, markCell=None, plotTerminator=True, title=None, **kwArgs): + def __init__(self,dataObject, + dataSet = 'active', + time = None, + axis = None, + scale = None, + autoScale = False, + plotZeros = False, + markCell = None, + plotTerminator = True, + title = None, + **kwArgs): + if axis == None: from matplotlib import pyplot as plt fig = plt.figure(figsize=figsize) @@ -488,10 +499,16 @@ def __init__(self,dataObject, if coords == 'gate': if secondary_coords: if secondary_coords == 'range': - axis.set_ylabel('Range Gate\n%s Slant Range [km]' % metadata['model']) + if metadata['model'] == 'IS': + axis.set_ylabel('Range Gate\nSlant Range [km]') + elif metadata['model'] == 'GS': + axis.set_ylabel('Range Gate\nGS Mapped Range [km]') else: geo_mag = 'Geographic' if currentData.fov.coords == 'geo' else 'Magnetic' - axis.set_ylabel('Range Gate\n%s Latitude' % geo_mag) + if metadata['model'] == 'IS': + axis.set_ylabel('Range Gate\n%s Latitude' % geo_mag) + elif metadata['model'] == 'GS': + axis.set_ylabel('Range Gate\nGS Mapped %s Latitude' % geo_mag) yticks = axis.get_yticks() ytick_str = [] @@ -547,9 +564,15 @@ def __init__(self,dataObject, axis.set_yticklabels(ytick_str,rotation=90,ma='center') # Set yticklabels # Label y-axis geo_mag = 'Geographic' if currentData.fov.coords == 'geo' else 'Magnetic' - axis.set_ylabel('%s Latitude\n%s Slant Range [km]' % (geo_mag,metadata['model'])) + if metadata['model'] == 'IS': + axis.set_ylabel('%s Latitude\nSlant Range [km]' % geo_mag) + elif metadata['model'] == 'GS': + axis.set_ylabel('GS Mapped %s Latitude\nGS Mapped Range [km]' % geo_mag) else: - axis.set_ylabel('%s Slant Range [km]' % metadata['model']) + if metadata['model'] == 'IS': + axis.set_ylabel('Slant Range [km]') + elif metadata['model'] == 'GS': + axis.set_ylabel('GS Mapped Range [km]') axis.set_ylim(ylim) #Shade xBoundary Limits From 51f2712fa4e57a63e394aa87b5526fba80a64267 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 16:44:33 -0500 Subject: [PATCH 08/29] added cbar options to musicFan --- pydarn/plotting/musicPlot.py | 55 +++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index eab9b463..93a699ac 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -106,16 +106,23 @@ class musicFan(object): Written by Nathaniel A. Frissell, Fall 2013 """ def __init__(self,dataObject, - dataSet = 'active', - time = None, - axis = None, - scale = None, - autoScale = False, - plotZeros = False, - markCell = None, - plotTerminator = True, - title = None, - **kwArgs): + dataSet = 'active', + time = None, + axis = None, + scale = None, + autoScale = False, + plotZeros = False, + markCell = None, + plotTerminator = True, + plot_title = True, + cmap_handling = 'superdarn', + cbar_ticks = None, + cbar_shrink = 1.0, + cbar_fraction = 0.15, + cbar_gstext_offset = -0.075, + cbar_gstext_fontsize = None, + title = None, + **kwArgs): if axis == None: from matplotlib import pyplot as plt @@ -221,11 +228,11 @@ def __init__(self,dataObject, x4,y4 = m(lonFull[bm+0,rg+1],latFull[bm+0,rg+1]) verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) - if (scale[0] >= -1 and scale[1] <= 1) or autoScale: + if (cmap_handling == 'matplotlib') or autoScale: cmap = matplotlib.cm.jet bounds = np.linspace(scale[0],scale[1],256) norm = matplotlib.colors.BoundaryNorm(bounds,cmap.N) - else: + elif cmap_handling == 'superdarn': colors = 'lasse' cmap,norm,bounds = utils.plotUtils.genCmap(param,scale,colors=colors) @@ -249,20 +256,24 @@ def __init__(self,dataObject, axis.add_patch(poly) dataName = currentData.history[max(currentData.history.keys())] #Label the plot with the current level of data processing. - if title is None: - axis.set_title(metadata['name']+' - '+dataName+currentData.time[timeInx].strftime('\n%Y %b %d %H%M UT')) - else: - axis.set_title(title) + if plot_title: + if title is None: + axis.set_title(metadata['name']+' - '+dataName+currentData.time[timeInx].strftime('\n%Y %b %d %H%M UT')) + else: + axis.set_title(title) -# cbar = fig.colorbar(pcoll,orientation='vertical')#,shrink=.65,fraction=.1) - cbar = fig.colorbar(pcoll,orientation='vertical',shrink=.85,fraction=.1) + cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) cbar.set_label(cbarLabel) - labels = cbar.ax.get_yticklabels() - labels[-1].set_visible(False) + if cbar_ticks is None: + labels = cbar.ax.get_yticklabels() + labels[-1].set_visible(False) + else: + cbar.set_ticks(cbar_ticks) + if currentData.metadata.has_key('gscat'): if currentData.metadata['gscat'] == 1: -# cbar.ax.text(0.5,-0.075,'Ground\nscat\nonly',ha='center') - cbar.ax.text(0.5,-0.115,'Ground\nscat\nonly',ha='center',fontsize=14) + cbar.ax.text(0.5,cbar_gstext_offset,'Ground\nscat\nonly',ha='center',fontsize=cbar_gstext_fontsize) + txt = 'Coordinates: ' + metadata['coords'] +', Model: ' + metadata['model'] axis.text(1.01, 0, txt, horizontalalignment='left', From 7de3ad8b41d79a87748f8dc913510a319e6cdaab Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 16:53:45 -0500 Subject: [PATCH 09/29] added plot_cbar keyword --- pydarn/plotting/musicPlot.py | 62 ++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 93a699ac..223874e4 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -101,6 +101,16 @@ class musicFan(object): * [**plotZeros**] (bool): If True, plot cells that are exactly 0. * [**markCell**] (None or 2-Element iterable): Mark the (beam, rangeGate) with black. * [**plotTerminator**] (bool): If True, overlay day/night terminator on map. Uses Basemap's nightshade. + * [**plot_title**] (bool): If True, plot the title information + * [**title**] (str): Overide default title text. + * [**cmap_handling**] (str): 'superdarn' to use SuperDARN-style colorbars, 'matplotlib' for direct use of matplotlib's colorbars. + 'matplotlib' is recommended when using custom scales and the 'superdarn' mode is not providing a desirable result. + * [**plot_cbar**] (bool): If True, plot the color bar. + * [**cbar_ticks**] (list): Where to put the ticks on the color bar. + * [**cbar_shrink**] (float): fraction by which to shrink the colorbar + * [**cbar_fraction**] (float): fraction of original axes to use for colorbar + * [**cbar_gstext_offset**] (float): y-offset from colorbar of "Ground Scatter Only" text + * [**cbar_gstext_fontsize**] (float): fontsize of "Ground Scatter Only" text * [**kwArgs**] (**kwArgs): Keyword Arguments Written by Nathaniel A. Frissell, Fall 2013 @@ -115,13 +125,14 @@ def __init__(self,dataObject, markCell = None, plotTerminator = True, plot_title = True, + title = None, cmap_handling = 'superdarn', + plot_cbar = True, cbar_ticks = None, cbar_shrink = 1.0, cbar_fraction = 0.15, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, - title = None, **kwArgs): if axis == None: @@ -262,17 +273,18 @@ def __init__(self,dataObject, else: axis.set_title(title) - cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) - cbar.set_label(cbarLabel) - if cbar_ticks is None: - labels = cbar.ax.get_yticklabels() - labels[-1].set_visible(False) - else: - cbar.set_ticks(cbar_ticks) + if plot_cbar: + cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) + cbar.set_label(cbarLabel) + if cbar_ticks is None: + labels = cbar.ax.get_yticklabels() + labels[-1].set_visible(False) + else: + cbar.set_ticks(cbar_ticks) - if currentData.metadata.has_key('gscat'): - if currentData.metadata['gscat'] == 1: - cbar.ax.text(0.5,cbar_gstext_offset,'Ground\nscat\nonly',ha='center',fontsize=cbar_gstext_fontsize) + if currentData.metadata.has_key('gscat'): + if currentData.metadata['gscat'] == 1: + cbar.ax.text(0.5,cbar_gstext_offset,'Ground\nscat\nonly',ha='center',fontsize=cbar_gstext_fontsize) txt = 'Coordinates: ' + metadata['coords'] +', Model: ' + metadata['model'] axis.text(1.01, 0, txt, @@ -310,10 +322,11 @@ class musicRTI(object): * [**axvlines**] (None or list of datetime.datetime): Dashed vertical lines will be drawn at each specified datetime.datetime. * [**axvline_color**] : Matplotlib color code specifying color of the axvlines. * [**secondary_coords**] (str): Secondary coordate system for RTI plot y-axis ('lat' or 'range') - * [**plot_info**] : If True, plot frequency/noise plots - * [**plot_title**] : If True, plot the title information + * [**plot_info**] (bool): If True, plot frequency/noise plots + * [**plot_title**] (bool): If True, plot the title information * [**cmap_handling**] (str): 'superdarn' to use SuperDARN-style colorbars, 'matplotlib' for direct use of matplotlib's colorbars. 'matplotlib' is recommended when using custom scales and the 'superdarn' mode is not providing a desirable result. + * [**plot_cbar**] (bool): If True, plot the color bar. * [**cbar_ticks**] (list): Where to put the ticks on the color bar. * [**cbar_shrink**] (float): fraction by which to shrink the colorbar * [**cbar_fraction**] (float): fraction of original axes to use for colorbar @@ -344,6 +357,7 @@ def __init__(self,dataObject, plot_info = True, plot_title = True, cmap_handling = 'superdarn', + plot_cbar = True, cbar_ticks = None, cbar_shrink = 1.0, cbar_fraction = 0.15, @@ -634,18 +648,18 @@ def __init__(self,dataObject, txt = '%.1f' % bnd_item axis.annotate(txt, (1.01, bnd_item) ,xycoords=('axes fraction','data'),rotation=90,ma='center') + if plot_cbar: + cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) + cbar.set_label(cbarLabel) + if cbar_ticks is None: + labels = cbar.ax.get_yticklabels() + labels[-1].set_visible(False) + else: + cbar.set_ticks(cbar_ticks) - cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) - cbar.set_label(cbarLabel) - if cbar_ticks is None: - labels = cbar.ax.get_yticklabels() - labels[-1].set_visible(False) - else: - cbar.set_ticks(cbar_ticks) - - if currentData.metadata.has_key('gscat'): - if currentData.metadata['gscat'] == 1: - cbar.ax.text(0.5,cbar_gstext_offset,'Ground\nscat\nonly',ha='center',fontsize=cbar_gstext_fontsize) + if currentData.metadata.has_key('gscat'): + if currentData.metadata['gscat'] == 1: + cbar.ax.text(0.5,cbar_gstext_offset,'Ground\nscat\nonly',ha='center',fontsize=cbar_gstext_fontsize) txt = 'Model: ' + metadata['model'] axis.text(1.01, 0, txt, From 729b685cf9d7ad26e3c40a7d444decba173e8f7e Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 17:03:38 -0500 Subject: [PATCH 10/29] removed gaps between patches in musicFan --- pydarn/plotting/musicPlot.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 223874e4..d0975333 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -133,6 +133,7 @@ def __init__(self,dataObject, cbar_fraction = 0.15, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, + basemap_dict = {}, **kwArgs): if axis == None: @@ -212,7 +213,7 @@ def __init__(self,dataObject, dist = width/50. #draw the actual map we want - m = Basemap(projection='stere',width=width,height=height,lon_0=np.mean(goodLonFull),lat_0=lat_0,ax=axis) + m = Basemap(projection='stere',width=width,height=height,lon_0=np.mean(goodLonFull),lat_0=lat_0,ax=axis,**basemap_dict) m.drawparallels(np.arange(-80.,81.,10.),labels=[1,0,0,0]) m.drawmeridians(np.arange(-180.,181.,20.),labels=[0,0,0,1]) if(coords == 'geo'): @@ -247,7 +248,8 @@ def __init__(self,dataObject, colors = 'lasse' cmap,norm,bounds = utils.plotUtils.genCmap(param,scale,colors=colors) - pcoll = PolyCollection(np.array(verts),edgecolors='face',linewidths=0,closed=False,cmap=cmap,norm=norm,zorder=99) +# pcoll = PolyCollection(np.array(verts),edgecolors='face',linewidths=0,closed=False,cmap=cmap,norm=norm,zorder=99) + pcoll = PolyCollection(np.array(verts),edgecolors='face',closed=False,cmap=cmap,norm=norm,zorder=99) pcoll.set_array(np.array(scan)) axis.add_collection(pcoll,autolim=False) From d0b9a6146877970e79073449ddddebb1cd9aa8bc Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 21:34:59 -0500 Subject: [PATCH 11/29] musicFan maps now fill entire axis area --- pydarn/plotting/musicPlot.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index d0975333..66a097f5 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -212,6 +212,19 @@ def __init__(self,dataObject, lon_0,lat_0 = tmpmap(cx, cy, inverse=True) dist = width/50. + + #Fill the entire subplot area without changing the data aspect ratio. + bbox = axis.get_window_extent() + bbox_width = bbox.width + bbox_height = bbox.height + ax_aspect = bbox_width / bbox_height + map_aspect = width / height + if map_aspect < ax_aspect: + width = (height*bbox_width) / bbox_height + + if map_aspect > ax_aspect: + height = (width*bbox_height) / bbox_width + #draw the actual map we want m = Basemap(projection='stere',width=width,height=height,lon_0=np.mean(goodLonFull),lat_0=lat_0,ax=axis,**basemap_dict) m.drawparallels(np.arange(-80.,81.,10.),labels=[1,0,0,0]) From f78c4d37af385b3b3af03a85cbeab6bf5a4e3540 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 23:11:52 -0500 Subject: [PATCH 12/29] added parallels/meridians ticks keyword to musicFan --- pydarn/plotting/musicPlot.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 66a097f5..6a0812ed 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -103,6 +103,8 @@ class musicFan(object): * [**plotTerminator**] (bool): If True, overlay day/night terminator on map. Uses Basemap's nightshade. * [**plot_title**] (bool): If True, plot the title information * [**title**] (str): Overide default title text. + * [**parallels_ticks**] (list): Where to draw the parallel (latitude) lines + * [**meridians_ticks**] (list): Where to draw the meridian (longitude) lines * [**cmap_handling**] (str): 'superdarn' to use SuperDARN-style colorbars, 'matplotlib' for direct use of matplotlib's colorbars. 'matplotlib' is recommended when using custom scales and the 'superdarn' mode is not providing a desirable result. * [**plot_cbar**] (bool): If True, plot the color bar. @@ -126,6 +128,9 @@ def __init__(self,dataObject, plotTerminator = True, plot_title = True, title = None, + parallels_ticks = None, + meridians_ticks = None, + zoom = 1., cmap_handling = 'superdarn', plot_cbar = True, cbar_ticks = None, @@ -225,10 +230,21 @@ def __init__(self,dataObject, if map_aspect > ax_aspect: height = (width*bbox_height) / bbox_width + #Zoom! + width = zoom * width + height = zoom * height + #draw the actual map we want m = Basemap(projection='stere',width=width,height=height,lon_0=np.mean(goodLonFull),lat_0=lat_0,ax=axis,**basemap_dict) - m.drawparallels(np.arange(-80.,81.,10.),labels=[1,0,0,0]) - m.drawmeridians(np.arange(-180.,181.,20.),labels=[0,0,0,1]) + if parallels_ticks is None: + parallels_ticks = np.arange(-80.,81.,10.) + + if meridians_ticks is None: + meridians_ticks = np.arange(-180.,181.,20.) + + m.drawparallels(parallels_ticks,labels=[1,0,0,0]) + m.drawmeridians(meridians_ticks,labels=[0,0,0,1]) + if(coords == 'geo'): m.drawcoastlines(linewidth=0.5,color='k') m.drawmapboundary(fill_color='w') @@ -312,6 +328,8 @@ def __init__(self,dataObject, if plotTerminator: m.nightshade(currentData.time[timeInx]) + self.map_obj = m + class musicRTI(object): """Class to create an RTI plot using a pydarn.proc.music.musicArray object as the data source. From 06e2d9a0bfbbbd99ab75ae1900b8e96bed98cd8a Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 23:20:26 -0500 Subject: [PATCH 13/29] model_text_size keyword added --- pydarn/plotting/musicPlot.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 6a0812ed..008ce071 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -113,6 +113,8 @@ class musicFan(object): * [**cbar_fraction**] (float): fraction of original axes to use for colorbar * [**cbar_gstext_offset**] (float): y-offset from colorbar of "Ground Scatter Only" text * [**cbar_gstext_fontsize**] (float): fontsize of "Ground Scatter Only" text + * [**model_text_size**] : fontsize of model and coordinate indicator text + * [**basemap_dict**] (dict): dictionary of keywords sent to the basemap invocation * [**kwArgs**] (**kwArgs): Keyword Arguments Written by Nathaniel A. Frissell, Fall 2013 @@ -138,6 +140,7 @@ def __init__(self,dataObject, cbar_fraction = 0.15, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, + model_text_size = 'small', basemap_dict = {}, **kwArgs): @@ -322,7 +325,7 @@ def __init__(self,dataObject, horizontalalignment='left', verticalalignment='bottom', rotation='vertical', - size='small', + size=model_text_size, transform=axis.transAxes) if plotTerminator: @@ -365,6 +368,7 @@ class musicRTI(object): * [**cbar_fraction**] (float): fraction of original axes to use for colorbar * [**cbar_gstext_offset**] (float): y-offset from colorbar of "Ground Scatter Only" text * [**cbar_gstext_fontsize**] (float): fontsize of "Ground Scatter Only" text + * [**model_text_size**] : fontsize of model and coordinate indicator text * [**kwArgs**] (**kwArgs): Keyword Arguments Written by Nathaniel A. Frissell, Fall 2013 @@ -396,6 +400,7 @@ def __init__(self,dataObject, cbar_fraction = 0.15, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, + model_text_size = 'small', **kwArgs): from scipy import stats @@ -699,7 +704,7 @@ def __init__(self,dataObject, horizontalalignment='left', verticalalignment='bottom', rotation='vertical', - size='small', + size=model_text_size, transform=axis.transAxes) #Get axis position information. From b61f98c225e038b7a49e8db512ee933a67c84dac Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 26 Jan 2014 23:44:08 -0500 Subject: [PATCH 14/29] added zoom, lat_shift, lon_shift --- pydarn/plotting/musicPlot.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 008ce071..66b871d5 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -105,6 +105,9 @@ class musicFan(object): * [**title**] (str): Overide default title text. * [**parallels_ticks**] (list): Where to draw the parallel (latitude) lines * [**meridians_ticks**] (list): Where to draw the meridian (longitude) lines + * [**zoom**] (float): Multiply the map height and width by this factor (bigger number shows more area). + * [**lat_shift**] (float): Add this number to the computed lat_0 sent to basemap. + * [**lon_shift**] (float): Add this number to the computed lon_0 sent to basemap. * [**cmap_handling**] (str): 'superdarn' to use SuperDARN-style colorbars, 'matplotlib' for direct use of matplotlib's colorbars. 'matplotlib' is recommended when using custom scales and the 'superdarn' mode is not providing a desirable result. * [**plot_cbar**] (bool): If True, plot the color bar. @@ -114,6 +117,7 @@ class musicFan(object): * [**cbar_gstext_offset**] (float): y-offset from colorbar of "Ground Scatter Only" text * [**cbar_gstext_fontsize**] (float): fontsize of "Ground Scatter Only" text * [**model_text_size**] : fontsize of model and coordinate indicator text + * [**draw_coastlines**] (bool): If True, draw the coastlines. * [**basemap_dict**] (dict): dictionary of keywords sent to the basemap invocation * [**kwArgs**] (**kwArgs): Keyword Arguments @@ -133,6 +137,8 @@ def __init__(self,dataObject, parallels_ticks = None, meridians_ticks = None, zoom = 1., + lat_shift = 0., + lon_shift = 0., cmap_handling = 'superdarn', plot_cbar = True, cbar_ticks = None, @@ -141,6 +147,7 @@ def __init__(self,dataObject, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, model_text_size = 'small', + draw_coastlines = True, basemap_dict = {}, **kwArgs): @@ -218,6 +225,7 @@ def __init__(self,dataObject, cx = minx + width/2. cy = miny + height/2. lon_0,lat_0 = tmpmap(cx, cy, inverse=True) + lon_0 = np.mean(goodLonFull) dist = width/50. @@ -236,9 +244,11 @@ def __init__(self,dataObject, #Zoom! width = zoom * width height = zoom * height + lat_0 = lat_0 + lat_shift + lon_0 = lon_0 + lon_shift #draw the actual map we want - m = Basemap(projection='stere',width=width,height=height,lon_0=np.mean(goodLonFull),lat_0=lat_0,ax=axis,**basemap_dict) + m = Basemap(projection='stere',width=width,height=height,lon_0=lon_0,lat_0=lat_0,ax=axis,**basemap_dict) if parallels_ticks is None: parallels_ticks = np.arange(-80.,81.,10.) @@ -248,7 +258,7 @@ def __init__(self,dataObject, m.drawparallels(parallels_ticks,labels=[1,0,0,0]) m.drawmeridians(meridians_ticks,labels=[0,0,0,1]) - if(coords == 'geo'): + if(coords == 'geo') and draw_coastlines == True: m.drawcoastlines(linewidth=0.5,color='k') m.drawmapboundary(fill_color='w') m.fillcontinents(color='w', lake_color='w') From 1d4e59e89da804dfa287caee98a82c85c2c48b6d Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Mon, 27 Jan 2014 00:01:09 -0500 Subject: [PATCH 15/29] added ylabelpad --- pydarn/plotting/musicPlot.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 66b871d5..f5a14a2a 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -132,8 +132,6 @@ def __init__(self,dataObject, plotZeros = False, markCell = None, plotTerminator = True, - plot_title = True, - title = None, parallels_ticks = None, meridians_ticks = None, zoom = 1., @@ -149,6 +147,8 @@ def __init__(self,dataObject, model_text_size = 'small', draw_coastlines = True, basemap_dict = {}, + plot_title = True, + title = None, **kwArgs): if axis == None: @@ -411,6 +411,7 @@ def __init__(self,dataObject, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, model_text_size = 'small', + y_labelpad = None, **kwArgs): from scipy import stats @@ -573,15 +574,15 @@ def __init__(self,dataObject, if secondary_coords: if secondary_coords == 'range': if metadata['model'] == 'IS': - axis.set_ylabel('Range Gate\nSlant Range [km]') + axis.set_ylabel('Range Gate\nSlant Range [km]',labelpad=y_labelpad) elif metadata['model'] == 'GS': - axis.set_ylabel('Range Gate\nGS Mapped Range [km]') + axis.set_ylabel('Range Gate\nGS Mapped Range [km]',labelpad=y_labelpad) else: geo_mag = 'Geographic' if currentData.fov.coords == 'geo' else 'Magnetic' if metadata['model'] == 'IS': - axis.set_ylabel('Range Gate\n%s Latitude' % geo_mag) + axis.set_ylabel('Range Gate\n%s Latitude' % geo_mag,labelpad=y_labelpad) elif metadata['model'] == 'GS': - axis.set_ylabel('Range Gate\nGS Mapped %s Latitude' % geo_mag) + axis.set_ylabel('Range Gate\nGS Mapped %s Latitude' % geo_mag,labelpad=y_labelpad) yticks = axis.get_yticks() ytick_str = [] @@ -607,7 +608,7 @@ def __init__(self,dataObject, ytick_str.append(txt) axis.set_yticklabels(ytick_str,rotation=90,ma='center') else: - axis.set_ylabel('Range Gate') + axis.set_ylabel('Range Gate',labelpad=y_labelpad) elif coords == 'range': if secondary_coords == 'lat': # Use linear interpolation to get the latitude associated with a particular range. @@ -638,14 +639,14 @@ def __init__(self,dataObject, # Label y-axis geo_mag = 'Geographic' if currentData.fov.coords == 'geo' else 'Magnetic' if metadata['model'] == 'IS': - axis.set_ylabel('%s Latitude\nSlant Range [km]' % geo_mag) + axis.set_ylabel('%s Latitude\nSlant Range [km]' % geo_mag,labelpad=y_labelpad) elif metadata['model'] == 'GS': - axis.set_ylabel('GS Mapped %s Latitude\nGS Mapped Range [km]' % geo_mag) + axis.set_ylabel('GS Mapped %s Latitude\nGS Mapped Range [km]' % geo_mag,labelpad=y_labelpad) else: if metadata['model'] == 'IS': - axis.set_ylabel('Slant Range [km]') + axis.set_ylabel('Slant Range [km]',labelpad=y_labelpad) elif metadata['model'] == 'GS': - axis.set_ylabel('GS Mapped Range [km]') + axis.set_ylabel('GS Mapped Range [km]',labelpad=y_labelpad) axis.set_ylim(ylim) #Shade xBoundary Limits From c0272b08a3fe7a49698c88a43d762e3aec8c5aab Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Mon, 27 Jan 2014 00:31:00 -0500 Subject: [PATCH 16/29] added markBeam to musicFan --- pydarn/plotting/musicPlot.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index f5a14a2a..70db4d2a 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -100,6 +100,8 @@ class musicFan(object): * [**autoScale**] (bool): If True, automatically scale the color bar for good data visualization. Keyword scale must be None when using autoScale. * [**plotZeros**] (bool): If True, plot cells that are exactly 0. * [**markCell**] (None or 2-Element iterable): Mark the (beam, rangeGate) with black. + * [**markBeam**] (None or int): Mark a chosen beam. + * [**markBeam_dict**] (dict): dictionary of keywords defining markBeam line properties. * [**plotTerminator**] (bool): If True, overlay day/night terminator on map. Uses Basemap's nightshade. * [**plot_title**] (bool): If True, plot the title information * [**title**] (str): Overide default title text. @@ -131,6 +133,8 @@ def __init__(self,dataObject, autoScale = False, plotZeros = False, markCell = None, + markBeam = None, + markBeam_dict = {'color':'white','lw':2}, plotTerminator = True, parallels_ticks = None, meridians_ticks = None, @@ -310,6 +314,25 @@ def __init__(self,dataObject, poly = Polygon(mkv,facecolor='#000000',edgecolor='none',zorder=100) axis.add_patch(poly) + #Mark Beam + if markBeam != None: + beamInx = int(np.where(currentData.fov.beams == markBeam)[0]) + startedMarking = False + for gateInx in range(ngates): + if goodLatLon[beamInx,gateInx] == False: continue + x1,y1 = m(lonFull[beamInx+0,gateInx+0],latFull[beamInx+0,gateInx+0]) + x2,y2 = m(lonFull[beamInx+1,gateInx+0],latFull[beamInx+1,gateInx+0]) + x3,y3 = m(lonFull[beamInx+1,gateInx+1],latFull[beamInx+1,gateInx+1]) + x4,y4 = m(lonFull[beamInx+0,gateInx+1],latFull[beamInx+0,gateInx+1]) + axis.plot([x1,x4],[y1,y4],zorder=150,**markBeam_dict) + axis.plot([x2,x3],[y2,y3],zorder=150,**markBeam_dict) + if not startedMarking: + axis.plot([x1,x2],[y1,y2],zorder=150,**markBeam_dict) + startedMarking = True + if gateInx == ngates-1: + axis.plot([x3,x4],[y3,y4],zorder=150,**markBeam_dict) + + dataName = currentData.history[max(currentData.history.keys())] #Label the plot with the current level of data processing. if plot_title: if title is None: From fc554b8ae965193ddc0b2aad1877e0d1c35a34cd Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Tue, 28 Jan 2014 16:12:46 -0500 Subject: [PATCH 17/29] added axis keyword to plotKarr --- pydarn/plotting/musicPlot.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 70db4d2a..af196bd4 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -1277,6 +1277,7 @@ def plotFullSpectrum(dataObj,dataSet='active',fig=None,axis=None,xlim=None, cbar * **dataObj** (:class:`pydarn.proc.music.musicArray`): musicArray object * [**dataSet**] (str): which dataSet in the musicArray object to plot * [**fig**] (matplotlib.figure): matplotlib figure object that will be plotted to. If not provided, one will be created. + * [**axis**] : Matplotlib axis object to plot on. * [**xlim**] (None or 2-element iterable): X-axis limits in Hz * [**plot_title**] : If True, plot the title information * [**cbar_label**] (str): Text for color bar label @@ -1615,7 +1616,7 @@ def plotDlm(dataObj,dataSet='active',fig=None): fig.text(xpos,0.95,text,fontsize=14,va='top') -def plotKarr(dataObj,dataSet='active',fig=None,maxSignals=None, sig_fontsize=24, +def plotKarr(dataObj,dataSet='active',fig=None,axis=None,maxSignals=None, sig_fontsize=24, plot_title=True, cbar_ticks=None, cbar_shrink=1.0, cbar_fraction=0.15, cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None, **kwArgs): """Plot the horizontal wave number array for a pydarn.proc.music.musicArray object. The kArr must have aready @@ -1628,6 +1629,7 @@ def plotKarr(dataObj,dataSet='active',fig=None,maxSignals=None, sig_fontsize=24, * **dataObj** (:class:`musicArray`): musicArray object * [**dataSet**] (str): which dataSet in the musicArray object to plot * [**fig**] (None or matplotlib.figure): matplotlib figure object that will be plotted to. If not provided, one will be created. + * [**axis**] : Matplotlib axis object to plot on. * [**maxSignals**] (None or int): Maximum number of signals to plot if detected signals exist for the chosen data set. * [**sig_fontsize**] (float): fontsize of signal markers * [**plot_title**] : If True, plot the title information @@ -1639,14 +1641,18 @@ def plotKarr(dataObj,dataSet='active',fig=None,maxSignals=None, sig_fontsize=24, Written by Nathaniel A. Frissell, Fall 2013 """ - if fig == None: + if fig is None and axis is None: from matplotlib import pyplot as plt fig = plt.figure(figsize=figsize) currentData = getDataSet(dataObj,dataSet) #Do plotting here! - axis = fig.add_subplot(111,aspect='equal') + if axis is None: + axis = fig.add_subplot(111,aspect='equal') + else: + fig = axis.get_figure() + plotKarrAxis(dataObj,dataSet=dataSet,axis=axis,maxSignals=maxSignals, cbar_ticks=cbar_ticks, cbar_shrink=cbar_shrink, cbar_fraction=cbar_fraction,sig_fontsize=sig_fontsize, cbar_gstext_offset=cbar_gstext_offset, cbar_gstext_fontsize=cbar_gstext_fontsize) From a84800a28356f16766957b7b5c3c9f10b9ef1cf7 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Fri, 31 Jan 2014 10:57:35 -0500 Subject: [PATCH 18/29] added scale, normalize kw to plotFullSpectrum --- pydarn/plotting/musicPlot.py | 45 +++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index af196bd4..d30ba2bc 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -1263,9 +1263,21 @@ def multiPlot(xData1,yData1,beams,gates,yData1_title=None,plotBeam=None,plotGate return fig -def plotFullSpectrum(dataObj,dataSet='active',fig=None,axis=None,xlim=None, cbar_label = 'ABS(Spectral Density)', - plot_title=True, cbar_ticks=None, cbar_shrink=1.0, cbar_fraction=0.15, - cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None, cbar_gstext_enable=True, **kwArgs): +def plotFullSpectrum(dataObj,dataSet='active', + fig = None, + axis = None, + xlim = None, + normalize = False, + scale = None, + cbar_label = 'ABS(Spectral Density)', + plot_title = True, + cbar_ticks = None, + cbar_shrink = 1.0, + cbar_fraction = 0.15, + cbar_gstext_offset = -0.075, + cbar_gstext_fontsize = None, + cbar_gstext_enable = True, + **kwArgs): """Plot full spectrum of a pydarn.proc.music.musicArray object. The spectrum must have already been calculated with pydarn.proc.music.calculateFFT(). @@ -1307,11 +1319,15 @@ def plotFullSpectrum(dataObj,dataSet='active',fig=None,axis=None,xlim=None, cbar data = np.abs(currentData.spectrum[posFreqInx,:,:]) #Use the magnitude of the positive frequency data. + if normalize: + data = data / data.max() + #Determine scale for colorbar. sd = stats.nanstd(data,axis=None) mean = stats.nanmean(data,axis=None) scMax = mean + 2.*sd - scale = scMax*np.array([0,1.]) + if scale is None: + scale = scMax*np.array([0,1.]) nXBins = nrBeams * npf #number of bins we are going to plot @@ -1349,15 +1365,11 @@ def plotFullSpectrum(dataObj,dataSet='active',fig=None,axis=None,xlim=None, cbar x4,y4 = xx0, yy1 verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) - colors = 'lasse' - if scale == None: - scale = (np.min(scan),np.max(scan)) param = 'power' cmap = matplotlib.cm.Blues_r bounds = np.linspace(scale[0],scale[1],256) norm = matplotlib.colors.BoundaryNorm(bounds,cmap.N) - pcoll = PolyCollection(np.array(verts),edgecolors='face',linewidths=0,closed=False,cmap=cmap,norm=norm,zorder=99) pcoll.set_array(np.array(scan)) axis.add_collection(pcoll,autolim=False) @@ -1655,7 +1667,7 @@ def plotKarr(dataObj,dataSet='active',fig=None,axis=None,maxSignals=None, sig_fo plotKarrAxis(dataObj,dataSet=dataSet,axis=axis,maxSignals=maxSignals, cbar_ticks=cbar_ticks, cbar_shrink=cbar_shrink, cbar_fraction=cbar_fraction,sig_fontsize=sig_fontsize, - cbar_gstext_offset=cbar_gstext_offset, cbar_gstext_fontsize=cbar_gstext_fontsize) + cbar_gstext_offset=cbar_gstext_offset, cbar_gstext_fontsize=cbar_gstext_fontsize,**kwArgs) if plot_title: xpos = 0.130 @@ -1842,9 +1854,9 @@ def plotKarrDetected(dataObj,dataSet='active',fig=None,maxSignals=None,roiPlot=T txt = '%i' % signal['order'] axis.text(xpos,ypos,txt,color='k',zorder=200-signal['order'],size=24,path_effects=pe) -def plotKarrAxis(dataObj,dataSet='active',axis=None,maxSignals=None, sig_fontsize=24, +def plotKarrAxis(dataObj,dataSet='active',axis=None,maxSignals=None, sig_fontsize=24,x_labelpad=None,y_labelpad=None, cbar_ticks=None, cbar_shrink=1.0, cbar_fraction=0.15, - cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None): + cbar_gstext_offset=-0.075, cbar_gstext_fontsize=None,cbar_pad=0.05): """Plot the horizontal wave number array for a pydarn.proc.music.musicArray object. The kArr must have aready been calculated for the chosen data set using pydarn.proc.music.calculateKarr(). @@ -1916,7 +1928,7 @@ def plotKarrAxis(dataObj,dataSet='active',axis=None,maxSignals=None, sig_fontsiz axis.axhline(color='0.82',lw=2,zorder=150) #Colorbar - cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) + cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction,pad=cbar_pad) cbar.set_label('Normalized Wavenumber Power') if not cbar_ticks: cbar_ticks = np.arange(10)/10. @@ -1952,7 +1964,8 @@ def plotKarrAxis(dataObj,dataSet='active',axis=None,maxSignals=None, sig_fontsiz newLabels.append(txt) axis.set_xticklabels(newLabels) - axis.set_xlabel(u'kx [rad]\n$\lambda$ [km]',ha='center') + axis.set_xlabel(u'kx [rad]\n$\lambda$ [km]',ha='center',labelpad=x_labelpad) +# axis.set_xlabel('%f' % x_labelpad,ha='center',labelpad=x_labelpad) ticks = axis.get_yticks() newLabels = [] @@ -1965,10 +1978,10 @@ def plotKarrAxis(dataObj,dataSet='active',axis=None,maxSignals=None, sig_fontsiz km_txt = '' rad_txt = '%.2f' % tck - txt = '\n'.join([rad_txt,km_txt]) + txt = '\n'.join([km_txt,rad_txt]) newLabels.append(txt) - axis.set_yticklabels(newLabels) - axis.set_ylabel(u'ky [rad]\n$\lambda$ [km]',va='center') + axis.set_yticklabels(newLabels,rotation=90.) + axis.set_ylabel(u'ky [rad]\n$\lambda$ [km]',va='center',labelpad=y_labelpad) # End add wavelength to x/y tick labels ######################################## md = currentData.metadata From 25605b068286cc0e06f02ddce279705dc608a7aa Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Fri, 31 Jan 2014 11:20:56 -0500 Subject: [PATCH 19/29] added cbar_pad kw to plotFullSpectrum --- pydarn/plotting/musicPlot.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index d30ba2bc..e6593d3e 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -1274,6 +1274,7 @@ def plotFullSpectrum(dataObj,dataSet='active', cbar_ticks = None, cbar_shrink = 1.0, cbar_fraction = 0.15, + cbar_pad = 0.05, cbar_gstext_offset = -0.075, cbar_gstext_fontsize = None, cbar_gstext_enable = True, @@ -1375,9 +1376,9 @@ def plotFullSpectrum(dataObj,dataSet='active', axis.add_collection(pcoll,autolim=False) #Colorbar - cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction) + cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction,pad=cbar_pad) cbar.set_label(cbar_label) - if not cbar_ticks: + if cbar_ticks is None: labels = cbar.ax.get_yticklabels() labels[-1].set_visible(False) else: From 2913f6e34647938214c30fea69ea23f4eae2919d Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Fri, 21 Feb 2014 16:31:41 -0500 Subject: [PATCH 20/29] put terminator plotting back --- pydarn/plotting/musicPlot.py | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index e6593d3e..23c5a47d 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -553,25 +553,25 @@ def __init__(self,dataObject, # Plot the terminator! ######################################################### if plotTerminator: - print 'Terminator functionality is disabled until further testing is completed.' -# term_verts = [] -# term_scan = [] -# -# rnge = currentData.fov.gates -# xvec = [matplotlib.dates.date2num(x) for x in currentData.time] -# for tm in range(nrTimes-1): -# for rg in range(nrGates-1): -# if daylight[tm,rg]: continue -# term_scan.append(1) -# -# x1,y1 = xvec[tm+0],rnge[rg+0] -# x2,y2 = xvec[tm+1],rnge[rg+0] -# x3,y3 = xvec[tm+1],rnge[rg+1] -# x4,y4 = xvec[tm+0],rnge[rg+1] -# term_verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) -# -# term_pcoll = PolyCollection(np.array(term_verts),facecolors='0.45',linewidth=0,zorder=99,alpha=0.25) -# axis.add_collection(term_pcoll,autolim=False) +# print 'Terminator functionality is disabled until further testing is completed.' + term_verts = [] + term_scan = [] + + rnge = currentData.fov.gates + xvec = [matplotlib.dates.date2num(x) for x in currentData.time] + for tm in range(nrTimes-1): + for rg in range(nrGates-1): + if daylight[tm,rg]: continue + term_scan.append(1) + + x1,y1 = xvec[tm+0],rnge[rg+0] + x2,y2 = xvec[tm+1],rnge[rg+0] + x3,y3 = xvec[tm+1],rnge[rg+1] + x4,y4 = xvec[tm+0],rnge[rg+1] + term_verts.append(((x1,y1),(x2,y2),(x3,y3),(x4,y4),(x1,y1))) + + term_pcoll = PolyCollection(np.array(term_verts),facecolors='0.45',linewidth=0,zorder=99,alpha=0.25) + axis.add_collection(term_pcoll,autolim=False) ################################################################################ if axvlines is not None: @@ -1269,8 +1269,9 @@ def plotFullSpectrum(dataObj,dataSet='active', xlim = None, normalize = False, scale = None, - cbar_label = 'ABS(Spectral Density)', plot_title = True, + maxXTicks = 10., + cbar_label = 'ABS(Spectral Density)', cbar_ticks = None, cbar_shrink = 1.0, cbar_fraction = 0.15, @@ -1293,6 +1294,7 @@ def plotFullSpectrum(dataObj,dataSet='active', * [**axis**] : Matplotlib axis object to plot on. * [**xlim**] (None or 2-element iterable): X-axis limits in Hz * [**plot_title**] : If True, plot the title information + * [**maxXTicks**] (int): Maximum number of xtick labels. * [**cbar_label**] (str): Text for color bar label * [**cbar_ticks**] (list): Where to put the ticks on the color bar. * [**cbar_shrink**] (float): fraction by which to shrink the colorbar @@ -1427,9 +1429,7 @@ def plotFullSpectrum(dataObj,dataSet='active', axis.add_patch(poly) #X-Labels - maxXTicks = 10. - modX = np.ceil(npf / maxXTicks) - fCharSize= 0.60 + modX = np.ceil(npf / np.float(maxXTicks)) xlabels = [] xpos = [] @@ -1439,7 +1439,7 @@ def plotFullSpectrum(dataObj,dataSet='active', if posFreqVec[ff] == 0: periodLabel = 'Inf' else: - periodLabel = '%i' % (1./posFreqVec[ff] / 60.) + periodLabel = '%.0f' % (1./posFreqVec[ff] / 60.) xlabels.append(freqLabel+'\n'+periodLabel) xpos.append(nrBeams* (ff + 0.1)) From be6dec4d7ac8f24a60481fe29cb7b01d5e10aedd Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sat, 22 Feb 2014 15:29:18 -0500 Subject: [PATCH 21/29] fixed problem where velocity goes to inf --- pydarn/proc/music/music.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 40790623..7c822adf 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -152,7 +152,10 @@ def stringify_signal(sig): if sig.has_key('period'): sigInfo['period'] = '%d' % np.round(sig['period']/60.) # minutes if sig.has_key('vel'): - sigInfo['vel'] = '%d' % np.round(sig['vel']) # km/s + if np.isinf(np.round(sig['vel'])): + sigInfo['vel'] = 'Inf' + else: + sigInfo['vel'] = '%d' % np.round(sig['vel']) # km/s if sig.has_key('area'): sigInfo['area'] = '%d' % sig['area'] # Pixels if sig.has_key('max'): From c3e58c331d4806733c2b12b4aec0ddbb9af2b5b2 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Fri, 7 Mar 2014 08:29:03 -0500 Subject: [PATCH 22/29] change plotting.rti to proc.music --- pydarn/proc/music/music.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 7c822adf..52060dba 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -33,7 +33,7 @@ .. moduleauthor:: Nathaniel A. Frissell, Fall 2013 ********************* -**Module**: pydarn.plotting.rti +**Module**: pydarn.proc.muic ********************* **Functions**: * :func:`pydarn.proc.music.getDataSet` From b353c72e8d63ef2d9f93bd853ed9e5516499d6e0 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Tue, 25 Mar 2014 17:39:47 -0400 Subject: [PATCH 23/29] added checkDataQuality() --- pydarn/proc/music/music.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 52060dba..6d54b1d7 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -747,6 +747,36 @@ def defineLimits(dataObj,dataSet='active',rangeLimits=None,gateLimits=None,beamL except: print "Warning! An error occured while defining limits. No limits set. Check your input values." +def checkDataQuality(dataObj,dataSet='active',max_off_time=10,sTime=None,eTime=None): + """Mark the data set as bad (metadata['good_period'] = False) if the radar was not operational within the chosen time period + for a specified length of time. + + **Args**: + * **dataObj** (:class:`musicArray`): musicArray object + * [**dataSet**] (str): which dataSet in the musicArray object to process + * [**max_off_time**] (int/float): Maximum length in minutes radar may remain off. + * [**sTime**] (datetime.datetime): Starting time of checking period. If None, min(currentData.time) is used. + * [**eTime**] (datetime.datetime): End time of checking period. If None, max(currentData.time) is used. + + Written by Nathaniel A. Frissell, Fall 2013 + """ + currentData = getDataSet(dataObj,dataSet) + + if sTime is None: + sTime = np.min(currentData.time) + + if eTime is None: + eTime = np.max(currentData.time) + + time_vec = currentData.time[np.logical_and(currentData.time > sTime, currentData.time < eTime)] + time_vec = np.concatenate(([sTime],time_vec,[eTime])) + max_diff = np.max(np.diff(time_vec)) + + if max_diff > datetime.timedelta(minutes=max_off_time): + currentData.setMetadata(good_period=False) + + return dataObj + def applyLimits(dataObj,dataSet='active',rangeLimits=None,gateLimits=None,timeLimits=None,newDataSetName='limitsApplied',comment=None): """Removes data outside of the rangeLimits and gateLimits boundaries. From e3b185765fd8ae094555d98b4728bbf025e0662c Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Tue, 25 Mar 2014 17:40:12 -0400 Subject: [PATCH 24/29] removed annoying warning --- pydarn/proc/music/music.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 6d54b1d7..cff3f8d4 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -886,7 +886,7 @@ def applyLimits(dataObj,dataSet='active',rangeLimits=None,gateLimits=None,timeLi return newData except: if hasattr(dataObj,newDataSetName): delattr(dataObj,newDataSetName) - print 'Warning! Limits not applied.' +# print 'Warning! Limits not applied.' return currentData def determineRelativePosition(dataObj,dataSet='active',altitude=250.): From f7b192d11f747b9b4f2c06086e4db91a4b3bff1e Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Wed, 26 Mar 2014 11:27:16 -0400 Subject: [PATCH 25/29] added good_period True flag --- pydarn/proc/music/music.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index cff3f8d4..39ba7919 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -774,6 +774,8 @@ def checkDataQuality(dataObj,dataSet='active',max_off_time=10,sTime=None,eTime=N if max_diff > datetime.timedelta(minutes=max_off_time): currentData.setMetadata(good_period=False) + else: + currentData.setMetadata(good_period=True) return dataObj From b8bfc979ebbe543116481c9180ee1efea9d7f38d Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sat, 3 May 2014 14:17:55 -0400 Subject: [PATCH 26/29] added messages support and No Data notification --- pydarn/proc/music/music.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 39ba7919..4b53fb1a 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -482,6 +482,9 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N scanNr = np.uint64(0) fov = None + # Create a list that can be used to store top-level messages. + self.messages = [] + # Create a place to store the prm data. prm = emptyObj() prm.time = [] @@ -579,6 +582,11 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N timeArray = np.array(scanTimeList) dataListArray = np.array(dataList) + # If no data, report and return. + if dataListArray.size == 0: + self.messages.append('No data for this time period.') + return + #Figure out what size arrays we need and initialize the arrays... nrTimes = np.max(dataListArray[:,scanInx]) + 1 nrBeams = np.max(dataListArray[:,beamInx]) + 1 From 5c0571a613a8ec37a6f4342a634798f6f957a767 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 4 May 2014 11:28:33 -0400 Subject: [PATCH 27/29] added another no data handling case --- pydarn/proc/music/music.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 4b53fb1a..10ff4176 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -465,6 +465,15 @@ class musicArray(object): Written by Nathaniel A. Frissell, Fall 2013 """ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=None,fovModel='GS',fovCoords='geo'): + # Create a list that can be used to store top-level messages. + self.messages = [] + + no_data_message = 'No data for this time period.' + # If no data, report and return. + if myPtr is None: + self.messages.append(no_data_message) + return + if sTime == None: sTime = myPtr.sTime if eTime == None: eTime = myPtr.eTime @@ -482,8 +491,6 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N scanNr = np.uint64(0) fov = None - # Create a list that can be used to store top-level messages. - self.messages = [] # Create a place to store the prm data. prm = emptyObj() @@ -584,7 +591,7 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N # If no data, report and return. if dataListArray.size == 0: - self.messages.append('No data for this time period.') + self.messages.append(no_data_message) return #Figure out what size arrays we need and initialize the arrays... @@ -616,7 +623,7 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N dataArray[:] = np.nan for inx in range(len(dataListArray)): dataArray[dataListArray[inx,scanInx],dataListArray[inx,beamInx],dataListArray[inx,gateInx]] = dataListArray[inx,dataInx] - + #Make metadata block to hold information about the processing. metadata = {} metadata['dType'] = myPtr.dType From b59e8bb5b43534a023c91637a6b2219673db8226 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Sun, 4 May 2014 12:28:45 -0400 Subject: [PATCH 28/29] fixed bug where timevector could become longer than datavector --- pydarn/proc/music/music.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pydarn/proc/music/music.py b/pydarn/proc/music/music.py index 10ff4176..0723546c 100644 --- a/pydarn/proc/music/music.py +++ b/pydarn/proc/music/music.py @@ -522,6 +522,7 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N myScan = pydarn.sdio.radDataRead.radDataReadScan(myPtr) if myScan == None: break + goodScan = False # This flag turns to True as soon as good data is found for the scan. for myBeam in myScan: #Calculate the field of view if it has not yet been calculated. if fov == None: @@ -569,6 +570,7 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N if (gscat == 2) and (flag == 1): continue tmp = (scanNr,beamTime,bmnum,gate,data) dataList.append(tmp) + goodScan = True elif len(slist) == 1: gate,data,flag = (slist[0],fitDataList[0],gflag[0]) #Get information from each gate in scan. Skip record if the chosen ground scatter option is not met. @@ -576,14 +578,16 @@ def __init__(self,myPtr,sTime=None,eTime=None,param='p_l',gscat=1,fovElevation=N if (gscat == 2) and (flag == 1): continue tmp = (scanNr,beamTime,bmnum,gate,data) dataList.append(tmp) + goodScan = True else: continue - #Determine the start time for each scan and save to list. - scanTimeList.append(min([x.time for x in myScan])) + if goodScan: + #Determine the start time for each scan and save to list. + scanTimeList.append(min([x.time for x in myScan])) - #Advance to the next scan number. - scanNr = scanNr + 1 + #Advance to the next scan number. + scanNr = scanNr + 1 #Convert lists to numpy arrays. timeArray = np.array(scanTimeList) From abbbe49093a39dcb448e0c7d17687c35e824d5e2 Mon Sep 17 00:00:00 2001 From: "Nathaniel A. Frissell" Date: Fri, 11 Jul 2014 14:40:05 -0400 Subject: [PATCH 29/29] added some switches to turn on/off some plot labels --- pydarn/plotting/musicPlot.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pydarn/plotting/musicPlot.py b/pydarn/plotting/musicPlot.py index 23c5a47d..2c65ecce 100644 --- a/pydarn/plotting/musicPlot.py +++ b/pydarn/plotting/musicPlot.py @@ -393,6 +393,7 @@ class musicRTI(object): * [**secondary_coords**] (str): Secondary coordate system for RTI plot y-axis ('lat' or 'range') * [**plot_info**] (bool): If True, plot frequency/noise plots * [**plot_title**] (bool): If True, plot the title information + * [**plot_range_limits_label**] (bool): If True, plot the label corresponding to the range limits on the right-hand y-axis. * [**cmap_handling**] (str): 'superdarn' to use SuperDARN-style colorbars, 'matplotlib' for direct use of matplotlib's colorbars. 'matplotlib' is recommended when using custom scales and the 'superdarn' mode is not providing a desirable result. * [**plot_cbar**] (bool): If True, plot the color bar. @@ -426,6 +427,7 @@ def __init__(self,dataObject, secondary_coords = 'lat', plot_info = True, plot_title = True, + plot_range_limits_label = True, cmap_handling = 'superdarn', plot_cbar = True, cbar_ticks = None, @@ -718,7 +720,8 @@ def __init__(self,dataObject, txt = '\n'.join(txt) else: txt = '%.1f' % bnd_item - axis.annotate(txt, (1.01, bnd_item) ,xycoords=('axes fraction','data'),rotation=90,ma='center') + if plot_range_limits_label: + axis.annotate(txt, (1.01, bnd_item) ,xycoords=('axes fraction','data'),rotation=90,ma='center') if plot_cbar: cbar = fig.colorbar(pcoll,orientation='vertical',shrink=cbar_shrink,fraction=cbar_fraction)