Source code for queso_cluster.addon.products

"""
	:file:  queso_cluster/addon/products.py
	:lang:  python
	:synopsis: 
	:author: Sarah Riley <academic@sriley.dev>
"""

from . import style as sty
from .logg import loggTimer, logger
from ..atoms import aux as auxAtom
from ..atoms import scores as scoresAtom
from ..atoms import error as errorAtom

from  ..runners import base as baseRun

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from matplotlib.colors import LinearSegmentedColormap

from sklearn import metrics


[docs] class Products: """ Detail Parameters ---------- quesoOut : :class:`~queso_cluster.ti.timeIndependent` or :class:`~queso_cluster.td.timeDependent` Analysis object that stores all of the configuration """ def __init__(self, quesoOut): self._quesoOut = quesoOut self.load() self.optLabels[self.optLabels == 0] = np.nan self.vindx = np.where(~np.isnan(self.optLabels))#[0] self.vfindx = np.ravel_multi_index(self.vindx, self.optLabels.shape) ii, jj = [self._quesoOut._config.blueEdge, self._quesoOut._config.redEdge] #print(self.vfindx) if self.vfindx.size == 0: raise errorAtom.OopsAllNan() self._raw_max = (np.ceil(np.nanmax(self._quesoOut.prepSquare[self.vfindx, ii:jj+1])*100)/100.) self._raw_min = (np.floor(np.nanmin(self._quesoOut.prepSquare[self.vfindx, ii:jj+1])*100)/100.) if hasattr(self._quesoOut._config, "waveFitFunc"): waveFit = self._quesoOut._config.waveFitFunc(self._quesoOut._instrumentObj.nSpectral+1).to('angstrom') self._wavelambda = waveFit.magnitude self._wavelambda -= self._wavelambda[self._quesoOut._config.lineCenter] self._waveUnit = waveFit.units #print(self._waveUnit) else: self._wavelambda = np.arange(self._quesoOut._instrumentObj.dataPrism.shape[2]) self._waveUnit = "index" self._extent = self._wavelambda[ii], self._wavelambda[jj], self._raw_min, self._raw_max if len(self.vindx) == 2: self.xlim = np.array([self.vindx[0].min(), self.vindx[0].max()])*self._quesoOut._instrumentObj.pxlDelta['pxlSlitWidth'].magnitude self.ylim = np.array([self.vindx[1].min(), self.vindx[1].max()])*self._quesoOut._instrumentObj.pxlDelta['pxlAlongSlit'].magnitude elif len(self.vindx) == 3: self.xlim = np.array([self.vindx[1].min(), self.vindx[1].max()])*self._quesoOut._instrumentObj.pxlDelta['pxlSlitWidth'].magnitude self.ylim = np.array([self.vindx[2].min(), self.vindx[2].max()])*self._quesoOut._instrumentObj.pxlDelta['pxlAlongSlit'].magnitude print([self.xlim, self.ylim]) self.aspect = np.diff(self.xlim)[0]/np.diff(self.ylim)[0] self.clusterCmap = sty.clusterColormap(np.unique(self.optLabels[self.vindx]).astype(int)) self.mapMake = sty.mapMaker(self._quesoOut._instrumentObj)
[docs] def load(self): loading = np.load("./{}/{}.npz".format(self._quesoOut._config.directoryFlavor, self._quesoOut._config.flavor)) logger.info(loading) self.optLabels = loading['labelSquare'] self._quesoOut.maskLine = loading['maskLine'] self._quesoOut.prepSquare = loading['prepSquare'] loading.close()
[docs] @loggTimer def clusterMapSequence(self, timeAxis=False): """ Parameters ---------- timeAxis : bool, optional Boolean to add an extra axis for time Returns ------- figA : mpl.Figure Map of the cluster results for individual time steps figB : mpl.Figure Map of all distinct sequences """ if np.abs(np.diff(self.ylim)) > np.abs(np.diff(self.xlim)): figA = self.clusterMapSequenceHorizontal(timeAxis) else: figA = self.clusterMapSequenceVertical(timeAxis) #figB = self.clusterMapCompound(compoundLabels, timeAxis) return(figA)
[docs] @loggTimer def intensityMapSequence(self, timeAxis=False, **kwargs): if np.abs(np.diff(self.ylim)) > np.abs(np.diff(self.xlim)): figA = self.intensityMapSequenceHorizontal(timeAxis, **kwargs) else: figA = self.intensityMapSequenceVertical(timeAxis) #figB = self.clusterMapCompound(compoundLabels, timeAxis) return(figA)
[docs] def intensityMapSequenceHorizontal(self, timeAxis, **kwargs): """ Horizontal oriented maps of the cluster results for individual time steps Parameters ---------- compoundLabels : char.array timeAxis : bool Boolean to add an extra axis for time Returns ------- fig : mpl.figure Map of the cluster results for individual time steps compoundLabels : np.char.array Character array for all sequence labels """ ncols = self.optLabels.shape[0] #> Error?: Maximum number of clients reached fig = plt.figure(layout='compressed', figsize=(3*ncols, (3*ncols*self.aspect) * 1.2), dpi=300) nrows = 2 height_ratios=[0.025, 1] width_ratios = [1 for x in range(ncols)] gs = GridSpec(nrows, ncols, figure=fig, height_ratios=height_ratios, width_ratios=width_ratios, hspace=0, wspace=0) intensitySequence = np.nanmean(self._quesoOut._instrumentObj.dataPrism[self._quesoOut._config.timeFrames, ..., self._quesoOut._config.blueEdge:self._quesoOut._config.redEdge], axis=-1) intensitySequence = intensitySequence.reshape(self._quesoOut._config.timeFrames.size, self._quesoOut.geometry['rasterSize'], self._quesoOut.geometry['alongSlitSize']) print(intensitySequence.shape) for t in range(self.optLabels.shape[0]): kwargs['cmap'] = "Greys_r" ax, im = self.mapMake._mapGen(fig, gs[1, t], intensitySequence[t, ...], timeAxis=timeAxis, xlim=self.xlim, ylim=self.ylim, #flareContour=self.mask_map, **kwargs) if not gs[0, t].is_first_col(): ax.set_yticklabels([]) cax = fig.add_subplot(gs[0, :]) cbar = fig.colorbar(im, spacing='uniform', orientation="horizontal", cax=cax) #cbar.minorticks_off() return(fig)#, compoundLabels)
[docs] def intensityMapSequenceVertical(self, timeAxis, **kwargs): """ Vertical oriented maps of the cluster results for individual time steps Parameters ---------- compoundLabels : char.array timeAxis : bool Boolean to add an extra axis for time Returns ------- fig : mpl.figure Map of the cluster results for individual time steps compoundLabels : np.char.array Character array for all sequence labels """ ncols = self.optLabels.shape[0] #> Error?: Maximum number of clients reached fig = plt.figure(layout='constrained', figsize=((3*self.aspect)*1.2, 3*ncols), dpi=300) nrows = ncols ncols = 2 height_ratios = [1 for x in range(nrows)] width_ratios = [1, 0.025] gs = GridSpec(nrows, ncols, figure=fig, height_ratios=height_ratios, width_ratios=width_ratios, hspace=0, wspace=0) intensitySequence = np.nanmean(self._quesoOut._instrumentObj.dataPrism[self._quesoOut._config.timeFrames, ..., self._quesoOut._config.blueEdge:self._quesoOut._config.redEdge], axis=-1) intensitySequence = intensitySequence.reshape(self._quesoOut._config.timeFrames.size, self._quesoOut.geometry['rasterSize'], self._quesoOut.geometry['alongSlitSize']) print(intensitySequence.shape) for t in range(self.optLabels.shape[0]): kwargs['cmap'] = "Greys_r" ax, im = self.mapMake._mapGen(fig, gs[t, 0], intensitySequence[t, ...], timeAxis=timeAxis, xlim=self.xlim, ylim=self.ylim, #flareContour=self.mask_map, **kwargs) if not gs[t, 0].is_last_row(): ax.set_xticklabels([]) cax = fig.add_subplot(gs[:, 1]) cbar = fig.colorbar(im, spacing='uniform', orientation="horizontal", cax=cax) #cbar.minorticks_off() return(fig)#, compoundLabels)
[docs] def clusterMapCompound(self, compoundLabels, timeAxis=False): """ Creates a figure showing all of the distinct sequences of spectra Parameters ---------- compoundLabels : char.array Character array for all sequence labels timeAxis : bool Boolean to add an extra axis for time Returns ------- fig : mpl.Figure Figure showing the distribution of cluster sequences """ #compoundLabels[~np.char.isalnum(compoundLabels)] = np.nan maskSquare = self._quesoOut.maskLine.reshape((self.optLabels.shape[0], *compoundLabels.shape)).sum(axis=0) maskSquare[maskSquare > 0] = True maskSquare[maskSquare == 0] = False compoundLabels[maskSquare] = 'X' #compoundLabels *= maskSquare recountedCompoundLabels = np.zeros(compoundLabels.shape) + np.nan labelLst = np.unique(compoundLabels) lcounter = 1 for l in range(labelLst.size): #for t in range(self.optLabels.shape[0]): if labelLst[l] == 'X': continue lindx = np.where(compoundLabels == labelLst[l]) if len(lindx[0]) > 3: recountedCompoundLabels[lindx] = lcounter lcounter += 1 boxNew = np.where(np.isfinite(recountedCompoundLabels)) xlim = np.array([np.max([self.xlim[0], (boxNew[0].min())*self._quesoOut._instrumentObj.pxlDelta['pxlSlitWidth'].magnitude]), np.min([self.xlim[1], (boxNew[0].max())*self._quesoOut._instrumentObj.pxlDelta['pxlSlitWidth'].magnitude])]) ylim = np.array([np.max([self.ylim[0], (boxNew[1].min())*self._quesoOut._instrumentObj.pxlDelta['pxlAlongSlit'].magnitude]), np.min([self.ylim[1], (boxNew[1].max())*self._quesoOut._instrumentObj.pxlDelta['pxlAlongSlit'].magnitude])]) boxAspect = np.diff(xlim)[0]/np.diff(ylim)[0] #self.clusterProfilesCompound(recountedCompoundLabels) labelLst = np.unique(recountedCompoundLabels) labelLst = labelLst[~np.isnan(labelLst)] # if self.aspect <= 1: # fig = plt.figure(layout='compressed', figsize=(10, 10*self.aspect), dpi=300) # else: fig = plt.figure(layout='compressed', figsize=(10*boxAspect, 10), dpi=300) gs = GridSpec(1, 2, figure=fig, width_ratios=[1, 0.025], hspace=0, wspace=0) compoundClusterCmap = sty.clusterColormap(np.unique(labelLst).astype(int)) kwargsDict = {'cmap': compoundClusterCmap.cmap, 'norm': compoundClusterCmap.norm} ax, im = self.mapMake._mapGen(fig, gs[0, 0], recountedCompoundLabels, timeAxis=timeAxis, xlim=xlim, ylim=ylim, #flareContour=self.mask_map, **kwargsDict) cax = fig.add_subplot(gs[0, 1]) cbar = fig.colorbar(im, spacing='uniform', orientation="vertical", cax=cax) cbar.minorticks_off() cbar.set_ticks(compoundClusterCmap.bound_ticks, labels=compoundClusterCmap.tickLabels) return(fig)
[docs] @loggTimer def clusterProfilesCompound(self, compoundLabels): labelLst = np.unique(compoundLabels) ncols = self.optLabels.shape[0] lcounter = 1 for ll in range(labelLst.size): if labelLst[ll] == "X": continue indx2D = np.where(compoundLabels == labelLst[ll]) if indx2D[0].size > 3: fig = plt.figure(layout='constrained', figsize=((ncols + 0.2)*3, 1*3), dpi=300) gs = GridSpec(1, ncols + 1, left=0, right=1, top=1, bottom=0, width_ratios=[1 for x in range(ncols)] + [0.2], height_ratios=[1 for x in range(1)], figure=fig) for oo in range(ncols): indx = np.ravel_multi_index((oo*np.ones(indx2D[0].size, dtype=int), *indx2D), self.optLabels.shape) ax = plt.subplot(gs[0, oo]) ax = self.spectralEntry(ax, indx, "black", True) if not gs[0, oo].is_first_col(): ax.set_yticklabels([]) ax.set_xlabel(r"$\lambda-\lambda_{0}$" + " [{}]".format(self._waveUnit)) fig.savefig("./{}/sequences/labelTest_{}.png".format(self._quesoOut._config.flavor, int(lcounter))) lcounter += 1 plt.close()
[docs] def clusterMapSequenceVertical(self, timeAxis): """ Vertically oriented maps of the cluster results for individual time steps Parameters ---------- compoundLabels : char.array timeAxis : bool Boolean to add an extra axis for time Returns ------- fig : mpl.figure Map of the cluster results for individual time steps compoundLabels : np.char.array Character array for all sequence labels """ ncols = self.optLabels.shape[0] #> Error?: Maximum number of clients reached fig = plt.figure(layout='constrained', figsize=((3*self.aspect)*1.2, 3*ncols), dpi=300) nrows = ncols ncols = 2 height_ratios = [1 for x in range(nrows)] width_ratios = [1, 0.025] gs = GridSpec(nrows, ncols, figure=fig, height_ratios=height_ratios, width_ratios=width_ratios, hspace=0, wspace=0) labelLst = np.unique(self.optLabels[self.vindx]).astype(int)#.astype(str) # tLabels = np.unique(self.optLabels) #actual_bounds, bound_ticks, color_pallet = sty.cbar_bounds() #cmap = mpl.colors.ListedColormap(color_pallet) #norm = mpl.colors.BoundaryNorm(actual_bounds, cmap.N+1) #compoundLabels = np.zeros(self.optLabels.shape[1:], dtype=str) recountedLabels = np.zeros(self.optLabels.shape) + np.nan for l in range(labelLst.size): #for t in range(self.optLabels.shape[0]): if not np.isnan(labelLst[l]): lindx = np.where(self.optLabels == labelLst[l]) recountedLabels[lindx] = l+1 for t in range(self.optLabels.shape[0]): kwargsDict = {'cmap': self.clusterCmap.cmap, 'norm': self.clusterCmap.norm} ax, im = self.mapMake._mapGen(fig, gs[t, 0], recountedLabels[t, ...], timeAxis=timeAxis, xlim=self.xlim, ylim=self.ylim, #flareContour=self.mask_map, **kwargsDict) if not gs[t, 0].is_last_row(): ax.set_xticklabels([]) #cbar = fig.colorbar(im, cax=cax, ticks=bounds_ticks)#, label='Binned Intensity') # # cbar.ax.set_yticklabels(["{}XX".format(int(x)) for x in recountLst]) #compoundLabels = np.char.add(compoundLabels, np.char.zfill(recountedLabels[t, ...].astype(np.uint).astype(str), 2)) cax = fig.add_subplot(gs[:, 1]) cbar = fig.colorbar(im, spacing='uniform', ticks=self.clusterCmap.bound_ticks, orientation="vertical", cax=cax) cbar.ax.set_yticklabels(["{}".format(int(x)) for x in np.unique(labelLst)]) cbar.minorticks_off() return(fig)
[docs] def clusterMapSequenceHorizontal(self, timeAxis): """ Horizontal oriented maps of the cluster results for individual time steps Parameters ---------- compoundLabels : char.array timeAxis : bool Boolean to add an extra axis for time Returns ------- fig : mpl.figure Map of the cluster results for individual time steps compoundLabels : np.char.array Character array for all sequence labels """ ncols = self.optLabels.shape[0] #> Error?: Maximum number of clients reached fig = plt.figure(layout='compressed', figsize=(3*ncols, (3*ncols*self.aspect) * 1.2), dpi=300) nrows = 2 height_ratios=[0.025, 1] width_ratios = [1 for x in range(ncols)] gs = GridSpec(nrows, ncols, figure=fig, height_ratios=height_ratios, width_ratios=width_ratios, hspace=0, wspace=0) labelLst = np.unique(self.optLabels[self.vindx]).astype(int)#.astype(str) # tLabels = np.unique(self.optLabels) # actual_bounds, bound_ticks, color_pallet = sty.cbar_bounds(list(labelLst[~np.isnan(labelLst)])) # cmap = mpl.colors.ListedColormap(color_pallet) # norm = mpl.colors.BoundaryNorm(actual_bounds, cmap.N+1) #compoundLabels = np.zeros(self.optLabels.shape[1:], dtype=str) recountedLabels = np.zeros(self.optLabels.shape) + np.nan for l in range(labelLst.size): #for t in range(self.optLabels.shape[0]): lindx = np.where(self.optLabels == labelLst[l]) recountedLabels[lindx] = l+1 print(recountedLabels.shape) for t in range(self.optLabels.shape[0]): kwargsDict = {'cmap': self.clusterCmap.cmap, 'norm': self.clusterCmap.norm} ax, im = self.mapMake._mapGen(fig, gs[1, t], recountedLabels[t, ...], timeAxis=timeAxis, xlim=self.xlim, ylim=self.ylim, #flareContour=self.mask_map, **kwargsDict) if not gs[0, t].is_first_col(): ax.set_yticklabels([]) #cbar = fig.colorbar(im, cax=cax, ticks=bounds_ticks)#, label='Binned Intensity') # # cbar.ax.set_yticklabels(["{}XX".format(int(x)) for x in recountLst]) # compoundLabels = np.char.add(compoundLabels, # np.char.zfill(recountedLabels[t, ...].astype(np.uint).astype(str), 2)) cax = fig.add_subplot(gs[0, :]) cbar = fig.colorbar(im, spacing='uniform', ticks=self.clusterCmap.bound_ticks, orientation="horizontal", cax=cax) cbar.ax.set_xticklabels(["{}".format(int(x)) for x in np.unique(labelLst)]) cbar.minorticks_off() return(fig)#, compoundLabels)
# @loggTimer # def figure03(self): # #> detail: # #> param type self: # #> return (type): # #> test-method: # width = [2, 0.025] # types = ['intensity', 'labels'] # for t in range(len(types)): # fig = plt.figure(layout='compressed', figsize=(2*4, 3.25*4), dpi=300) # gs = GridSpec(3,2, figure=fig, width_ratios=width, height_ratios=[1, 1, 1], hspace=0, wspace=0) # intrinsicConfig = self.config.srcLst.clusterConfig['intrinsic'] # for i in range(len(intrinsicConfig)): # match intrinsicConfig[i]['label']: # case 'window': # moment0 = self._quesoOut._instrumentObj.dataSquare[:, self.ii:self.jj+1].mean(axis=-1).compute() # bins = intrinsicConfig[i]['layerConfig']['bins'] # cbar_label = "Mean Window Intensity" # case 'continuum': # moment0 = self._quesoOut._instrumentObj.dataSquare[:, self._quesoOut.lineContinuum].compute() # bins = intrinsicConfig[i]['layerConfig']['bins'] # cbar_label = "Continuum Intensity" # intrinsicLayerMap = baseRun.runIntrinsic(len(np.diff(bins)), np.floor(moment0*100)/100., # edgeOverride=np.array(bins).astype(float)) # match types[t]: # case 'intensity': # present = moment0 # cmap = 'Greys_r' # case 'labels': # instrinsicCmap = sty.clusterColormap(np.unique(intrinsicLayerMap).size) # present = intrinsicLayerMap # cmap = instrinsicCmap.cmap # norm = instrinsicCmap.norm # #cmap = mpl.colors.ListedColormap(color_pallet) # #norm = mpl.colors.BoundaryNorm(np.array(bins).astype(float), cmap.N) # kwargsDict = {'cmap': cmap} # # if i > np.inf: # # ax, im, tax = self.mapMake._mapGen(fig, gs[i, 0], # # present, # # timeAxis=True, # # #flareContour=self.mask_map, # # **kwargsDict) # # ax.set_xlabel("Raster Direction [arcseconds]") # # tax.set_xlabel('Time [hours after 20:02:42 UTC]') # # else: # ax, im = self.mapMake._mapGen(fig, gs[i, 0], # present, # #flareContour=self.mask_map, # **kwargsDict) # ax.set_xticklabels([]) # ax.set_aspect("equal") # ax.set_ylabel("Along Slit Direction [arcseconds]") # #ax.text(20, 2250, " ({})".format(self.alphaLst[i]), va="center", ha="center", bbox=dict(facecolor='white', edgecolor='black', boxstyle='round,pad=0.25', alpha=0.3), font='monospace') # # ax.annotate('({})'.format(self.alphaLst[i]), # # xy=(0.035, 1-0.05), xycoords='axes fraction', # # xytext=(0.035, 1-0.05), textcoords='axes fraction', fontfamily='sans-serif', # # va='center', ha='center', bbox=dict(boxstyle='square', facecolor='white', edgecolor='black', alpha=0.4)) # cax = fig.add_subplot(gs[i, 1]) # match types[t]: # case 'intensity': # im_cbar = im # case 'labels': # im_cbar = mpl.cm.ScalarMappable(norm=norm, cmap=cmap) # cbar = fig.colorbar(im_cbar, cax=cax, spacing='uniform', label=cbar_label) # intrinsicLayerMap_oldCount = auxAtom.pick_jth_label(self.optLabels[self.vindx], 0).astype(float) # intrinsicLayerMap = np.zeros(self.optLabels.shape) + np.nan # recountLst = np.unique(intrinsicLayerMap_oldCount) # for rc in range(recountLst.size): # lindx = np.where(intrinsicLayerMap_oldCount == recountLst[rc])[0] # intrinsicLayerMap[self.vindx[lindx]] = rc+1 # compoundInstrinsicColor = sty.clusterColormap(np.unique(intrinsicLayerMap[self.vindx]).size) # # actual_bounds, bound_ticks, color_pallet = sty.cbar_bounds(list()) # # cmap = mpl.colors.ListedColormap(color_pallet) # # norm = mpl.colors.BoundaryNorm(actual_bounds, cmap.N+1) # kwargsDict = {'cmap': compoundInstrinsicColor.cmap, "norm": compoundInstrinsicColor.norm} # ax, im, tax = self.mapMake._mapGen(fig, gs[-1, 0], # intrinsicLayerMap, # timeAxis=True, # #flareContour=self.mask_map, # **kwargsDict) # cax = fig.add_subplot(gs[-1, 1]) # ax.set_aspect("equal") # #cbar = fig.colorbar(im, cax=cax, ticks=bounds_ticks)#, label='Binned Intensity') # cbar = fig.colorbar(im, spacing='proportional', # ticks=compoundInstrinsicColor.bound_ticks, # cax=cax, label='Intrinsic bins') # cbar.ax.set_yticklabels(["{}XX".format(int(x)) for x in recountLst]) # ax.set_xlabel("Raster Direction [arcseconds]") # tax.set_xlabel('Time [hours after 20:02:42 UTC]') # ax.set_ylabel("Along Slit Direction [arcseconds]") # #ax.text(20, 2250, " ({})".format(self.alphaLst[2]), va="center", ha="center", bbox=dict(facecolor='white', edgecolor='black', boxstyle='round,pad=0.25', alpha=0.3)) # # ax.annotate('({})'.format(self.alphaLst[2]), # # xy=(0.035, 1-0.05), xycoords='axes fraction', # # xytext=(0.035, 1-0.05), textcoords='axes fraction', fontfamily='sans-serif', # # va='center', ha='center', bbox=dict(boxstyle='square', facecolor='white', edgecolor='black', alpha=0.4)) # fig.savefig('./figure03_{}.png'.format(types[t])) # #fig.savefig(self.figDir + 'figure03_{}.pdf'.format(types[t]))
[docs] @loggTimer def clusterProfiles(self, dev=False, showContinuum=True): """ Figure showing the representative profiles of each of the clusters and the raw data histogram Parameters ---------- showContinuum : bool, optional Adds a horizontal line at the continuum. Useful only if normalized to continuum dev : bool secret testing Returns ------- fig : mpl.figure Figure """ ii, jj = [self._quesoOut._config.blueEdge, self._quesoOut._config.redEdge] # if hasattr(self._quesoOut._config, "waveFit"): # wavelambda = self._quesoOut._config.waveFit.magnitude # wavelambda -= wavelambda[self._quesoOut._config.lineCenter] # waveUnit = self._quesoOut._config.waveFit.units # else: # wavelambda = np.arange(self._quesoOut._instrumentObj.dataPrism.shape[2]) # waveUnit = "index" validLabels = self.optLabels[self.vindx] i0Arr = auxAtom.pick_jth_label(validLabels, 0) i0o1Arr = auxAtom.pick_jth_label(validLabels, 0)*10 + auxAtom.pick_jth_label(validLabels, 1) i0o1Lst = np.unique(i0o1Arr) nrows = len(i0o1Lst) ncols = 1 + auxAtom.pick_jth_label(validLabels, 2).max() fig = plt.figure(layout='constrained', figsize=((ncols + 0.2)*3, nrows*3), dpi=300) gs = GridSpec(nrows, ncols + 1, left=0, right=1, top=1, bottom=0, width_ratios=[1 for x in range(ncols)] + [0.2], height_ratios=[1 for x in range(nrows)], figure=fig) raw_max = (np.ceil(np.nanmax(self._quesoOut.prepSquare[self.vfindx, ii:jj+1])*100)/100.)#.compute() raw_min = (np.floor(np.nanmin(self._quesoOut.prepSquare[self.vfindx, ii:jj+1])*100)/100.)#.compute() extent = self._wavelambda[ii], self._wavelambda[jj], raw_min, raw_max panel_bounds = [] bounds_ticker = int(str(i0o1Lst[0])[0]) for j in range(len(i0o1Lst)): i0_indx = np.where(i0o1Arr == i0o1Lst[j])[0] if i0_indx.size <= 1: continue ax0 = plt.subplot(gs[j, 0]) sindx = np.where(i0Arr == i0Arr[i0_indx[0]])[0].astype(np.uint32) dbScore = scoresAtom.calcDaviesBouldin(self._quesoOut.prepSquare[self.vfindx[sindx], ii:jj+1], validLabels[sindx]) dbSciKit = metrics.davies_bouldin_score(self._quesoOut.prepSquare[self.vfindx[sindx], ii:jj+1], validLabels[sindx]) print([dbScore, dbSciKit]) ax0 = self.spectralEntry(ax0, self.vfindx[i0_indx], showContinuum, scores=dbScore) if gs[j,0].is_last_row(): #ax0.set_xlabel(r"$\lambda-\lambda_{0}$ [$\mathrm{\AA}$]") ax0.set_xlabel(r"$\lambda-\lambda_{0}$" + " [{}]".format(self._waveUnit)) ax0.tick_params(labelleft=True) #axR0.tick_params(labelright=False) if not gs[j, 0].is_last_row(): ax0.tick_params(labelbottom=False) if bounds_ticker != int(str(i0o1Lst[j])[0]): trans = mpl.transforms.blended_transform_factory(ax0.transData, fig.transFigure) panel_bounds.append([-extent[0], ax0.get_position().bounds[2], j, trans]) bounds_ticker = int(str(i0o1Lst[j])[0]) o2Arr = auxAtom.pick_jth_label(validLabels[i0_indx], 2).astype(int) o2Lst = np.unique(o2Arr).astype(int) for k in range(len(o2Lst)): ax = plt.subplot(gs[j, k+1]) o2_indx = i0_indx[np.where(o2Arr == o2Lst[k])[0]] #sArr = auxAtom.pick_jth_label(validLabels[o2_indx], 0) #print(sindx) score = None print(np.unique(validLabels[sindx])) if np.unique(validLabels[sindx]).size > 1: score = scoresAtom.calcNeighborSilhouetteScore(self._quesoOut.prepSquare[self.vfindx[sindx], ii:jj+1], validLabels[sindx], point=validLabels[o2_indx[0]]) scikitScore = metrics.silhouette_samples(self._quesoOut.prepSquare[self.vfindx[sindx], ii:jj+1], validLabels[sindx], metric='euclidean') print([score, scikitScore[validLabels[sindx] == validLabels[o2_indx[0]]].mean(), np.median(scikitScore[validLabels[sindx] == validLabels[o2_indx[0]]])]) ax = self.spectralEntry(ax,self.vfindx[o2_indx.astype(np.uint32)], showContinuum, scores=score) if gs[j,k+1].is_last_row(): ax.set_xlabel(r"$\lambda-\lambda_{0}$" + " [{}]".format(self._waveUnit)) else: ax.tick_params(labelbottom=False) ax.tick_params(labelleft=False) # if dev and not gs[j, k+1].is_last_col(): # axR.tick_params(labelright=False) return(fig)
[docs] def spectralEntry(self, ax, indx, showContinuum, scores=None, dev=False, neighbor=None): """ Calculation function for :func:`~queso_cluster.addon.products.Products.clusterProfiles` Parameters ---------- ax : mpl.Axes matplotlib axes to add content to indx : ndarray 1D array of data indexes for a given cluster color : str color string for 2D histogram of raw data. gradient goes as white -> color wavelambda : ndarray 1D array containing the wavelength extent : list List containing the left, right, bottom, top of the content showContinuum : bool Adds a horizontal line at the continuum. Useful only if normalized to continuum scores : float, optional Validation score to be shown in the figure window dev : bool, optional secret testing Returns ------- ax : mpl.Axes Updated axis with all the content added """ ii, jj = [self._quesoOut._config.blueEdge, self._quesoOut._config.redEdge] # raw_dat = self._quesoOut.prepSquare[indx, ii:jj+1] centroid_i = raw_dat.sum(axis=0)/raw_dat.shape[0] if dev: resolvingIndex = scoresAtom.calcSingleResolvingIndex(raw_dat) centroid_min, centroid_max = np.quantile(raw_dat, [0.25, 0.75], axis=0) axR = ax.twinx() axR.set_ylim([-1, 1]) axR.plot(self._wavelambda[ii:jj+1]-self._wavelambda[self._quesoOut._config.lineCenter], resolvingIndex, color='red', linestyle='dashed', linewidth=0.75) ax.plot(self._wavelambda[ii:jj+1]-self._wavelambda[self._quesoOut._config.lineCenter], centroid_min, color='blue', linewidth=0.75) ax.plot(self._wavelambda[ii:jj+1]--self._wavelambda[self._quesoOut._config.lineCenter], centroid_max, color='blue', linewidth=0.75) logger.debug("Resolving Index: {}".format(np.mean(np.abs(resolvingIndex)))) ax.plot(self._wavelambda[ii:jj+1]-self._wavelambda[self._quesoOut._config.lineCenter], centroid_i, color='black', linewidth=0.75) # im = ax.hist2d(raw_dat, bins=[0.01, wavelambda[ii:jj+1]-wavelambda[self.lineCenter]]) temp_im = auxAtom.density_hist2d(raw_dat, 0.01, self._extent[3], self._extent[2]) ww, insty = np.meshgrid(self._wavelambda[ii:jj+1+1]-self._wavelambda[self._quesoOut._config.lineCenter], np.arange(self._extent[2], self._extent[3]+0.01, 0.01)) #print([ww.shape, insty.shape, temp_im.shape]) im = ax.pcolormesh(ww, insty, temp_im.T, cmap=LinearSegmentedColormap.from_list('', ['white', self._quesoOut._config.lineTheme])) ax.axvline(x = 0, linestyle='dashed', color='black') #tindx = self.vindx[0][indx] #xindx = self.vindx[1][indx] #yindx = self.vindx[2][indx] # if self.optLabels.shape == 3: # tindx, xindx, yindx = np.unravel_index(indx, self.optLabels.shape) # labelLst = np.unique(self.optLabels[tindx, xindx, yindx]).astype(int).astype(str) # else: # xindx, yindx = np.unravel_index(indx, self.optLabels.shape) labelLst = np.unique(self.optLabels[np.unravel_index(indx, self.optLabels.shape)]).astype(int).astype(str) commonLabel = [labelLst[0][j] for j in range(len(labelLst[0])) if np.unique([a[j] for a in [list(x) for x in labelLst]]).size == 1] label = "{}{}".format(int("".join(commonLabel)), "X"*(len(labelLst[0]) - len(commonLabel))) ax.annotate("{}".format(label), xy=(0.01, 1-0.05), xycoords='axes fraction', xytext=(0.01, 1-0.05), textcoords='axes fraction', fontfamily='sans-serif', va='center', ha='left') ax.annotate("N={}".format(len(indx)), xy=(0.01, 1-0.1), xycoords='axes fraction', xytext=(0.01, 1-0.1), textcoords='axes fraction', fontfamily='sans-serif', va='center', ha='left') if not (scores is None): ax.annotate("S={:.3f}".format(float(scores)), xy=(0.01, 1-0.15), xycoords='axes fraction', xytext=(0.01, 1-0.15), textcoords='axes fraction', fontfamily='sans-serif', va='center', ha='left') if not (neighbor is None): ax.annotate("N={:d}".format(int(neighbor)), xy=(0.01, 1-0.2), xycoords='axes fraction', xytext=(0.01, 1-0.2), textcoords='axes fraction', fontfamily='sans-serif', va='center', ha='left') if showContinuum: ax.axhline(y = 1, color='black', linestyle='dotted') wdiff = np.floor(np.abs(self._wavelambda[jj] - self._wavelambda[ii])) wMajor = 10**np.floor(np.log10(wdiff)) wMajor *= np.ceil(wdiff/wMajor)/4. ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(base=wMajor)) ax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(base=wMajor/2.)) return(ax)