def gen_features_norm(data_file, lower, upper, sim_file=None): """ This generates a certain set of features from photon-stream simulation or data files that can be used for further analyses. Inputs: data_file: location of input data file as string lower: lower limit for time slice cleaning upper: upper limit for time slice cleaning sim_file: location of input simulations file as string default: corresponding to name of data file return: pandas data frame with features """ # read in files if is_simulation_file(data_file): reader = ps.SimulationReader( photon_stream_path=data_file, mmcs_corsika_path=sim_file) else: reader = ps.EventListReader(data_file) # initialisation of list of dicts containing generated data events = list() border_pix = get_border_pixel_mask() x, y = get_pixel_coords() # loop for events for event in reader: lol = event.photon_stream.list_of_lists image = phs2image(lol, lower, upper) mask = facttools_cleaning(image, lol, lower, upper) # empty dict for values ev = {} # number of photons in biggest cluster ev['size'] = image[mask].sum() if ev['size'] > 0: border_ph = [(border_pix[i] and mask[i]) for i in range(1440)] ev['leakage'] = image[border_ph].sum()/ev['size'] ev.update(safe_observation_info(event)) ev.update(calc_hillas_features_image(image, mask)) # append values from dict to list of dicts (events) events.append(ev) # save list of dicts in pandas data frame df = pd.DataFrame(events) return df
def calc_hillas_features_image(image, mask): """ Safes hillas features from image to dict ev Inputs: ----------------------------------------- image: Number of photons per pixel (1440) mask: List of pixels that survived the cleaning Returns: ----------------------------------------- ev: dictionary with observation infos """ ev = {} x, y = get_pixel_coords() ev['n_pixel'] = mask.sum() # means of cluster ev['cog_x'] = np.average(x[mask], weights=image[mask]) ev['cog_y'] = np.average(y[mask], weights=image[mask]) # covariance and eigenvalues/vectors for later calculations cov = np.cov(x[mask], y[mask], fweights=image[mask]) eig_vals, eig_vecs = np.linalg.eigh(cov) # width, length and delta with warnings.catch_warnings(): warnings.simplefilter("ignore") ev['width'], ev['length'] = np.sqrt(eig_vals) delta = np.arctan(eig_vecs[1, 1] / eig_vecs[0, 1]) ev['delta'] = delta # rotate into main component system delta_x = x[mask] - ev['cog_x'] delta_y = y[mask] - ev['cog_y'] long = np.cos(delta) * delta_x + np.sin(delta) * delta_y trans = - np.sin(delta) * delta_x + np.cos(delta) * delta_y # higher order weights in cluster coordinates m3_long = np.average(long**3, weights=image[mask]) m3_trans = np.average(trans**3, weights=image[mask]) m4_long = np.average(long**4, weights=image[mask]) m4_trans = np.average(trans**4, weights=image[mask]) with warnings.catch_warnings(): warnings.simplefilter("ignore") ev['skewness_long'] = m3_long / ev['length']**3 ev['skewness_trans'] = m3_trans / ev['width']**3 ev['kurtosis_long'] = m4_long / ev['length']**4 ev['kurtosis_trans'] = m4_trans / ev['width']**4 return ev
def test_coords_relation_to_pos_from_dataframe(): from fact.instrument.camera import get_pixel_dataframe from fact.instrument.camera import get_pixel_coords import numpy as np pc = get_pixel_coords() pd = get_pixel_dataframe() assert np.allclose(pc[0], -pd.pos_Y.values * 9.5) assert np.allclose(pc[1], pd.pos_X.values * 9.5)
def calc_delta_delta(event, mask): x, y = get_pixel_coords() # if 'source_position_zd' not in df.columns: frame = AltAz(location=LOCATION, obstime=to_astropy_time(pd.to_datetime(event.observation_info.time))) crab_altaz = crab.transform_to(frame) source_position_zd_phs = crab_altaz.zen.deg source_position_az_phs = crab_altaz.az.deg source_x, source_y = horizontal_to_camera( source_position_zd_phs, source_position_az_phs, event.zd, event.az, ) # safe x, y and t components of Photons. shape = (#photons,3) xyt = event.photon_stream.point_cloud lol = event.photon_stream.list_of_lists x, y, t = xyt.T x = np.rad2deg(x) / camera_distance_mm_to_deg(1) y = np.rad2deg(y) / camera_distance_mm_to_deg(1) cleaned_pix = np.zeros(len(x), dtype=bool) for i in range(len(lol)): if mask[i]: for j in range(len(lol[i])): cleaned_pix[i] = True cog_x = np.mean(x[cleaned_pix]) cog_y = np.mean(y[cleaned_pix]) true_delta = np.arctan2(cog_y - source_y, cog_x - source_x) delta = calc_delta(phs2image(event.photon_stream.list_of_lists), mask) delta_delta = true_delta - delta if delta_delta < -np.pi/2: delta_delta += 2 * np.pi return delta_delta
def main(inputfile, output, threshold): df = pd.read_csv(inputfile) x, y = get_pixel_coords() df['x'] = x df['y'] = y df['r'] = np.sqrt(df.x**2 + df.y**2) psf = df.sigma.values psf[df.A.values < threshold] = np.nan sigma = np.ma.masked_invalid(df.sigma.values) cmap = plt.get_cmap('viridis') cmap.set_bad('lightgray') camera(sigma, cmap=cmap) df = df.query('A >= @threshold') plt.show() xplot = np.linspace(0, 190, 2) # only fit the main star going through the camera center df = df.loc[(df.y < 30) & (df.y > -30)].dropna() a, b = np.polyfit(df.r.values, df.sigma.values, deg=1) fig, ax = plt.subplots() ax.scatter('r', 'sigma', data=df) ax.plot(xplot, a * xplot + b, color='C1', label='Linear regression') ax.set_xlabel(r'$d \,\, / \,\, \mathrm{mm}$') ax.set_ylabel(r'$\sigma \,\, / \,\, \mathrm{mm}$') fig.tight_layout() if output: fig.savefig(output, dpi=300) else: plt.show()
mpl.rcParams['backend'] = 'pgf' mpl.rcParams['font.family'] = 'sans-serif' mpl.rcParams['text.usetex'] = True mpl.rcParams['text.latex.unicode'] = True mpl.rcParams['font.size'] = 9 mpl.rcParams['legend.fontsize'] = 'medium' mpl.rcParams['xtick.labelsize'] = 8 mpl.rcParams['ytick.labelsize'] = 8 mpl.rcParams['pgf.rcfonts'] = False mpl.rcParams['pgf.texsystem'] = 'lualatex' mpl.rcParams['pgf.preamble'] = '\input{/net/nfshome/home/ksedlaczek/phs_analysis/header-matplotlib.tex}' picture_thresh = 5 boundary_thresh = 2 x, y = get_pixel_coords() crab = SkyCoord.from_name('Crab Nebula') @click.command() @click.argument('method', required=True) @click.argument('path', required=True) @click.argument('file', required=True) @click.argument('feat', required=True) @click.option('-n', '--number', default=130, type=int, help='Number of events to plot') def main(method, path, file, feat, number): border_pix = get_border_pixel_mask() print("Reading in facttools dl1 file...") t = Table.read('/net/big-tank/POOL/projects/fact/photon-stream/facttools/crab/{}_dl1.fits'.format(file))
import photon_stream as ps import numpy as np import scipy import pandas as pd import warnings from fact.instrument import camera_distance_mm_to_deg from fact.instrument.camera import get_border_pixel_mask, get_pixel_coords az_offset_between_magnetic_and_geographic_north = -0.12217305 pix_x, pix_y = get_pixel_coords() def phs2image(lol, lower=0, upper=7000): """ Delete time slices at beginning and end of the event and return an image for Photon Stream events. Inputs: lol: Photon Stream list of photon arrival times per pixel Optional: lower: lower limit of range of time slices to return upper: upper limit of range of time slices to return return: image: Array with number of photons within time-slice intervall [lower, upper] in every of the 1440 pixels """ image = np.array([ np.sum((lower <= np.array(l)) & (np.array(l) < upper)) for l in lol