def test_FitGammaHillas(): ''' a test of the complete fit procedure on one event including: • tailcut cleaning • hillas parametrisation • GreatCircle creation • direction fit • position fit in the end, proper units in the output are asserted ''' filename = get_dataset("gamma_test.simtel.gz") fit = HillasReconstructor() cam_geom = {} tel_phi = {} tel_theta = {} source = hessio_event_source(filename) for event in source: hillas_dict = {} for tel_id in event.dl0.tels_with_data: if tel_id not in cam_geom: cam_geom[tel_id] = CameraGeometry.guess( event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], event.inst.optical_foclen[tel_id]) tel_phi[tel_id] = event.mc.tel[tel_id].azimuth_raw * u.rad tel_theta[tel_id] = (np.pi/2-event.mc.tel[tel_id].altitude_raw)*u.rad pmt_signal = event.r0.tel[tel_id].adc_sums[0] mask = tailcuts_clean(cam_geom[tel_id], pmt_signal, picture_thresh=10., boundary_thresh=5.) pmt_signal[mask == 0] = 0 try: moments = hillas_parameters(event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], pmt_signal) hillas_dict[tel_id] = moments except HillasParameterizationError as e: print(e) continue if len(hillas_dict) < 2: continue fit_result = fit.predict(hillas_dict, event.inst, tel_phi, tel_theta) print(fit_result) fit_result.alt.to(u.deg) fit_result.az.to(u.deg) fit_result.core_x.to(u.m) assert fit_result.is_valid return
def display_event(event): """an extremely inefficient display. It creates new instances of CameraDisplay for every event and every camera, and also new axes for each event. It's hacked, but it works """ print("Displaying... please wait (this is an inefficient implementation)") global fig ntels = len(event.r0.tels_with_data) fig.clear() plt.suptitle("EVENT {}".format(event.r0.event_id)) disps = [] for ii, tel_id in enumerate(event.r0.tels_with_data): print("\t draw cam {}...".format(tel_id)) nn = int(ceil(sqrt(ntels))) ax = plt.subplot(nn, nn, ii + 1) x, y = event.inst.pixel_pos[tel_id] geom = CameraGeometry.guess(x, y, event.inst.optical_foclen[tel_id]) disp = CameraDisplay(geom, ax=ax, title="CT{0}".format(tel_id)) disp.pixels.set_antialiaseds(False) disp.autoupdate = False disp.cmap = random.choice(cmaps) chan = 0 signals = event.r0.tel[tel_id].adc_sums[chan].astype(float) signals -= signals.mean() disp.image = signals disp.set_limits_percent(95) disp.add_colorbar() disps.append(disp) return disps
def display_event(event): """an extremely inefficient display. It creates new instances of CameraDisplay for every event and every camera, and also new axes for each event. It's hacked, but it works """ print("Displaying... please wait (this is an inefficient implementation)") global fig ntels = len(event.r0.tels_with_data) fig.clear() plt.suptitle("EVENT {}".format(event.r0.event_id)) disps = [] for ii, tel_id in enumerate(event.r0.tels_with_data): print("\t draw cam {}...".format(tel_id)) nn = int(ceil(sqrt(ntels))) ax = plt.subplot(nn, nn, ii + 1) x, y = event.inst.pixel_pos[tel_id] geom = CameraGeometry.guess(x, y, event.inst.optical_foclen[tel_id]) disp = CameraDisplay(geom, ax=ax, title="CT{0}".format(tel_id)) disp.pixels.set_antialiaseds(False) disp.autoupdate = False disp.cmap = random.choice(cmaps) chan = 0 signals = event.r0.tel[tel_id].adc_sums[chan].astype(float) signals -= signals.mean() disp.image = signals disp.set_limits_percent(95) disp.add_colorbar() disps.append(disp) return disps
def setup(self): self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]" kwargs = dict(config=self.config, tool=self) arrays = np.load(self.input_path) self.charge = self.dead.mask2d(arrays['charge']) self.charge_error = self.dead.mask2d(arrays['charge_error']) self.rundesc = arrays['rundesc'] self.n_run, self.n_pixels = self.charge.shape assert (self.n_run == self.rundesc.size) geom = CameraGeometry.guess(*checm_pixel_pos * u.m, optical_foclen * u.m) self.modules = np.arange(self.n_pixels) // self.n_tmpix self.tmpix = np.arange(self.n_pixels) % self.n_tmpix self.n_tm = np.unique(self.modules).size # Init Plots self.p_c_pix = Camera(self, "", geom) self.p_c_tm = Camera(self, "", geom) self.p_c_tmpixspread = Camera(self, "", geom) self.p_p_pix = Plotter(**kwargs) self.p_p_tm = Plotter(**kwargs) self.p_b_tmpixspread = BoxPlotter(**kwargs) self.p_b_tmspread = BoxPlotter(**kwargs) self.p_b_pixspread = BoxPlotter(**kwargs)
def get_camera(self, tel_id): if not tel_id in self.camera_geom_dict: pos = self.inst.pixel_pos[tel_id] foclen = self.inst.optical_foclen[tel_id] geom = CameraGeometry.guess(*pos, foclen, apply_derotation=False) self.camera_geom_dict[tel_id] = geom return self.camera_geom_dict[tel_id]
def setup(self): self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]" kwargs = dict(config=self.config, tool=self) arrays = np.load(self.input_path) self.charge = self.dead.mask2d(arrays['charge']) self.charge = np.ma.masked_where(self.charge <= 0, self.charge) self.charge_error = np.ma.array(arrays['charge_error'], mask=self.charge.mask) self.hv = arrays['rundesc'] self.n_hv, self.n_pixels = self.charge.shape assert (self.n_hv == self.hv.size) geom = CameraGeometry.guess(*checm_pixel_pos * u.m, optical_foclen * u.m) self.modules = np.arange(self.n_pixels) // self.n_tmpix self.tmpix = np.arange(self.n_pixels) % self.n_tmpix self.n_tm = np.unique(self.modules).size # Init Plots self.p_camera_pix = Camera(self, "Gain Matching Pixels", geom) self.p_camera_tm = Camera(self, "Gain Matching TMs", geom) self.p_plotter_pix = Plotter(**kwargs) self.p_plotter_tm = Plotter(**kwargs)
def setup(self): self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]" kwargs = dict(config=self.config, tool=self) reader_factory = EventFileReaderFactory(**kwargs) reader_class = reader_factory.get_class() self.reader = reader_class(**kwargs) r1_factory = CameraR1CalibratorFactory(origin=self.reader.origin, **kwargs) r1_class = r1_factory.get_class() self.r1 = r1_class(**kwargs) self.dl0 = CameraDL0Reducer(**kwargs) self.cleaner = CHECMWaveformCleanerAverage(**kwargs) self.extractor = AverageWfPeakIntegrator(**kwargs) self.extractor_height = SimpleIntegrator(window_shift=0, window_width=1, **kwargs) self.dl1 = CameraDL1Calibrator(extractor=self.extractor, cleaner=self.cleaner, **kwargs) self.dl1_height = CameraDL1Calibrator(extractor=self.extractor_height, cleaner=self.cleaner, **kwargs) self.dead = Dead() fitter_factory = ChargeFitterFactory(**kwargs) fitter_class = fitter_factory.get_class() self.fitter = fitter_class(**kwargs) self.n_events = self.reader.num_events first_event = self.reader.get_event(0) self.n_pixels = first_event.inst.num_pixels[0] self.n_samples = first_event.r0.tel[0].num_samples geom = CameraGeometry.guess(*first_event.inst.pixel_pos[0], first_event.inst.optical_foclen[0]) self.neighbours2d = get_neighbours_2d(geom.pix_x, geom.pix_y) # Get stage names self.stage_names = [ '0: raw', '1: baseline_sub', '2: no_pulse', '3: smooth_baseline', '4: smooth_wf', '5: cleaned' ] # Init Plots self.p_camera_area = Camera(self, self.neighbours2d, "Area", geom) self.p_camera_fit_gain = Camera(self, self.neighbours2d, "Gain", geom) self.p_camera_fit_brightness = Camera(self, self.neighbours2d, "Brightness", geom) self.p_fitter = FitterWidget(fitter=self.fitter, **kwargs) self.p_stage_viewer = StageViewer(**kwargs) self.p_fit_viewer = FitViewer(**kwargs) self.p_fit_table = FitTable(**kwargs)
def display_telescope(calibrated_data,cam,tel_id,pdffilename): logger.info("Tel_ID %d\n"%tel_id) pp = PdfPages("%s"%pdffilename) global fig for event in calibrated_data: tels = list(event.r0.tels_with_data) logger.debug(tels) # Select telescope if tel_id not in tels: continue fig.clear() # geom = cam['CameraTable_VersionFeb2016_TelID%s'%tel_id] geom = CameraGeometry.guess(*event.inst.pixel_pos[tel_id], event.inst.optical_foclen[tel_id]) # Select number of pads to display. It depends on the numberr of gains: nchan = event.inst.num_channels[tel_id] plt.suptitle("EVENT {} {:.1e} TeV @({:.1f},{:.1f})deg @{:.1f} m".format( event.r0.event_id, event.mc.energy, event.mc.alt, event.mc.az, np.sqrt(pow(event.mc.core_x, 2) + pow(event.mc.core_y, 2)))) print("\t draw cam {} (gains={})...".format(tel_id,nchan)) ax=[] disp=[] signals=[] npads=0 for i in range(nchan): npads += 1 # Display the camera charge (HG/LG) ax.append(plt.subplot(nchan, 2, npads)) disp.append(visualization.CameraDisplay(geom, ax=ax[-1], title="CT{} [{} ADC cts]".format(tel_id,gain_label[i]))) disp[-1].pixels.set_antialiaseds(False) signals.append(event.r0.tel[tel_id].adc_sums[i]) disp[-1].image = signals[-1] disp[-1].pixels.set_cmap(get_cmap(disp[-1].image)) disp[-1].add_colorbar(label=" [{} ADC cts]".format(gain_label[i])) # Display the camera charge for significant pixels (HG/LG) npads += 1 ax.append(plt.subplot(nchan, 2, npads)) disp.append(visualization.CameraDisplay(geom, ax=ax[-1], title="CT{} [{} ADC cts]".format(tel_id,gain_label[i]))) disp[-1].pixels.set_antialiaseds(False) signals.append(event.r0.tel[tel_id].adc_sums[i]) m = (get_zero_sup_mode(tel_id) & 0x001) or (get_significant(tel_id) & 0x020) disp[-1].image = signals[-1]*(m/m.max()) disp[-1].pixels.set_cmap(get_cmap(disp[-1].image)) disp[-1].add_colorbar(label=" [{} ADC cts]".format(gain_label[i])) plt.pause(0.1) pp.savefig(fig) pp.close()
def get_geometry(self, tel): npix = len(self.event.r0.tel[tel].adc_sums[0]) cam_dimensions = (npix, self.event.inst.optical_foclen[tel]) if tel not in self.geom_dict: self.geom_dict[tel] = \ CameraGeometry.guess(*self.event.inst.pixel_pos[tel], self.event.inst.optical_foclen[tel]) return self.geom_dict[tel]
def plot_quick_camera(image, ax=None): ax = ax if ax is not None else plt.gca() cameraconfig = Config() pos = cameraconfig.pixel_pos * u.m foclen = cameraconfig.optical_foclen * u.m geom = CameraGeometry.guess(*pos, foclen) camera = CameraDisplay(geom, ax=ax, image=image, cmap='viridis') return camera
def get_geometry(self, tel): npix = len(self.event.r0.tel[tel].adc_sums[0]) cam_dimensions = (npix, self.event.inst.optical_foclen[tel]) if tel not in self.geom_dict: self.geom_dict[tel] = \ CameraGeometry.guess(*self.event.inst.pixel_pos[tel], self.event.inst.optical_foclen[tel]) return self.geom_dict[tel]
def write_camera_geometries(self): cam_types = get_camera_types(self.inst) print_camera_types(self.inst, printer=self.log.info) for cam_name in cam_types: ext, args = self._get_file_format_info(self.format, 'CAMGEOM', cam_name) self.log.debug("writing {}".format(cam_name)) tel_id = cam_types[cam_name].pop() pix = self.inst.pixel_pos[tel_id] flen = self.inst.optical_foclen[tel_id] geom = CameraGeometry.guess(*pix, flen) table = geom.to_table() table.meta['SOURCE'] = self.infile table.write("{}.camgeom.{}".format(cam_name, ext), **args)
def start(self): event = self.reader.get_event(self.req_event) telid = list(event.r0.tels_with_data)[0] geom = CameraGeometry.guess(*event.inst.pixel_pos[0], event.inst.optical_foclen[0]) self.r1.calibrate(event) self.dl0.reduce(event) self.dl1.calibrate(event) cleaned = event.dl1.tel[telid].cleaned[0] output_dir = self.reader.output_directory self.animator.plot(cleaned, geom, self.req_event, output_dir)
def setup_arrays(self, file_reader): global TELID global CHAN global N_PIXELS global N_SAMPLES global PIXEL_POS first_event = file_reader.get_event(0) TELID = list(first_event.r0.tels_with_data)[0] CHAN = 0 N_PIXELS, N_SAMPLES = first_event.r0.tel[TELID].adc_samples[CHAN].shape PIXEL_POS = first_event.inst.pixel_pos[TELID] pos = first_event.inst.pixel_pos[TELID] foclen = first_event.inst.optical_foclen[TELID] self.geom = CameraGeometry.guess(*pos, foclen)
def write_camera_geometries(self): cam_types = get_camera_types(self.inst) print_camera_types(self.inst, printer=self.log.info) for cam_name in cam_types: ext, args = self._get_file_format_info(self.format, 'CAMGEOM', cam_name) self.log.debug("writing {}".format(cam_name)) tel_id = cam_types[cam_name].pop() pix = self.inst.pixel_pos[tel_id] flen = self.inst.optical_foclen[tel_id] geom = CameraGeometry.guess(*pix, flen) table = geom.to_table() table.meta['SOURCE'] = self.infile table.write("{}.camgeom.{}".format(cam_name, ext), **args)
def get_geometry(event, telid): """ Obtain the geometry for this telescope. Parameters ---------- event : container A `ctapipe` event container telid : int The telescope id. The neighbours are calculated once per telescope. Returns ------- `CameraGeometry` """ return CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid])
def get_geometry(event, telid): """ Obtain the geometry for this telescope. Parameters ---------- event : container A `ctapipe` event container telid : int The telescope id. The neighbours are calculated once per telescope. Returns ------- `CameraGeometry` """ return CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid])
def test_nb_peak_integration(): telid = 11 event = get_test_event() data = event.r0.tel[telid].adc_samples nsamples = data.shape[2] ped = event.mc.tel[telid].pedestal data_ped = data - np.atleast_3d(ped/nsamples) data_ped = np.array([data_ped[0], data_ped[0]]) # Test LG functionality geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) nei = geom.neighbors integrator = NeighbourPeakIntegrator(None, None) integrator.neighbours = nei integration, peakpos, window = integrator.extract_charge(data_ped) assert_almost_equal(integration[0][0], -64, 0) assert_almost_equal(integration[1][0], -64, 0) assert peakpos[0][0] == 20 assert peakpos[1][0] == 20
def start(self): geom = None imsum = None disp = None for data in hessio_event_source(self.infile, allowed_tels=self._selected_tels, max_events=self.max_events): self.calibrator.calibrate(data) if geom is None: x, y = data.inst.pixel_pos[self._base_tel] flen = data.inst.optical_foclen[self._base_tel] geom = CameraGeometry.guess(x, y, flen) imsum = np.zeros(shape=x.shape, dtype=np.float) disp = CameraDisplay(geom, title=geom.cam_id) disp.add_colorbar() disp.cmap = 'viridis' if len(data.dl0.tels_with_data) <= 2: continue imsum[:] = 0 for telid in data.dl0.tels_with_data: imsum += data.dl1.tel[telid].image[0] self.log.info("event={} ntels={} energy={}" \ .format(data.r0.event_id, len(data.dl0.tels_with_data), data.mc.energy)) disp.image = imsum plt.pause(0.1) if self.output_suffix is not "": filename = "{:020d}{}".format(data.r0.event_id, self.output_suffix) self.log.info("saving: '{}'".format(filename)) plt.savefig(filename)
def start(self): geom = None imsum = None disp = None for data in hessio_event_source(self.infile, allowed_tels=self._selected_tels, max_events=self.max_events): self.calibrator.calibrate(data) if geom is None: x, y = data.inst.pixel_pos[self._base_tel] flen = data.inst.optical_foclen[self._base_tel] geom = CameraGeometry.guess(x, y, flen) imsum = np.zeros(shape=x.shape, dtype=np.float) disp = CameraDisplay(geom, title=geom.cam_id) disp.add_colorbar() disp.cmap = 'viridis' if len(data.dl0.tels_with_data) <= 2: continue imsum[:] = 0 for telid in data.dl0.tels_with_data: imsum += data.dl1.tel[telid].image[0] self.log.info("event={} ntels={} energy={}" \ .format(data.r0.event_id, len(data.dl0.tels_with_data), data.mc.energy)) disp.image = imsum plt.pause(0.1) if self.output_suffix is not "": filename = "{:020d}{}".format(data.r0.event_id, self.output_suffix) self.log.info("saving: '{}'".format(filename)) plt.savefig(filename)
def create(self, residual, pixel_pos, foclen): self.log.info("Creating {}".format(self.name)) mean = np.mean(residual, axis=(0, 2)) stddev = np.std(residual, axis=(0, 2)) min_ = np.min(residual, axis=(0, 2)) max_ = np.max(residual, axis=(0, 2)) x = np.arange(residual.shape[1]) cdsource_d = dict(x=x, mean=mean, stddev=stddev, min=min_, max=max_) cdsource = ColumnDataSource(data=cdsource_d) title = "Residual Spread Vs Pixel ID" geom = CameraGeometry.guess(*pixel_pos, foclen) camera_mean = CameraDisplay(geometry=geom, image=mean) camera_mean.add_colorbar() camera_mean_fig = camera_mean.fig camera_mean_fig.title.text = "Residual Means" camera_stddev = CameraDisplay(geometry=geom, image=stddev) camera_stddev.add_colorbar() camera_stddev_fig = camera_stddev.fig camera_stddev_fig.title.text = "Residual Standard Deviations" self.layout = layout([[camera_mean_fig, camera_stddev_fig]])
disp = None print('SELECTING EVENTS FROM TELESCOPE {}'.format(args.tel)) print('=' * 70) for event in source: print('Scanning input file... count = {}'.format(event.count)) print(event.trig) print(event.mc) print(event.dl0) if disp is None: x, y = event.inst.pixel_pos[args.tel] focal_len = event.inst.optical_foclen[args.tel] geom = CameraGeometry.guess(x, y, focal_len) print(geom.pix_x) disp = CameraDisplay(geom, title='CT%d' % args.tel) #disp.enable_pixel_picker() disp.add_colorbar() plt.show(block=False) # display the event disp.axes.set_title('CT{:03d}, event {:010d}'.format( args.tel, event.r0.event_id)) if args.show_samples: # display time-varying event data = event.r0.tel[args.tel].adc_samples[args.channel] if args.calibrate: peds, gains = get_mc_calibration_coeffs(event, args.tel) data = apply_mc_calibration(data, peds, gains, args.tel)
def get_geometry(): cameraconfig = Config() pixel_pos = cameraconfig.pixel_pos optical_foclen = cameraconfig.optical_foclen return CameraGeometry.guess(*pixel_pos * u.m, optical_foclen * u.m)
def analyze_muon_event(event, params=None, geom_dict=None): """ Generic muon event analyzer. Parameters ---------- event : ctapipe dl1 event container Returns ------- muonringparam, muonintensityparam : MuonRingParameter and MuonIntensityParameter container event """ # Declare a dict to define the muon cuts (ASTRI and SCT missing) muon_cuts = {} names = [ 'LST:LSTCam', 'MST:NectarCam', 'MST:FlashCam', 'MST-SCT:SCTCam', 'SST-1M:DigiCam', 'SST-GCT:CHEC', 'SST-ASTRI:ASTRICam' ] TailCuts = [(5, 7), (5, 7), (10, 12), (5, 7), (5, 7), (5, 7), (5, 7)] #10,12? impact = [(0.2, 0.9), (0.1, 0.95), (0.2, 0.9), (0.2, 0.9), (0.1, 0.95), (0.1, 0.95), (0.1, 0.95)] ringwidth = [(0.04, 0.08), (0.02, 0.1), (0.01, 0.1), (0.02, 0.1), (0.01, 0.5), (0.02, 0.2), (0.02, 0.2)] TotalPix = [1855., 1855., 1764., 11328., 1296., 2048., 2368.] #8% (or 6%) as limit MinPix = [148., 148., 141., 680., 104., 164., 142.] #Need to either convert from the pixel area in m^2 or check the camera specs AngPixelWidth = [0.1, 0.2, 0.18, 0.067, 0.24, 0.2, 0.17] #Found from TDRs (or the pixel area) hole_rad = [] #Need to check and implement cam_rad = [2.26, 3.96, 3.87, 4., 4.45, 2.86, 5.25] #Found from the field of view calculation sec_rad = [ 0. * u.m, 0. * u.m, 0. * u.m, 2.7 * u.m, 0. * u.m, 1. * u.m, 1.8 * u.m ] sct = [False, False, False, True, False, True, True] muon_cuts = { 'Name': names, 'TailCuts': TailCuts, 'Impact': impact, 'RingWidth': ringwidth, 'TotalPix': TotalPix, 'MinPix': MinPix, 'CamRad': cam_rad, 'SecRad': sec_rad, 'SCT': sct, 'AngPixW': AngPixelWidth } #print(muon_cuts) muonringlist = [] #[None] * len(event.dl0.tels_with_data) muonintensitylist = [] #[None] * len(event.dl0.tels_with_data) tellist = [] #for tid in event.dl0.tels_with_data: # tellist.append(tid) muon_event_param = { 'TelIds': tellist, 'MuonRingParams': muonringlist, 'MuonIntensityParams': muonintensitylist } #muonringparam = None #muonintensityparam = None for telid in event.dl0.tels_with_data: #print("Analysing muon event for tel",telid) muonringparam = None muonintensityparam = None #idx = muon_event_param['TelIds'].index(telid) x, y = event.inst.pixel_pos[telid] #image = event.dl1.tel[telid].calibrated_image image = event.dl1.tel[telid].image[0] # Get geometry geom = None if geom_dict is not None and telid in geom_dict: geom = geom_dict[telid] else: log.debug("[calib] Guessing camera geometry") geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) log.debug("[calib] Camera geometry found") if geom_dict is not None: geom_dict[telid] = geom teldes = event.inst.subarray.tel[telid] dict_index = muon_cuts['Name'].index(str(teldes)) #print('found an index of',dict_index,'for camera',geom.cam_id) #tailcuts = (5.,7.) tailcuts = muon_cuts['TailCuts'][dict_index] #print("Tailcuts are",tailcuts[0],tailcuts[1]) #rot_angle = 0.*u.deg #if event.inst.optical_foclen[telid] > 10.*u.m and event.dl0.tel[telid].num_pixels != 1764: #rot_angle = -100.14*u.deg clean_mask = tailcuts_clean(geom, image, picture_thresh=tailcuts[0], boundary_thresh=tailcuts[1]) 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) #print("Camera",geom.cam_id,"focal length",event.inst.optical_foclen[telid],"rotation",geom.pix_rotation) #TODO: correct this hack for values over 90 altval = event.mcheader.run_array_direction[1] if (altval > np.pi / 2.): altval = np.pi / 2. altaz = HorizonFrame(alt=altval * u.rad, az=event.mcheader.run_array_direction[0] * u.rad) nom_coord = camera_coord.transform_to( NominalFrame(array_direction=altaz, pointing_direction=altaz)) x = nom_coord.x.to(u.deg) y = nom_coord.y.to(u.deg) img = image * clean_mask noise = 5. weight = img / (img + noise) muonring = ChaudhuriKunduRingFitter(None) #print("img:",np.sum(image),"mask:",np.sum(clean_mask), "x=",x,"y=",y) if not sum(img): #Nothing left after tail cuts continue muonringparam = muonring.fit(x, y, image * clean_mask) #muonringparam = muonring.fit(x,y,weight) 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, img * (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) #print("1: x",muonringparam.ring_center_x,"y",muonringparam.ring_center_y,"radius",muonringparam.ring_radius) muonringparam = muonring.fit( x, y, img * (ring_dist < muonringparam.ring_radius * 0.4)) #print("2: x",muonringparam.ring_center_x,"y",muonringparam.ring_center_y,"radius",muonringparam.ring_radius) muonringparam.tel_id = telid muonringparam.run_id = event.dl0.run_id muonringparam.event_id = event.dl0.event_id dist_mask = np.abs( dist - muonringparam.ring_radius) < muonringparam.ring_radius * 0.4 rad = list() cx = list() cy = list() mc_x = event.mc.core_x mc_y = event.mc.core_y pix_im = image * dist_mask nom_dist = np.sqrt( np.power(muonringparam.ring_center_x, 2) + np.power(muonringparam.ring_center_y, 2)) #numpix = event.dl0.tel[telid].num_pixels minpix = muon_cuts['MinPix'][dict_index] #0.06*numpix #or 8% mir_rad = np.sqrt( event.inst.mirror_dish_area[telid] / (np.pi) ) #need to consider units? (what about hole? Area is then less...) #Camera containment radius - better than nothing - guess pixel diameter of 0.11, all cameras are perfectly circular cam_rad = np.sqrt(numpix*0.11/(2.*np.pi)) if (np.sum(pix_im > tailcuts[0]) > 0.1 * minpix and np.sum(pix_im) > minpix and nom_dist < muon_cuts['CamRad'][dict_index] * u.deg and muonringparam.ring_radius < 1.5 * u.deg and muonringparam.ring_radius > 1. * u.deg): #Guess HESS is 0.16 #sec_rad = 0.*u.m #sct = False #if numpix == 2048 and mir_rad > 2.*u.m and mir_rad < 2.1*u.m: # sec_rad = 1.*u.m # sct = True #Store muon ring parameters (passing cuts stage 1) #muonringlist[idx] = muonringparam tellist.append(telid) muonringlist.append(muonringparam) muonintensitylist.append(None) #embed() ctel = MuonLineIntegrate( mir_rad, 0.2 * u.m, pixel_width=muon_cuts['AngPixW'][dict_index] * u.deg, sct_flag=muon_cuts['SCT'][dict_index], secondary_radius=muon_cuts['SecRad'][dict_index]) if (image.shape[0] == muon_cuts['TotalPix'][dict_index]): muonintensityoutput = ctel.fit_muon( muonringparam.ring_center_x, muonringparam.ring_center_y, muonringparam.ring_radius, x[dist_mask], y[dist_mask], image[dist_mask]) muonintensityoutput.tel_id = telid muonintensityoutput.run_id = event.dl0.run_id muonintensityoutput.event_id = event.dl0.event_id muonintensityoutput.mask = dist_mask print("Tel", telid, "Impact parameter = ", muonintensityoutput.impact_parameter, "mir_rad", mir_rad, "ring_width=", muonintensityoutput.ring_width) #if(muonintensityoutput.impact_parameter > muon_cuts['Impact'][dict_index][1]*mir_rad or muonintensityoutput.impact_parameter < muon_cuts['Impact'][dict_index][0]*mir_rad): # print("Failed on impact parameter low cut",muon_cuts['Impact'][dict_index][0]*mir_rad,"high cut",muon_cuts['Impact'][dict_index][1]*mir_rad,"for",geom.cam_id) #if(muonintensityoutput.ring_width > muon_cuts['RingWidth'][dict_index][1]*u.deg or muonintensityoutput.ring_width < muon_cuts['RingWidth'][dict_index][0]*u.deg): # print("Failed on ring width low cut",muon_cuts['RingWidth'][dict_index][0]*u.deg,"high cut",muon_cuts['RingWidth'][dict_index][1]*u.deg,"for ",geom.cam_id) #print("Cuts <",muon_cuts["Impact"][dict_index][1]*mir_rad,"cuts >",muon_cuts['Impact'][dict_index][0]*u.m,'ring_width < ',muon_cuts['RingWidth'][dict_index][1]*u.deg,'ring_width >',muon_cuts['RingWidth'][dict_index][0]*u.deg) if (muonintensityoutput.impact_parameter < muon_cuts['Impact'][dict_index][1] * mir_rad and muonintensityoutput.impact_parameter > muon_cuts['Impact'][dict_index][0] * u.m and muonintensityoutput.ring_width < muon_cuts['RingWidth'][dict_index][1] * u.deg and muonintensityoutput.ring_width > muon_cuts['RingWidth'][dict_index][0] * u.deg): muonintensityparam = muonintensityoutput idx = tellist.index(telid) muonintensitylist[idx] = muonintensityparam print("Muon in tel", telid, "# tels in event=", len(event.dl0.tels_with_data)) else: continue #print("Fitted ring centre (2):",muonringparam.ring_center_x,muonringparam.ring_center_y) #return muonringparam, muonintensityparam return muon_event_param
def test_guess_camera(): px = np.linspace(-10, 10, 11328) * u.m py = np.linspace(-10, 10, 11328) * u.m geom = CameraGeometry.guess(px, py,0 * u.m) assert geom.pix_type.startswith('rect')
def extract_images(simtel_file_path, tel_id_filter_list=None, event_id_filter_list=None, output_directory=None): # EXTRACT IMAGES ########################################################## # hessio_event_source returns a Python generator that streams data from an # EventIO/HESSIO MC data file (e.g. a standard CTA data file). # This generator contains ctapipe.core.Container instances ("event"). # # Parameters: # - max_events: maximum number of events to read # - allowed_tels: select only a subset of telescope, if None, all are read. source = hessio_event_source(simtel_file_path, allowed_tels=tel_id_filter_list) # ITERATE OVER EVENTS ##################################################### calib = CameraCalibrator(None, None) for event in source: calib.calibrate(event) # calibrate the event event_id = int(event.dl0.event_id) if (event_id_filter_list is None) or (event_id in event_id_filter_list): #print("event", event_id) # ITERATE OVER IMAGES ############################################# for tel_id in event.trig.tels_with_trigger: tel_id = int(tel_id) if tel_id in tel_id_filter_list: #print("telescope", tel_id) # CHECK THE IMAGE GEOMETRY ################################ #print("checking geometry") x, y = event.inst.subarray.tel[ tel_id].camera.pix_x, event.inst.subarray.tel[ tel_id].camera.pix_y foclen = event.inst.subarray.tel[ tel_id].optics.equivalent_focal_length geom = CameraGeometry.guess(x, y, foclen) if (geom.pix_type != "hexagonal") or (geom.cam_id != "DigiCam"): raise ValueError( "Telescope {}: error (the input image is not a valide DigiCam telescope image) -> {} ({})" .format(tel_id, geom.pix_type, geom.cam_id)) # GET IMAGES ############################################## pe_image = event.mc.tel[ tel_id].photo_electron_image # 1D np array #uncalibrated_image = event.dl0.tel[tel_id].adc_sums # ctapipe 0.3.0 uncalibrated_image = event.r0.tel[ tel_id].adc_sums # ctapipe 0.4.0 pedestal = event.mc.tel[tel_id].pedestal gain = event.mc.tel[tel_id].dc_to_pe pixel_pos = (event.inst.subarray.tel[tel_id].camera.pix_x, event.inst.subarray.tel[tel_id].camera.pix_y) calibrated_image = event.dl1.tel[tel_id].image #print(pe_image.shape) #print(calibrated_image.shape) #print(uncalibrated_image.shape) #print(pedestal.shape) #print(gain.shape) #print(pixel_pos.shape) #print(pixel_pos[0]) #print(pixel_pos[1]) # CONVERTING GEOMETRY (1D TO 2D) ########################## buffer_id_str = geom.cam_id + "0" geom2d, pe_image_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d( geom, pe_image, buffer_id_str, add_rot=0) geom2d, calibrated_image_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d( geom, calibrated_image[0], buffer_id_str, add_rot=0) geom2d, uncalibrated_image_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d( geom, uncalibrated_image[0], buffer_id_str, add_rot=0) geom2d, pedestal_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d( geom, pedestal[0], buffer_id_str, add_rot=0) geom2d, gains_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d( geom, gain[0], buffer_id_str, add_rot=0) # Make a mock pixel position array... pixel_pos_2d = np.array( np.meshgrid( np.linspace(pixel_pos[0].min(), pixel_pos[0].max(), pe_image_2d.shape[0]), np.linspace(pixel_pos[1].min(), pixel_pos[1].max(), pe_image_2d.shape[1]))) # PUT NAN IN BLANK PIXELS ################################# calibrated_image_2d[np.logical_not(geom2d.mask)] = np.nan pe_image_2d[np.logical_not(geom2d.mask)] = np.nan uncalibrated_image_2d[np.logical_not(geom2d.mask)] = np.nan pedestal_2d[np.logical_not(geom2d.mask)] = np.nan gains_2d[np.logical_not(geom2d.mask)] = np.nan pixel_pos_2d[0, np.logical_not(geom2d.mask)] = np.nan pixel_pos_2d[1, np.logical_not(geom2d.mask)] = np.nan ########################################################### # The ctapipe geometry converter operate on one channel # only and then takes and return a 2D array but pywicta # fits files keep all channels and thus takes 3D arrays... uncalibrated_image_2d = np.array([uncalibrated_image_2d]) pedestal_2d = np.array([pedestal_2d]) gains_2d = np.array([gains_2d]) ########################################################### #print(pe_image_2d.shape) #print(calibrated_image_2d.shape) #print(uncalibrated_image_2d.shape) #print(pedestal_2d.shape) #print(gains_2d.shape) #img = pixel_pos_2d #print(img[1]) #import matplotlib.pyplot as plt #im = plt.imshow(img[1]) #plt.colorbar(im) #plt.show() #sys.exit(0) # GET PIXEL MASK ########################################## pixel_mask = geom2d.mask.astype( int ) # 1 for pixels with actual data, 0 for virtual (blank) pixels # MAKE METADATA ########################################### metadata = {} metadata[ 'version'] = 1 # Version of the pywicta fits format metadata['cam_id'] = "DigiCam" metadata['tel_id'] = tel_id metadata['event_id'] = event_id metadata['simtel'] = simtel_file_path metadata['tel_trig'] = len(event.trig.tels_with_trigger) metadata['energy'] = quantity_to_tuple( event.mc.energy, 'TeV') metadata['mc_az'] = quantity_to_tuple(event.mc.az, 'rad') metadata['mc_alt'] = quantity_to_tuple(event.mc.alt, 'rad') metadata['mc_corex'] = quantity_to_tuple( event.mc.core_x, 'm') metadata['mc_corey'] = quantity_to_tuple( event.mc.core_y, 'm') metadata['mc_hfi'] = quantity_to_tuple( event.mc.h_first_int, 'm') metadata['count'] = int(event.count) metadata['run_id'] = int(event.dl0.obs_id) metadata['tel_data'] = len(event.dl0.tels_with_data) metadata['foclen'] = quantity_to_tuple( event.inst.subarray.tel[tel_id].optics. equivalent_focal_length, 'm') metadata['tel_posx'] = quantity_to_tuple( event.inst.subarray.tel_coords[tel_id].x, 'm') metadata['tel_posy'] = quantity_to_tuple( event.inst.subarray.tel_coords[tel_id].y, 'm') metadata['tel_posz'] = quantity_to_tuple( event.inst.subarray.tel_coords[tel_id].z, 'm') # TODO: Astropy fails to store the following data in FITS files #metadata['uid'] = os.getuid() #metadata['datetime'] = str(datetime.datetime.now()) #metadata['version'] = VERSION #metadata['argv'] = " ".join(sys.argv).encode('ascii', errors='ignore').decode('ascii') #metadata['python'] = " ".join(sys.version.splitlines()).encode('ascii', errors='ignore').decode('ascii') #metadata['system'] = " ".join(os.uname()) # SAVE THE IMAGE ########################################## output_file_path_template = "{}_TEL{:03d}_EV{:05d}.fits" if output_directory is not None: simtel_basename = os.path.basename(simtel_file_path) prefix = os.path.join(output_directory, simtel_basename) else: prefix = simtel_file_path output_file_path = output_file_path_template.format( prefix, tel_id, event_id) print("saving", output_file_path) images.save_benchmark_images( img=calibrated_image_2d, pe_img=pe_image_2d, adc_sums_img=uncalibrated_image_2d, pedestal_img=pedestal_2d, gains_img=gains_2d, pixel_pos=pixel_pos_2d, pixel_mask=pixel_mask, metadata=metadata, output_file_path=output_file_path)
def draw_event(self, event, hillas_parameters=None): """ Draw display for a given event Parameters ---------- event: ctapipe event object hillas_parameters: dict Dictionary of Hillas parameters (in nominal system) Returns ------- None """ tel_list = event.r0.tels_with_data images = event.dl1 # First close any plots that already exist plt.close() ntels = len(tel_list) fig = plt.figure(figsize=(20, 20 * 0.66)) # If we want to draw the Hillas parameters in different planes we need to split our figure if self.draw_hillas_planes: y_axis_split = 2 else: y_axis_split = 1 outer_grid = gridspec.GridSpec(1, y_axis_split, width_ratios=[y_axis_split, 1]) # Create a square grid for camera images nn = int(ceil(sqrt(ntels))) nx = nn ny = nn while nx * ny >= ntels: ny-=1 ny+=1 while nx * ny >= ntels: nx -= 1 nx += 1 camera_grid = gridspec.GridSpecFromSubplotSpec(ny, nx, subplot_spec=outer_grid[0]) # Loop over camera images of all telescopes and create plots for ii, tel_id in zip(range(ntels), tel_list): # Cache of camera geometries, this may go away soon if tel_id not in self.geom: self.geom[tel_id] = CameraGeometry.guess( event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], event.inst.optical_foclen[tel_id]) ax = plt.subplot(camera_grid[ii]) self.get_camera_view(tel_id, images.tel[tel_id].image[0], ax) # If we want to draw the Hillas parameters in different planes we need to make a couple more viewers if self.draw_hillas_planes: # Split the second sub figure into two further figures reco_grid = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=outer_grid[1]) # Create plot of telescope positions at ground level array = ArrayPlotter(telescopes=tel_list, instrument=event.inst,# system=tilted_system, ax=plt.subplot(reco_grid[0])) # Draw MC position (this should change later) array.draw_position(event.mc.core_x, event.mc.core_y, use_centre=True) array.draw_array(((-300,300),(-300,300))) # If we have valid Hillas parameters we should draw them in the Nominal system if hillas_parameters is not None: array.overlay_hillas(hillas_parameters, draw_axes=True) nominal = NominalPlotter(hillas_parameters=hillas_parameters, draw_axes=True, ax=plt.subplot(reco_grid[1])) nominal.draw_array() plt.show() return
def extract_images(simtel_file_path, tel_id_filter_list=None, event_id_filter_list=None, output_directory=None, crop=True): # EXTRACT IMAGES ########################################################## # hessio_event_source returns a Python generator that streams data from an # EventIO/HESSIO MC data file (e.g. a standard CTA data file). # This generator contains ctapipe.core.Container instances ("event"). # # Parameters: # - max_events: maximum number of events to read # - allowed_tels: select only a subset of telescope, if None, all are read. source = hessio_event_source(simtel_file_path, allowed_tels=tel_id_filter_list) # ITERATE OVER EVENTS ##################################################### calib = CameraCalibrator(None, None) for event in source: calib.calibrate(event) # calibrate the event event_id = int(event.dl0.event_id) if (event_id_filter_list is None) or (event_id in event_id_filter_list): #print("event", event_id) # ITERATE OVER IMAGES ############################################# for tel_id in event.trig.tels_with_trigger: tel_id = int(tel_id) if tel_id in tel_id_filter_list: #print("telescope", tel_id) # CHECK THE IMAGE GEOMETRY (ASTRI ONLY) ################### # TODO #print("checking geometry") x, y = event.inst.subarray.tel[ tel_id].camera.pix_x, event.inst.subarray.tel[ tel_id].camera.pix_y foclen = event.inst.subarray.tel[ tel_id].optics.equivalent_focal_length geom = CameraGeometry.guess(x, y, foclen) if (geom.pix_type != "rectangular") or (geom.cam_id not in ("ASTRICam", "ASTRI")): raise ValueError( "Telescope {}: error (the input image is not a valide ASTRI telescope image) -> {} ({})" .format(tel_id, geom.pix_type, geom.cam_id)) # GET IMAGES ############################################## pe_image = event.mc.tel[ tel_id].photo_electron_image # 1D np array #uncalibrated_image = event.dl0.tel[tel_id].adc_sums # ctapipe 0.3.0 uncalibrated_image = event.r0.tel[ tel_id].adc_sums # ctapipe 0.4.0 pedestal = event.mc.tel[tel_id].pedestal gain = event.mc.tel[tel_id].dc_to_pe pixel_pos = (event.inst.subarray.tel[tel_id].camera.pix_x, event.inst.subarray.tel[tel_id].camera.pix_y) calibrated_image = event.dl1.tel[tel_id].image calibrated_image[1, calibrated_image[ 0, :] <= ASTRI_CAM_CHANNEL_THRESHOLD] = 0 calibrated_image[0, calibrated_image[ 0, :] > ASTRI_CAM_CHANNEL_THRESHOLD] = 0 calibrated_image = calibrated_image.sum(axis=0) #print(pe_image.shape) #print(calibrated_image.shape) #print(uncalibrated_image.shape) #print(pedestal.shape) #print(gain.shape) #print(pixel_pos.shape) #print(pixel_pos[0]) #print(pixel_pos[1]) # CONVERTING GEOMETRY (1D TO 2D) ########################## pe_image_2d = geometry_converter.astri_to_2d_array( pe_image, crop=crop) calibrated_image_2d = geometry_converter.astri_to_2d_array( calibrated_image, crop=crop) uncalibrated_image_2d = geometry_converter.astri_to_3d_array( uncalibrated_image, crop=crop) pedestal_2d = geometry_converter.astri_to_3d_array( pedestal, crop=crop) gains_2d = geometry_converter.astri_to_3d_array(gain, crop=crop) pixel_pos_2d = geometry_converter.astri_to_3d_array( pixel_pos, crop=crop) #print(pe_image_2d.shape) #print(calibrated_image_2d.shape) #print(uncalibrated_image_2d.shape) #print(pedestal_2d.shape) #print(gains_2d.shape) #print(pixel_pos_2d.shape) #sys.exit(0) # GET PIXEL MASK ########################################## pixel_mask = geometry_converter.astri_pixel_mask( crop ) # 1 for pixels with actual data, 0 for virtual (blank) pixels # MAKE METADATA ########################################### metadata = {} metadata[ 'version'] = 1 # Version of the pywicta fits format if crop: metadata['cam_id'] = "ASTRI_CROPPED" else: metadata['cam_id'] = "ASTRI" metadata['tel_id'] = tel_id metadata['event_id'] = event_id metadata['simtel'] = simtel_file_path metadata['tel_trig'] = len(event.trig.tels_with_trigger) metadata['energy'] = quantity_to_tuple( event.mc.energy, 'TeV') metadata['mc_az'] = quantity_to_tuple(event.mc.az, 'rad') metadata['mc_alt'] = quantity_to_tuple(event.mc.alt, 'rad') metadata['mc_corex'] = quantity_to_tuple( event.mc.core_x, 'm') metadata['mc_corey'] = quantity_to_tuple( event.mc.core_y, 'm') metadata['mc_hfi'] = quantity_to_tuple( event.mc.h_first_int, 'm') metadata['count'] = int(event.count) metadata['run_id'] = int(event.dl0.obs_id) metadata['tel_data'] = len(event.dl0.tels_with_data) metadata['foclen'] = quantity_to_tuple( event.inst.subarray.tel[tel_id].optics. equivalent_focal_length, 'm') metadata['tel_posx'] = quantity_to_tuple( event.inst.subarray.tel_coords[tel_id].x, 'm') metadata['tel_posy'] = quantity_to_tuple( event.inst.subarray.tel_coords[tel_id].y, 'm') metadata['tel_posz'] = quantity_to_tuple( event.inst.subarray.tel_coords[tel_id].z, 'm') # TODO: Astropy fails to store the following data in FITS files #metadata['uid'] = os.getuid() #metadata['datetime'] = str(datetime.datetime.now()) #metadata['version'] = VERSION #metadata['argv'] = " ".join(sys.argv).encode('ascii', errors='ignore').decode('ascii') #metadata['python'] = " ".join(sys.version.splitlines()).encode('ascii', errors='ignore').decode('ascii') #metadata['system'] = " ".join(os.uname()) # SAVE THE IMAGE ########################################## output_file_path_template = "{}_TEL{:03d}_EV{:05d}.fits" if output_directory is not None: simtel_basename = os.path.basename(simtel_file_path) prefix = os.path.join(output_directory, simtel_basename) else: prefix = simtel_file_path output_file_path = output_file_path_template.format( prefix, tel_id, event_id) print("saving", output_file_path) images.save_benchmark_images( img=calibrated_image_2d, pe_img=pe_image_2d, adc_sums_img=uncalibrated_image_2d, pedestal_img=pedestal_2d, gains_img=gains_2d, pixel_pos=pixel_pos_2d, pixel_mask=pixel_mask, metadata=metadata, output_file_path=output_file_path)
def test_FitGammaHillas(): ''' a test of the complete fit procedure on one event including: • tailcut cleaning • hillas parametrisation • GreatCircle creation • direction fit • position fit in the end, proper units in the output are asserted ''' filename = get_dataset("gamma_test.simtel.gz") fit = HillasReconstructor() cam_geom = {} tel_phi = {} tel_theta = {} source = hessio_event_source(filename) for event in source: hillas_dict = {} for tel_id in event.dl0.tels_with_data: if tel_id not in cam_geom: cam_geom[tel_id] = CameraGeometry.guess( event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], event.inst.optical_foclen[tel_id]) tel_phi[tel_id] = event.mc.tel[tel_id].azimuth_raw * u.rad tel_theta[tel_id] = (np.pi / 2 - event.mc.tel[tel_id].altitude_raw) * u.rad pmt_signal = event.r0.tel[tel_id].adc_sums[0] mask = tailcuts_clean(cam_geom[tel_id], pmt_signal, picture_thresh=10., boundary_thresh=5.) pmt_signal[mask == 0] = 0 try: moments = hillas_parameters(event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], pmt_signal) hillas_dict[tel_id] = moments except HillasParameterizationError as e: print(e) continue if len(hillas_dict) < 2: continue fit_result = fit.predict(hillas_dict, event.inst, tel_phi, tel_theta) print(fit_result) fit_result.alt.to(u.deg) fit_result.az.to(u.deg) fit_result.core_x.to(u.m) assert fit_result.is_valid return
def extract_images(simtel_file_path, tel_id_filter_list=None, event_id_filter_list=None, output_directory=None): # EXTRACT IMAGES ########################################################## # hessio_event_source returns a Python generator that streams data from an # EventIO/HESSIO MC data file (e.g. a standard CTA data file). # This generator contains ctapipe.core.Container instances ("event"). # # Parameters: # - max_events: maximum number of events to read # - allowed_tels: select only a subset of telescope, if None, all are read. source = hessio_event_source(simtel_file_path, allowed_tels=tel_id_filter_list) # ITERATE OVER EVENTS ##################################################### calib = CameraCalibrator(None, None) for event in source: calib.calibrate(event) # calibrate the event event_id = int(event.dl0.event_id) if (event_id_filter_list is None) or (event_id in event_id_filter_list): #print("event", event_id) # ITERATE OVER IMAGES ############################################# for tel_id in event.trig.tels_with_trigger: tel_id = int(tel_id) if tel_id in tel_id_filter_list: #print("telescope", tel_id) # CHECK THE IMAGE GEOMETRY ################################ #print("checking geometry") x, y = event.inst.pixel_pos[tel_id] foclen = event.inst.optical_foclen[tel_id] geom = CameraGeometry.guess(x, y, foclen) if (geom.pix_type != "hexagonal") or (geom.cam_id != "LSTCam"): raise ValueError("Telescope {}: error (the input image is not a valide LSTCam telescope image) -> {} ({})".format(tel_id, geom.pix_type, geom.cam_id)) # GET IMAGES ############################################## pe_image = event.mc.tel[tel_id].photo_electron_image # 1D np array #uncalibrated_image = event.dl0.tel[tel_id].adc_sums # ctapipe 0.3.0 uncalibrated_image = event.r0.tel[tel_id].adc_sums # ctapipe 0.4.0 pedestal = event.mc.tel[tel_id].pedestal gain = event.mc.tel[tel_id].dc_to_pe pixel_pos = event.inst.pixel_pos[tel_id] calibrated_image = event.dl1.tel[tel_id].image calibrated_image[1, calibrated_image[0,:] <= LST_CAM_CHANNEL_THRESHOLD] = 0 calibrated_image[0, calibrated_image[0,:] > LST_CAM_CHANNEL_THRESHOLD] = 0 calibrated_image = calibrated_image.sum(axis=0) #print(pe_image.shape) #print(calibrated_image.shape) #print(uncalibrated_image.shape) #print(pedestal.shape) #print(gain.shape) #print(pixel_pos.shape) #print(pixel_pos[0]) #print(pixel_pos[1]) # CONVERTING GEOMETRY (1D TO 2D) ########################## buffer_id_str = geom.cam_id + "0" geom2d, pe_image_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, pe_image, buffer_id_str, add_rot=0) geom2d, calibrated_image_2d = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, calibrated_image, buffer_id_str, add_rot=0) geom2d, uncalibrated_image_2d_ch0 = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, uncalibrated_image[0], buffer_id_str, add_rot=0) geom2d, uncalibrated_image_2d_ch1 = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, uncalibrated_image[1], buffer_id_str, add_rot=0) geom2d, pedestal_2d_ch0 = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, pedestal[0], buffer_id_str, add_rot=0) geom2d, pedestal_2d_ch1 = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, pedestal[1], buffer_id_str, add_rot=0) geom2d, gains_2d_ch0 = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, gain[0], buffer_id_str, add_rot=0) geom2d, gains_2d_ch1 = ctapipe_geom_converter.convert_geometry_1d_to_2d(geom, gain[1], buffer_id_str, add_rot=0) # Make a mock pixel position array... pixel_pos_2d = np.array(np.meshgrid(np.linspace(pixel_pos[0].min(), pixel_pos[0].max(), pe_image_2d.shape[0]), np.linspace(pixel_pos[1].min(), pixel_pos[1].max(), pe_image_2d.shape[1]))) ########################################################### # The ctapipe geometry converter operate on one channel # only and then takes and return a 2D array but datapipe # fits files keep all channels and thus takes 3D arrays... uncalibrated_image_2d = np.array([uncalibrated_image_2d_ch0, uncalibrated_image_2d_ch1]) pedestal_2d = np.array([pedestal_2d_ch0, pedestal_2d_ch1 ]) gains_2d = np.array([gains_2d_ch0, gains_2d_ch1]) # PUT NAN IN BLANK PIXELS ################################# calibrated_image_2d[np.logical_not(geom2d.mask)] = np.nan pe_image_2d[np.logical_not(geom2d.mask)] = np.nan uncalibrated_image_2d[0, np.logical_not(geom2d.mask)] = np.nan uncalibrated_image_2d[1, np.logical_not(geom2d.mask)] = np.nan pedestal_2d[0, np.logical_not(geom2d.mask)] = np.nan pedestal_2d[1, np.logical_not(geom2d.mask)] = np.nan gains_2d[0, np.logical_not(geom2d.mask)] = np.nan gains_2d[1, np.logical_not(geom2d.mask)] = np.nan pixel_pos_2d[0, np.logical_not(geom2d.mask)] = np.nan pixel_pos_2d[1, np.logical_not(geom2d.mask)] = np.nan ########################################################### #print(pe_image_2d.shape) #print(calibrated_image_2d.shape) #print(uncalibrated_image_2d.shape) #print(pedestal_2d.shape) #print(gains_2d.shape) #img = pixel_pos_2d #print(img[1]) #import matplotlib.pyplot as plt #im = plt.imshow(img[1]) #plt.colorbar(im) #plt.show() #sys.exit(0) # GET PIXEL MASK ########################################## pixel_mask = geom2d.mask.astype(int) # 1 for pixels with actual data, 0 for virtual (blank) pixels # MAKE METADATA ########################################### metadata = {} metadata['version'] = 1 # Version of the datapipe fits format metadata['cam_id'] = "LSTCam" metadata['tel_id'] = tel_id metadata['event_id'] = event_id metadata['simtel'] = simtel_file_path metadata['tel_trig'] = len(event.trig.tels_with_trigger) metadata['energy'] = quantity_to_tuple(event.mc.energy, 'TeV') metadata['mc_az'] = quantity_to_tuple(event.mc.az, 'rad') metadata['mc_alt'] = quantity_to_tuple(event.mc.alt, 'rad') metadata['mc_corex'] = quantity_to_tuple(event.mc.core_x, 'm') metadata['mc_corey'] = quantity_to_tuple(event.mc.core_y, 'm') metadata['mc_hfi'] = quantity_to_tuple(event.mc.h_first_int, 'm') metadata['count'] = int(event.count) metadata['run_id'] = int(event.dl0.run_id) metadata['tel_data'] = len(event.dl0.tels_with_data) metadata['foclen'] = quantity_to_tuple(event.inst.optical_foclen[tel_id], 'm') metadata['tel_posx'] = quantity_to_tuple(event.inst.tel_pos[tel_id][0], 'm') metadata['tel_posy'] = quantity_to_tuple(event.inst.tel_pos[tel_id][1], 'm') metadata['tel_posz'] = quantity_to_tuple(event.inst.tel_pos[tel_id][2], 'm') # TODO: Astropy fails to store the following data in FITS files #metadata['uid'] = os.getuid() #metadata['datetime'] = str(datetime.datetime.now()) #metadata['version'] = VERSION #metadata['argv'] = " ".join(sys.argv).encode('ascii', errors='ignore').decode('ascii') #metadata['python'] = " ".join(sys.version.splitlines()).encode('ascii', errors='ignore').decode('ascii') #metadata['system'] = " ".join(os.uname()) # SAVE THE IMAGE ########################################## output_file_path_template = "{}_TEL{:03d}_EV{:05d}.fits" if output_directory is not None: simtel_basename = os.path.basename(simtel_file_path) prefix = os.path.join(output_directory, simtel_basename) else: prefix = simtel_file_path output_file_path = output_file_path_template.format(prefix, tel_id, event_id) print("saving", output_file_path) images.save_benchmark_images(img = calibrated_image_2d, pe_img = pe_image_2d, adc_sums_img = uncalibrated_image_2d, pedestal_img = pedestal_2d, gains_img = gains_2d, pixel_pos = pixel_pos_2d, pixel_mask = pixel_mask, metadata = metadata, output_file_path = output_file_path)
def reconstruct_event(self, event): """ Perform full event reconstruction, including Hillas and ImPACT analysis. Parameters ---------- event: ctapipe event container Returns ------- None """ # store MC pointing direction for the array array_pointing = HorizonFrame( alt=event.mcheader.run_array_direction[1] * u.rad, az=event.mcheader.run_array_direction[0] * u.rad) tilted_system = TiltedGroundFrame(pointing_direction=array_pointing) image = {} pixel_x = {} pixel_y = {} pixel_area = {} tel_type = {} tel_x = {} tel_y = {} hillas = {} hillas_nom = {} image_pred = {} mask_dict = {} print("Event energy", event.mc.energy) for tel_id in event.dl0.tels_with_data: # Get calibrated image (low gain channel only) pmt_signal = event.dl1.tel[tel_id].image[0] if len(event.dl1.tel[tel_id].image) > 1: print(event.dl1.tel[tel_id].image[1][pmt_signal > 100]) pmt_signal[pmt_signal > 100] = \ event.dl1.tel[tel_id].image[1][pmt_signal > 100] # Create nominal system for the telescope (this should later used telescope # pointing) nom_system = NominalFrame(array_direction=array_pointing, pointing_direction=array_pointing) # Create camera system of all pixels pix_x, pix_y = event.inst.pixel_pos[tel_id] fl = event.inst.optical_foclen[tel_id] if tel_id not in self.geoms: self.geoms[tel_id] = CameraGeometry.guess( pix_x, pix_y, event.inst.optical_foclen[tel_id], apply_derotation=False) # Transform the pixels positions into nominal coordinates camera_coord = CameraFrame(x=pix_x, y=pix_y, z=np.zeros(pix_x.shape) * u.m, focal_length=fl, rotation=-1 * self.geoms[tel_id].cam_rotation) nom_coord = camera_coord.transform_to(nom_system) tx, ty, tz = event.inst.tel_pos[tel_id] # ImPACT reconstruction is performed in the tilted system, # so we need to transform tel positions grd_tel = GroundFrame(x=tx, y=ty, z=tz) tilt_tel = grd_tel.transform_to(tilted_system) # Clean image using split level cleaning mask = tailcuts_clean( self.geoms[tel_id], pmt_signal, picture_thresh=self.tail_cut[self.geoms[tel_id].cam_id][1], boundary_thresh=self.tail_cut[self.geoms[tel_id].cam_id][0]) # Perform Hillas parameterisation moments = None try: moments_cam = hillas_parameters( event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], pmt_signal * mask) moments = hillas_parameters(nom_coord.x, nom_coord.y, pmt_signal * mask) except HillasParameterizationError as e: print(e) continue # Make cut based on Hillas parameters if self.preselect(moments, np.sum(mask), tel_id): # Dialte around edges of image for i in range(4): mask = dilate(self.geoms[tel_id], mask) # Save everything in dicts for reconstruction later pixel_area[tel_id] = self.geoms[tel_id].pix_area / (fl * fl) pixel_area[tel_id] *= u.rad * u.rad pixel_x[tel_id] = nom_coord.x pixel_y[tel_id] = nom_coord.y tel_x[tel_id] = tilt_tel.x tel_y[tel_id] = tilt_tel.y tel_type[tel_id] = self.geoms[tel_id].cam_id image[tel_id] = pmt_signal image_pred[tel_id] = np.zeros(pmt_signal.shape) hillas[tel_id] = moments_cam hillas_nom[tel_id] = moments mask_dict[tel_id] = mask # Cut on number of telescopes remaining if len(image) > 1: fit_result = self.fit.predict(hillas_nom, tel_x, tel_y, array_pointing) for tel_id in hillas_nom: core_grd = GroundFrame(x=fit_result.core_x, y=fit_result.core_y, z=0. * u.m) core_tilt = core_grd.transform_to(tilted_system) impact = np.sqrt( np.power(tel_x[tel_id] - core_tilt.x, 2) + np.power(tel_y[tel_id] - core_tilt.y, 2)) pix = np.array([ pixel_x[tel_id].to(u.deg).value, pixel_y[tel_id].to(u.deg).value ]) img = image[tel_id] #img[img < 0.0] = 0.0 #img /= np.max(img) lin = LinearNDInterpolator(pix.T, img, fill_value=0.0) x_img = np.arange(-4, 4, 0.05) * u.deg y_img = np.arange(-4, 4, 0.05) * u.deg xv, yv = np.meshgrid(x_img, y_img) pos = np.array([xv.ravel(), yv.ravel()]) npix = xv.shape[0] img_int = np.reshape(lin(pos.T), xv.shape) print(img_int) hdu = fits.ImageHDU(img_int.astype(np.float32)) hdu.header["IMPACT"] = impact.to(u.m).value hdu.header["TELTYPE"] = tel_type[tel_id] hdu.header["TELNUM"] = tel_id hdu.header["MCENERGY"] = event.mc.energy.to(u.TeV).value hdu.header["RECENERGY"] = 0 hdu.header["AMP"] = hillas_nom[tel_id].size hdu.header["WIDTH"] = hillas_nom[tel_id].width.to(u.deg).value hdu.header["LENGTH"] = hillas_nom[tel_id].length.to( u.deg).value self.output.append(hdu)
def plot(self, input_file, event, telid, chan, extractor_name): # Extract required images dl0 = event.dl0.tel[telid].pe_samples[chan] t_pe = event.mc.tel[telid].photo_electron_image dl1 = event.dl1.tel[telid].image[chan] max_time = np.unravel_index(np.argmax(dl0), dl0.shape)[1] max_charges = np.max(dl0, axis=1) max_pix = int(np.argmax(max_charges)) min_pix = int(np.argmin(max_charges)) geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) nei = geom.neighbors # Get Neighbours max_pixel_nei = nei[max_pix] min_pixel_nei = nei[min_pix] # Get Windows windows = event.dl1.tel[telid].extracted_samples[chan] length = np.sum(windows, axis=1) start = np.argmax(windows, axis=1) end = start + length - 1 # Draw figures ax_max_nei = {} ax_min_nei = {} fig_waveforms = plt.figure(figsize=(18, 9)) fig_waveforms.subplots_adjust(hspace=.5) fig_camera = plt.figure(figsize=(15, 12)) ax_max_pix = fig_waveforms.add_subplot(4, 2, 1) ax_min_pix = fig_waveforms.add_subplot(4, 2, 2) ax_max_nei[0] = fig_waveforms.add_subplot(4, 2, 3) ax_min_nei[0] = fig_waveforms.add_subplot(4, 2, 4) ax_max_nei[1] = fig_waveforms.add_subplot(4, 2, 5) ax_min_nei[1] = fig_waveforms.add_subplot(4, 2, 6) ax_max_nei[2] = fig_waveforms.add_subplot(4, 2, 7) ax_min_nei[2] = fig_waveforms.add_subplot(4, 2, 8) ax_img_nei = fig_camera.add_subplot(2, 2, 1) ax_img_max = fig_camera.add_subplot(2, 2, 2) ax_img_true = fig_camera.add_subplot(2, 2, 3) ax_img_cal = fig_camera.add_subplot(2, 2, 4) # Draw max pixel traces ax_max_pix.plot(dl0[max_pix]) ax_max_pix.set_xlabel("Time (ns)") ax_max_pix.set_ylabel("DL0 Samples (ADC)") ax_max_pix.set_title( "(Max) Pixel: {}, True: {}, Measured = {:.3f}".format( max_pix, t_pe[max_pix], dl1[max_pix])) max_ylim = ax_max_pix.get_ylim() ax_max_pix.plot([start[max_pix], start[max_pix]], ax_max_pix.get_ylim(), color='r', alpha=1) ax_max_pix.plot([end[max_pix], end[max_pix]], ax_max_pix.get_ylim(), color='r', alpha=1) for i, ax in ax_max_nei.items(): if len(max_pixel_nei) > i: pix = max_pixel_nei[i] ax.plot(dl0[pix]) ax.set_xlabel("Time (ns)") ax.set_ylabel("DL0 Samples (ADC)") ax.set_title( "(Max Nei) Pixel: {}, True: {}, Measured = {:.3f}".format( pix, t_pe[pix], dl1[pix])) ax.set_ylim(max_ylim) ax.plot([start[pix], start[pix]], ax.get_ylim(), color='r', alpha=1) ax.plot([end[pix], end[pix]], ax.get_ylim(), color='r', alpha=1) # Draw min pixel traces ax_min_pix.plot(dl0[min_pix]) ax_min_pix.set_xlabel("Time (ns)") ax_min_pix.set_ylabel("DL0 Samples (ADC)") ax_min_pix.set_title( "(Min) Pixel: {}, True: {}, Measured = {:.3f}".format( min_pix, t_pe[min_pix], dl1[min_pix])) ax_min_pix.set_ylim(max_ylim) ax_min_pix.plot([start[min_pix], start[min_pix]], ax_min_pix.get_ylim(), color='r', alpha=1) ax_min_pix.plot([end[min_pix], end[min_pix]], ax_min_pix.get_ylim(), color='r', alpha=1) for i, ax in ax_min_nei.items(): if len(min_pixel_nei) > i: pix = min_pixel_nei[i] ax.plot(dl0[pix]) ax.set_xlabel("Time (ns)") ax.set_ylabel("DL0 Samples (ADC)") ax.set_title( "(Min Nei) Pixel: {}, True: {}, Measured = {:.3f}".format( pix, t_pe[pix], dl1[pix])) ax.set_ylim(max_ylim) ax.plot([start[pix], start[pix]], ax.get_ylim(), color='r', alpha=1) ax.plot([end[pix], end[pix]], ax.get_ylim(), color='r', alpha=1) # Draw cameras nei_camera = np.zeros_like(max_charges, dtype=np.int) nei_camera[min_pixel_nei] = 2 nei_camera[min_pix] = 1 nei_camera[max_pixel_nei] = 3 nei_camera[max_pix] = 4 camera = CameraDisplay(geom, ax=ax_img_nei) camera.image = nei_camera camera.cmap = plt.cm.viridis ax_img_nei.set_title("Neighbour Map") ax_img_nei.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_nei.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') camera = CameraDisplay(geom, ax=ax_img_max) camera.image = dl0[:, max_time] camera.cmap = plt.cm.viridis camera.add_colorbar(ax=ax_img_max, label="DL0 Samples (ADC)") ax_img_max.set_title("Max Timeslice (T = {})".format(max_time)) ax_img_max.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_max.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') camera = CameraDisplay(geom, ax=ax_img_true) camera.image = t_pe camera.cmap = plt.cm.viridis camera.add_colorbar(ax=ax_img_true, label="True Charge (p.e.)") ax_img_true.set_title("True Charge") ax_img_true.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_true.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') camera = CameraDisplay(geom, ax=ax_img_cal) camera.image = dl1 camera.cmap = plt.cm.viridis camera.add_colorbar(ax=ax_img_cal, label="Calib Charge (Photo-electrons)") ax_img_cal.set_title("Charge (integrator={})".format(extractor_name)) ax_img_cal.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_cal.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') fig_waveforms.suptitle("Integrator = {}".format(extractor_name)) fig_camera.suptitle("Camera = {}".format(geom.cam_id)) waveform_output_name = "e{}_t{}_c{}_extractor{}_waveform.pdf"\ .format(event.count, telid, chan, extractor_name) camera_output_name = "e{}_t{}_c{}_extractor{}_camera.pdf"\ .format(event.count, telid, chan, extractor_name) output_dir = self.output_dir if output_dir is None: output_dir = input_file.output_directory output_dir = os.path.join(output_dir, self.name) if not os.path.exists(output_dir): self.log.info("Creating directory: {}".format(output_dir)) os.makedirs(output_dir) waveform_output_path = os.path.join(output_dir, waveform_output_name) self.log.info("Saving: {}".format(waveform_output_path)) fig_waveforms.savefig(waveform_output_path, format='pdf', bbox_inches='tight') camera_output_path = os.path.join(output_dir, camera_output_name) self.log.info("Saving: {}".format(camera_output_path)) fig_camera.savefig(camera_output_path, format='pdf', bbox_inches='tight') return geom
def get_geometry(self, event, telid): if telid not in self._geom_dict: geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) self._geom_dict[telid] = geom return self._geom_dict[telid]
def start(self): df_list = [] n_frames = 0 first_event = self.reader.get_event(0) n_samples = first_event.r0.tel[0].num_samples pos = first_event.inst.pixel_pos[0] foclen = first_event.inst.optical_foclen[0] geom = CameraGeometry.guess(*pos, foclen) desc = "Extracting image slices from file" n_events = self.reader.num_events source = self.reader.read() for event in tqdm(source, total=n_events, desc=desc): event_id = event.r0.event_id self.r1.calibrate(event) self.dl0.reduce(event) self.dl1.calibrate(event) image = event.dl1.tel[0].image[0] cleaned = event.dl1.tel[0].cleaned[0] # Cleaning tc = tailcuts_clean(geom, image, 7, 3) empty = np.zeros(cleaned.shape, dtype=bool) cleaned_tc_mask = np.ma.mask_or(empty, ~tc[:, None]) cleaned_dl1 = np.ma.masked_array(cleaned, mask=cleaned_tc_mask) # Find start and end of movie for event sum_wf = np.sum(cleaned_dl1, axis=0) sum_wf_t = np.arange(sum_wf.size) max_ = np.max(sum_wf) tmax = np.argmax(sum_wf) before = sum_wf[:tmax + 1][::-1] before_t = sum_wf_t[:tmax + 1][::-1] after = sum_wf[tmax:] after_t = sum_wf_t[tmax:] limit = 0.1 * max_ # if limit < 2: # limit = 2 try: start = before_t[before <= limit][0] - 2 end = after_t[after <= limit][0] + 5 except IndexError: self.log.warning("No image for event id {}".format(event_id)) continue if start < 0: start = 0 if end >= n_samples: end = n_samples - 1 s = [] for t in range(start, end): s.append(cleaned[:, t]) n_frames += 1 df_list.append(dict(event_id=event_id, images=np.array(s), tc=tc)) df = pd.DataFrame(df_list) output_dir = self.reader.output_directory title = self.reader.filename title = title[:title.find("_")] # Prepare Output if not exists(output_dir): self.log.info("Creating directory: {}".format(output_dir)) makedirs(output_dir) output_path = join(output_dir, title + "_animation.mp4") self.animator.plot(df, n_frames, geom, output_path, title)
def extract_images(simtel_file_path, tel_id_filter_list=None, event_id_filter_list=None, output_directory=None, crop=True): # EXTRACT IMAGES ########################################################## # hessio_event_source returns a Python generator that streams data from an # EventIO/HESSIO MC data file (e.g. a standard CTA data file). # This generator contains ctapipe.core.Container instances ("event"). # # Parameters: # - max_events: maximum number of events to read # - allowed_tels: select only a subset of telescope, if None, all are read. source = hessio_event_source(simtel_file_path, allowed_tels=tel_id_filter_list) # ITERATE OVER EVENTS ##################################################### calib = CameraCalibrator(None, None) for event in source: calib.calibrate(event) # calibrate the event event_id = int(event.dl0.event_id) if (event_id_filter_list is None) or (event_id in event_id_filter_list): #print("event", event_id) # ITERATE OVER IMAGES ############################################# for tel_id in event.trig.tels_with_trigger: tel_id = int(tel_id) if tel_id in tel_id_filter_list: #print("telescope", tel_id) # CHECK THE IMAGE GEOMETRY (ASTRI ONLY) ################### # TODO #print("checking geometry") x, y = event.inst.pixel_pos[tel_id] foclen = event.inst.optical_foclen[tel_id] geom = CameraGeometry.guess(x, y, foclen) if (geom.pix_type != "rectangular") or (geom.cam_id not in ("ASTRICam", "ASTRI")): raise ValueError("Telescope {}: error (the input image is not a valide ASTRI telescope image) -> {} ({})".format(tel_id, geom.pix_type, geom.cam_id)) # GET IMAGES ############################################## pe_image = event.mc.tel[tel_id].photo_electron_image # 1D np array #uncalibrated_image = event.dl0.tel[tel_id].adc_sums # ctapipe 0.3.0 uncalibrated_image = event.r0.tel[tel_id].adc_sums # ctapipe 0.4.0 pedestal = event.mc.tel[tel_id].pedestal gain = event.mc.tel[tel_id].dc_to_pe pixel_pos = event.inst.pixel_pos[tel_id] calibrated_image = event.dl1.tel[tel_id].image calibrated_image[1, calibrated_image[0,:] <= ASTRI_CAM_CHANNEL_THRESHOLD] = 0 calibrated_image[0, calibrated_image[0,:] > ASTRI_CAM_CHANNEL_THRESHOLD] = 0 calibrated_image = calibrated_image.sum(axis=0) #print(pe_image.shape) #print(calibrated_image.shape) #print(uncalibrated_image.shape) #print(pedestal.shape) #print(gain.shape) #print(pixel_pos.shape) #print(pixel_pos[0]) #print(pixel_pos[1]) # CONVERTING GEOMETRY (1D TO 2D) ########################## pe_image_2d = geometry_converter.astri_to_2d_array(pe_image, crop=crop) calibrated_image_2d = geometry_converter.astri_to_2d_array(calibrated_image, crop=crop) uncalibrated_image_2d = geometry_converter.astri_to_3d_array(uncalibrated_image, crop=crop) pedestal_2d = geometry_converter.astri_to_3d_array(pedestal, crop=crop) gains_2d = geometry_converter.astri_to_3d_array(gain, crop=crop) pixel_pos_2d = geometry_converter.astri_to_3d_array(pixel_pos, crop=crop) #print(pe_image_2d.shape) #print(calibrated_image_2d.shape) #print(uncalibrated_image_2d.shape) #print(pedestal_2d.shape) #print(gains_2d.shape) #print(pixel_pos_2d.shape) #sys.exit(0) # GET PIXEL MASK ########################################## pixel_mask = geometry_converter.astri_pixel_mask(crop) # 1 for pixels with actual data, 0 for virtual (blank) pixels # MAKE METADATA ########################################### metadata = {} metadata['version'] = 1 # Version of the datapipe fits format if crop: metadata['cam_id'] = "ASTRI_CROPPED" else: metadata['cam_id'] = "ASTRI" metadata['tel_id'] = tel_id metadata['event_id'] = event_id metadata['simtel'] = simtel_file_path metadata['tel_trig'] = len(event.trig.tels_with_trigger) metadata['energy'] = quantity_to_tuple(event.mc.energy, 'TeV') metadata['mc_az'] = quantity_to_tuple(event.mc.az, 'rad') metadata['mc_alt'] = quantity_to_tuple(event.mc.alt, 'rad') metadata['mc_corex'] = quantity_to_tuple(event.mc.core_x, 'm') metadata['mc_corey'] = quantity_to_tuple(event.mc.core_y, 'm') metadata['mc_hfi'] = quantity_to_tuple(event.mc.h_first_int, 'm') metadata['count'] = int(event.count) metadata['run_id'] = int(event.dl0.run_id) metadata['tel_data'] = len(event.dl0.tels_with_data) metadata['foclen'] = quantity_to_tuple(event.inst.optical_foclen[tel_id], 'm') metadata['tel_posx'] = quantity_to_tuple(event.inst.tel_pos[tel_id][0], 'm') metadata['tel_posy'] = quantity_to_tuple(event.inst.tel_pos[tel_id][1], 'm') metadata['tel_posz'] = quantity_to_tuple(event.inst.tel_pos[tel_id][2], 'm') # TODO: Astropy fails to store the following data in FITS files #metadata['uid'] = os.getuid() #metadata['datetime'] = str(datetime.datetime.now()) #metadata['version'] = VERSION #metadata['argv'] = " ".join(sys.argv).encode('ascii', errors='ignore').decode('ascii') #metadata['python'] = " ".join(sys.version.splitlines()).encode('ascii', errors='ignore').decode('ascii') #metadata['system'] = " ".join(os.uname()) # SAVE THE IMAGE ########################################## output_file_path_template = "{}_TEL{:03d}_EV{:05d}.fits" if output_directory is not None: simtel_basename = os.path.basename(simtel_file_path) prefix = os.path.join(output_directory, simtel_basename) else: prefix = simtel_file_path output_file_path = output_file_path_template.format(prefix, tel_id, event_id) print("saving", output_file_path) images.save_benchmark_images(img = calibrated_image_2d, pe_img = pe_image_2d, adc_sums_img = uncalibrated_image_2d, pedestal_img = pedestal_2d, gains_img = gains_2d, pixel_pos = pixel_pos_2d, pixel_mask = pixel_mask, metadata = metadata, output_file_path = output_file_path)
def plot(self, input_file, event, telid, chan, extractor_name): # Extract required images dl0 = event.dl0.tel[telid].pe_samples[chan] t_pe = event.mc.tel[telid].photo_electron_image dl1 = event.dl1.tel[telid].image[chan] max_time = np.unravel_index(np.argmax(dl0), dl0.shape)[1] max_charges = np.max(dl0, axis=1) max_pix = int(np.argmax(max_charges)) min_pix = int(np.argmin(max_charges)) geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) nei = geom.neighbors # Get Neighbours max_pixel_nei = nei[max_pix] min_pixel_nei = nei[min_pix] # Get Windows windows = event.dl1.tel[telid].extracted_samples[chan] length = np.sum(windows, axis=1) start = np.argmax(windows, axis=1) end = start + length - 1 # Draw figures ax_max_nei = {} ax_min_nei = {} fig_waveforms = plt.figure(figsize=(18, 9)) fig_waveforms.subplots_adjust(hspace=.5) fig_camera = plt.figure(figsize=(15, 12)) ax_max_pix = fig_waveforms.add_subplot(4, 2, 1) ax_min_pix = fig_waveforms.add_subplot(4, 2, 2) ax_max_nei[0] = fig_waveforms.add_subplot(4, 2, 3) ax_min_nei[0] = fig_waveforms.add_subplot(4, 2, 4) ax_max_nei[1] = fig_waveforms.add_subplot(4, 2, 5) ax_min_nei[1] = fig_waveforms.add_subplot(4, 2, 6) ax_max_nei[2] = fig_waveforms.add_subplot(4, 2, 7) ax_min_nei[2] = fig_waveforms.add_subplot(4, 2, 8) ax_img_nei = fig_camera.add_subplot(2, 2, 1) ax_img_max = fig_camera.add_subplot(2, 2, 2) ax_img_true = fig_camera.add_subplot(2, 2, 3) ax_img_cal = fig_camera.add_subplot(2, 2, 4) # Draw max pixel traces ax_max_pix.plot(dl0[max_pix]) ax_max_pix.set_xlabel("Time (ns)") ax_max_pix.set_ylabel("DL0 Samples (ADC)") ax_max_pix.set_title("(Max) Pixel: {}, True: {}, Measured = {:.3f}" .format(max_pix, t_pe[max_pix], dl1[max_pix])) max_ylim = ax_max_pix.get_ylim() ax_max_pix.plot([start[max_pix], start[max_pix]], ax_max_pix.get_ylim(), color='r', alpha=1) ax_max_pix.plot([end[max_pix], end[max_pix]], ax_max_pix.get_ylim(), color='r', alpha=1) for i, ax in ax_max_nei.items(): if len(max_pixel_nei) > i: pix = max_pixel_nei[i] ax.plot(dl0[pix]) ax.set_xlabel("Time (ns)") ax.set_ylabel("DL0 Samples (ADC)") ax.set_title("(Max Nei) Pixel: {}, True: {}, Measured = {:.3f}" .format(pix, t_pe[pix], dl1[pix])) ax.set_ylim(max_ylim) ax.plot([start[pix], start[pix]], ax.get_ylim(), color='r', alpha=1) ax.plot([end[pix], end[pix]], ax.get_ylim(), color='r', alpha=1) # Draw min pixel traces ax_min_pix.plot(dl0[min_pix]) ax_min_pix.set_xlabel("Time (ns)") ax_min_pix.set_ylabel("DL0 Samples (ADC)") ax_min_pix.set_title("(Min) Pixel: {}, True: {}, Measured = {:.3f}" .format(min_pix, t_pe[min_pix], dl1[min_pix])) ax_min_pix.set_ylim(max_ylim) ax_min_pix.plot([start[min_pix], start[min_pix]], ax_min_pix.get_ylim(), color='r', alpha=1) ax_min_pix.plot([end[min_pix], end[min_pix]], ax_min_pix.get_ylim(), color='r', alpha=1) for i, ax in ax_min_nei.items(): if len(min_pixel_nei) > i: pix = min_pixel_nei[i] ax.plot(dl0[pix]) ax.set_xlabel("Time (ns)") ax.set_ylabel("DL0 Samples (ADC)") ax.set_title("(Min Nei) Pixel: {}, True: {}, Measured = {:.3f}" .format(pix, t_pe[pix], dl1[pix])) ax.set_ylim(max_ylim) ax.plot([start[pix], start[pix]], ax.get_ylim(), color='r', alpha=1) ax.plot([end[pix], end[pix]], ax.get_ylim(), color='r', alpha=1) # Draw cameras nei_camera = np.zeros_like(max_charges, dtype=np.int) nei_camera[min_pixel_nei] = 2 nei_camera[min_pix] = 1 nei_camera[max_pixel_nei] = 3 nei_camera[max_pix] = 4 camera = CameraDisplay(geom, ax=ax_img_nei) camera.image = nei_camera camera.cmap = plt.cm.viridis ax_img_nei.set_title("Neighbour Map") ax_img_nei.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_nei.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') camera = CameraDisplay(geom, ax=ax_img_max) camera.image = dl0[:, max_time] camera.cmap = plt.cm.viridis camera.add_colorbar(ax=ax_img_max, label="DL0 Samples (ADC)") ax_img_max.set_title("Max Timeslice (T = {})".format(max_time)) ax_img_max.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_max.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') camera = CameraDisplay(geom, ax=ax_img_true) camera.image = t_pe camera.cmap = plt.cm.viridis camera.add_colorbar(ax=ax_img_true, label="True Charge (p.e.)") ax_img_true.set_title("True Charge") ax_img_true.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_true.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') camera = CameraDisplay(geom, ax=ax_img_cal) camera.image = dl1 camera.cmap = plt.cm.viridis camera.add_colorbar(ax=ax_img_cal, label="Calib Charge (Photo-electrons)") ax_img_cal.set_title("Charge (integrator={})".format(extractor_name)) ax_img_cal.annotate("Pixel: {}".format(max_pix), xy=(geom.pix_x.value[max_pix], geom.pix_y.value[max_pix]), xycoords='data', xytext=(0.05, 0.98), textcoords='axes fraction', arrowprops=dict(facecolor='red', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') ax_img_cal.annotate("Pixel: {}".format(min_pix), xy=(geom.pix_x.value[min_pix], geom.pix_y.value[min_pix]), xycoords='data', xytext=(0.05, 0.94), textcoords='axes fraction', arrowprops=dict(facecolor='orange', width=2, alpha=0.4), horizontalalignment='left', verticalalignment='top') fig_waveforms.suptitle("Integrator = {}".format(extractor_name)) fig_camera.suptitle("Camera = {}".format(geom.cam_id)) waveform_output_name = "e{}_t{}_c{}_extractor{}_waveform.pdf"\ .format(event.count, telid, chan, extractor_name) camera_output_name = "e{}_t{}_c{}_extractor{}_camera.pdf"\ .format(event.count, telid, chan, extractor_name) output_dir = self.output_dir if output_dir is None: output_dir = input_file.output_directory output_dir = os.path.join(output_dir, self.name) if not os.path.exists(output_dir): self.log.info("Creating directory: {}".format(output_dir)) os.makedirs(output_dir) waveform_output_path = os.path.join(output_dir, waveform_output_name) self.log.info("Saving: {}".format(waveform_output_path)) fig_waveforms.savefig(waveform_output_path, format='pdf', bbox_inches='tight') camera_output_path = os.path.join(output_dir, camera_output_name) self.log.info("Saving: {}".format(camera_output_path)) fig_camera.savefig(camera_output_path, format='pdf', bbox_inches='tight') return geom
def analyze_muon_event(event, params=None, geom_dict=None): """ Generic muon event analyzer. Parameters ---------- event : ctapipe dl1 event container Returns ------- muonringparam, muonintensityparam : MuonRingParameter and MuonIntensityParameter container event """ # Declare a dict to define the muon cuts (ASTRI and SCT missing) muon_cuts = {} names = ['LST:LSTCam','MST:NectarCam','MST:FlashCam','MST-SCT:SCTCam','SST-1M:DigiCam','SST-GCT:CHEC','SST-ASTRI:ASTRICam'] TailCuts = [(5,7),(5,7),(10,12),(5,7),(5,7),(5,7),(5,7)] #10,12? impact = [(0.2,0.9),(0.1,0.95),(0.2,0.9),(0.2,0.9),(0.1,0.95),(0.1,0.95),(0.1,0.95)] ringwidth = [(0.04,0.08),(0.02,0.1),(0.01,0.1),(0.02,0.1),(0.01,0.5),(0.02,0.2),(0.02,0.2)] TotalPix = [1855.,1855.,1764.,11328.,1296.,2048.,2368.]#8% (or 6%) as limit MinPix = [148.,148.,141.,680.,104.,164.,142.] #Need to either convert from the pixel area in m^2 or check the camera specs AngPixelWidth = [0.1,0.2,0.18,0.067,0.24,0.2,0.17] #Found from TDRs (or the pixel area) hole_rad = []#Need to check and implement cam_rad = [2.26,3.96,3.87,4.,4.45,2.86,5.25]#Found from the field of view calculation sec_rad = [0.*u.m,0.*u.m,0.*u.m,2.7*u.m,0.*u.m,1.*u.m,1.8*u.m] sct = [False,False,False,True,False,True,True] muon_cuts = {'Name':names,'TailCuts':TailCuts,'Impact':impact,'RingWidth':ringwidth,'TotalPix':TotalPix,'MinPix':MinPix,'CamRad':cam_rad,'SecRad':sec_rad,'SCT':sct,'AngPixW':AngPixelWidth} #print(muon_cuts) muonringlist = []#[None] * len(event.dl0.tels_with_data) muonintensitylist = []#[None] * len(event.dl0.tels_with_data) tellist = [] #for tid in event.dl0.tels_with_data: # tellist.append(tid) muon_event_param = {'TelIds':tellist,'MuonRingParams':muonringlist,'MuonIntensityParams':muonintensitylist} #muonringparam = None #muonintensityparam = None for telid in event.dl0.tels_with_data: #print("Analysing muon event for tel",telid) muonringparam = None muonintensityparam = None #idx = muon_event_param['TelIds'].index(telid) x, y = event.inst.pixel_pos[telid] #image = event.dl1.tel[telid].calibrated_image image = event.dl1.tel[telid].image[0] # Get geometry geom = None if geom_dict is not None and telid in geom_dict: geom = geom_dict[telid] else: log.debug("[calib] Guessing camera geometry") geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) log.debug("[calib] Camera geometry found") if geom_dict is not None: geom_dict[telid] = geom teldes = event.inst.subarray.tel[telid] dict_index = muon_cuts['Name'].index(str(teldes)) #print('found an index of',dict_index,'for camera',geom.cam_id) #tailcuts = (5.,7.) tailcuts = muon_cuts['TailCuts'][dict_index] #print("Tailcuts are",tailcuts[0],tailcuts[1]) #rot_angle = 0.*u.deg #if event.inst.optical_foclen[telid] > 10.*u.m and event.dl0.tel[telid].num_pixels != 1764: #rot_angle = -100.14*u.deg clean_mask = tailcuts_clean(geom,image,picture_thresh=tailcuts[0],boundary_thresh=tailcuts[1]) 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) #print("Camera",geom.cam_id,"focal length",event.inst.optical_foclen[telid],"rotation",geom.pix_rotation) #TODO: correct this hack for values over 90 altval = event.mcheader.run_array_direction[1] if (altval > np.pi/2.): altval = np.pi/2. altaz = HorizonFrame(alt=altval*u.rad,az=event.mcheader.run_array_direction[0]*u.rad) nom_coord = camera_coord.transform_to(NominalFrame(array_direction=altaz,pointing_direction=altaz)) x = nom_coord.x.to(u.deg) y = nom_coord.y.to(u.deg) img = image*clean_mask noise = 5. weight = img / (img+noise) muonring = ChaudhuriKunduRingFitter(None) #print("img:",np.sum(image),"mask:",np.sum(clean_mask), "x=",x,"y=",y) if not sum(img):#Nothing left after tail cuts continue muonringparam = muonring.fit(x,y,image*clean_mask) #muonringparam = muonring.fit(x,y,weight) 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,img*(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) #print("1: x",muonringparam.ring_center_x,"y",muonringparam.ring_center_y,"radius",muonringparam.ring_radius) muonringparam = muonring.fit(x,y,img*(ring_dist<muonringparam.ring_radius*0.4)) #print("2: x",muonringparam.ring_center_x,"y",muonringparam.ring_center_y,"radius",muonringparam.ring_radius) muonringparam.tel_id = telid muonringparam.run_id = event.dl0.run_id muonringparam.event_id = event.dl0.event_id dist_mask = np.abs(dist-muonringparam.ring_radius)<muonringparam.ring_radius*0.4 rad = list() cx = list() cy = list() mc_x = event.mc.core_x mc_y = event.mc.core_y pix_im = image*dist_mask nom_dist = np.sqrt(np.power(muonringparam.ring_center_x,2)+np.power(muonringparam.ring_center_y,2)) #numpix = event.dl0.tel[telid].num_pixels minpix = muon_cuts['MinPix'][dict_index]#0.06*numpix #or 8% mir_rad = np.sqrt(event.inst.mirror_dish_area[telid]/(np.pi))#need to consider units? (what about hole? Area is then less...) #Camera containment radius - better than nothing - guess pixel diameter of 0.11, all cameras are perfectly circular cam_rad = np.sqrt(numpix*0.11/(2.*np.pi)) if(np.sum(pix_im>tailcuts[0])>0.1*minpix and np.sum(pix_im)>minpix and nom_dist < muon_cuts['CamRad'][dict_index]*u.deg and muonringparam.ring_radius<1.5*u.deg and muonringparam.ring_radius>1.*u.deg): #Guess HESS is 0.16 #sec_rad = 0.*u.m #sct = False #if numpix == 2048 and mir_rad > 2.*u.m and mir_rad < 2.1*u.m: # sec_rad = 1.*u.m # sct = True #Store muon ring parameters (passing cuts stage 1) #muonringlist[idx] = muonringparam tellist.append(telid) muonringlist.append(muonringparam) muonintensitylist.append(None) #embed() ctel = MuonLineIntegrate(mir_rad,0.2*u.m,pixel_width=muon_cuts['AngPixW'][dict_index]*u.deg,sct_flag=muon_cuts['SCT'][dict_index], secondary_radius=muon_cuts['SecRad'][dict_index]) if (image.shape[0] == muon_cuts['TotalPix'][dict_index]): muonintensityoutput = ctel.fit_muon(muonringparam.ring_center_x,muonringparam.ring_center_y,muonringparam.ring_radius,x[dist_mask],y[dist_mask],image[dist_mask]) muonintensityoutput.tel_id = telid muonintensityoutput.run_id = event.dl0.run_id muonintensityoutput.event_id = event.dl0.event_id muonintensityoutput.mask = dist_mask print("Tel",telid,"Impact parameter = ",muonintensityoutput.impact_parameter,"mir_rad",mir_rad,"ring_width=",muonintensityoutput.ring_width) #if(muonintensityoutput.impact_parameter > muon_cuts['Impact'][dict_index][1]*mir_rad or muonintensityoutput.impact_parameter < muon_cuts['Impact'][dict_index][0]*mir_rad): # print("Failed on impact parameter low cut",muon_cuts['Impact'][dict_index][0]*mir_rad,"high cut",muon_cuts['Impact'][dict_index][1]*mir_rad,"for",geom.cam_id) #if(muonintensityoutput.ring_width > muon_cuts['RingWidth'][dict_index][1]*u.deg or muonintensityoutput.ring_width < muon_cuts['RingWidth'][dict_index][0]*u.deg): # print("Failed on ring width low cut",muon_cuts['RingWidth'][dict_index][0]*u.deg,"high cut",muon_cuts['RingWidth'][dict_index][1]*u.deg,"for ",geom.cam_id) #print("Cuts <",muon_cuts["Impact"][dict_index][1]*mir_rad,"cuts >",muon_cuts['Impact'][dict_index][0]*u.m,'ring_width < ',muon_cuts['RingWidth'][dict_index][1]*u.deg,'ring_width >',muon_cuts['RingWidth'][dict_index][0]*u.deg) if( muonintensityoutput.impact_parameter < muon_cuts['Impact'][dict_index][1]*mir_rad and muonintensityoutput.impact_parameter > muon_cuts['Impact'][dict_index][0]*u.m and muonintensityoutput.ring_width < muon_cuts['RingWidth'][dict_index][1]*u.deg and muonintensityoutput.ring_width > muon_cuts['RingWidth'][dict_index][0]*u.deg ): muonintensityparam = muonintensityoutput idx = tellist.index(telid) muonintensitylist[idx] = muonintensityparam print("Muon in tel",telid,"# tels in event=",len(event.dl0.tels_with_data)) else: continue #print("Fitted ring centre (2):",muonringparam.ring_center_x,muonringparam.ring_center_y) #return muonringparam, muonintensityparam return muon_event_param
def get_geometry(self, event, telid): if telid not in self._geom_dict: geom = CameraGeometry.guess(*event.inst.pixel_pos[telid], event.inst.optical_foclen[telid]) self._geom_dict[telid] = geom return self._geom_dict[telid]
def setup(self): self.log_format = "%(levelname)s: %(message)s [%(name)s.%(funcName)s]" data_config = self.config.copy() data_config['WaveformCleanerFactory'] = Config(cleaner='CHECMWaveformCleanerLocal') mc_config = self.config.copy() data_kwargs = dict(config=data_config, tool=self) mc_kwargs = dict(config=mc_config, tool=self) filepath = '/Volumes/gct-jason/data/170330/onsky-mrk501/Run05477_r1.tio' reader = TargetioFileReader(input_path=filepath, **data_kwargs) filepath = '/Users/Jason/Software/outputs/sim_telarray/meudon_cr/simtel_proton_nsb50_thrs30_1petal_rndm015_heide.gz' # filepath = '/Users/Jason/Software/outputs/sim_telarray/meudon_cr/simtel_proton_nsb50_thrs30.gz' reader_mc = HessioFileReader(input_path=filepath, **mc_kwargs) calibrator = CameraCalibrator(origin=reader.origin, **data_kwargs) calibrator_mc = CameraCalibrator(origin=reader_mc.origin, **mc_kwargs) first_event = reader.get_event(0) telid = list(first_event.r0.tels_with_data)[0] pos = first_event.inst.pixel_pos[telid] foclen = first_event.inst.optical_foclen[telid] geom = CameraGeometry.guess(*pos, foclen) first_event = reader_mc.get_event(0) telid = list(first_event.r0.tels_with_data)[0] pos_mc = first_event.inst.pixel_pos[telid] foclen = first_event.inst.optical_foclen[telid] geom_mc = CameraGeometry.guess(*pos_mc, foclen) d1 = dict(type='Data', reader=reader, calibrator=calibrator, pos=pos, geom=geom, t1=20, t2=10) d2 = dict(type='MC', reader=reader_mc, calibrator=calibrator_mc, pos=pos_mc, geom=geom_mc, t1=20, t2=10) self.reader_df = pd.DataFrame([d1, d2]) p_kwargs = data_kwargs p_kwargs['script'] = "checm_paper_hillas" p_kwargs['figure_name'] = "all_images" self.p_allimage = AllImagePlotter(**p_kwargs) p_kwargs['figure_name'] = "all_peak_time_images" self.p_alltimeimage = PeakTimePlotter(**p_kwargs) p_kwargs['figure_name'] = "all_mc_images" self.p_allmcimage = AllImagePlotter(**p_kwargs) p_kwargs['figure_name'] = "zero_width_images" self.p_zwimage = ZeroWidthImagePlotter(**p_kwargs) p_kwargs['figure_name'] = "zero_width_mc_images" self.p_zwmcimage = ZeroWidthImagePlotter(**p_kwargs) p_kwargs['figure_name'] = "muon_images" self.p_muonimage = MuonImagePlotter(**p_kwargs) p_kwargs['figure_name'] = "bright_images" self.p_brightimage = BrightImagePlotter(**p_kwargs) p_kwargs['figure_name'] = "count_image" self.p_countimage = CountPlotter(**p_kwargs) p_kwargs['figure_name'] = "whole_distribution" self.p_whole_dist = WholeDist(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "width_vs_length" self.p_widthvslength = WidthVsLength(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "size_vs_length" self.p_sizevslength = SizeVsLength(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "width_div_length" self.p_widthdivlength = WidthDivLength(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "length_div_size" self.p_lengthdivsize = LengthDivSize(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "pair_plot" self.p_pair = PairPlotter(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "pair_mc_plot" self.p_mc_pair = PairPlotter(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "length" self.p_length = LengthPlotter(**p_kwargs, shape='wide') p_kwargs['figure_name'] = "width" self.p_width = WidthPlotter(**p_kwargs, shape='wide')
def plot_muon_event(event, muonparams, geom_dict=None, args=None): if muonparams[0] is not None: # Plot the muon event and overlay muon parameters fig = plt.figure(figsize=(16, 7)) # if args.display: # plt.show(block=False) #pp = PdfPages(args.output_path) if args.output_path is not None else None # pp = None #For now, need to correct this colorbar = None colorbar2 = None for tel_id in event.dl0.tels_with_data: npads = 2 # Only create two pads if there is timing information extracted # from the calibration ax1 = fig.add_subplot(1, npads, 1) plotter = CameraPlotter(event, geom_dict) #image = event.dl1.tel[tel_id].calibrated_image image = event.dl1.tel[tel_id].image[0] # Get geometry geom = None if geom_dict is not None and tel_id in geom_dict: geom = geom_dict[tel_id] else: #log.debug("[calib] Guessing camera geometry") geom = CameraGeometry.guess(*event.inst.pixel_pos[tel_id], event.inst.optical_foclen[tel_id]) #log.debug("[calib] Camera geometry found") if geom_dict is not None: geom_dict[tel_id] = geom tailcuts = (5., 7.) # Try a higher threshold for if geom.cam_id == 'FlashCam': tailcuts = (10., 12.) #print("Using Tail Cuts:",tailcuts) clean_mask = tailcuts_clean(geom, image, picture_thresh=tailcuts[0], boundary_thresh=tailcuts[1]) signals = image * clean_mask #print("Ring Centre in Nominal Coords:",muonparams[0].ring_center_x,muonparams[0].ring_center_y) muon_incl = np.sqrt(muonparams[0].ring_center_x**2. + muonparams[0].ring_center_y**2.) muon_phi = np.arctan(muonparams[0].ring_center_y / muonparams[0].ring_center_x) rotr_angle = geom.pix_rotation # if event.inst.optical_foclen[tel_id] > 10.*u.m and # event.dl0.tel[tel_id].num_pixels != 1764: if geom.cam_id == 'LSTCam' or geom.cam_id == 'NectarCam': #print("Resetting the rotation angle") rotr_angle = 0. * u.deg # Convert to camera frame (centre & radius) altaz = HorizonFrame(alt=event.mc.alt, az=event.mc.az) ring_nominal = NominalFrame(x=muonparams[0].ring_center_x, y=muonparams[0].ring_center_y, array_direction=altaz, pointing_direction=altaz) # embed() ring_camcoord = ring_nominal.transform_to(CameraFrame( pointing_direction=altaz, focal_length=event.inst.optical_foclen[tel_id], rotation=rotr_angle)) centroid_rad = np.sqrt(ring_camcoord.y**2 + ring_camcoord.x**2) centroid = (ring_camcoord.x.value, ring_camcoord.y.value) ringrad_camcoord = muonparams[0].ring_radius.to(u.rad) \ * event.inst.optical_foclen[tel_id] * 2. # But not FC? #rot_angle = 0.*u.deg # if event.inst.optical_foclen[tel_id] > 10.*u.m and event.dl0.tel[tel_id].num_pixels != 1764: #rot_angle = -100.14*u.deg px, py = event.inst.pixel_pos[tel_id] flen = event.inst.optical_foclen[tel_id] camera_coord = CameraFrame(x=px, y=py, z=np.zeros(px.shape) * u.m, focal_length=flen, rotation=geom.pix_rotation) nom_coord = camera_coord.transform_to( NominalFrame(array_direction=altaz, pointing_direction=altaz) ) #,focal_length = event.inst.optical_foclen[tel_id])) # tel['TelescopeTable_VersionFeb2016'][tel['TelescopeTable_VersionFeb2016']['TelID']==telid]['FL'][0]*u.m)) px = nom_coord.x.to(u.deg) py = nom_coord.y.to(u.deg) dist = np.sqrt(np.power( px - muonparams[0].ring_center_x, 2) + np.power(py - muonparams[0].ring_center_y, 2)) ring_dist = np.abs(dist - muonparams[0].ring_radius) pixRmask = ring_dist < muonparams[0].ring_radius * 0.4 if muonparams[1] is not None: signals *= muonparams[1].mask camera1 = plotter.draw_camera(tel_id, signals, ax1) cmaxmin = (max(signals) - min(signals)) if not cmaxmin: cmaxmin = 1. cmap_charge = colors.LinearSegmentedColormap.from_list( 'cmap_c', [(0 / cmaxmin, 'darkblue'), (np.abs(min(signals)) / cmaxmin, 'black'), (2.0 * np.abs(min(signals)) / cmaxmin, 'blue'), (2.5 * np.abs(min(signals)) / cmaxmin, 'green'), (1, 'yellow')] ) camera1.pixels.set_cmap(cmap_charge) if not colorbar: camera1.add_colorbar(ax=ax1, label=" [photo-electrons]") colorbar = camera1.colorbar else: camera1.colorbar = colorbar camera1.update(True) camera1.add_ellipse(centroid, ringrad_camcoord.value, ringrad_camcoord.value, 0., 0., color="red") # ax1.set_title("CT {} ({}) - Mean pixel charge" # .format(tel_id, geom_dict[tel_id].cam_id)) if muonparams[1] is not None: # continue #Comment this...(should ringwidthfrac also be *0.5?) ringwidthfrac = muonparams[ 1].ring_width / muonparams[0].ring_radius ringrad_inner = ringrad_camcoord * (1. - ringwidthfrac) ringrad_outer = ringrad_camcoord * (1. + ringwidthfrac) camera1.add_ellipse(centroid, ringrad_inner.value, ringrad_inner.value, 0., 0., color="magenta") camera1.add_ellipse(centroid, ringrad_outer.value, ringrad_outer.value, 0., 0., color="magenta") npads = 2 ax2 = fig.add_subplot(1, npads, npads) pred = muonparams[1].prediction if len(pred) != np.sum(muonparams[1].mask): print("Warning! Lengths do not match...len(pred)=", len(pred), "len(mask)=", np.sum(muonparams[1].mask)) # Numpy broadcasting - fill in the shape plotpred = np.zeros(image.shape) plotpred[muonparams[1].mask == True] = pred camera2 = plotter.draw_camera(tel_id, plotpred, ax2) c2maxmin = (max(plotpred) - min(plotpred)) if not c2maxmin: c2maxmin = 1. c2map_charge = colors.LinearSegmentedColormap.from_list( 'c2map_c', [(0 / c2maxmin, 'darkblue'), (np.abs(min(plotpred)) / c2maxmin, 'black'), (2.0 * np.abs(min(plotpred)) / c2maxmin, 'blue'), (2.5 * np.abs(min(plotpred)) / c2maxmin, 'green'), (1, 'yellow')] ) camera2.pixels.set_cmap(c2map_charge) if not colorbar2: camera2.add_colorbar(ax=ax2, label=" [photo-electrons]") colorbar2 = camera2.colorbar else: camera2.colorbar = colorbar2 camera2.update(True) plt.pause(1.) # make shorter # plt.pause(0.1) # if pp is not None: # pp.savefig(fig) fig.savefig(str(args.output_path) + "_" + str(event.dl0.event_id) + '.png') plt.close()
def test_guess_camera(): px = np.linspace(-10, 10, 11328) * u.m py = np.linspace(-10, 10, 11328) * u.m geom = CameraGeometry.guess(px, py, 0 * u.m) assert geom.pix_type.startswith('rect')
def start(self): # Get first event information first_event = self.reader.get_event(0) n_pixels = first_event.inst.num_pixels[0] n_samples = first_event.r0.tel[0].num_samples pos = first_event.inst.pixel_pos[0] foclen = first_event.inst.optical_foclen[0] geom = CameraGeometry.guess(*pos, foclen) # Setup Output output_dir = self.reader.output_directory title = self.reader.filename title = title[:title.find("_")] # Prepare Output if not exists(output_dir): self.log.info("Creating directory: {}".format(output_dir)) makedirs(output_dir) output_path = join(output_dir, title + "_events.pdf") # Setup plot fig = plt.figure(figsize=(10, 10)) ax_camera = fig.add_subplot(1, 1, 1) fig.patch.set_visible(False) ax_camera.axis('off') camera = CameraDisplay(geom, ax=ax_camera, image=np.zeros(2048), cmap='viridis') camera.add_colorbar() cb = camera.colorbar camera.colorbar.set_label("Amplitude (p.e.)") fig.suptitle(title) source = self.reader.read() desc = "Looping through file" with PdfPages(output_path) as pdf: for event in tqdm(source, desc=desc): ev = event.count event_id = event.r0.event_id self.r1.calibrate(event) self.dl0.reduce(event) self.dl1.calibrate(event) for t in event.r0.tels_with_data: dl1 = event.dl1.tel[t].image[0] # Cleaning tc = tailcuts_clean(geom, dl1, 20, 10) if not tc.any(): continue cleaned_dl1 = np.ma.masked_array(dl1, mask=~tc) try: # hillas = hillas_parameters(*pos, cleaned_tc) hillas = hillas_parameters_4(*pos, cleaned_dl1) except HillasParameterizationError: continue ax_camera.cla() camera = CameraDisplay(geom, ax=ax_camera, image=np.zeros(2048), cmap='viridis') camera.colorbar = cb camera.image = dl1 max_ = cleaned_dl1.max() # np.percentile(dl1, 99.9) min_ = np.percentile(dl1, 0.1) camera.set_limits_minmax(min_, max_) camera.highlight_pixels(tc, 'white') camera.overlay_moments(hillas, color='red') camera.update(True) ax_camera.set_title("Event: {}".format(event_id)) ax_camera.axis('off') pdf.savefig(fig) self.log.info("Created images: {}".format(output_path))
def draw_event(self, event, hillas_parameters=None): """ Draw display for a given event Parameters ---------- event: ctapipe event object hillas_parameters: dict Dictionary of Hillas parameters (in nominal system) Returns ------- None """ tel_list = event.r0.tels_with_data images = event.dl1 # First close any plots that already exist plt.close() ntels = len(tel_list) fig = plt.figure(figsize=(20, 20 * 0.66)) # If we want to draw the Hillas parameters in different planes we need to split our figure if self.draw_hillas_planes: y_axis_split = 2 else: y_axis_split = 1 outer_grid = gridspec.GridSpec(1, y_axis_split, width_ratios=[y_axis_split, 1]) # Create a square grid for camera images nn = int(ceil(sqrt(ntels))) nx = nn ny = nn while nx * ny >= ntels: ny -= 1 ny += 1 while nx * ny >= ntels: nx -= 1 nx += 1 camera_grid = gridspec.GridSpecFromSubplotSpec( ny, nx, subplot_spec=outer_grid[0]) # Loop over camera images of all telescopes and create plots for ii, tel_id in zip(range(ntels), tel_list): # Cache of camera geometries, this may go away soon if tel_id not in self.geom: self.geom[tel_id] = CameraGeometry.guess( event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], event.inst.optical_foclen[tel_id]) ax = plt.subplot(camera_grid[ii]) self.get_camera_view(tel_id, images.tel[tel_id].image[0], ax) # If we want to draw the Hillas parameters in different planes we need to make a couple more viewers if self.draw_hillas_planes: # Split the second sub figure into two further figures reco_grid = gridspec.GridSpecFromSubplotSpec( 2, 1, subplot_spec=outer_grid[1]) # Create plot of telescope positions at ground level array = ArrayPlotter( telescopes=tel_list, instrument=event.inst, # system=tilted_system, ax=plt.subplot(reco_grid[0])) # Draw MC position (this should change later) array.draw_position(event.mc.core_x, event.mc.core_y, use_centre=True) array.draw_array(((-300, 300), (-300, 300))) # If we have valid Hillas parameters we should draw them in the Nominal system if hillas_parameters is not None: array.overlay_hillas(hillas_parameters, draw_axes=True) nominal = NominalPlotter(hillas_parameters=hillas_parameters, draw_axes=True, ax=plt.subplot(reco_grid[1])) nominal.draw_array() plt.show() return
def test_array_draw(): filename = get_dataset("gamma_test.simtel.gz") cam_geom = {} source = hessio_event_source(filename, max_events=2) r1 = HessioR1Calibrator(None, None) dl0 = CameraDL0Reducer(None, None) calibrator = CameraDL1Calibrator(None, None) for event in source: array_pointing = SkyCoord( event.mcheader.run_array_direction[1] * u.rad, event.mcheader.run_array_direction[0] * u.rad, frame=AltAz) #array_view = ArrayPlotter(instrument=event.inst, # system=TiltedGroundFrame(pointing_direction=array_pointing)) hillas_dict = {} r1.calibrate(event) dl0.reduce(event) calibrator.calibrate(event) # calibrate the events # store MC pointing direction for the array for tel_id in event.dl0.tels_with_data: pmt_signal = event.dl1.tel[tel_id].image[0] x, y = event.inst.pixel_pos[tel_id] fl = event.inst.optical_foclen[tel_id] if tel_id not in cam_geom: cam_geom[tel_id] = CameraGeometry.guess( event.inst.pixel_pos[tel_id][0], event.inst.pixel_pos[tel_id][1], event.inst.optical_foclen[tel_id]) # Transform the pixels positions into nominal coordinates camera_coord = CameraFrame(x=x, y=y, z=np.zeros(x.shape) * u.m, focal_length=fl, rotation=90 * u.deg - cam_geom[tel_id].cam_rotation) nom_coord = camera_coord.transform_to( NominalFrame(array_direction=array_pointing, pointing_direction=array_pointing)) mask = tailcuts_clean(cam_geom[tel_id], pmt_signal, picture_thresh=10., boundary_thresh=5.) try: moments = hillas_parameters(nom_coord.x, nom_coord.y, pmt_signal * mask) hillas_dict[tel_id] = moments nom_coord = NominalPlotter(hillas_parameters=hillas_dict, draw_axes=True) nom_coord.draw_array() except HillasParameterizationError as e: print(e) continue
def start(self): disp = None for event in tqdm(self.source, desc='Tel{}'.format(self.tel), total=self.reader.max_events, disable=~self.progress): self.log.debug(event.trig) self.log.debug("Energy: {}".format(event.mc.energy)) self.calibrator.calibrate(event) if disp is None: x, y = event.inst.pixel_pos[self.tel] focal_len = event.inst.optical_foclen[self.tel] geom = CameraGeometry.guess(x, y, focal_len) self.log.info(geom) disp = CameraDisplay(geom) # disp.enable_pixel_picker() disp.add_colorbar() if self.display: plt.show(block=False) # display the event disp.axes.set_title('CT{:03d} ({}), event {:06d}'.format( self.tel, geom.cam_id, event.r0.event_id) ) if self.samples: # display time-varying event data = event.dl0.tel[self.tel].pe_samples[self.channel] for ii in range(data.shape[1]): disp.image = data[:, ii] disp.set_limits_percent(70) plt.suptitle("Sample {:03d}".format(ii)) if self.display: plt.pause(self.delay) if self.write: plt.savefig('CT{:03d}_EV{:10d}_S{:02d}.png' .format(self.tel, event.r0.event_id, ii)) else: # display integrated event: im = event.dl1.tel[self.tel].image[self.channel] if self.clean: mask = tailcuts_clean(geom, im, picture_thresh=10, boundary_thresh=7) im[~mask] = 0.0 disp.image = im if self.hillas: try: ellipses = disp.axes.findobj(Ellipse) if len(ellipses) > 0: ellipses[0].remove() params = hillas_parameters(pix_x=geom.pix_x, pix_y=geom.pix_y, image=im) disp.overlay_moments(params, color='pink', lw=3, with_label=False) except HillasParameterizationError: pass if self.display: plt.pause(self.delay) if self.write: plt.savefig('CT{:03d}_EV{:010d}.png' .format(self.tel, event.r0.event_id)) self.log.info("FINISHED READING DATA FILE") if disp is None: self.log.warning('No events for tel {} were found in {}. Try a ' 'different EventIO file or another telescope' .format(self.tel, self.infile), ) pass
filepath = get_path("/Users/Jason/Software/outputs/sim_telarray/meudon_gamma/" "simtel_runmeudon_gamma_30tel_30deg_19.gz") # filepath = get_path(sys.argv[1]) source = hessio_event_source(filepath, max_events=1) event = next(source) tel = list(event.dl0.tels_with_data)[0] pos_arr = np.array(event.inst.pixel_pos[tel]) n_pix = pos_arr.shape[1] pos_arr = pos_arr[:, checm_pixel_id] pos_arr[1] = -pos_arr[1] fig = plt.figure(figsize=(13, 13)) ax = fig.add_subplot(111) geom = CameraGeometry.guess(*event.inst.pixel_pos[tel], event.inst.optical_foclen[tel]) camera = CameraDisplay(geom, ax=ax, image=np.zeros(2048)) for pix in range(n_pix): pos_x = pos_arr[0, pix] pos_y = pos_arr[1, pix] ax.text(pos_x, pos_y, pix, fontsize=3, color='w', ha='center') # print("[{0:.5g}, {1:.5g}], # {2}".format(pos_x, pos_y, pix)) name = "checm_pixel_pos.npy" path = join(realpath(dirname(__file__)), "../targetpipe/io", name) np.save(path, pos_arr) plt.show()