def plot_ima_spectra( start, finish, species=["H", "O", "O2"], colorbar=True, ax=None, blocks=None, check_times=True, return_val=None, verbose=False, check_overlap=True, vmin=2, vmax=7.0, raise_all_errors=False, cmap=None, norm=None, die_on_empty_blocks=False, accept_new_tables=True, inverted=True, **kwargs ): """ Plot IMA spectra from start - finish, . blocks is a list of data blocks to work from, if this is not specified then we'll read them species names: [only those with x will function] heavy (16, 85, 272) x sumions (85, 32) CO2 (16, 85, 272) x E (96, 1) Horig (16, 85, 272) x tmptime (1, 272) H (16, 85, 272) dE (1, 85) sumorigions (85, 32) O (16, 85, 272) x Hsp (16, 85, 272) x mass (50, 272) alpha (16, 85, 272) x O2 (16, 85, 272) x He (16, 85, 272) x for blocks read with dataset='fion', we'll add an 'f' before CO2, O2, O2plus, O, Horig, He, H automagically """ if not blocks: blocks = read_ima(start, finish, verbose=verbose, **kwargs) if ax is None: ax = plt.gca() plt.sca(ax) ax.set_axis_bgcolor("lightgrey") if not cmap: cmap = matplotlib.cm.Greys_r # cmap.set_under('white') if not norm: norm = plt.Normalize(vmin, vmax, clip=True) ims = [] last_finish = -9e99 if blocks: if "fH" in list(blocks[0].keys()): # blocks were read with dataset='fion' if isinstance(species, str): if species in ("O", "H", "He", "alpha", "Horig", "O2", "O2plus", "CO2"): species = "f" + species else: new_species = [] for s in species: if s in ("O", "H", "He", "alpha", "Horig", "O2", "O2plus", "CO2"): new_species.append("f" + s) species = new_species # if isinstance(species, basestring): # if species[0] == 'f': # label = species[1:] + r' flux \n / $cm^{-2}s^{-1}$' # else: # label = species + '****' # else: # label = '' # for s in species: # if s[0] == 'f': # label += s[1:] + ', ' # else: # label += s # label += r' flux \n/ $cm^{-2}s^{-1}$' label = r"Flux / $cm^{-2}s^{-1}$" # Make sure we set the ylimits correctly by tracking min and max energies min_energy = 60000.0 max_energy = -10.0 for b in blocks: # min(abs()) to account for negative values in E table extent = [ celsius.matlabtime_to_spiceet(b["tmptime"][0]), celsius.matlabtime_to_spiceet(b["tmptime"][-1]), min(abs(b["E"])), max(b["E"]), ] # Account for the varying size of the Energy table: if b["sumions"].shape[0] == 96: extent[2] = b["E"][-1] extent[3] = b["E"][0] elif b["sumions"].shape[0] == 85: # revised energy table extent[2] = b["E"][-11] extent[3] = b["E"][0] if extent[2] < 0.0: raise ValueError("Energies should be positive - unrecognised energy table?") else: if accept_new_tables: extent[2] = np.min(np.abs(b["E"])) extent[3] = b["E"][0] print("New table:", extent[2], extent[3], b["E"][-1], b["E"][0], b["sumions"].shape[0]) else: raise ValueError( "Unrecognised energy table: E: %e - %e in %d steps?" % (b["E"][-1], b["E"][-1], b["sumions"].shape[0]) ) if extent[2] < min_energy: min_energy = extent[2] if extent[3] > max_energy: max_energy = extent[3] if check_times: spacing = 86400.0 * np.mean(np.diff(b["tmptime"])) if spacing > 15.0: if raise_all_errors: raise ValueError("Resolution not good? Mean spacing = %fs " % spacing) else: plt.annotate( "Resolution warning:\nmean spacing = %.2fs @ %s " % (spacing, celsius.utcstr(np.median(b["tmptime"]))), (0.5, 0.5), xycoords="axes fraction", color="red", ha="center", ) if not isinstance(species, str): # produce the MxNx3 array for to up 3 values of species (in R, G, B) img = np.zeros((b[species[0]].shape[1], b[species[0]].shape[2], 3)) + 1.0 for i, s in enumerate(species): im = np.sum(b[s], 0).astype(np.float64) # im[im < 0.01] += 0.1e-10 if inverted: im = 1.0 - norm(np.log10(im)) for j in (0, 1, 2): if j != i: img[..., j] *= im tot = np.sum(1.0 - img) else: img[..., i] *= norm(np.log10(im)) tot = np.sum(img) else: img = np.sum(b[species], 0) img[img < 0.01] += 0.1e-10 img = np.log10(img) tot = np.sum(img) if verbose: print("Total scaled: %e" % tot) # print 'Fraction good = %2.0f%%' % (np.float(np.sum(np.isfinite(img))) / (img.size) * 100.) # print 'Min, mean, max = ', np.min(img), np.mean(img), np.max(img) if check_overlap and (extent[0] < last_finish): raise ValueError("Blocks overlap: Last finish = %f, this start = %f" % (last_finish, extent[0])) if FUDGE_FIX_HANS_IMA_TIME_BUG: # print extent, last_finish if abs(extent[0] - last_finish) < 20.0: # if there's 20s or less between blocks if verbose: print("\tFudging extent: Adjusting start by %fs" % (extent[0] - last_finish)) extent[0] = last_finish # squeeze them together if inverted: name = cmap.name if name[-2:] == "_r": name = name[:-2] else: name = name + "_r" cmap = getattr(plt.cm, name) if extent[1] < start: # if verbose: print("Dumping block (B)", start - extent[1]) continue if extent[0] > finish: print("Dumping block (A)", extent[0] - finish) continue ims.append(plt.imshow(img, extent=extent, origin="upper", interpolation="nearest", cmap=cmap, norm=norm)) last_finish = extent[1] if ims: plt.xlim(start, finish) plt.ylim(min_energy, max_energy) cbar_im = ims[0] else: plt.ylim(10.0, 60000) # guess # invisible image for using with colorbar cbar_im = plt.imshow(np.zeros((1, 1)), cmap=cmap, norm=norm, visible=False) plt.yscale("log") celsius.ylabel("E / eV") if colorbar: ## make_colorbar_cax is doing something weird to following colorbars... # if not isinstance(species, basestring): # img = np.zeros((64,len(species),3)) + 1. # cax = celsius.make_colorbar_cax(width=0.03) # for i, s in enumerate(species): # for j in (0,1,2): # if j != i: # img[:,i,j] = np.linspace(0., 1., 64) # # plt.sca(cax) # plt.imshow(img, extent=(0, 3, vmin, vmax), interpolation='nearest', aspect='auto') # plt.xticks([0.5, 1.5, 2.5], label.split(', ')) # plt.xlim(0., 3.) # cax.yaxis.tick_right() # cax.xaxis.tick_top() # plt.yticks = [2,3,4,5,6] # cax.yaxis.set_label_position('right') # plt.ylabel(r'$Flux / cm^{-2}s^{-1}$') # # plt.sca(ax) # else: ticks = np.arange(int(vmin), int(vmax) + 1, dtype=int) plt.colorbar(cbar_im, cax=celsius.make_colorbar_cax(), ticks=ticks).set_label(label) if return_val: if return_val == "IMAGES": del blocks return ims elif return_val == "BLOCKS": return blocks else: print("Unrecognised return_value = " + str(return_value)) del blocks del ims return
def plot_els_spectra( start, finish, sector="SUM", colorbar=True, ax=None, blocks=None, return_val=None, verbose=False, check_times=True, vmin=None, vmax=None, cmap=None, norm=None, die_on_empty_blocks=False, **kwargs ): """ Plot ASPERA/ELS spectra from start - finish. sector = int from 0 - 15 to select single sector to plot. sector = 'SUM' to integrate over all sector = 'MEAN' to average over all Shapes of the stuff in each block (215 = time!) altElec (1, 215) latElec (1, 215) zmsoElec (1, 215) dEElec (128, 1) ymsoElec (1, 215) xmsoElec (1, 215) tElec (1, 215) fElec (16, 128, 215) longElec (1, 215) EElec (128, 1) New versions: elslevels (128, 112) elsmatrix (128, 16, 783) elstimes (1, 783) elssectors (1, 16) elsleveltimes (1, 112) elsdeltatimes (128, 112) """ if not blocks: blocks = read_els(start, finish, verbose=verbose, **kwargs) if ax is None: ax = plt.gca() plt.sca(ax) ax.set_axis_bgcolor("lightgrey") if not cmap: cmap = Spectral_r cmap.set_bad("white") ims = [] last_finish = -9e99 # label = r'Flux / $cm^{-2}s^{-1}$' label = "Counts" # Make sure we set the ylimits correctly by tracking min and max energies min_energy = 1e99 max_energy = -1e99 cbar_ticks = np.array((7, 8, 9, 10, 11)) # Establish function to handle the data if isinstance(sector, str): if sector.lower() == "mean": process = lambda x: np.nanmean(x, 1) # if vmin is None: # vmin = 7. # if vmax is None: # vmax = 11. elif sector.lower() == "sum": process = lambda x: np.nansum(x, 1) # if vmin is None: # vmin = 7. + 1. # if vmax is None: # vmax = 11. + 1. # cbar_ticks += 1 else: raise ValueError("Unrecognized argument for sector: %s" % sector) else: process = lambda x: x[:, sector, :] # if vmin is None: # vmin = 7. # if vmax is None: # vmax = 11. if vmin is None: vmin = 0 if vmax is None: vmax = 4 if not norm: norm = plt.Normalize(vmin, vmax, clip=False) norm = None for b in blocks: # min(abs()) to account for negative values in E table extent = [ celsius.matlabtime_to_spiceet(np.min(b["elstimes"])), celsius.matlabtime_to_spiceet(np.max(b["elstimes"])), np.min(np.abs(b["elslevels"])), np.max(b["elslevels"]), ] if extent[2] < min_energy: min_energy = extent[2] if extent[3] > max_energy: max_energy = extent[3] print(extent) # if check_times: # spacing = 86400.*np.mean(np.diff(b['tElec'])) # if spacing > 15.: # raise ValueError("Resolution not good? Mean spacing = %fs " % spacing ) img = process(b["elsmatrix"]) # img[img < 10.] = np.min(img) img = np.log10(img) if verbose: print( "Fraction good = %2.0f%%" % (np.float(np.sum(np.isfinite(img))) / (img.shape[0] * img.shape[1]) * 100.0) ) # print 'Min, mean, max = ', np.nanmin(img), np.nanmean(img), np.nanmax(img) if extent[0] < last_finish: s = "Blocks overlap: Last finish = %f, this start = %f" % (last_finish, extent[0]) if check_times: raise ValueError(s) else: print(s) # e = extent[2] # extent[2] = extent[3] # extent[3] = e ims.append(plt.imshow(img, extent=extent, origin="upper", interpolation="nearest", cmap=cmap, norm=norm)) last_finish = extent[1] number_of_blocks = len(blocks) if blocks: plt.xlim(start, finish) plt.ylim(min_energy, max_energy) cbar_im = ims[0] else: plt.ylim(1e0, 1e4) # need to create an empty image so that colorbar functions cbar_im = plt.imshow(np.zeros((1, 1)), cmap=cmap, norm=norm, visible=False) plt.ylim(min_energy, max_energy) plt.yscale("log") # plt.ylabel('E / eV') print("ELS PLOT: Time is not accurate to more than ~+/- 4s for now.") if colorbar: if ims: plt.colorbar(cbar_im, cax=celsius.make_colorbar_cax(), ticks=cbar_ticks).set_label(label) if return_val: if return_val.upper() == "IMAGES": del blocks return ims elif return_val.upper() == "BLOCKS": del ims return blocks else: print("Unrecognised return_value = " + str(return_value)) del blocks del ims return number_of_blocks