def dd(self, his, xc=None, yc=None, logz=None): """Plot 2D histogram, his may be a positive integer (loads histogram from the data file) negative integer (2D plots registry) or Plot instance (must be a 2D plot) xc is x range, yc is y range, that may be applied immediately, see also xc() and yc() functions """ self.mode = 2 for p in Experiment.maps: p.active = False plot = None #self.plotter.clear() if isinstance(his, int): if his > 0: data = self.hisfile.load_histogram(his) if data[0] != 2: print('{} is not a 2D histogram'.format(his)) return None title = self.hisfile.histograms[his]['title'].strip() title = '{}:{}'.format(his, self._replace_latex_chars(title)) histo = histogram.Histogram(dim=2) histo.title = title histo.x_axis = data[1] histo.y_axis = data[2] histo.weights = data[3] plot = Plot(histo, 'map', True) Experiment.maps.append(plot) else: # plot histogram from the registry # Numbered by negative numbers (-1 being the latest) # Call show_registers for a list of available plots try: plot = Experiment.maps[his] Experiment.maps[his].active = True except IndexError: print('There is no 2D plot in the registry under the', 'number', his, 'use show_registry() to see', 'available plots') return None elif isinstance(his, Plot): # If instance of Plot class is given, mark it active and add # to the deque (if not already there) # and to the array to be returned at the end if his.histogram.dim != 2: print('This {} is not a 2D histogram'.format(his)) return None his.active = True plot = his if his not in Experiment.maps: Experiment.maps.append(his) if xc is not None: Experiment.xlim2d = xc if yc is not None: Experiment.ylim2d = yc if logz is None: use_log = Experiment.logz else: use_log = logz if plot is not None: self.plotter.plot2d(plot, Experiment.xlim2d, Experiment.ylim2d, use_log) return [plot]
def gy(self, his, gate_y, gate_x=None, bg_gate=None, norm=1, bin_size=1, clear=True, plot=True): """Make projection on X axis of 2D histogram with gate set on Y (gate_y) and possibly on X (gate_x) see gx for more details """ if gate_y is None or len(gate_y) != 2: print('Please select gate on Y in a (min, max) format') return None if gate_x is not None and len(gate_x) != 2: print('Please select gate on X in a (min, max) format') return None # If clear flag used, clear the plotting area #if clear and plot: # self.plotter.clear() # Switch mode to 1D self.mode = 1 # Deactivate all plots if clear flag is used if clear and plot: for p in Experiment.plots: p.active = False data = self.hisfile.load_histogram(his) if data[0] != 2: print('{} is not a 2D histogram'.format(his)) return None # x for x_axis data # y for y_axis data # w for weights # g for gate (result) # bg for background gate x = data[1] y = data[2] w = data[3] if gate_x is None: gate_x = [0, len(x)-2] x = x[gate_x[0]:gate_x[1]+1] g = w[gate_x[0]:gate_x[1]+1, gate_y[0]:gate_y[1]+1].sum(axis=1) dg = self._standard_errors_array(g) if bg_gate is not None: if (bg_gate[1] - bg_gate[0]) != (gate_y[1] - gate_y[0]): print('#Warning: background and gate of different widths') bg = w[gate_x[0]:gate_x[1]+1, bg_gate[0]:bg_gate[1]+1].sum(axis=1) g = g - bg # Note that since the gate is adding bins, the formula # used for standard error is no longer valid # This approximation should be good enough though dbg = self._standard_errors_array(bg) dg = self._add_errors(dg, dbg) title = '{}:{} gy({},{})'.format(his, self.hisfile.\ histograms[his]['title'].strip(), gate_y[0], gate_y[1]) if bg_gate is not None: title += ' bg ({}, {})'.format(bg_gate[0], bg_gate[1]) title = self._replace_latex_chars(title) histo = histogram.Histogram() histo.title = title histo.x_axis = x histo.weights = g histo.errors = dg gate_plot = Plot(histo, 'histogram', True) gate_plot.bin_size = bin_size gate_plot.norm = norm Experiment.plots.append(gate_plot) if plot: ylim = None if self.ylim is None: ylim = self._auto_scale_y() else: ylim = self.ylim ### self.plotter.plot1d(gate_plot, Experiment.xlim, ylim) return gate_plot
def d(self, *args, norm=1, bin_size=1, clear=True): #def scatterplot(self,plotobj): """ Plot 1D histogram. * args: is a list of histograms that may be given as: - positive integer: is interpreted as the histogram id from a currently open file - negative integer: is interpreted as the registry number (see (show_registers()) - Plot object: see Plot class - string: in 'x-y' format where x and y are integers (note also mandatory quatation marks) is interpreted as a range of histograms ids * norm: may be given as a single float or int value or an 'area' string, also a list of length matching the *args list may be used with any combination of the above accepted values * bin_size: must be an integer, a list of ints is also accepted (see norm) * clear: is True by default, which means that previous plot is cleared if False is given, the previous plots are not cleared. Example: e.d(100, plot1, '105-106', -3, bin_size=[1, 2, 1, 1, 10], clear=False) """ plots = [] his_list = self._expand_d_args(args) normalization = self._expand_norm(norm, len(his_list)) if normalization is None: return None bin_sizes = self._expand_bin_sizes(bin_size, len(his_list)) if bin_sizes is None: return None # Clear the plotting area (of clear is False, the currently # active plots are not deactivated, so they got replotted at # the end of this function) # Switch mode to 1D self.mode = 1 # Deactivate current plots if clear flag is used if clear: for p in Experiment.plots: p.active = False # Prepare data for plotting for i_plot, his in enumerate(his_list): if isinstance(his, int): # load histograms from the file if his > 0: data = self.hisfile.load_histogram(his) if data[0] != 1: print('{} is not a 1D histogram'.format(his)) return None title = self.hisfile.histograms[his]['title'].strip() title = '{}:{}'.format(his, self._replace_latex_chars(title)) histo = histogram.Histogram() histo.title = title histo.x_axis = data[1] histo.weights = data[3] histo.errors = self._standard_errors_array(data[3]) plot = Plot(histo, 'histogram', True) plot.bin_size = bin_sizes[i_plot] plot.norm = normalization[i_plot] plots.append(plot) Experiment.plots.append(plot) else: # plot histograms from registry # Numbered by negative numbers (-1 being the latest) # Call show_registers for a list of available plots try: plot = Experiment.plots[his] Experiment.plots[his].active = True Experiment.plots[his].bin_size = bin_sizes[i_plot] Experiment.plots[his].norm = normalization[i_plot] except IndexError: print('There is no plot in the registry under the', 'number', his, 'use show_registry() to see', 'available plots') return None plots.append(plot) elif isinstance(his, Plot): # If instance of Plot class is given, mark it active and add # to the deque (if not already there) # and to the array to be returned at the end his.active = True his.bin_size = bin_sizes[i_plot] his.norm = normalization[i_plot] plots.append(his) if his not in Experiment.plots: Experiment.plots.append(his) # Count the number of active plots active_plots = 0 for plot in Experiment.plots: if plot.active: active_plots += 1 # Here the actual plotting happens i_plot = 0 for plot in Experiment.plots: if plot.active: i_plot += 1 # If ylim is not given explicitely, go through the # active plots to find the plot limits # This is run only for the last plot. # Note that this is neccesary as matplotlib is not # autoscaling Y axis when # changing the X axis is being changed # If, in a future, the behaviour of matplotlib # changes, this part may dropped """ylim = None if self.ylim is None and i_plot == active_plots: ylim = self._auto_scale_y() else: ylim = self.ylim """ # Note that ylim is autoscaled above if self.ylim is None # But we still keep self.ylim None, # to indicate autoscaling self.plotter.plot1d(plot, self.xlim, self.ylim) # Return plots that were added or activated return plots
def gx(self, his, gate_x, gate_y=None, bg_gate=None, norm=1, bin_size=1, clear=True, plot=True): """Make projection on Y axis of 2D histogram with gate set on X (gate_x) and possibly on Y (gate_y) his: is a histogram id in a file gate_x: is range of bins in (x0, x1) format, this selects the range of X columns to be projected on Y axis gate_y: is a range of bins in (y0, y1) format (optional), this truncates the range of the projection along the Y axis bg_gate: is a range of bins in (x0, x1) format (optional), this selects the background gate that is subtracted from the selected gate_x norm: normalization factor (see d()) bin_size: binning factor (see d()) clear: True by default, clears previous plots plot: True by default, if False no plotting is taking place, only the plot object is being returned """ if gate_x is None or len(gate_x) != 2: print('Please select gate on X in a (min, max) format') return None if gate_y is not None and len(gate_y) != 2: print('Please select gate on Y in a (min, max) format') return None # If clear flag used, clear the plotting area if clear and plot: self.plotter.clear() # Switch mode to 1D self.mode = 1 # Deactivate all plots if clear flag is used if clear and plot: for p in Experiment.plots: p.active = False data = self.hisfile.load_histogram(his) if data[0] != 2: print('{} is not a 2D histogram'.format(his)) return None # x for x_axis data # y for y_axis data # w for weights # g for gate (result) # bg for background gate x = data[1] y = data[2] w = data[3] if gate_y is None: gate_y = [0, len(y)-2] y = y[gate_y[0]:gate_y[1]+1] g = w[gate_x[0]:gate_x[1]+1, gate_y[0]:gate_y[1]+1].sum(axis=0) dg = self._standard_errors_array(g) if bg_gate is not None: if (bg_gate[1] - bg_gate[0]) != (gate_x[1] - gate_x[0]): print('#Warning: background and gate of different widths') bg = w[bg_gate[0]:bg_gate[1]+1, gate_y[0]:gate_y[1]+1].sum(axis=0) g = g - bg # Note that since the gate is adding bins, the formula # used for standard error is no longer valid # This approximation should be good enough though dbg = self._standard_errors_array(bg) dg = self._add_errors(dg, dbg) title = '{}:{} gx({},{})'.format(his, self.hisfile.\ histograms[his]['title'].strip(), gate_x[0], gate_x[1]) if bg_gate is not None: title += ' bg ({}, {})'.format(bg_gate[0], bg_gate[1]) title = self._replace_latex_chars(title) histo = histogram.Histogram() histo.title = title histo.x_axis = y histo.weights = g histo.errors = dg gate_plot = Plot(histo, 'histogram', True) gate_plot.bin_size = bin_size gate_plot.norm = norm if plot: Experiment.plots.append(gate_plot) ylim = None if self.ylim is None: ylim = self._auto_scale_y() else: ylim = self.ylim ### self.plotter.plot1d(gate_plot, Experiment.xlim, ylim) return gate_plot