Esempio n. 1
0
    def test_value(self):
        density = lambda x, y, z: 6e19 * (1 + 0.1 * np.sin(x) * np.sin(y) * np.
                                          sin(z))  # m^-3
        temperature = lambda x, y, z: 3e3 * (1 + 0.1 * np.sin(x + 1) * np.sin(
            y + 1) * np.sin(z + 1))  # eV
        velocity = lambda x, y, z: 1.6e5 * (1 + 0.1 * np.sin(x + 2) * np.sin(
            y + 2) * np.sin(z + 2)) * Vector3D(1, 2, 3).normalise()  # m/s
        mass = 4 * atomic_mass  # kg
        maxwellian = Maxwellian(density, temperature, velocity, mass)

        sigma = lambda x, y, z: np.sqrt(
            temperature(x, y, z) * elementary_charge / mass)  # m/s
        phase_space_density = lambda x, y, z, vx, vy, vz: density(x, y, z) / (np.sqrt(2 * np.pi) * sigma(x, y, z)) ** 3 \
                                                          * np.exp(-(Vector3D(vx, vy, vz) - velocity(x, y, z)).length ** 2 / (2 * sigma(x, y, z) ** 2))  # s^3/m^6

        # testing only half the values to avoid huge execution time
        for x in self.x[::2]:
            for y in self.y[::2]:
                for z in self.z[::2]:
                    for vx in self.vx[::2]:
                        for vy in self.vy[::2]:
                            for vz in self.vz[::2]:
                                self.assertAlmostEqual(
                                    maxwellian(x, y, z, vx, vy, vz),
                                    phase_space_density(x, y, z, vx, vy, vz),
                                    delta=1e-10,
                                    msg=
                                    'call method gives a wrong phase space density at ({}, {}, {}, {}, {}, {}).'
                                    .format(x, y, z, vx, vy, vz))
Esempio n. 2
0
 def point(self, value):
     if not (self._direction.x == 0 and self._direction.y == 0
             and self._direction.z == 1):
         up = Vector3D(0, 0, 1)
     else:
         up = Vector3D(1, 0, 0)
     self._point = value
     self._observer.transform = translate(
         value.x, value.y, value.z) * rotate_basis(self._direction, up)
Esempio n. 3
0
 def direction(self, value):
     if value.x != 0 and value.y != 0 and value.z != 1:
         up = Vector3D(0, 0, 1)
     else:
         up = Vector3D(1, 0, 0)
     self._direction = value
     self._observer.transform = translate(self._point.x, self._point.y,
                                          self._point.z) * rotate_basis(
                                              value, up)
Esempio n. 4
0
def load_dms_output(config, world, plasma, spec, fibgeom):
    from raysect.optical.observer import FibreOptic, PowerPipeline0D, SpectralRadiancePipeline0D
    from raysect.optical import translate, rotate, rotate_basis
    from raysect.core import Vector3D, Point3D

    power_arr = np.zeros(fibgeom.numfibres)
    spectra_arr = np.zeros((spec.pixels, fibgeom.numfibres))

    for i, f in enumerate(power_arr):
        print("Analysing fibre: ", int(i + 1))
        fibgeom.set_fibre(number=int(i + 1))
        start_point = Point3D(fibgeom.origin[0], fibgeom.origin[1],
                              fibgeom.origin[2])
        forward_vector = Vector3D(fibgeom.xhat(), fibgeom.yhat(),
                                  fibgeom.zhat()).normalise()
        up_vector = Vector3D(0, 0, 1.0)
        if config['dms']['power_pipeline']:
            power = PowerPipeline0D()
            fibre = FibreOptic([power],
                               acceptance_angle=1,
                               radius=0.001,
                               spectral_bins=spec.pixels,
                               spectral_rays=1,
                               pixel_samples=5,
                               transform=translate(*start_point) *
                               rotate_basis(forward_vector, up_vector),
                               parent=world)
            fibre.min_wavelength = spec.wlower
            fibre.max_wavelength = spec.wupper
            fibre.observe()
            power_arr[i] = power.value.mean
        else:
            power_arr[i] = None
        if config['dms']['radiance_pipeline']:
            spectra = SpectralRadiancePipeline0D(display_progress=False)
            fibre = FibreOptic([spectra],
                               acceptance_angle=1,
                               radius=0.001,
                               spectral_bins=spec.pixels,
                               spectral_rays=1,
                               pixel_samples=5,
                               transform=translate(*start_point) *
                               rotate_basis(forward_vector, up_vector),
                               parent=world)
            fibre.min_wavelength = spec.wlower
            fibre.max_wavelength = spec.wupper
            fibre.observe()
            spectra_arr[:, i] = spectra.samples.mean
        else:
            spectra_arr[:, i] = None

    return power_arr, spectra_arr
Esempio n. 5
0
def visualise_scenegraph(camera, focal_distance=1, zoom=1):

    if not isinstance(camera, Observer):
        raise TypeError("The vtk visualisation function takes a Raysect Observer object as its argument.")

    world = camera.root

    if not isinstance(world, World):
        raise TypeError("The vtk visualisation function requires the Raysect Observer object to be connected to a valid scene-graph.")

    # Add the actors to the renderer
    renderer = vtk.vtkRenderer()
    renderer.SetBackground(0, 0, 0)
    for child in world.children:
        vtk_element = map_raysect_element_to_vtk(child)
        if isinstance(vtk_element, VTKAssembly):
            renderer.AddActor(vtk_element.assembly)
        else:
            renderer.AddActor(vtk_element.actor)

    axes = vtk.vtkAxesActor()
    renderer.AddActor(axes)

    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(renderer)
    renWin.SetSize(512, 512)

    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    iren.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
    iren.Initialize()

    camera_origin = Point3D(0, 0, 0).transform(camera.transform)
    camera_direction = Vector3D(0, 0, 1).transform(camera.transform)
    up_direction = Vector3D(0, 1, 0).transform(camera.transform)
    focal_point = camera_origin + camera_direction * focal_distance

    vtk_camera = vtk.vtkCamera()
    vtk_camera.SetPosition(camera_origin.x, camera_origin.y, camera_origin.z)
    vtk_camera.SetFocalPoint(focal_point.x, focal_point.y, focal_point.z)
    vtk_camera.SetViewUp(up_direction.x, up_direction.y, up_direction.z)
    vtk_camera.ComputeViewPlaneNormal()
    vtk_camera.SetDistance(focal_distance)
    vtk_camera.Zoom(zoom)
    renderer.SetActiveCamera(vtk_camera)
    renderer.SetBackground(1.0, 0.9688, 0.8594)
    renderer.SetBackground(vtk_colors.GetColor3d("SlateGray"))

    # Start the event loop.
    iren.Start()
Esempio n. 6
0
    def __init__(self, point, direction, parent=None, name=""):

        if not isinstance(point, Point3D):
            raise TypeError(
                "point argument for SpectroscopicSightLine must be of type Point3D."
            )

        if not isinstance(direction, Vector3D):
            raise TypeError(
                "direction argument for SpectroscopicSightLine must be of type Vector3D."
            )

        self._point = Point3D(0, 0, 0)
        self._direction = Vector3D(1, 0, 0)
        self._transform = AffineMatrix3D()

        self._spectral_pipeline = SpectralRadiancePipeline0D(accumulate=False)
        # TODO - carry over wavelength range and resolution settings
        self._observer = SightLine(pipelines=[self._spectral_pipeline],
                                   parent=parent,
                                   name=name)

        self.name = name
        self.point = point
        self.direction = direction
Esempio n. 7
0
def plot_brdf(light_angle):

    light_position = Point3D(np.sin(np.deg2rad(light_angle)), 0,
                             np.cos(np.deg2rad(light_angle)))
    light_direction = origin.vector_to(light_position).normalise()

    phis = np.linspace(0, 360, 200)
    num_phis = len(phis)
    thetas = np.linspace(0, 90, 100)
    num_thetas = len(thetas)

    values = np.zeros((num_thetas, num_phis))
    for i in range(num_thetas):
        for j in range(num_phis):
            theta = np.deg2rad(thetas[i])
            phi = np.deg2rad(phis[j])
            outgoing = Vector3D(
                np.cos(phi) * np.sin(theta),
                np.sin(phi) * np.sin(theta), np.cos(theta))
            values[i, j] = aluminium.bsdf(light_direction, outgoing, 500.0)

    fig, ax = plt.subplots(subplot_kw=dict(projection='polar'))
    cs = ax.contourf(np.deg2rad(phis), thetas, values, extend="both")
    cs.cmap.set_under('k')
    plt.title("Light angle: {} degrees".format(light_angle))
Esempio n. 8
0
def calculate_brdf_surface(light_vector):

    thetas = np.arange(0, 91, step=5)
    num_thetas = len(thetas)
    phis = np.arange(0, 361, step=10)
    num_phis = len(phis)
    thetas, phis = np.meshgrid(thetas, phis)

    X = np.zeros((num_phis, num_thetas))
    Y = np.zeros((num_phis, num_thetas))
    Z = np.zeros((num_phis, num_thetas))

    for i in range(num_phis):
        for j in range(num_thetas):

            theta = np.deg2rad(thetas[i, j])
            phi = np.deg2rad(phis[i, j])
            outgoing = Vector3D(
                np.cos(phi) * np.sin(theta),
                np.sin(phi) * np.sin(theta), np.cos(theta))

            radius = aluminium.bsdf(light_vector, outgoing, 500)
            X[i, j] = radius * np.cos(phi) * np.sin(theta)
            Y[i, j] = radius * np.sin(phi) * np.sin(theta)
            Z[i, j] = radius * np.cos(theta)

    return X, Y, Z
Esempio n. 9
0
    def test_bulk_velocity(self):
        density = lambda x, y, z: 6e19 * (1 + 0.1 * np.sin(x) * np.sin(y) * np.
                                          sin(z))  # m^-3
        temperature = lambda x, y, z: 3e3 * (1 + 0.1 * np.sin(x + 1) * np.sin(
            y + 1) * np.sin(z + 1))  # eV
        velocity = lambda x, y, z: 1.6e5 * (1 + 0.1 * np.sin(x + 2) * np.sin(
            y + 2) * np.sin(z + 2)) * Vector3D(1, 2, 3).normalise()  # m/s
        mass = 4 * atomic_mass  # kg
        maxwellian = Maxwellian(density, temperature, velocity, mass)

        for x in self.x:
            for y in self.y:
                for z in self.z:
                    self.assertAlmostEqual(
                        maxwellian.bulk_velocity(x, y, z).x,
                        velocity(x, y, z).x,
                        delta=1e-10,
                        msg=
                        'bulk_velocity method gives a wrong value at ({}, {}, {}).'
                        .format(x, y, z))
                    self.assertAlmostEqual(
                        maxwellian.bulk_velocity(x, y, z).y,
                        velocity(x, y, z).y,
                        delta=1e-10,
                        msg=
                        'bulk_velocity method gives a wrong value at ({}, {}, {}).'
                        .format(x, y, z))
                    self.assertAlmostEqual(
                        maxwellian.bulk_velocity(x, y, z).z,
                        velocity(x, y, z).z,
                        delta=1e-10,
                        msg=
                        'bulk_velocity method gives a wrong value at ({}, {}, {}).'
                        .format(x, y, z))
Esempio n. 10
0
    def __call__(self, x, y, z):

        direction = Vector3D(1, 0, 0)
        spectrum = Spectrum(400, 750, 1)
        observed = self.model.emission(Point3D(x, y, z), direction, spectrum)

        return observed.total()
Esempio n. 11
0
    def test_no_distribution_setter(self):
        species = Species(elements.carbon, 3, self.get_maxwellian())

        with self.assertRaises(
                AttributeError,
                msg=
                'It must not be possible to change the distribution of a species!'
        ):
            species.distribution = Maxwellian(
                lambda x, y, z: 2e20, lambda x, y, z: 3e3,
                lambda x, y, z: Vector3D(1.6e5, 0, 0), 4.1 * atomic_mass)
Esempio n. 12
0
def vectorfunction3d(x, y, z):

    r = sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)

    b_mag = 1 / r

    b_vec = Vector3D(r * np.cos(phi), r * np.sin(phi), 0)
    b_vec = b_vec.transform(rotate_z(90))
    b_vec = b_vec.normalise() * b_mag

    return b_vec
Esempio n. 13
0
    def fibre_distance_world(self, world):

        from cherab.tools.observers.intersections import find_wall_intersection
        from raysect.core import Vector3D, Point3D

        start_point = Point3D(self.origin[0] + 1.0 * self.xhat(),
                              self.origin[1] + 1.0 * self.yhat(),
                              self.origin[2] + 1.0 * self.zhat())
        forward_vector = Vector3D(self.xhat(), self.yhat(), self.zhat())

        hit_point, primitive = find_wall_intersection(world,
                                                      start_point,
                                                      forward_vector,
                                                      delta=1E-3)

        return abs((self.origin[0] - hit_point[0]) / self.xhat())
Esempio n. 14
0
    def _check_barrel_surface(self, lens, azimuths, barrel_z):
        """
        Checks barrel surface of a lens by calculating ray-lens intersection. Hit point position and angle of incidence
        are compared to predicted ones.

        :param lens: Spherical lens object to test plane surface of.
        :param azimuths: Azimuth angles to test lens surface at.
        :param barrel_z:
        """

        lens_radius = lens.diameter / 2

        for z in barrel_z:
            for ta in azimuths:
                # get x-y coordinates of the surface point from azimuth
                x = lens_radius * cos(ta)
                y = lens_radius * sin(ta)

                # get origin by surface point offset and calculate ray direction
                surface_point = Point3D(x, y, z)
                direction = Vector3D(-x, -y, 0)
                origin = Point3D(1.1 * x, 1.1 * y, z)

                # calculate ray-lens intersection
                intersection = lens.hit(CoreRay(origin, direction))
                hit_point = intersection.hit_point.transform(
                    intersection.primitive_to_world)

                # distance of expected surface point and the ray hit point
                distance = hit_point.vector_to(surface_point).length
                self.assertAlmostEqual(
                    distance,
                    0,
                    self.tolerance_distance,
                    msg=
                    "Ray-curved surface hit point and predicted surface point difference"
                    " is larger than tolerance.")

                # angle of incidence on the sphere surface should be perpendicular
                cos_angle_incidence = intersection.normal.dot(
                    intersection.ray.direction.normalise())
                self.assertAlmostEqual(
                    fabs(cos_angle_incidence),
                    1,
                    self.tolerance_angle,
                    msg="Angle of incidence differs from perpendicular.")
    def plot_line_of_sight(self, x_pixel, y_pixel, ax, **kwargs):
        """

        :param x_pixel:
        :param y_pixel:
        :param ax:
        :return:
        """

        direction = Vector3D(*list(self.view_vectors.isel(x=x_pixel, y=y_pixel, ).values)).normalise()
        ray_length = float(self.ray_lengths.isel(x=x_pixel, y=y_pixel, ).values)

        n_steps = 50
        increment = (ray_length / n_steps) * direction
        rs, zs = np.zeros(n_steps), np.zeros(n_steps)
        point_i = self.pupil_point  # initialise at pupil
        for i in range(n_steps):
            point_i += increment
            rs[i], zs[i], _ = cart2cyl(*[point_i[j] for j in range(3)])
        ax.plot(rs, zs, **kwargs)
Esempio n. 16
0
def get_pini_alignment(pulse, oct8_pini):

    import idlbridge as idl

    global _idl_was_setup
    if not _idl_was_setup:
        _setup_idl()
        _idl_was_setup = True

    # Note: array index starts at zero, so actual pini index equals pini number - 1/.
    oct8_pini -= 1

    idl.execute("ret = get_cherab_pinialignment(pulse={})".format(pulse))
    ret = idl.get("ret")

    # Pull out the origin points from the IDL structure, convert to Point3D
    origin = Point3D(ret['origin'][oct8_pini][0] / 1000,
                     ret['origin'][oct8_pini][1] / 1000,
                     ret['origin'][oct8_pini][2] / 1000)

    # Pull out the direction vector from the IDL structure, convert to Vector3D
    direction = Vector3D(ret['vector'][oct8_pini][0],
                         ret['vector'][oct8_pini][1],
                         ret['vector'][oct8_pini][2])

    # TODO - note divergence numbers are different between Carine and Corentin.
    div_u = ret['divu'][oct8_pini] / (2 * PI) * 360
    div_v = ret['divv'][oct8_pini] / (2 * PI) * 360
    divergence = (div_u, div_v)

    # Minimal 1/e width (at the source) of the beam (scalar in meters)
    initial_width = 0.001  # Approximate with 1mm as an effective point source.

    pini_length = PINI_LENGTHS[oct8_pini]

    pini_geometry = (origin, direction, divergence, initial_width, pini_length)

    return pini_geometry
Esempio n. 17
0
src.n_pulse = PULSE_PLASMA
psi = src.get_psi_normalised(cached2d=True)
inside = lambda x, y, z: not isnan(psi(x, y, z))

ppfsetdevice("JET")
ppfuid('cgiroud', rw='R')
ppfgo(pulse=PULSE_PLASMA, seq=0)

psi_coord = np.array(ppfget(PULSE_PLASMA, 'PRFL', 'C6')[3], dtype=np.float64)
mask = psi_coord <= 1.0
psi_coord = psi_coord[mask]

flow_velocity_tor_data = np.array(ppfget(PULSE_PLASMA, 'PRFL', 'VT')[2], dtype=np.float64)[mask]
flow_velocity_tor_psi = Interpolate1DCubic(psi_coord, flow_velocity_tor_data)
flow_velocity_tor = IsoMapper3D(psi, flow_velocity_tor_psi)
flow_velocity = lambda x, y, z: Vector3D(y * flow_velocity_tor(x, y, z), - x * flow_velocity_tor(x, y, z), 0.) / np.sqrt(x*x + y*y)

ion_temperature_data = np.array(ppfget(PULSE_PLASMA, 'PRFL', 'TI')[2], dtype=np.float64)[mask]
print("Ti between {} and {} eV".format(ion_temperature_data.min(), ion_temperature_data.max()))
ion_temperature_psi = Interpolate1DCubic(psi_coord, ion_temperature_data)
ion_temperature = IsoMapper3D(psi, ion_temperature_psi)

electron_density_data = np.array(ppfget(PULSE_PLASMA, 'PRFL', 'NE')[2], dtype=np.float64)[mask]
print("Ne between {} and {} m-3".format(electron_density_data.min(), electron_density_data.max()))
electron_density_psi = Interpolate1DCubic(psi_coord, electron_density_data)
electron_density = IsoMapper3D(psi, electron_density_psi)

density_c6_data = np.array(ppfget(PULSE_PLASMA, 'PRFL', 'C6')[2], dtype=np.float64)[mask]
density_c6_psi = Interpolate1DCubic(psi_coord, density_c6_data)
density_c6 = IsoMapper3D(psi, density_c6_psi)
Esempio n. 18
0
 def get_maxwellian(self):
     return Maxwellian(lambda x, y, z: 1e20, lambda x, y, z: 1e3,
                       lambda x, y, z: Vector3D(1e5, 0, 0), 4 * atomic_mass)
Esempio n. 19
0
    def _mayavi_source_from_raysect_object(self):

        # Calculate vertices and faces using the icosohedren method
        # We compute a regular icosohedren with 12 vertices and 20 faces.
        # Vertices given by all perturbations of:
        # (0, ±1, ±ϕ), (±1, ±ϕ, 0), (±ϕ, 0, ±1), where ϕ = golden ratio

        golden_ratio = 1.61803398875

        radius = self._raysect_object.radius

        v1 = Vector3D(-1.0, golden_ratio, 0.0).normalise() * radius
        v2 = Vector3D(1.0, golden_ratio, 0.0).normalise() * radius
        v3 = Vector3D(-1.0, -golden_ratio, 0.0).normalise() * radius
        v4 = Vector3D(1.0, -golden_ratio, 0.0).normalise() * radius
        v5 = Vector3D(0.0, -1.0, golden_ratio).normalise() * radius
        v6 = Vector3D(0.0, 1.0, golden_ratio).normalise() * radius
        v7 = Vector3D(0.0, -1.0, -golden_ratio).normalise() * radius
        v8 = Vector3D(0.0, 1.0, -golden_ratio).normalise() * radius
        v9 = Vector3D(golden_ratio, 0.0, -1.0).normalise() * radius
        v10 = Vector3D(golden_ratio, 0.0, 1.0).normalise() * radius
        v11 = Vector3D(-golden_ratio, 0.0, -1.0).normalise() * radius
        v12 = Vector3D(-golden_ratio, 0.0, 1.0).normalise() * radius

        vertices = [
            [v1.x, v1.y, v1.z],
            [v2.x, v2.y, v2.z],
            [v3.x, v3.y, v3.z],
            [v4.x, v4.y, v4.z],
            [v5.x, v5.y, v5.z],
            [v6.x, v6.y, v6.z],
            [v7.x, v7.y, v7.z],
            [v8.x, v8.y, v8.z],
            [v9.x, v9.y, v9.z],
            [v10.x, v10.y, v10.z],
            [v11.x, v11.y, v11.z],
            [v12.x, v12.y, v12.z],
        ]

        triangles = [[0, 11, 5], [0, 5, 1], [0, 1, 7], [0, 7, 10], [0, 10, 11],
                     [1, 5, 9], [5, 11, 4], [11, 10, 2], [10, 7, 6], [7, 1, 8],
                     [3, 9, 4], [3, 4, 2], [3, 2, 6], [3, 6, 8], [3, 8, 9],
                     [4, 9, 5], [2, 4, 11], [6, 2, 10], [8, 6, 7], [9, 8, 1]]

        # Optional - subdivision of icosohedren to increase resolution
        num_vertices = 12
        num_triangles = 20
        for i in range(self._subdivision_count):
            for j in range(num_triangles):
                triangle = triangles[j]
                # extract current triangle vertices
                v0_id = triangle[0]
                v1_id = triangle[1]
                v2_id = triangle[2]
                v0 = Vector3D(vertices[v0_id][0], vertices[v0_id][1],
                              vertices[v0_id][2])
                v1 = Vector3D(vertices[v1_id][0], vertices[v1_id][1],
                              vertices[v1_id][2])
                v2 = Vector3D(vertices[v2_id][0], vertices[v2_id][1],
                              vertices[v2_id][2])

                # subdivide with three new vertices
                v3 = (v0 + v1).normalise() * radius
                v3_id = num_vertices
                v4 = (v1 + v2).normalise() * radius
                v4_id = num_vertices + 1
                v5 = (v2 + v0).normalise() * radius
                v5_id = num_vertices + 2
                vertices.append([v3.x, v3.y, v3.z])
                vertices.append([v4.x, v4.y, v4.z])
                vertices.append([v5.x, v5.y, v5.z])

                # ... and three new faces
                triangles[j] = [v0_id, v3_id, v5_id]  # replace the first face
                triangles.append([v3_id, v1_id, v4_id])
                triangles.append([v4_id, v2_id, v5_id])
                triangles.append([v3_id, v4_id, v5_id])

                num_vertices += 3
                num_triangles += 3

        vertices = np.array(vertices)
        triangles = np.array(triangles)

        self._raysect_mesh = Mesh(vertices, triangles)
Esempio n. 20
0
def raytraced_etendue(distance,
                      detector_radius=0.001,
                      ray_count=100000,
                      batches=10):

    # generate the transform to the detector position and orientation
    detector_transform = translate(0, 0, distance) * rotate_basis(
        Vector3D(0, 0, -1), Vector3D(0, -1, 0))

    # generate bounding sphere and convert to local coordinate system
    sphere = target.bounding_sphere()
    spheres = [(sphere.centre.transform(detector_transform), sphere.radius,
                1.0)]

    # instance targetted pixel sampler
    targetted_sampler = TargettedHemisphereSampler(spheres)

    point_sampler = DiskSampler3D(detector_radius)

    detector_area = detector_radius**2 * np.pi
    solid_angle = 2 * np.pi
    etendue_sampled = solid_angle * detector_area

    etendues = []
    for i in range(batches):

        # sample pixel origins
        origins = point_sampler(samples=ray_count)

        passed = 0.0
        for origin in origins:

            # obtain targetted vector sample
            direction, pdf = targetted_sampler(origin, pdf=True)
            path_weight = R_2_PI * direction.z / pdf

            origin = origin.transform(detector_transform)
            direction = direction.transform(detector_transform)

            while True:

                # Find the next intersection point of the ray with the world
                intersection = world.hit(CoreRay(origin, direction))

                if intersection is None:
                    passed += 1 * path_weight
                    break

                elif isinstance(intersection.primitive.material, NullMaterial):
                    hit_point = intersection.hit_point.transform(
                        intersection.primitive_to_world)
                    origin = hit_point + direction * 1E-9
                    continue

                else:
                    break

        if passed == 0:
            raise ValueError(
                "Something is wrong with the scene-graph, calculated etendue should not zero."
            )

        etendue_fraction = passed / ray_count
        etendues.append(etendue_sampled * etendue_fraction)

    etendue = np.mean(etendues)
    etendue_error = np.std(etendues)

    return etendue, etendue_error
Esempio n. 21
0
 def basis_y(self):
     return Vector3D(0, 1, 0).transform(self.to_root())
Esempio n. 22
0
 def basis_x(self):
     return Vector3D(1, 0, 0).transform(self.to_root())
Esempio n. 23
0
 def normal_vector(self):
     return Vector3D(0, 0, 1).transform(self.to_root())
Esempio n. 24
0
                              (-1, 1, 200))
plt.imshow(np.transpose(np.squeeze(t_samples)), extent=[-1, 2, -1, 1])
plt.colorbar()
plt.axis('equal')
plt.xlabel('x axis')
plt.ylabel('z axis')
plt.title("Neutral Density profile in x-z plane")

###########################
# Inject beam into plasma #

adas = OpenADAS(permit_extrapolation=True, missing_rates_return_null=True)

integration_step = 0.0025
beam_transform = translate(-0.5, 0.0, 0) * rotate_basis(
    Vector3D(1, 0, 0), Vector3D(0, 0, 1))

beam_energy = 50000  # keV

beam_full = Beam(parent=world, transform=beam_transform)
beam_full.plasma = plasma
beam_full.atomic_data = adas
beam_full.energy = beam_energy
beam_full.power = 3e6
beam_full.element = deuterium
beam_full.sigma = 0.05
beam_full.divergence_x = 0.5
beam_full.divergence_y = 0.5
beam_full.length = 3.0
beam_full.attenuator = SingleRayAttenuator(clamp_to_zero=True)
beam_full.models = [BeamCXLine(Line(carbon, 5, (8, 7)))]
Esempio n. 25
0
def load_ks5_sightlines(pulse, spectrometer, parent=None,
                        fibre_names=None,
                        min_wavelength = 526,
                        max_wavelength = 532,
                        spectral_bins = 500):

    if not pulse >= 76666:
        raise ValueError("Only shots >= 76666 are supported at this time.")

    if spectrometer not in ["ks5c", "ks5d"]:
        raise ValueError("Only spectrometers ['ks5c', 'ks5d'] are supported at this time.")

    import idlbridge as idl
    idl.execute('searchpath = !PATH')

    global _idl_was_setup
    if not _idl_was_setup:
        _setup_idl()
        _idl_was_setup = True

    idl.execute("ret = get_ks5_alignment(pulse={}, spec='{}')".format(pulse, spectrometer))

    # Pull out data
    cg_align = idl.get("ret")

    # Process fibres in the order that CXSfit uses.
    cxsfit_order = [i[0] for i in sorted(enumerate(cg_align['cxsfit_track']), key=lambda x:x[1], reverse=True)]

    sightline_group = LineOfSightGroup(parent=parent, name=spectrometer)

    for icg in cxsfit_order:

        fibre_name = str(cg_align['fibre_name'][icg])

        # Some fibre names are blank, meaning ignore them.
        if not fibre_name.strip():
            continue

        if fibre_names and fibre_name not in fibre_names:
             print('Skipped', fibre_name)
             continue

        # Extract the fibres origin and direction
        xi = cg_align['origin_cart']['x'][icg]/1000
        yi = cg_align['origin_cart']['y'][icg]/1000
        zi = cg_align['origin_cart']['z'][icg]/1000

        pini6 = 5
        xj = cg_align['pos_activevol_cart']['x'][pini6][icg]/1000
        yj = cg_align['pos_activevol_cart']['y'][pini6][icg]/1000
        zj = cg_align['pos_activevol_cart']['z'][pini6][icg]/1000

        los_origin = Point3D(xi, yi, zi)
        los_vec = Vector3D(xj-xi, yj-yi, zj-zi).normalise()

        sight_line = SpectroscopicSightLine(los_origin, los_vec, name=fibre_name, parent=sightline_group)
        sight_line.min_wavelength = min_wavelength
        sight_line.max_wavelength = max_wavelength
        sight_line.spectral_bins = spectral_bins

        sightline_group.add_sight_line(sight_line)

    return sightline_group
Esempio n. 26
0
    def create_plasma(self, parent=None, transform=None, name=None):
        """
        Make a CHERAB plasma object from this SOLEGE2D simulation.

        :param Node parent: The plasma's parent node in the scenegraph, e.g. a World object.
        :param AffineMatrix3D transform: Affine matrix describing the location and orientation
        of the plasma in the world.
        :param str name: User friendly name for this plasma (default = "SOLEDGE2D Plasma").
        :rtype: Plasma
        """

        mesh = self.mesh
        name = name or "SOLEDGE2D Plasma"
        plasma = Plasma(parent=parent, transform=transform, name=name)
        radius = mesh.mesh_extent['maxr']
        height = mesh.mesh_extent['maxz'] - mesh.mesh_extent['minz']
        plasma.geometry = Cylinder(radius, height)
        plasma.geometry_transform = translate(0, 0, mesh.mesh_extent['minz'])

        tri_index_lookup = self.mesh.triangle_index_lookup
        tri_to_grid = self.mesh.triangle_to_grid_map

        if isinstance(self._b_field_vectors, np.ndarray):
            plasma.b_field = SOLEDGE2DVectorFunction3D(
                tri_index_lookup, tri_to_grid, self._b_field_vectors_cartesian)
        else:
            print(
                'Warning! No magnetic field data available for this simulation.'
            )

        # Create electron species
        triangle_data = _map_data_onto_triangles(self._electron_temperature)
        electron_te_interp = Discrete2DMesh(mesh.vertex_coords,
                                            mesh.triangles,
                                            triangle_data,
                                            limit=False)
        electron_temp = AxisymmetricMapper(electron_te_interp)
        triangle_data = _map_data_onto_triangles(self._electron_density)
        electron_ne_interp = Discrete2DMesh.instance(electron_te_interp,
                                                     triangle_data)
        electron_dens = AxisymmetricMapper(electron_ne_interp)
        electron_velocity = lambda x, y, z: Vector3D(0, 0, 0)
        plasma.electron_distribution = Maxwellian(electron_dens, electron_temp,
                                                  electron_velocity,
                                                  electron_mass)

        if not isinstance(self.velocities_cartesian, np.ndarray):
            print(
                'Warning! No velocity field data available for this simulation.'
            )

        b2_neutral_i = 0  # counter for B2 neutrals
        for k, sp in enumerate(self.species_list):

            # Identify the species based on its symbol
            symbol, charge = re.match(_SPECIES_REGEX, sp).groups()
            charge = int(charge)
            species_type = _species_symbol_map[symbol]

            # If neutral and B" atomic density available,  use B2 density, otherwise use fluid species density.
            if isinstance(self.b2_neutral_densities,
                          np.ndarray) and charge == 0:
                species_dens_data = self.b2_neutral_densities[:, :,
                                                              b2_neutral_i]
                b2_neutral_i += 1
            else:
                species_dens_data = self.species_density[:, :, k]

            triangle_data = _map_data_onto_triangles(species_dens_data)
            dens = AxisymmetricMapper(
                Discrete2DMesh.instance(electron_te_interp, triangle_data))
            # dens = SOLPSFunction3D(tri_index_lookup, tri_to_grid, species_dens_data)

            # Create the velocity vector lookup function
            if isinstance(self.velocities_cartesian, np.ndarray):
                velocity = SOLEDGE2DVectorFunction3D(
                    tri_index_lookup, tri_to_grid,
                    self.velocities_cartesian[:, :, k, :])
            else:
                velocity = lambda x, y, z: Vector3D(0, 0, 0)

            distribution = Maxwellian(dens, electron_temp, velocity,
                                      species_type.atomic_weight * atomic_mass)
            plasma.composition.add(Species(species_type, charge, distribution))

        return plasma
Esempio n. 27
0
                                  inside_outside=plasma.inside_outside)
d_delta_recom.add_emitter_to_world(world, plasma)

d_epsilon_excit = ExcitationLine(d_epsilon,
                                 plasma.electron_distribution,
                                 d_atom_species,
                                 inside_outside=plasma.inside_outside)
d_epsilon_excit.add_emitter_to_world(world, plasma)
d_epsilon_recom = RecombinationLine(d_epsilon,
                                    plasma.electron_distribution,
                                    d_ion_species,
                                    inside_outside=plasma.inside_outside)
d_epsilon_recom.add_emitter_to_world(world, plasma)

start_point = Point3D(1.669, 0, -1.6502)
forward_vector = Vector3D(1 - 1.669, 0, -2 + 1.6502).normalise()
up_vector = Vector3D(0, 0, 1.0)

spectra = SpectralPipeline0D()
fibre = FibreOptic([spectra],
                   acceptance_angle=1,
                   radius=0.001,
                   spectral_bins=8000,
                   spectral_rays=1,
                   pixel_samples=5,
                   transform=translate(*start_point) *
                   rotate_basis(forward_vector, up_vector),
                   parent=world)

fibre.min_wavelength = 350.0
fibre.max_wavelength = 700.0
Esempio n. 28
0
def sphere_to_mesh(sphere, subdivision_count=2):

    if not isinstance(sphere, Sphere):
        raise TypeError("The _sphere_to_mesh() function takes a Raysect Box primitive as an argument, "
                        "wrong type '{}' given.".format(type(sphere)))

    # Calculate vertices and faces using the icosohedren method
    # We compute a regular icosohedren with 12 vertices and 20 faces.
    # Vertices given by all perturbations of:
    # (0, ±1, ±ϕ), (±1, ±ϕ, 0), (±ϕ, 0, ±1), where ϕ = golden ratio

    golden_ratio = 1.61803398875

    radius = sphere.radius

    v1 = Vector3D(-1.0, golden_ratio, 0.0).normalise() * radius
    v2 = Vector3D(1.0, golden_ratio, 0.0).normalise() * radius
    v3 = Vector3D(-1.0, -golden_ratio, 0.0).normalise() * radius
    v4 = Vector3D(1.0, -golden_ratio, 0.0).normalise() * radius
    v5 = Vector3D(0.0, -1.0, golden_ratio).normalise() * radius
    v6 = Vector3D(0.0, 1.0, golden_ratio).normalise() * radius
    v7 = Vector3D(0.0, -1.0, -golden_ratio).normalise() * radius
    v8 = Vector3D(0.0, 1.0, -golden_ratio).normalise() * radius
    v9 = Vector3D(golden_ratio, 0.0, -1.0).normalise() * radius
    v10 = Vector3D(golden_ratio, 0.0, 1.0).normalise() * radius
    v11 = Vector3D(-golden_ratio, 0.0, -1.0).normalise() * radius
    v12 = Vector3D(-golden_ratio, 0.0, 1.0).normalise() * radius

    vertices = [
        [v1.x, v1.y, v1.z],
        [v2.x, v2.y, v2.z],
        [v3.x, v3.y, v3.z],
        [v4.x, v4.y, v4.z],
        [v5.x, v5.y, v5.z],
        [v6.x, v6.y, v6.z],
        [v7.x, v7.y, v7.z],
        [v8.x, v8.y, v8.z],
        [v9.x, v9.y, v9.z],
        [v10.x, v10.y, v10.z],
        [v11.x, v11.y, v11.z],
        [v12.x, v12.y, v12.z],
    ]

    triangles = [
        [0, 11, 5],
        [0, 5, 1],
        [0, 1, 7],
        [0, 7, 10],
        [0, 10, 11],
        [1, 5, 9],
        [5, 11, 4],
        [11, 10, 2],
        [10, 7, 6],
        [7, 1, 8],
        [3, 9, 4],
        [3, 4, 2],
        [3, 2, 6],
        [3, 6, 8],
        [3, 8, 9],
        [4, 9, 5],
        [2, 4, 11],
        [6, 2, 10],
        [8, 6, 7],
        [9, 8, 1]
    ]

    # Optional - subdivision of icosohedren to increase resolution
    num_vertices = 12
    num_triangles = 20
    for i in range(subdivision_count):
        for j in range(num_triangles):
            triangle = triangles[j]
            # extract current triangle vertices
            v0_id = triangle[0]
            v1_id = triangle[1]
            v2_id = triangle[2]
            v0 = Vector3D(vertices[v0_id][0], vertices[v0_id][1], vertices[v0_id][2])
            v1 = Vector3D(vertices[v1_id][0], vertices[v1_id][1], vertices[v1_id][2])
            v2 = Vector3D(vertices[v2_id][0], vertices[v2_id][1], vertices[v2_id][2])

            # subdivide with three new vertices
            v3 = (v0 + v1).normalise() * radius
            v3_id = num_vertices
            v4 = (v1 + v2).normalise() * radius
            v4_id = num_vertices + 1
            v5 = (v2 + v0).normalise() * radius
            v5_id = num_vertices + 2
            vertices.append([v3.x, v3.y, v3.z])
            vertices.append([v4.x, v4.y, v4.z])
            vertices.append([v5.x, v5.y, v5.z])

            # ... and three new faces
            triangles[j] = [v0_id, v3_id, v5_id]  # replace the first face
            triangles.append([v3_id, v1_id, v4_id])
            triangles.append([v4_id, v2_id, v5_id])
            triangles.append([v3_id, v4_id, v5_id])

            num_vertices += 3
            num_triangles += 3

    vertices = np.array(vertices)
    triangles = np.array(triangles)

    if sphere.parent:
        to_world = sphere.to_root()
    else:
        to_world = sphere.transform

    # Convert vertices to positions in world coordinates
    for i in range(vertices.shape[0]):
        p = Point3D(vertices[i, 0], vertices[i, 1], vertices[i, 2]).transform(to_world)
        vertices[i, 0] = p.x
        vertices[i, 1] = p.y
        vertices[i, 2] = p.z

    return vertices, triangles
Esempio n. 29
0
import numpy as np
import matplotlib.pyplot as plt
from mayavi import mlab
from raysect.core import World, Point3D, Vector3D
from cherab.core.math import ConstantVector3D

from vita.modules.cherab import FieldlineTracer, Euler

# the world scene-graph
world = World()

b_field = ConstantVector3D(Vector3D(0, 1.5, 0))

field_tracer = FieldlineTracer(b_field, method=Euler(step_size=0.001))

start_point = Point3D(0, 0, 0)
end_point, trajectory = field_tracer.trace(world,
                                           start_point,
                                           save_trajectory=True,
                                           max_steps=1000)

num_segments = len(trajectory)
x = np.zeros(num_segments)
y = np.zeros(num_segments)
z = np.zeros(num_segments)
for ith_position, position in enumerate(trajectory):
    x[ith_position] = position.x
    y[ith_position] = position.y
    z[ith_position] = position.z

mlab.plot3d(x, y, z, tube_radius=0.0005, color=(1, 0, 0))
Esempio n. 30
0
def load_kb1_camera(parent=None):

    camera_id = 'KB1'

    # Transforms, read from KB1 CAD model for INDIVIDUAL_BOLOMETER_ASSEMBLY
    # Note that the rotation angle is positive when Axis is the Z axis, and
    # negative when Axis is the -Z axis
    camera_transforms = [
        translate(-1.73116, 2.59086, 3.31650) * rotate_z(123.75),
        translate(-3.05613, 0.60790, 3.31650) * rotate_z(168.75),
        translate(1.73116, -2.59086, 3.31650) * rotate_z(-56.25),
        translate(3.05613, -0.60790, 3.31650) * rotate_z(-11.25),
    ]
    # Transform for INDIVIDUAL_BOLOMETER_ASSEMBLY/SINGLE_BOLOMETER_ASSEMBLY/FOIL 1
    # in CAD model
    foil_camera_transform = translate(0, 0, 18.70e-3)
    # Foils point downwards towards the plasma
    foil_orientation_transform = rotate_basis(Vector3D(0, 0, -1),
                                              Vector3D(0, 1, 0))
    # Dimensions read from edge to edge (and adjacent vertices defining rounded corners) on
    # INDIVIDUAL_BOLOMETER_ASSEMBLY/SINGLE_BOLOMETER_ASSEMBLY/FOIL SUPPORT 1,
    # edges (and vertices) closest to the foil
    foil_width = 11e-3
    foil_height = 11e-3
    foil_curvature_radius = 1e-3

    # KB1 does not really have a slit, per-se. The vessel functions as the
    # aperture. To ensure a sufficiently displaced bounding sphere for the
    # TargettedPixel, we'll put a dummy slit at the exit of the port through
    # which the camera views. Note that with the camera transform defined above,
    # the y axis is in the toroidal direction and the x axis in the inward
    # radial direction.
    #
    # The foil is not centred on the centre of the port. To measure the
    # displacement, the centre of the port was read from the CAD model for
    # KB1-1, then the vector from the foil centre to the centre of the port exit
    # for this channel was calculated in the foil's local coordinate system.
    foil_slit_transform = translate(-0.05025, 0, 1.38658)
    slit_width = 0.25  # slightly larger than widest point of port (~225 mm)
    slit_height = 0.09  # sligtly larger than length of port (~73.84 mm)

    num_slits = len(camera_transforms)
    num_foils = len(camera_transforms)

    bolometer_camera = BolometerCamera(name=camera_id, parent=parent)

    slit_objects = {}
    for i in range(num_slits):
        slit_id = '{}_Slit_#{}'.format(camera_id, i + 1)
        slit_transform = (camera_transforms[i] * foil_orientation_transform *
                          foil_slit_transform * foil_camera_transform)
        centre_point = Point3D(0, 0, 0).transform(slit_transform)
        basis_x = Vector3D(1, 0, 0).transform(slit_transform)
        basis_y = Vector3D(0, 1, 0).transform(slit_transform)
        dx = slit_width
        dy = slit_height
        slit_objects[slit_id] = BolometerSlit(slit_id,
                                              centre_point,
                                              basis_x,
                                              dx,
                                              basis_y,
                                              dy,
                                              csg_aperture=True,
                                              parent=bolometer_camera)

    for i in range(num_foils):
        foil_id = '{}_CH{}_Foil'.format(camera_id, i + 1)
        slit_id = '{}_Slit_#{}'.format(camera_id, i + 1)
        foil_transform = (camera_transforms[i] * foil_orientation_transform *
                          foil_camera_transform)
        centre_point = Point3D(0, 0, 0).transform(foil_transform)
        basis_x = Vector3D(1, 0, 0).transform(foil_transform)
        basis_y = Vector3D(0, 1, 0).transform(foil_transform)
        dx = foil_width
        dy = foil_height
        rc = foil_curvature_radius
        foil = BolometerFoil(foil_id,
                             centre_point,
                             basis_x,
                             dx,
                             basis_y,
                             dy,
                             slit_objects[slit_id],
                             curvature_radius=rc,
                             parent=bolometer_camera)

        bolometer_camera.add_foil_detector(foil)

    return bolometer_camera