def plot_on_single_pmt_array(c, array_name='top', r=straxen.tpc_r * 1.1, pmt_label_size=7, pmt_label_color='white', log_scale=False, vmin=None, vmax=None, **kwargs): """Plot one of the PMT arrays and color it by c. :param c: Array of colors to use. Must be len(straxen.n_tpc_pmts) :param label: Label for the color bar :param pmt_label_size: Fontsize for the PMT number labels. Set to 0 to disable. :param pmt_label_color: Text color of the PMT number labels. :param log_scale: If True, use a logarithmic color scale :param extend: same as plt.colorbar(extend=...) :param vmin: Minimum of color scale :param vmax: maximum of color scale Other arguments are passed to plt.scatter. """ assert len(c) == straxen.n_tpc_pmts, \ f"Need array of {straxen.n_tpc_pmts} values, got {len(c)}" if vmin is None: vmin = c.min() if vmax is None: vmax = c.max() pmt_positions = straxen.pmt_positions().to_records() plt.gca().set_aspect('equal') plt.xlim(-r, r) plt.ylim(-r, r) mask = pmt_positions['array'] == array_name pos = pmt_positions[mask] kwargs.setdefault('s', 230) result = plt.scatter( pos['x'], pos['y'], c=c[mask], vmin=vmin, vmax=vmax, norm=matplotlib.colors.LogNorm() if log_scale else None, **kwargs) if pmt_label_size: for p in pos: plt.text(p['x'], p['y'], str(p['i']), horizontalalignment='center', verticalalignment='center', fontsize=pmt_label_size, color=pmt_label_color) return result
def hvdisp_plot_pmt_pattern(*, config, records, to_pe, array='bottom'): """Plot a PMT array, with colors showing the intensity of light observed in the time range :param array: 'top' or 'bottom', array to show """ import holoviews as hv pmts = straxen.pmt_positions(xenon1t=config['n_tpc_pmts'] < 300) areas = np.bincount(records['channel'], weights=records['area'] * to_pe[records['channel']], minlength=len(pmts)) # Which PMTs should we include? m = pmts['array'] == array pmts = pmts[m].copy() pmts['area'] = areas[m] f = 1.08 pmts = hv.Dataset(pmts, kdims=[ hv.Dimension('x', unit='cm', range=(-straxen.tpc_r * f, straxen.tpc_r * f)), hv.Dimension('y', unit='cm', range=(-straxen.tpc_r * f, straxen.tpc_r * f)), hv.Dimension('i', range=(0, config['n_tpc_pmts']), label='PMT number'), hv.Dimension('area', label='Area', unit='PE') ]) pmts = pmts.to(hv.Points, vdims=['area', 'i'], group='PMTPattern', label=array.capitalize()).opts(plot=dict(color_index=2, tools=['hover'], show_grid=False), style=dict(size=17, cmap='plasma')) return pmts
def plot_on_single_pmt_array( c, array_name='top', xenon1t=False, r=straxen.tpc_r * 1.03, pmt_label_size=8, pmt_label_color='white', show_tpc=True, log_scale=False, vmin=None, vmax=None, dead_pmts=None, dead_pmt_color='gray', **kwargs): """Plot one of the PMT arrays and color it by c. :param c: Array of colors to use. Must be len() of the number of TPC PMTs :param label: Label for the color bar :param pmt_label_size: Fontsize for the PMT number labels. Set to 0 to disable. :param pmt_label_color: Text color of the PMT number labels. :param log_scale: If True, use a logarithmic color scale :param extend: same as plt.colorbar(extend=...) :param vmin: Minimum of color scale :param vmax: maximum of color scale Other arguments are passed to plt.scatter. """ if vmin is None: vmin = c.min() if vmax is None: vmax = c.max() pmt_positions = straxen.pmt_positions(xenon1t=xenon1t).to_records() ax = plt.gca() ax.set_aspect('equal') plt.xlim(-r, r) plt.ylim(-r, r) mask = pmt_positions['array'] == array_name pos = pmt_positions[mask] kwargs.setdefault('s', 280) if log_scale: kwargs.setdefault('norm', matplotlib.colors.LogNorm(vmin=vmin, vmax=vmax)) else: kwargs.setdefault('vmin', vmin) kwargs.setdefault('vmax', vmax) result = plt.scatter( pos['x'], pos['y'], c=c[mask], **kwargs) if show_tpc: ax.set_facecolor('lightgrey') ax.add_artist(plt.Circle( (0, 0), straxen.tpc_r, edgecolor='k', facecolor='w', zorder=-5, linewidth=1)) else: ax.set_axis_off() if dead_pmts is not None: _dead_mask = [pi in dead_pmts for pi in pos['i']] result = plt.scatter( pos[_dead_mask]['x'], pos[_dead_mask]['y'], c=dead_pmt_color, **kwargs) if pmt_label_size: for p in pos: plt.text(p['x'], p['y'], str(p['i']), horizontalalignment='center', verticalalignment='center', fontsize=pmt_label_size, color=pmt_label_color) return result
def plot_pmt_array( peak, array_type, to_pe, plot_all_pmts=False, log=False, xenon1t=False, fig=None, label='', ): """ Plots top or bottom PMT array for given peak. :param peak: Peak for which the hit pattern should be plotted. :param array_type: String which specifies if "top" or "bottom" PMT array should be plotted :param to_pe: PMT gains. :param log: If true use a log-scale for the color scale. :param plot_all_pmts: If True colors all PMTs instead of showing swtiched off PMTs as gray dots. :param xenon1t: If True plots 1T array. :param fig: Instance of bokeh.plotting.figure if None one will be created via straxen.bokeh.utils.default_figure(). :param label: Label of the peak which should be used for the plot legend :returns: Tuple containing a bokeh figure, glyph and transform instance. """ if peak.shape: raise ValueError( 'Can plot PMT array only for a single peak at a time.') tool_tip = [('Plot', '$name'), ('Channel', '@pmt'), ('X-Position [cm]', '$x'), ('Y-Position [cm]', '$y'), ('area [pe]', '@area')] array = ('top', 'bottom') if array_type not in array: raise ValueError('"array_type" must be either top or bottom.') if not fig: fig = straxen.bokeh_utils.default_fig(title=f'{array_type} array') # Creating TPC axis and title fig = _plot_tpc(fig) # Plotting PMTs: pmts = straxen.pmt_positions(xenon1t) if plot_all_pmts: mask_pmts = np.zeros(len(pmts), dtype=np.bool_) else: mask_pmts = to_pe == 0 pmts_on = pmts[~mask_pmts] pmts_on = pmts_on[pmts_on['array'] == array_type] if np.any(mask_pmts): pmts_off = pmts[mask_pmts] pmts_off = pmts_off[pmts_off['array'] == array_type] fig = _plot_off_pmts(pmts_off, fig) area_per_channel = peak['area_per_channel'][pmts_on['i']] if log: area_plot = np.log10(area_per_channel) # Manually set infs to zero since cmap cannot handle it. area_plot = np.where(area_plot == -np.inf, 0, area_plot) else: area_plot = area_per_channel mapper = bokeh.transform.linear_cmap(field_name='area_plot', palette="Viridis256", low=min(area_plot), high=max(area_plot)) source_on = bklt.ColumnDataSource( data={ 'x': pmts_on['x'], 'y': pmts_on['y'], 'area': area_per_channel, 'area_plot': area_plot, 'pmt': pmts_on['i'] }) p = fig.scatter( source=source_on, radius=straxen.tpc_pmt_radius, fill_color=mapper, fill_alpha=1, line_color='black', legend_label=label, name=label + '_pmt_array', ) fig.add_tools( bokeh.models.HoverTool(names=[label + '_pmt_array'], tooltips=tool_tip)) fig.legend.location = 'top_left' fig.legend.click_policy = "hide" fig.legend.orientation = "horizontal" fig.legend.padding = 0 fig.toolbar_location = None return fig, p, mapper
def test_pmt_pos_nt(): """ Test if we can get the nT PMT positions """ pandas.DataFrame(straxen.pmt_positions(False))
def test_pmt_pos_1t(): """ Test if we can get the 1T PMT positions """ pandas.DataFrame(straxen.pmt_positions(True))