Beispiel #1
0
    def __init__(self, bandgap=555, origin=(0, 0, 0), size=(1, 1, 1), shape="box"):
        super(Channel, self).__init__()
        self.origin = np.array(origin)
        self.size = np.array(size)
        self.volume = 1
        if shape == "box":
            self.shape = Box(origin=origin, extent=np.array(origin) + np.array(size))
            for coord in size:
                self.volume *= coord
        elif shape == "cylinder":  # takes radius, length
            # The following is a little workaround to convert origin, size into cylinder (radius, length) descriptors
            # Axis is based on the longest direction among the size (x,y,z)
            axis = np.argmax(size)
            # Length is the value of the longest axis of size
            length = np.amax(size)
            # Radius is the average of the other two coordinates divided by two (radius, not diameter!)
            radius = np.average(np.delete(size, axis)) / 2  # Div. by 2 cause what's given it's the diameter

            # Cylinder volume formula
            self.volume = math.pi * radius ** 2 * length

            self.shape = Cylinder(radius=radius, length=length)

            # For CSG first rotation then translation (assuming scaling is not needed)
            if axis == 0:  # Z to X Rotation needed
                self.shape.append_transform(tf.rotation_matrix(math.pi / 2.0, [0, 1, 0]))
            elif axis == 1:  # Z to Y Rotation needed
                self.shape.append_transform(tf.rotation_matrix(-math.pi / 2.0, [1, 0, 0]))

            self.shape.append_transform(tf.translation_matrix(origin))
        else:
            self.logger.warn("The channel shape is invalid (neither box nor cylinder. It was " + str(shape))
            raise Exception("Channel has invalid shape")
        self.material = SimpleMaterial(bandgap)
        self.name = "Channel"
Beispiel #2
0
    def photon(self):
        photon = Photon()
        photon.source = self.source_id
        photon.id = self.throw
        self.throw += 1

        # This does not work, since the area element scales with Sin(theta) d theta d phi
        # See  http://mathworld.wolfram.com/SpherePointPicking.html
        # Reimplementing the Randomizer

        phi = np.random.uniform(self.phi_min, self.phi_max)
        # theta = np.random.uniform(self.theta_min, self.theta_max)

        theta = -1
        while theta > self.theta_max or theta < self.theta_min:
            theta = np.arccos(2 * np.random.uniform(0, 1) - 1)

        x = np.cos(phi) * np.sin(theta)
        y = np.sin(phi) * np.sin(theta)
        z = np.cos(theta)
        direction = (x, y, z)

        transform = tf.translation_matrix((0, 0, 0))
        point = transform_point(self.center, transform)

        photon.direction = direction
        photon.position = point

        if self.spectrum is not None:
            photon.wavelength = self.spectrum.wavelength_at_probability(
                np.random.uniform())
        else:
            photon.wavelength = self.wavelength

        photon.active = True

        photon.id = self.throw
        self.log.debug('Emitted photon (pid: ' + str(self.throw) + ')')
        self.throw += 1
        return photon
Beispiel #3
0
    def photon(self):
        photon = Photon()
        photon.source = self.source_id
        photon.id = self.throw
        self.throw += 1
        
        # This does not work, since the area element scales with Sin(theta) d theta d phi
        # See  http://mathworld.wolfram.com/SpherePointPicking.html
        # Reimplementing the Randomizer

        phi = np.random.uniform(self.phi_min, self.phi_max)
        # theta = np.random.uniform(self.theta_min, self.theta_max)
        
        theta = -1
        while theta > self.theta_max or theta < self.theta_min:
            theta = np.arccos(2 * np.random.uniform(0, 1)-1)
        
        x = np.cos(phi) * np.sin(theta)
        y = np.sin(phi) * np.sin(theta)
        z = np.cos(theta)
        direction = (x, y, z)

        transform = tf.translation_matrix((0, 0, 0))
        point = transform_point(self.center, transform)

        photon.direction = direction
        photon.position = point

        if self.spectrum is not None:
            photon.wavelength = self.spectrum.wavelength_at_probability(np.random.uniform())
        else:
            photon.wavelength = self.wavelength

        photon.active = True

        photon.id = self.throw
        self.log.debug('Emitted photon (pid: ' + str(self.throw)+')')
        self.throw += 1
        return photon
Beispiel #4
0
    def photon(self):
        photon = Photon()

        photon.source = self.source_id

        int_phi = np.random.randint(1, self.spacing + 1)
        int_theta = np.random.randint(1, self.spacing + 1)

        phi = int_phi * (self.phi_max - self.phi_min) / self.spacing
        if self.theta_min == self.theta_max:
            theta = self.theta_min
        else:
            theta = int_theta * (self.theta_max -
                                 self.theta_min) / self.spacing

        x = np.cos(phi) * np.sin(theta)
        y = np.sin(phi) * np.sin(theta)
        z = np.cos(theta)
        direction = (x, y, z)

        transform = tf.translation_matrix((0, 0, 0))
        point = transform_point(self.center, transform)

        photon.direction = direction
        photon.position = point

        if self.spectrum is not None:
            photon.wavelength = self.spectrum.wavelength_at_probability(
                np.random.uniform())
        else:
            photon.wavelength = self.wavelength

        photon.active = True

        photon.id = self.throw
        self.log.debug('Emitted photon (pid: ' + str(self.throw) + ')')
        self.throw += 1
        return photon
Beispiel #5
0
    def photon(self):
        photon = Photon()

        photon.source = self.source_id
        photon.id = self.throw
        self.throw = self.throw + 1

        intphi = np.random.randint(1, self.spacing + 1)
        inttheta = np.random.randint(1, self.spacing + 1)

        phi = intphi * (self.phimax - self.phimin) / self.spacing
        if self.thetamin == self.thetamax:
            theta = self.thetamin
        else:
            theta = inttheta * (self.thetamax - self.thetamin) / self.spacing

        x = np.cos(phi) * np.sin(theta)
        y = np.sin(phi) * np.sin(theta)
        z = np.cos(theta)
        direction = (x, y, z)

        transform = tf.translation_matrix((0, 0, 0))
        point = transform_point(self.center, transform)

        photon.direction = direction
        photon.position = point

        if self.spectrum != None:
            photon.wavelength = self.spectrum.wavelength_at_probability(
                np.random.uniform())
        else:
            photon.wavelength = self.wavelength

        photon.active = True

        return photon
Beispiel #6
0
    def photon(self):
        photon = Photon()

        photon.source = self.source_id

        int_phi = np.random.randint(1, self.spacing + 1)
        int_theta = np.random.randint(1, self.spacing + 1)

        phi = int_phi * (self.phi_max - self.phi_min) / self.spacing
        if self.theta_min == self.theta_max:
            theta = self.theta_min
        else:
            theta = int_theta * (self.theta_max - self.theta_min) / self.spacing

        x = np.cos(phi) * np.sin(theta)
        y = np.sin(phi) * np.sin(theta)
        z = np.cos(theta)
        direction = (x, y, z)

        transform = tf.translation_matrix((0, 0, 0))
        point = transform_point(self.center, transform)

        photon.direction = direction
        photon.position = point

        if self.spectrum is not None:
            photon.wavelength = self.spectrum.wavelength_at_probability(np.random.uniform())
        else:
            photon.wavelength = self.wavelength

        photon.active = True

        photon.id = self.throw
        self.log.debug('Emitted photon (pid: ' + str(self.throw)+')')
        self.throw += 1
        return photon
Beispiel #7
0
 fluro_red = Material(absorption_data=abs, emission_data=ems, quantum_efficiency=0.95, refractive_index=1.5)
 
 # 4) Give the material a linear background absorption (pmma)
 abs = Spectrum([0,1000], [2,2])
 ems = Spectrum([0,1000], [0,0])
 pmma = Material(absorption_data=abs, emission_data=ems, quantum_efficiency=0.0, refractive_index=1.5)
 
 # 5) Make the LSC and give it both dye and pmma materials
 #lsc = LSC(origin=(0,0,0), size=(L,W,H) )
 #lsc.material = CompositeMaterial([pmma, fluro_red], refractive_index = 1.5)
 #lsc.name = "LSC"
 
 lsc = Rod(radius = L, length = H)
 lsc.material = CompositeMaterial([pmma, fluro_red], refractive_index = 1.5)
 lsc.name = "LSC"
 lsc.shape.append_transform(tf.translation_matrix((2*L,0,0)))
 lsc2 = Rod(radius = L, length = H)
 lsc2.material = CompositeMaterial([pmma, fluro_red], refractive_index = 1.5)
 lsc2.name = "LSC2"
 
 
 scene = Scene()
 scene.add_object(lsc2)
 scene.add_object(lsc)
 
 # Ask python that the directory of this script file is and use it as the location of the database file
 pwd = os.getcwd()
 sql_file = str(x) + 'homogen_db2.sql'
 dbfile = os.path.join(pwd, sql_file) # <--- the name of the database file
 
 trace = Tracer(scene=scene, source=source, seed=1, throws=1000, database_file=dbfile, use_visualiser=False, show_log=False)
Beispiel #8
0
 def __init__(self, finiteplane, origin=(0., 0., 0.,)):
     super(Detector, self).__init__()
     self.shape = finiteplane
     self.shape.append_transform(tf.translation_matrix(origin))
     self.name = "cell"
     self.material = None
Beispiel #9
0
 def translate(self, translation):
     self.shape.append_transform(tf.translation_matrix(translation))
Beispiel #10
0
 def translate(self, translation):
     self.shape.append_transform(tf.translation_matrix(translation))
Beispiel #11
0
    def intersection(self, ray):
        """
        Returns all forward intersection points with ray and the capped cylinder. 
        The intersection algoithm is taken from, "Intersecting a Ray with a Cylinder"
        Joseph M. Cychosz and Warren N. Waggenspack, Jr., in "Graphics Gems IV", 
        Academic Press, 1994.
        """
        """
        >>> cld = Cylinder(1.0, 1.0)
        >>> cld.intersection(Ray([0.0, 0.0, 0.5], [1, 0, 0]))
        [array([ 1. ,  0. ,  0.5])]
        
        >>> cld.intersection(Ray([-5, 0.0, 0.5], [1, 0, 0]))
        [array([-1. ,  0. ,  0.5]), array([ 1. ,  0. ,  0.5])]
        
        >>> cld.intersection(Ray([.5, .5, -1], [0, 0, 1]))
        [array([ 0.5,  0.5,  1. ]), array([ 0.5,  0.5,  0. ])]
        
        >>> cld.intersection( Ray([0.0, 0.0, 2.0], [0, 0, -1]))
        [array([ 0.,  0.,  1.]), array([ 0.,  0.,  0.])]
        
        >>> cld.intersection(Ray([-0.2, 1.2, 0.5], [0.75498586, -0.53837322,  0.37436697]))
        [array([ 0.08561878,  0.99632797,  0.64162681]), array([ 0.80834999,  0.48095523,  1.        ])]
        
        >>> cld.intersection(Ray(position=[ 0.65993112596983427575736414, -0.036309587083015459896273569, 1.], direction=[0.24273873128664008591570678, -0.81399482405912471083553328, 0.52772183462341881732271531]))
        [array([ 0.65993113, -0.03630959,  1.        ])]
        
        >>> cld.transform = tf.translation_matrix([0,0,1])
        >>> cld.intersection(Ray([-5,0.0,1.5], [1,0,0]))
        [array([-1. ,  0. ,  1.5]), array([ 1. ,  0. ,  1.5])]
        
        >>> cld.transform = tf.identity_matrix()
        >>> cld.transform = tf.rotation_matrix(0.25*np.pi, [1,0,0])
        >>> cld.intersection(Ray([-5,-.5,-0.25], [1,0,0]))
        [array([-0.84779125, -0.5       , -0.25      ]), array([ 0.84779125, -0.5       , -0.25      ])]
        """
        # Inverse transform the ray to get it into the cylinders local frame
        inv_transform = tf.inverse_matrix(self.transform)
        rpos = transform_point(ray.position, inv_transform)
        rdir = transform_direction(ray.direction, inv_transform)
        direction = np.array([0, 0, 1])

        normal = np.cross(rdir, direction)
        normal_magnitude = magnitude(normal)
        # print normal_magnitude, "Normal magnitude"

        if cmp_floats(normal_magnitude, .0):

            # Ray parallel to cylinder direction
            normal = norm(normal)
            # d = abs(np.dot(rpos, direction))
            # D = rpos - d * np.array(direction)
            # if magnitude(D) <= self.radius:

            # Axis aligned ray inside the cylinder volume only hits caps
            # print "Inside axis aligned ray only hits caps"
            bottom = Plane()
            top = Plane()
            top.transform = tf.translation_matrix([0, 0, self.length])
            p0 = top.intersection(Ray(rpos, rdir))
            p1 = bottom.intersection(Ray(rpos, rdir))
            cap_intersections = []
            if p0 is not None:
                cap_intersections.append(p0)
            if p1 is not None:
                cap_intersections.append(p1)
            points = []
            for point in cap_intersections:

                if point[0] is not None:
                    point = point[0]
                    point_radius = np.sqrt(point[0] ** 2 + point[1] ** 2)
                    if point_radius <= self.radius:
                        # print "Hit cap at point:"
                        # print point
                        # print ""
                        points.append(point)

            if len(points) > 0:
                world_points = []
                for pt in points:
                    world_points.append(transform_point(pt, self.transform))
                # print "Local points", points
                # print "World points", world_points
                return world_points

            return None
        # finish axis parallel branch

        # print "Not parallel to cylinder axis."
        # print ""
        normal = norm(normal)
        d = abs(np.dot(rpos, normal))
        if d <= self.radius:

            # Hit quadratic surface
            O = np.cross(rpos, direction)
            t = - np.dot(O, normal) / normal_magnitude
            O = np.cross(normal, direction)
            O = norm(O)
            s = abs(np.sqrt(self.radius ** 2 - d ** 2) / np.dot(rdir, O))
            t0 = t - s
            p0 = rpos + t0 * rdir
            t1 = t + s
            p1 = rpos + t1 * rdir

            points = []
            if (t0 >= 0.0) and (.0 <= p0[2] <= self.length):
                points.append(p0)

            if (t1 >= 0.0) and (.0 <= p1[2] <= self.length):
                points.append(p1)

            # print "Hits quadratic surface with t0 and t1, ", t0, t1
            # print ""
            # print "Intersection points:"
            # p0 = rpos + t0 * rdir
            # p1 = rpos + t1 * rdir

            # Check that hit quadratic surface in the length range
            # points = []
            # if (.0 <= p0[2] <= self.length) and not Ray(rpos, rdir).behind(p0):
            #    points.append(p0)
            #
            # if (.0 <= p1[2] <= self.length) and not Ray(rpos, rdir).behind(p1):
            #    points.append(p1)

            # print points
            # Now compute intersection with end caps
            # print "Now to calculate caps intersections"

            bottom = Plane()
            top = Plane()
            top.transform = tf.translation_matrix([0, 0, self.length])
            p2 = top.intersection(Ray(rpos, rdir))
            p3 = bottom.intersection(Ray(rpos, rdir))
            cap_intersections = []
            if p2 is not None:
                cap_intersections.append(p2)
            if p3 is not None:
                cap_intersections.append(p3)

            for point in cap_intersections:

                if point[0] is not None:
                    point = point[0]
                    point_radius = np.sqrt(point[0] ** 2 + point[1] ** 2)
                    if point_radius <= self.radius:
                        # print "Hit cap at point:"
                        # print point
                        # print ""
                        points.append(point)

            # print points
            if len(points) > 0:
                world_points = []
                for pt in points:
                    world_points.append(transform_point(pt, self.transform))
                return world_points
            return None