Exemplo n.º 1
0
    def poloidal_trajectory_plot(self,
                                 field_tracer,
                                 world,
                                 equilibrium,
                                 num_of_fieldlines=5,
                                 max_tracing_length=15):

        if not (isinstance(num_of_fieldlines, int) and num_of_fieldlines > 0):
            raise TypeError(
                "The number of fieldlines to trace must be an integer > 0.")

        point_a = Point3D(self._point_a.x, 0, self._point_a.y)
        point_b = Point3D(self._point_b.x, 0, self._point_b.y)
        interface_vector = point_a.vector_to(point_b)

        plot_equilibrium(equilibrium, detail=False)

        for i in range(num_of_fieldlines):

            sample_point = point_a + interface_vector * i / num_of_fieldlines

            _, _, trajectory = field_tracer.trace(
                world,
                sample_point,
                max_length=max_tracing_length,
                save_trajectory=True)

            rz_trajectory = np.zeros((trajectory.shape[0], 2))
            for i in range(trajectory.shape[0]):
                r = sqrt(trajectory[i, 0]**2 + trajectory[i, 1]**2)
                z = trajectory[i, 2]
                rz_trajectory[i, :] = r, z

            plt.plot(rz_trajectory[:, 0], rz_trajectory[:, 1], 'g')
Exemplo n.º 2
0
    def __init__(self, slit_id, centre_point, basis_x, dx, basis_y, dy, dz=0.001,
                 parent=None, csg_aperture=False, curvature_radius=0):

        # perform validation of input parameters

        if not isinstance(dx, (float, int)):
            raise TypeError("dx argument for BolometerSlit must be of type float/int.")
        if not dx > 0:
            raise ValueError("dx argument for BolometerSlit must be greater than zero.")

        if not isinstance(dy, (float, int)):
            raise TypeError("dy argument for BolometerSlit must be of type float/int.")
        if not dy > 0:
            raise ValueError("dy argument for BolometerSlit must be greater than zero.")

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

        if not isinstance(curvature_radius, (float, int)):
            raise TypeError("curvature_radius argument for BolometerSlit "
                            "must be of type float/int.")
        if curvature_radius < 0:
            raise ValueError("curvature_radius argument for BolometerSlit "
                             "must not be negative.")

        if not isinstance(basis_x, Vector3D):
            raise TypeError("The basis vectors of BolometerSlit must be of type Vector3D.")
        if not isinstance(basis_y, Vector3D):
            raise TypeError("The basis vectors of BolometerSlit must be of type Vector3D.")

        self._centre_point = centre_point
        self._basis_x = basis_x.normalise()
        self.dx = dx
        self._basis_y = basis_y.normalise()
        self.dy = dy
        self.dz = dz
        self._curvature_radius = curvature_radius

        # NOTE - target primitive and aperture surface cannot be co-incident otherwise numerics will cause Raysect
        # to be blind to one of the two surfaces.
        slit_normal = basis_x.cross(basis_y)
        transform = translate(centre_point.x, centre_point.y, centre_point.z) * rotate_basis(slit_normal, basis_y)

        super().__init__(parent=parent, transform=transform, name=slit_id)

        self.target = Box(lower=Point3D(-dx/2*1.01, -dy/2*1.01, -dz/2), upper=Point3D(dx/2*1.01, dy/2*1.01, dz/2),
                          transform=None, material=NullMaterial(), parent=self, name=slit_id+' - target')

        self._csg_aperture = None
        self.csg_aperture = csg_aperture

        # round off the detector corners, if applicable
        if self._curvature_radius > 0:
            mask_corners(self)
Exemplo n.º 3
0
def generate_annulus_mesh_segments(lower_corner, upper_corner, number_segments, world, material=None):
    """
    Generates an annulus from many smaller mesh segments.

    Used for calculating sensitivity matrices for poloidal inversion grids.

    :param Point2D lower_corner: the lower corner of the poloidal 2D cell.
    :param Point2D upper_corner: the upper corner of the poloidal 2D cell.
    :param int number_segments: The number of angular mesh segments used to build the annulus.
    :param World world: The scene-graph to which the annulus will be attached.
    :return: Node holding all the annulus segment primitives.
    :rtype: Node
    """

    material = material or UnityVolumeEmitter()

    annulus_node = Node(parent=world)

    theta_adjusted = 360 / number_segments

    # Set of points in x-z plane
    p1a = Point3D(lower_corner.x, 0, lower_corner.y)  # corresponds to lower corner is x-z plane
    p2a = Point3D(lower_corner.x, 0, upper_corner.y)
    p3a = Point3D(upper_corner.x, 0, upper_corner.y)  # corresponds to upper corner in x-z plane
    p4a = Point3D(upper_corner.x, 0, lower_corner.y)

    # Set of points rotated away from x-z plane
    p1b = p1a.transform(rotate_z(theta_adjusted))
    p2b = p2a.transform(rotate_z(theta_adjusted))
    p3b = p3a.transform(rotate_z(theta_adjusted))
    p4b = p4a.transform(rotate_z(theta_adjusted))

    vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z],
                [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z],
                [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z],
                [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]]

    triangles = [[1, 0, 3], [1, 3, 2],  # front face (x-z)
                 [7, 4, 5], [7, 5, 6],  # rear face (rotated out of x-z plane)
                 [5, 1, 2], [5, 2, 6],  # top face (x-y plane)
                 [3, 0, 4], [3, 4, 7],  # bottom face (x-y plane)
                 [4, 0, 5], [1, 5, 0],  # inner face (y-z plane)
                 [2, 3, 7], [2, 7, 6]]  # outer face (y-z plane)

    base_segment = Mesh(vertices=vertices, triangles=triangles, smoothing=False)

    # Construct annulus by duplicating and rotating base segment.
    for i in range(number_segments):
        theta_rotation = theta_adjusted * i
        segment = Mesh(instance=base_segment, transform=rotate_z(theta_rotation),
                       material=material, parent=annulus_node)

    return annulus_node
Exemplo n.º 4
0
 def test_invalid_types(self):
     voxel_coords = {'v1': (2, 0), 'v2': (2, 1), 'v3': (3, 1)}
     with self.assertRaises(TypeError, msg="Calling with dict with string keys didn't error"):
         AxisymmetricVoxel(voxel_coords)
     voxel_coords = {1: (2, 0), 2: (2, 1), 3: (3, 1)}
     with self.assertRaises(TypeError, msg="Calling with dict with int keys didn't error"):
         AxisymmetricVoxel(voxel_coords)
     voxel_coords = [Point3D(2, 0, 0), Point3D(2, 0, 1), Point3D(3, 0, 1)]
     with self.assertRaises(TypeError, msg="Calling with list of Point3D didn't error"):
         AxisymmetricVoxel(voxel_coords)
     voxel_coords = np.asarray([[2, 0, 0], [2, 0, 1], [3, 0, 1]])
     with self.assertRaises(TypeError, msg="Calling with Nx3 array didn't error"):
         AxisymmetricVoxel(voxel_coords)
Exemplo n.º 5
0
def _sample_along_beam_axis(function, beam_axis, beam_to_world, debug=False):

    if debug:
        samples = []
        for i, z in enumerate(beam_axis):
            p = Point3D(0, 0, z).transform(beam_to_world)
            samples.append(function(p.x, p.y, p.z))
    else:
        samples = []
        for z in beam_axis:
            p = Point3D(0, 0, z).transform(beam_to_world)
            samples.append(function(p.x, p.y, p.z))

    return samples
Exemplo n.º 6
0
    def csg_aperture(self, value):

        if value is True:
            width = max(self.dx, self.dy)
            face = Box(Point3D(-width, -width, -self.dz/2), Point3D(width, width, self.dz/2))
            slit = Box(lower=Point3D(-self.dx/2, -self.dy/2, -self.dz/2 - self.dz*0.1),
                       upper=Point3D(self.dx/2, self.dy/2, self.dz/2 + self.dz*0.1))
            self._csg_aperture = Subtract(face, slit, parent=self,
                                          material=AbsorbingSurface(), name=self.name+' - CSG Aperture')

        else:
            if isinstance(self._csg_aperture, Primitive):
                self._csg_aperture.parent = None
            self._csg_aperture = None
Exemplo n.º 7
0
    def _generate_rays(self, template, ray_count):

        origin_vectors = self._sphere_sampler(ray_count)
        directions = self._vector_sampler(ray_count)

        rays = []
        for n in range(ray_count):

            # calculate surface point
            origin = origin_vectors[n].copy()
            origin.length = self._radius
            origin = Point3D(*origin)

            # calculate surface normal
            normal = -origin_vectors[n]

            # transform sampling direction from surface space
            direction = directions[n].transform(
                rotate_basis(normal, normal.orthogonal()))

            # USE WITH HEMISPHERECOSINESAMPLER
            # cosine weighted distribution, projected area weight is
            # implicit in distribution, so set weight appropriately
            rays.append((template.copy(origin, direction), 0.5))

        return rays
Exemplo n.º 8
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))
Exemplo n.º 9
0
def csg_to_mesh(csg_primitive):

    vertices, triangles = to_mesh(csg_primitive.primitive_a)
    mesh_a = Mesh(vertices, triangles)

    vertices, triangles = to_mesh(csg_primitive.primitive_b)
    mesh_b = Mesh(vertices, triangles)

    if csg_primitive.__class__ == Intersect:
        operator = IntersectOperator()
    elif csg_primitive.__class__ == Union:
        operator = UnionOperator()
    elif csg_primitive.__class__ == Subtract:
        operator = SubtractOperator()
    else:
        raise ValueError("Unidentified CSG primitive '{}'.".format(csg_primitive.__class__))

    mesh = perform_mesh_csg(mesh_a, mesh_b, operator=operator)

    vertices = mesh.data.vertices.copy()
    triangles = mesh.data.triangles.copy()

    if csg_primitive.parent:
        to_world = csg_primitive.to_root()
    else:
        to_world = csg_primitive.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
Exemplo 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()
Exemplo n.º 11
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
Exemplo n.º 12
0
 def voxel_matches_polygon(self, coordinate_list):
     for voxel_coords in coordinate_list:
         voxel_coords = np.asarray(voxel_coords)
         rmax = voxel_coords[:, 0].max()
         rmin = voxel_coords[:, 0].min()
         zmax = voxel_coords[:, 1].max()
         zmin = voxel_coords[:, 1].min()
         router = 1.5 * rmax
         rinner = 0.5 * rmin
         zupper = 1.5 * zmax if zmax > 0 else 0.5 * zmax
         zlower = 0.5 * zmin if zmin > 0 else 1.5 * zmin
         test_rs = np.linspace(rinner, router, int(100 * (router - rinner)))
         test_zs = np.linspace(zlower, zupper, int(100 * (zupper - zlower)))
         voxel = AxisymmetricVoxel(voxel_coords, primitive_type='csg')
         polygon = Polygon(voxel_coords, closed=True)
         test_verts = list(itertools.product(test_rs, test_zs))
         try:
             inside_poly = polygon.contains_points(test_verts)
         except AttributeError:
             # Polygon.contains_points was only introduced in Matplotlib 2.2.
             # Before that we need to convert to Path
             inside_poly = Path(polygon.get_verts()).contains_points(test_verts)
         inside_csg = [any(child.contains(Point3D(r, 0, z)) for child in voxel.children)
                       for (r, z) in test_verts]
         self.assertSequenceEqual(inside_csg, inside_poly.tolist())
Exemplo n.º 13
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.")
Exemplo n.º 14
0
def generate_annulus_mesh_segments(lower_corner, upper_corner, theta_width,
                                   theta_offset, world):

    material = UnityVolumeEmitter()

    # Set of points in x-z plane
    p1a = Point3D(lower_corner.x, 0,
                  lower_corner.y)  # corresponds to lower corner is x-z plane
    p2a = Point3D(lower_corner.x, 0, upper_corner.y)
    p3a = Point3D(upper_corner.x, 0,
                  upper_corner.y)  # corresponds to upper corner in x-z plane
    p4a = Point3D(upper_corner.x, 0, lower_corner.y)

    # Set of points rotated away from x-z plane
    p1b = p1a.transform(rotate_z(theta_width))
    p2b = p2a.transform(rotate_z(theta_width))
    p3b = p3a.transform(rotate_z(theta_width))
    p4b = p4a.transform(rotate_z(theta_width))

    vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z],
                [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z],
                [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z],
                [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]]

    triangles = [
        [1, 0, 3],
        [1, 3, 2],  # front face (x-z)
        [7, 4, 5],
        [7, 5, 6],  # rear face (rotated out of x-z plane)
        [5, 1, 2],
        [5, 2, 6],  # top face (x-y plane)
        [3, 0, 4],
        [3, 4, 7],  # bottom face (x-y plane)
        [4, 0, 5],
        [1, 5, 0],  # inner face (y-z plane)
        [2, 3, 7],
        [2, 7, 6]
    ]  # outer face (y-z plane)

    return Mesh(vertices=vertices,
                triangles=triangles,
                smoothing=False,
                transform=rotate_z(theta_offset),
                material=material,
                parent=world)
Exemplo n.º 15
0
    def test_planoconcave(self):
        """
        Test planoconcave lens for a range of curvatures and center thickness combinations.
        """

        # combinations of lens parameters to test
        diameter = 75
        curvatures = np.array([0.5, 0.75, 1, 1.5, 5]) * diameter
        threshold_ratios = np.array([1, 1.05, 2, 3, 5, 10])

        radius = diameter / 2
        radius2 = radius**2

        for curvature in curvatures:
            for threshold_ratio in threshold_ratios:

                # center thickness calculated from the minimum threshold
                front_thickness = curvature - sqrt(curvature**2 - radius2)
                center_thickness = threshold_ratio * front_thickness

                lens = PlanoConcave(diameter, center_thickness, curvature)

                # calculate coordinates of center of curvature of the lens front surface
                center_front = Point3D(0, 0, center_thickness + curvature)

                # check lens front and back surface by inside and outside envelopes
                azimuths = np.linspace(0,
                                       2 * pi,
                                       self.n_testpoints,
                                       endpoint=False)
                min_altitude = self.pad_constant

                max_altitude = asin(radius / curvature) - self.pad_constant
                altitude = np.linspace(max_altitude,
                                       min_altitude,
                                       self.n_testpoints,
                                       endpoint=True)
                radii = curvature * np.sin(altitude)
                self._check_spherical_surface(curvature, lens, center_front,
                                              True, False, azimuths, radii)

                radii = np.linspace(radius - self.pad_constant,
                                    self.pad_constant, self.n_testpoints)
                self._check_plane_surface(lens, azimuths, radii)

                # check lens barrel surface by inside and outside envelope
                min_z = 0
                max_z = center_thickness + front_thickness
                if max_z - min_z <= 3 * self.pad_constant:
                    barrel_z = np.array(((min_z + max_z) / 2), ndmin=1)
                else:
                    barrel_z = np.linspace(min_z + self.pad_constant,
                                           max_z - self.pad_constant,
                                           self.n_testpoints,
                                           endpoint=True)
                self._check_barrel_surface(lens, azimuths, barrel_z)
Exemplo n.º 16
0
    def _mayavi_source_from_raysect_object(self):

        lower = self._raysect_object.lower
        upper = self._raysect_object.upper
        # more negative face in x-z plane
        p1a = lower  # lower corner in x-z plane
        p2a = Point3D(lower.x, lower.y, upper.z)
        p3a = Point3D(upper.x, lower.y, upper.z)  # upper corner in x-z plane
        p4a = Point3D(upper.x, lower.y, lower.z)
        # more positive face in x-z plane
        p1b = Point3D(lower.x, upper.y, lower.z)
        p2b = Point3D(lower.x, upper.y, upper.z)
        p3b = upper
        p4b = Point3D(upper.x, upper.y, lower.z)
        vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z],
                    [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z],
                    [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z],
                    [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]]
        triangles = [[1, 0, 3], [1, 3, 2],  # front face (x-z)
                    [7, 4, 5], [7, 5, 6],  # rear face (x-z)
                    [5, 1, 2], [5, 2, 6],  # top face (x-y)
                    [3, 0, 4], [3, 4, 7],  # bottom face (x-y)
                    [4, 0, 5], [1, 5, 0],  # left face (y-z)
                    [2, 3, 7], [2, 7, 6]]  # right face (y-z)

        mesh = Mesh(vertices, triangles)
        self._raysect_mesh = subdivide(mesh)
Exemplo n.º 17
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
Exemplo n.º 18
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()
Exemplo n.º 19
0
    def __init__(self,
                 slit_id,
                 centre_point,
                 basis_x,
                 dx,
                 basis_y,
                 dy,
                 dz=0.001,
                 parent=None,
                 csg_aperture=False):

        self._centre_point = centre_point
        self._basis_x = basis_x.normalise()
        self.dx = dx
        self._basis_y = basis_y.normalise()
        self.dy = dy
        self.dz = dz

        # NOTE - target primitive and aperture surface cannot be co-incident otherwise numerics will cause Raysect
        # to be blind to one of the two surfaces.
        slit_normal = basis_x.cross(basis_y)
        transform = translate(centre_point.x, centre_point.y,
                              centre_point.z) * rotate_basis(
                                  slit_normal, basis_y)

        super().__init__(parent=parent, transform=transform, name=slit_id)

        self.target = Box(lower=Point3D(-dx / 2 * 1.01, -dy / 2 * 1.01,
                                        -dz / 2),
                          upper=Point3D(dx / 2 * 1.01, dy / 2 * 1.01, dz / 2),
                          transform=None,
                          material=NullMaterial(),
                          parent=self,
                          name=slit_id + ' - target')

        self._csg_aperture = None
        self.csg_aperture = csg_aperture
Exemplo n.º 20
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())
Exemplo n.º 21
0
def box_to_mesh(box):

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

    lower = box.lower
    upper = box.upper
    # more negative face in x-z plane
    p1a = lower  # lower corner in x-z plane
    p2a = Point3D(lower.x, lower.y, upper.z)
    p3a = Point3D(upper.x, lower.y, upper.z)  # upper corner in x-z plane
    p4a = Point3D(upper.x, lower.y, lower.z)
    # more positive face in x-z plane
    p1b = Point3D(lower.x, upper.y, lower.z)
    p2b = Point3D(lower.x, upper.y, upper.z)
    p3b = upper
    p4b = Point3D(upper.x, upper.y, lower.z)
    vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z],
                [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z],
                [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z],
                [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]]
    triangles = [[1, 0, 3], [1, 3, 2],  # front face (x-z)
                 [7, 4, 5], [7, 5, 6],  # rear face (x-z)
                 [5, 1, 2], [5, 2, 6],  # top face (x-y)
                 [3, 0, 4], [3, 4, 7],  # bottom face (x-y)
                 [4, 0, 5], [1, 5, 0],  # left face (y-z)
                 [2, 3, 7], [2, 7, 6]]  # right face (y-z)

    mesh = Mesh(vertices, triangles)
    mesh = subdivide(mesh)

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

    if box.parent:
        to_world = box.to_root()
    else:
        to_world = box.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
Exemplo n.º 22
0
def mesh_to_mesh(mesh):

    vertices = mesh.data.vertices.copy()
    triangles = mesh.data.triangles.copy()[:, 0:3]

    if mesh.parent:
        to_world = mesh.to_root()
    else:
        to_world = mesh.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
Exemplo n.º 23
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
Exemplo n.º 24
0
 def voxel_matches_polygon(self, coordinate_list):
     for voxel_coords in coordinate_list:
         voxel_coords = np.asarray(voxel_coords)
         rmax = voxel_coords[:, 0].max()
         rmin = voxel_coords[:, 0].min()
         zmax = voxel_coords[:, 1].max()
         zmin = voxel_coords[:, 1].min()
         router = 1.5 * rmax
         rinner = 0.5 * rmin
         zupper = 1.5 * zmax if zmax > 0 else 0.5 * zmax
         zlower = 0.5 * zmin if zmin > 0 else 1.5 * zmin
         test_rs = np.linspace(rinner, router, int(50 * (router - rinner)))
         test_zs = np.linspace(zlower, zupper, int(50 * (zupper - zlower)))
         # Test for 0 area: not supported by mesh representation
         x, y = voxel_coords.T
         area = 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
         if area == 0:
             continue
         voxel = AxisymmetricVoxel(voxel_coords, primitive_type='mesh')
         polygon = Polygon(voxel_coords, closed=True).get_path()
         test_verts = list(itertools.product(test_rs, test_zs))
         inside_poly = polygon.contains_points(test_verts)
         inside_voxel = [any(child.contains(Point3D(r, 0, z)) for child in voxel.children)
                         for (r, z) in test_verts]
         # Due to numerical precision, some points may be inside the
         # Matplotlib polygon but not the Mesh. Check in this case that the
         # "failing" points are just very close to the edge of the polygon
         fails = np.nonzero(np.not_equal(inside_voxel, inside_poly))[0]
         for fail in fails:
             if inside_voxel[fail] and not inside_poly[fail]:
                 # Polygon should be made slightly bigger
                 inside_poly[fail] = polygon.contains_point(test_verts[fail], radius=-0.01)
             elif inside_poly[fail] and not inside_voxel[fail]:
                 # Polygon should be made slightly smaller
                 inside_poly[fail] = polygon.contains_point(test_verts[fail], radius=0.01)
         self.assertSequenceEqual(inside_voxel, inside_poly.tolist(),
                                  "Failed for vertices {}".format(voxel_coords))
Exemplo n.º 25
0
def box_to_mesh(box):

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

    lower = box.lower
    upper = box.upper
    # more negative face in x-z plane
    p1a = lower  # lower corner in x-z plane
    p2a = Point3D(lower.x, lower.y, upper.z)
    p3a = Point3D(upper.x, lower.y, upper.z)  # upper corner in x-z plane
    p4a = Point3D(upper.x, lower.y, lower.z)
    # more positive face in x-z plane
    p1b = Point3D(lower.x, upper.y, lower.z)
    p2b = Point3D(lower.x, upper.y, upper.z)
    p3b = upper
    p4b = Point3D(upper.x, upper.y, lower.z)
    vertices = [[p1a.x, p1a.y, p1a.z], [p2a.x, p2a.y, p2a.z],
                [p3a.x, p3a.y, p3a.z], [p4a.x, p4a.y, p4a.z],
                [p1b.x, p1b.y, p1b.z], [p2b.x, p2b.y, p2b.z],
                [p3b.x, p3b.y, p3b.z], [p4b.x, p4b.y, p4b.z]]
    triangles = [
        [1, 0, 3],
        [1, 3, 2],  # front face (x-z)
        [7, 4, 5],
        [7, 5, 6],  # rear face (x-z)
        [5, 1, 2],
        [5, 2, 6],  # top face (x-y)
        [3, 0, 4],
        [3, 4, 7],  # bottom face (x-y)
        [4, 0, 5],
        [1, 5, 0],  # left face (y-z)
        [2, 3, 7],
        [2, 7, 6]
    ]  # right face (y-z)
    return Mesh(vertices=vertices,
                triangles=triangles,
                smoothing=False,
                transform=box.transform,
                material=box.material,
                name=box.name)
Exemplo n.º 26
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))
Exemplo n.º 27
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
Exemplo n.º 28
0
def cone_to_mesh(cone, vertical_divisions=10, cylindrical_divisions=36, base_radial_divisions=5):

    if not isinstance(cone, Cone):
        raise TypeError("The _cone_to_mesh() function takes a Raysect Cone primitive as an argument, "
                        "wrong type '{}' given.".format(type(cone)))

    radius = cone.radius
    height = cone.height

    # first make the cone body

    working_cylindrical_divisions = cylindrical_divisions

    cone_body_vertices = []
    for i in range(vertical_divisions):

        working_radius = radius * (1 - (i / vertical_divisions))
        working_height = height * (i / vertical_divisions)
        theta_step = 360 / working_cylindrical_divisions

        for j in range(working_cylindrical_divisions):
            theta_rad = np.deg2rad(j * theta_step)
            cone_body_vertices.append([working_radius * np.cos(theta_rad), working_radius * np.sin(theta_rad), working_height])

        working_cylindrical_divisions -= int(cylindrical_divisions / (vertical_divisions + 1))
        if working_cylindrical_divisions < 5:
            working_cylindrical_divisions = 5

    # Finally, add centre point
    cone_body_vertices.append([0, 0, height])

    # Triangulate the vertices
    vertices_2d = np.array(cone_body_vertices)[:, 0:2]
    cone_body_triangles = Delaunay(vertices_2d).simplices.tolist()


    # Now make the cone base

    working_cylindrical_divisions = cylindrical_divisions
    cone_base_vertices = []
    for i in range(base_radial_divisions):

        working_radius = radius * (1 - (i / base_radial_divisions))
        theta_step = 360 / working_cylindrical_divisions

        for j in range(working_cylindrical_divisions):
            theta_rad = np.deg2rad(j * theta_step)
            cone_base_vertices.append([working_radius * np.cos(theta_rad), working_radius * np.sin(theta_rad), 0])

        working_cylindrical_divisions -= int(cylindrical_divisions / (base_radial_divisions + 1))
        if working_cylindrical_divisions < 5:
            working_cylindrical_divisions = 5

    # Finally, add centre point
    cone_base_vertices.append([0, 0, 0])

    # Triangulate the vertices
    vertices_2d = np.array(cone_base_vertices)[:, 0:2]
    cone_base_triangles = np.flip(Delaunay(vertices_2d).simplices + len(cone_body_vertices), 1).tolist()

    # Combine the resulting triangles together
    vertices = cone_body_vertices + cone_base_vertices
    triangles = cone_body_triangles + cone_base_triangles

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

    if cone.parent:
        to_world = cone.to_root()
    else:
        to_world = cone.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
Exemplo n.º 29
0
def cylinder_to_mesh(cylinder, vertical_divisions=10, cylindrical_divisions=36, radial_divisions=5):

    if not isinstance(cylinder, Cylinder):
        raise TypeError("The _cylinder_to_mesh() function takes a Raysect Cylinder primitive as an argument, "
                        "wrong type '{}' given.".format(type(cylinder)))

    radius = cylinder.radius
    height = cylinder.height

    # first make the main cylinder
    theta_step = 360 / cylindrical_divisions

    vertices = []
    for i in range(vertical_divisions):
        z = (i / (vertical_divisions - 1)) * height
        for j in range(cylindrical_divisions):
            theta_rad = np.deg2rad(j * theta_step)
            vertices.append([radius * np.cos(theta_rad), radius * np.sin(theta_rad), z])

    triangles = []
    for i in range(vertical_divisions - 1):

        row_start = cylindrical_divisions * i
        next_row_start = cylindrical_divisions * (i + 1)

        for j in range(cylindrical_divisions):

            v1 = row_start + j
            if j != cylindrical_divisions - 1:
                v2 = row_start + j + 1
                v3 = next_row_start + j + 1
            else:
                v2 = row_start
                v3 = next_row_start
            v4 = next_row_start + j

            triangles.append([v1, v2, v3])
            triangles.append([v3, v4, v1])

    def _make_cap_triangles(n_cylindrical_segments, n_radial_segments, radius, z_height):

        working_cylindrical_segments = n_cylindrical_segments

        cap_vertices = []

        for i in range(n_radial_segments):

            working_radius = radius * (1 - (i / n_radial_segments))
            theta_step = 360 / working_cylindrical_segments

            for j in range(working_cylindrical_segments):
                theta_rad = np.deg2rad(j * theta_step)
                cap_vertices.append([working_radius * np.cos(theta_rad), working_radius * np.sin(theta_rad), z_height])

            working_cylindrical_segments -= int(n_cylindrical_segments/(n_radial_segments+1))
            if working_cylindrical_segments < 5:
                working_cylindrical_segments = 5

        # Finally, add centre point
        cap_vertices.append([0, 0, z_height])

        vertices_2d = np.array(cap_vertices)[:, 0:2]

        triangles = Delaunay(vertices_2d).simplices

        return cap_vertices, triangles

    # Make the upper and lower end caps
    lower_cap_vertices, lower_cap_triangles = _make_cap_triangles(cylindrical_divisions, radial_divisions, radius, 0)
    lower_cap_triangles = np.flip(lower_cap_triangles, 1)
    lower_cap_triangles += len(vertices)
    lower_cap_triangles = lower_cap_triangles.tolist()

    vertices += lower_cap_vertices
    triangles += lower_cap_triangles

    upper_cap_vertices, upper_cap_triangles = _make_cap_triangles(cylindrical_divisions, radial_divisions, radius, height)
    upper_cap_triangles += len(vertices)
    upper_cap_triangles = upper_cap_triangles.tolist()

    vertices += upper_cap_vertices
    triangles += upper_cap_triangles

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

    if cylinder.parent:
        to_world = cylinder.to_root()
    else:
        to_world = cylinder.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
Exemplo n.º 30
0
##########################
# add machine components #

config_file = get_resource("ST40-IVC1", "configuration", 'st40_ivc1_config')
load_wall_configuration(config_file, world)


eq002 = get_resource("ST40-IVC1", "equilibrium", "eq_006_2T_export")
fiesta = Fiesta(eq002)
b_field = fiesta.b_field
lcfs = fiesta.get_midplane_lcfs()[1]


seed_points = [
    Point3D(0.75, 0, 0),
    Point3D(lcfs + 0.001, 0, 0),
    Point3D(lcfs + 0.01, 0, 0),
    Point3D(lcfs + 0.02, 0, -0.01)
]


field_tracer = FieldlineTracer(b_field, method=RK2(step_size=0.0001))

end_point, _, trajectory1 = field_tracer.trace(world, seed_points[0], save_trajectory=True, max_length=15)
end_point, _, trajectory2 = field_tracer.trace(world, seed_points[1], save_trajectory=True, max_length=15)
end_point, _, trajectory3 = field_tracer.trace(world, seed_points[2], save_trajectory=True, max_length=15)
end_point, _, trajectory4 = field_tracer.trace(world, seed_points[3], save_trajectory=True, max_length=15)

# mlab.plot3d([0, 0.005, 0.001], [0, 0, 0], [0, 0, 0], tube_radius=0.0005, color=(1, 0, 0))
# mlab.plot3d([0, 0, 0], [0, 0.005, 0.001], [0, 0, 0], tube_radius=0.0005, color=(0, 1, 0))