def test_equals(): cam1 = CameraGeometry.from_name("LSTCam") cam2 = CameraGeometry.from_name("LSTCam") cam3 = CameraGeometry.from_name("ASTRICam") assert cam1 is not cam2 assert cam1 == cam2 assert cam1 != cam3
def test_border_pixels(): from ctapipe.instrument.camera import CameraGeometry cam = CameraGeometry.from_name("LSTCam") assert np.sum(cam.get_border_pixel_mask(1)) == 168 assert np.sum(cam.get_border_pixel_mask(2)) == 330 cam = CameraGeometry.from_name("ASTRICam") assert np.sum(cam.get_border_pixel_mask(1)) == 212 assert np.sum(cam.get_border_pixel_mask(2)) == 408 assert cam.get_border_pixel_mask(1)[0] assert cam.get_border_pixel_mask(1)[2351] assert not cam.get_border_pixel_mask(1)[521]
def test_convert_geometry(cam_id, rot): geom = CameraGeometry.from_name(cam_id) if geom.pix_type=='rectangular': return # skip non-hexagonal cameras, since they don't need conversion model = generate_2d_shower_model(centroid=(0.4, 0), width=0.01, length=0.03, psi="25d") _,image,_ = make_toymodel_shower_image(geom, model.pdf, intensity=50, nsb_level_pe=100) hillas_0 = hillas_parameters(geom.pix_x, geom.pix_y, image) geom2d, image2d = convert_geometry_1d_to_2d(geom, image, geom.cam_id+str(rot), add_rot=-2) geom1d, image1d = convert_geometry_back(geom2d, image2d, geom.cam_id+str(rot), add_rot=rot) hillas_1 = hillas_parameters(geom1d.pix_x, geom1d.pix_y, image1d) if __name__ == "__main__": plot_cam(geom, geom2d, geom1d, image, image2d, image1d) assert np.abs(hillas_1.phi - hillas_0.phi).deg < 1.0
def create_sample_image(psi='-30d'): seed(10) # set up the sample image using a HESS camera geometry (since it's easy # to load) geom = CameraGeometry.from_name("LSTCam") # make a toymodel shower model model = toymodel.generate_2d_shower_model(centroid=(0.2, 0.3), width=0.001, length=0.01, psi=psi) # generate toymodel image in camera for this shower model. image, signal, noise = toymodel.make_toymodel_shower_image(geom, model.pdf, intensity=50, nsb_level_pe=100) # denoise the image, so we can calculate hillas params clean_mask = tailcuts_clean(geom, image, 10, 5) # pedvars = 1 and core and boundary # threshold in pe image[~clean_mask] = 0 # Pixel values in the camera pix_x = geom.pix_x.value pix_y = geom.pix_y.value return pix_x, pix_y, image
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_neighbor_pixels(cam_id): """ test if each camera has a reasonable number of neighbor pixels (4 for rectangular, and 6 for hexagonal. Other than edge pixels, the majority should have the same value """ geom = CameraGeometry.from_name(cam_id) n_pix = len(geom.pix_id) n_neighbors = [len(x) for x in geom.neighbors] if geom.pix_type.startswith('hex'): assert n_neighbors.count(6) > 0.5 * n_pix assert n_neighbors.count(6) > n_neighbors.count(4) if geom.pix_type.startswith('rect'): assert n_neighbors.count(4) > 0.5 * n_pix assert n_neighbors.count(5) == 0 assert n_neighbors.count(6) == 0 # whipple has inhomogenious pixels that mess with pixel neighborhood # calculation if cam_id != 'Whipple490': assert np.all(geom.neighbor_matrix == geom.neighbor_matrix.T) assert n_neighbors.count(1) == 0 # no pixel should have a single neighbor
def test_slicing_rotation(cam_id): cam = CameraGeometry.from_name(cam_id) cam.rotate('25d') sliced1 = cam[5:10] assert sliced1.pix_x[0] == cam.pix_x[5]
def test_skewed(): from ctapipe.image.toymodel import SkewedGaussian # test if the parameters we calculated for the skew normal # distribution produce the correct moments 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' skewness = 0.3 model = SkewedGaussian( x=x, y=y, width=width, length=length, psi=psi, skewness=skewness ) image, signal, _ = model.generate_image( geom, intensity=intensity, nsb_level_pe=5, ) a, loc, scale = model._moments_to_parameters() mean, var, skew = skewnorm(a=a, loc=loc, scale=scale).stats(moments='mvs') assert np.isclose(mean, 0) assert np.isclose(var, length.to_value(u.m)**2) assert np.isclose(skew, skewness)
def camera_waveforms(): camera = CameraGeometry.from_name("CHEC") n_pixels = camera.n_pixels n_samples = 96 mid = n_samples // 2 pulse_sigma = 6 r_hi = np.random.RandomState(1) r_lo = np.random.RandomState(2) x = np.arange(n_samples) # Randomize times t_pulse_hi = r_hi.uniform(mid - 10, mid + 10, n_pixels)[:, np.newaxis] t_pulse_lo = r_lo.uniform(mid + 10, mid + 20, n_pixels)[:, np.newaxis] # Create pulses y_hi = norm.pdf(x, t_pulse_hi, pulse_sigma) y_lo = norm.pdf(x, t_pulse_lo, pulse_sigma) # Randomize amplitudes y_hi *= r_hi.uniform(100, 1000, n_pixels)[:, np.newaxis] y_lo *= r_lo.uniform(100, 1000, n_pixels)[:, np.newaxis] y = np.stack([y_hi, y_lo]) return y, camera
def test_fact_image_cleaning(): # use LST pixel geometry geom = CameraGeometry.from_name("LSTCam") # create some signal pixels values = np.zeros(len(geom)) timing = np.zeros(len(geom)) signal_pixels = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 37, 38, 111, 222]) values[signal_pixels] = 5 timing[signal_pixels] = 10 # manipulate some of those values[[1, 2]] = 3 values[7] = 1 timing[[5, 6, 13, 111]] = 20 mask = cleaning.fact_image_cleaning(geom, values, timing, boundary_threshold=2, picture_threshold=4, min_number_neighbors=2, time_limit=5) expected_pixels = np.array([0, 1, 2, 3, 4, 8, 9, 10, 11]) expected_mask = np.zeros(len(geom)).astype(bool) expected_mask[expected_pixels] = 1 assert_allclose(mask, expected_mask)
def test_intensity(): from .. import toymodel np.random.seed(0) geom = CameraGeometry.from_name('LSTCam') width = 0.05 length = 0.15 intensity = 50 # make a toymodel shower model model = toymodel.generate_2d_shower_model( centroid=(0.2, 0.3), width=width, length=length, psi='30d', ) image, signal, noise = toymodel.make_toymodel_shower_image( geom, model.pdf, intensity=intensity, nsb_level_pe=5, ) # test if signal reproduces given cog values assert np.average(geom.pix_x.value, weights=signal) == approx(0.2, rel=0.15) assert np.average(geom.pix_y.value, 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, rel=0.15) assert np.sqrt(eigvals[1]) == approx(length, 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 create_sample_image( psi='-30d', x=0.2 * u.m, y=0.3 * u.m, width=0.05 * u.m, length=0.15 * u.m, intensity=1500 ): seed(10) geom = CameraGeometry.from_name('LSTCam') # make a toymodel shower model model = toymodel.Gaussian(x=x, y=y, width=width, length=length, psi=psi) # generate toymodel image in camera for this shower model. image, _, _ = model.generate_image( geom, intensity=1500, nsb_level_pe=3, ) # calculate pixels likely containing signal clean_mask = tailcuts_clean(geom, image, 10, 5) return geom, image, clean_mask
def test_convert_geometry_mock(cam_id, rot): """here we use a different key for the back conversion to trigger the mock conversion """ geom = CameraGeometry.from_name(cam_id) image = create_mock_image(geom) hillas_0 = hillas_parameters(geom, image) if geom.pix_type == 'hexagonal': convert_geometry_1d_to_2d = convert_geometry_hex1d_to_rect2d convert_geometry_back = convert_geometry_rect2d_back_to_hexe1d geom2d, image2d = convert_geometry_1d_to_2d(geom, image, key=None, add_rot=rot) geom1d, image1d = convert_geometry_back(geom2d, image2d, "_".join([geom.cam_id, str(rot), "mock"]), add_rot=rot) else: # originally rectangular geometries don't need a buffer and therefore no mock # conversion return hillas_1 = hillas_parameters(geom, image1d) assert np.abs(hillas_1.phi - hillas_0.phi).deg < 1.0
def test_neighbor_pixels(): hexgeom = CameraGeometry.from_name("LSTCam") recgeom = CameraGeometry.make_rectangular() # most pixels should have 4 neighbors for rectangular geometry and 6 for # hexagonal assert int(median(recgeom.neighbor_matrix.sum(axis=1))) == 4 assert int(median(hexgeom.neighbor_matrix.sum(axis=1))) == 6
def test_known_camera_names(): cams = CameraGeometry.get_known_camera_names() assert len(cams) > 4 assert 'FlashCam' in cams assert 'NectarCam' in cams for cam in cams: geom = CameraGeometry.from_name(cam) geom.info()
def test_known_camera_names(): cams = CameraGeometry.get_known_camera_names() assert len(cams) > 4 assert 'FlashCam' in cams assert 'NectarCam' in cams for cam in cams: geom = CameraGeometry.from_name(cam) geom.info()
def _generator(self): # container for LST data self.data = LSTDataContainer() self.data.meta['input_url'] = self.input_url self.data.meta['max_events'] = self.max_events # fill LST data from the CameraConfig table self.fill_lst_service_container_from_zfile() # Instrument information for tel_id in self.data.lst.tels_with_data: assert (tel_id == 0 or tel_id == 1) # only LST1 (for the moment id = 0) # optics info from standard optics.fits.gz file optics = OpticsDescription.from_name("LST") # camera info from LSTCam-[geometry_version].camgeom.fits.gz file geometry_version = 2 camera = CameraGeometry.from_name("LSTCam", geometry_version) tel_descr = TelescopeDescription( name='LST', type='LST', optics=optics, camera=camera ) self.n_camera_pixels = tel_descr.camera.n_pixels tels = {tel_id: tel_descr} # LSTs telescope position taken from MC from the moment tel_pos = {tel_id: [50., 50., 16] * u.m} subarray = SubarrayDescription("LST1 subarray") subarray.tels = tels subarray.positions = tel_pos self.data.inst.subarray = subarray # initialize general monitoring container self.initialize_mon_container() # loop on events for count, event in enumerate(self.multi_file): self.data.count = count # fill specific LST event data self.fill_lst_event_container_from_zfile(event) # fill general monitoring data self.fill_mon_container_from_zfile(event) # fill general R0 data self.fill_r0_container_from_zfile(event) yield self.data
def test_ChaudhuriKunduRingFitter(): geom = CameraGeometry.from_name('HESS-I') ring_rad = np.deg2rad( 1. * u.deg) * 15. # make sure this is in camera coordinates ring_width = np.deg2rad(0.05 * u.deg) * 15. geom_pixall = np.empty(geom.pix_x.shape + (2, )) geom_pixall[..., 0] = geom.pix_x.value geom_pixall[..., 1] = geom.pix_y.value # image = generate_muon_model(geom_pixall, ring_rad, ring_width, 0.3, 0.2) muon_model = partial(toymodel.generate_muon_model, radius=ring_rad.value, width=ring_width.value, centre_x=-0.2, centre_y=-0.3) toymodel_image, toy_signal, toy_noise = \ toymodel.make_toymodel_shower_image(geom, muon_model) clean_toy_mask = tailcuts_clean(geom, toymodel_image, boundary_thresh=5, picture_thresh=10) # camera_coord = CameraFrame(x=x,y=y,z=np.zeros(x.shape)*u.m, # focal_length = event.inst.optical_foclen[telid], rotation=geom.pix_rotation) muonring = muon_ring_finder.ChaudhuriKunduRingFitter(None) x = np.rad2deg((geom.pix_x.value / 15.) * u.rad) # .value y = np.rad2deg((geom.pix_y.value / 15.) * u.rad) # .value muonringparam = muonring.fit(x, y, toymodel_image * clean_toy_mask) dist = np.sqrt( np.power(x - muonringparam.ring_center_x, 2) + np.power(y - muonringparam.ring_center_y, 2)) ring_dist = np.abs(dist - muonringparam.ring_radius) muonringparam = muonring.fit( x, y, toymodel_image * (ring_dist < muonringparam.ring_radius * 0.4)) dist = np.sqrt( np.power(x - muonringparam.ring_center_x, 2) + np.power(y - muonringparam.ring_center_y, 2)) ring_dist = np.abs(dist - muonringparam.ring_radius) muonringparam = muonring.fit( x, y, toymodel_image * (ring_dist < muonringparam.ring_radius * 0.4)) print('Fitted ring radius', muonringparam.ring_radius, 'c.f.', ring_rad) print('Fitted ring centre', muonringparam.ring_center_x, muonringparam.ring_center_y) assert muonringparam.ring_radius is not ring_rad # .value assert muonringparam.ring_center_x is not -0.2 assert muonringparam.ring_center_y is not -0.3
def test_array_display(): """ check that we can do basic array display functionality """ from ctapipe.visualization.mpl_array import ArrayDisplay from ctapipe.image import timing_parameters # build a test subarray: tels = dict() tel_pos = dict() for ii, pos in enumerate([[0, 0, 0], [100, 0, 0], [-100, 0, 0]] * u.m): tels[ii + 1] = TelescopeDescription.from_name("MST", "NectarCam") tel_pos[ii + 1] = pos sub = SubarrayDescription(name="TestSubarray", tel_positions=tel_pos, tel_descriptions=tels) ad = ArrayDisplay(sub) ad.set_vector_rho_phi(1 * u.m, 90 * u.deg) # try setting a value vals = np.ones(sub.num_tels) ad.values = vals assert (vals == ad.values).all() # test using hillas params: hillas_dict = { 1: HillasParametersContainer(length=100.0 * u.m, psi=90 * u.deg), 2: HillasParametersContainer(length=20000 * u.cm, psi="95deg"), } grad = 2 intercept = 1 geom = CameraGeometry.from_name("LSTCam") rot_angle = 20 * u.deg hillas = HillasParametersContainer(x=0 * u.m, y=0 * u.m, psi=rot_angle) timing_rot20 = timing_parameters( geom, image=np.ones(geom.n_pixels), peak_time=intercept + grad * geom.pix_x.value, hillas_parameters=hillas, cleaning_mask=np.ones(geom.n_pixels, dtype=bool), ) gradient_dict = {1: timing_rot20.slope.value, 2: timing_rot20.slope.value} ad.set_vector_hillas( hillas_dict=hillas_dict, length=500, time_gradient=gradient_dict, angle_offset=0 * u.deg, ) ad.set_line_hillas(hillas_dict, range=300) ad.add_labels() ad.remove_labels()
def _display_camera_animation(self): #plt.style.use("ggplot") fig = plt.figure(num="ctapipe Camera Demo", figsize=(7, 7)) ax = plt.subplot(111) # load the camera geom = CameraGeometry.from_name(self.camera) disp = CameraDisplay(geom, ax=ax, autoupdate=True, ) disp.cmap = plt.cm.terrain def update(frame): centroid = np.random.uniform(-0.5, 0.5, size=2) width = np.random.uniform(0, 0.01) length = np.random.uniform(0, 0.03) + width angle = np.random.uniform(0, 360) intens = np.random.exponential(2) * 50 model = toymodel.generate_2d_shower_model(centroid=centroid, width=width, length=length, psi=angle * u.deg) image, sig, bg = toymodel.make_toymodel_shower_image(geom, model.pdf, intensity=intens, nsb_level_pe=5000) # alternate between cleaned and raw images if self._counter == self.cleanframes: plt.suptitle("Image Cleaning ON") self.imclean = True if self._counter == self.cleanframes*2: plt.suptitle("Image Cleaning OFF") self.imclean = False self._counter = 0 if self.imclean: cleanmask = tailcuts_clean(geom, image/80.0) for ii in range(3): dilate(geom, cleanmask) image[cleanmask == 0] = 0 # zero noise pixels self.log.debug("count = {}, image sum={} max={}" .format(self._counter, image.sum(), image.max())) disp.image = image if self.autoscale: disp.set_limits_percent(95) else: disp.set_limits_minmax(-100, 4000) disp.axes.figure.canvas.draw() self._counter += 1 return [ax,] self.anim = FuncAnimation(fig, update, interval=self.delay, blit=self.blit) plt.show()
def test_to_and_from_table(): geom = CameraGeometry.from_name("LSTCam") tab = geom.to_table() geom2 = geom.from_table(tab) assert geom.cam_id == geom2.cam_id assert (geom.pix_x == geom2.pix_x).all() assert (geom.pix_y == geom2.pix_y).all() assert (geom.pix_area == geom2.pix_area).all() assert geom.pix_type == geom2.pix_type
def test_overlay_disp_vector(): from ctapipe.image import hillas_parameters geom = CameraGeometry.from_name('LSTCam') image = np.random.rand(geom.n_pixels) display = CameraDisplay(geom, image) hillas = hillas_parameters(geom, image) disp = disp_parameters_event(hillas, 0.1 * u.m, 0.3 * u.m) overlay_disp_vector(display, disp, hillas)
def test_known_camera_names(): """ Check that we can get a list of known camera names """ cams = CameraGeometry.get_known_camera_names() assert len(cams) > 4 assert 'FlashCam' in cams assert 'NectarCam' in cams for cam in cams: geom = CameraGeometry.from_name(cam) geom.info()
def test_to_and_from_table(): geom = CameraGeometry.from_name("LSTCam") tab = geom.to_table() geom2 = geom.from_table(tab) assert geom.cam_id == geom2.cam_id assert (geom.pix_x == geom2.pix_x).all() assert (geom.pix_y == geom2.pix_y).all() assert (geom.pix_area == geom2.pix_area).all() assert geom.pix_type == geom2.pix_type
def test_camera_coordinate_transform(camera_name): '''test conversion of the coordinates stored in a camera frame''' from ctapipe.coordinates import EngineeringCameraFrame geom = CameraGeometry.from_name(camera_name) trans_geom = geom.transform_to(EngineeringCameraFrame()) unit = geom.pix_x.unit assert np.allclose(geom.pix_x.to_value(unit), -trans_geom.pix_y.to_value(unit)) assert np.allclose(geom.pix_y.to_value(unit), -trans_geom.pix_x.to_value(unit))
def __init__(self, config=None, tool=None, **kwargs): """ Constructor Parameters ---------- config: traitlets.loader.Config Configuration specified by config file or cmdline arguments. Used to set traitlet values. Set to None if no configuration to pass. tool: ctapipe.core.Tool Tool executable that is calling this component. Passes the correct logger to the component. Set to None if no Tool to pass. kwargs: dict Additional parameters to be passed. NOTE: The file mask of the data to read can be passed with the 'input_url' parameter. """ file_list = glob.glob(kwargs['input_url']) file_list.sort() # EventSource can not handle file wild cards as input_url # To overcome this we substitute the input_url with first file matching # the specified file mask. del kwargs['input_url'] super().__init__(config=config, tool=tool, input_url=file_list[0], **kwargs) try: import uproot except ImportError: msg = "The `uproot` python module is required to access the MAGIC data" self.log.error(msg) raise # Retrieving the list of run numbers corresponding to the data files run_numbers = list(map(self._get_run_number, file_list)) self.run_numbers = np.unique(run_numbers) # # Setting up the current run with the first run present in the data # self.current_run = self._set_active_run(run_number=0) self.current_run = None # MAGIC telescope positions in m wrt. to the center of CTA simulations self.magic_tel_positions = { 1: [-27.24, -146.66, 50.00] * u.m, 2: [-96.44, -96.77, 51.00] * u.m } # MAGIC telescope description optics = OpticsDescription.from_name('MAGIC') geom = CameraGeometry.from_name('MAGICCam') self.magic_tel_description = TelescopeDescription(optics=optics, camera=geom) self.magic_tel_descriptions = {1: self.magic_tel_description, 2: self.magic_tel_description} self.magic_subarray = SubarrayDescription('MAGIC', self.magic_tel_positions, self.magic_tel_descriptions)
def test_to_and_from_table(): """ Check converting to and from an astropy Table """ geom = CameraGeometry.from_name("LSTCam") tab = geom.to_table() geom2 = geom.from_table(tab) assert geom.cam_id == geom2.cam_id assert (geom.pix_x == geom2.pix_x).all() assert (geom.pix_y == geom2.pix_y).all() assert (geom.pix_area == geom2.pix_area).all() assert geom.pix_type == geom2.pix_type
def test_hillas_overlay(): from ctapipe.visualization import CameraDisplay disp = CameraDisplay(CameraGeometry.from_name("LSTCam")) hillas = CameraHillasParametersContainer(x=0.1 * u.m, y=-0.1 * u.m, length=0.5 * u.m, width=0.2 * u.m, psi=90 * u.deg) disp.overlay_moments(hillas)
def test_camera_display_single(): """ test CameraDisplay functionality """ from ..mpl import CameraDisplay geom = CameraGeometry.from_name("LSTCam") disp = CameraDisplay(geom) image = ones(len(geom.pix_x), dtype=float) disp.image = image disp.add_colorbar() disp.cmap = 'spectral' disp.set_limits_minmax(0, 10) disp.set_limits_percent(95)
def test_ChaudhuriKunduRingFitter(): geom = CameraGeometry.from_name('LSTCam') focal_length = u.Quantity(28, u.m) ring_radius = u.Quantity(0.4, u.m) # make sure this is in camera coordinates ring_width = u.Quantity(0.03, u.m) center_x = u.Quantity(-0.2, u.m) center_y = u.Quantity(-0.3, u.m) muon_model = RingGaussian( x=center_x, y=center_y, sigma=ring_width, radius=ring_radius, ) image, _, _ = muon_model.generate_image( geom, intensity=1000, nsb_level_pe=5, ) clean_mask = tailcuts_clean( geom, image, boundary_thresh=5, picture_thresh=10 ) fitter = muon_ring_finder.ChaudhuriKunduRingFitter() x = geom.pix_x / focal_length * u.rad y = geom.pix_y / focal_length * u.rad # fit 3 times, first iteration use cleaning, after that use # distance to previous fit result result = None for _ in range(3): if result is None: mask = clean_mask else: dist = np.sqrt((x - result.ring_center_x)**2 + (y - result.ring_center_y)**2) ring_dist = np.abs(dist - result.ring_radius) mask = ring_dist < (result.ring_radius * 0.4) result = fitter.fit(x[mask], y[mask], image[mask]) assert np.isclose( result.ring_radius.to_value(u.rad), ring_radius / focal_length, rtol=0.05, ) assert np.isclose( result.ring_center_x.to_value(u.rad), center_x / focal_length, rtol=0.05 ) assert np.isclose( result.ring_center_y.to_value(u.rad), center_y / focal_length, rtol=0.05, )
def test_camera_display_single(): """ test CameraDisplay functionality """ from ..mpl import CameraDisplay geom = CameraGeometry.from_name("LSTCam") disp = CameraDisplay(geom) image = ones(len(geom.pix_x), dtype=float) disp.image = image disp.add_colorbar() disp.cmap = 'spectral' disp.set_limits_minmax(0, 10) disp.set_limits_percent(95)
def test_skewness(): np.random.seed(42) geom = CameraGeometry.from_name('LSTCam') width = 0.03 * u.m length = 0.15 * u.m intensity = 2500 xs = u.Quantity([0.5, 0.5, -0.5, -0.5], u.m) ys = u.Quantity([0.5, -0.5, 0.5, -0.5], u.m) psis = Angle([-90, -45, 0, 45, 90], unit='deg') skews = [0, 0.3, 0.6] for x, y, psi, skew in itertools.product(xs, ys, psis, skews): # make a toymodel shower model model = toymodel.SkewedGaussian( x=x, y=y, width=width, length=length, psi=psi, skewness=skew, ) _, signal, _ = model.generate_image( geom, intensity=intensity, nsb_level_pe=5, ) result = hillas_parameters(geom, signal) assert quantity_approx(result.x, x, rel=0.1) assert quantity_approx(result.y, y, rel=0.1) assert quantity_approx(result.width, width, rel=0.1) assert quantity_approx(result.length, length, rel=0.1) psi_same = result.psi.to_value(u.deg) == approx(psi.deg, abs=3) psi_opposite = abs(result.psi.to_value(u.deg) - psi.deg) == approx( 180.0, abs=3) assert psi_same or psi_opposite # if we have delta the other way around, we get a negative sign for skewness # skewness is quite imprecise, maybe we could improve this somehow if psi_same: assert result.skewness == approx(skew, abs=0.3) else: assert result.skewness == approx(-skew, abs=0.3) assert signal.sum() == result.intensity
def test_apply_time_delta_cleaning(): geom = CameraGeometry.from_name("LSTCam") peak_time = np.zeros(geom.n_pixels, dtype=np.float64) pixel = 40 neighbors = geom.neighbors[pixel] peak_time[neighbors] = 32.0 peak_time[pixel] = 30.0 mask = peak_time > 0 # Test unchanged td_mask = cleaning.apply_time_delta_cleaning(geom, mask, peak_time, min_number_neighbors=1, time_limit=5) test_mask = mask.copy() assert (test_mask == td_mask).all() # Test time_limit noise_neighbor = neighbors[0] peak_time[noise_neighbor] += 10 td_mask = cleaning.apply_time_delta_cleaning(geom, mask, peak_time, min_number_neighbors=1, time_limit=5) test_mask = mask.copy() test_mask[noise_neighbor] = 0 assert (test_mask == td_mask).all() # Test min_number_neighbors td_mask = cleaning.apply_time_delta_cleaning(geom, mask, peak_time, min_number_neighbors=4, time_limit=5) test_mask = mask.copy() test_mask[neighbors] = 0 assert (test_mask == td_mask).all() # Test unselected neighbors mask[156] = 0 peak_time[noise_neighbor] -= 10 td_mask = cleaning.apply_time_delta_cleaning(geom, mask, peak_time, min_number_neighbors=3, time_limit=5) test_mask = mask.copy() test_mask[[41, 157]] = 0 assert (test_mask == td_mask).all()
def _generator(self): # container for NectarCAM data self.data = NectarCAMDataContainer() self.data.meta['input_url'] = self.input_url # fill data from the CameraConfig table self.fill_nectarcam_service_container_from_zfile() # Instrument information for tel_id in self.data.nectarcam.tels_with_data: assert (tel_id == 0) # only one telescope for the moment (id = 0) # optics info from standard optics.fits.gz file optics = OpticsDescription.from_name("MST") optics.tel_subtype = '' # to correct bug in reading # camera info from NectarCam-[geometry_version].camgeom.fits.gz file geometry_version = 2 camera = CameraGeometry.from_name("NectarCam", geometry_version) tel_descr = TelescopeDescription(optics, camera) tel_descr.optics.tel_subtype = '' # to correct bug in reading self.n_camera_pixels = tel_descr.camera.n_pixels tels = {tel_id: tel_descr} # LSTs telescope position tel_pos = {tel_id: [0., 0., 0] * u.m} self.subarray = SubarrayDescription("MST prototype subarray") self.subarray.tels = tels self.subarray.positions = tel_pos self.data.inst.subarray = self.subarray # loop on events for count, event in enumerate(self.multi_file): self.data.count = count # fill specific NectarCAM event data self.fill_nectarcam_event_container_from_zfile(event) # fill general R0 data self.fill_r0_container_from_zfile(event) yield self.data
def test_write_read(tmpdir): """ Check that serialization to disk doesn't lose info """ filename = str(tmpdir.join('testcamera.fits.gz')) geom = CameraGeometry.from_name("LSTCam") geom.to_table().write(filename, overwrite=True) geom2 = geom.from_table(filename) assert geom.cam_id == geom2.cam_id assert (geom.pix_x == geom2.pix_x).all() assert (geom.pix_y == geom2.pix_y).all() assert (geom.pix_area == geom2.pix_area).all() assert geom.pix_type == geom2.pix_type
def test_camera_display_multiple(): """ create a figure with 2 subplots, each with a CameraDisplay """ from ..mpl import CameraDisplay geom = CameraGeometry.from_name("LSTCam") fig, ax = plt.subplots(2, 1) d1 = CameraDisplay(geom, ax=ax[0]) d2 = CameraDisplay(geom, ax=ax[1]) image = ones(len(geom.pix_x), dtype=float) d1.image = image d2.image = image
def test_pixel_shapes(pix_type): """ test CameraDisplay functionality """ from ..mpl_camera import CameraDisplay geom = CameraGeometry.from_name("LSTCam") geom.pix_type = pix_type disp = CameraDisplay(geom) image = np.random.normal(size=len(geom.pix_x)) disp.image = image disp.add_colorbar() disp.highlight_pixels([1, 2, 3, 4, 5]) disp.add_ellipse(centroid=(0, 0), width=0.1, length=0.1, angle=0.1)
def test_write_read(tmpdir): filename = str(tmpdir.join('testcamera.fits.gz')) geom = CameraGeometry.from_name("LSTCam") geom.to_table().write(filename, overwrite=True) geom2 = geom.from_table(filename) assert geom.cam_id == geom2.cam_id assert (geom.pix_x == geom2.pix_x).all() assert (geom.pix_y == geom2.pix_y).all() assert (geom.pix_area == geom2.pix_area).all() assert geom.pix_type == geom2.pix_type
def test_slicing(): geom = CameraGeometry.from_name("NectarCam") sliced1 = geom[100:200] assert len(sliced1.pix_x) == 100 assert len(sliced1.pix_y) == 100 assert len(sliced1.pix_area) == 100 assert len(sliced1.pix_id) == 100 sliced2 = geom[[5, 7, 8, 9, 10]] assert sliced2.pix_id[0] == 5 assert sliced2.pix_id[1] == 7 assert len(sliced2.pix_x) == 5
def test_slicing(): geom = CameraGeometry.from_name("NectarCam") sliced1 = geom[100:200] assert len(sliced1.pix_x) == 100 assert len(sliced1.pix_y) == 100 assert len(sliced1.pix_area) == 100 assert len(sliced1.pix_id) == 100 sliced2 = geom[[5, 7, 8, 9, 10]] assert sliced2.pix_id[0] == 5 assert sliced2.pix_id[1] == 7 assert len(sliced2.pix_x) == 5
def test_camera_display_multiple(): """ create a figure with 2 subplots, each with a CameraDisplay """ from ..mpl_camera import CameraDisplay geom = CameraGeometry.from_name("LSTCam") fig, ax = plt.subplots(2, 1) d1 = CameraDisplay(geom, ax=ax[0]) d2 = CameraDisplay(geom, ax=ax[1]) image = ones(len(geom.pix_x), dtype=float) d1.image = image d2.image = image
def test_write_read(tmpdir): filename = str(tmpdir.join('testcamera.fits.gz')) geom = CameraGeometry.from_name("LSTCam") geom.to_table().write(filename, overwrite=True) geom2 = geom.from_table(filename) assert geom.cam_id == geom2.cam_id assert (geom.pix_x == geom2.pix_x).all() assert (geom.pix_y == geom2.pix_y).all() assert (geom.pix_area == geom2.pix_area).all() assert geom.pix_type == geom2.pix_type
def test_with_toy(): np.random.seed(42) geom = CameraGeometry.from_name("LSTCam") width = 0.03 * u.m length = 0.15 * u.m width_uncertainty = 0.00094 * u.m length_uncertainty = 0.00465 * u.m intensity = 500 xs = u.Quantity([0.5, 0.5, -0.5, -0.5], u.m) ys = u.Quantity([0.5, -0.5, 0.5, -0.5], u.m) psis = Angle([-90, -45, 0, 45, 90], unit="deg") for x, y in zip(xs, ys): for psi in psis: # make a toymodel shower model model = toymodel.Gaussian( x=x, y=y, width=width, length=length, psi=psi, ) image, signal, noise = model.generate_image( geom, intensity=intensity, nsb_level_pe=5, ) result = hillas_parameters(geom, signal) assert u.isclose(result.x, x, rtol=0.1) assert u.isclose(result.y, y, rtol=0.1) assert u.isclose(result.width, width, rtol=0.1) assert u.isclose(result.width_uncertainty, width_uncertainty, rtol=0.4) assert u.isclose(result.length, length, rtol=0.1) assert u.isclose(result.length_uncertainty, length_uncertainty, rtol=0.4) assert (result.psi.to_value(u.deg) == approx( psi.deg, abs=2)) or abs(result.psi.to_value(u.deg) - psi.deg) == approx(180.0, abs=2) assert signal.sum() == result.intensity
def test_intensity(seed, monkeypatch): """ Test generation of the toymodel roughly follows the given intensity. Tests once with passing a custom rng instance, once with relying on the modules rng. """ from ctapipe.image import toymodel 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 sure we set a fixed seed for this test even when testing the # API without giving the rng monkeypatch.setattr(toymodel, "TOYMODEL_RNG", np.random.default_rng(0)) # make a toymodel shower model model = toymodel.Gaussian(x=x, y=y, width=width, length=length, psi=psi) if seed is None: _, signal, _ = model.generate_image(geom, intensity=intensity, nsb_level_pe=5) else: rng = np.random.default_rng(seed) _, signal, _ = model.generate_image(geom, intensity=intensity, nsb_level_pe=5, rng=rng) # 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 test_convert_geometry(cam_id, rot): geom = CameraGeometry.from_name(cam_id) model = generate_2d_shower_model(centroid=(0.4, 0), width=0.01, length=0.03, psi="25d") _, image, _ = make_toymodel_shower_image(geom, model.pdf, intensity=50, nsb_level_pe=100) hillas_0 = hillas_parameters(geom, image) if geom.pix_type == 'hexagonal': convert_geometry_1d_to_2d = convert_geometry_hex1d_to_rect2d convert_geometry_back = convert_geometry_rect2d_back_to_hexe1d geom2d, image2d = convert_geometry_1d_to_2d(geom, image, geom.cam_id + str(rot), add_rot=rot) geom1d, image1d = convert_geometry_back(geom2d, image2d, geom.cam_id + str(rot), add_rot=rot) else: if geom.cam_id == "ASTRICam": convert_geometry_1d_to_2d = astri_to_2d_array convert_geometry_back = array_2d_to_astri elif geom.cam_id == "CHEC": convert_geometry_1d_to_2d = chec_to_2d_array convert_geometry_back = array_2d_to_chec else: print("camera {geom.cam_id} not implemented") return image2d = convert_geometry_1d_to_2d(image) image1d = convert_geometry_back(image2d) hillas_1 = hillas_parameters(geom, image1d) # if __name__ == "__main__": # plot_cam(geom, geom2d, geom1d, image, image2d, image1d) # plt.tight_layout() # plt.pause(.1) assert np.abs(hillas_1.phi - hillas_0.phi).deg < 1.0
def _generator(self): # container for LST data self.data = LSTDataContainer() self.data.meta['input_url'] = self.input_url self.data.meta['max_events'] = self.max_events # fill LST data from the CameraConfig table self.fill_lst_service_container_from_zfile() # Instrument information for tel_id in self.data.lst.tels_with_data: assert (tel_id == 0) # only LST1 for the moment (id = 0) # optics info from standard optics.fits.gz file optics = OpticsDescription.from_name("LST") optics.tel_subtype = '' # to correct bug in reading # camera info from LSTCam-[geometry_version].camgeom.fits.gz file geometry_version = 2 camera = CameraGeometry.from_name("LSTCam", geometry_version) tel_descr = TelescopeDescription(optics, camera) self.n_camera_pixels = tel_descr.camera.n_pixels tels = {tel_id: tel_descr} # LSTs telescope position taken from MC from the moment tel_pos = {tel_id: [50., 50., 16] * u.m} subarray = SubarrayDescription("LST1 subarray") subarray.tels = tels subarray.positions = tel_pos self.data.inst.subarray = subarray # loop on events for count, event in enumerate(self.multi_file): self.data.count = count # fill specific LST event data self.fill_lst_event_container_from_zfile(event) # fill general R0 data self.fill_r0_container_from_zfile(event) yield self.data
def __init__(self, obstime=None): if obstime is None: self.obstime = Time('2013-11-01T03:00') else: self.obstime = obstime self.magic_location = EarthLocation(lat=Angle("28°45′42.462″"), lon=Angle("-17°53′26.525″"), height=2199.4 * u.m) self.altaz = AltAz(location=self.magic_location, obstime=self.obstime) self.focal_length = 16.97*u.m # Maybe get from file? self.camera = CameraGeometry.from_name('MAGICCam')
def test_slicing(): """ Check that we can slice a camera into a smaller one """ geom = CameraGeometry.from_name("NectarCam") sliced1 = geom[100:200] assert len(sliced1.pix_x) == 100 assert len(sliced1.pix_y) == 100 assert len(sliced1.pix_area) == 100 assert len(sliced1.pix_id) == 100 sliced2 = geom[[5, 7, 8, 9, 10]] assert sliced2.pix_id[0] == 5 assert sliced2.pix_id[1] == 7 assert len(sliced2.pix_x) == 5
def test_dl1_charge_calib(example_subarray): camera = CameraGeometry.from_name("CHEC") n_pixels = camera.n_pixels n_samples = 96 mid = n_samples // 2 pulse_sigma = 6 random = np.random.RandomState(1) x = np.arange(n_samples) # Randomize times and create pulses time_offset = random.uniform(mid - 10, mid + 10, n_pixels)[:, np.newaxis] y = norm.pdf(x, time_offset, pulse_sigma).astype("float32") # Define absolute calibration coefficients absolute = random.uniform(100, 1000, n_pixels).astype("float32") y *= absolute[:, np.newaxis] # Define relative coefficients relative = random.normal(1, 0.01, n_pixels) y /= relative[:, np.newaxis] # Define pedestal pedestal = random.uniform(-4, 4, n_pixels) y += pedestal[:, np.newaxis] event = DataContainer() telid = list(example_subarray.tel.keys())[0] event.dl0.tel[telid].waveform = y # Test default calibrator = CameraCalibrator( subarray=example_subarray, image_extractor=FullWaveformSum(subarray=example_subarray), ) calibrator(event) np.testing.assert_allclose(event.dl1.tel[telid].image, y.sum(1), rtol=1e-4) event.calibration.tel[telid].dl1.time_shift = time_offset event.calibration.tel[telid].dl1.pedestal_offset = pedestal * n_samples event.calibration.tel[telid].dl1.absolute_factor = absolute event.calibration.tel[telid].dl1.relative_factor = relative # Test without need for timing corrections calibrator = CameraCalibrator( subarray=example_subarray, image_extractor=FullWaveformSum(subarray=example_subarray), ) calibrator(event) np.testing.assert_allclose(event.dl1.tel[telid].image, 1, rtol=1e-5)
def test_tailcuts_clean_simple(): geom = CameraGeometry.from_name("LSTCam") image = np.zeros_like(geom.pix_id, dtype=np.float64) num_pix = 40 some_neighs = geom.neighbors[num_pix][0:3] # pick 3 neighbors image[num_pix] = 5.0 # set a single image pixel image[some_neighs] = 3.0 # make some boundaries that are neighbors image[10] = 3.0 # a boundary that is not a neighbor mask = cleaning.tailcuts_clean(geom, image, picture_thresh=4.5, boundary_thresh=2.5) assert 10 not in geom.pix_id[mask] assert set(some_neighs).union({num_pix}) == set(geom.pix_id[mask]) assert np.count_nonzero(mask) == 4
def _generator(self): # container for NectarCAM data self.data = NectarCAMDataContainer() self.data.meta['input_url'] = self.input_url # fill data from the CameraConfig table self.fill_nectarcam_service_container_from_zfile() # Instrument information for tel_id in self.data.nectarcam.tels_with_data: assert (tel_id == 0) # only one telescope for the moment (id = 0) # optics info from standard optics.fits.gz file optics = OpticsDescription.from_name("MST") optics.tel_subtype = '' # to correct bug in reading # camera info from NectarCam-[geometry_version].camgeom.fits.gz file geometry_version = 2 camera = CameraGeometry.from_name("NectarCam", geometry_version) tel_descr = TelescopeDescription(optics, camera) tel_descr.optics.tel_subtype = '' # to correct bug in reading self.n_camera_pixels = tel_descr.camera.n_pixels tels = {tel_id: tel_descr} # LSTs telescope position tel_pos = {tel_id: [0., 0., 0] * u.m} self.subarray = SubarrayDescription("MST prototype subarray") self.subarray.tels = tels self.subarray.positions = tel_pos self.data.inst.subarray = self.subarray # loop on events for count, event in enumerate(self.multi_file): self.data.count = count # fill specific NectarCAM event data self.fill_nectarcam_event_container_from_zfile(event) # fill general R0 data self.fill_r0_container_from_zfile(event) yield self.data
def test_skewness(): np.random.seed(42) geom = CameraGeometry.from_name('LSTCam') width = 0.03 * u.m length = 0.15 * u.m intensity = 2500 xs = u.Quantity([0.5, 0.5, -0.5, -0.5], u.m) ys = u.Quantity([0.5, -0.5, 0.5, -0.5], u.m) psis = Angle([-90, -45, 0, 45, 90], unit='deg') skews = [0, 0.3, 0.6] for x, y, psi, skew in itertools.product(xs, ys, psis, skews): # make a toymodel shower model model = toymodel.SkewedGaussian( x=x, y=y, width=width, length=length, psi=psi, skewness=skew, ) _, signal, _ = model.generate_image( geom, intensity=intensity, nsb_level_pe=5, ) result = hillas_parameters(geom, signal) assert quantity_approx(result.x, x, rel=0.1) assert quantity_approx(result.y, y, rel=0.1) assert quantity_approx(result.width, width, rel=0.1) assert quantity_approx(result.length, length, rel=0.1) psi_same = result.psi.to_value(u.deg) == approx(psi.deg, abs=3) psi_opposite = abs(result.psi.to_value(u.deg) - psi.deg) == approx(180.0, abs=3) assert psi_same or psi_opposite # if we have delta the other way around, we get a negative sign for skewness # skewness is quite imprecise, maybe we could improve this somehow if psi_same: assert result.skewness == approx(skew, abs=0.3) else: assert result.skewness == approx(-skew, abs=0.3) assert signal.sum() == result.intensity
def test_apply_time_delta_cleaning(): geom = CameraGeometry.from_name("LSTCam") pulse_time = np.zeros(geom.n_pixels, dtype=np.float) pixel = 40 neighbours = geom.neighbors[pixel] pulse_time[neighbours] = 32.0 pulse_time[pixel] = 30.0 mask = pulse_time > 0 # Test unchanged td_mask = cleaning.apply_time_delta_cleaning( geom, mask, pulse_time, min_number_neighbors=1, time_limit=5, ) test_mask = mask.copy() assert (test_mask == td_mask).all() # Test time_limit noise_neighbour = neighbours[0] pulse_time[noise_neighbour] += 10 td_mask = cleaning.apply_time_delta_cleaning( geom, mask, pulse_time, min_number_neighbors=1, time_limit=5, ) test_mask = mask.copy() test_mask[noise_neighbour] = 0 assert (test_mask == td_mask).all() # Test min_number_neighbours td_mask = cleaning.apply_time_delta_cleaning( geom, mask, pulse_time, min_number_neighbors=4, time_limit=5, ) test_mask = mask.copy() test_mask[neighbours] = 0 assert (test_mask == td_mask).all()
def __init__(self): self.fig = plt.figure(1, figsize=(7, 7)) self.ax = self.fig.add_subplot(111) # TODO Make this more flexible for lab setup self.required_pe = 100 self.geom = CameraGeometry.from_name("CHEC") self.npix = len(self.geom.pix_id) self.total_scale = np.ones(self.npix) self.pixel_mask = np.ones(self.npix) self.camera_curve_center_x = 1 self.camera_curve_center_y = 0 self.camera_curve_radius = 1 self.pixel_pos = np.load( "/Users/armstrongt/Software/CTA/CHECsoft/CHECAnalysis/targetpipe/targetpipe/io/checm_pixel_pos.npy" ) self.pix_size = np.sqrt(self.geom.pix_area[0]).value self.fiducial_radius = 0.2 self.fiducial_center = self.camera_curve_center_x + self.camera_curve_radius * np.cos( np.pi ) # This is a little confusing, is it going to be set up to change the position of the lightsource self.lightsource_distance = 1 self.lightsource_x = 0 self.lightsource_y = 0 self.ang_dist_file = np.loadtxt( "/Users/armstrongt/Workspace/CTA/MCValidation/src/ang_dist_2.dat", unpack=True) theta_f = np.pi / 2 - np.arccos( self.fiducial_radius / self.lightsource_distance) # theta_ls = theta_f#self.lightsource_angle * np.pi / 180 theta_p = np.arctan(self.pix_size / (2 * self.lightsource_distance)) # self.lightsource_angle = theta_ls * 180 / np.pi self.lightsource_angle = max(self.ang_dist_file[0]) theta_ls = self.lightsource_angle * np.pi / 180 self.lightsource_sa = 2 * np.pi * (1 - np.cos(theta_ls)) self.fiducial_sa = 2 * np.pi * (1 - np.cos(theta_f)) self.fiducial_percent = self.fiducial_sa / self.lightsource_sa if self.fiducial_percent > 1: self.fiducial_percent = 1 self.pix_sa = 2 * np.pi * (1 - np.cos(theta_p)) self.pix_percent = self.pix_sa / self.lightsource_sa if self.pix_percent > 1: self.pix_percent = 1 photons = self.set_illumination(self.required_pe) print(photons) print(self.lightsource_angle)
def __init__(self, run_file_mask): """ Constructor of the class. Defines the run to use and the camera pixel arrangement. Parameters ---------- run_file_mask: str A path mask for files belonging to the run. Must correspond to a single run or an exception will be raised. Must correspond to calibrated ("sorcerer"-level) data. """ self.run_file_mask = run_file_mask # Loading the camera geometry camera_geometry = CameraGeometry.from_name('MAGICCam') self.camera_pixel_x = camera_geometry.pix_x.value self.camera_pixel_y = camera_geometry.pix_y.value self.n_camera_pixels = len(self.camera_pixel_x) # Preparing the lists of M1/2 data files file_list = glob.glob(run_file_mask) self.m1_file_list = list(filter(lambda name: '_M1_' in name, file_list)) self.m1_file_list.sort() self.m2_file_list = list(filter(lambda name: '_M2_' in name, file_list)) self.m2_file_list.sort() # Retrieving the list of run numbers corresponding to the data files run_numbers = list(map(self._get_run_number, file_list)) run_numbers = np.unique(run_numbers) # Checking if a single run is going to be read if len(run_numbers) > 1: raise ValueError("Run mask corresponds to more than one run: {}".format(run_numbers)) # Reading the event data self.event_data = dict() self.event_data['M1'] = self.load_events(self.m1_file_list) self.event_data['M2'] = self.load_events(self.m2_file_list) # Detecting pedestal events self.pedestal_ids = self._find_pedestal_events() # Detecting stereo events self.stereo_ids = self._find_stereo_events() # Detecting mono events self.mono_ids = self._find_mono_events()
def test_ChaudhuriKunduRingFitter(): geom = CameraGeometry.from_name('HESS-I') ring_rad = np.deg2rad(1. * u.deg) * 15. # make sure this is in camera coordinates ring_width = np.deg2rad(0.05 * u.deg) * 15. geom_pixall = np.empty(geom.pix_x.shape + (2,)) geom_pixall[..., 0] = geom.pix_x.value geom_pixall[..., 1] = geom.pix_y.value # image = generate_muon_model(geom_pixall, ring_rad, ring_width, 0.3, 0.2) muon_model = partial(toymodel.generate_muon_model, radius=ring_rad.value, width=ring_width.value, centre_x=-0.2, centre_y=-0.3) toymodel_image, toy_signal, toy_noise = \ toymodel.make_toymodel_shower_image(geom, muon_model) clean_toy_mask = tailcuts_clean(geom, toymodel_image, boundary_thresh=5, picture_thresh=10) muonring = muon_ring_finder.ChaudhuriKunduRingFitter(None) x = np.rad2deg((geom.pix_x.value / 15.) * u.rad) # .value y = np.rad2deg((geom.pix_y.value / 15.) * u.rad) # .value muonringparam = muonring.fit(x, y, toymodel_image * clean_toy_mask) dist = np.sqrt(np.power(x - muonringparam.ring_center_x, 2) + np.power(y - muonringparam.ring_center_y, 2)) ring_dist = np.abs(dist - muonringparam.ring_radius) muonringparam = muonring.fit(x, y, toymodel_image * (ring_dist < muonringparam.ring_radius * 0.4)) dist = np.sqrt(np.power(x - muonringparam.ring_center_x, 2) + np.power(y - muonringparam.ring_center_y, 2)) ring_dist = np.abs(dist - muonringparam.ring_radius) muonringparam = muonring.fit(x, y, toymodel_image * (ring_dist < muonringparam.ring_radius * 0.4)) print('Fitted ring radius', muonringparam.ring_radius, 'c.f.', ring_rad) print('Fitted ring centre', muonringparam.ring_center_x, muonringparam.ring_center_y) assert muonringparam.ring_radius is not ring_rad # .value assert muonringparam.ring_center_x is not -0.2 assert muonringparam.ring_center_y is not -0.3
def test_dilate(): geom = CameraGeometry.from_name("LSTCam") mask = np.zeros_like(geom.pix_id, dtype=bool) mask[100] = True # a single pixel far from a border is true. assert mask.sum() == 1 # dilate a single row dmask = cleaning.dilate(geom, mask) assert dmask.sum() == 1 + 6 # dilate a second row dmask = cleaning.dilate(geom, dmask) assert dmask.sum() == 1 + 6 + 12 # dilate a third row dmask = cleaning.dilate(geom, dmask) assert dmask.sum() == 1 + 6 + 12 + 18
def test_tailcuts_clean_simple(): geom = CameraGeometry.from_name("LSTCam") image = np.zeros_like(geom.pix_id, dtype=np.float) num_pix = 40 some_neighs = geom.neighbors[num_pix][0:3] # pick 4 neighbors image[num_pix] = 5.0 # set a single image pixel image[some_neighs] = 3.0 # make some boundaries that are neighbors image[10] = 3.0 # a boundary that is not a neighbor mask = cleaning.tailcuts_clean(geom, image, picture_thresh=4.5, boundary_thresh=2.5) print((mask > 0).sum(), "clean pixels") print(geom.pix_id[mask]) assert 10 not in geom.pix_id[mask] assert set(some_neighs).union({num_pix}) == set(geom.pix_id[mask]) assert (mask > 0).sum() == 4
def test_neighbor_pixels(cam_id): """ test if each camera has a reasonable number of neighbor pixels (4 for rectangular, and 6 for hexagonal. Other than edge pixels, the majority should have the same value """ geom = CameraGeometry.from_name(cam_id) n_pix = len(geom.pix_id) n_neighbors = [len(x) for x in geom.neighbors] if geom.pix_type.startswith('hex'): assert n_neighbors.count(6) > 0.5 * n_pix assert n_neighbors.count(6) > n_neighbors.count(4) if geom.pix_type.startswith('rect'): assert n_neighbors.count(4) > 0.5 * n_pix assert n_neighbors.count(5) == 0 assert n_neighbors.count(6) == 0 assert n_neighbors.count(1) == 0 # no pixel should have a single neighbor
def test_with_toy(): np.random.seed(42) geom = CameraGeometry.from_name('LSTCam') width = 0.03 * u.m length = 0.15 * u.m intensity = 500 xs = u.Quantity([0.5, 0.5, -0.5, -0.5], u.m) ys = u.Quantity([0.5, -0.5, 0.5, -0.5], u.m) psis = Angle([-90, -45, 0, 45, 90], unit='deg') for x, y in zip(xs, ys): for psi in psis: # make a toymodel shower model model = toymodel.Gaussian( x=x, y=y, width=width, length=length, psi=psi, ) image, signal, noise = model.generate_image( geom, intensity=intensity, nsb_level_pe=5, ) result = hillas_parameters(geom, signal) assert quantity_approx(result.x, x, rel=0.1) assert quantity_approx(result.y, y, rel=0.1) assert quantity_approx(result.width, width, rel=0.1) assert quantity_approx(result.length, length, rel=0.1) assert ( (result.psi.to_value(u.deg) == approx(psi.deg, abs=2)) or abs(result.psi.to_value(u.deg) - psi.deg) == approx(180.0, abs=2) ) assert signal.sum() == result.intensity