def test_AdvectivePropagation(self):

        ConstMagVec = crpropa.Vector3d(0.)
        BField = crpropa.UniformMagneticField(ConstMagVec)

        ConstAdvVec = crpropa.Vector3d(0., 1e6, 0.)
        AdvField = crpropa.UniformAdvectionField(ConstAdvVec)

        precision = 1e-4
        minStep = 1*pc
        maxStep = 10*kpc
        epsilon = 0.

        Dif = crpropa.DiffusionSDE(BField, AdvField, precision, minStep, maxStep, epsilon)
        c = crpropa.Candidate()
        c.current.setId(crpropa.nucleusId(1,1))
        c.current.setEnergy(10*TeV)
        c.current.setDirection(crpropa.Vector3d(1,0,0))

        # check for position
        Dif.process(c)
        pos = c.current.getPosition()
        self.assertEqual(pos.x, 0.)
        self.assertAlmostEqual(pos.y, minStep/c_light*1e6)
        self.assertEqual(pos.z, 0.)

        # Step size is increased to maxStep
        self.assertAlmostEqual(c.getNextStep()/minStep, 5.) #AlmostEqual due to rounding error
Exemple #2
0
    def compute_field(self, seed):
        # Extracts grid information
        assert self.grid.grid_type == 'cartesian', 'Only cartesian grids are supported'
        box = self.grid.box
        boxOrigin = crp.Vector3d(box[0][0].si.value, box[1][0].si.value,
                                 box[2][0].si.value)
        boxEnd = crp.Vector3d(box[0][1].si.value, box[1][1].si.value,
                              box[2][1].si.value)
        gridPoints = crp.Vector3d(*self.grid.resolution.astype(float))
        gridSpacing = (boxEnd - boxOrigin) / gridPoints

        # Creates CRPropa-compatible grid object
        boxSize = [int(i) for i in self.grid.resolution]
        self._crp_grid = crp.Grid3f(boxOrigin, *boxSize, gridSpacing)

        # CRPropa uses units in SI internally
        # and SWIG does not like numpy types
        Brms = float(self.parameters['Brms'].si.value)
        minScale = float(self.parameters['min_scale'].si.value)
        maxScale = float(self.parameters['max_scale'].si.value)
        alpha = float(self.parameters['alpha'])
        seed = int(seed)
        helicity_factor = float(self.parameters['helicity_factor'])

        # Initializes the field generator
        print(self._crp_grid,
              Brms,
              minScale / crp.kpc,
              maxScale / crp.Mpc,
              alpha,
              seed,
              helicity_factor,
              sep='\n')
        crp.initHelicalTurbulence(self._crp_grid, Brms, minScale, maxScale,
                                  alpha, seed, helicity_factor)
        crp_field = crp.MagneticFieldGrid(self._crp_grid)

        # Evaluates on the grid
        def mapper(quantities):
            positions = [float(q.si.value) for q in quantities]
            vec = crp_field.getField(crp.Vector3d(*positions))
            return vec[0], vec[1], vec[2]

        field = np.array(
            list(
                map(
                    mapper,
                    zip(self.grid.x.ravel(), self.grid.y.ravel(),
                        self.grid.z.ravel()))))

        return field.reshape(self.data_shape) << u.T
 def testPublicReferenceAccess(self):
     v = crp.Vector3d(1., 2., 3.)
     self.assertEqual(v.x, 1.)
     self.assertEqual(v.y, 2.)
     self.assertEqual(v.z, 3.)
     v.x = 23.
     self.assertEqual(v.x, 23.)
Exemple #4
0
 def testGridTurbulence(self):
     N = 64
     boxSize = 1 * crp.Mpc
     l_bo = boxSize / 8
     spacing = boxSize / N
     tf = crp.GridTurbulence(
         crp.TurbulenceSpectrum(1.0, 2 * spacing, boxSize, l_bo),
         crp.GridProperties(crp.Vector3d(0), N, spacing))
def initial_directions(M, source_l, source_b, weights, d, NN, energies=None):
    lons0 = []
    lats0 = []

    for isource in range(len(source_l)):
        l = source_l[isource] * np.pi / 180.0 - (2.0 * np.pi)
        b = Lat2CoLat(source_b[isource] * np.pi / 180.0)
        #M.addParticles(Id, E, l, b, E0**-1)
        print(isource, weights[isource], l, b)
        meanDir = crpropa.Vector3d(-1, 0, 0)
        meanDir.setRThetaPhi(-1, b, l)
        kappa = 50.0

        ncrs = int((weights[isource] / total) * NN)
        #if ncrs>0: ncrs = 500
        #Emin = 10.0
        energies = powerlaw.Power_Law(xmin=10.0, xmax=100.0,
                                      parameters=[2.2]).generate_random(ncrs)

        #print (energies)
        for i in xrange(ncrs):
            particleId = crpropa.nucleusId(1, 1)
            energy = (energies[i]) * crpropa.EeV

            energy = 10.0 * crpropa.EeV
            galCenter = crpropa.Vector3d(-1, 0, 0)

            theta_k = 0.8 * (100.0 * crpropa.EeV / energy) * np.sqrt(
                d[isource] / 10.0)
            kappa = (81.0 / theta_k)**2
            #print (kappa)

            momentumVector = crpropa.Random.instance().randFisherVector(
                meanDir, kappa)
            M.addParticle(particleId, energy, momentumVector)

            lons0.append(momentumVector.getPhi())
            lats0.append(momentumVector.getTheta())

    lons0 = np.array(lons0) - np.pi
    lats0 = -CoLat2Lat(np.array(lats0))

    return (lons0, lats0)
Exemple #6
0
    def testCustomAdvectionField(self):
        class CustomAdvectionField(crp.AdvectionField):
            def __init__(self, val):
                crp.AdvectionField.__init__(self)
                self.val = val

            def getField(self, position):
                return crp.Vector3d(self.val)

            def getDivergence(self, position):
                return 0.0

        constMagVec = crp.Vector3d(0 * crp.nG, 0 * crp.nG, 1 * crp.nG)
        magField = crp.UniformMagneticField(constMagVec)
        advField = CustomAdvectionField(1)
        propSDE = crp.DiffusionSDE(magField, advField)
        pos = crp.Vector3d(1, 0, 0)
        advFieldAtPos = advField.getField(pos)
        self.assertEqual(advFieldAtPos,
                         propSDE.getAdvectionFieldAtPosition(pos))
    def testAddParticleVectorInterface(self):
        try:
            import numpy as np
        except:
            print("Cannot import numpy. Not testing AddParticleVectorInterface!")
            return

        self.maps.addParticle(12, 1 * EeV, crpropa.Vector3d(1, 0, 0))
        self.assertEquals(len(self.maps.getParticleIds()), 1)
        self.assertEquals(self.maps.getParticleIds()[0], 12)
        self.assertEquals(len(self.maps.getEnergies(12)), 1)
 def testRepr(self):
     v = crp.Vector3d(1., 2., 3.)
     if sys.version_info >= (3, 3):
         import unittest.mock
         import io
         with unittest.mock.patch('sys.stdout',
                                  new=io.StringIO()) as fake_out:
             print(v)
     else:
         import StringIO
         fake_out = StringIO.StringIO()
         sys.stdout = fake_out
         print(v)
         sys.stdout = sys.__stdout__
     self.assertEqual(fake_out.getvalue().rstrip(), v.getDescription())
    def test_NeutralPropagation(self):
        c = crpropa.Candidate()
        c.current.setId(crpropa.nucleusId(1,0))
        c.current.setEnergy(10*TeV)
        c.current.setDirection(crpropa.Vector3d(1,0,0))

        # check for position
        self.Dif.process(c)
        pos = c.current.getPosition()
        self.assertAlmostEqual(pos.x/pc, 1.) #AlmostEqual due to rounding error
        self.assertEqual(pos.y, 0.)
        self.assertEqual(pos.z, 0.)

        # Step size is increased to maxStep
        self.assertAlmostEqual(c.getNextStep()/self.maxStep, 1.) #AlmostEqual due to rounding error
Exemple #10
0
    def testCustomMassDensity(self):
        class CustomMassDensity(crp.Density):
            def __init__(self, density, HIDensity, HIIDensity, H2Density,
                         nucleonDensity):
                crp.Density.__init__(self)
                self.density = density
                self.HIDensity = HIDensity
                self.HIIDensity = HIIDensity
                self.H2Density = H2Density
                self.nucleonDensity = nucleonDensity

            def getDensity(self, position):
                return self.density

            def getHIDensity(self, position):
                return self.HIDensity

            def getHIIDensity(self, position):
                return self.HIIDensity

            def getH2Density(self, position):
                return self.H2Density

            def NucleonDensity(self, position):
                return self.nucleonDensity

        density = 10
        HIDensity = 5
        HIIDensity = 2
        H2Density = 1
        nucleonDensity = 0.5
        massDensity = CustomMassDensity(density, HIDensity, HIIDensity,
                                        H2Density, nucleonDensity)
        pos = crp.Vector3d(1, 0, 0)
        self.assertEqual(density, massDensity.getDensity(pos))
        self.assertEqual(HIDensity, massDensity.getHIDensity(pos))
        self.assertEqual(HIIDensity, massDensity.getHIIDensity(pos))
        self.assertEqual(H2Density, massDensity.getH2Density(pos))
Exemple #11
0
    def testCustomMagneticField(self):
        class CustomMagneticField(crp.MagneticField):
            def __init__(self, val):
                crp.MagneticField.__init__(self)
                self.val = val

            def getField(self, position):
                return crp.Vector3d(self.val)

            def getField(self, position, z):
                return crp.Vector3d(self.val)

        field = CustomMagneticField(crp.gauss)
        propBP = crp.PropagationBP(field, 1e-4, 1 * crp.Mpc, 1 * crp.Mpc)
        propCK = crp.PropagationCK(field, 1e-4, 1 * crp.Mpc, 1 * crp.Mpc)
        propSDE = crp.DiffusionSDE(field)
        pos = crp.Vector3d(-1, 0, 0)
        z = 0
        fieldAtPos = field.getField(pos, z)
        self.assertEqual(fieldAtPos, propBP.getFieldAtPosition(pos, z))
        self.assertEqual(fieldAtPos, propCK.getFieldAtPosition(pos, z))
        self.assertEqual(fieldAtPos,
                         propSDE.getMagneticFieldAtPosition(pos, z))
Exemple #12
0
 def getField(self, position, z):
     return crp.Vector3d(self.val)
 def testArrayInterface(self):
     if numpy_available:
         v = crp.Vector3d(1., 2., 3.)
         self.assertEqual(2., np.mean(v))
         x = np.ones(3)
         self.assertEqual(6., sum(v * x))
    def test_FullTransport(self):
        x, y, z = [], [], []
        E = 10 * TeV
        D = self.DifAdv.getScale()*6.1e24*(E/(4*GeV))**self.DifAdv.getAlpha()
        L_max = 50 * kpc
        epsilon = 0.1
        advSpeed = 1e6

        std_exp_x = np.sqrt(2*epsilon*D*L_max/c_light)
        std_exp_y = np.sqrt(2*epsilon*D*L_max/c_light)
        std_exp_z = np.sqrt(2*D*L_max/c_light)
        mean_exp_x = advSpeed * L_max / c_light
        mean_exp_y = 0.
        mean_exp_z = 0.

        N = 10**4

        maxTra = crpropa.MaximumTrajectoryLength(L_max)

        ConstMagVec = crpropa.Vector3d(0*nG,0*nG,1*nG)
        BField = crpropa.UniformMagneticField(ConstMagVec)

        ConstAdvVec = crpropa.Vector3d(advSpeed, 0., 0.)
        AdvField = crpropa.UniformAdvectionField(ConstAdvVec)

        precision = 1e-4
        minStep = 1*pc
        maxStep = 10*kpc

        DifAdv = crpropa.DiffusionSDE(BField, AdvField, precision, minStep, maxStep, epsilon)


        for i in range(N):
            c = crpropa.Candidate()
            c.current.setId(crpropa.nucleusId(1,1))
            c.current.setEnergy(E)
            while c.getTrajectoryLength() < L_max:
                maxTra.process(c)
                DifAdv.process(c)
            x.append(c.current.getPosition().x)
            y.append(c.current.getPosition().y)
            z.append(c.current.getPosition().z)

        # test for normality
        A2 = Anderson(x)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        A2 = Anderson(y)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        A2 = Anderson(z)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)

        meanX, meanY, meanZ = np.mean(x), np.mean(y), np.mean(z)
        stdX, stdY, stdZ = np.std(x), np.std(y), np.std(z)


        # diffusion in parallel direction
        # compare the mean and std of the z-positions with expected values
        # z_mean = 0. (no advection)
        # z_ std = (2*D_parallel*t)^0.5
        # Take 4 sigma errors due to limited number of candidates into account
        stdOfMeans_x = std_exp_x/np.sqrt(N)
        stdOfStds_x = std_exp_x/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanX-mean_exp_x)/4./stdOfMeans_x), 1., msg=self.msg1)
        self.assertLess(abs((stdX-std_exp_x)/4./stdOfStds_x), 1., msg=self.msg1)

        stdOfMeans_y = std_exp_y/np.sqrt(N)
        stdOfStds_y = std_exp_y/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanY-mean_exp_y)/4./stdOfMeans_y), 1., msg=self.msg1)
        self.assertLess(abs((stdY-std_exp_y)/4./stdOfStds_y), 1., msg=self.msg1)

        stdOfMeans_z = std_exp_z/np.sqrt(N)
        stdOfStds_z = std_exp_z/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanZ-mean_exp_z)/4./stdOfMeans_z), 1., msg=self.msg1)
        self.assertLess(abs((stdZ-std_exp_z)/4./stdOfStds_z), 1., msg=self.msg1)
Exemple #15
0
E = crdata[:, 3] * crpropa.EeV
E0 = crdata[:, 4] * crpropa.EeV
px = crdata[:, 11]
py = crdata[:, 12]
pz = crdata[:, 13]
galactic_longitude = np.arctan2(-1. * py, -1. * px)
galactic_latitude = np.pi / 2 - np.arccos(-pz / (px * px + py * py + pz * pz))

M.addParticles(id, E, galactic_longitude, galactic_latitude, E0**-1)

# Alternatively, data can be added manually.
# This provides freedom to adapt to customized weights used in the simulation
for i in xrange(1000):
    particleId = crpropa.nucleusId(1, 1)
    energy = 10 * crpropa.EeV
    galCenter = crpropa.Vector3d(-1, 0, 0)
    momentumVector = crpropa.Random.instance().randFisherVector(galCenter, 200)
    M.addParticle(particleId, energy, momentumVector)

# ## Plot Maps
#
# The probability maps for the individual particles can be accessed directly and plotted with healpy.
#

# In[2]:

get_ipython().magic('matplotlib inline')

import healpy
from pylab import *
draw_map_lines()
plt.savefig("fig/earth_data.eps", bbox_inches="tight")
plt.clf()

# crpropa backtracking
# set up GMF
B = crp.JF12Field()
B.randomStriated(seed)
B.randomTurbulent(seed)

# set up simulation
sim = crp.ModuleList()
sim.add(crp.PropagationCK(B, 1e-3, 0.1 * crp.parsec, 100 * crp.parsec))
obs = crp.Observer()
obs.add(crp.ObserverLargeSphere(crp.Vector3d(0), gal_size * crp.kpc))
sim.add(obs)

position = crp.Vector3d(-8.5, 0, 0) * crp.kpc  # start at the earth

pid = crp.nucleusId(1, 1)  # proton
pid *= -1  # antiparticle, for backtracking

if read_in_galaxy_map:
    galaxy_map = np.genfromtxt("maps/galaxy_map.txt")
else:
    galaxy_map = np.zeros(hp.nside2npix(nside))
    for i in xrange(len(events)):
        if i % 10 == 0: print i, len(events)
        event = events[i]
        if event["is_Auger"]:
Exemple #17
0
 def testGridPropertiesConstructor(self):
     N = 32
     gp = crp.GridProperties(crp.Vector3d(0), N, 0.1)
     grid = crp.Grid1f(gp)
     self.assertEqual(grid.getNx(), 32)
Exemple #18
0
import healpy as hp

a1, b1 = (12.6 - 18.25) / 2.75, (19.5 - 18.25) / 2.75
a2, b2 = (0. - 0.2) / 0.12, (1 - 0.2) / 0.12
a3, b3 = (0 - 10.97) / 3.80, (25. - 10.97) / 3.8
a4, b4 = (0 - 2.84) / 1.3, (8 - 2.84) / 1.3

E = float(sys.argv[1])
lon = float(sys.argv[2])
lat = float(sys.argv[3])
s1 = int(sys.argv[4])
s2 = int(sys.argv[5])
s3 = int(sys.argv[6])

pid = -crp.nucleusId(1, 1)
sun = crp.Vector3d(-8.5, 0, 0) * crp.kpc

E = E * crp.EeV
nhat = hp.dir2vec(lon, lat, lonlat=True)
direc = crp.Vector3d()
direc.setXYZ(nhat[0], nhat[1], nhat[2])

ps = crp.ParticleState(pid, E, sun, direc)
cr = crp.Candidate(ps)
sim = crp.ModuleList()
sim.add(crp.Redshift())
sim.add(crp.PhotoPionProduction(crp.CMB))
sim.add(crp.PhotoPionProduction(crp.IRB))
sim.add(crp.PhotoDisintegration(crp.CMB))
sim.add(crp.PhotoDisintegration(crp.IRB))
sim.add(crp.NuclearDecay())
Exemple #19
0
 def mapper(quantities):
     positions = [float(q.si.value) for q in quantities]
     vec = crp_field.getField(crp.Vector3d(*positions))
     return vec[0], vec[1], vec[2]
Exemple #20
0
 def testOutOfBound(self):
     v = crp.Vector3d(1., 2., 3.)
     self.assertRaises(IndexError, v.__getitem__, 3)
     self.assertRaises(IndexError, v.__setitem__, 3, 10)
        candidate.limitNextStep(abs(currentDistance))

        if np.sign(currentDistance) == np.sign(previousDistance):
            return crpropa.NOTHING
        else:
            return crpropa.DETECTED


# As test, we propagate some particels in a random field with a sheet observer:

# In[2]:

from crpropa import Mpc, nG, EeV
import numpy as np

vgrid = crpropa.VectorGrid(crpropa.Vector3d(0), 128, 1 * Mpc)
crpropa.initTurbulence(vgrid, 1 * nG, 2 * Mpc, 5 * Mpc, -11. / 3.)
BField = crpropa.MagneticFieldGrid(vgrid)

m = crpropa.ModuleList()
m.add(crpropa.PropagationCK(BField, 1e-4, 0.1 * Mpc, 5 * Mpc))
m.add(crpropa.MaximumTrajectoryLength(25 * Mpc))

# Observer
out = crpropa.TextOutput("sheet.txt")
o = crpropa.Observer()
# The Observer feature has to be created outside of the class attribute
# o.add(ObserverPlane(...)) will not work for custom python modules
plo = ObserverPlane(
    np.asarray([0., 0, 0]) * Mpc,
    np.asarray([0., 1., 0.]) * Mpc,
# In[1]:

import crpropa
import numpy as np

n = 10000000

# simulation setup
sim = crpropa.ModuleList()
# we just need propagation in straight lines here to demonstrate the effect
sim.add(crpropa.SimplePropagation())

# collect arriving cosmic rays at observer 19 kpc outside of the Galactic center
# to exaggerate effects
obs = crpropa.Observer()
pos_earth = crpropa.Vector3d(-19, 0, 0) * crpropa.kpc
# observer with radius 500 pc to collect fast reasonable statistics
obs.add(crpropa.ObserverSurface(crpropa.Sphere(pos_earth, 0.5 * crpropa.kpc)))
# Use crpropa's particle collector to only collect the cosmic rays at Earth
output = crpropa.ParticleCollector()
obs.onDetection(output)
sim.add(obs)

# discard outwards going cosmic rays, that missed Earth and leave the Galaxy
obs_trash = crpropa.Observer()
obs_trash.add(
    crpropa.ObserverSurface(
        crpropa.Sphere(crpropa.Vector3d(0), 21 * crpropa.kpc)))
sim.add(obs_trash)

# ## Lambert's distribution
class DiffusionOneDirection(unittest.TestCase):

    ConstMagVec = crpropa.Vector3d(0*nG,0*nG,1*nG)
    BField = crpropa.UniformMagneticField(ConstMagVec)

    precision = 1e-4
    minStep = 1*pc
    maxStep = 10*kpc
    epsilon = 0.

    Dif = crpropa.DiffusionSDE(BField, precision, minStep, maxStep, epsilon)
    DifAdv = crpropa.DiffusionSDE(BField, precision, minStep, maxStep, epsilon)

    def test_Simple(self):
        self.assertEqual(self.Dif.getTolerance(), self.precision)
        self.assertEqual(self.Dif.getMinimumStep(), self.minStep)
        self.assertEqual(self.Dif.getMaximumStep(), self.maxStep)
        self.assertEqual(self.Dif.getEpsilon(), self.epsilon)
        self.assertEqual(self.Dif.getAlpha(), 1./3.) # default Kolmogorov diffusion
        self.assertEqual(self.Dif.getScale(), 1.) # default D(4GeV) = 6.1e28 cm^2/s

    def test_NeutralPropagation(self):
        c = crpropa.Candidate()
        c.current.setId(crpropa.nucleusId(1,0))
        c.current.setEnergy(10*TeV)
        c.current.setDirection(crpropa.Vector3d(1,0,0))

        # check for position
        self.Dif.process(c)
        pos = c.current.getPosition()
        self.assertAlmostEqual(pos.x/pc, 1.) #AlmostEqual due to rounding error
        self.assertEqual(pos.y, 0.)
        self.assertEqual(pos.z, 0.)

        # Step size is increased to maxStep
        self.assertAlmostEqual(c.getNextStep()/self.maxStep, 1.) #AlmostEqual due to rounding error

    def test_NoBFieldPropagation(self):

        ConstMagVec = crpropa.Vector3d(0.)
        BField = crpropa.UniformMagneticField(ConstMagVec)

        precision = 1e-4
        minStep = 1*pc
        maxStep = 10*kpc
        epsilon = 0.

        Dif = crpropa.DiffusionSDE(BField, precision, minStep, maxStep, epsilon)
        c = crpropa.Candidate()
        c.current.setId(crpropa.nucleusId(1,1))
        c.current.setEnergy(10*TeV)
        c.current.setDirection(crpropa.Vector3d(1,0,0))

        # check for position
        Dif.process(c)
        pos = c.current.getPosition()
        self.assertAlmostEqual(pos.x/pc, 1.) #AlmostEqual due to rounding error
        self.assertEqual(pos.y, 0.)
        self.assertEqual(pos.z, 0.)

        # Step size is increased to maxStep
        self.assertAlmostEqual(c.getNextStep()/minStep, 5.) #AlmostEqual due to rounding error


    def test_AdvectivePropagation(self):

        ConstMagVec = crpropa.Vector3d(0.)
        BField = crpropa.UniformMagneticField(ConstMagVec)

        ConstAdvVec = crpropa.Vector3d(0., 1e6, 0.)
        AdvField = crpropa.UniformAdvectionField(ConstAdvVec)

        precision = 1e-4
        minStep = 1*pc
        maxStep = 10*kpc
        epsilon = 0.

        Dif = crpropa.DiffusionSDE(BField, AdvField, precision, minStep, maxStep, epsilon)
        c = crpropa.Candidate()
        c.current.setId(crpropa.nucleusId(1,1))
        c.current.setEnergy(10*TeV)
        c.current.setDirection(crpropa.Vector3d(1,0,0))

        # check for position
        Dif.process(c)
        pos = c.current.getPosition()
        self.assertEqual(pos.x, 0.)
        self.assertAlmostEqual(pos.y, minStep/c_light*1e6)
        self.assertEqual(pos.z, 0.)

        # Step size is increased to maxStep
        self.assertAlmostEqual(c.getNextStep()/minStep, 5.) #AlmostEqual due to rounding error

    msg1 = "Note that this is a statistical test. It might fail by chance with a probabilty O(0.00001)! You should rerun the test to make sure there is a bug."

    def test_DiffusionEnergy10TeV(self):
        x, y, z = [], [], []
        E = 10 * TeV
        D = self.Dif.getScale()*6.1e24*(E/(4*GeV))**self.Dif.getAlpha()
        L_max = 50 * kpc
        std_exp = np.sqrt(2*D*L_max/c_light)
        mean_exp = 0.
        N = 10**4

        maxTra = crpropa.MaximumTrajectoryLength(L_max)

        for i in range(N):
            c = crpropa.Candidate()
            c.current.setId(crpropa.nucleusId(1,1))
            c.current.setEnergy(E)
            while c.getTrajectoryLength() < L_max:
                maxTra.process(c)
                self.Dif.process(c)
                x.append(c.current.getPosition().x)
                y.append(c.current.getPosition().y)
            z.append(c.current.getPosition().z)
        A2 = Anderson(z)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        meanX, meanY, meanZ = np.mean(x), np.mean(y), np.mean(z)
        stdZ = np.std(z)

        # no diffusion in perpendicular direction
        self.assertAlmostEqual(meanX, 0.)
        self.assertAlmostEqual(meanY, 0.)

        # diffusion in parallel direction
        # compare the mean and std of the z-positions with expected values
        # z_mean = 0. (no advection)
        # z_ std = (2*D_parallel*t)^0.5
        # Take 4 sigma errors due to limited number of candidates into account
        stdOfMeans = std_exp/np.sqrt(N)
        stdOfStds = std_exp/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanZ-mean_exp)/4./stdOfMeans), 1., msg=self.msg1)
        self.assertLess(abs((stdZ-std_exp)/4./stdOfStds), 1., msg=self.msg1)


    def test_DiffusionEnergy1PeV(self):
        x, y, z = [], [], []
        E = 1 * TeV
        D = self.Dif.getScale()*6.1e24*(E/(4*GeV))**self.Dif.getAlpha()
        L_max = 50 * kpc
        std_exp = np.sqrt(2*D*L_max/c_light)
        mean_exp = 0.
        N = 10**4

        maxTra = crpropa.MaximumTrajectoryLength(L_max)

        for i in range(N):
            c = crpropa.Candidate()
            c.current.setId(crpropa.nucleusId(1,1))
            c.current.setEnergy(E)
            while c.getTrajectoryLength() < L_max:
                maxTra.process(c)
                self.Dif.process(c)
                x.append(c.current.getPosition().x)
                y.append(c.current.getPosition().y)
            z.append(c.current.getPosition().z)
        A2 = Anderson(z)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        meanX, meanY, meanZ = np.mean(x), np.mean(y), np.mean(z)
        stdZ = np.std(z)

        # no diffusion in perpendicular direction
        self.assertAlmostEqual(meanX, 0.)
        self.assertAlmostEqual(meanY, 0.)

        # diffusion in parallel direction
        # compare the mean and std of the z-positions with expected values
        # z_mean = 0. (no advection)
        # z_ std = (2*D_parallel*t)^0.5
        # Take 4 sigma errors due to limited number of candidates into account
        stdOfMeans = std_exp/np.sqrt(N)
        stdOfStds = std_exp/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanZ-mean_exp)/4./stdOfMeans), 1., msg=self.msg1)
        self.assertLess(abs((stdZ-std_exp)/4./stdOfStds), 1., msg=self.msg1)

    def test_DiffusionEnergy100PeV(self):
        x, y, z = [], [], []
        E = 10 * PeV
        D = self.Dif.getScale()*6.1e24*(E/(4*GeV))**self.Dif.getAlpha()
        L_max = 50 * kpc
        std_exp = np.sqrt(2*D*L_max/c_light)
        mean_exp = 0.
        N = 10**4

        maxTra = crpropa.MaximumTrajectoryLength(L_max)

        for i in range(N):
            c = crpropa.Candidate()
            c.current.setId(crpropa.nucleusId(1,1))
            c.current.setEnergy(E)
            while c.getTrajectoryLength() < L_max:
                maxTra.process(c)
                self.Dif.process(c)
                x.append(c.current.getPosition().x)
                y.append(c.current.getPosition().y)
            z.append(c.current.getPosition().z)
        A2 = Anderson(z)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        meanX, meanY, meanZ = np.mean(x), np.mean(y), np.mean(z)
        stdZ = np.std(z)

        # no diffusion in perpendicular direction
        self.assertAlmostEqual(meanX, 0.)
        self.assertAlmostEqual(meanY, 0.)

        # diffusion in parallel direction
        # compare the mean and std of the z-positions with expected values
        # z_mean = 0. (no advection)
        # z_ std = (2*D_parallel*t)^0.5
        # Take 4 sigma errors due to limited number of candidates into account
        stdOfMeans = std_exp/np.sqrt(N)
        stdOfStds = std_exp/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanZ-mean_exp)/4./stdOfMeans), 1., msg=self.msg1)
        self.assertLess(abs((stdZ-std_exp)/4./stdOfStds), 1., msg=self.msg1)


    def test_FullTransport(self):
        x, y, z = [], [], []
        E = 10 * TeV
        D = self.DifAdv.getScale()*6.1e24*(E/(4*GeV))**self.DifAdv.getAlpha()
        L_max = 50 * kpc
        epsilon = 0.1
        advSpeed = 1e6

        std_exp_x = np.sqrt(2*epsilon*D*L_max/c_light)
        std_exp_y = np.sqrt(2*epsilon*D*L_max/c_light)
        std_exp_z = np.sqrt(2*D*L_max/c_light)
        mean_exp_x = advSpeed * L_max / c_light
        mean_exp_y = 0.
        mean_exp_z = 0.

        N = 10**4

        maxTra = crpropa.MaximumTrajectoryLength(L_max)

        ConstMagVec = crpropa.Vector3d(0*nG,0*nG,1*nG)
        BField = crpropa.UniformMagneticField(ConstMagVec)

        ConstAdvVec = crpropa.Vector3d(advSpeed, 0., 0.)
        AdvField = crpropa.UniformAdvectionField(ConstAdvVec)

        precision = 1e-4
        minStep = 1*pc
        maxStep = 10*kpc

        DifAdv = crpropa.DiffusionSDE(BField, AdvField, precision, minStep, maxStep, epsilon)


        for i in range(N):
            c = crpropa.Candidate()
            c.current.setId(crpropa.nucleusId(1,1))
            c.current.setEnergy(E)
            while c.getTrajectoryLength() < L_max:
                maxTra.process(c)
                DifAdv.process(c)
            x.append(c.current.getPosition().x)
            y.append(c.current.getPosition().y)
            z.append(c.current.getPosition().z)

        # test for normality
        A2 = Anderson(x)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        A2 = Anderson(y)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)
        A2 = Anderson(z)['testStatistic']
        self.assertLess(A2, 2.274, msg=self.msg1)

        meanX, meanY, meanZ = np.mean(x), np.mean(y), np.mean(z)
        stdX, stdY, stdZ = np.std(x), np.std(y), np.std(z)


        # diffusion in parallel direction
        # compare the mean and std of the z-positions with expected values
        # z_mean = 0. (no advection)
        # z_ std = (2*D_parallel*t)^0.5
        # Take 4 sigma errors due to limited number of candidates into account
        stdOfMeans_x = std_exp_x/np.sqrt(N)
        stdOfStds_x = std_exp_x/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanX-mean_exp_x)/4./stdOfMeans_x), 1., msg=self.msg1)
        self.assertLess(abs((stdX-std_exp_x)/4./stdOfStds_x), 1., msg=self.msg1)

        stdOfMeans_y = std_exp_y/np.sqrt(N)
        stdOfStds_y = std_exp_y/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanY-mean_exp_y)/4./stdOfMeans_y), 1., msg=self.msg1)
        self.assertLess(abs((stdY-std_exp_y)/4./stdOfStds_y), 1., msg=self.msg1)

        stdOfMeans_z = std_exp_z/np.sqrt(N)
        stdOfStds_z = std_exp_z/np.sqrt(N)/np.sqrt(2.)
        self.assertLess(abs((meanZ-mean_exp_z)/4./stdOfMeans_z), 1., msg=self.msg1)
        self.assertLess(abs((stdZ-std_exp_z)/4./stdOfStds_z), 1., msg=self.msg1)