Example #1
0
def calculate_chi_square(event_info, zenith, azimuth, energy):
    target_direction = hp.spherical_to_cartesian(zenith, azimuth)
    event_direction = hp.spherical_to_cartesian(float(event_info[2]),
                                                float(event_info[3]))
    direction_error = hp.get_angle(target_direction, event_direction)
    energy_error = np.log10(energy) - np.log10(float(event_info[1]))
    return (direction_error / sigma_angle)**2 + (energy_error /
                                                 sigma_log_energy)**2
Example #2
0
def load_file_with_labels(i_file, n_events, start_index=0, norm=1e-6):
    # Load 500 MHz filter
    filt = np.load("bandpass_filters/500MHz_filter.npy")

    t0 = time.time()
    print(f"loading file {i_file}", flush=True)
    data = np.load(os.path.join(datapath, f"{data_filename}{i_file:04d}.npy"),
                   allow_pickle=True,
                   mmap_mode="r")

    data = data[start_index:(n_events + start_index), :, :]
    data = np.fft.irfft(np.fft.rfft(data, axis=-1) * filt, axis=-1)
    data = data[:, :, :, np.newaxis]

    labels_tmp = np.load(os.path.join(datapath,
                                      f"{label_filename}{i_file:04d}.npy"),
                         allow_pickle=True)
    print(f"finished loading file {i_file} in {time.time() - t0}s")
    nu_zenith = np.array(labels_tmp.item()["nu_zenith"])
    nu_azimuth = np.array(labels_tmp.item()["nu_azimuth"])
    nu_direction = hp.spherical_to_cartesian(nu_zenith, nu_azimuth)

    nu_direction = nu_direction[start_index:(n_events + start_index), :]

    # check for nans and remove them
    idx = ~(np.isnan(data))
    idx = np.all(idx, axis=1)
    idx = np.all(idx, axis=1)
    idx = np.all(idx, axis=1)
    data = data[idx, :, :, :]
    nu_direction = nu_direction[idx]
    data /= norm

    return data, nu_direction
Example #3
0
def MakeAntennaGeo(antFile, iAnt):

    x = antFile['CenterX'][iAnt]
    y = antFile['CenterY'][iAnt]
    z = antFile['CenterZ'][iAnt]
    OrientationTheta = np.deg2rad(antFile['OrientationTheta'][iAnt])
    OrientationPhi = np.deg2rad(antFile['OrientationPhi'][iAnt])
    RotationTheta = np.deg2rad(antFile['RotationTheta'][iAnt])
    RotationPhi = np.deg2rad(antFile['RotationPhi'][iAnt])
    AntennaType = antFile['AntennaType'][iAnt]
    AntennaModel = antFile['AntennaModel'][iAnt]
    AmplifierFilterModel = antFile['AmplifierFilterModel'][iAnt]

    iceantennaGeo = dataclasses.I3IceAntennaGeo()
    iceantennaGeo.position = dataclasses.I3Position(x, y, z)

    sph_orientation = np.array([OrientationTheta, OrientationPhi])
    sph_rotation = np.array([RotationTheta, RotationPhi])
    car_orientation = hp.spherical_to_cartesian(*sph_orientation)
    car_rotation = hp.spherical_to_cartesian(*sph_rotation)

    iceantennaGeo.orientation = dataclasses.I3Direction(
        car_orientation[0], car_orientation[1], car_orientation[2])
    iceantennaGeo.rotation = dataclasses.I3Direction(car_rotation[0],
                                                     car_rotation[1],
                                                     car_rotation[2])

    if AntennaType == 'dipole':
        iceantennaGeo.antennaType = dataclasses.I3IceAntennaGeo.IceAntennaType.dipole
    elif AntennaType == 'lpda':
        iceantennaGeo.antennaType = dataclasses.I3IceAntennaGeo.IceAntennaType.lpda

    iceantennaGeo.antennaModel = AntennaModel
    iceantennaGeo.amplifierFilterModel = AmplifierFilterModel

    return iceantennaGeo
 def get_expected_times(params, channel_positions):
     zenith, azimuth = params
     if cosmic_ray:
         if ((zenith < 0) or (zenith > 0.5 * np.pi)):
             return np.ones(len(channel_positions)) * np.inf
     else:
         if ((zenith < 0.5 * np.pi) or (zenith > np.pi)):
             return np.ones(len(channel_positions)) * np.inf
     v = hp.spherical_to_cartesian(zenith, azimuth)
     c = constants.c * units.m / units.s
     if not cosmic_ray:
         c = c / n_ice
         logger.debug("using speed of light = {:.4g}".format(c))
     t_expected = -(np.dot(v, channel_positions.T) / c)
     return t_expected
Example #5
0
def get_angles(corsika):
    """
    Converting angles in corsika coordinates to local coordinates
    """
    zenith = np.deg2rad(corsika['inputs'].attrs["THETAP"][0])
    azimuth = hp.get_normalized_angle(3 * np.pi / 2. + np.deg2rad(corsika['inputs'].attrs["PHIP"][0]))

    Bx, Bz = corsika['inputs'].attrs["MAGNET"]
    B_inclination = np.arctan2(Bz, Bx)

    B_strength = (Bx ** 2 + Bz ** 2) ** 0.5 * units.micro * units.tesla

    # in local coordinates north is + 90 deg
    magnetic_field_vector = B_strength * hp.spherical_to_cartesian(np.pi * 0.5 + B_inclination, 0 + np.pi * 0.5)

    return zenith, azimuth, magnetic_field_vector
 def obj_plane(params, positions, t_measured):
     zenith, azimuth = params
     if cosmic_ray:
         if ((zenith < 0) or (zenith > 0.5 * np.pi)):
             return np.inf
     else:
         if ((zenith < 0.5 * np.pi) or (zenith > np.pi)):
             return np.inf
     v = hp.spherical_to_cartesian(zenith, azimuth)
     c = constants.c * units.m / units.s
     if not cosmic_ray:
         c = c / n_ice
         logger.debug("using speed of light = {:.4g}".format(c))
     t_expected = -(np.dot(v, positions.T) / c)
     sigma = 1 * units.ns
     chi2 = np.sum(((t_expected - t_expected.mean()) -
                    (t_measured - t_measured.mean()))**2 / sigma**2)
     logger.debug("texp = {texp}, tm = {tmeas}, {chi2}".format(
         texp=t_expected, tmeas=t_measured, chi2=chi2))
     return chi2
    def run(self, evt, station, det, channels_to_use=None, cosmic_ray=False):
        """
        Fits the direction using templates

        Parameters
        ----------
        evt: event

        station: station

        det: detector

        channels_to_use: list (default: [0, 1, 2, 3]
            antenna to use for fit
        cosmic_ray: bool
            type to set correlation template

        """
        if channels_to_use is None:
            channels_to_use = [0, 1, 2, 3]
        if (cosmic_ray):
            type_str = 'cr'
            xcorrelations = chp.cr_xcorrelations
        else:
            type_str = 'nu'
            xcorrelations = chp.nu_xcorrelations

        station_id = station.get_id()
        channels = station.iter_channels(channels_to_use)

        times = []
        positions = []

        for iCh, channel in enumerate(channels):
            channel_id = channel.get_id()
            times.append(
                channel[xcorrelations]['{}_ref_xcorr_time'.format(type_str)] +
                channel.get_trace_start_time())
            positions.append(det.get_relative_position(station_id, channel_id))

        times = np.array(times)
        positions = np.array(positions)
        site = det.get_site(station_id)
        n_ice = ice.get_refractive_index(-0.01, site)

        from scipy import optimize as opt

        def obj_plane(params, positions, t_measured):
            zenith, azimuth = params
            if cosmic_ray:
                if ((zenith < 0) or (zenith > 0.5 * np.pi)):
                    return np.inf
            else:
                if ((zenith < 0.5 * np.pi) or (zenith > np.pi)):
                    return np.inf
            v = hp.spherical_to_cartesian(zenith, azimuth)
            c = constants.c * units.m / units.s
            if not cosmic_ray:
                c = c / n_ice
                logger.debug("using speed of light = {:.4g}".format(c))
            t_expected = -(np.dot(v, positions.T) / c)
            sigma = 1 * units.ns
            chi2 = np.sum(((t_expected - t_expected.mean()) -
                           (t_measured - t_measured.mean()))**2 / sigma**2)
            logger.debug("texp = {texp}, tm = {tmeas}, {chi2}".format(
                texp=t_expected, tmeas=t_measured, chi2=chi2))
            return chi2

        method = "Nelder-Mead"
        options = {'maxiter': 1000, 'disp': False}
        zenith_start = 135 * units.deg
        if cosmic_ray:
            zenith_start = 45 * units.deg
        starting_chi2 = {}
        for starting_az in np.array([0, 90, 180, 270]) * units.degree:
            starting_chi2[starting_az] = obj_plane((zenith_start, starting_az),
                                                   positions, times)
        azimuth_start = min(starting_chi2, key=starting_chi2.get)
        res = opt.minimize(obj_plane,
                           x0=[zenith_start, azimuth_start],
                           args=(positions, times),
                           method=method,
                           options=options)

        output_str = "reconstucted angles theta = {:.1f}, phi = {:.1f}".format(
            res.x[0] / units.deg,
            hp.get_normalized_angle(res.x[1]) / units.deg)
        if station.has_sim_station():
            sim_zen = station.get_sim_station()[stnp.zenith]
            sim_az = station.get_sim_station()[stnp.azimuth]
            dOmega = hp.get_angle(
                hp.spherical_to_cartesian(sim_zen, sim_az),
                hp.spherical_to_cartesian(res.x[0], res.x[1]))
            output_str += "  MC theta = {:.1f}, phi = {:.1f},  dOmega = {:.2f}".format(
                sim_zen / units.deg, sim_az / units.deg, dOmega / units.deg)
        logger.info(output_str)
        station[stnp.zenith] = res.x[0]
        station[stnp.azimuth] = hp.get_normalized_angle(res.x[1])
        if (cosmic_ray):
            station[stnp.cr_zenith] = res.x[0]
            station[stnp.cr_azimuth] = hp.get_normalized_angle(res.x[1])
        else:
            station[stnp.nu_zenith] = res.x[0]
            station[stnp.nu_azimuth] = hp.get_normalized_angle(res.x[1])
Example #8
0
    data = defaultdict(list)

    zeniths = np.deg2rad(np.arange(55, 80, 1))
    depths = [400]
    core = np.array([0, 0, 1400])

    positions = np.array([
        np.linspace(-1000, 1000, 20),
        np.zeros(20), np.zeros(20)
    ]).T + core
    print(positions)
    print(positions.shape)

    for zenith in zeniths:
        print('zenith', np.rad2deg(zenith))
        shower_axis = helper.spherical_to_cartesian(zenith, 0)

        for depth in depths:
            dist = at.get_distance_xmax_geometric(zenith,
                                                  depth,
                                                  observation_level=core[-1])
            if dist < 0:
                continue

            # sea level
            point_on_axis = shower_axis * dist + core
            point_on_axis_height = atm.get_height_above_ground(
                dist, zenith, observation_level=core[-1]) + core[-1]
            print("Height of point in inital sys:", point_on_axis_height)

            for pos in positions:
Example #9
0
def update_signal_direction_plot(zenith, azimuth, antenna_type):
    zenith = zenith * units.deg
    azimuth = azimuth * units.deg
    signal_direction = hp.spherical_to_cartesian(zenith, azimuth)
    data = []
    data.append(go.Scatter3d(
        x=[0, signal_direction[0]],
        y=[0, signal_direction[1]],
        z=[0, signal_direction[2]],
        mode='lines',
        name='Signal Direction'
    ))
    data.append(go.Scatter3d(
        x=[0, 0],
        y=[0, 0],
        z=[0, 1],
        mode='lines',
        name='Antenna Orientation'
    ))
    rot = hp.spherical_to_cartesian(90.*units.deg, 180*units.deg)
    data.append(go.Scatter3d(
        x=[0, rot[0]],
        y=[0, rot[1]],
        z=[0, rot[2]],
        mode='lines',
        name='Antenna Rotation'
    ))
    if antenna_type == 'createLPDA_100MHz_InfFirn':
        data.append(go.Mesh3d(
            x=[0, 0, 0],
            y=[-.25, 0, .25],
            z=[0, .75, 0],
            delaunayaxis='x',
            opacity=.5,
            color='black'
            ))
    else:
        d_angle = 30
        angles = np.arange(0, 360, d_angle) * units.deg
        r = .05
        cylinder_points = []
        i = []
        j = []
        k = []
        for i_angle, angle in enumerate(angles):
            cylinder_points.append([r * np.cos(angle), r * np.sin(angle), -.5])
            cylinder_points.append([r * np.cos(angle), r * np.sin(angle), .5])
            cylinder_points.append([r * np.cos(angle + d_angle * units.deg), r * np.sin(angle + d_angle * units.deg), -.5])
            cylinder_points.append([r * np.cos(angle), r * np.sin(angle), .5])
            cylinder_points.append([r * np.cos(angle + d_angle * units.deg), r * np.sin(angle + d_angle * units.deg), -.5])
            cylinder_points.append([r * np.cos(angle + d_angle * units.deg), r * np.sin(angle + d_angle * units.deg), .5])
            i.append(6 * i_angle)
            j.append(6 * i_angle + 1)
            k.append(6 * i_angle + 2)
            i.append(6 * i_angle + 3)
            j.append(6 * i_angle + 4)
            k.append(6 * i_angle + 5)
        cylinder_points = np.array(cylinder_points)
        data.append(go.Mesh3d(
            x=cylinder_points[:, 0],
            y=cylinder_points[:, 1],
            z=cylinder_points[:, 2],
            i=i,
            j=j,
            k=k,
            color='black',
            opacity=.5
        ))

    fig = go.Figure(
        data=data
    )
    fig.update_layout(
        scene=dict(
        xaxis=dict(range=[-1, 1]),
        yaxis=dict(range=[-1, 1]),
        zaxis=dict(range=[-1, 1]),
        aspectmode='manual',
        aspectratio=dict(x=1, y=1, z=1)
        ),
        showlegend=True,
        legend=dict(x=-.1, y=1.1),
        margin=dict(
            l=10,
            r=10,
            t=10,
            b=10
        )
    )
    return fig
Example #10
0
    str(np.average(zeniths, weights=weights)) + "\nstd: " + str(varZen**0.5))
plt.subplot(2, 1, 2)
plt.hist(zeniths, bins=np.arange(0, 181, 5))
plt.xlabel('zenith angle [deg]')
plt.ylabel('unweighted entries')
plt.figtext(
    1.0, 0.2, "N: " + str(len(zeniths)) + "\nmean: " +
    str(np.average(zeniths)) + "\nstd: " + str(np.std(zeniths)))
plt.suptitle("neutrino direction")
plt.savefig(os.path.join(plot_folder, 'neutrino_direction.pdf'),
            bbox_inches="tight")
plt.clf()

#plot difference between cherenkov angle and viewing angle
# i.e., opposite to the direction of propagation. We need the propagation direction here, so we multiply the shower axis with '-1'
shower_axis = -1.0 * hp.spherical_to_cartesian(theta, phi)
viewing_angles_d = np.array(
    [hp.get_angle(x, y) for x, y in zip(shower_axis, launch_vectors[:, 0, 0])])
viewing_angles_r = np.array(
    [hp.get_angle(x, y) for x, y in zip(shower_axis, launch_vectors[:, 0, 1])])
# calculate correct chereknov angle for ice density at vertex position
ice = medium.southpole_simple()
n_indexs = np.array(
    [ice.get_index_of_refraction(x) for x in np.array([xx, yy, zz]).T])
rho = np.arccos(1. / n_indexs)
weightsExt = weights
for chan in range(1, len(launch_vectors[0])):
    viewing_angles_d = np.append(
        viewing_angles_d,
        np.array([
            hp.get_angle(x, y)
def generate_eventlist_cylinder(filename, n_events, Emin, Emax,
                                full_rmin=None, full_rmax=None, full_zmin=None, full_zmax=None,
                                thetamin=0.*units.rad, thetamax=np.pi * units.rad,
                                phimin=0.*units.rad, phimax=2 * np.pi * units.rad,
                                start_event_id=1,
                                flavor=[12, -12, 14, -14, 16, -16],
                                n_events_per_file=None,
                                spectrum='log_uniform',
                                start_file_id=0):
    """
    Event generator

    Generates neutrino interactions, i.e., vertex positions, neutrino directions,
    neutrino flavor, charged currend/neutral current and inelastiviy distributions.
    All events are saved in an hdf5 file.

    Parameters
    ----------
    filename: string
        the output filename of the hdf5 file
    n_events: int
        number of events to generate
    Emin: float
        the minimum neutrino energy (energies are randomly chosen assuming a
        uniform distribution in the logarithm of the energy)
    Emax: float
        the maximum neutrino energy (energies are randomly chosen assuming a
        uniform distribution in the logarithm of the energy)

    full_rmin: float (default None)
        lower r coordinate of simulated volume (if None it is set to 1/3 of the fiducial volume, if second vertices are not activated it is set to the fiducial volume)
    full_rmax: float (default None)
        upper r coordinate of simulated volume (if None it is set to 5x the fiducial volume, if second vertices are not activated it is set to the fiducial volume)
    full_zmin: float (default None)
        lower z coordinate of simulated volume (if None it is set to 1/3 of the fiducial volume, if second vertices are not activated it is set to the fiducial volume)
    full_zmax: float (default None)
        upper z coordinate of simulated volume (if None it is set to 5x the fiducial volume, if second vertices are not activated it is set to the fiducial volume)
    thetamin: float
        lower zenith angle for neutrino arrival direction
    thetamax: float
        upper zenith angle for neutrino arrival direction
    phimin: float
        lower azimuth angle for neutrino arrival direction
    phimax: float
         upper azimuth angle for neutrino arrival direction
    start_event: int
        default: 1
        event number of first event
    flavor: array of ints
        default: [12, -12, 14, -14, 16, -16]
        specify which neutrino flavors to generate. A uniform distribution of
        all specified flavors is assumed.
        The neutrino flavor (integer) encoded as using PDF numbering scheme,
        particles have positive sign, anti-particles have negative sign,
        relevant for us are:
        * 12: electron neutrino
        * 14: muon neutrino
        * 16: tau neutrino
    n_events_per_file: int or None
        the maximum number of events per output files. Default is None, which
        means that all events are saved in one file. If 'n_events_per_file' is
        smaller than 'n_events' the event list is split up into multiple files.
        This is useful to split up the computing on multiple cores.
    spectrum: string
        defines the probability distribution for which the neutrino energies are generated
        * 'log_uniform': uniformly distributed in the logarithm of energy
    start_file_id: int (default 0)
        in case the data set is distributed over several files, this number specifies the id of the first file
        (useful if an existing data set is extended)
        if True, generate deposited energies instead of primary neutrino energies
    """

    attributes = {}
    n_events = int(n_events)

    # save current NuRadioMC version as attribute
    # save NuRadioMC and NuRadioReco versions
    attributes['NuRadioMC_EvtGen_version'] = NuRadioMC.__version__
    attributes['NuRadioMC_EvtGen_version_hash'] = version.get_NuRadioMC_commit_hash()

    attributes['start_event_id'] = start_event_id

    attributes['fiducial_rmin'] = full_rmin
    attributes['fiducial_rmax'] = full_rmax
    attributes['fiducial_zmin'] = full_zmin
    attributes['fiducial_zmax'] = full_zmax
    attributes['rmin'] = full_rmin
    attributes['rmax'] = full_rmax
    attributes['zmin'] = full_zmin
    attributes['zmax'] = full_zmax
    attributes['flavors'] = flavor
    attributes['Emin'] = Emin
    attributes['Emax'] = Emax
    attributes['thetamin'] = thetamin
    attributes['thetamax'] = thetamax
    attributes['phimin'] = phimin
    attributes['phimax'] = phimax

    # define cylinder by two points and the radius
    h_cylinder = full_zmax - full_zmin
    r_cylinder = full_rmax
    pt1 = np.array([0, 0, R_earth + full_zmax])
    pt2 = np.array([0, 0, R_earth + full_zmin])

    data_sets = {}

    # calculate maximum width of projected area
    theta_max = np.arctan(h_cylinder / 2 / r_cylinder)
    d = 2 * r_cylinder * np.cos(theta_max) + h_cylinder * np.sin(theta_max)  # width of area

    print(f"cylinder r = {r_cylinder/units.km:.1f}km, h = {h_cylinder/units.km:.1f}km -> dmax = {d/units.km:.1f}km")

    def perp(a) :
        b = np.empty_like(a)
        b[0] = -a[1]
        b[1] = a[0]
        return b

    # line segment a given by endpoints a1, a2
    # line segment b given by endpoints b1, b2
    # return
    def seg_intersect(a1, a2, b1, b2) :
        da = a2 - a1
        db = b2 - b1
        dp = a1 - b1
        dap = perp(da)
        denom = np.dot(dap, db)
        num = np.dot(dap, dp)
        return (num / denom) * db + b1

    def get_R(t, v, X):
        """"
        calculate distance to center of Earth as a function of travel distance
        
        Parameters
        -----------
        t: 3dim array
            travel distance
        v: 3dim array
            direction
        X: 3dim array
            start point
        """
        return np.linalg.norm(v * t + X)

    def get_density(t, v, X):
        """
        calculates density as a function of travel distance
        
        Parameters
        -----------
        t: 3dim array
            travel distance
        v: 3dim array
            direction
        X: 3dim array
            start point
        """
        return  earth.density(get_R(t, v, X))

    def slant_depth(t, v, X):
        """
        calculates slant depth (grammage) as a function of travel distance
        
        Parameters
        -----------
        t: 3dim array
            travel distance
        v: 3dim array
            direction
        X: 3dim array
            start point
        """
        res = quad(get_density, 0, t, args=(v, X), limit=200)
        return res[0]

    def slant_depth_num(t, v, X, step=50 * units.m):
        """
        calculates slant depth (grammage) as a function of travel distance
        
        Parameters
        -----------
        t: 3dim array
            travel distance
        v: 3dim array
            direction
        X: 3dim array
            start point
        """
        tt = np.linspace(0, t, t / step)
        rr = np.linalg.norm(X + np.outer(tt, v), axis=1)
        res = np.trapz(earth.density(rr), tt)
        return res

    def obj_dist_to_surface(t, v, X):
        return get_R(t, v, X) - R_earth

    def obj(t, v, X, Lint):
        """
        objective function to determine at which travel distance we reached the interaction point
        """
        return slant_depth(t, v, X) - Lint

    def points_in_cylinder(pt1, pt2, r, q):
        """
        determines if point lies within a cylinder
        
        Parameters
        -----------
        pt1: 3dim array
            lowest point on cylinder axis
        pt2: 3dim array
            highest point on cylinder axis
        r: float
            radius of cylinder
        q: 3dim array
            point under test
        
        Returns True/False
        """
        vec = pt2 - pt1
        const = r * np.linalg.norm(vec)
        return len(np.where(np.dot(q - pt1, vec) >= 0 and np.dot(q - pt2, vec) <= 0 and np.linalg.norm(np.cross(q - pt1, vec)) <= const)[0]) > 0

    # precalculate the maximum slant depth to the detector
    if(not os.path.exists("buffer_Llimit.pkl")):
        zens = np.arange(0, 180.1 * units.deg, 2 * units.deg)
        Lint_max = np.zeros_like(zens)
        Lint_min = np.zeros_like(zens)
        Xs = np.array([[0, -0.5 * r_cylinder, -h_cylinder + R_earth],
                       [0, -0.5 * r_cylinder, R_earth],
                       [0, 0.5 * r_cylinder, -h_cylinder + R_earth],
                       [0, 0.5 * r_cylinder, R_earth]]
                       )
        v_tmps = -hp.spherical_to_cartesian(zens, np.zeros_like(zens))  # neutrino direction
        for i in range(len(v_tmps)):
            v = v_tmps[i]
            sdepth_tmp = np.zeros(4)
            for j, X in enumerate(Xs):
                if((X[2] == R_earth) and (zens[i] <= 90 * units.deg)):
                    t = 0
                    sdepth_tmp[j] = 0
                else:
                    t = brentq(obj_dist_to_surface, 100, 2 * R_earth, args=(-v, X))
                    sdepth_tmp[j] = slant_depth_num(t, -v, X)
        #         print(i, zens[i] / units.deg, X, sdepth_tmp[j])
        #     enter_point = X + (-v * t)
            Lint_max[i] = np.max(sdepth_tmp)
            Lint_min[i] = np.min(sdepth_tmp)
        pickle.dump([zens, Lint_max, Lint_min], open("buffer_Llimit.pkl", "wb"), protocol=4)
    else:
        zens, Lint_max, Lint_min = pickle.load(open("buffer_Llimit.pkl", "rb"))

    get_Lmax = interp1d(zens, Lint_max, kind='next')
    get_Lmin = interp1d(zens, Lint_min, kind='previous')

    if 0:
        fig, a = plt.subplots(1, 1)
        ztmp = np.linspace(0, 180 * units.deg, 10000)
        a.plot(ztmp / units.deg, get_Lmax(ztmp) / units.g * units.cm ** 2, 'C0-', label="max possible Lint")
    #     a.plot(zens / units.deg, Lint_max / units.g * units.cm ** 2, 'oC0')
        a.plot(ztmp / units.deg, get_Lmin(ztmp) / units.g * units.cm ** 2, 'C1-', label="min possible Lint")
    #     a.plot(zens / units.deg, Lint_min / units.g * units.cm ** 2, 'dC1')
        a.hlines(cs.get_interaction_length(.1 * units.EeV, 1, 12, "total") / units.g * units.cm ** 2, 0, 180, label="0.1 EeV", colors='C2')
        a.hlines(cs.get_interaction_length(1 * units.EeV, 1, 12, "total") / units.g * units.cm ** 2, 0, 180 , label="1 EeV", colors='C3')
        a.hlines(cs.get_interaction_length(10 * units.EeV, 1, 12, "total") / units.g * units.cm ** 2, 0, 180 , label="10 EeV", colors='C4')
        a.set_xlabel("zenith angle [deg]")
        a.set_ylabel("slant depth [g/cm^2]")
        a.semilogy(True)
        a.set_xticks(np.arange(0, 181, 10))
        a.set_ylim(5e5)
        a.legend()

        fig.tight_layout()
        fig.savefig("Lvszen.png")
        plt.show()

    failed = 0
    if(spectrum == 'log_uniform'):
        Enu = 10 ** np.random.uniform(np.log10(Emin), np.log10(Emax), n_events)
    flavors = np.array([flavor[i] for i in np.random.randint(0, high=len(flavor), size=n_events)])
    az = np.random.uniform(phimin, phimax, n_events)
    zen = np.arccos(np.random.uniform(np.cos(thetamax), np.cos(thetamin), n_events))
    # generate random positions on an area perpendicular do neutrino direction
    ax, ay = np.random.uniform(-0.5 * d, 0.5 * d, (2, n_events))
    # az = np.ones(n_events) * (R_earth - .5 * h_cylinder)  # move plane to the center of the cylinder

    # calculate grammage (g/cm^2) after which neutrino interacted
    Lint = np.random.exponential(cs.get_interaction_length(Enu, 1, flavors, "total"), n_events)

    mask = (Lint < get_Lmax(zen)) & (Lint > get_Lmin(zen))
    print(f"{np.sum(mask)}/{n_events} = {np.sum(mask)/n_events:.2g} can potentially interact in simulation volume")

    # calculate position where neutrino interacts
    data_sets = {'xx': [],
                'yy': [],
                'zz': [],
                'azimuths': [],
                'zeniths': [],
                'flavors': [],
                'energies': []}
    # calculate rotation matrix to transform position on area to 3D
    mask_int = np.zeros_like(mask, dtype=np.bool)
    t0 = time.perf_counter()
    n_cylinder = 0
    for j, i in enumerate(np.arange(n_events, dtype=np.int)[mask]):
        if(j % 1000 == 0 and i > 0):
            eta = (time.perf_counter() - t0) * (n_events - i) / i
            logger.info(f"{i}/{n_events} interacting = {np.sum(mask_int)}, failed = {failed}, n_cylinder = {n_cylinder}, eta = {pretty_time_delta(eta)}")
    #     print(f"calculating interaction point of event {i}"),
        c, s = np.cos(az[i]), np.sin(az[i])
        Raz = np.array(((c, -s, 0), (s, c, 0), (0, 0, 1)))
        c, s = np.cos(zen[i]), np.sin(zen[i])
    #     Rzen = np.array(((c, 1, -s), (0, 1, 0), (s, 0, c)))
        Rzen = hp.get_rotation(hp.spherical_to_cartesian(0, az[i]), hp.spherical_to_cartesian(zen[i], az[i]))
    #     R = hp.get_rotation(np.array([0, 0, 1]), hp.spherical_to_cartesian(zen[i], az[i]))
        R = np.matmul(Rzen, Raz)
        v = -hp.spherical_to_cartesian(zen[i], az[i])  # neutrino direction
        X = np.matmul(R, np.array([ax[i], ay[i], 0])) + np.array([0, 0, -0.5 * h_cylinder])
        if 0:
            import matplotlib.pyplot as plt
            from mpl_toolkits.mplot3d import Axes3D
            from mpl_toolkits.mplot3d.art3d import Poly3DCollection
            fig = plt.figure()
            a = fig.add_subplot(111, projection='3d')
            # Cylinder
            x = np.linspace(-r_cylinder, r_cylinder, 100)
            z = np.linspace(0, -h_cylinder, 100)
            Xc, Zc = np.meshgrid(x, z)
            Yc = np.sqrt(r_cylinder ** 2 - Xc ** 2)

            # Draw parameters
            rstride = 20
            cstride = 10
            a.plot_surface(Xc, Yc, Zc, alpha=0.2, rstride=rstride, cstride=cstride)
            a.plot_surface(Xc, -Yc, Zc, alpha=0.2, rstride=rstride, cstride=cstride)
            a.set_title(f"zenith = {zen[i]/units.deg:.0f}")
            xx = []
            yy = []
            zz = []
            for vert in np.array([[-0.5 * d, -0.5 * d, 0], [0.5 * d, -0.5 * d, 0], [0.5 * d, 0.5 * d, 0], [-0.5 * d, 0.5 * d, 0]]):
                t = np.matmul(Raz, vert) + np.array([0, 0, -0.5 * h_cylinder])
                xx.append(t[0])
                yy.append(t[1])
                zz.append(t[2])
            verts = [list(zip(xx, yy, zz))]
            a.add_collection3d(Poly3DCollection(verts, alpha=0.5))

            xx = []
            yy = []
            zz = []
            for vert in np.array([[-0.5 * d, -0.5 * d, 0], [0.5 * d, -0.5 * d, 0], [0.5 * d, 0.5 * d, 0], [-0.5 * d, 0.5 * d, 0]]):
                t = np.matmul(Rzen, np.matmul(Raz, vert)) + np.array([0, 0, -0.5 * h_cylinder])
                xx.append(t[0])
                yy.append(t[1])
                zz.append(t[2])
            verts = [list(zip(xx, yy, zz))]
            a.add_collection3d(Poly3DCollection(verts, alpha=0.5))

            s = np.array([0, 0, -0.5 * h_cylinder])
            t = v * 10 * units.km + s
            a.plot([s[0], t[0]], [s[1], t[1]], [s[2], t[2]], '-d')

            s = np.array([0, 0, -0.5 * h_cylinder])
            t = -hp.spherical_to_cartesian(90 * units.deg, az[i]) * 10 * units.km + s
            a.plot([s[0], t[0]], [s[1], t[1]], [s[2], t[2]], '--d')

            # check if neutrino axis is perpendicular
            t = np.array(verts[0][0]) - np.array(verts[0][1])
            t /= np.linalg.norm(t)
            print(np.dot(t, v))

            a.set_xlabel("x")
            a.set_zlabel("z")
            a.set_ylabel("y")
            plt.show()

        # check if trajectory passes through cylinder
    #     if(not points_in_cylinder(pt1, pt2, r_cylinder, X)):
        # we rotate everything in the plane defined by z and the propagration direction (such that v_y = 0)
        Xaz = np.matmul(Raz.T, X)
        rmin = Xaz[1]  # the closest distance to the z axis (center of cyllinder)
        if(abs(rmin) >= r_cylinder):
            continue
        # define the projected square of the cylinder
        # the two endpoints of the two horizontal lines are
        xtmp = (r_cylinder ** 2 - rmin ** 2) ** 0.5
        Lh1 = np.array([[-xtmp, 0], [xtmp, 0]])
        Lh2 = np.array([[-xtmp, -h_cylinder], [xtmp, -h_cylinder]])
        # the two endpoints of the two vertical lines are
        Lv1 = np.array([[-xtmp, 0], [-xtmp, -h_cylinder]])
        Lv2 = np.array([[xtmp, 0], [xtmp, -h_cylinder]])

        # define line of neutrino propagation by two points
        vaz = np.matmul(Raz.T, v)
        if(abs(vaz[1]) > 1e-10):
            a = 1 / 0
        v2d = np.array([vaz[0], vaz[2]])
        X2d = np.array([Xaz[0], Xaz[2]])
        t = 2 * d
        Paz = np.array([X2d + -t * v2d, X2d + t * v2d])

        # calculate points that intersect any of the 4 area (projected cylinder) boundaries
        intersects = []
        for k, (a1, a2) in enumerate([Lh1, Lh2]):
            tmp = seg_intersect(a1, a2, Paz[0], Paz[1])
            if((tmp[0] >= a1[0]) and (tmp[0] <= a2[0])):
                intersects.append(tmp)
        for k, (a1, a2) in enumerate([Lv1, Lv2]):
            tmp = seg_intersect(a1, a2, Paz[0], Paz[1])
            if((tmp[1] <= a1[1]) and (tmp[1] >= a2[1])):
                intersects.append(tmp)
        intersects = np.array(intersects)
        if(len(intersects) != 2):
            if 0:
                print(len(intersects))
                import matplotlib.pyplot as plt
                from mpl_toolkits.mplot3d import Axes3D
                fig = plt.figure()
                a = fig.add_subplot(111, projection='3d')
                # Cylinder
                x = np.linspace(-r_cylinder, r_cylinder, 100)
                z = np.linspace(0, -h_cylinder, 100)
                Xc, Zc = np.meshgrid(x, z)
                Yc = np.sqrt(r_cylinder ** 2 - Xc ** 2)

                # Draw parameters
                rstride = 20
                cstride = 10
                a.plot_surface(Xc, Yc, Zc, alpha=0.2, rstride=rstride, cstride=cstride)
                a.plot_surface(Xc, -Yc, Zc, alpha=0.2, rstride=rstride, cstride=cstride)
                X_enter = X + 10 * units.km * v
                X_leave = X - 10 * units.km * v
                a.plot([X_enter[0], X_leave[0]], [X_enter[1], X_leave[1]], [X_enter[2], X_leave[2]], '-o')

                a.set_xlabel("x")
                a.set_zlabel("z")
                a.set_ylabel("y")
                a.legend()
                a.set_title("no intersection")

                fig = plt.figure()
                a = fig.add_subplot(111, projection='3d')
                for (a1, a2) in [Lh1, Lh2, Lv1, Lv2]:
                    a.plot([a1[0], a2[0]], [rmin, rmin], [a1[1], a2[1]])
                a.plot([Paz[0][0], Paz[1][0]], [rmin, rmin], [Paz[0][1], Paz[1][1]])
                a.set_xlabel("x")
                a.set_zlabel("z")
                a.set_ylabel("y")
                a.legend()
                plt.show()
            continue  # neutrino is not passing through cylinder
        n_cylinder += 1
        ss = []
        for tmp in intersects:
            ss.append(np.dot(tmp - X2d, v2d.T))
        argsort = np.argsort(np.array(ss))  # check which intersection happens first along neutrino path
        if 0:
            if(len(intersects)):
                import matplotlib.pyplot as plt
                from mpl_toolkits.mplot3d import Axes3D
                fig = plt.figure()
                a = fig.add_subplot(111, projection='3d')
                for (a1, a2) in [Lh1, Lh2, Lv1, Lv2]:
                    a.plot([a1[0], a2[0]], [rmin, rmin], [a1[1], a2[1]])
                a.plot([Paz[0][0], Paz[1][0]], [rmin, rmin], [Paz[0][1], Paz[1][1]])
                for k, tmp in enumerate(intersects):
                    a.plot([tmp[0]], [rmin], [tmp[1]], 'o', label=f"s = {ss[k]:.0f}")
                a.set_xlabel("x")
                a.set_zlabel("z")
                a.set_ylabel("y")
                a.legend()
    #             plt.ion()
                plt.show()

        # calculate the 3D points where the neutrino enters/leaves the cylinder and transform to outside Earth
        X_enter = np.matmul(Raz, np.array([intersects[argsort][0][0], rmin, intersects[argsort][0][1]])) + np.array([0, 0, R_earth])
        X_leave = np.matmul(Raz, np.array([intersects[argsort][1][0], rmin, intersects[argsort][1][1]])) + np.array([0, 0, R_earth])
        X += np.array([0, 0, R_earth])

        # calculate point where neutrino enters Earth
        if(np.linalg.norm(X_enter) > R_earth):  # if enter point is outside of Earth (can happen because cylinder does not account for Earth curvature)
            if(np.linalg.norm(X_leave) > R_earth):  # check if leave point is also outside of Earth (can also happen because cylinder does not account for Earth curvature)
                continue
            t = brentq(obj_dist_to_surface, 0, 5 * d, args=(-v, X_leave))
            enter_point = X_leave + (-v * t)
            X_enter = enter_point  # define point where neutrino enters the cylinder as the point where it enters the Earth
        else:
            t = brentq(obj_dist_to_surface, 0, 2 * R_earth, args=(-v, X_enter))
            enter_point = X_enter + (-v * t)
    #     logger.debug(f"zen = {zen[i]/units.deg:.0f}deg, trajectory enters Earth at {enter_point[0]:.1f}, {enter_point[0]:.1f}, {enter_point[0]:.1f}. Dist to core = {np.linalg.norm(enter_point)/R_earth:.5f}, dist to (0,0,R) = {np.linalg.norm(enter_point - np.array([0,0,R_earth]))/R_earth:.4f}")

        # check if event interacts at all
        # calcualte slant depth to point of entering cylinder
        t = np.linalg.norm(enter_point - X_enter)
        slant_depth_min = slant_depth(t, v, enter_point)
        if(t == 0):
            slant_depth_min = 0
        # calculate slant depth through the cylinder
        s = np.linalg.norm(X_leave - X_enter)
        slant_depth_max = slant_depth(s, v, X_enter) + slant_depth_min  # full slant depth from outside Earth to point when it leaves the cylinder

        if 0:
            import matplotlib.pyplot as plt
            from mpl_toolkits.mplot3d import Axes3D
            fig = plt.figure()
            a = fig.add_subplot(111, projection='3d')
            # Cylinder
            x = np.linspace(-r_cylinder, r_cylinder, 100)
            z = np.linspace(0, -h_cylinder, 100)
            Xc, Zc = np.meshgrid(x, z)
            Yc = np.sqrt(r_cylinder ** 2 - Xc ** 2)

            # Draw parameters
            rstride = 20
            cstride = 10
            a.plot_surface(Xc, Yc, Zc, alpha=0.2, rstride=rstride, cstride=cstride)
            a.plot_surface(Xc, -Yc, Zc, alpha=0.2, rstride=rstride, cstride=cstride)
            a.plot([X_enter[0], X_leave[0]], [X_enter[1], X_leave[1]], [X_enter[2] - R_earth, X_leave[2] - R_earth], '-o')

            a.set_xlabel("x")
            a.set_zlabel("z")
            a.set_ylabel("y")
            print(f"Lmin = {slant_depth_min:.2g}, Lmax = {slant_depth_max:.2g}, Lnu = {Lint[i]:.2g}")
            a.legend()
            plt.show()
    #         a = 1 / 0
        if((Lint[i] <= slant_depth_min) or (Lint[i] >= slant_depth_max)):
            logger.debug("neutrino does not interact in cylinder, skipping to next event")
            continue

        try:
            # calculate interaction point by inegrating the density of Earth along the neutrino path until we wind the interaction length
            t = brentq(obj, 0, s, args=(v, X_enter, Lint[i] - slant_depth_min), maxiter=500)
        except:
            logger.warning("failed to converge, skipping event")
            failed += 1
            continue
        Xint = X_enter + v * t  # calculate interaction point

        is_in_cylinder = points_in_cylinder(pt1, pt2, r_cylinder, Xint)
        mask_int[i] = is_in_cylinder
        if(is_in_cylinder):
            logger.debug(f"event {i}, interaction point ({Xint[0]:.1f}, {Xint[1]:.1f}, {Xint[2]-R_earth:.1f}), in cylinder {is_in_cylinder}")
            data_sets['xx'].append(Xint[0])
            data_sets['yy'].append(Xint[1])
            data_sets['zz'].append(Xint[2] - R_earth)
            data_sets['zeniths'].append(zen[i])
            data_sets['azimuths'].append(az[i])
            data_sets['flavors'].append(flavors[i])
            data_sets['energies'].append(Enu[i])

        else:
            logger.error("interaction is not in cylinder but it should be")
            a = 1 / 0

    data_sets['event_ids'] = range(np.sum(mask_int))
    data_sets['flavors'] = np.ones(np.sum(mask_int))
    data_sets["event_ids"] = np.arange(np.sum(mask_int)) + start_event_id
    data_sets["n_interaction"] = np.ones(np.sum(mask_int), dtype=np.int)
    data_sets["vertex_times"] = np.zeros(np.sum(mask_int), dtype=np.float)

    data_sets["interaction_type"] = inelasticities.get_ccnc(np.sum(mask_int))
    data_sets["inelasticity"] = inelasticities.get_neutrino_inelasticity(np.sum(mask_int))

    attributes['n_events'] = n_events

    logger.info(f"{np.sum(mask_int)} event interacted in simulation volume")

    write_events_to_hdf5(filename, data_sets, attributes,
                         n_events_per_file=n_events_per_file, start_file_id=start_file_id)
Example #12
0
	def get_test_emission(self, frame):

		propagator = propagation.get_propagation_module('analytic')
		ice = medium.get_ice_model('ARAsim_southpole')

		# work up a simple example to test functionality
		ant = np.array([0,0,-100])
		vertex = np.array([-2543.18,2319.96,-1828.74])
		azi = 2.4658
		zen = 1.0863
		inelast = 0.55
		inttype = 'cc'
		flavor = 14
		energy = 9.20e+18
		n_index = ice.get_index_of_refraction(vertex)
		cherenkov_angle = np.arccos(1./n_index)
		shower_axis = -1 * hp.spherical_to_cartesian(zen, azi)

		r = propagator(vertex,
			ant,
			medium=ice,
			attenuation_model='SP1',
			n_frequencies_integration=25,
			n_reflections=0
			)
		r.find_solutions()
		num_solutions = r.get_number_of_solutions()
		viewing_angles = []
		distances = []
		launch_vectors = []
		receive_vectors = []
		# print('num solutions is {}'.format(num_solutions))
		for iS in range(num_solutions):
			launch_vectors.append(r.get_launch_vector(iS))
			receive_vectors.append(r.get_receive_vector(iS))
			# launch_vector = r.get_launch_vector(iS)
			viewing_angles.append(hp.get_angle(shower_axis, launch_vectors[iS]))
			distances.append(r.get_path_length(iS))
			# viewing_angle = hp.get_angle(shower_axis, launch_vector)

		#fem, fhad = helper._get_em_had_fraction(inelast, inttype, flavor)
		fem=0
		fhad=0.55

		signal = askaryan.get_time_trace(
			energy = energy * fhad,
			theta = viewing_angles[0],
			N = self._n_samples,
			dt = self._dt,
			shower_type='HAD',
			n_index = n_index,
			R=distances[0],
			model=self._askaryan_model,
			seed=self._seed
		)

		polarization_direction_onsky = util_geo.calculate_polarization_vector(launch_vectors[0], shower_axis)
		icetray.logging.log_debug("Polarization direction on sky {}".format(polarization_direction_onsky))

		this_eR, this_eTheta, this_ePhi = np.outer(polarization_direction_onsky, signal)

		# create traces for the eR, eTheta, and ePhi components inside
		eR = icetradio.I3Trace()
		eTheta = icetradio.I3Trace()
		ePhi = icetradio.I3Trace()

		eR.trace = this_eR
		eR.traceStartTime = 0
		eR.samplingRate = self._sampling_rate
		eTheta.trace = this_eTheta
		eTheta.traceStartTime = 0
		eTheta.samplingRate = self._sampling_rate
		ePhi.trace = this_ePhi
		ePhi.traceStartTime = 0
		eTheta.samplingRate = self._sampling_rate


		# put those traces inside an EField
		field = icetradio.I3EField()
		field.eR = eR
		field.eTheta = eTheta
		field.ePhi = ePhi

		frame.Put("DummyEField", field)
Example #13
0
    def __init__(self, zenith, azimuth, magnetic_field_vector=None, site=None):
        """ Initialization with signal/air-shower direction and magnetic field configuration.

        All parameters should be specified according to the default coordinate
        system of the radiotools package (the Auger coordinate system).

        Parameters
        ----------
        zenith : float
            zenith angle of the incoming signal/air-shower direction (0 deg is pointing to the zenith)
        azimuth : float
            azimuth angle of the incoming signal/air-shower direction (0 deg is North, 90 deg is South)
        magnetic_field_vector (optional): 3-vector, default None
            the magnetic field vector in the cartesian ground coordinate system,
            if no magnetic field vector is specified, the default value for the
            site specified in the 'site' function argument is used.
        site (optional): string, default 'Auger'
            this argument has only effect it 'magnetic_field_vector' is None
            the site for which the magnetic field vector should be used. Currently, default
            values for for the sites 'auger' and 'arianna' are available
        """
        showeraxis = -1 * hp.spherical_to_cartesian(
            zenith, azimuth)  # -1 is because shower is propagating towards us
        if (magnetic_field_vector is None):
            magnetic_field_vector = hp.get_magnetic_field_vector(site=site)
        magnetic_field_normalized = magnetic_field_vector / \
            linalg.norm(magnetic_field_vector)
        vxB = np.cross(showeraxis, magnetic_field_normalized)
        e1 = vxB
        e2 = np.cross(showeraxis, vxB)
        e3 = np.cross(e1, e2)

        e1 /= linalg.norm(e1)
        e2 /= linalg.norm(e2)
        e3 /= linalg.norm(e3)

        self.__transformation_matrix_vBvvB = copy.copy(np.matrix([e1, e2, e3]))
        self.__inverse_transformation_matrix_vBvvB = np.linalg.inv(
            self.__transformation_matrix_vBvvB)

        # initilize transformation matrix to on-sky coordinate system (er, etheta, ephi)
        ct = np.cos(zenith)
        st = np.sin(zenith)
        cp = np.cos(azimuth)
        sp = np.sin(azimuth)
        e1 = np.array([st * cp, st * sp, ct])
        e2 = np.array([ct * cp, ct * sp, -st])
        e3 = np.array([-sp, cp, 0])
        self.__transformation_matrix_onsky = copy.copy(np.matrix([e1, e2, e3]))
        self.__inverse_transformation_matrix_onsky = np.linalg.inv(
            self.__transformation_matrix_onsky)

        # initilize transformation matrix from magnetic north to geographic north coordinate system
        declination = hp.get_declination(magnetic_field_vector)
        c = np.cos(-1 * declination)
        s = np.sin(-1 * declination)
        e1 = np.array([c, -s, 0])
        e2 = np.array([s, c, 0])
        e3 = np.array([0, 0, 1])
        self.__transformation_matrix_magnetic = copy.copy(
            np.matrix([e1, e2, e3]))
        self.__inverse_transformation_matrix_magnetic = np.linalg.inv(
            self.__transformation_matrix_magnetic)

        # initilize transformation matrix from ground (geographic) cs to ground
        # cs where x axis points into shower direction projected on ground
        c = np.cos(-1 * azimuth)
        s = np.sin(-1 * azimuth)
        e1 = np.array([c, -s, 0])
        e2 = np.array([s, c, 0])
        e3 = np.array([0, 0, 1])
        self.__transformation_matrix_azimuth = copy.copy(
            np.matrix([e1, e2, e3]))
        self.__inverse_transformation_matrix_azimuth = np.linalg.inv(
            self.__transformation_matrix_azimuth)

        # initilize transformation matrix from ground (geographic) cs to shower plane (early-late) cs
        # rotation along z axis -> shower axis along y axis
        c = np.cos(-azimuth + np.pi / 2)
        s = np.sin(-azimuth + np.pi / 2)
        e1 = np.matrix([[c, -s, 0], [s, c, 0], [0, 0, 1]])

        # rotation along x axis -> rotation in shower plane
        c = np.cos(zenith)
        s = np.sin(zenith)
        e2 = np.matrix([[1, 0, 0], [0, c, -s], [0, s, c]])

        self.__transformation_matrix_early_late = copy.copy(np.matmul(e2, e1))
        self.__inverse_transformation_matrix_early_late = np.linalg.inv(
            self.__transformation_matrix_early_late)
    def run(self, evt, station, det, n_index=None, ZenLim=None,
            AziLim=None,
            channel_pairs=((0, 2), (1, 3)),
            use_envelope=False):
        """
        reconstruct signal arrival direction for all events

        Parameters
        ----------
        evt: Event
            The event to run the module on
        station: Station
            The station to run the module on
        det: Detector
            The detector description
        n_index: float
            the index of refraction
        ZenLim: 2-dim array/list of floats (default: [0 * units.deg, 90 * units.deg])
            the zenith angle limits for the fit
        AziLim: 2-dim array/list of floats (default: [0 * units.deg, 360 * units.deg])
            the azimuth angle limits for the fit
        channel_pairs: pair of pair of integers
            specify the two channel pairs to use, default ((0, 2), (1, 3))
        use_envelope: bool (default False)
            if True, the hilbert envelope of the traces is used
        """

        if ZenLim is None:
            ZenLim = [0 * units.deg, 90 * units.deg]
        if AziLim is None:
            AziLim = [0 * units.deg, 360 * units.deg]
        use_correlation = True

        def ll_regular_station(angles, corr_02, corr_13, sampling_rate, positions, trace_start_times):
            """
            Likelihood function for a four antenna ARIANNA station, using correction.
            Using correlation, has no built in wrap around, pulse needs to be in the middle
            """

            zenith = angles[0]
            azimuth = angles[1]
            times = []

            for pos in positions:
                tmp = [geo_utl.get_time_delay_from_direction(zenith, azimuth, pos[0], n=n_index),
                       geo_utl.get_time_delay_from_direction(zenith, azimuth, pos[1], n=n_index)]
                times.append(tmp)

            delta_t_02 = times[0][1] - times[0][0]
            delta_t_13 = times[1][1] - times[1][0]
            # take different trace start times into account
            delta_t_02 -= (trace_start_times[0][1] - trace_start_times[0][0])
            delta_t_13 -= (trace_start_times[1][1] - trace_start_times[1][0])
            delta_t_02 *= sampling_rate
            delta_t_13 *= sampling_rate
            pos_02 = int(corr_02.shape[0] / 2 - delta_t_02)
            pos_13 = int(corr_13.shape[0] / 2 - delta_t_13)

#             weight_02 = np.sum(corr_02 ** 2)  # Normalize crosscorrelation
#             weight_13 = np.sum(corr_13 ** 2)
#
#             likelihood = -1 * (corr_02[pos_02] ** 2 / weight_02 + corr_13[pos_13] ** 2 / weight_13)
            # After deliberating a bit, I don't think we should use the square because anti-correlating
            # pulses would be wrong, given that it is not a continous waveform

            weight_02 = np.sum(np.abs(corr_02))  # Normalize crosscorrelation
            weight_13 = np.sum(np.abs(corr_13))

            likelihood = -1 * (corr_02[pos_02] / weight_02 + corr_13[pos_13] / weight_13)

            return likelihood

        def ll_regular_station_fft(angles, corr_02_fft, corr_13_fft, sampling_rate, positions, trace_start_times):
            """
            Likelihood function for a four antenna ARIANNA station, using FFT convolution
            Using FFT convolution, has built-in wrap around, but ARIANNA signals are too short for it to be accurate
            will show problems at zero time delay
            """

            zenith = angles[0]
            azimuth = angles[1]
            times = []

            for pos in positions:
                tmp = [geo_utl.get_time_delay_from_direction(zenith, azimuth, pos[0], n=n_index) * sampling_rate,
                       geo_utl.get_time_delay_from_direction(zenith, azimuth, pos[1], n=n_index) * sampling_rate]
                times.append(tmp)

            delta_t_02 = (times[0][1] + trace_start_times[0][1] * sampling_rate) - (times[0][0] + trace_start_times[0][0] * sampling_rate)
            delta_t_13 = (times[1][1] + trace_start_times[1][1] * sampling_rate) - (times[1][0] + trace_start_times[1][0] * sampling_rate)

            if delta_t_02 < 0:
                pos_02 = int(delta_t_02 + corr_02_fft.shape[0])
            else:
                pos_02 = int(delta_t_02)

            if delta_t_13 < 0:
                pos_13 = int(delta_t_13 + corr_13_fft.shape[0])
            else:
                pos_13 = int(delta_t_13)

            weight_02 = np.sum(np.abs(corr_02_fft))  # Normalize crosscorrelation
            weight_13 = np.sum(np.abs(corr_13_fft))

            likelihood = -1 * (np.abs(corr_02_fft[pos_02]) ** 2 / weight_02 + np.abs(corr_13[pos_13]) ** 2 / weight_13)
            return likelihood

        station_id = station.get_id()
        positions_pairs = [[det.get_relative_position(station_id, channel_pairs[0][0]), det.get_relative_position(station_id, channel_pairs[0][1])],
                           [det.get_relative_position(station_id, channel_pairs[1][0]), det.get_relative_position(station_id, channel_pairs[1][1])]]
        sampling_rate = station.get_channel(0).get_sampling_rate()  # assume that channels have the same sampling rate
        trace_start_time_pairs = [[station.get_channel(channel_pairs[0][0]).get_trace_start_time(), station.get_channel(channel_pairs[0][1]).get_trace_start_time()],
                                  [station.get_channel(channel_pairs[1][0]).get_trace_start_time(), station.get_channel(channel_pairs[1][1]).get_trace_start_time()]]
        # determine automatically if one channel has an inverted waveform with respect to the other
        signs = [1., 1.]
        for iPair, pair in enumerate(channel_pairs):
            antenna_type = det.get_antenna_type(station_id, pair[0])
            if("LPDA" in antenna_type):
                otheta, ophi, rot_theta, rot_azimuth = det.get_antenna_orientation(station_id, pair[0])
                otheta2, ophi2, rot_theta2, rot_azimuth2 = det.get_antenna_orientation(station_id, pair[1])
                if(np.isclose(np.abs(rot_azimuth - rot_azimuth2), 180 * units.deg, atol=1 * units.deg)):
                    signs[iPair] = -1

        if use_correlation:
            # Correlation
            if not use_envelope:
                corr_02 = signal.correlate(station.get_channel(channel_pairs[0][0]).get_trace(),
                                           signs[0] * station.get_channel(channel_pairs[0][1]).get_trace())
                corr_13 = signal.correlate(station.get_channel(channel_pairs[1][0]).get_trace(),
                                           signs[1] * station.get_channel(channel_pairs[1][1]).get_trace())
            else:
                corr_02 = signal.correlate(np.abs(signal.hilbert(station.get_channel(channel_pairs[0][0]).get_trace())),
                                           np.abs(signal.hilbert(station.get_channel(channel_pairs[0][1]).get_trace())))
                corr_13 = signal.correlate(np.abs(signal.hilbert(station.get_channel(channel_pairs[1][0]).get_trace())),
                                           np.abs(signal.hilbert(station.get_channel(channel_pairs[1][1]).get_trace())))

        else:
            # FFT convolution
            corr_02_fft = fftpack.ifft(-1 * fftpack.fft(station.get_channel(channel_pairs[0][0]).get_trace()).conjugate() * fftpack.fft(station.get_channel(channel_pairs[0][1]).get_trace()))
            corr_13_fft = fftpack.ifft(-1 * fftpack.fft(station.get_channel(channel_pairs[1][0]).get_trace()).conjugate() * fftpack.fft(station.get_channel(channel_pairs[1][1]).get_trace()))

        if use_correlation:
            # Using correlation
            ll = opt.brute(
                ll_regular_station,
                ranges=(slice(ZenLim[0], ZenLim[1], 0.01), slice(AziLim[0], AziLim[1], 0.01)),
                args=(corr_02, corr_13, sampling_rate, positions_pairs, trace_start_time_pairs),
                full_output=True, finish=opt.fmin)  # slow but does the trick
        else:
            ll = opt.brute(ll_regular_station_fft, ranges=(slice(ZenLim[0], ZenLim[1], 0.05),
                                                           slice(AziLim[0], AziLim[1], 0.05)),
                           args=(corr_02_fft, corr_13_fft, sampling_rate, positions_pairs, trace_start_time_pairs), full_output=True, finish=opt.fmin)  # slow but does the trick

        if self.__debug:
            import peakutils
            zenith = ll[0][0]
            azimuth = ll[0][1]
            times = []

            for pos in positions_pairs:
                tmp = [geo_utl.get_time_delay_from_direction(zenith, azimuth, pos[0], n=n_index),
                       geo_utl.get_time_delay_from_direction(zenith, azimuth, pos[1], n=n_index)]
                times.append(tmp)

            delta_t_02 = times[0][1] - times[0][0]
            delta_t_13 = times[1][1] - times[1][0]
            # take different trace start times into account
            delta_t_02 -= (trace_start_time_pairs[0][1] - trace_start_time_pairs[0][0])
            delta_t_13 -= (trace_start_time_pairs[1][1] - trace_start_time_pairs[1][0])
            delta_t_02 *= sampling_rate
            delta_t_13 *= sampling_rate

            toffset = -(np.arange(0, corr_02.shape[0]) - corr_02.shape[0] / 2) / sampling_rate

            fig, (ax, ax2) = plt.subplots(2, 1, sharex=True)
            ax.plot(toffset, corr_02)
            ax.axvline(delta_t_02 / sampling_rate, label='time', c='k')
            indices = peakutils.indexes(corr_02, thres=0.8, min_dist=5)
            ax.plot(toffset[indices], corr_02[indices], 'o')
            imax = np.argmax(corr_02[indices])
            self.logger.debug("offset 02= {:.3f}".format(toffset[indices[imax]] - (delta_t_02 / sampling_rate)))

            ax2.plot(toffset, corr_13)
            indices = peakutils.indexes(corr_13, thres=0.8, min_dist=5)
            ax2.plot(toffset[indices], corr_13[indices], 'o')

            ax2.axvline(delta_t_13 / sampling_rate, label='time', c='k')

            ax2.set_xlabel("time")
            ax2.set_ylabel("Correlation Ch 1/ Ch3", fontsize='small')
            ax.set_ylabel("Correlation Ch 0/ Ch2", fontsize='small')
            plt.tight_layout()
#             plt.close("all")

        station[stnp.zenith] = max(ZenLim[0], min(ZenLim[1], ll[0][0]))
        station[stnp.azimuth] = ll[0][1]
        output_str = "reconstucted angles theta = {:.1f}, phi = {:.1f}".format(station[stnp.zenith] / units.deg, station[stnp.azimuth] / units.deg)
        if station.has_sim_station():
            sim_zen = None
            sim_az = None
            if(station.get_sim_station().is_cosmic_ray()):
                sim_zen = station.get_sim_station()[stnp.zenith]
                sim_az = station.get_sim_station()[stnp.azimuth]
            elif(station.get_sim_station().is_neutrino()):  # in case of a neutrino simulation, each channel has a slightly different arrival direction -> compute the average
                sim_zen = []
                sim_az = []
                for efield in station.get_sim_station().get_electric_fields_for_channels(ray_path_type='direct'):
                    sim_zen.append(efield[efp.zenith])
                    sim_az.append(efield[efp.azimuth])
                sim_zen = np.array(sim_zen)
                sim_az = hp.get_normalized_angle(np.array(sim_az))
                ops = "average incident zenith {:.1f} +- {:.1f}".format(np.mean(sim_zen) / units.deg, np.std(sim_zen) / units.deg)
                ops += " (individual: "
                for x in sim_zen:
                    ops += "{:.1f}, ".format(x / units.deg)
                ops += ")"
                self.logger.debug(ops)
                ops = "average incident azimuth {:.1f} +- {:.1f}".format(np.mean(sim_az) / units.deg, np.std(sim_az) / units.deg)
                ops += " (individual: "
                for x in sim_az:
                    ops += "{:.1f}, ".format(x / units.deg)
                ops += ")"

                self.logger.debug(ops)
                sim_zen = np.mean(np.array(sim_zen))
                sim_az = np.mean(np.array(sim_az))

            if(sim_zen is not None):
                dOmega = hp.get_angle(hp.spherical_to_cartesian(sim_zen, sim_az), hp.spherical_to_cartesian(station[stnp.zenith], station[stnp.azimuth]))
                output_str += "  MC theta = {:.2f}, phi = {:.2f},  dOmega = {:.2f}, dZen = {:.1f}, dAz = {:.1f}".format(sim_zen / units.deg, hp.get_normalized_angle(sim_az) / units.deg, dOmega / units.deg, (station[stnp.zenith] - sim_zen) / units.deg, (station[stnp.azimuth] - hp.get_normalized_angle(sim_az)) / units.deg)
                self.__zenith.append(sim_zen)
                self.__azimuth.append(sim_az)
                self.__delta_zenith.append(station[stnp.zenith] - sim_zen)
                self.__delta_azimuth.append(station[stnp.azimuth] - hp.get_normalized_angle(sim_az))

        self.logger.info(output_str)
        # Still have to add fit quality parameter to output

        if self.__debug:
            import peakutils
            # access simulated efield and high level parameters
            sim_present = False
            if(station.has_sim_station()):
                if(station.get_sim_station().has_parameter(stnp.zenith)):
                    sim_station = station.get_sim_station()
                    azimuth_orig = sim_station[stnp.azimuth]
                    zenith_orig = sim_station[stnp.zenith]
                    sim_present = True
                    self.logger.debug("True CoREAS zenith {0}, azimuth {1}".format(zenith_orig, azimuth_orig))
            self.logger.debug("Result of direction fitting: [zenith, azimuth] {}".format(np.rad2deg(ll[0])))

            # Show fit space
            zen = np.arange(ZenLim[0], ZenLim[1], 1 * units.deg)
            az = np.arange(AziLim[0], AziLim[1], 2 * units.deg)

            x_plot = np.zeros(zen.shape[0] * az.shape[0])
            y_plot = np.zeros(zen.shape[0] * az.shape[0])
            z_plot = np.zeros(zen.shape[0] * az.shape[0])
            i = 0
            for a in az:
                for z in zen:
                    # Evaluate fit function for grid
                    if use_correlation:
                        z_plot[i] = ll_regular_station([z, a], corr_02, corr_13, sampling_rate, positions_pairs, trace_start_time_pairs)
                    else:
                        z_plot[i] = ll_regular_station_fft([z, a], corr_02_fft, corr_13_fft, sampling_rate, positions_pairs, trace_start_time_pairs)
                    x_plot[i] = a
                    y_plot[i] = z
                    i += 1

            fig, ax = plt.subplots(1, 1)
            ax.scatter(np.rad2deg(x_plot), np.rad2deg(y_plot), c=z_plot, cmap='gnuplot2_r', lw=0)
#             ax.imshow(z_plot, cmap='gnuplot2_r', extent=(0, 360, 90, 180))
            if sim_present:
                ax.plot(np.rad2deg(hp.get_normalized_angle(azimuth_orig)), np.rad2deg(zenith_orig), marker='d', c='g', label="True")
            ax.scatter(np.rad2deg(ll[0][1]), np.rad2deg(ll[0][0]), marker='o', c='k', label='Fit')
#             ax.colorbar(label='Fit parameter')
            ax.set_ylabel('Zenith [rad]')
            ax.set_xlabel('Azimuth [rad]')
            plt.tight_layout()

            # plot allowed solution separately for each pair of channels
            toffset = -(np.arange(0, corr_02.shape[0]) - corr_02.shape[0] / 2.) / sampling_rate
            indices = peakutils.indexes(corr_02, thres=0.8, min_dist=5)
            t02s = toffset[indices][np.argsort(corr_02[indices])[::-1]] + (trace_start_time_pairs[0][1] - trace_start_time_pairs[0][0])
            toffset = -(np.arange(0, corr_13.shape[0]) - corr_13.shape[0] / 2.) / sampling_rate
            indices = peakutils.indexes(corr_13, thres=0.8, min_dist=5)
            t13s = toffset[indices][np.argsort(corr_13[indices])[::-1]] + (trace_start_time_pairs[1][1] - trace_start_time_pairs[1][0])
            from scipy import constants
            c = constants.c * units.m / units.s
            dx = -6 * units.m

            def get_deltat13(dt, phi):
                t = -1. * dt * c / (dx * np.cos(phi) * n_index)
                t[t < 0] = np.nan
                return np.arcsin(t)

            def get_deltat02(dt, phi):
                t = -1 * dt * c / (dx * np.sin(phi) * n_index)
                t[t < 0] = np.nan
                return np.arcsin(t)

            def getDeltaTCone(r, dt):
                dist = np.linalg.norm(r)
                t0 = -dist * n_index / c
                Phic = np.arccos(dt / t0)  # cone angle for allowable solutions
                self.logger.debug('dist = {}, dt = {}, t0 = {}, phic = {}'.format(dist, dt, t0, Phic))
                nr = r / dist  # normalize
                p = np.cross([0, 0, 1], nr)  # create a perpendicular normal vector to r
                p = p / np.linalg.norm(p)
                q = np.cross(nr, p)  # nr, p, and q form an orthonormal basis
                self.logger.debug('nr = {}\np = {}\nq = {}\n'.format(nr, p, q))
                ThetaC = np.linspace(0, 2 * np.pi, 1000)
                Phis = np.zeros(len(ThetaC))
                Thetas = np.zeros(len(ThetaC))
                for i, thetac in enumerate(ThetaC):
                    # create a set of vectors that point along the cone defined by r and PhiC
                    rc = nr + np.tan(Phic) * (np.sin(thetac) * p + np.cos(thetac) * q)
                    nrc = rc / np.linalg.norm(rc)
                    theta = np.arccos(nrc[2])
                    phi = np.arctan2(nrc[1], nrc[0])
                    Phis[i] = phi
                    Thetas[i] = theta
                return Phis, Thetas

            # phis = np.deg2rad(np.linspace(0, 360, 10000))
            r0_2 = positions_pairs[0][1] - positions_pairs[0][0]  # vector pointing from Ch2 to Ch0
            r1_3 = positions_pairs[1][1] - positions_pairs[1][0]  # vector pointing from Ch3 to Ch1
            self.logger.debug('r02 {}\nr13 {}'.format(r0_2, r1_3))
            linestyles = ['-', '--', ':', '-.']
            for i, t02 in enumerate(t02s):
                # theta02 = get_deltat02(t02, phis)
                phi02, theta02 = getDeltaTCone(r0_2, t02)
                theta02[theta02 < 0] += np.pi
                phi02[phi02 < 0] += 2 * np.pi
                jumppos02 = np.where(np.abs(np.diff(phi02)) >= 5.0)
                for j, pos in enumerate(jumppos02):
                    phi02 = np.insert(phi02, pos + 1 + j, np.nan)
                    theta02 = np.insert(theta02, pos + 1 + j, np.nan)
                # mask02 = ~np.isnan(theta02)
                ax.plot(np.rad2deg(phi02), np.rad2deg(theta02), '{}C3'.format(linestyles[i % 4]), label='c 0+2 dt = {}'.format(t02))
            for i, t13 in enumerate(t13s):
                # theta13 = get_deltat13(t13, phis)
                phi13, theta13 = getDeltaTCone(r1_3, t13)
                theta13[theta13 < 0] += np.pi
                phi13[phi13 < 0] += 2 * np.pi
                jumppos13 = np.where(np.abs(np.diff(phi13)) >= 5.0)
                for j, pos in enumerate(jumppos13):
                    phi13 = np.insert(phi13, pos + 1 + j, np.nan)
                    theta13 = np.insert(theta13, pos + 1 + j, np.nan)
                # mask13 = ~np.isnan(theta13)
                ax.plot(np.rad2deg(phi13), np.rad2deg(theta13), '{}C2'.format(linestyles[i % 4]), label='c 1+3 dt = {}'.format(t13))
            ax.legend(fontsize='small')
            ax.set_ylim(ZenLim[0] / units.deg, ZenLim[1] / units.deg)
            ax.set_xlim(AziLim[0] / units.deg, AziLim[1] / units.deg)
def update_sim_event_3d(i_event, filename, station_id, juser_id):
    if filename is None or station_id is None:
        return {}
    user_id = json.loads(juser_id)
    ariio = provider.get_arianna_io(user_id, filename)
    evt = ariio.get_event_i(i_event)
    station = evt.get_station(station_id)
    sim_station = station.get_sim_station()
    if sim_station is None:
        return {}
    data = [
        plotly.graph_objs.Scatter3d(x=[0],
                                    y=[0],
                                    z=[0],
                                    mode='markers',
                                    name='Station')
    ]
    if sim_station.has_parameter(stnp.nu_vertex):
        vertex = sim_station.get_parameter(stnp.nu_vertex)
        data.append(
            plotly.graph_objs.Scatter3d(x=[vertex[0]],
                                        y=[vertex[1]],
                                        z=[vertex[2]],
                                        mode='markers',
                                        name='Interaction Vertex'))
        plot_range = 1.5 * np.max(np.abs(vertex))
        if sim_station.has_parameter(
                stnp.nu_zenith) and sim_station.has_parameter(stnp.nu_azimuth):
            neutrino_path = hp.spherical_to_cartesian(
                sim_station.get_parameter(stnp.nu_zenith),
                sim_station.get_parameter(stnp.nu_azimuth))
            data.append(
                plotly.graph_objs.Scatter3d(
                    x=[
                        vertex[0],
                        vertex[0] + .25 * plot_range * neutrino_path[0]
                    ],
                    y=[
                        vertex[1],
                        vertex[1] + .25 * plot_range * neutrino_path[1]
                    ],
                    z=[
                        vertex[2],
                        vertex[2] + .25 * plot_range * neutrino_path[2]
                    ],
                    name='Neutrino Direction',
                    mode='lines'))
    else:
        plot_range = 1 * units.km
    fig = plotly.graph_objs.Figure(data=data,
                                   layout=plotly.graph_objs.Layout(
                                       width=1000,
                                       height=1000,
                                       legend={
                                           'orientation': 'h',
                                           'y': 1.1
                                       },
                                       scene={
                                           'aspectmode': 'manual',
                                           'aspectratio': {
                                               'x': 2,
                                               'y': 2,
                                               'z': 1
                                           },
                                           'xaxis': {
                                               'range':
                                               [-plot_range, plot_range]
                                           },
                                           'yaxis': {
                                               'range':
                                               [-plot_range, plot_range]
                                           },
                                           'zaxis': {
                                               'range': [-plot_range, 0]
                                           }
                                       }))
    return fig
Example #16
0
    xx = np.append(xx, np.array(fin['xx']))
    yy = np.append(yy, np.array(fin['yy']))
    zz = np.append(zz, np.array(fin['zz']))
    zeniths = np.append(zeniths, np.array(fin['zeniths']))
    azimuths = np.append(azimuths, np.array(fin['azimuths']))
    inelasticity = np.append(inelasticity, np.array(fin['inelasticity']))
    weight = np.append(weight, np.array(fin['weights']))
    st = np.append(st, np.array(fin['ray_tracing_solution_type']), axis=0)
    launch_vectors = np.append(launch_vectors,
                               np.array(fin['launch_vectors']),
                               axis=0)
    receive_vectors = np.append(receive_vectors,
                                np.array(fin['receive_vectors']),
                                axis=0)

shower_axis = -1.0 * hp.spherical_to_cartesian(zeniths, azimuths)
viewing_angles_d = np.array(
    [hp.get_angle(x, y) for x, y in zip(shower_axis, launch_vectors[:, 5, 0])])
viewing_angles_r = np.array(
    [hp.get_angle(x, y) for x, y in zip(shower_axis, launch_vectors[:, 5, 1])])
launch_angles_d, launch_azimuths_d = hp.cartesian_to_spherical_vectorized(
    launch_vectors[:, 5, 0, 0].flatten(), launch_vectors[:, 5, 0, 1].flatten(),
    launch_vectors[:, 5, 0, 2].flatten())
launch_angles_r, launch_azimuths_r = hp.cartesian_to_spherical_vectorized(
    launch_vectors[:, 5, 1, 0].flatten(), launch_vectors[:, 5, 1, 1].flatten(),
    launch_vectors[:, 5, 1, 2].flatten())
rec_angles_d, rec_azimuths_d = hp.cartesian_to_spherical_vectorized(
    receive_vectors[:, 5, 0, 0].flatten(),
    receive_vectors[:, 5, 0, 1].flatten(), receive_vectors[:, 5, 0,
                                                           2].flatten())
rec_angles_r, rec_azimuths_r = hp.cartesian_to_spherical_vectorized(
from astropy.time import Time

pio.renderers.default = "browser"
det = detector.GenericDetector(json_filename=sys.argv[1], default_station=101)
det.update(Time.now())

sid = 101
ll = 1 * units.m

data = []

for cid in det.get_channel_ids(sid):
    ori_zen, ori_az, rot_zen, rot_az = det.get_antenna_orientation(sid, cid)
    x, y, z = det.get_relative_position(sid, cid)

    dx, dy, dz = hp.spherical_to_cartesian(ori_zen, ori_az)
    xx = [x, x - ll * dx]
    yy = [y, y - ll * dy]
    zz = [z, z - ll * dz]
    dx, dy, dz = hp.spherical_to_cartesian(rot_zen, rot_az)
    xx.insert(0, x + 0.5 * ll * dx)
    yy.insert(0, y + 0.5 * ll * dy)
    zz.insert(0, z + 0.5 * ll * dz)
    print(
        f"channel {cid:d}, rot = {dx:.1f}, {dy:.1f}, {dz:.1f}, ({rot_zen / units.deg:.0f}, {rot_az / units.deg:.0f})"
    )

    data.append(go.Scatter3d(x=xx, y=yy, z=zz, mode='lines+markers'))

    if "LPDA" in det.get_antenna_type(sid, cid):
        ori = hp.spherical_to_cartesian(ori_zen, ori_az)
Example #18
0
     zz = np.array([])
     
     for i in range(flav.size):
         if (flav[i]):
             launch_vectors = np.append(launch_vectors, [lvtemp[i]], axis=0)
             zenith_inp = np.append(zenith_inp, [zeniths[i]], axis=0)
             azimuth_inp = np.append(azimuth_inp, [azimuths[i]], axis=0)
             xx = np.append(xx, xtemp[i])
             yy = np.append(yy, ytemp[i])
             zz = np.append(zz, ztemp[i])
             
     launch_vectors = np.delete(launch_vectors, 0, axis=0)
     zenith_inp = np.delete(zenith_inp, 0, axis=0)
     azimuth_inp = np.delete(azimuth_inp, 0, axis=0)
     
     shower_axis = -1 * hp.spherical_to_cartesian(zenith_inp, azimuth_inp)
     viewing_angles = np.array([hp.get_angle(x, y) for x, y in zip(shower_axis, launch_vectors[:, 0, 0])])
     
     # calculate correct chereknov angle for ice density at vertex position
     ice = medium.southpole_simple()
     n_indexs = np.array([ice.get_index_of_refraction(x) for x in np.array([xx, yy, zz]).T])
     rho = np.arccos(1. / n_indexs)
     
     mask = ~np.isnan(viewing_angles)
     fig, ax = php.get_histogram((viewing_angles[mask] - rho[mask]) / units.deg, weights=weightstemp[mask],
                                 bins=np.arange(-30, 30, 1), xlabel='viewing - cherenkov angle [deg] - ' + title, figsize=(6, 6))
     fig.savefig(os.path.join(plot_folder, title + '_{}_dCherenkov.pdf'.format(key)))
 
 ###########################
 # plot flavor ratios
 ###########################
Example #19
0
            ax.plot([x2[0]], [x2[1]], [x2[2]], 'ko')
        if (j != 0 and
            (~(np.array(triggered_deep[iE], dtype=np.bool) & mask))[j]):
            continue
        vertex = np.array([fin['xx'][iE], fin['yy'][iE], fin['zz'][iE]])
        #         print(fin.keys())
        #         l1 = fin['launch_vectors'][iE][3] / units.deg
        l2 = fin['station_101']['launch_vectors'][iE][j * 4 + 3]

        #         r1 = ray.ray_tracing(vertex, x1, med, log_level=logging.DEBUG)
        # #         r1.find_solutions()
        #         r1.set_solution(fin['ray_tracing_C0'][iE][3], fin['ray_tracing_C1'][iE][3], fin['ray_tracing_solution_type'][iE][3])
        #         path1 = r1.get_path(0)

        zen, az = fin['zeniths'][iE], fin['azimuths'][iE]
        v = hp.spherical_to_cartesian(zen, az)

        if (plot):
            r2 = ray.ray_tracing(vertex, x2, med, log_level=logging.INFO)
            r2.set_solution(
                fin['station_101']['ray_tracing_C0'][iE][iC],
                fin['station_101']['ray_tracing_C1'][iE][iC],
                fin['station_101']['ray_tracing_solution_type'][iE][iC])
            path2 = r2.get_path(0)
            #         ax.plot3D(path1.T[0], path1.T[1], path1.T[2], label='path 1')
            ax.plot3D(path2.T[0],
                      path2.T[1],
                      path2.T[2],
                      label='path {}'.format(j))
            ax.plot3D([vertex[0], vertex[0] + 500 * v[0]],
                      [vertex[1], vertex[1] + 500 * v[1]],
Example #20
0
def plot_event_overview(evt_counter, filename, station_id, station_mode,
                        channel_station, juser_id):
    if filename is None or station_id is None:
        return {}
    user_id = json.loads(juser_id)
    ariio = provider.get_arianna_io(user_id, filename)
    evt = ariio.get_event_i(evt_counter)
    station = evt.get_station(station_id)
    plots = []
    if station.is_neutrino():
        if station.has_sim_station():
            sim_station = station.get_sim_station()
            sim_vertex = sim_station.get_parameter(stnp.nu_vertex)
            sim_zenith = sim_station.get_parameter(stnp.nu_zenith)
            sim_azimuth = sim_station.get_parameter(stnp.nu_azimuth)
            sim_direction = hp.spherical_to_cartesian(
                sim_zenith, sim_azimuth) * 300. + sim_vertex
            plots.append(
                plotly.graph_objs.Scatter3d(x=[sim_vertex[0]],
                                            y=[sim_vertex[1]],
                                            z=[sim_vertex[2]],
                                            text=['Sim Vertex'],
                                            mode='markers',
                                            marker={
                                                'size': 3,
                                                'color': 'red'
                                            },
                                            showlegend=False,
                                            name='Vertex'))
            plots.append(
                plotly.graph_objs.Scatter3d(
                    x=[sim_vertex[0], sim_direction[0]],
                    y=[sim_vertex[1], sim_direction[1]],
                    z=[sim_vertex[2], sim_direction[2]],
                    mode='lines',
                    line={'color': 'red'},
                    showlegend=False,
                    name='Neutrino direction'))
            if evt.has_parameter(
                    evp.sim_config) and ariio.get_detector() is not None:
                det = ariio.get_detector()
                det.update(station.get_station_time())
                sim_config = evt.get_parameter(evp.sim_config)
                import NuRadioMC.SignalProp.analyticraytracing
                import NuRadioMC.utilities.medium
                attenuation_model = sim_config['propagation'][
                    'attenuation_model']
                ice_model = NuRadioMC.utilities.medium.get_ice_model(
                    sim_config['propagation']['ice_model'])
                n_reflections = sim_config['propagation']['n_reflections']
                for channel_id in det.get_channel_ids(station_id):
                    channel_pos = det.get_relative_position(
                        station_id,
                        channel_id) + det.get_absolute_position(station_id)
                    raytracer = NuRadioMC.SignalProp.analyticraytracing.ray_tracing(
                        sim_vertex,
                        channel_pos,
                        ice_model,
                        attenuation_model,
                        n_reflections=n_reflections)
                    raytracer.find_solutions()
                    for iS, solution in enumerate(raytracer.get_results()):
                        path = raytracer.get_path(iS, 100)
                        plots.append(
                            plotly.graph_objs.Scatter3d(
                                x=path[:, 0],
                                y=path[:, 1],
                                z=path[:, 2],
                                mode='lines',
                                line={'color': 'orange'},
                                showlegend=False,
                                name='Ch. {}, {}'.format(
                                    channel_id,
                                    NuRadioMC.SignalProp.analyticraytracing.
                                    solution_types[solution['type']])))
                cherenkov_cone, i_ch, j_ch, k_ch = get_cherenkov_cone(
                    ice_model, sim_vertex,
                    hp.spherical_to_cartesian(sim_zenith, sim_azimuth))
                plots.append(
                    plotly.graph_objs.Mesh3d(x=cherenkov_cone[:, 0],
                                             y=cherenkov_cone[:, 1],
                                             z=cherenkov_cone[:, 2],
                                             i=i_ch,
                                             j=j_ch,
                                             k=k_ch,
                                             color='red',
                                             opacity=.5,
                                             name='Cherenkov ring'))
    if station.is_cosmic_ray():
        for sim_shower in evt.get_sim_showers():
            sim_core = sim_shower.get_parameter(shp.core)
            sim_zenith = sim_shower.get_parameter(shp.zenith)
            sim_azimuth = sim_shower.get_parameter(shp.azimuth)
            sim_direction = hp.spherical_to_cartesian(sim_zenith, sim_azimuth)
            plots.append(
                plotly.graph_objs.Scatter3d(x=[sim_core[0]],
                                            y=[sim_core[1]],
                                            z=[sim_core[2]],
                                            mode='markers',
                                            marker={'color': 'red'},
                                            showlegend=False,
                                            name='Core position'))
            dir_points = np.array([sim_core, sim_core + 100 * sim_direction])
            plots.append(
                plotly.graph_objs.Scatter3d(x=dir_points[:, 0],
                                            y=dir_points[:, 1],
                                            z=dir_points[:, 2],
                                            mode='lines',
                                            line={'color': 'red'},
                                            showlegend=False,
                                            name='Shower direction'))

    if ariio.get_detector() is not None:
        det = ariio.get_detector()
        det.update(station.get_station_time())
        channel_positions = []
        channel_comments = []
        station_positions = []
        station_comments = []
        if station_mode == 'selected':
            draw_stations = [station_id]
        else:
            draw_stations = det.get_station_ids()
        for stat_id in draw_stations:
            station_positions.append(det.get_absolute_position(stat_id))
            station_comments.append('Station {}'.format(stat_id))
            for channel_id in det.get_channel_ids(stat_id):
                channel_comments.append('Ch.{}[{}]'.format(
                    channel_id,
                    det.get_channel(stat_id, channel_id)['ant_comment']))
                channel_positions.append(
                    det.get_absolute_position(stat_id) +
                    det.get_relative_position(stat_id, channel_id))
        channel_positions = np.array(channel_positions)
        station_positions = np.array(station_positions)
        if 'station' in channel_station:
            plots.append(
                plotly.graph_objs.Scatter3d(x=station_positions[:, 0],
                                            y=station_positions[:, 1],
                                            z=station_positions[:, 2],
                                            text=station_comments,
                                            mode='markers',
                                            marker={'size': 4},
                                            showlegend=False,
                                            name='Stations'))
        if 'channel' in channel_station:
            plots.append(
                plotly.graph_objs.Scatter3d(x=channel_positions[:, 0],
                                            y=channel_positions[:, 1],
                                            z=channel_positions[:, 2],
                                            text=channel_comments,
                                            mode='markers',
                                            marker={'size': 3},
                                            showlegend=False,
                                            name='Channels'))
    fig = plotly.graph_objs.Figure(data=plots)
    return fig
Example #21
0
        maxy = ax.get_ylim()
        php.get_histogram(p_ratio[mask],
                          bins=bins,
                          xlabel='vertical/horizonal polarization ratio',
                          stats=False,
                          ax=ax, kwargs={'facecolor': 'C0', 'alpha': 1, 'edgecolor': "k", 'label': 'direct rays'})
        # ax.set_xticks(bins)
        ax.legend()
        ax.set_ylim(maxy)
        fig.tight_layout()
        fig.savefig(os.path.join(plot_folder, '{}_polarization_unweighted.png'.format(key)))

        ###########################
        # plot viewing angle
        ###########################
        shower_axis = -1 * hp.spherical_to_cartesian(np.array(fin['zeniths'])[triggered], np.array(fin['azimuths'])[triggered])
        launch_vectors = np.array(station['launch_vectors'])[triggered]
        viewing_angles = np.array([hp.get_angle(x, y) for x, y in zip(shower_axis, launch_vectors[:, 0, 0])])

        # calculate correct chereknov angle for ice density at vertex position
        ice = medium.southpole_simple()
        n_indexs = np.array([ice.get_index_of_refraction(x) for x in np.array([np.array(fin['xx'])[triggered], np.array(fin['yy'])[triggered], np.array(fin['zz'])[triggered]]).T])
        rho = np.arccos(1. / n_indexs)

        mask = ~np.isnan(viewing_angles)
        fig, ax = php.get_histogram((viewing_angles[mask] - rho[mask]) / units.deg, weights=weights[mask],
                                    bins=np.arange(-30, 30, 1), xlabel='viewing - cherenkov angle [deg]', figsize=(6, 6))
        fig.savefig(os.path.join(plot_folder, '{}_dCherenkov.png'.format(key)))

        ###########################
        # plot flavor ratios
Example #22
0
def draw_station_view(station_id, checklist):
    """
    Draws the 3D view of the selected station

    Parameters:
    -----------------------
    station_id: int
        ID of the selected station
    checklist: array
        Array containing state of the station view
        options checkboxes
    """
    if station_id is None:
        return go.Figure([])
    detector_provider = NuRadioReco.detector.detector_browser.detector_provider.DetectorProvider(
    )
    detector = detector_provider.get_detector()
    channel_positions = []
    channel_ids = detector.get_channel_ids(station_id)
    antenna_types = []
    antenna_orientations = []
    antenna_rotations = []
    data = []
    for channel_id in channel_ids:
        channel_position = detector.get_relative_position(
            station_id, channel_id)
        channel_positions.append(channel_position)
        antenna_types.append(detector.get_antenna_type(station_id, channel_id))
        orientation = detector.get_antenna_orientation(station_id, channel_id)
        ant_ori = hp.spherical_to_cartesian(orientation[0], orientation[1])
        antenna_orientations.append(channel_position)
        antenna_orientations.append(channel_position + ant_ori)
        antenna_orientations.append([None, None, None])
        ant_rot = hp.spherical_to_cartesian(orientation[2], orientation[3])
        antenna_rotations.append(channel_position)
        antenna_rotations.append(channel_position + ant_rot)
        antenna_rotations.append([None, None, None])
        if 'createLPDA' in detector.get_antenna_type(
                station_id, channel_id) and 'sketch' in checklist:
            antenna_tip = channel_position + ant_ori
            antenna_tine_1 = channel_position + np.cross(ant_ori, ant_rot)
            antenna_tine_2 = channel_position - np.cross(ant_ori, ant_rot)
            data.append(
                go.Mesh3d(
                    x=[antenna_tip[0], antenna_tine_1[0], antenna_tine_2[0]],
                    y=[antenna_tip[1], antenna_tine_1[1], antenna_tine_2[1]],
                    z=[antenna_tip[2], antenna_tine_1[2], antenna_tine_2[2]],
                    opacity=.5,
                    color='black',
                    delaunayaxis='x',
                    hoverinfo='skip'))
    channel_positions = np.array(channel_positions)
    antenna_types = np.array(antenna_types)
    antenna_orientations = np.array(antenna_orientations)
    antenna_rotations = np.array(antenna_rotations)
    channel_ids = np.array(channel_ids)
    lpda_mask = (np.char.find(antenna_types, 'createLPDA') >= 0)
    vpol_mask = (np.char.find(antenna_types, 'bicone_v8') >=
                 0) | (np.char.find(antenna_types, 'greenland_vpol') >= 0)
    hpol_mask = (np.char.find(antenna_types, 'fourslot') >= 0) | (np.char.find(
        antenna_types, 'trislot') >= 0)
    if len(channel_positions[:, 0][lpda_mask]) > 0:
        data.append(
            go.Scatter3d(x=channel_positions[:, 0][lpda_mask],
                         y=channel_positions[:, 1][lpda_mask],
                         z=channel_positions[:, 2][lpda_mask],
                         ids=channel_ids[lpda_mask],
                         text=channel_ids[lpda_mask],
                         mode='markers+text',
                         name='LPDAs',
                         textposition='middle right',
                         marker_symbol='diamond-open',
                         marker=dict(size=4)))
    if len(channel_positions[:, 0][vpol_mask]) > 0:
        data.append(
            go.Scatter3d(x=channel_positions[:, 0][vpol_mask],
                         y=channel_positions[:, 1][vpol_mask],
                         z=channel_positions[:, 2][vpol_mask],
                         ids=channel_ids[vpol_mask],
                         text=channel_ids[vpol_mask],
                         mode='markers+text',
                         name='V-pol',
                         textposition='middle right',
                         marker_symbol='x',
                         marker=dict(size=4)))
    if len(channel_positions[:, 0][hpol_mask]) > 0:
        data.append(
            go.Scatter3d(x=channel_positions[:, 0][hpol_mask],
                         y=channel_positions[:, 1][hpol_mask],
                         z=channel_positions[:, 2][hpol_mask],
                         ids=channel_ids[hpol_mask],
                         text=channel_ids[hpol_mask],
                         mode='markers+text',
                         name='H-pol',
                         textposition='middle right',
                         marker_symbol='cross',
                         marker=dict(size=4)))
    if len(channel_positions[:, 0][(~lpda_mask) & (~vpol_mask) &
                                   (~hpol_mask)]) > 0:
        data.append(
            go.Scatter3d(
                x=channel_positions[:, 0][(~lpda_mask) & (~vpol_mask) &
                                          (~hpol_mask)],
                y=channel_positions[:, 1][(~lpda_mask) & (~vpol_mask) &
                                          (~hpol_mask)],
                z=channel_positions[:, 2][(~lpda_mask) & (~vpol_mask) &
                                          (~hpol_mask)],
                ids=channel_ids[(~lpda_mask) & (~vpol_mask) & (~hpol_mask)],
                text=channel_ids[(~lpda_mask) & (~vpol_mask) & (~hpol_mask)],
                mode='markers+text',
                name='other',
                textposition='middle right',
                marker=dict(size=3)))
    if len(channel_positions[:, 0]) > 0:
        data.append(
            go.Scatter3d(x=antenna_orientations[:, 0],
                         y=antenna_orientations[:, 1],
                         z=antenna_orientations[:, 2],
                         mode='lines',
                         name='Orientations',
                         marker_color='red',
                         hoverinfo='skip'))
        data.append(
            go.Scatter3d(x=antenna_rotations[:, 0],
                         y=antenna_rotations[:, 1],
                         z=antenna_rotations[:, 2],
                         mode='lines',
                         name='Rotations',
                         marker_color='blue',
                         hoverinfo='skip'))

    fig = go.Figure(data)
    fig.update_layout(scene=dict(aspectmode='data'),
                      legend_orientation='h',
                      legend=dict(x=.0, y=1.),
                      height=600,
                      margin=dict(l=10, r=10, t=30, b=10))
    return fig
def get_weight(theta_nu,
               pnu,
               flavors,
               mode='simple',
               cross_section_type='ctw',
               vertex_position=None,
               phi_nu=None):
    """
    calculates neutrino weight due to Earth absorption for different models

    Parameters
    ----------
    theta_nu: float or array of floats
        the zenith angle of the neutrino direction (where it came from, i.e., opposite to the direction of propagation)
    pnu: float or array of floats
        the momentum of the neutrino
    mode: string
        * 'simple': assuming interaction happens at the surface and approximating the Earth with constant density
        * 'core_mantle_crust_simple': assuming interaction happens at the surface and approximating the Earth with 3 layers of constant density
        * 'core_mantle_crust': approximating the Earth with 3 layers of constant density, path through Earth to interaction vertex is considered
        * 'PREM': density of Earth is parameterized as a fuction of radius, path through Earth to interaction vertex is considered
    cross_section_type: string
        'ghandi', 'ctw' or 'csms' (see description in `cross_sections.py`)
    vertex_position: 3-dim array or None (default)
        the position of the neutrino interaction
    phi_nu: float
        the azimuth angle of the neutrino direction
    """
    if (mode == 'simple'):
        return get_simple_weight(theta_nu,
                                 pnu,
                                 cross_section_type=cross_section_type)
    elif (mode == "core_mantle_crust_simple"):
        return get_core_mantle_crust_weight(
            theta_nu, pnu, flavors, cross_section_type=cross_section_type)
    elif (mode == "core_mantle_crust"):
        earth = CoreMantleCrustModel()
        direction = hp.spherical_to_cartesian(theta_nu, phi_nu)
        slant_depth = earth.slant_depth(vertex_position, direction)
        # by requesting the interaction length for a density of 1, we get it in units of length**2/weight
        L_int = cross_sections.get_interaction_length(
            pnu,
            density=1.,
            flavor=flavors,
            inttype='total',
            cross_section_type=cross_section_type)
        return np.exp(-slant_depth / L_int)
    elif (mode == "PREM"):
        earth = PREM()
        direction = hp.spherical_to_cartesian(theta_nu, phi_nu)
        slant_depth = earth.slant_depth(vertex_position, direction)
        # by requesting the interaction length for a density of 1, we get it in units of length**2/weight
        L_int = cross_sections.get_interaction_length(
            pnu,
            density=1.,
            flavor=flavors,
            inttype='total',
            cross_section_type=cross_section_type)
        return np.exp(-slant_depth / L_int)
    elif (mode == "None"):
        return 1.
    else:
        logger.error('mode {} not supported'.format(mode))
        raise NotImplementedError