def test_intensity(): from ctapipe.image.toymodel import Gaussian np.random.seed(0) geom = CameraGeometry.from_name("LSTCam") x, y = u.Quantity([0.2, 0.3], u.m) width = 0.05 * u.m length = 0.15 * u.m intensity = 200 psi = "30d" # make a toymodel shower model model = Gaussian(x=x, y=y, width=width, length=length, psi=psi) _, signal, _ = model.generate_image(geom, intensity=intensity, nsb_level_pe=5) # test if signal reproduces given cog values assert np.average(geom.pix_x.to_value(u.m), weights=signal) == approx(0.2, rel=0.15) assert np.average(geom.pix_y.to_value(u.m), weights=signal) == approx(0.3, rel=0.15) # test if signal reproduces given width/length values cov = np.cov(geom.pix_x.value, geom.pix_y.value, aweights=signal) eigvals, _ = np.linalg.eigh(cov) assert np.sqrt(eigvals[0]) == approx(width.to_value(u.m), rel=0.15) assert np.sqrt(eigvals[1]) == approx(length.to_value(u.m), rel=0.15) # test if total intensity is inside in 99 percent confidence interval assert poisson(intensity).ppf(0.05) <= signal.sum() <= poisson(intensity).ppf(0.95)
def get_cherenkov_shower_image(xpix, ypix, centroid_x, centroid_y, length, width, psi, time_gradient, time_intercept): """ Obtain the PDF and time images for a Cherenkov shower ellipse Uses the toymodel methods defined in ctapipe. Parameters ---------- xpix : ndarray Pixel X coordinates. Unit: m ypix : ndarray Pixel Y coordinates. Unit: m centroid_x : float X coordinate for the center of the ellipse. Unit: m centroid_y : float Y coordinate for the center of the ellipse. Unit: m length : float Length of the ellipse. Unit: m width : float Width of the ellipse. Unit: m psi : float Rotation of the ellipse major axis from the X axis. Unit: degrees time_gradient : float Rate at which the time changes with distance along the shower axis Unit: ns / m time_intercept : float Pulse time at the shower centroid. Unit: ns Returns ------- pdf : ndarray Probability density function of the Cherenkov shower ellipse amplitude time : ndarray Pulse time per pixel. Unit: ns """ xpix = u.Quantity(xpix, u.m) ypix = u.Quantity(ypix, u.m) centroid_x = u.Quantity(centroid_x, u.m) centroid_y = u.Quantity(centroid_y, u.m) psi = Angle(psi, unit='deg') shower_image_pdf = Gaussian( x=centroid_x, y=centroid_y, length=u.Quantity(length, u.m), width=u.Quantity(width, u.m), psi=psi, ).pdf(xpix, ypix) # Normalise shower_image_pdf /= shower_image_pdf.sum() # TODO: replace when ctapipe 0.8 is released longitudinal = camera_to_shower_coordinates(xpix, ypix, centroid_x, centroid_y, psi)[0].to_value(u.m) time = longitudinal * time_gradient + time_intercept return shower_image_pdf, time
def test_intensity(): from ctapipe.image.toymodel import Gaussian np.random.seed(0) geom = CameraGeometry.from_name('LSTCam') x, y = u.Quantity([0.2, 0.3], u.m) width = 0.05 * u.m length = 0.15 * u.m intensity = 50 psi = '30d' # make a toymodel shower model model = Gaussian(x=x, y=y, width=width, length=length, psi=psi) image, signal, noise = model.generate_image( geom, intensity=intensity, nsb_level_pe=5, ) # test if signal reproduces given cog values assert np.average(geom.pix_x.to_value(u.m), weights=signal) == approx(0.2, rel=0.15) assert np.average(geom.pix_y.to_value(u.m), weights=signal) == approx(0.3, rel=0.15) # test if signal reproduces given width/length values cov = np.cov(geom.pix_x.value, geom.pix_y.value, aweights=signal) eigvals, eigvecs = np.linalg.eigh(cov) assert np.sqrt(eigvals[0]) == approx(width.to_value(u.m), rel=0.15) assert np.sqrt(eigvals[1]) == approx(length.to_value(u.m), rel=0.15) # test if total intensity is inside in 99 percent confidence interval assert poisson(intensity).ppf(0.05) <= signal.sum() <= poisson(intensity).ppf(0.95)
def test_waveform_model(): from ctapipe.image.toymodel import Gaussian geom = CameraGeometry.from_name("CHEC") readout = CameraReadout.from_name("CHEC") ref_duration = 67 n_ref_samples = 100 pulse_sigma = 3 ref_x_norm = np.linspace(0, ref_duration, n_ref_samples) ref_y_norm = norm.pdf(ref_x_norm, ref_duration / 2, pulse_sigma) readout.reference_pulse_shape = ref_y_norm[np.newaxis, :] readout.reference_pulse_sample_width = u.Quantity( ref_x_norm[1] - ref_x_norm[0], u.ns) readout.sampling_rate = u.Quantity(2, u.GHz) centroid_x = u.Quantity(0.05, u.m) centroid_y = u.Quantity(0.05, u.m) length = u.Quantity(0.03, u.m) width = u.Quantity(0.008, u.m) psi = u.Quantity(70, u.deg) time_gradient = u.Quantity(50, u.ns / u.m) time_intercept = u.Quantity(20, u.ns) _, charge, _ = Gaussian(x=centroid_x, y=centroid_y, width=width, length=length, psi=psi).generate_image(geom, 10000) time = obtain_time_image( geom.pix_x, geom.pix_y, centroid_x, centroid_y, psi, time_gradient, time_intercept, ) time[charge == 0] = 0 waveform_model = WaveformModel.from_camera_readout(readout) waveform = waveform_model.get_waveform(charge, time, 96) np.testing.assert_allclose(waveform.sum(axis=1), charge, rtol=1e-3) np.testing.assert_allclose(waveform.argmax(axis=1) / readout.sampling_rate.to_value(u.GHz), time, rtol=1e-1) time_2 = time + 1 time_2[charge == 0] = 0 waveform_2 = waveform_model.get_waveform(charge, time_2, 96) np.testing.assert_allclose(waveform_2.sum(axis=1), charge, rtol=1e-3) np.testing.assert_allclose( waveform_2.argmax(axis=1) / readout.sampling_rate.to_value(u.GHz), time_2, rtol=1e-1, ) assert (waveform_2.argmax(axis=1)[charge != 0] > waveform.argmax(axis=1)[charge != 0]).all()
def test_compare(): from ctapipe.image.toymodel import SkewedGaussian, Gaussian geom = CameraGeometry.from_name("LSTCam") x, y = u.Quantity([0.2, 0.3], u.m) width = 0.05 * u.m length = 0.15 * u.m intensity = 50 psi = "30d" skewed = SkewedGaussian(x=x, y=y, width=width, length=length, psi=psi, skewness=0) normal = Gaussian(x=x, y=y, width=width, length=length, psi=psi) signal_skewed = skewed.expected_signal(geom, intensity=intensity) signal_normal = normal.expected_signal(geom, intensity=intensity) assert np.isclose(signal_skewed, signal_normal).all()
def create_mock_image(geom): ''' creates a mock image, which parameters are adapted to the camera size ''' camera_r = np.max(np.sqrt(geom.pix_x**2 + geom.pix_y**2)) model = Gaussian(x=0.3 * camera_r, y=0 * u.m, width=0.03 * camera_r, length=0.10 * camera_r, psi="25d") _, image, _ = model.generate_image( geom, intensity=0.5 * geom.n_pixels, nsb_level_pe=3, ) return image
def main(): fig, axs = plt.subplots(1, 2, constrained_layout=True, figsize=(6, 3)) model = Gaussian(0 * u.m, 0.1 * u.m, 0.3 * u.m, 0.05 * u.m, 25 * u.deg) cam = CameraGeometry.from_name('FlashCam') image, *_ = model.generate_image(cam, 2500) CameraDisplay(cam, ax=axs[0], image=image) CameraDisplay( cam.transform_to(EngineeringCameraFrame()), ax=axs[1], image=image, ) axs[0].set_title('CameraFrame') axs[1].set_title('EngineeringCameraFrame') plt.show()
def create_mock_image(geom): ''' creates a mock image, which parameters are adapted to the camera size ''' camera_r = np.max(np.sqrt(geom.pix_x**2 + geom.pix_y**2)) model = Gaussian( x=0.3 * camera_r, y=0 * u.m, width=0.03 * camera_r, length=0.10 * camera_r, psi="25d" ) _, image, _ = model.generate_image( geom, intensity=0.5 * geom.n_pixels, nsb_level_pe=3, ) return image
def test_compare(): from ctapipe.image.toymodel import SkewedGaussian, Gaussian geom = CameraGeometry.from_name('LSTCam') x, y = u.Quantity([0.2, 0.3], u.m) width = 0.05 * u.m length = 0.15 * u.m intensity = 50 psi = '30d' skewed = SkewedGaussian( x=x, y=y, width=width, length=length, psi=psi, skewness=0 ) normal = Gaussian( x=x, y=y, width=width, length=length, psi=psi ) signal_skewed = skewed.expected_signal(geom, intensity=intensity) signal_normal = normal.expected_signal(geom, intensity=intensity) assert np.isclose(signal_skewed, signal_normal).all()
image = np.zeros(32, dtype=np.int) image[[5, 6, 7, 8, 13, 18, 25, 24, 23, 26]] = 5 time = np.full(32, 5, dtype=np.int) z_next = False elif type_rand == 3: image = np.zeros(32, dtype=np.int) image[[5, 6, 7, 8, 13, 19, 25, 24, 23]] = 5 time = np.full(32, 5, dtype=np.int) z_next = True elif type_rand == 7: ring = RingGaussian(x, y, radius, sigma) image = ring.pdf(xpix, ypix) image = np.round(image * max_amp / image.max()).astype(np.int) time = np.full(32, 5, dtype=np.int) else: gaussian = Gaussian(x, y, length, width, psi) image = gaussian.pdf(xpix, ypix) image = np.round(image * max_amp / image.max()).astype(np.int) array = [convert(a, t) for a, t in zip(image, time)] print( f" {{{array[0]},{array[1]},{array[2]},{array[3]},\n" f"{array[4]},{array[5]},{array[6]},{array[7]},{array[8]},{array[9]},\n" f"{array[10]},{array[11]},{array[12]},{array[13]},{array[14]},{array[15]},\n" f"{array[16]},{array[17]},{array[18]},{array[19]},{array[20]},{array[21]},\n" f"{array[22]},{array[23]},{array[24]},{array[25]},{array[26]},{array[27]},\n" f" {array[28]},{array[29]},{array[30]},{array[31]}}},") # pixels.set_array(np.ma.masked_invalid(image)) # pixels.changed()