def lon_lt_ticks(self, x, pos): ''' Define ticks to include local time in addition to longitude. Assumes that x is longitude in degrees. ''' import math import gitm_plot_rout as gpr # Calculate the local time in hours lth = gpr.glon_to_localtime(self['time'], x) ltm = int((lth - math.floor(lth)) * 60.0) # Build the format string fmtstring = "{:g}$^\circ$\n {:02d}:{:02d}".format(x, int(lth), ltm) return (fmtstring)
def lon_lt_ticks(self, x, pos): ''' Define ticks to include local time in addition to longitude. Assumes that x is longitude in degrees. ''' import math import gitm_plot_rout as gpr # Calculate the local time in hours lth = gpr.glon_to_localtime(self['time'], x) ltm = int((lth - math.floor(lth)) * 60.0) # Build the format string fmtstring = "{:g}$^\circ$\n {:02d}:{:02d}".format(x, int(lth), ltm) return(fmtstring)
def gitm_single_alt_image(plot_type, zkey, gData, lat_index=-1, lon_index=-1, title=None, figname=None, draw=True, xkey="dLat", lon_lt=False, hold_key=None, geo_key=None, hold_value=None, color="b", marker="o", line=":", zmax=None, zmin=None, amax=None, amin=None, xmax=None, xmin=None, zcenter=False, add_hmf2=False, hcolor="k", hline="--", add_fieldlines=False, apex_alts=list(), acolor="k", aline="-", *args, **kwargs): ''' Creates a rectangular or polar map projection plot for a specified latitude range. Input: plot_type = key to determine plot type (linear, contour, scatter) zkey = key for z variable (ie 'Vertical TEC') gData = gitm bin structure lat_index = index of constant latitude (default -1, none) lon_index = index of constant longitude (default -1, none) title = plot title figname = file name to save figure as (default is none) xkey = for contour plots specify an x key (default dLat) (options dLat/dLon/Latitude/Longitude) lon_lt = Add local time to the x axis (default=False). Will cause problems unless xkey is dLon. hold_key = Key to coordinate in which desired location is specified geo_key = Geographic coordinate corresponding to hold_key coord. hold_value = value of desired, specific coordinate location color = linear color (default blue) for b&w contour, enter 'k' marker = linear marker type (default circles) line = linear line type (default dotted) zmax = z key maximum (None to compute automatically, default) zmin = z key minimum (None to compute automatically, default) amax = a key maximum (None to compute automatically, default) amin = a key minimum (None to compute automatically, default) xmax = x key maximum for countour plots (or None to compute automatically, default) xmin = x key minimum for contour plots (or None to compute automatically, default) zcenter = Center z axis about zero? (default is False) add_hmf2 = Add line showing hmF2? (default=False) hcolor = Line color for hmF2 line (default=black) hline = Line style for hmF2 line (default=dashes) add_fieldlines = Add dipole field lines (default=False) apex_alts = List of apex altitudes to plot field lines at (default=list(), will pick a range of apex alts) acolor = Line color for field lines (default="k") aline = Line style for field lines (default="-") ''' # Initialize the altitude and x variable limits if (amin == None or amax == None): tmin, tmax = gpr.find_data_limits([gData], "Altitude", lat_index, lon_index, -2, 30) if amin == None: amin = tmin amin = math.ceil(amin / 10000.0) * 10.0 if amax == None: amax = tmax amax = math.floor(amax / 10000.0) * 10.0 if (plot_type.find("linear") < 0 and (xmin == None or xmax == None)): if gData[xkey].attrs['scale'].find("exp") >= 0: raw = True else: raw = False tmin, tmax = gpr.find_data_limits([gData], xkey, lat_index, lon_index, -2, 6, raw=raw) if xmin == None: xmin = tmin if xmax == None: xmax = tmax # Initialize the input data indices datadim = [gData.attrs['nAlt']] if lat_index >= 0: latmin = lat_index latmax = latmin + 1 else: latmin = 0 latmax = gData.attrs['nLat'] datadim.insert(0, gData.attrs['nLat']) if lon_index >= 0: lonmin = lon_index lonmax = lonmin + 1 else: lonmin = 0 lonmax = gData.attrs['nLon'] datadim.insert(0, gData.attrs['nLon']) # Initialize the data alt_data = np.array(gData['Altitude'][lonmin:lonmax, latmin:latmax, :]) alt_data = alt_data.reshape(datadim) if plot_type.find("linear") >= 0: # Perform interpolation to plot data at a specific location instead of a # grid point if (gData.has_key(hold_key) and hold_value is not None): if geo_key.find("Lon") >= 0: lonmin = 0 lonmax = gData.attrs['nLon'] elif geo_key.find("Lat") >= 0: latmin = 0 latmax = gData.attrs['nLat'] i_data = gpr.create_linear_input_array(hold_key, hold_value, "Altitude", [zkey], gData, alt_data, lonmin=lonmin, lonmax=lonmax, latmin=latmin, latmax=latmax, altmax=gData.attrs['nAlt']) x_data = np.array(i_data[zkey]) if zmin == None: xmin = np.nanmin(x_data) if zmax == None: xmax = np.nanmax(x_data) else: if (zmin == None or zmax == None): if gData[zkey].attrs['scale'].find("exp") >= 0: raw = True else: raw = False tmin, tmax = gpr.find_data_limits([gData], zkey, lat_index, lon_index, -2, 6, raw=raw) if zmin == None: xmin = tmin if zmax == None: xmax = tmax x_data = np.array(gData[zkey][lonmin:lonmax, latmin:latmax, :]) x_data = x_data.reshape(datadim) x_name = gData[zkey].attrs['name'] x_scale = gData[zkey].attrs['scale'] x_units = gData[zkey].attrs['units'] z_data = [] z_name = "" z_scale = "" z_units = "" else: if color.find('k') == 0: color = False else: color = True marker = True line = zcenter # Perform interpolation to plot data at a specific location instead of a # grid point if (gData.has_key(hold_key) and hold_value is not None): ilon = 0 ilat = 0 x_data = np.array(gData[xkey][lonmin:lonmax, latmin:latmax, 0]).flatten() if geo_key.find("Lon") >= 0: ilon = -1 elif geo_key.find("Lat") >= 0: ilat = -1 i_data = gpr.create_contour_input_array(hold_key, hold_value, xkey, "Altitude", [zkey], gData, x_data, alt_data[0, :], lonmin=ilon, latmin=ilat) x_data = np.array(i_data[xkey]) z_data = np.array(i_data[zkey]) alt_data = np.array(i_data['Altitude']) if zmin == None: zmin = np.nanmin(z_data) if zmax == None: zmax = np.nanmax(z_data) else: if (zmin == None or zmax == None): if gData[zkey].attrs['scale'].find("exp") >= 0: raw = True else: raw = False tmin, tmax = gpr.find_data_limits([gData], zkey, lat_index, lon_index, -2, 6, raw=raw) if zmin == None: zmin = tmin if zmax == None: zmax = tmax x_data = np.array(gData[xkey][lonmin:lonmax, latmin:latmax, :]) x_data = x_data.reshape(datadim) z_data = np.array(gData[zkey][lonmin:lonmax, latmin:latmax, :]) z_data = z_data.reshape(datadim) x_name = gData[xkey].attrs['name'] x_scale = gData[xkey].attrs['scale'] x_units = gData[xkey].attrs['units'] z_name = gData[zkey].attrs['name'] z_scale = gData[zkey].attrs['scale'] z_units = gData[zkey].attrs['units'] # Initialize the new figure f, ax = pap.plot_single_alt_image(plot_type, x_data, alt_data / 1000.0, z_data, x_name, x_scale, x_units, "km", z_name=z_name, z_scale=z_scale, z_units=z_units, xmin=xmin, xmax=xmax, amin=amin, amax=amax, zmin=zmin, zmax=zmax, title=title, draw=False, color1=color, color2=marker, color3=line) # Add local time to longitude axis, if desired if lon_lt: xfmt = FuncFormatter(gData.lon_lt_ticks) ax.xaxis.set_major_formatter(xfmt) ax.set_xlabel("Longitude \ Local Time") plt.subplots_adjust(bottom=.13) # Add hmF2 if desired if add_hmf2 and not gData.has_key("hmF2"): gData.calc_2dion() if not gData.has_key("hmF2"): print module_name, "WARNING: hmF2 data is not available" add_hmF2 = False if add_hmf2: if plot_type.find("linear") >= 0: x = np.array([xmin, xmax]) if (gData.has_key(hold_key) and hold_value is not None): if geo_key.find("Lon") >= 0: x_data = gData[hold_key][:, latmin:latmax, int(gData.attrs['nAlt'] / 2)].flatten() y_data = gData['hmF2'][:, latmin:latmax, 0].flatten() elif geo_key.find("Lat") >= 0: x_data = gData[hold_key][lonmin:lonmax, :, int(gData.attrs['nAlt'] / 2)].flatten() y_data = gData['hmF2'][20:21, :, 0].flatten() hold = interpolate.interp1d(x_data, y_data) hmf2 = hold(hold_value) else: hmf2 = gData['hmF2'][lonmin:lonmax, latmin:latmax, 0] y = np.array([hmf2, hmf2]) else: if (gData.has_key(hold_key) and hold_value is not None): if geo_key.find("Lon") >= 0: lonmin = 0 lonmax = gData.attrs['nLon'] elif geo_key.find("Lat") >= 0: latmin = 0 latmax = gData.attrs['nLat'] x = x_data[0, :] i_data = gpr.create_linear_input_array(hold_key, hold_value, xkey, ['hmF2'], gData, x, lonmin=lonmin, lonmax=lonmax, latmin=latmin, latmax=latmax) y = np.array(i_data['hmF2']) else: x = x_data y = np.array(gData['hmF2'][lonmin:lonmax, latmin:latmax, 0]) y = y.reshape(datadim[0:-1]) ax.plot(x, y, color=hcolor, linestyle=hline, linewidth=2) # Add field lines, if desired if add_fieldlines and plot_type.find("contour") >= 0: lon = None dec = None lon_units = "radians" lat_units = "degrees" lat_type = "geographic" if hold_key == None: hold_key = "Longitude" hold_value = float(gData[hold_key][lonmin:lonmax, 0, 0]) if xkey == "Latitude" or xkey == "dLat": from scipy import interpolate x = x_data[0] if xkey == "Latitude": lat_units = "radians" # If the geographic equator is on the x-axis, find the longitude # and declination at the geomagnetic equator ikeys = ["Declination"] if hold_key != "Longitude" and hold_key != "dLon": ikeys.append("Longitude") i_data = gpr.create_linear_input_array( hold_key, hold_value, "Inclination", ikeys, gData, x_data[0], lonmax=lonmax, lonmin=lonmin, latmax=latmax, latmin=latmin, altmax=gData.attrs['nAlt']) else: x = x_data[:, 0] i_data = dict() i_data['Inclination'] = gData['Inclination'][lonmin:lonmax, latmin:latmax, 0] i_data['Inclination'] = i_data['Inclination'].reshape(latmax) i_data['Declination'] = gData['Declination'][lonmin:lonmax, latmin:latmax, 0] i_data['Declination'] = i_data['Declination'].reshape(latmax) # Remove any NaN ikeys.append("Inclination") test = range(len(i_data[ikeys[0]])) for i in ikeys: test *= i_data[i] good = [i for i, t in enumerate(test) if not np.isnan(t)] if len(good) > 2: for i in ikeys: i_data[i] = i_data[i].take(good) # Interpolate good data tckdec = interpolate.splrep(i_data['Inclination'], i_data['Declination'], s=0) dec = interpolate.splev(0.0, tckdec, der=0) if i_data.has_key("Longitude"): tcklon = interpolate.splrep(i_data['Inclination'], i_data['Longitude'], s=0) lon = interpolate.splev(0.0, tcklon, der=0) else: lon = hold_value if np.isnan(dec) or np.isnan(lon): print "WARNING: unable to interpolate lon and dec at meq" lat_type = None else: # Add local time to the title lt = gpr.glon_to_localtime(gData['time'], lon, lon_units) h = int(lt) m = int((lt - h) * 60.0) ax.set_title("{:}, {:02d}:{:02d} SLT".format(title, h, m), size="medium") else: print "WARNING: unable to find longitude and declination at meq" lat_type = None elif xkey == "Inclination": lat_type = "inclination" elif xkey == "Magnetic Latitude": lat_type = "magnetic" else: print "WARNING: can't output field lines when xaxis is", xkey lat_type = None if lat_type is not None: if len(apex_alts) < 1: # Set default apex altitudes apex_alts = [ amin + float(i + 1) * 200.0 for i in range(int(math.ceil((amax - amin) / 200.0))) ] for alt in apex_alts: gpr.add_dipole_fieldline(ax, alt, x, lat_units=lat_units, lat_type=lat_type, longitude=lon, lon_units=lon_units, declination=dec, color=acolor, linestyle=aline) if draw: # Draw to screen. if plt.isinteractive(): plt.draw() #In interactive mode, you just "draw". else: # W/o interactive mode, "show" stops the user from typing more # at the terminal until plots are drawn. plt.show() # Save output file if figname is not None: plt.savefig(figname) return f, ax
def gitm_single_alt_image(plot_type, zkey, gData, lat_index=-1, lon_index=-1, title=None, figname=None, draw=True, xkey="dLat", lon_lt=False, hold_key=None, geo_key=None, hold_value=None, color="b", marker="o", line=":", zmax=None, zmin=None, amax=None, amin=None, xmax=None, xmin=None, zcenter=False, add_hmf2=False, hcolor="k", hline="--", add_fieldlines=False, apex_alts=list(), acolor="k", aline="-", *args, **kwargs): ''' Creates a rectangular or polar map projection plot for a specified latitude range. Input: plot_type = key to determine plot type (linear, contour, scatter) zkey = key for z variable (ie 'Vertical TEC') gData = gitm bin structure lat_index = index of constant latitude (default -1, none) lon_index = index of constant longitude (default -1, none) title = plot title figname = file name to save figure as (default is none) xkey = for contour plots specify an x key (default dLat) (options dLat/dLon/Latitude/Longitude) lon_lt = Add local time to the x axis (default=False). Will cause problems unless xkey is dLon. hold_key = Key to coordinate in which desired location is specified geo_key = Geographic coordinate corresponding to hold_key coord. hold_value = value of desired, specific coordinate location color = linear color (default blue) for b&w contour, enter 'k' marker = linear marker type (default circles) line = linear line type (default dotted) zmax = z key maximum (None to compute automatically, default) zmin = z key minimum (None to compute automatically, default) amax = a key maximum (None to compute automatically, default) amin = a key minimum (None to compute automatically, default) xmax = x key maximum for countour plots (or None to compute automatically, default) xmin = x key minimum for contour plots (or None to compute automatically, default) zcenter = Center z axis about zero? (default is False) add_hmf2 = Add line showing hmF2? (default=False) hcolor = Line color for hmF2 line (default=black) hline = Line style for hmF2 line (default=dashes) add_fieldlines = Add dipole field lines (default=False) apex_alts = List of apex altitudes to plot field lines at (default=list(), will pick a range of apex alts) acolor = Line color for field lines (default="k") aline = Line style for field lines (default="-") ''' # Initialize the altitude and x variable limits if(amin == None or amax == None): tmin, tmax = gpr.find_data_limits([gData], "Altitude", lat_index, lon_index, -2, 30) if amin == None: amin = tmin amin = math.ceil(amin / 10000.0) * 10.0 if amax == None: amax = tmax amax = math.floor(amax / 10000.0) * 10.0 if(plot_type.find("linear") < 0 and (xmin == None or xmax == None)): if gData[xkey].attrs['scale'].find("exp") >= 0: raw = True else: raw = False tmin, tmax = gpr.find_data_limits([gData], xkey, lat_index, lon_index, -2, 6, raw=raw) if xmin == None: xmin = tmin if xmax == None: xmax = tmax # Initialize the input data indices datadim = [gData.attrs['nAlt']] if lat_index >= 0: latmin = lat_index latmax = latmin + 1 else: latmin = 0 latmax = gData.attrs['nLat'] datadim.insert(0, gData.attrs['nLat']) if lon_index >= 0: lonmin = lon_index lonmax = lonmin + 1 else: lonmin = 0 lonmax = gData.attrs['nLon'] datadim.insert(0, gData.attrs['nLon']) # Initialize the data alt_data = np.array(gData['Altitude'][lonmin:lonmax,latmin:latmax,:]) alt_data = alt_data.reshape(datadim) if plot_type.find("linear") >= 0: # Perform interpolation to plot data at a specific location instead of a # grid point if(gData.has_key(hold_key) and hold_value is not None): if geo_key.find("Lon") >= 0: lonmin = 0 lonmax = gData.attrs['nLon'] elif geo_key.find("Lat") >= 0: latmin = 0 latmax = gData.attrs['nLat'] i_data = gpr.create_linear_input_array(hold_key, hold_value, "Altitude", [zkey], gData, alt_data, lonmin=lonmin, lonmax=lonmax, latmin=latmin, latmax=latmax, altmax=gData.attrs['nAlt']) x_data = np.array(i_data[zkey]) if zmin == None: xmin = np.nanmin(x_data) if zmax == None: xmax = np.nanmax(x_data) else: if(zmin == None or zmax == None): if gData[zkey].attrs['scale'].find("exp") >= 0: raw = True else: raw = False tmin, tmax = gpr.find_data_limits([gData],zkey,lat_index, lon_index,-2,6,raw=raw) if zmin == None: xmin = tmin if zmax == None: xmax = tmax x_data = np.array(gData[zkey][lonmin:lonmax,latmin:latmax,:]) x_data = x_data.reshape(datadim) x_name = gData[zkey].attrs['name'] x_scale = gData[zkey].attrs['scale'] x_units = gData[zkey].attrs['units'] z_data = [] z_name = "" z_scale = "" z_units = "" else: if color.find('k') == 0: color = False else: color = True marker=True line=zcenter # Perform interpolation to plot data at a specific location instead of a # grid point if(gData.has_key(hold_key) and hold_value is not None): ilon = 0 ilat = 0 x_data = np.array(gData[xkey][lonmin:lonmax,latmin:latmax, 0]).flatten() if geo_key.find("Lon") >= 0: ilon = -1 elif geo_key.find("Lat") >= 0: ilat = -1 i_data = gpr.create_contour_input_array(hold_key, hold_value, xkey, "Altitude", [zkey], gData, x_data, alt_data[0,:], lonmin=ilon, latmin=ilat) x_data = np.array(i_data[xkey]) z_data = np.array(i_data[zkey]) alt_data = np.array(i_data['Altitude']) if zmin == None: zmin = np.nanmin(z_data) if zmax == None: zmax = np.nanmax(z_data) else: if(zmin == None or zmax == None): if gData[zkey].attrs['scale'].find("exp") >= 0: raw = True else: raw = False tmin, tmax = gpr.find_data_limits([gData],zkey,lat_index, lon_index, -2, 6, raw=raw) if zmin == None: zmin = tmin if zmax == None: zmax = tmax x_data = np.array(gData[xkey][lonmin:lonmax,latmin:latmax,:]) x_data = x_data.reshape(datadim) z_data = np.array(gData[zkey][lonmin:lonmax,latmin:latmax,:]) z_data = z_data.reshape(datadim) x_name = gData[xkey].attrs['name'] x_scale = gData[xkey].attrs['scale'] x_units = gData[xkey].attrs['units'] z_name = gData[zkey].attrs['name'] z_scale = gData[zkey].attrs['scale'] z_units = gData[zkey].attrs['units'] # Initialize the new figure f, ax = pap.plot_single_alt_image(plot_type, x_data, alt_data/1000.0, z_data, x_name, x_scale, x_units, "km", z_name=z_name, z_scale=z_scale, z_units=z_units, xmin=xmin, xmax=xmax, amin=amin, amax=amax, zmin=zmin, zmax=zmax, title=title, draw=False, color1=color, color2=marker, color3=line) # Add local time to longitude axis, if desired if lon_lt: xfmt = FuncFormatter(gData.lon_lt_ticks) ax.xaxis.set_major_formatter(xfmt) ax.set_xlabel("Longitude \ Local Time") plt.subplots_adjust(bottom=.13) # Add hmF2 if desired if add_hmf2 and not gData.has_key("hmF2"): gData.calc_2dion() if not gData.has_key("hmF2"): print module_name, "WARNING: hmF2 data is not available" add_hmF2 = False if add_hmf2: if plot_type.find("linear") >= 0: x = np.array([xmin, xmax]) if(gData.has_key(hold_key) and hold_value is not None): if geo_key.find("Lon") >= 0: x_data = gData[hold_key][:,latmin:latmax, int(gData.attrs['nAlt']/2)].flatten() y_data = gData['hmF2'][:,latmin:latmax,0].flatten() elif geo_key.find("Lat") >= 0: x_data = gData[hold_key][lonmin:lonmax,:,int(gData.attrs['nAlt']/2)].flatten() y_data = gData['hmF2'][20:21,:,0].flatten() hold = interpolate.interp1d(x_data, y_data) hmf2 = hold(hold_value) else: hmf2 = gData['hmF2'][lonmin:lonmax,latmin:latmax,0] y = np.array([hmf2, hmf2]) else: if(gData.has_key(hold_key) and hold_value is not None): if geo_key.find("Lon") >= 0: lonmin = 0 lonmax = gData.attrs['nLon'] elif geo_key.find("Lat") >= 0: latmin = 0 latmax = gData.attrs['nLat'] x = x_data[0,:] i_data = gpr.create_linear_input_array(hold_key, hold_value, xkey, ['hmF2'], gData, x, lonmin=lonmin, lonmax=lonmax, latmin=latmin, latmax=latmax) y = np.array(i_data['hmF2']) else: x = x_data y = np.array(gData['hmF2'][lonmin:lonmax,latmin:latmax,0]) y = y.reshape(datadim[0:-1]) ax.plot(x, y, color=hcolor, linestyle=hline, linewidth=2) # Add field lines, if desired if add_fieldlines and plot_type.find("contour")>=0: lon = None dec = None lon_units = "radians" lat_units = "degrees" lat_type = "geographic" if hold_key == None: hold_key = "Longitude" hold_value = float(gData[hold_key][lonmin:lonmax,0,0]) if xkey == "Latitude" or xkey == "dLat": from scipy import interpolate x = x_data[0] if xkey == "Latitude": lat_units = "radians" # If the geographic equator is on the x-axis, find the longitude # and declination at the geomagnetic equator ikeys = ["Declination"] if hold_key != "Longitude" and hold_key != "dLon": ikeys.append("Longitude") i_data = gpr.create_linear_input_array(hold_key, hold_value, "Inclination", ikeys, gData, x_data[0], lonmax=lonmax, lonmin=lonmin, latmax=latmax, latmin=latmin, altmax=gData.attrs['nAlt']) else: x = x_data[:,0] i_data = dict() i_data['Inclination'] = gData['Inclination'][lonmin:lonmax, latmin:latmax,0] i_data['Inclination'] = i_data['Inclination'].reshape(latmax) i_data['Declination'] = gData['Declination'][lonmin:lonmax, latmin:latmax,0] i_data['Declination'] = i_data['Declination'].reshape(latmax) # Remove any NaN ikeys.append("Inclination") test = range(len(i_data[ikeys[0]])) for i in ikeys: test *= i_data[i] good = [i for i,t in enumerate(test) if not np.isnan(t)] if len(good) > 2: for i in ikeys: i_data[i] = i_data[i].take(good) # Interpolate good data tckdec = interpolate.splrep(i_data['Inclination'], i_data['Declination'], s=0) dec = interpolate.splev(0.0, tckdec, der=0) if i_data.has_key("Longitude"): tcklon = interpolate.splrep(i_data['Inclination'], i_data['Longitude'], s=0) lon = interpolate.splev(0.0, tcklon, der=0) else: lon = hold_value if np.isnan(dec) or np.isnan(lon): print "WARNING: unable to interpolate lon and dec at meq" lat_type = None else: # Add local time to the title lt = gpr.glon_to_localtime(gData['time'], lon, lon_units) h = int(lt) m = int((lt - h) * 60.0) ax.set_title("{:}, {:02d}:{:02d} SLT".format(title, h, m), size="medium") else: print "WARNING: unable to find longitude and declination at meq" lat_type = None elif xkey == "Inclination": lat_type = "inclination" elif xkey == "Magnetic Latitude": lat_type = "magnetic" else: print "WARNING: can't output field lines when xaxis is", xkey lat_type = None if lat_type is not None: if len(apex_alts) < 1: # Set default apex altitudes apex_alts = [amin+float(i+1)*200.0 for i in range(int(math.ceil((amax-amin)/200.0)))] for alt in apex_alts: gpr.add_dipole_fieldline(ax, alt, x, lat_units=lat_units, lat_type=lat_type, longitude=lon, lon_units=lon_units, declination=dec, color=acolor, linestyle=aline) if draw: # Draw to screen. if plt.isinteractive(): plt.draw() #In interactive mode, you just "draw". else: # W/o interactive mode, "show" stops the user from typing more # at the terminal until plots are drawn. plt.show() # Save output file if figname is not None: plt.savefig(figname) return f, ax