# pvtrace is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# 
# pvtrace is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import numpy as np
from external.transformations import translation_matrix, rotation_matrix
import external.transformations as tf
from Trace import Photon
from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm
from Materials import Spectrum

def random_spherecial_vector():
    # This method of calculating isotropic vectors is taken from GNU Scientific Library
    LOOP = True
    while LOOP:
        x = -1. + 2. * np.random.uniform()
        y = -1. + 2. * np.random.uniform()
        s = x**2 + y**2
        if s <= 1.0:
            LOOP = False
            
    z = -1. + 2. * s
    a = 2 * np.sqrt(1 - s)
    x = a * x
    y = a * y
    return np.array([x,y,z])
        
class SimpleSource(object):
    """A light source that will generate photons of a single colour, direction and position."""
    def __init__(self, position=[0,0,0], direction=[0,0,1], wavelength=555, use_random_polarisation=False):
        super(SimpleSource, self).__init__()
        self.position = position
        self.direction = direction
        self.wavelength = wavelength
        self.use_random_polarisation = use_random_polarisation
        self.throw = 0
        self.source_id = "SimpleSource_" + str(id(self))
        
        
    def photon(self):
        
        photon = Photon()
        photon.source = self.source_id
        photon.position = np.array(self.position)
        photon.direction = np.array(self.direction)
        photon.active = True
        photon.wavelength = self.wavelength
        
        # If use_polarisation is set generate a random polarisation vector of the photon
        if self.use_random_polarisation:
            
            # Randomise rotation angle around xy-plane, the transform from +z to the direction of the photon
            vec = random_spherecial_vector()
            vec[2] = 0.
            vec = norm(vec)
            R = rotation_matrix_from_vector_alignment(self.direction, [0,0,1])
            photon.polarisation = transform_direction(vec, R)
            
        else:
            photon.polarisation = None
        
        photon.id = self.throw
        self.throw = self.throw + 1 
        return photon

class Laser(object):
    """A light source that will generate photons of a single colour, direction and position."""
    
    def __init__(self, position=[0,0,0], direction=[0,0,1], wavelength=555, polarisation=None):
        super(Laser, self).__init__()
        self.position = np.array(position)
        self.direction = np.array(direction)
        self.wavelength = wavelength
        assert polarisation != None, "Polarisation of the Laser is not set."
        self.polarisation = np.array(polarisation)
        self.throw = 0
        self.source_id = "LaserSource_" + str(id(self))
        
        
    def photon(self):
        
        photon = Photon()
        photon.source = self.source_id
        photon.position = np.array(self.position)
        photon.direction = np.array(self.direction)
        photon.active = True
        photon.wavelength = self.wavelength
        photon.polarisation = self.polarisation
        photon.id = self.throw
        self.throw = self.throw + 1 
        return photon
        
class PlanarSource(object):
    """A box that emits photons from the top surface (normal), sampled from the spectrum."""
    def __init__(self, spectrum=None, wavelength=555, direction=(0,0,1), length=0.05, width=0.05):
        super(PlanarSource, self).__init__()
        self.spectrum = spectrum
        self.wavelength = wavelength
        self.plane = FinitePlane(length=length, width=width)
        self.length = length
        self.width = width
        # direction is the direction that photons are fired out of the plane in the GLOBAL FRAME.
        # i.e. this is passed directly to the photon to set is's direction
        self.direction = direction
        self.throw = 0
        self.source_id = "PlanarSource_" + str(id(self))
    
    def translate(self, translation):
        self.plane.append_transform(tf.translation_matrix(translation))
    
    def rotate(self, angle, axis):
        self.plane.append_transform(tf.rotation_matrix(angle, axis))
    
    def photon(self):
        photon = Photon()
        photon.source = self.source_id
        photon.id = self.throw
        self.throw = self.throw + 1 
        # Create a point which is on the surface of the finite plane in it's local frame
        x = np.random.uniform(0., self.length)
        y = np.random.uniform(0., self.width)
        local_point = (x, y, 0.)
        
        # Transform the direciton
        photon.position = transform_point(local_point, self.plane.transform)
        photon.direction = self.direction
        photon.active = True
        if self.spectrum != None:
            photon.wavelength = self.spectrum.wavelength_at_probability(np.random.uniform())
        else:
            photon.wavelength = self.wavelength
        return photon

class LensSource(object):
    """
    A source where photons generated in a plane are focused on a line with space tolerance given by variable "focussize".
    The focus line should be perpendicular to the plane normal and aligned with the z-axis. 
    """
    def __init__(self, spectrum = None, wavelength = 555, linepoint=(0,0,0), linedirection=(0,0,1), focussize = 0, planeorigin = (-1,-1,-1), planeextent = (-1,1,1)):
        super(LensSource, self).__init__()
        self.spectrum = spectrum
        self.wavelength = wavelength
        self.planeorigin = planeorigin
        self.planeextent = planeextent
        self.linepoint = np.array(linepoint)
        self.linedirection = np.array(linedirection)
        self.focussize = focussize
        self.throw = 0
        self.source_id = "LensSource_" + str(id(self))

    def photon(self):
        photon = Photon()
        photon.source = self.source_id
        photon.id = self.throw
        self.throw = self.throw + 1 
        
        # Position
        x = np.random.uniform(self.planeorigin[0],self.planeextent[0])
        y = np.random.uniform(self.planeorigin[1],self.planeextent[1])
        z = np.random.uniform(self.planeorigin[2],self.planeextent[2])
        photon.position = np.array((x,y,z))        
        
        # Direction
        focuspoint = np.array((0.,0.,0.))        
        focuspoint[0] = self.linepoint[0] + np.random.uniform(-self.focussize,self.focussize)
        focuspoint[1] = self.linepoint[1] + np.random.uniform(-self.focussize,self.focussize)
        focuspoint[2] = photon.position[2] 
        
        direction = focuspoint - photon.position
        modulus = (direction[0]**2+direction[1]**2+direction[2]**2)**0.5
        photon.direction = direction/modulus
        
        # Wavelength
        if self.spectrum != None:
            photon.wavelength = self.spectrum.wavelength_at_probability(np.random.uniform())
        else:
            photon.wavelength = self.wavelength
            
        return photon   


class LensSourceAngle(object):
    """
    A source where photons generated in a plane are focused on a line with space tolerance given by variable "focussize".
    The focus line should be perpendicular to the plane normal and aligned with the z-axis. 
    For this lense an additional z-boost is added (Angle of incidence in z-direction).
    """
    def __init__(self, spectrum = None, wavelength = 555, linepoint=(0,0,0), linedirection=(0,0,1), angle = 0, focussize = 0, planeorigin = (-1,-1,-1), planeextent = (-1,1,1)):
        super(LensSourceAngle, self).__init__()
        self.spectrum = spectrum
        self.wavelength = wavelength
        self.planeorigin = planeorigin
        self.planeextent = planeextent
        self.linepoint = np.array(linepoint)
        self.linedirection = np.array(linedirection)
        self.focussize = focussize
        self.angle = angle
        self.throw = 0
        self.source_id = "LensSourceAngle_" + str(id(self))
        
    def photon(self):
        photon = Photon()
        
        photon.id = self.throw
        self.throw = self.throw + 1 
        
        # Position
        x = np.random.uniform(self.planeorigin[0],self.planeextent[0])
        y = np.random.uniform(self.planeorigin[1],self.planeextent[1])
        boost = y*np.tan(self.angle)
        z = np.random.uniform(self.planeorigin[2],self.planeextent[2]) - boost
        photon.position = np.array((x,y,z))        
        
        # Direction
        focuspoint = np.array((0.,0.,0.))        
        focuspoint[0] = self.linepoint[0] + np.random.uniform(-self.focussize,self.focussize)
        focuspoint[1] = self.linepoint[1] + np.random.uniform(-self.focussize,self.focussize)
        focuspoint[2] = photon.position[2] + boost
        
        direction = focuspoint - photon.position
        modulus = (direction[0]**2+direction[1]**2+direction[2]**2)**0.5
        photon.direction = direction/modulus
        
        # Wavelength
        if self.spectrum != None:
            photon.wavelength = self.spectrum.wavelength_at_probability(np.random.uniform())
        else:
            photon.wavelength = self.wavelength
            
        return photon   
    

class CylindricalSource(object):
    """
    A source for photons emitted in a random direction and position inside a cylinder(radius, length)
    """
    def __init__(self, spectrum = None, wavelength = 555, radius = 1, length = 10):
        super(CylindricalSource, self).__init__()
        self.spectrum = spectrum
        self.wavelength = wavelength
        self.shape = Cylinder(radius = radius, length = length)
        self.radius = radius
        self.length = length
        self.throw = 0
        self.source_id = "CylindricalSource_" + str(id(self))
                
    def translate(self, translation):
        self.shape.append_transform(tf.translation_matrix(translation))

    def rotate(self, angle, axis):
        self.shape.append_transform(tf.rotation_matrix(angle, axis))

    def photon(self):
        photon = Photon()
        photon.source = self.source_id
        photon.id = self.throw
        self.throw = self.throw + 1 
        
        # Position of emission
        phi = np.random.uniform(0., 2*np.pi)
        r = np.random.uniform(0.,self.radius)        
        
        x = r*np.cos(phi)
        y = r*np.sin(phi) 
        z = np.random.uniform(0.,self.length)
        local_center = (x,y,z)
        
        photon.position = transform_point(local_center, self.shape.transform)
        
        
        # Direction of emission (no need to transform if meant to be isotropic)
        phi = np.random.uniform(0.,2*np.pi)
        theta = np.random.uniform(0.,np.pi)
        
        x = np.cos(phi)*np.sin(theta)
        y = np.sin(phi)*np.sin(theta)
        z = np.cos(theta)
        local_direction = (x,y,z)
        
        photon.direction = local_direction
        
        # Set wavelength of photon
        if self.spectrum != None:
            photon.wavelength = self.spectrum.wavelength_at_probability(np.random.uniform())        
        else:
            photon.wavelength = self.wavelength
            
        # Further initialisation
        photon.active = True
        
        return photon

class PointSource(object):
    """
    A point source that emits randomly in solid angle specified by phimin, ..., thetamax
    """
    def __init__(self, spectrum = None, wavelength = 555, center = (0.,0.,0.), phimin = 0, phimax = 2*np.pi, thetamin = 0, thetamax = np.pi):
        super(PointSource, self).__init__()
        self.spectrum = spectrum
        self.wavelength = wavelength
        self.center = center
        self.phimin = phimin
        self.phimax = phimax
        self.thetamin = thetamin
        self.thetamax = thetamax
        self.throw = 0
        self.source_id = "PointSource_" + str(id(self))

    def photon(self):
        photon = Photon()
        photon.source = self.source_id
        photon.id = self.throw
        self.throw = self.throw + 1
        
        phi = np.random.uniform(self.phimin, self.phimax)
        theta = np.random.uniform(self.thetamin, self.thetamax)
        
        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

class RadialSource(object):
    """
    A point source that emits at discrete angles theta(i) and phi(i)
    """
    def __init__(self, spectrum = None, wavelength = 555, center = (0.,0.,0.), phimin = 0, phimax = 2*np.pi, thetamin = 0, thetamax = np.pi, spacing=20):
        super(RadialSource, self).__init__()
        self.spectrum = spectrum
        self.wavelength = wavelength
        self.center = center
        self.phimin = phimin
        self.phimax = phimax
        self.thetamin = thetamin
        self.thetamax = thetamax
        self.spacing = spacing
        self.throw = 0
        self.source_id = "RadialSource_" + str(id(self))

    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

[((1353, 1372), 'numpy.array', 'np.array', (['[x, y, z]'], {}), '([x, y, z])\n', (1361, 1372), True, 'import numpy as np\n'), ((1299, 1313), 'numpy.sqrt', 'np.sqrt', (['(1 - s)'], {}), '(1 - s)\n', (1306, 1313), True, 'import numpy as np\n'), ((1971, 1979), 'Trace.Photon', 'Photon', ([], {}), '()\n', (1977, 1979), False, 'from Trace import Photon\n'), ((2045, 2068), 'numpy.array', 'np.array', (['self.position'], {}), '(self.position)\n', (2053, 2068), True, 'import numpy as np\n'), ((2096, 2120), 'numpy.array', 'np.array', (['self.direction'], {}), '(self.direction)\n', (2104, 2120), True, 'import numpy as np\n'), ((3139, 3157), 'numpy.array', 'np.array', (['position'], {}), '(position)\n', (3147, 3157), True, 'import numpy as np\n'), ((3183, 3202), 'numpy.array', 'np.array', (['direction'], {}), '(direction)\n', (3191, 3202), True, 'import numpy as np\n'), ((3345, 3367), 'numpy.array', 'np.array', (['polarisation'], {}), '(polarisation)\n', (3353, 3367), True, 'import numpy as np\n'), ((3513, 3521), 'Trace.Photon', 'Photon', ([], {}), '()\n', (3519, 3521), False, 'from Trace import Photon\n'), ((3587, 3610), 'numpy.array', 'np.array', (['self.position'], {}), '(self.position)\n', (3595, 3610), True, 'import numpy as np\n'), ((3638, 3662), 'numpy.array', 'np.array', (['self.direction'], {}), '(self.direction)\n', (3646, 3662), True, 'import numpy as np\n'), ((4239, 4278), 'Geometry.FinitePlane', 'FinitePlane', ([], {'length': 'length', 'width': 'width'}), '(length=length, width=width)\n', (4250, 4278), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((4891, 4899), 'Trace.Photon', 'Photon', ([], {}), '()\n', (4897, 4899), False, 'from Trace import Photon\n'), ((5108, 5143), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', 'self.length'], {}), '(0.0, self.length)\n', (5125, 5143), True, 'import numpy as np\n'), ((5155, 5189), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', 'self.width'], {}), '(0.0, self.width)\n', (5172, 5189), True, 'import numpy as np\n'), ((5291, 5341), 'Geometry.transform_point', 'transform_point', (['local_point', 'self.plane.transform'], {}), '(local_point, self.plane.transform)\n', (5306, 5341), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((6264, 6283), 'numpy.array', 'np.array', (['linepoint'], {}), '(linepoint)\n', (6272, 6283), True, 'import numpy as np\n'), ((6313, 6336), 'numpy.array', 'np.array', (['linedirection'], {}), '(linedirection)\n', (6321, 6336), True, 'import numpy as np\n'), ((6490, 6498), 'Trace.Photon', 'Photon', ([], {}), '()\n', (6496, 6498), False, 'from Trace import Photon\n'), ((6646, 6705), 'numpy.random.uniform', 'np.random.uniform', (['self.planeorigin[0]', 'self.planeextent[0]'], {}), '(self.planeorigin[0], self.planeextent[0])\n', (6663, 6705), True, 'import numpy as np\n'), ((6717, 6776), 'numpy.random.uniform', 'np.random.uniform', (['self.planeorigin[1]', 'self.planeextent[1]'], {}), '(self.planeorigin[1], self.planeextent[1])\n', (6734, 6776), True, 'import numpy as np\n'), ((6788, 6847), 'numpy.random.uniform', 'np.random.uniform', (['self.planeorigin[2]', 'self.planeextent[2]'], {}), '(self.planeorigin[2], self.planeextent[2])\n', (6805, 6847), True, 'import numpy as np\n'), ((6873, 6892), 'numpy.array', 'np.array', (['(x, y, z)'], {}), '((x, y, z))\n', (6881, 6892), True, 'import numpy as np\n'), ((6949, 6974), 'numpy.array', 'np.array', (['(0.0, 0.0, 0.0)'], {}), '((0.0, 0.0, 0.0))\n', (6957, 6974), True, 'import numpy as np\n'), ((8392, 8411), 'numpy.array', 'np.array', (['linepoint'], {}), '(linepoint)\n', (8400, 8411), True, 'import numpy as np\n'), ((8441, 8464), 'numpy.array', 'np.array', (['linedirection'], {}), '(linedirection)\n', (8449, 8464), True, 'import numpy as np\n'), ((8658, 8666), 'Trace.Photon', 'Photon', ([], {}), '()\n', (8664, 8666), False, 'from Trace import Photon\n'), ((8784, 8843), 'numpy.random.uniform', 'np.random.uniform', (['self.planeorigin[0]', 'self.planeextent[0]'], {}), '(self.planeorigin[0], self.planeextent[0])\n', (8801, 8843), True, 'import numpy as np\n'), ((8855, 8914), 'numpy.random.uniform', 'np.random.uniform', (['self.planeorigin[1]', 'self.planeextent[1]'], {}), '(self.planeorigin[1], self.planeextent[1])\n', (8872, 8914), True, 'import numpy as np\n'), ((9056, 9075), 'numpy.array', 'np.array', (['(x, y, z)'], {}), '((x, y, z))\n', (9064, 9075), True, 'import numpy as np\n'), ((9132, 9157), 'numpy.array', 'np.array', (['(0.0, 0.0, 0.0)'], {}), '((0.0, 0.0, 0.0))\n', (9140, 9157), True, 'import numpy as np\n'), ((10215, 10253), 'Geometry.Cylinder', 'Cylinder', ([], {'radius': 'radius', 'length': 'length'}), '(radius=radius, length=length)\n', (10223, 10253), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((10673, 10681), 'Trace.Photon', 'Photon', ([], {}), '()\n', (10679, 10681), False, 'from Trace import Photon\n'), ((10843, 10876), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', '(2 * np.pi)'], {}), '(0.0, 2 * np.pi)\n', (10860, 10876), True, 'import numpy as np\n'), ((10886, 10921), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', 'self.radius'], {}), '(0.0, self.radius)\n', (10903, 10921), True, 'import numpy as np\n'), ((11002, 11037), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', 'self.length'], {}), '(0.0, self.length)\n', (11019, 11037), True, 'import numpy as np\n'), ((11102, 11153), 'Geometry.transform_point', 'transform_point', (['local_center', 'self.shape.transform'], {}), '(local_center, self.shape.transform)\n', (11117, 11153), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((11266, 11299), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', '(2 * np.pi)'], {}), '(0.0, 2 * np.pi)\n', (11283, 11299), True, 'import numpy as np\n'), ((11312, 11341), 'numpy.random.uniform', 'np.random.uniform', (['(0.0)', 'np.pi'], {}), '(0.0, np.pi)\n', (11329, 11341), True, 'import numpy as np\n'), ((11437, 11450), 'numpy.cos', 'np.cos', (['theta'], {}), '(theta)\n', (11443, 11450), True, 'import numpy as np\n'), ((12545, 12553), 'Trace.Photon', 'Photon', ([], {}), '()\n', (12551, 12553), False, 'from Trace import Photon\n'), ((12683, 12726), 'numpy.random.uniform', 'np.random.uniform', (['self.phimin', 'self.phimax'], {}), '(self.phimin, self.phimax)\n', (12700, 12726), True, 'import numpy as np\n'), ((12743, 12790), 'numpy.random.uniform', 'np.random.uniform', (['self.thetamin', 'self.thetamax'], {}), '(self.thetamin, self.thetamax)\n', (12760, 12790), True, 'import numpy as np\n'), ((12888, 12901), 'numpy.cos', 'np.cos', (['theta'], {}), '(theta)\n', (12894, 12901), True, 'import numpy as np\n'), ((12959, 12991), 'external.transformations.translation_matrix', 'tf.translation_matrix', (['(0, 0, 0)'], {}), '((0, 0, 0))\n', (12980, 12991), True, 'import external.transformations as tf\n'), ((13006, 13045), 'Geometry.transform_point', 'transform_point', (['self.center', 'transform'], {}), '(self.center, transform)\n', (13021, 13045), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((14082, 14090), 'Trace.Photon', 'Photon', ([], {}), '()\n', (14088, 14090), False, 'from Trace import Photon\n'), ((14232, 14270), 'numpy.random.randint', 'np.random.randint', (['(1)', '(self.spacing + 1)'], {}), '(1, self.spacing + 1)\n', (14249, 14270), True, 'import numpy as np\n'), ((14296, 14334), 'numpy.random.randint', 'np.random.randint', (['(1)', '(self.spacing + 1)'], {}), '(1, self.spacing + 1)\n', (14313, 14334), True, 'import numpy as np\n'), ((14669, 14682), 'numpy.cos', 'np.cos', (['theta'], {}), '(theta)\n', (14675, 14682), True, 'import numpy as np\n'), ((14740, 14772), 'external.transformations.translation_matrix', 'tf.translation_matrix', (['(0, 0, 0)'], {}), '((0, 0, 0))\n', (14761, 14772), True, 'import external.transformations as tf\n'), ((14787, 14826), 'Geometry.transform_point', 'transform_point', (['self.center', 'transform'], {}), '(self.center, transform)\n', (14802, 14826), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((2542, 2551), 'Geometry.norm', 'norm', (['vec'], {}), '(vec)\n', (2546, 2551), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((2568, 2632), 'Geometry.rotation_matrix_from_vector_alignment', 'rotation_matrix_from_vector_alignment', (['self.direction', '[0, 0, 1]'], {}), '(self.direction, [0, 0, 1])\n', (2605, 2632), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((2665, 2692), 'Geometry.transform_direction', 'transform_direction', (['vec', 'R'], {}), '(vec, R)\n', (2684, 2692), False, 'from Geometry import Box, Cylinder, FinitePlane, transform_point, transform_direction, rotation_matrix_from_vector_alignment, norm\n'), ((4702, 4736), 'external.transformations.translation_matrix', 'tf.translation_matrix', (['translation'], {}), '(translation)\n', (4723, 4736), True, 'import external.transformations as tf\n'), ((4814, 4845), 'external.transformations.rotation_matrix', 'tf.rotation_matrix', (['angle', 'axis'], {}), '(angle, axis)\n', (4832, 4845), True, 'import external.transformations as tf\n'), ((7022, 7072), 'numpy.random.uniform', 'np.random.uniform', (['(-self.focussize)', 'self.focussize'], {}), '(-self.focussize, self.focussize)\n', (7039, 7072), True, 'import numpy as np\n'), ((7116, 7166), 'numpy.random.uniform', 'np.random.uniform', (['(-self.focussize)', 'self.focussize'], {}), '(-self.focussize, self.focussize)\n', (7133, 7166), True, 'import numpy as np\n'), ((8932, 8950), 'numpy.tan', 'np.tan', (['self.angle'], {}), '(self.angle)\n', (8938, 8950), True, 'import numpy as np\n'), ((8963, 9022), 'numpy.random.uniform', 'np.random.uniform', (['self.planeorigin[2]', 'self.planeextent[2]'], {}), '(self.planeorigin[2], self.planeextent[2])\n', (8980, 9022), True, 'import numpy as np\n'), ((9205, 9255), 'numpy.random.uniform', 'np.random.uniform', (['(-self.focussize)', 'self.focussize'], {}), '(-self.focussize, self.focussize)\n', (9222, 9255), True, 'import numpy as np\n'), ((9299, 9349), 'numpy.random.uniform', 'np.random.uniform', (['(-self.focussize)', 'self.focussize'], {}), '(-self.focussize, self.focussize)\n', (9316, 9349), True, 'import numpy as np\n'), ((10492, 10526), 'external.transformations.translation_matrix', 'tf.translation_matrix', (['translation'], {}), '(translation)\n', (10513, 10526), True, 'import external.transformations as tf\n'), ((10600, 10631), 'external.transformations.rotation_matrix', 'tf.rotation_matrix', (['angle', 'axis'], {}), '(angle, axis)\n', (10618, 10631), True, 'import external.transformations as tf\n'), ((10951, 10962), 'numpy.cos', 'np.cos', (['phi'], {}), '(phi)\n', (10957, 10962), True, 'import numpy as np\n'), ((10977, 10988), 'numpy.sin', 'np.sin', (['phi'], {}), '(phi)\n', (10983, 10988), True, 'import numpy as np\n'), ((11361, 11372), 'numpy.cos', 'np.cos', (['phi'], {}), '(phi)\n', (11367, 11372), True, 'import numpy as np\n'), ((11373, 11386), 'numpy.sin', 'np.sin', (['theta'], {}), '(theta)\n', (11379, 11386), True, 'import numpy as np\n'), ((11399, 11410), 'numpy.sin', 'np.sin', (['phi'], {}), '(phi)\n', (11405, 11410), True, 'import numpy as np\n'), ((11411, 11424), 'numpy.sin', 'np.sin', (['theta'], {}), '(theta)\n', (11417, 11424), True, 'import numpy as np\n'), ((12812, 12823), 'numpy.cos', 'np.cos', (['phi'], {}), '(phi)\n', (12818, 12823), True, 'import numpy as np\n'), ((12824, 12837), 'numpy.sin', 'np.sin', (['theta'], {}), '(theta)\n', (12830, 12837), True, 'import numpy as np\n'), ((12850, 12861), 'numpy.sin', 'np.sin', (['phi'], {}), '(phi)\n', (12856, 12861), True, 'import numpy as np\n'), ((12862, 12875), 'numpy.sin', 'np.sin', (['theta'], {}), '(theta)\n', (12868, 12875), True, 'import numpy as np\n'), ((14586, 14597), 'numpy.cos', 'np.cos', (['phi'], {}), '(phi)\n', (14592, 14597), True, 'import numpy as np\n'), ((14598, 14611), 'numpy.sin', 'np.sin', (['theta'], {}), '(theta)\n', (14604, 14611), True, 'import numpy as np\n'), ((14630, 14641), 'numpy.sin', 'np.sin', (['phi'], {}), '(phi)\n', (14636, 14641), True, 'import numpy as np\n'), ((14642, 14655), 'numpy.sin', 'np.sin', (['theta'], {}), '(theta)\n', (14648, 14655), True, 'import numpy as np\n'), ((1120, 1139), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (1137, 1139), True, 'import numpy as np\n'), ((1163, 1182), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (1180, 1182), True, 'import numpy as np\n'), ((5519, 5538), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (5536, 5538), True, 'import numpy as np\n'), ((7522, 7541), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (7539, 7541), True, 'import numpy as np\n'), ((9712, 9731), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (9729, 9731), True, 'import numpy as np\n'), ((11687, 11706), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (11704, 11706), True, 'import numpy as np\n'), ((13239, 13258), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (13256, 13258), True, 'import numpy as np\n'), ((15020, 15039), 'numpy.random.uniform', 'np.random.uniform', ([], {}), '()\n', (15037, 15039), True, 'import numpy as np\n')]