Beispiel #1
0
    def reset_antennas():
        times = np.linspace(-20e-9, 80e-9, 2048, endpoint=False)
        pulse = pyrex.AskaryanSignal(times=times, energy=1e8, theta=np.radians(45))

        times2 = np.linspace(180e-9, 280e-9, 2048, endpoint=False)
        pulse2 = pyrex.AskaryanSignal(times=times, energy=1e8, theta=np.radians(45),
                                    t0=200e-9)

        antenna = pyrex.Antenna((0,0,0), freq_range=(100e6, 400e6), noise_rms=25e-6)
        antenna.receive(pulse)

        antenna2 = pyrex.Antenna((0,0,0), freq_range=(100e6, 400e6), noise_rms=25e-6)
        antenna2.receive(pulse)
        antenna2.receive(pulse2)

        return antenna, antenna2
Beispiel #2
0
def test_filter_attenuation():
    # filtered_spectrum = self.spectrum
    # responses = np.array(freq_response(self.frequencies))
    # filtered_spectrum *= responses
    # self.values = np.real(scipy.fftpack.ifft(filtered_spectrum))

    # freq_response = pf.attenuation
    # self = AskaryanSignal(times=np.linspace(-20e-9, 80e-9, 2048, endpoint=False),
    #                       energy=p.energy*1e-3, theta=psi, n=n)
    t = 0

    pf = pyrex.PathFinder(pyrex.IceModel(), (0,0,-2800), (5000,5000,-200))
    while not(pf.exists):
        z = np.random.random()*-2800
        pf = pyrex.PathFinder(pyrex.IceModel(), (0,0,z), (5000,5000,-200))

    p = pyrex.Particle(vertex=pf.from_point,
                       direction=(1/np.sqrt(2),1/np.sqrt(2),0), energy=1e6)

    k = pf.emitted_ray
    epol = np.vdot(k, p.direction) * k - p.direction
    epol = epol / np.linalg.norm(epol)
    psi = np.arccos(np.vdot(p.direction, k))
    n = pyrex.IceModel.index(p.vertex[2])

    pulse = pyrex.AskaryanSignal(times=np.linspace(-20e-9, 80e-9, 2048, endpoint=False),
                                 energy=p.energy, theta=psi, n=n)

    t += performance_test("filtered_spectrum = pulse.spectrum", number=1000,
                          use_globals={"pulse": pulse})

    t += performance_test("fs = pulse.frequencies", number=1000,
                          use_globals={"pulse": pulse})

    fs = pulse.frequencies

    # performance_test("alen = ice.attenuation_length(-1000, fa*1e-6)", number=100,
    #                  use_globals={"ice": pyrex.IceModel(), "fa": np.abs(fs)})

    t += performance_test("responses = freq_response(fs)", number=1000,
                          use_globals={"freq_response": pf.attenuation, "fs": fs})

    # t += performance_test("responses = np.array(freq_response(pulse.frequencies))",
    #                       number = 100, setup="import numpy as np",
    #                       use_globals={"freq_response": pf.attenuation,
    #                                    "pulse": pulse})

    filtered_spectrum = pulse.spectrum * np.array(pf.attenuation(pulse.frequencies))

    t += performance_test("np.real(scipy.fftpack.ifft(filtered_spectrum))",
                          number=1000, setup="import numpy as np; import scipy.fftpack",
                          use_globals={"filtered_spectrum": filtered_spectrum})

    print("Total time:", round(t*1000, 1), "milliseconds for", len(fs), "frequencies")
    print("           ", round(t*1e6/len(fs), 1), "microseconds per frequency")
Beispiel #3
0
def test_PathFinder_propagate():
    t = 0

    pf = pyrex.PathFinder(pyrex.IceModel(), (0,0,-2800), (5000,5000,-200))
    while not(pf.exists):
        z = np.random.random()*-2800
        pf = pyrex.PathFinder(pyrex.IceModel(), (0,0,z), (5000,5000,-200))

    p = pyrex.Particle(vertex=pf.from_point,
                       direction=(1/np.sqrt(2),1/np.sqrt(2),0), energy=1e6)

    k = pf.emitted_ray
    epol = np.vdot(k, p.direction) * k - p.direction
    epol = epol / np.linalg.norm(epol)
    psi = np.arccos(np.vdot(p.direction, k))
    n = pyrex.IceModel.index(p.vertex[2])

    pulse = pyrex.AskaryanSignal(times=np.linspace(-20e-9, 80e-9, 2048, endpoint=False),
                                 energy=p.energy, theta=psi, n=n)

    t += performance_test("signal.values *= 1 / pf.path_length", repeats=100,
                          setup="import pyrex;"+
                                "signal = pyrex.Signal(pulse.times, pulse.values)",
                          use_globals={"pf": pf, "pulse": pulse})

    pulse.values *= 1 / pf.path_length

    t += performance_test("signal.filter_frequencies(pf.attenuation)", repeats=100,
                          setup="import pyrex;"+
                                "signal = pyrex.Signal(pulse.times, pulse.values)",
                          use_globals={"pf": pf, "pulse": pulse})

    # pulse.filter_frequencies(pf.attenuation)

    t += performance_test("signal.times += pf.tof", repeats=100,
                          setup="import pyrex;"+
                                "signal = pyrex.Signal(pulse.times, pulse.values)",
                          use_globals={"pf": pf, "pulse": pulse})

    print("Total time:", round(t*1000, 1), "milliseconds per signal")
Beispiel #4
0
def test_pyspice_envelope():
    times, dt = np.linspace(0, 100e-9, 2048, endpoint=False, retstep=True)
    pulse = pyrex.AskaryanSignal(times=times, energy=1e8, theta=45*np.pi/180,
                                 n=1.75, t0=20e-9)

    performance_test("pyrex.Signal(pulse.times, pulse.envelope)", number=1000,
                     setup="import pyrex", use_globals={"pulse": pulse})

    spice_library = SpiceLibrary("/Users/bhokansonfasig/Documents/IceCube/"+
                                 "scalable_radio_array/spice_models")

    class NgSpiceSharedSignal(NgSpiceShared):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self._signal = None

        def get_vsrc_data(self, voltage, time, node, ngspice_id):
            self._logger.debug('ngspice_id-{} get_vsrc_data @{} node {}'.format(ngspice_id, time, node))
            voltage[0] = np.interp(time, self._signal.times, self._signal.values)
            return 0

    ngspice_shared = NgSpiceSharedSignal()

    class NgSpiceSignal:
        def __init__(self, signal, shared=ngspice_shared):
            self.shared = ngspice_shared
            self.shared._signal = signal

    def setup_circuit(kind="biased"):
        if kind=="biased":
            circuit = Circuit('Biased Envelope Circuit')
            circuit.include(spice_library['hsms'])

            circuit.V('in', 'input', circuit.gnd, 'dc 0 external')
            # bias portion
            circuit.C(2, 'input', 1, 10@u_nF)
            circuit.R(2, 1, 2, 1@u_kOhm)
            circuit.X('D2', 'hsms', 2, circuit.gnd)
            circuit.R(3, 2, 'bias', 1@u_kOhm)
            circuit.V('bias', 'bias', circuit.gnd, 5@u_V)
            # envelope portion
            circuit.X('D1', 'hsms', 1, 'output')
            circuit.C(1, 'output', circuit.gnd, 220@u_pF)
            circuit.R(1, 'output', circuit.gnd, 50@u_Ohm)
            return circuit

        elif kind=="basic":
            circuit = Circuit('Biased Envelope Circuit')
            circuit.include(spice_library['hsms'])

            circuit.V('in', 'input', circuit.gnd, 'dc 0 external')
            # envelope portion
            circuit.X('D1', 'hsms', 'input', 'output')
            circuit.C(1, 'output', circuit.gnd, 220@u_pF)
            circuit.R(1, 'output', circuit.gnd, 50@u_Ohm)
            return circuit

        elif kind=="diode":
            circuit = Circuit('Diode Output')
            circuit.include(spice_library['hsms'])
            
            circuit.V('in', 'input', circuit.gnd, 'dc 0 external')
            circuit.X('D1', 'hsms', 'input', 'output')
            return circuit

    performance_test("ng_in = NgSpiceSignal(pulse); "+
                     "simulator = circuit.simulator(temperature=25, "+
                     "nominal_temperature=25, ngspice_shared=ng_in.shared); "+
                     "analysis = simulator.transient(step_time=dt, "+
                     "end_time=pulse.times[-1]); "+
                     "pyrex.Signal(analysis.output.abscissa, analysis.output)",
                     number=10,
                     setup="import pyrex; circuit = setup_circuit()",
                     use_globals={"pulse": pulse, "dt": dt,
                                  "setup_circuit": setup_circuit,
                                  "NgSpiceSignal": NgSpiceSignal},
                     alternate_title="pyrex.Signal(analysis.output.abscissa, "+
                                     "analysis.output)")


    def envelope_circuit(signal, cap=220e-12, res=50):
        v_c = 0
        v_out = []

        r_d = 25
        i_s = 3e-6
        n = 1.06
        v_t = 26e-3

        charge_exp = np.exp(-signal.dt/(res*cap))
        discharge = i_s*res*(1-charge_exp)
        lambert_factor = n*v_t*res/r_d*(1-charge_exp)
        frac = i_s*r_d/n/v_t

        lambert_exponent = np.log(frac) + frac

        for v_in in signal.values:
            a = lambert_exponent + (v_in - v_c)/n/v_t
            if a>100:
                b = np.log(a)
                lambert_term = a - b + b/a
            else:
                lambert_term = np.real(lambertw(np.exp(a)))
                if np.isnan(lambert_term):
                    lambert_term = 0
            v_c = v_c*charge_exp - discharge + lambert_factor*lambert_term
            v_out.append(v_c)

        return pyrex.Signal(signal.times, v_out,
                            value_type=pyrex.Signal.ValueTypes.voltage)


    performance_test("envelope(pulse)",
                     number=100,
                     use_globals={"pulse": pulse, "envelope": envelope_circuit},
                     alternate_title="analytic circuit simulation")
Beispiel #5
0
def test_EventKernel_event(energy=1e6):
    t = 0

    t += performance_test("p = gen.create_particle()", number=100,
                          setup="import pyrex;"+
                                "gen = pyrex.ShadowGenerator(dx=10000, dy=10000, "+
                                "dz=2800, energy_generator=lambda: "+str(energy)+")")

    t += performance_test("n = ice.index(p.vertex[2])", number=1000,
                          setup="import pyrex;"+
                                "import numpy as np;"+
                                "z = np.random.random() * -2800;"+
                                "p = pyrex.Particle(vertex=(0,0,z), direction=(0,0,1), "+
                                "energy="+str(energy)+");"+
                                "ice = pyrex.IceModel();")

    t += performance_test("pf = PathFinder(ice, p.vertex, ant.position)", number=1000,
                          setup="import pyrex;"+
                                "from pyrex import PathFinder;"
                                "import numpy as np;"+
                                "z = np.random.random() * -2800;"+
                                "p = pyrex.Particle(vertex=(0,0,z), direction=(0,0,1), "+
                                "energy="+str(energy)+");"+
                                "ice = pyrex.IceModel();"+
                                "ant = pyrex.DipoleAntenna(name='ant', position=(5000,5000,-200), "+
                                "center_frequency=250, bandwidth=100, resistance=None, "+
                                "effective_height=1.0, trigger_threshold=3*(12e-6), noisy=False)")

    ice = pyrex.IceModel()
    ant = pyrex.DipoleAntenna(name='ant', position=(5000,5000,-200),
                              center_frequency=250e6, bandwidth=100e6, resistance=None,
                              effective_height=1, trigger_threshold=36e-6, noisy=False)
    def get_good_path():
        z = np.random.random() * -2800
        p = pyrex.Particle(vertex=(0,0,z), direction=(0,0,1), energy=energy)
        pf = pyrex.PathFinder(ice, p.vertex, ant.position)
        k = pf.emitted_ray
        epol = np.vdot(k, p.direction) * k - p.direction
        epol = epol / np.linalg.norm(epol)
        psi = np.arccos(np.vdot(p.direction, k))
        if pf.exists and psi<np.pi/2:
            return p, pf, psi
        else:
            return get_good_path()

    p, pf, psi = get_good_path()

    t_loop = 0

    t_loop += performance_test("pf.exists", number=1000, use_globals={"pf": pf})
    print("  * ~1000 antennas")

    t_loop += performance_test("k = pf.emitted_ray; "+
                               "epol = np.vdot(k, p.direction) * k - p.direction; "+
                               "epol = epol / np.linalg.norm(epol); "+
                               "psi = np.arccos(np.vdot(p.direction, k))", number=1000,
                               setup="import numpy as np",
                               use_globals={"p": p, "pf": pf},
                               alternate_title="Set k, epol, psi")
    print("  * ~1000 antennas")

    t_loop += performance_test("times = np.linspace(-20e-9, 80e-9, 2048, endpoint=False)",
                               number=1000, setup="import numpy as np")
    print("  * ~1000 antennas")

    t_loop += performance_test("pulse = AskaryanSignal(times=times, energy=p.energy, "+
                               "theta=psi, n=n)", number=100,
                               setup="import numpy as np;"+
                                     "from pyrex import AskaryanSignal;"+
                                     "times = np.linspace(-20e-9, 80e-9, 2048, endpoint=False)",
                               use_globals={"p": p, "pf": pf, "psi": psi,
                                            "n": ice.index(p.vertex[2])})
    print("  * ~1000 antennas")

    times = np.linspace(-20e-9, 80e-9, 2048, endpoint=False)
    pulse = pyrex.AskaryanSignal(times=times, energy=p.energy*1e-3,
                                 theta=psi, n=ice.index(p.vertex[2]))

    t_loop += performance_test("pf.propagate(pulse)", repeats=100,
                               setup="import numpy as np;"+
                                     "import pyrex;"+
                                     "times = np.linspace(-20e-9, 80e-9, 2048, endpoint=False);"+
                                     "pulse = pyrex.AskaryanSignal(times=times, "+
                                     "energy=p.energy, theta=psi, n=n)",
                               use_globals={"p": p, "pf": pf, "psi": psi,
                                            "n": ice.index(p.vertex[2])})
    print("  * ~1000 antennas")

    t_loop += performance_test("ant.receive(pulse)", repeats=100,
                               setup="import numpy as np;"+
                                     "import pyrex;"+
                                     "times = np.linspace(-20e-9, 80e-9, 2048, endpoint=False);"+
                                     "pulse = pyrex.AskaryanSignal(times=times, "+
                                     "energy=p.energy, theta=psi, n=n)",
                               use_globals={"p": p, "pf": pf, "psi": psi,
                                            "n": ice.index(p.vertex[2]),
                                            "ant": ant})
    print("  * ~1000 antennas")


    print("Total time:", round(t+t_loop*800,1), "seconds per event on average")
Beispiel #6
0
import matplotlib.pyplot as plt
import pyrex

# First, set up a neutrino source and find the index of refraction at its depth.
# Then use that index of refraction to calculate the Cherenkov angle.
source = pyrex.Particle("nu_e", vertex=(0, 0, -1000), direction=(0, 0, -1),
                        energy=1e8)
n = pyrex.ice.index(source.vertex[2])
ch_angle = np.arccos(1/n)

# Now, for a range of dthetas, generate an Askaryan pulse dtheta away from the
# Chereknov angle and plot its frequency spectrum.
for dtheta in np.radians(np.logspace(-1, 1, 5)):
    n_pts = 10001
    pulse = pyrex.AskaryanSignal(times=np.linspace(-20e-9, 80e-9, n_pts),
                                 particle=source,
                                 viewing_angle=ch_angle+dtheta,
                                 viewing_distance=1000)
    plt.plot(pulse.frequencies[:int(n_pts/2)] * 1e-6, # Convert from Hz to MHz
             np.abs(pulse.spectrum)[:int(n_pts/2)],
             label=f"$\\Delta\\theta = {np.degrees(dtheta):.2f}$")
plt.legend(loc='upper right')
plt.title("Frequency Spectrum of Askaryan Pulse\n"+
          "For Different Off-Cone Angles")
plt.xlabel("Frequency (MHz)")
plt.xlim(0, 3000)
plt.tight_layout()
plt.show()

# Actually, we probably really want to see the frequency content after the
# signal has propagated through the ice a bit. So first set up the ray tracer
# from our neutrino source to some other point where our antenna might be