def load_qa(self): cam = self.selected_arm + str(self.selected_spectrograph) mergedqa = QLFModels().get_output(self.selected_process_id, cam) gen_info = mergedqa['GENERAL_INFO'] ra = gen_info['RA'] dec = gen_info['DEC'] check_spectra = mergedqa['TASKS']['CHECK_SPECTRA'] skycont = check_spectra['METRICS'] sky = skycont['SKYCONT_FIBER'] skyfibers = gen_info['SKY_FIBERID'] nrg = check_spectra['PARAMS']['SKYCONT_NORMAL_RANGE'] wrg = check_spectra['PARAMS']['SKYCONT_WARN_RANGE'] current_exposures = [check_spectra['METRICS']['SKYCONT']] program = gen_info['PROGRAM'].upper() reference_exposures = check_spectra['PARAMS']['SKYCONT_' + program + '_REF'] ra_sky = [ra[i % 500] for i in skyfibers] dec_sky = [dec[i % 500] for i in skyfibers] my_palette = get_palette("RdYlBu_r") skc_tooltips = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">SKY CONT: </span> <span style="font-size: 1vw; color: #515151;">@skycont</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@ra</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 1vw; color: #515151;">@dec</span> </div> </div> """ url = "http://legacysurvey.org/viewer?ra=@ra&dec=@dec&zoom=16&layer=decals-dr5" qlf_fiberid = np.arange(0, 500) # sky continuum per sky fiber averaged over two continuum regions, # 'n' is number of sky fibers ra_not, dec_not = [], [] fiber_mod = [] for fiber in skyfibers: fiber_mod.append(fiber % 500) for i in range(500): if i not in fiber_mod: ra_not.append(ra[i]) dec_not.append(dec[i]) source = ColumnDataSource( data={ 'skycont': sky, 'delta_skycont': np.array(sky) - reference_exposures, 'fiberid': skyfibers, 'ra': ra_sky, 'dec': dec_sky }) source_not = ColumnDataSource(data={ 'ra': ra_not, 'dec': dec_not, 'skycont': [''] * len(dec_not) }) low, high = wrg mapper = LinearColorMapper( palette=my_palette, low=low, #np.min(sky), high=high, #np.max(sky), nan_color='darkgrey') radius = 0.0165 # 0.013 radius_hover = 0.02 # 0.015 # centralize wedges in plots: ra_center = 0.5 * (max(ra) + min(ra)) dec_center = 0.5 * (max(dec) + min(dec)) xrange_wedge = Range1d(start=ra_center + .95, end=ra_center - .95) yrange_wedge = Range1d(start=dec_center + .82, end=dec_center - .82) wedge_plot = Plot2d(x_range=xrange_wedge, y_range=yrange_wedge, x_label="RA", y_label="DEC", tooltip=skc_tooltips, title="SKY_CONT", width=500, height=380, yscale="auto").wedge( source, x='ra', y='dec', field='delta_skycont', mapper=mapper, ).wedge( source_not, x='ra', y='dec', ).plot taptool = wedge_plot.select(type=TapTool) taptool.callback = OpenURL(url=url) # infos info_col = Title().write_description('skycont') # Prepare tables keynames = ["SKYCONT" for i in range(len(current_exposures))] table = Table().single_table(keynames, current_exposures, reference_exposures, nrg, wrg) layout = column(info_col, Div(), table, Div(), column(wedge_plot, sizing_mode='scale_both', css_classes=["main-one"]), css_classes=["display-grid"]) # End of Bokeh Block return file_html(layout, CDN, "SKYCONT")
def load_qa(self): cam = self.selected_arm + str(self.selected_spectrograph) mergedqa = QLFModels().get_output(self.selected_process_id, cam) gen_info = mergedqa['GENERAL_INFO'] flavor = mergedqa['FLAVOR'] if flavor == "science": ra = gen_info['RA'] dec = gen_info['DEC'] check_ccds = mergedqa['TASKS']['CHECK_CCDs'] xwsigma = check_ccds['METRICS']['XWSIGMA'] xw_amp = check_ccds['METRICS']['XWSIGMA_AMP'] xw_fib = check_ccds['METRICS']['XWSIGMA_FIB'] nrg = check_ccds['PARAMS']['XWSIGMA_NORMAL_RANGE'] wrg = check_ccds['PARAMS']['XWSIGMA_WARN_RANGE'] obj_type = sort_obj(gen_info) # [""]*500 if mergedqa['FLAVOR'].upper() == 'SCIENCE': program = mergedqa['GENERAL_INFO']['PROGRAM'].upper() program_prefix = '_' + program else: program_prefix = '' xw_ref = check_ccds['PARAMS']['XWSIGMA' + program_prefix + '_REF'] xsigma = xw_fib[0] wsigma = xw_fib[1] delta_rg = wrg[1] - wrg[0] hist_rg = (wrg[0] - 0.1 * delta_rg, wrg[1] + 0.1 * delta_rg) my_palette = get_palette("RdYlBu_r") xfiber = np.arange(len(xsigma)) wfiber = np.arange(len(wsigma)) if mergedqa['FLAVOR'].upper() != 'SCIENCE': ra = np.full(500, np.nan) dec = np.full(500, np.nan) source = ColumnDataSource( data={ 'x1': ra, 'y1': dec, 'xsigma': xsigma, 'wsigma': wsigma, 'delta_xsigma': np.array(xsigma) - xw_ref[0], 'delta_wsigma': np.array(wsigma) - xw_ref[1], 'xref': [xw_ref[0]] * len(xsigma), 'wref': [xw_ref[1]] * len(xsigma), 'xfiber': xfiber, 'wfiber': wfiber, 'OBJ_TYPE': obj_type, 'left': np.arange(0, 500) - 0.4, 'right': np.arange(0, 500) + 0.4, 'bottom': [0] * 500 }) xsigma_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">XSigma: </span> <span style="font-size: 1vw; color: #515151">@xsigma</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Reference: </span> <span style="font-size: 1vw; color: #515151">@xref</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 1vw; color: #515151;">@OBJ_TYPE</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@x1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 1vw; color: #515151;">@y1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">FIBER ID: </span> <span style="font-size: 1vw; color: #515151;">@xfiber</span> </div> </div> """ wsigma_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">WSigma: </span> <span style="font-size: 1vw; color: #515151">@wsigma</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Reference: </span> <span style="font-size: 1vw; color: #515151">@wref</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 1vw; color: #515151;">@OBJ_TYPE</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@x1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 1vw; color: #515151;">@y1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">FIBER ID: </span> <span style="font-size: 1vw; color: #515151;">@wfiber</span> </div> </div> """ url = "http://legacysurvey.org/viewer?ra=@ra&dec=@dec&zoom=16&layer=decals-dr5" # determining the position of selected cam fibers: obj_type = sort_obj(gen_info) # --------------------------------- if flavor == "science": # axes limit xmin, xmax = [min(ra[:]), max(ra[:])] ymin, ymax = [min(dec[:]), max(dec[:])] xfac, yfac = [(xmax - xmin) * 0.06, (ymax - ymin) * 0.06] left, right = xmin - xfac, xmax + xfac bottom, top = ymin - yfac, ymax + yfac low, high = wrg xmapper = LinearColorMapper(palette=my_palette, low=low, high=high, nan_color="darkgrey") wmapper = LinearColorMapper(palette=my_palette, low=low, high=high, nan_color="darkgrey") # ============ # XSIGMA WEDGE radius = 0.0165 radius_hover = 0.02 # centralize wedges in plots: ra_center = 0.5 * (max(ra) + min(ra)) dec_center = 0.5 * (max(dec) + min(dec)) xrange_wedge = Range1d(start=ra_center + .95, end=ra_center - .95) yrange_wedge = Range1d(start=dec_center + .82, end=dec_center - .82) wedge_plot_x = Plot2d(x_range=xrange_wedge, y_range=yrange_wedge, x_label="RA", y_label="DEC", tooltip=xsigma_tooltip, title="XSIGMA", width=500, height=380, yscale="auto").wedge( source, x='x1', y='y1', field='delta_xsigma', mapper=xmapper, colorbar_title='xsigma').plot taptool = wedge_plot_x.select(type=TapTool) taptool.callback = OpenURL(url=url) # ============ # WSIGMA WEDGE wedge_plot_w = Plot2d(x_range=xrange_wedge, y_range=yrange_wedge, x_label="RA", y_label="DEC", tooltip=wsigma_tooltip, title="WSIGMA", width=500, height=380, yscale="auto").wedge( source, x='x1', y='y1', field='delta_wsigma', mapper=wmapper, colorbar_title='wsigma').plot taptool = wedge_plot_w.select(type=TapTool) taptool.callback = OpenURL(url=url) # ================================ # Stat histogram # x_fiber_hist d_yplt = (max(xsigma) - min(xsigma)) * 0.1 yrange = [0, max(xsigma) + d_yplt] xhist = Plot2d( yrange, x_label="Fiber number", y_label="X std dev (number of pixels)", tooltip=xsigma_tooltip, title="", width=600, height=300, yscale="auto", hover_mode="vline", ).quad( source, top='xsigma', ) # w_fiber_hist d_yplt = (max(wsigma) - min(wsigma)) * 0.1 yrange = [0, max(wsigma) + d_yplt] whist = Plot2d( yrange, x_label="Fiber number", y_label="W std dev (number of pixels)", tooltip=xsigma_tooltip, title="", width=600, height=300, yscale="auto", hover_mode="vline", ).quad( source, top='wsigma', ) # ================================ # Stat histogram def histpar(yscale, hist): if yscale == 'log': ylabel = "Frequency + 1" yrange = (1, 11**(int(np.log10(max(hist))) + 1)) bottomval = 'bottomplusone' histval = 'histplusone' else: ylabel = "Frequency" yrange = (0.0 * max(hist), 1.1 * max(hist)) bottomval = 'bottom' histval = 'hist' return [ylabel, yrange, bottomval, histval] xhistlabel = "XSIGMA" yscale = "auto" hist_tooltip_x = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Frequency: </span> <span style="font-size: 1vw; color: #515151">@hist</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">XSIGMA: </span> <span style="font-size: 1vw; color: #515151;">[@left, @right]</span> </div> </div> """ hist, edges = np.histogram(xsigma, 'sqrt') source_hist = ColumnDataSource( data={ 'hist': hist, 'histplusone': hist + 1, 'bottom': [0] * len(hist), 'bottomplusone': [1] * len(hist), 'left': edges[:-1], 'right': edges[1:] }) ylabel, yrange, bottomval, histval = histpar(yscale, hist) p_hist_x = Plot2d( x_label=xhistlabel, y_label=ylabel, tooltip=hist_tooltip_x, title="", width=600, height=300, yscale="auto", y_range=yrange, x_range=(hist_rg[0] + xw_ref[0], hist_rg[1] + xw_ref[0]), hover_mode="vline", ).quad( source_hist, top=histval, bottom=bottomval, line_width=0.4, ) # Histogram 2 xhistlabel = "WSIGMA" hist_tooltip_w = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Frequency: </span> <span style="font-size: 1vw; color: #515151">@hist</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">WSIGMA: </span> <span style="font-size: 1vw; color: #515151;">[@left, @right]</span> </div> </div> """ hist, edges = np.histogram(wsigma, 'sqrt') source_hist = ColumnDataSource( data={ 'hist': hist, 'histplusone': hist + 1, 'bottom': [0] * len(hist), 'bottomplusone': [1] * len(hist), 'left': edges[:-1], 'right': edges[1:] }) ylabel, yrange, bottomval, histval = histpar(yscale, hist) yrangew = yrange p_hist_w = Plot2d( x_label=xhistlabel, y_label=ylabel, tooltip=hist_tooltip_w, title="", width=600, height=300, yscale="auto", y_range=yrange, x_range=(hist_rg[0] + xw_ref[1], hist_rg[1] + xw_ref[1]), hover_mode="vline", ).quad( source_hist, top=histval, bottom=bottomval, line_width=0.8, ) # -------------------------------------------------------------- # vlines ranges: bname = 'XWSIGMA' for ialert in nrg: # par[bname+'_NORMAL_RANGE']: spans = Span(location=ialert + xw_ref[0], dimension='height', line_color='green', line_dash='dashed', line_width=2) p_hist_x.add_layout(spans) my_label = Label(x=ialert + xw_ref[0], y=yrange[-1] / 2.2, y_units='data', text='Normal Range', text_color='green', angle=np.pi / 2.) p_hist_x.add_layout(my_label) for ialert in wrg: # par[bname+'_WARN_RANGE']: spans = Span(location=ialert + xw_ref[0], dimension='height', line_color='tomato', line_dash='dotdash', line_width=2) p_hist_x.add_layout(spans) my_label = Label(x=ialert + xw_ref[0], y=yrange[-1] / 2.2, y_units='data', text='Warning Range', text_color='tomato', angle=np.pi / 2.) p_hist_x.add_layout(my_label) for ialert in nrg: # par[bname+'_NORMAL_RANGE']: spans = Span(location=ialert + xw_ref[1], dimension='height', line_color='green', line_dash='dashed', line_width=2) p_hist_w.add_layout(spans) my_label = Label(x=ialert + xw_ref[1], y=yrangew[-1] / 2.2, y_units='data', text='Normal Range', text_color='green', angle=np.pi / 2.) p_hist_w.add_layout(my_label) for ialert in wrg: # par[bname+'_WARN_RANGE']: spans = Span(location=ialert + xw_ref[1], dimension='height', line_color='tomato', line_dash='dotdash', line_width=2) p_hist_w.add_layout(spans) my_label = Label(x=ialert + xw_ref[1], y=yrangew[-1] / 2.2, y_units='data', text='Warning Range', text_color='tomato', angle=np.pi / 2.) p_hist_w.add_layout(my_label) # amp 1 xamp = Patch().plot_amp( dz=xw_amp[0], refexp=[xw_ref[0]] * 4, name="XSIGMA AMP", description="X standard deviation per Amp (number of pixels)", wrg=wrg) # amp 2 wamp = Patch().plot_amp( dz=xw_amp[1], refexp=[xw_ref[1]] * 4, name="WSIGMA AMP", description="W standard deviation per Amp (number of pixels)", wrg=wrg) # ------------------------------------------------------------------------- info_col = Title().write_description('xwsigma') current_exposures = check_ccds['METRICS']['XWSIGMA'] alert_x = Table().alert_table(nrg, wrg) alert_w = Table().alert_table(nrg, wrg) if flavor == 'science': program = gen_info['PROGRAM'].upper() reference_exposures = check_ccds['PARAMS']['XWSIGMA_' + program + '_REF'] keynames = ["XSIGMA"] x_metric = Table().reference_table(keynames, [current_exposures[0]], [reference_exposures[0]]) keynames = ["WSIGMA"] w_metric = Table().reference_table(keynames, [current_exposures[1]], [reference_exposures[1]]) layout = column( info_col, widgetbox(Div(), css_classes=["tableranges"]), widgetbox( Div(text= '<h2 align=center style="text-align:center;"> XSIGMA </h2>' )), widgetbox( Div(text= '<h2 align=center style="text-align:center;"> WSIGMA </h2>' )), x_metric, w_metric, alert_x, alert_w, column(wedge_plot_x, sizing_mode='scale_both'), column(wedge_plot_w, sizing_mode='scale_both'), column(xhist, sizing_mode='scale_both'), column(whist, sizing_mode='scale_both'), column(p_hist_x, sizing_mode='scale_both'), column(p_hist_w, sizing_mode='scale_both'), column(xamp, sizing_mode='scale_both'), column(wamp, sizing_mode='scale_both'), css_classes=["display-grid"], sizing_mode='scale_width') else: reference_exposures = check_ccds['PARAMS']['XWSIGMA_REF'] keynames = ["XSIGMA"] x_metric = Table().reference_table(keynames, [current_exposures[0]], [reference_exposures[0]]) keynames = ["WSIGMA"] w_metric = Table().reference_table(keynames, [current_exposures[1]], [reference_exposures[1]]) layout = column( info_col, widgetbox(Div(), css_classes=["tableranges"]), widgetbox( Div(text= '<h2 align=center style="text-align:center;"> XSIGMA </h2>' )), widgetbox( Div(text= '<h2 align=center style="text-align:center;"> WSIGMA </h2>' )), x_metric, w_metric, alert_x, alert_w, column(xhist, sizing_mode='scale_both'), column(whist, sizing_mode='scale_both'), column(p_hist_x, sizing_mode='scale_both'), column(p_hist_w, sizing_mode='scale_both'), column(xamp, sizing_mode='scale_both'), column(wamp, sizing_mode='scale_both'), css_classes=["display-grid"], sizing_mode='scale_width') return file_html(layout, CDN, "XWSIGMA")
def plot_amp(self, dz, refexp, name="", font_size="1.2vw", description="", nrg=[], wrg=[], status_plot=False): ''' Initializing AMP plot ''' ztext, cbarformat = self.set_amp(dz) dx = [0, 1, 0, 1] dy = [1, 1, 0, 0] zvalid = np.array([x if x > -999 else np.nan for x in dz]) data_source = dict( x=dx, y=dy, z=dz, zvalid=zvalid, ref=["{:.2f}".format(x) for x in refexp], zdiff=zvalid - np.array(refexp), y_offset1=[i + 0.15 for i in dy], y_offset2=[i - 0.10 for i in dy], amp=['AMP %s' % i for i in range(1, 5)], amp_number=['%s' % i for i in range(1, 5)], ztext=ztext, ) if status_plot: text_val = 'status' color_status = ['green', 'darkgrey', 'yellow', 'red'] color = { 'NaN': 'darkgrey', 'NORMAL': 'green', 'WARNING': 'yellow', 'ALARM': 'red', } status = [ self.val_status(x, nrg=nrg, wrg=wrg) for x in zvalid - np.array(refexp) ] color_status = [ color[self.val_status(x, nrg=nrg, wrg=wrg)] for x in zvalid - np.array(refexp) ] fill_color = "color_status" data_source.update({ 'status': status, 'color_status': color_status, }) fill_alpha = 0.8 if not status_plot: text_val = 'ztext' cmap = get_palette("RdBu_r") mapper = LinearColorMapper(palette=cmap, low=wrg[0], high=wrg[1], nan_color="darkgrey") formatter = PrintfTickFormatter(format=cbarformat) color_bar = ColorBar(color_mapper=mapper, major_label_text_align='left', major_label_text_font_size='10pt', label_standoff=2, location=(0, 0), formatter=formatter, title="(Val-Ref)", title_standoff=15, title_text_baseline="alphabetic") fill_color = {'field': 'zdiff', 'transform': mapper} fill_alpha = 0.9 cmap_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">AMP: </span> <span style="font-size: 1vw; color: #515151;">@amp_number</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">counts: </span> <span style="font-size: 1vw; color: #515151">@text_val</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Reference: </span> <span style="font-size: 1vw; color: #515151;">@ref</span> </div> </div> """.replace("counts:", name.replace("_AMP", "") + ":").replace( "text_val", text_val) hover = HoverTool(tooltips=cmap_tooltip) p = Figure(title=name, tools=[hover], x_range=list([-0.5, 1.5]), y_range=list([-0.5, 1.5]), plot_width=450, plot_height=400) source = ColumnDataSource(data=data_source) text_props = { "source": source, "angle": 0, "color": "black", "text_color": "black", "text_align": "center", "text_baseline": "middle" } p.rect("x", "y", .98, .98, 0, source=source, fill_color=fill_color, fill_alpha=fill_alpha) p.text(x="x", y="y_offset1", text="amp", text_font_size="2vw", **text_props) p.text(x="x", y="y_offset2", text="ztext", text_font_style="bold", text_font_size="2.5vw", **text_props) if not status_plot: p.add_layout(color_bar, 'right') # Format: p.xaxis.axis_label_text_font_size = font_size p.legend.label_text_font_size = font_size p.title.text_font_size = font_size p.xaxis.axis_label = description # Clear Axis: p.grid.grid_line_color = None p.outline_line_color = None p.axis.minor_tick_line_color = None p.axis.major_label_text_font_size = '0pt' p.yaxis.major_label_text_font_size = '0pt' p.xaxis.major_tick_line_color = None p.xaxis.minor_tick_line_color = None p.yaxis.major_tick_line_color = None p.yaxis.minor_tick_line_color = None p.yaxis.visible = False p.xaxis.visible = True p.axis.clear return p
def load_qa(self): cam = self.selected_arm+str(self.selected_spectrograph) mergedqa = QLFModels().get_output(self.selected_process_id, cam) check_spectra = mergedqa['TASKS']['CHECK_SPECTRA'] gen_info = mergedqa['GENERAL_INFO'] ra = gen_info['RA'] dec = gen_info['DEC'] nrg = check_spectra['PARAMS']['PEAKCOUNT_NORMAL_RANGE'] wrg = check_spectra['PARAMS']['PEAKCOUNT_WARN_RANGE'] current_exposures = [check_spectra['METRICS']['PEAKCOUNT']] program = gen_info['PROGRAM'].upper() reference_exposures = check_spectra['PARAMS']['PEAKCOUNT_' + program + '_REF'] obj_type = sort_obj(gen_info) my_palette = get_palette("RdYlBu_r") peak_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">PEAKCOUNT: </span> <span style="font-size: 1vw; color: #515151">@peakcount_fib</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@x1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 1vw; color: #515151;">@y1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 1vw; color: #515151;">@OBJ_TYPE</span> </div> </div> """ url = "http://legacysurvey.org/viewer?ra=@ra&dec=@dec&zoom=16&layer=decals-dr5" qlf_fiberid = np.arange(0, 500) peak_hover = HoverTool(tooltips=peak_tooltip) peakcount_fib = check_spectra['METRICS']['PEAKCOUNT_FIB'] source = ColumnDataSource(data={ 'x1': ra, 'y1': dec, 'peakcount_fib': peakcount_fib, 'delta_peakcount_fib': np.array(peakcount_fib)-reference_exposures, 'QLF_FIBERID': qlf_fiberid, 'OBJ_TYPE': obj_type, }) low, high = wrg mapper = LinearColorMapper(palette=my_palette, low=low, #0.98*np.min(peakcount_fib), high=high, #1.02*np.max(peakcount_fib)) nan_color='darkgrey') radius = 0.0165 radius_hover = 0.02 # centralize wedges in plots: ra_center=0.5*(max(ra)+min(ra)) dec_center=0.5*(max(dec)+min(dec)) xrange_wedge = Range1d(start=ra_center + .95, end=ra_center-.95) yrange_wedge = Range1d(start=dec_center+.82, end=dec_center-.82) # axes limit xmin, xmax = [min(gen_info['RA'][:]), max(gen_info['RA'][:])] ymin, ymax = [min(gen_info['DEC'][:]), max(gen_info['DEC'][:])] xfac, yfac = [(xmax-xmin)*0.06, (ymax-ymin)*0.06] left, right = xmin - xfac, xmax+xfac bottom, top = ymin-yfac, ymax+yfac wedge_plot = Plot2d( x_range=xrange_wedge, y_range=yrange_wedge, x_label="RA", y_label="DEC", tooltip=peak_tooltip, title="PEAKCOUNT", width=500, height=380, ).wedge( source, x='x1', y='y1', field='delta_peakcount_fib', mapper=mapper, ).plot info_col = Title().write_description('skypeak') # ================================ # histogram hist_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Frequency: </span> <span style="font-size: 1vw; color: #515151">@hist</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Peakcount: </span> <span style="font-size: 1vw; color: #515151;">[@left, @right]</span> </div> </div> """ hist, edges = np.histogram(peakcount_fib, bins="sqrt") source_hist = ColumnDataSource(data={ 'hist': hist, 'histplusone': hist+1, 'bottom': [0] * len(hist), 'bottomplusone': [1]*len(hist), 'left': edges[:-1], 'right': edges[1:] }) p_hist = Plot2d( y_range=(1, 11**(int(np.log10(max(hist)))+1)), x_label='PEAKCOUNT', y_label='Frequency + 1', tooltip=hist_tooltip, title="", width=550, height=300, yscale="log", hover_mode="vline", ).quad( source_hist, top='histplusone', bottom='bottomplusone', line_width=1, ) # Prepare tables keynames = ["PEAKCOUNT" for i in range(len(current_exposures))] metric = Table().reference_table(keynames, current_exposures, reference_exposures) alert = Table().alert_table(nrg, wrg) layout = column(info_col, Div(), metric, alert, column(wedge_plot, sizing_mode='scale_both'), column(p_hist, sizing_mode='scale_both'), css_classes=["display-grid"]) return file_html(layout, CDN, "SKYPEAK")
def wedge_plot(self, wedge_arm, fmap, common_source=None, sigma_kind='x'): ra_center = fmap.exposure.telra dec_center = fmap.exposure.teldec fiber_tooltip = """ <div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">SIGMA: </span> <span style="font-size: 13px; color: #515151">@y</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 13px; color: #515151;">@ra</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 13px; color: #515151;">@dec</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 13px; color: #515151;">@OBJ_TYPE</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">CAM: </span> <span style="font-size: 13px; color: #515151;">@cam</span> </div> """ fiber_tooltip = fiber_tooltip.replace('SIGMA:', '%sSIGMA:' % sigma_kind.upper()) hover = HoverTool(tooltips=fiber_tooltip) my_palette = get_palette("bwr") source = common_source process_id = self.selected_process_id joblist = [ entry.camera.camera for entry in Job.objects.filter(process_id=process_id) ] if len(joblist) > 0: cam = joblist[0] mergedqa = QLFModels().get_output(self.selected_process_id, cam) warn_range = mergedqa['TASKS']['CHECK_CCDs']['PARAMS'][ 'XWSIGMA_WARN_RANGE'] arg_kind = {'x': 0, 'w': 1} refvalue = mergedqa['TASKS']['CHECK_CCDs']['PARAMS'][ 'XWSIGMA_REF'][arg_kind[sigma_kind]] rng_warn_min, rng_warn_max = warn_range[0] + \ refvalue, warn_range[1] + refvalue sigma = source.data['{}'.format(sigma_kind)] rng_min, rng_max = np.nanmin(sigma), np.nanmax(sigma) rng = rng_max - rng_min if np.isnan(rng_min) or np.isnan(rng_max): fill_color = 'lightgray' else: mapper = LinearColorMapper(palette=my_palette, nan_color='lightgray', low=rng_warn_min, high=rng_warn_max) fill_color = {'field': '%s' % (sigma_kind), 'transform': mapper} radius = 0.017 radius_hover = 0.018 xrange = Range1d(start=ra_center + 2, end=ra_center - 2) yrange = Range1d(start=dec_center + 1.8, end=dec_center - 1.8) p = Figure(title='FOCUS %s (ARM %s)' % (sigma_kind.upper(), wedge_arm), x_axis_label='RA', y_axis_label='DEC', plot_width=600, plot_height=600, tools=[ hover, "box_zoom,pan,wheel_zoom,reset,lasso_select,crosshair" ], active_drag="box_zoom", x_range=xrange, y_range=yrange) p.title.align = 'center' p.circle('ra', 'dec', source=source, name="data", radius=radius, fill_color=fill_color, line_color='black', line_width=0.4, hover_line_color='red') p.circle('ra', 'dec', source=source, name="data", radius=radius_hover, hover_fill_color=fill_color, fill_color=None, line_color=None, line_width=3, hover_line_color='orange') if 'mapper' in locals(): cbar = Figure( height=p.plot_height, width=120, toolbar_location=None, min_border=0, outline_line_color=None, ) color_bar = ColorBar(color_mapper=mapper, label_standoff=14, major_label_text_font_style="bold", padding=26, major_label_text_align='right', major_label_text_font_size="10pt", location=(0, 0)) cbar.title.align = 'center' cbar.title.text_font_size = '10pt' cbar.add_layout(color_bar, 'left') p_list = [cbar, p] else: p_list = [p] return p_list
def wedge_plot(self, wedge_arm, fmap, common_source=None, sigma_kind='x'): ra_center = fmap.exposure.telra dec_center = fmap.exposure.teldec fiber_tooltip = """ <div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">RESIDUAL SNR: </span> <span style="font-size: 13px; color: #515151">@y</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 13px; color: #515151;">@ra</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 13px; color: #515151;">@dec</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 13px; color: #515151;">@OBJ_TYPE</span> </div> <div> <span style="font-size: 12px; font-weight: bold; color: #303030;">CAM: </span> <span style="font-size: 13px; color: #515151;">@cam</span> </div> """ fiber_tooltip = fiber_tooltip.replace('@y', '@hover') hover = HoverTool(tooltips=fiber_tooltip) my_palette = get_palette("bwr") # "seismic")#"RdYlBu_r")#"viridis") source = common_source sigma = source.data['resids'] # ['{}_'.format(sigma_kind) +wedge_arm] rng_min, rng_max = np.nanmin(sigma), np.nanmax(sigma) rng = rng_max-rng_min if np.isnan(rng_min) or np.isnan(rng_max): fill_color = 'lightgray' else: mapper = LinearColorMapper(palette=my_palette, nan_color='darkgrey', low=-0.2, high=0.2) fill_color = {'field': 'resids', 'transform': mapper} radius = 0.017 radius_hover = 0.018 xrange = Range1d(start=ra_center + 2, end=ra_center-2) yrange = Range1d(start=dec_center+1.8, end=dec_center-1.8) p = Figure(title='SNR (ARM {})'.format(wedge_arm), x_axis_label='RA', y_axis_label='DEC', plot_width=600, plot_height=600, tools=[hover, "pan,wheel_zoom,reset,box_zoom,crosshair"], active_drag="box_zoom", x_range=xrange, y_range=yrange ) p.title.align = 'center' p.circle('ra', 'dec', source=source, name="data", radius=radius, fill_color=fill_color, line_color='black', line_width=0.4, hover_line_color='red') p.circle('ra', 'dec', source=source, name="data", radius=radius_hover, hover_fill_color=fill_color, fill_color=None, line_color=None, line_width=3, hover_line_color='orange') if 'mapper' in locals(): cbar = Figure(height=p.plot_height, width=140, toolbar_location=None, min_border=0, outline_line_color=None, ) color_bar = ColorBar(color_mapper=mapper, label_standoff=14, major_label_text_font_style="bold", padding=26, major_label_text_align='right', major_label_text_font_size="10pt", location=(0, 0)) cbar.title.align = 'center' cbar.title.text_font_size = '10pt' cbar.add_layout(color_bar, 'left') p_list = [cbar, p] else: p_list = [p] return p_list
def load_qa(self): cam = self.selected_arm + str(self.selected_spectrograph) mergedqa = QLFModels().get_output(self.selected_process_id, cam) # list of available object in petal objlist = mergedqa["TASKS"]["CHECK_SPECTRA"]["METRICS"]["OBJLIST"] if 'SKY' in objlist: objlist.remove('SKY') gen_info = mergedqa['GENERAL_INFO'] ra = gen_info['RA'] dec = gen_info['DEC'] check_spectra = mergedqa['TASKS']['CHECK_SPECTRA'] snr = check_spectra['METRICS'] nrg = check_spectra['PARAMS']['FIDSNR_TGT_NORMAL_RANGE'] wrg = check_spectra['PARAMS']['FIDSNR_TGT_WARN_RANGE'] # Object identification in fibers: obj_fiber = sort_obj(gen_info) qlf_obj = ['ELG', 'LRG', 'QSO', 'STAR'] avobj = ['STAR' if x == 'STD' else x for x in objlist] obj_idx = {} for o in qlf_obj: try: obj_idx.update({o: avobj.index(o)}) except: obj_idx.update({o: None}) try: exptime = gen_info['EXPTIME'] name_warn = '' except: exptime = 1000 name_warn = ' (exptime fixed)' # Sort objects for QLF: obj_idx = {} for o in qlf_obj: try: obj_idx.update({o: avobj.index(o)}) except: obj_idx.update({o: None}) def good_idx(mag, snr): # Filtering measurements with good SNR & good MAG # Treating None (inf and Nan already treated in db) mag_2 = np.array([-9998 if x is None else x for x in mag]) snr_2 = np.array([-9998 if x is None else x for x in snr]) idx = np.arange(len(snr_2)) # Filtering values with good mag AND snr return list(idx[(mag_2 > -999) & (snr_2 > 0)]) # Treating bad snr and mag mag_snr = {} for o in avobj: snr_ql, mag_ql = snr['SNR_MAG_TGT'][obj_idx[o]] idx = good_idx(mag_ql, snr_ql) x = [mag_ql[i] for i in idx] y = [snr_ql[i] for i in idx] mag_snr.update({o: [y, x]}) # Preparing xy_plot data: if obj_idx['ELG'] is not None: elg_snr = mag_snr['ELG'] if obj_idx['LRG'] is not None: lrg_snr = mag_snr['LRG'] if obj_idx['QSO'] is not None: qso_snr = mag_snr['QSO'] if obj_idx['STAR'] is not None: star_snr = mag_snr['STAR'] #lrg_snr = mag_snr['LRG'] def fit_func(xdata, coeff): """ astro fit """ r1 = 0.0 # read noise a, b = coeff x = np.linspace(min(xdata), max(xdata), 1000) Flux = 10**(-0.4 * (x - 22.5)) y = a * Flux * exptime / np.sqrt(a * Flux * exptime + b * exptime + r1**2) return x, y data_model = { 'x': [], 'y': [], 'y2': [], 'fiber_id': [], 'ra': [], 'dec': [], } elg = ColumnDataSource(data=data_model.copy()) lrg = ColumnDataSource(data=data_model.copy()) qso = ColumnDataSource(data=data_model.copy()) star = ColumnDataSource(data=data_model.copy()) data_fit = { 'x': [], 'y': [], 'y2': [], 'fiber_id': [], 'ra': [], 'dec': [] } elg_fit = ColumnDataSource(data=data_fit.copy()) lrg_fit = ColumnDataSource(data=data_fit.copy()) qso_fit = ColumnDataSource(data=data_fit.copy()) star_fit = ColumnDataSource(data=data_fit.copy()) if obj_idx['ELG'] is not None: elg.data['x'] = elg_snr[1] elg.data['y'] = np.array(elg_snr[0]) elg.data['y2'] = np.array(elg_snr[0])**2 elg.data['fiber_id'] = gen_info['ELG_FIBERID'] elg.data['ra'] = [ra[i % 500] for i in gen_info['ELG_FIBERID']] elg.data['dec'] = [dec[i % 500] for i in gen_info['ELG_FIBERID']] xfit, yfit = fit_func(elg_snr[1], snr['FITCOEFF_TGT'][obj_idx['ELG']]) elg_fit.data['x'] = xfit elg_fit.data['y'] = np.array(yfit) elg_fit.data['y2'] = np.array(yfit)**2 for key in ['fiber_id', 'ra', 'dec']: elg_fit.data[key] = [''] * len(yfit) if obj_idx['LRG'] is not None: lrg.data['x'] = lrg_snr[1] lrg.data['y'] = np.array(lrg_snr[0]) lrg.data['y2'] = np.array(lrg_snr[0])**2 lrg.data['fiber_id'] = gen_info['LRG_FIBERID'] lrg.data['ra'] = [ra[i % 500] for i in gen_info['LRG_FIBERID']] lrg.data['dec'] = [dec[i % 500] for i in gen_info['LRG_FIBERID']] xfit, yfit = fit_func(lrg_snr[1], snr['FITCOEFF_TGT'][obj_idx['LRG']]) lrg_fit.data['x'] = xfit lrg_fit.data['y'] = np.array(yfit) lrg_fit.data['y2'] = np.array(yfit)**2 for key in ['fiber_id', 'ra', 'dec']: lrg_fit.data[key] = [''] * len(yfit) if obj_idx['QSO'] is not None: qso.data['x'] = qso_snr[1] qso.data['y'] = np.array(qso_snr[0]) qso.data['y2'] = np.array(qso_snr[0])**2 qso.data['fiber_id'] = gen_info['QSO_FIBERID'] qso.data['ra'] = [ra[i % 500] for i in gen_info['QSO_FIBERID']] qso.data['dec'] = [dec[i % 500] for i in gen_info['QSO_FIBERID']] xfit, yfit = fit_func(qso_snr[1], snr['FITCOEFF_TGT'][obj_idx['QSO']]) qso_fit.data['x'] = xfit qso_fit.data['y'] = np.array(yfit) qso_fit.data['y2'] = np.array(yfit)**2 for key in ['fiber_id', 'ra', 'dec']: qso_fit.data[key] = [''] * len(yfit) if obj_idx['STAR'] is not None: star.data['x'] = star_snr[1] star.data['y'] = np.array(star_snr[0]) star.data['y2'] = np.array(star_snr[0])**2 star.data['fiber_id'] = gen_info['STAR_FIBERID'] star.data['ra'] = [ra[i % 500] for i in gen_info['STAR_FIBERID']] star.data['dec'] = [dec[i % 500] for i in gen_info['STAR_FIBERID']] xfit, yfit = fit_func(star_snr[1], snr['FITCOEFF_TGT'][obj_idx['STAR']]) star_fit.data['x'] = xfit star_fit.data['y'] = np.array(yfit) star_fit.data['y2'] = np.array(yfit)**2 for key in ['fiber_id', 'ra', 'dec']: star_fit.data[key] = [''] * len(yfit) html_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">SNR: </span> <span style="font-size: 1vw; color: #515151;">@y</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DECAM_{}: </span> <span style="font-size: 1vw; color: #515151;">@x</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Fiber ID: </span> <span style="font-size: 1vw; color: #515151;">@fiber_id</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@ra</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Dec: </span> <span style="font-size: 1vw; color: #515151">@dec</span> </div> </div> """.format(str(self.selected_arm).upper()) url = "http://legacysurvey.org/viewer?ra=@ra&dec=@dec&zoom=16&layer=decals-dr5" elg_plot = Plot2d( x_label="DECAM_{}".format(str(self.selected_arm).upper()), y_label="MEDIAN SNR^2", tooltip=html_tooltip, title="ELG", width=500, height=380, yscale="log", ).line( source=elg_fit, y='y2', ).circle( source=elg, size=8, y='y2', fill_color="blue", ).plot taptool = elg_plot.select(type=TapTool) taptool.callback = OpenURL(url=url) lrg_plot = Plot2d(x_label="DECAM_{}".format( str(self.selected_arm).upper()), y_label="MEDIAN SNR^2", tooltip=html_tooltip, title="LRG", width=500, height=380, yscale="log").line( source=lrg_fit, y='y2', ).circle( source=lrg, size=8, y='y2', fill_color="red", ).plot taptool = lrg_plot.select(type=TapTool) taptool.callback = OpenURL(url=url) qso_plot = Plot2d(x_label="DECAM_{}".format( str(self.selected_arm).upper()), y_label="MEDIAN SNR^2", tooltip=html_tooltip, title="QSO", width=500, height=380, yscale="log").line( source=qso_fit, y='y2', ).circle( source=qso, size=8, y='y2', fill_color="green", ).plot taptool = qso_plot.select(type=TapTool) taptool.callback = OpenURL(url=url) star_plot = Plot2d( x_label="DECAM_{}".format(str(self.selected_arm).upper()), y_label="MEDIAN SNR^2", tooltip=html_tooltip, title="STAR", width=500, height=380, yscale="log", ).line(source=star_fit, y='y2').circle( source=star, size=8, y='y2', fill_color="yellow", ).plot taptool = star_plot.select(type=TapTool) taptool.callback = OpenURL(url=url) # infos info_col = Title().write_description('snr') # ----------------- # WEDGES snr_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Resid: </span> <span style="font-size: 1vw; color: #515151">@resid_snr</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 1vw; color: #515151;">@OBJ_TYPE</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@x1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 1vw; color: #515151;">@y1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">FIBER ID: </span> <span style="font-size: 1vw; color: #515151;">@QLF_FIBERID</span> </div> </div> """ median = snr['MEDIAN_SNR'] resid = snr['SNR_RESID'] qlf_fiberid = range(0, 500) my_palette = get_palette('bwr') fibersnr_tgt = [] for i in avobj: fibersnr_tgt.append(gen_info[i + '_FIBERID']) fibersnr = [] for i in list(range(len(fibersnr_tgt))): fibersnr = fibersnr + fibersnr_tgt[i] source = ColumnDataSource( data={ 'x1': [ra[i % 500] for i in fibersnr], 'y1': [dec[i % 500] for i in fibersnr], 'resid_snr': resid, 'QLF_FIBERID': fibersnr, 'OBJ_TYPE': [obj_fiber[i % 500] for i in fibersnr], 'median': median }) ra_not = [] dec_not = [] obj_not = [] fiber_not = [] fiber_mod = [] for fiber in fibersnr: fiber_mod.append(fiber % 500) for i in range(500): if i not in fiber_mod: ra_not.append(ra[i]) dec_not.append(dec[i]) fiber_not.append(i) obj_not.append(obj_fiber[i]) source_not = ColumnDataSource( data={ 'x1': ra_not, 'y1': dec_not, 'resid_snr': [''] * len(dec_not), 'QLF_FIBERID': fiber_not, 'OBJ_TYPE': obj_not }) rmax, rmin = np.nanmax(resid), np.nanmin(resid) if np.isnan(rmax) or np.isnan(rmin): fill_color = 'lightgray' else: dy = (rmax - rmin) * 0.1 mapper = LinearColorMapper(palette=my_palette, nan_color='darkgray', low=rmin - dy, high=rmax + dy) fill_color = {'field': 'resid_snr', 'transform': mapper} radius = 0.0165 radius_hover = 0.02 # centralize wedges in plots: ra_center = 0.5 * (max(ra) + min(ra)) dec_center = 0.5 * (max(dec) + min(dec)) xrange_wedge = Range1d(start=ra_center + .95, end=ra_center - .95) yrange_wedge = Range1d(start=dec_center + .82, end=dec_center - .82) # axes limit xmin, xmax = [min(ra[:]), max(ra[:])] ymin, ymax = [min(dec[:]), max(dec[:])] xfac, yfac = [(xmax - xmin) * 0.06, (ymax - ymin) * 0.06] left, right = xmin - xfac, xmax + xfac bottom, top = ymin - yfac, ymax + yfac # WEDGE RESIDUAL plots wedge_plot = Plot2d(x_range=xrange_wedge, y_range=yrange_wedge, x_label="RA", y_label="DEC", tooltip=snr_tooltip, title='Residual SNR' + name_warn, width=500, height=380, yscale="auto").wedge( source, x='x1', y='y1', field='resid_snr', mapper=mapper, ).wedge( source_not, x='x1', y='y1', ).plot taptool = wedge_plot.select(type=TapTool) taptool.callback = OpenURL(url=url) # ------------------- # Median plot median_tooltip = """ <div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">MEDIAN: </span> <span style="font-size: 1vw; color: #515151">@median</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Resid: </span> <span style="font-size: 1vw; color: #515151">@resid_snr</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">Obj Type: </span> <span style="font-size: 1vw; color: #515151;">@OBJ_TYPE</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">RA: </span> <span style="font-size: 1vw; color: #515151;">@x1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">DEC: </span> <span style="font-size: 1vw; color: #515151;">@y1</span> </div> <div> <span style="font-size: 1vw; font-weight: bold; color: #303030;">FIBER ID: </span> <span style="font-size: 1vw; color: #515151;">@QLF_FIBERID</span> </div> </div> """ mediam_plot = Plot2d( x_label="Fiber", y_label='Median SNR', tooltip=median_tooltip, title="", width=600, height=400, yscale="auto", hover_mode="vline", ).vbar( source, y="median", x="QLF_FIBERID", line_width=0.4, ) # Prepare tables current_exposures = check_spectra['METRICS']['FIDSNR_TGT'] program = gen_info['PROGRAM'].upper() reference_exposures = check_spectra['PARAMS']['FIDSNR_TGT_' + program + '_REF'] keynames = ["FIDSNR_TGT" + " ({})".format(i) for i in objlist] metric = Table().reference_table(keynames, current_exposures, reference_exposures) alert = Table().alert_table(nrg, wrg) layout = column(info_col, Div(), metric, alert, column(elg_plot, sizing_mode='scale_both'), column(lrg_plot, sizing_mode='scale_both'), column(qso_plot, sizing_mode='scale_both'), column(star_plot, sizing_mode='scale_both'), column(mediam_plot, sizing_mode='scale_both'), column(wedge_plot, sizing_mode='scale_both'), css_classes=["display-grid"]) return file_html(layout, CDN, "MEDIAN SNR")