def main(): parser = argparse.ArgumentParser( description="Generate Camera configuration files") parser.add_argument('-o', dest='output', help='Output directory') args = parser.parse_args() output_dir = args.output create_directory(output_dir) n_samples = 96 spe = SiPMPrompt(opct=0.1, normalise_charge=False) camera_kwargs = dict( mapping=SSTCameraMapping(), photoelectron_spectrum=spe, n_waveform_samples=n_samples, continuous_readout_duration=n_samples, readout_noise=GaussianNoise(stddev=2), digitisation_noise=GaussianNoise(stddev=1), ) for mv_per_pe in [0.5, 0.8, 1.1, 1.375, 2.25, 3.125, 4]: for width in [2, 4, 6, 8, 10, 14, 20]: sigma = width / 2.355 pulse = GaussianPulse(30, sigma, 60, mv_per_pe=mv_per_pe) coupling = ACOffsetCoupling(pulse_area=pulse.area, spectrum_average=spe.average) camera = Camera(**camera_kwargs, photoelectron_pulse=pulse, coupling=coupling) name = f"width_{width:.2f}_height_{mv_per_pe:.2f}.pkl" camera.save(join(output_dir, name))
def main(): parser = argparse.ArgumentParser( description="Generate Camera configuration files") parser.add_argument('-o', dest='output', help='Output directory') args = parser.parse_args() output_dir = args.output create_directory(output_dir) n_samples = 128 width = 14 sigma = width / 2.355 for opct in np.linspace(0, 0.5, 6): for mv_per_pe in np.linspace(0.4, 4, 5): for nsb in np.linspace(0, 50, 5): pulse = GaussianPulse(20, sigma, 40, mv_per_pe=mv_per_pe) spe = SiPMPrompt(opct=opct, normalise_charge=False) coupling = ACOffsetCoupling(pulse_area=pulse.area, spectrum_average=spe.average) camera = Camera( mapping=SSTCameraMapping(), photoelectron_spectrum=spe, photoelectron_pulse=pulse, coupling=coupling, n_waveform_samples=n_samples, continuous_readout_duration=n_samples, readout_noise=GaussianNoise(stddev=0.5), digitisation_noise=GaussianNoise(stddev=1), ) camera.attach_metadata("nsb", nsb) name = f"camera_{opct:.2f}_{mv_per_pe:.2f}_{nsb:.2f}.pkl" camera.save(join(output_dir, name))
def get_camera_and_readout(pulse_width, mv_per_pe, spectrum, nsb_rate): camera = Camera(continuous_readout_duration=int(2e5), n_waveform_samples=int(2e5), mapping=SSTCameraMapping(n_pixels=1), photoelectron_pulse=GaussianPulse(sigma=pulse_width, mv_per_pe=mv_per_pe), photoelectron_spectrum=spectrum) source = PhotoelectronSource(camera=camera, seed=1) acquisition = EventAcquisition(camera=camera, seed=1) pe = source.get_nsb(nsb_rate) return camera, acquisition.get_continuous_readout(pe)
def test_neighbour(): mapping = SSTCameraMapping(n_pixels=16) n_photoelectrons = 1000000 photoelectrons = Photoelectrons( pixel=np.zeros(n_photoelectrons, dtype=int), time=np.full(n_photoelectrons, 10.), charge=np.ones(n_photoelectrons), ) rng = np.random.RandomState(seed=1) spectrum_template = SiPMReflectedOCT(mapping=mapping, reflected_scale=5) result = spectrum_template.apply(photoelectrons, rng) charge = result.get_charge_per_pixel(mapping.n_pixels) assert (charge > 0).all()
def main(): normalise_charge = True spectra = { "No OCT": SiPMPrompt(opct=0, normalise_charge=normalise_charge), "Prompt OCT (20%)": SiPMPrompt(opct=0.2, normalise_charge=normalise_charge), "Delayed OCT (20%, τ=24ns)": SiPMDelayed(opct=0.2, time_constant=24, normalise_charge=normalise_charge), "Delayed OCT (55%, τ=24ns)": SiPMDelayed(opct=0.55, time_constant=24, normalise_charge=normalise_charge), } path = "/Users/Jason/Software/TargetCalib/source/dev/reference_pulse_checs_V1-1-0.cfg" ref_x, ref_y = np.loadtxt(path, unpack=True) pulse = GenericPulse(ref_x * 1e9, ref_y, mv_per_pe=4) p_waveform = WaveformPlot(talk=True) for name, spectrum in spectra.items(): camera = Camera( continuous_readout_duration=128, n_waveform_samples=128, mapping=SSTCameraMapping(n_pixels=1), photoelectron_spectrum=spectrum, photoelectron_pulse=pulse, ) source = PhotoelectronSource(camera=camera) acquisition = EventAcquisition(camera=camera) n_events = 100 waveform = np.zeros((n_events, 128)) for iev in trange(n_events): pe = source.get_uniform_illumination(30, 50) readout = acquisition.get_continuous_readout(pe) waveform[iev] = acquisition.get_sampled_waveform(readout)[0] waveform_avg = np.mean(waveform, 0) p_waveform.ax.plot(waveform_avg, label=name) p_waveform.add_legend('best') p_waveform.ax.set_xlabel("Time (ns)") p_waveform.ax.set_ylabel("Amplitude (mV)") p_waveform.ax.set_title("Average Pulse (50 p.e.)") p_waveform.save("pulse.pdf")
def main(): parser = argparse.ArgumentParser( description="Generate Camera configuration files") parser.add_argument('-o', dest='output', help='Output directory') args = parser.parse_args() output_dir = args.output create_directory(output_dir) # Define camera n_samples = 128 width = 8 # ns sigma = width / (2 * np.sqrt(2 * np.log(2))) pulse = GaussianPulse(mean=15, sigma=sigma, duration=30, mv_per_pe=4) mapping = SSTCameraMapping() camera_kwargs = dict( mapping=mapping, photoelectron_pulse=pulse, n_waveform_samples=n_samples, continuous_readout_duration=n_samples, digitisation_noise=GaussianNoise(stddev=1), ) self_opct_l = [0.08, 0.15, 0.3] reflected_opct_l = [0, 0.08, 0.15, 0.3] reflected_scale_l = [0.6, 1.0, 1.5, 2.3, 5] for self_opct in self_opct_l: for reflected_opct in reflected_opct_l: for reflected_scale in reflected_scale_l: spe = SiPMReflectedOCT( opct=self_opct, reflected_opct=reflected_opct, reflected_scale=reflected_scale, normalise_charge=False, mapping=mapping, ) coupling = ACOffsetCoupling(pulse_area=pulse.area, spectrum_average=spe.average) camera = Camera(**camera_kwargs, photoelectron_spectrum=spe, coupling=coupling) name = f"refl_opct_{self_opct:.2f}_{reflected_opct:.2f}_{reflected_scale:.2f}.pkl" camera.save(join(output_dir, name))
def main(): spectrum = SiPMGentileSPE(opct=0.2, normalise_x=False) camera = Camera(photoelectron_spectrum=spectrum, mapping=SSTCameraMapping(n_pixels=1)) n_events = 200000 source = PhotoelectronSource(camera=camera) pe1 = [] pe50 = [] for iev in trange(n_events): pe1.append(source.get_uniform_illumination(20, 1).charge.sum()) pe50.append(source.get_uniform_illumination(20, 20).charge.sum()) pe1 = np.array(pe1) pe50 = np.array(pe50) # embed() plot = SpectrumPlot(sidebyside=True) plot.ax.hist( pe1, bins=70, histtype='step', label=f"λ = 1, Average Charge Per Event = {pe1.mean():.2f} f.c.") plot.ax.hist( pe50, bins=70, histtype='step', label=f"λ = 20, Average Charge Per Event = {pe50.mean():.2f} f.c.") # plot.ax.set_yscale('log') plot.ax.set_xlabel("Charge Per Event (f.c.)") plot.ax.set_ylabel("Number of Events") plot.add_legend('best') plot.save(get_plot("d201029_sipm_calib_doc/charge_mc.pdf")) spectrum = SiPMGentileSPE(opct=0.2, normalise_x=True) camera = Camera(photoelectron_spectrum=spectrum, mapping=SSTCameraMapping(n_pixels=1)) n_events = 200000 source = PhotoelectronSource(camera=camera) pe1 = [] pe50 = [] for iev in trange(n_events): pe1.append(source.get_uniform_illumination(20, 1).charge.sum()) pe50.append(source.get_uniform_illumination(20, 20).charge.sum()) pe1 = np.array(pe1) pe50 = np.array(pe50) # embed() plot = SpectrumPlot(sidebyside=True) plot.ax.hist( pe1, bins=70, histtype='step', label=f"λ = 1, Average Charge Per Event = {pe1.mean():.2f} p.e.") plot.ax.hist( pe50, bins=70, histtype='step', label=f"λ = 20, Average Charge Per Event = {pe50.mean():.2f} p.e.") # plot.ax.set_yscale('log') plot.ax.set_xlabel("Charge Per Event (p.e.)") plot.ax.set_ylabel("Number of Events") plot.add_legend('best') plot.save(get_plot("d201029_sipm_calib_doc/charge_pe.pdf"))
def main(): camera = Camera( continuous_readout_duration=10000, mapping=SSTCameraMapping(n_pixels=1), photoelectron_spectrum=SiPMDelayed(opct=0.2, time_constant=24), # photoelectron_spectrum=PerfectPhotosensor(), ) source = PhotoelectronSource(camera=camera) nsb_rate = 2.3 n_events = 100000 dt = [] rng = np.random.RandomState(None) for iev in trange(n_events): pe = source.get_nsb(rate=nsb_rate) # pe = Photoelectrons( # pixel=np.zeros(1), # time=np.full(1, 20.), # charge=np.ones(1), # ) # pe = camera.photoelectron_spectrum.apply(pe, rng) time = np.sort(pe.time) # time = pe.time if time.size > 1: # embed() dt.append(time[1] - time[0]) # dt.append(time[1:] - time[0]) # if (np.diff(time) < 100).any(): # embed() # dt.append(np.diff(time)) # dt = dt[dt < 1000] # dt = (time - time[:, None]).ravel() # dt = dt[dt > 8] # embed() dt = np.array(dt) # dt = np.concatenate(dt) dt = dt[(dt > 0) & (dt < 1000)] hist, edges = np.histogram(dt, bins=200) between = (edges[1:] + edges[:-1]) / 2 def func(t, a0, tc0, a1, tc1): return a0 * 1 / tc0 * np.exp(t / -tc0) + a1 * 1 / tc1 * np.exp( t / -tc1) def cost_binned_nll(a0, tc0, a1, tc1): f_y = func(between, a0, tc0, a1, tc1) scale = np.sum(hist) / np.sum(f_y) return np.sum(_bin_nll(f_y * scale, hist)) def cost_ls(a0, tc0, a1, tc1): f_y = func(between, a0, tc0, a1, tc1) gt5 = hist > 5 return np.sum((hist[gt5] - f_y[gt5])**2 / hist[gt5]) def cost_unbinned_nll(a0, tc0, a1, tc1): if np.isnan(np.array([a0, tc0, a1, tc1])).any(): return np.inf f_y = func(dt, a0, tc0, a1, tc1) return -_sum_log_x(f_y) initial = dict(a0=1, tc0=30, a1=1, tc1=1e3 / nsb_rate) limits = dict(limit_a0=(0, None), limit_tc0=(1, None), limit_a1=(0, None), limit_tc1=(1, None)) fixed = dict( # fix_a0=True, # fix_tc0=True, # fix_a1=True, # fix_tc1=True ) m0 = iminuit.Minuit( cost_binned_nll, **initial, **limits, **fixed, errordef=0.5, print_level=0, pedantic=False, throw_nan=True, ) m0.migrad() m0.hesse() # # Attempt to run HESSE to compute parabolic errors. # with warnings.catch_warnings(): # warnings.simplefilter("ignore", iminuit.util.HesseFailedWarning) # m0.hesse() # embed() print(m0.values) print(m0.errors) # popt, pcov = curve_fit(func, between, hist) # embed() p_timesep = TimeSeperationPlot(talk=True) # p_timesep.ax.hist(dt, bins=100)#, density=True) # p_timesep.ax.plot(between, hist, '.') (_, caps, _) = p_timesep.ax.errorbar(between, hist, yerr=np.sqrt(hist), mew=1, capsize=1, elinewidth=0.5, markersize=2, linewidth=0.5, fmt='.', zorder=1) # p_timesep.ax.errorbar(between, hist, yerr=np.sqrt(hist)) f_y = func(between, *m0.values.values()) scale = np.sum(hist) / np.sum(f_y) p_timesep.ax.plot(between, f_y * scale) p_timesep.ax.text(0.1, 0.8, fr"$τ_S$={m0.values['tc0']:.2f}", transform=p_timesep.ax.transAxes) p_timesep.ax.text(0.7, 0.4, fr"$τ_L$={m0.values['tc1']:.2f}", transform=p_timesep.ax.transAxes) p_timesep.ax.set_yscale("log") p_timesep.ax.set_xlabel("Δt (ns)") p_timesep.save("timesep.pdf")