Beispiel #1
0
def point_source_p(origin=(0.,0.,0.),direction=(0.,0.,0),span=pi/8,num_rays=(10,10),wavelength=0.58929, label=""):
    """Point source, with a polar beam distribution

    This function creates a point source, where the rays are organized in a
    polar grid.

    Parameters:


    *origin*
        Tuple with the coordinates of the central ray origin
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *span*
        Tuple angular size of the ray pencil.
    *num_rays*
        Tuple (nr,na) containing the number of rays used to create the beam
    *label*
        String used to identify the ray source
    """

    ret_val=[Ray(pos=(0,0,0),dir=(0,0,1),wavelength=wavelength, label=label).ch_coord_sys_inv(origin,direction)]
    nr,nt=num_rays
    for r_ in range(1,nr):
        r=span*float(r_)/nr
        temp_ray=Ray(pos=(0,0,0),dir=(0,0,1),wavelength=wavelength, label=label).ch_coord_sys_inv((0,0,0),(r,0,0))
        for t in range(nt):
            tz=2*pi*t/nt
            temp_ray1=temp_ray.ch_coord_sys_inv((0,0,0),(0,0,tz))
            ret_val.append(temp_ray1.ch_coord_sys_inv(origin,direction))
    return ret_val
Beispiel #2
0
def point_source_r(origin=(0.,0.,0.),direction=(0.,0.,0),span=pi/8,num_rays=100,wavelength=0.58929, label=""):
    """Point source, with a ranrom beam distribution

    This function creates a point source, where the rays are organized in a
    random grid.

    Parameters:


    *origin*
        Tuple with the coordinates of the central ray origin
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *span*
        Tuple angular size of the ray pencil.
    *num_rays*
        Number of rays used to create the beam
    *label*
        String used to identify the ray source
    """

    ret_val=[]

    for n_ in range(num_rays):
        rx=normal(0,span)
        ry=normal(0,span)
        temp_ray=Ray(pos=(0,0,0),dir=(0,0,1),wavelength=wavelength, label=label).ch_coord_sys_inv((0,0,0),(rx,ry,0))
        ret_val.append(temp_ray.ch_coord_sys_inv(origin,direction))
    return ret_val
Beispiel #3
0
def test_intersection():
    # TODO: choose better example
    # Intersecting
    expected_intersection_point = (0, 0, 0)
    ray1 = Ray(pos=expected_intersection_point, dir=(0, 0.2, 1))
    ray2 = Ray(pos=expected_intersection_point, dir=(1, 2, 1))
    intersection_point, real_ = calc.intersection(ray1, ray2)
    np.testing.assert_almost_equal(intersection_point, expected_intersection_point)
    assert real_ == True

    # Not intersecting
    ray1 = Ray(pos=(0, 0, 0), dir=(0, 0.2, 1))
    ray2 = Ray(pos=(1, 0, 0), dir=(0, 0.2, 1))
    intersection_point, real_ = calc.intersection(ray1, ray2)
    np.testing.assert_almost_equal(intersection_point, [np.nan, np.nan, np.nan])
    assert real_ == False
Beispiel #4
0
def test_paraxial_location():
    # image_location, real_ = paraxial_location(opsys, opaxis):
    lens1 = library.Edmund.get("45179")  # f=200 r= 25
    optical_axis = Ray(pos=(0, 0, -10000), dir=(0, 0, 1), wavelength=0.55)
    ccd = CCD(size=(10, 10))
    s = System(
        complist=[
            (lens1, (0, 0, 100), (0, np.pi, 0)),
            (ccd, (0, 0, 320.053), (0, 0, 0)),
        ],
        n=1,
    )
    PB = parallel_beam_c(
        origin=(0, 0, 50),
        direction=(0, 0, 0),
        size=(15, 15),
        num_rays=(15, 15),
        wavelength=0.55,
    )
    s.ray_add(PB)
    s.propagate()

    image_location, real_ = calc.paraxial_location(s, optical_axis)
    np.testing.assert_almost_equal(image_location, [-5.59109334e-16, 0, 3.07249900e02])
    assert real_ == False
Beispiel #5
0
def parallel_beam_p(origin=(0., 0., 0.),
                    direction=(0., 0., 0),
                    radius=0.5,
                    num_rays=(5, 10),
                    wavelength=0.58929,
                    label=""):
    """Polar grid parallel beam
    
    This function creates a parallel beam, where the rays are organized in a 
    polar grid. 
    
    Parameters:
   
    
    *origin*
        Tuple with the coordinates of the central ray origin 
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *r*
        Beam radious 
    *num_rays*
        Tuple (nr,na) containing the number of rays used to create the beam. 
    *label*
        String used to identify the ray source
    """

    ret_val = [
        Ray(pos=(0, 0, 0), dir=(0, 0, 1), wavelength=wavelength,
            label=label).ch_coord_sys_inv(origin, direction)
    ]
    nr, nt = num_rays
    for r_ in range(1, nr):
        r = radius * float(r_) / (nr - 1)
        for t in range(nt):
            x_ = r * sin(2 * pi * t / nt)
            y_ = r * cos(2 * pi * t / nt)
            ret_val.append(
                Ray(pos=(x_, y_, 0),
                    dir=(0, 0, 1),
                    wavelength=wavelength,
                    label=label).ch_coord_sys_inv(origin, direction))
    return ret_val
Beispiel #6
0
def point_source_p(origin=(0., 0., 0.),
                   direction=(0., 0., 0),
                   span=pi / 8,
                   num_rays=(10, 10),
                   wavelength=0.58929,
                   label=""):
    """Point source, with a polar beam distribution
    
    This function creates a point source, where the rays are organized in a 
    polar grid. 
    
    Parameters:
    
    
    *origin*
        Tuple with the coordinates of the central ray origin 
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *span*
        Tuple angular size of the ray pencil.
    *num_rays*
        Tuple (nr,na) containing the number of rays used to create the beam
    *label*
        String used to identify the ray source
    """

    ret_val = [
        Ray(pos=(0, 0, 0), dir=(0, 0, 1), wavelength=wavelength,
            label=label).ch_coord_sys_inv(origin, direction)
    ]
    nr, nt = num_rays
    for r_ in range(1, nr):
        r = span * float(r_) / nr
        temp_ray = Ray(pos=(0, 0, 0),
                       dir=(0, 0, 1),
                       wavelength=wavelength,
                       label=label).ch_coord_sys_inv((0, 0, 0), (r, 0, 0))
        for t in range(nt):
            tz = 2 * pi * t / nt
            temp_ray1 = temp_ray.ch_coord_sys_inv((0, 0, 0), (0, 0, tz))
            ret_val.append(temp_ray1.ch_coord_sys_inv(origin, direction))
    return ret_val
Beispiel #7
0
def test_nearest_points():
    # Real closest point
    ray1 = Ray(pos=(0, 0, 0), dir=(1, 1, 0))
    ray2 = Ray(pos=(1, 0, 1), dir=(0, 1, 0))
    closest_point_on_ray1, closest_point_on_ray2, distance, real_ = calc.nearest_points(
        ray1, ray2)
    np.testing.assert_almost_equal(closest_point_on_ray1, [1.0, 1.0, 0.0])
    np.testing.assert_almost_equal(closest_point_on_ray2, [1.0, 1.0, 1.0])
    assert distance == 1
    assert real_ is True

    # Virtual closest point
    ray1 = Ray(pos=(0, 0, 0), dir=(1, 1, 0))
    ray2 = Ray(pos=(1, 10, 1), dir=(0, 1, 0))
    closest_point_on_ray1, closest_point_on_ray2, distance, real_ = calc.nearest_points(
        ray1, ray2)
    np.testing.assert_almost_equal(closest_point_on_ray1, [1.0, 1.0, 0.0])
    np.testing.assert_almost_equal(closest_point_on_ray2, [1.0, 1.0, 1.0])
    assert distance == 1
    assert real_ is False
Beispiel #8
0
    def pyoptools_repr(self, obj):

        wl = obj.wl.getValueAs("µm").Value

        pla = obj.getGlobalPlacement()
        X, Y, Z = pla.Base

        r_vec = pla.Rotation.multVec(FreeCAD.Base.Vector(0, 0, 1))

        return [
            Ray(pos=(X, Y, Z), dir=(r_vec.x, r_vec.y, r_vec.z), wavelength=wl)
        ]
Beispiel #9
0
def point_source_c(origin=(0.,0.,0.),direction=(0.,0.,0),span=(pi/8,pi/8)\
                     ,num_rays=(10,10),wavelength=0.58929, label=""):
    """Point source, with a cartesian beam distribution 
    
    This function creates a point source, where the rays are organized in a 
    cartesian grid. 
    
    Parameters:
    
    
    *origin*
        Tuple with the coordinates of the central ray origin 
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *span*
        Tuple angular size of the ray pencil.
    *num_rays*
        Tuple (nx,ny) containing the number of rays used to create the beam. 
    *label*
        String used to identify the ray source
    """
    ret_val = []

    nx, ny = num_rays
    dx, dy = span

    for ix in range(nx):
        for iy in range(ny):
            if nx != 1: tx = -dx / 2. + dx * ix / (nx - 1)
            else: tx = 0.

            if ny != 1: ty = -dy / 2. + dy * iy / (ny - 1)
            else: ty = 0.
            temp_ray = Ray(pos=(0, 0, 0),
                           dir=(0, 0, 1),
                           wavelength=wavelength,
                           label=label).ch_coord_sys_inv((0, 0, 0),
                                                         (tx, ty, 0))
            ret_val.append(temp_ray.ch_coord_sys_inv(origin, direction))
    return ret_val
Beispiel #10
0
def point_source_c(origin=(0.,0.,0.),direction=(0.,0.,0),span=(pi/8,pi/8)\
                     ,num_rays=(10,10),wavelength=0.58929, label=""):
    """Point source, with a cartesian beam distribution

    This function creates a point source, where the rays are organized in a
    cartesian grid.

    Parameters:


    *origin*
        Tuple with the coordinates of the central ray origin
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *span*
        Tuple angular size of the ray pencil.
    *num_rays*
        Tuple (nx,ny) containing the number of rays used to create the beam.
    *label*
        String used to identify the ray source
    """
    ret_val=[]

    nx,ny=num_rays
    dx,dy=span

    for ix in range(nx):
        for iy in range(ny):
            if nx!=1: tx=-dx/2.+dx*ix/(nx-1)
            else: tx=0.

            if ny!=1: ty=-dy/2.+dy*iy/(ny-1)
            else: ty=0.
            temp_ray=Ray(pos=(0,0,0),
                         dir=(0,0,1),
                         wavelength=wavelength, label=label
                         ).ch_coord_sys_inv((0,0,0),(tx,ty,0))
            ret_val.append(temp_ray.ch_coord_sys_inv(origin,direction))
    return ret_val
Beispiel #11
0
def point_source_r(origin=(0., 0., 0.),
                   direction=(0., 0., 0),
                   span=pi / 8,
                   num_rays=100,
                   wavelength=0.58929,
                   label=""):
    """Point source, with a ranrom beam distribution
    
    This function creates a point source, where the rays are organized in a 
    random grid. 
    
    Parameters:
   
    
    *origin*
        Tuple with the coordinates of the central ray origin 
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *span*
        Tuple angular size of the ray pencil.
    *num_rays*
        Number of rays used to create the beam
    *label*
        String used to identify the ray source
    """

    ret_val = []

    for n_ in range(num_rays):
        rx = normal(0, span)
        ry = normal(0, span)
        temp_ray = Ray(pos=(0, 0, 0),
                       dir=(0, 0, 1),
                       wavelength=wavelength,
                       label=label).ch_coord_sys_inv((0, 0, 0), (rx, ry, 0))
        ret_val.append(temp_ray.ch_coord_sys_inv(origin, direction))
    return ret_val
Beispiel #12
0
def parallel_beam_c(origin=(0., 0., 0.),
                    direction=(0., 0., 0.),
                    size=(1., 1.),
                    num_rays=(10, 10),
                    wavelength=0.58929,
                    label=""):
    """Cartesian grid parallel beam 
    
    This function creates a parallel beam, where the rays are organized in a 
    cartesian grid. 
    
    Parameters:
    
    
    *origin*
        Tuple with the coordinates of the central ray origin 
    *direction*
        Tuple with the rotation of the beam arround the XYZ axes.
    *size*
        Tuple with the beam's width and the height.
    *num_rays*
        Tuple (nx,ny) containing the number of rays used to create the beam. 
    *label*
        String used to identify the ray source
    """

    ret_val = []

    nx, ny = num_rays
    dx, dy = size

    # note modify this to use traits
    dx = float(dx)
    dy = float(dy)

    for ix in range(nx):
        for iy in range(ny):
            x = -dx / 2. + dx * ix / (nx - 1)
            y = -dy / 2. + dy * iy / (ny - 1)
            ret_val.append(
                Ray(pos=(x, y, 0),
                    dir=(0, 0, 1),
                    wavelength=wavelength,
                    label=label).ch_coord_sys_inv(origin, direction))
    return ret_val
Beispiel #13
0
def test_find_ppp():
    # find_ppp(opsys, opaxis)
    lens1 = library.Edmund.get("45179")  # f=200 r= 25
    optical_axis = Ray(pos=(0, 0, -10000), dir=(0, 0, 1), wavelength=0.55)
    ccd = CCD(size=(10, 10))
    s = System(
        complist=[
            (lens1, (0, 0, 100), (0, np.pi, 0)),
            (ccd, (0, 0, 320.053), (0, 0, 0)),
        ],
        n=1,
    )
    PB = parallel_beam_c(
        origin=(0, 0, 50),
        direction=(0, 0, 0),
        size=(15, 15),
        num_rays=(15, 15),
        wavelength=0.55,
    )
    s.ray_add(PB)
    s.propagate()

    result = calc.find_ppp(s, optical_axis)
    np.testing.assert_almost_equal(result, [0.0, 0.0, 104.5670357])
Beispiel #14
0
def test_intersection():
    # Intersecting exactly
    expected_intersection_point = (3, 1, 1)
    d1 = np.array((0.1, 0.2, 0.3))
    d2 = np.array((1, 0.5, 0))
    t1 = 2
    t2 = 3
    ray1 = Ray(pos=expected_intersection_point - t1 * d1, dir=d1)
    ray2 = Ray(pos=expected_intersection_point - t2 * d2, dir=d2)
    intersection_point, real_ = calc.intersection(ray1, ray2)
    np.testing.assert_almost_equal(intersection_point,
                                   expected_intersection_point)
    assert real_ is True

    # Approximately intersecting
    ray1 = Ray(
        pos=np.array((-1.18414888e-15, 0.0, 5.603)),
        dir=np.array((-5.22664407e-18, 0.0, 1.0)),
    )
    ray2 = Ray(
        pos=np.array((0.01068222, 0.0, 5.60299917)),
        dir=np.array((-5.56560819e-05, 0.0, 9.99999998e-01)),
    )
    intersection_point, real_ = calc.intersection(ray1, ray2)
    expected_intersection_point = np.array((0.0, 0.0, 1.97535672e02))
    np.testing.assert_almost_equal(intersection_point,
                                   expected_intersection_point)
    assert real_ is True

    # Not intersecting
    ray1 = Ray(pos=(0, 0, 0), dir=(0, 0.2, 1))
    ray2 = Ray(pos=(1, 0, 0), dir=(0, 0.2, 1))
    intersection_point, real_ = calc.intersection(ray1, ray2)
    np.testing.assert_almost_equal(intersection_point,
                                   [np.nan, np.nan, np.nan])
    assert real_ is False
Beispiel #15
0
def chief_ray_search(opsys,
                     ccds,
                     o=(0., 0., 0.),
                     rt=(0., 0., 0.),
                     er=0.1,
                     w=pi / 2.,
                     maxiter=1000,
                     wavelength=.58929):
    '''
    This function uses a random search algorithm to find the chief_ray for a 
    given optical system and object point.  
    
    **Algorithm description:**

    The algorithm starts using a given ray, propagating it in the optical
    system, and finding the intersection point of this test ray and the 
    aperture plane. The distance from this point and the optical axis is 
    recorded.
    
    Using a gaussian random generator, two rotation angles are calculated,
    to generate a new test ray that is propagated in the optical system, 
    and its distance to the optical axis is found at the aperture plane. 
    If this distance is less than the distance found for the previous ray,
    this ray is taken as the new *chief ray* candidate, and  the algorithm
    is repeated until the number of iterations reaches *maxiter*, or until
    the distance is less than *er*.
    
    the *rt* parameter gives the rotations made to a ray originating in 
    *o*, and propagating in the *Z* direction, to find the first test ray.
    
    A detector object *ccds* should be placed at the aperture plane. It is used
    to find the point where the ray intersects the aperture. To increase the 
    convergense speed of the algorithm, it is better to make sure that the first
    test ray intersects the detector.
    
    **Parameters:**
 
        ==========  ======================================================
        opsys       Optical system that will be used to find the chief ray
        ccds        Detector placed in the aperture plane. Should be 
                    centred in the optical axis 
        o           Tuple, list or numpy array indicating the coordinates
                    of the object point used to find the chief ray
        rt          Tuple with the rotations made to a ray propagating in
                    the z direction to obtain the first test ray
        er          Maximum acceptable distance between the ray and the 
                    center of the aperture
        w           Gaussian width in radians
        wavelength  Wavelength of the ray used to find the principal ray given
                    in micrometers (.58929 by default).
        ==========  ======================================================
    
    **Return Value:**
        
        Chief ray found. (Ray instance)
        
        
    .. todo:: 
        Implement a function similar to this one, using a minimization
        algorithm         
    '''

    #log.info("Entering chief_ray_search function")
    test_ray = Ray(wavelength=wavelength)
    opsys.clear_ray_list()

    btx, bty, btz = rt  #btz is not used
    ntry = 0
    nt = 0
    #Check the initial test ray
    retray = test_ray.ch_coord_sys_inv(o, (btx, bty, 0))
    #log.info("Calculating test_ray")
    opsys.clear_ray_list()
    opsys.reset()
    opsys.ray_add(retray)
    opsys.propagate()
    try:
        x, y, z = ccds.hit_list[0][0]
        dist = sqrt(square(x) + square(y))
    except:
        dist = inf

    p_dist = dist

    while (p_dist > er) and (ntry < maxiter):
        ntry = ntry + 1
        nt = nt + 1
        rx = normal(btx, w)
        ry = normal(bty, w)
        tray = test_ray.ch_coord_sys_inv(o, (rx, ry, 0))

        opsys.clear_ray_list()
        opsys.reset()
        opsys.ray_add(tray)
        opsys.propagate()
        try:
            x, y, z = ccds.hit_list[0][0]
            dist = sqrt(square(x) + square(y))
        except:
            #log.info("CCD not hitted by ray")
            dist = inf

        if p_dist > dist:
            #Select this ray as new generator ray

            btx = rx
            bty = ry
            p_dist = dist
            nt = 0
            retray = tray
            #log.info("distance to aperture center="+str(dist))
        if (nt > 10) and p_dist < inf:
            nt = 0
            w = w / 2
        #limit the minimum value of w
        if w < .0000001: w = .0000001
    # print p_dist,ntry
    return retray
Beispiel #16
0
def chief_ray_search(opsys,ccds,o=(0.,0.,0.),rt=(0.,0.,0.),er=0.1,w=pi/2.,maxiter=1000,wavelength=.58929):
    '''
    This function uses a random search algorithm to find the chief_ray for a 
    given optical system and object point.  
    
    **Algorithm description:**

    The algorithm starts using a given ray, propagating it in the optical
    system, and finding the intersection point of this test ray and the 
    aperture plane. The distance from this point and the optical axis is 
    recorded.
    
    Using a gaussian random generator, two rotation angles are calculated,
    to generate a new test ray that is propagated in the optical system, 
    and its distance to the optical axis is found at the aperture plane. 
    If this distance is less than the distance found for the previous ray,
    this ray is taken as the new *chief ray* candidate, and  the algorithm
    is repeated until the number of iterations reaches *maxiter*, or until
    the distance is less than *er*.
    
    the *rt* parameter gives the rotations made to a ray originating in 
    *o*, and propagating in the *Z* direction, to find the first test ray.
    
    A detector object *ccds* should be placed at the aperture plane. It is used
    to find the point where the ray intersects the aperture. To increase the 
    convergense speed of the algorithm, it is better to make sure that the first
    test ray intersects the detector.
    
    **Parameters:**
 
        ==========  ======================================================
        opsys       Optical system that will be used to find the chief ray
        ccds        Detector placed in the aperture plane. Should be 
                    centred in the optical axis 
        o           Tuple, list or numpy array indicating the coordinates
                    of the object point used to find the chief ray
        rt          Tuple with the rotations made to a ray propagating in
                    the z direction to obtain the first test ray
        er          Maximum acceptable distance between the ray and the 
                    center of the aperture
        w           Gaussian width in radians
        wavelength  Wavelength of the ray used to find the principal ray given
                    in micrometers (.58929 by default).
        ==========  ======================================================
    
    **Return Value:**
        
        Chief ray found. (Ray instance)
        
        
    .. todo:: 
        Implement a function similar to this one, using a minimization
        algorithm         
    '''
    
    #log.info("Entering chief_ray_search function")
    test_ray=Ray(wavelength=wavelength)
    opsys.clear_ray_list()

    btx,bty,btz=rt #btz is not used
    ntry=0
    nt=0
    #Check the initial test ray
    retray=test_ray.ch_coord_sys_inv(o,(btx,bty,0))
    #log.info("Calculating test_ray")
    opsys.clear_ray_list()
    opsys.reset()
    opsys.ray_add(retray)
    opsys.propagate()
    try:
        x,y,z=ccds.hit_list[0][0]
        dist=sqrt(square(x)+square(y))
    except:
        dist=inf
        
    p_dist=dist
    
    while (p_dist> er)and (ntry<maxiter):
        ntry=ntry+1
        nt=nt+1
        rx=normal(btx,w)
        ry=normal(bty,w)
        tray=test_ray.ch_coord_sys_inv(o,(rx,ry,0))
        
        opsys.clear_ray_list()
        opsys.reset()
        opsys.ray_add(tray)
        opsys.propagate()
        try:
            x,y,z=ccds.hit_list[0][0]
            dist=sqrt(square(x)+square(y))
        except:
            #log.info("CCD not hitted by ray")
            dist=inf

        if p_dist>dist:
            #Select this ray as new generator ray
            
            btx=rx
            bty=ry
            p_dist=dist
            nt=0
            retray=tray
            #log.info("distance to aperture center="+str(dist))
        if (nt>10)and p_dist<inf:
            nt=0
            w=w/2
        #limit the minimum value of w
        if w<.0000001: w=.0000001
    # print p_dist,ntry
    return retray