Beispiel #1
0
    def getImage(self, xpixel=256, ypixel=None, nrays=50):
        """
        Get the knife edge image

        :param xpixel: xsize of image (Default = 256)
        :type xpixel: int
        :param ypixel: ysize of image (Deault = None ) same as xpixel
        :type ypixel: int or None
        :param nrays: number or rays, (Default = 50)
        :param nrays: int
        :return: OpticalImage

        """

        #      Make the raypencil
        pencil = ray.RayPencil().addBeam(self.lens, self.source, "array",
                                         nrays, self.wavelength)
        pencil *= self.lens  # Propagate through lens.

        psf = self.lens.imagePoint(self.source,
                                   self.design)  # Paraxial point location
        if self.refopt == 1:
            psf = Psf().setWithRays(pencil, psf.z)  # Optimal positin in plane
        if self.refopt == 2:
            psf = Psf().optimalArea(pencil, psf.z)  # Make optimal PSF

        self.knife.setPoint(psf)  # Set the position of the knife

        #          Set position of ouput plane, being one focal length beyond psf in direction from back nodal point
        fl = self.lens.backFocalLength(self.design)
        bn = self.lens.backNodalPoint(self.design)
        u = Unit3d(psf - bn)  # Direction
        xsize = 3.0 * self.lens.entranceAperture(
        ).maxRadius  # Size of output feild
        output = OpticalImage(psf.propagate(fl, u), xpixel, ypixel, xsize,
                              xsize)
        pencil *= self.knife  # propagate through knife edge
        pencil *= output  # Then to output (will give shadow image)

        return output
Beispiel #2
0
def main():

    #      Get lens from database
    lens = DataBaseLens()

    #           Get angle of beam and wavelnegth
    angle = getFloat("Angle in degrees", 0.0, 0.0, 15.0)
    u = Unit3d(Angle().setDegrees(angle))  # Angle as unit vectr
    w = getFloat("Wavelength", Default)

    #    Make two ray pencils, one for spot diagram and one for display (vertical only)
    pencil = RayPencil().addBeam(lens, u, "array", wavelength=w)
    vpencil = RayPencil().addBeam(lens, u, "vl",
                                  wavelength=w).addMonitor(RayPath())
    bf = lens.backFocalPlane()

    #            Propagate through lens to back focal plane
    pencil *= lens

    vpencil *= lens
    vpencil *= bf

    #            Get optimal area psf and create a SpotDiagram
    sd = SpotDiagram(pencil)

    #             Go round loop plotting the sopt diagram as various zplane positions

    while True:
        zp = getFloat("Zplane", bf.getPoint().z)
        plane = OpticalPlane(zp)
        plt.subplot(2, 1, 1)
        lens.draw()
        vpencil.draw()
        plt.axis("equal")
        plt.title("Lens " + lens.title)

        plt.subplot(2, 1, 2)
        sd.draw(plane, True)
        plt.title("Spot diagram")
        plt.show(block=True)
Beispiel #3
0
def main():

    #      Get the materail type and make a prism of default angle, size and location
    n = MaterialIndex()
    prism = Prism(index=n)
    tprint(repr(prism))

    #      Get input point on prism and min deviation at Mercury_i line
    pt = prism.getInputPoint()
    dev = prism.minDeviation(Mercury_e)
    tprint("Min deviation : ", math.degrees(dev), " at : ", Mercury_e)
    tprint("Max resolutions is ", prism.maxResolution(Mercury_e))
    tprint("Resolution with 20 mm diameter beam : ",
           prism.resolution(10, Mercury_e))

    u = Unit3d().parseAngle(dev /
                            2)  # Set ray input angle at half min deviation

    #      Form np array of wavelength and angle
    wavelengths = np.linspace(Mercury_i, Helium_r, 50)
    angle = np.zeros(wavelengths.size)

    #      Go through each wavelength, make a ray and trace it
    for i, wave in enumerate(wavelengths):
        ray = r.IntensityRay(pt, u, wave)
        ray *= prism
        #      Extract angle of ray in degrees
        angle[i] = math.degrees(Angle(ray.director).theta)

    # Do the plotting

    plt.plot(wavelengths, angle)
    plt.title("Spectrometer Output angle")
    plt.xlabel("Wavelength in microns")
    plt.ylabel("Output angle in degrees")
    plt.grid()

    plt.show()
def main():

    #      Get lens from database
    lens = DataBaseLens()

    #           Get angle of beam and wavelnegth
    angle = getFloat("Angle in degrees", 0.0, 0.0, 15.0)
    u = Unit3d(Angle().setDegrees(angle))  # Angle as unit vectr
    wave = getFloat("Wavelength", getDefaultWavelength())

    #            Get optimal area psf and create a SpotDiagram
    sd = SpotAnalysis(lens, u, 0, wavelength=wave)

    #             Go round loop plotting the sopt diagram as various zplane positions

    while True:
        zp = getFloat("Delta", 0.0)

        sd.draw(zp, True)
        pos = sd.plane.getPoint().z
        print("Plane pos " + str(pos))
        plt.title("Spot diagram")
        plt.show(block=True)
Beispiel #5
0
def main():

    eye = Eye(0.0)
    print("Original Focalength : " + str(eye.backFocalLength(wl.PhotopicPeak)))
    #eye.setIris(0.5)
    eye.moveRetina(1.0)

    #eye.setNearPoint(300)
    #print("Modified Focalength : " + str(eye.backFocalLength(wl.PhotopicPeak)))

    theta = 10
    u = Unit3d().parseAngle(math.radians(theta))
    pencil = RayPencil().addBeam(eye, u, "vl", 10, wl.Red)
    pencil.addBeam(eye, u, "vl", 10, wl.Green)
    pencil.addBeam(eye, u, "vl", 10, wl.Blue)
    pencil.addMonitor(RayPath())
    pencil *= eye

    eye.draw()
    pencil.draw()
    plt.axis("equal")
    plt.grid()
    plt.show()
Beispiel #6
0
def main():

    doublet = AchromaticDoublet(0.0, 120, 20.0, ct=10)  # 120mm, 20mm radius
    t.tprint("Focal length is :", doublet.backFocalLength())
    u = Unit3d().parseAngle("5")  # trace at 5 degrees

    #           Make ray pencil of three coloured rays
    pencil = RayPencil().addBeam(doublet, u, nrays=5, wavelength=Red)
    pencil.addBeam(doublet, u, nrays=5, wavelength=Green)
    pencil.addBeam(doublet, u, nrays=5, wavelength=Blue)
    pencil.addMonitor(RayPath())  # Add monitor to all rays to allow plotting

    ip = doublet.backFocalPlane()  # Back focal plane
    pencil *= doublet  # Propagte through lens to back focal plane
    pencil *= ip

    #      Draw the diagram
    doublet.draw(True, True)
    ip.draw()
    pencil.draw()
    plt.axis("equal")
    plt.grid()
    plt.title(repr(doublet))
    plt.show()
Beispiel #7
0
def getWavelength(prism, inAngle, outAngle, wavelengths=[0.25, 1.0]):

    #        Get prism point and angle of input at Unit3d
    #
    pt = prism.getInputPoint()
    u = Unit3d(Angle(inAngle))

    #         Guess at initial wavelngth
    wave = (wavelengths[1] - wavelengths[0]) / 2
    #         Make input ray at guess wavelength
    ray = IntensityRay(pt, u, wave)

    #       Parameters for seaerch
    delta = 0.1
    forward = True
    na = float("inf")  # New angle

    while abs(na - outAngle) > 1.0e-9 / abs(outAngle):
        nray = ray * prism  #      New Ray through prism
        na = nray.getAngle()
        na = na.theta * math.cos(na.psi)  # In radians
        if na < outAngle:  # Less that target
            wave += delta
            forward = True
        else:
            if forward:  # Half step
                delta *= 0.5
            forward = False
            wave -= delta
        if wave < wavelengths[0] or wave > wavelengths[1]:
            print("Out of wavelength range :")
            return float("nan")

        ray.wavelength = wave  # Update wavelength of ray

    return ray.getWavelength()  # End of loop, so success
Beispiel #8
0
 def __init__(self,pt = 0.0 ,type = Clear, index = None):
     """
     Conststrucor for Optical plane
     """
     FlatSurface.__init__(self,pt,Unit3d(0,0,1),type,index)
Beispiel #9
0
Set of classes to implement various types of optical surface.

"""
from poptics.vector import Vector2d,Vector3d,Unit3d
from poptics.ray import SourcePoint
from poptics.matrix import ParaxialGroup
import math
from matplotlib.pyplot import plot

"""
Define the three types of surface.
"""
Clear = 0             #: Define a clear surface.
Refracting = 1        #: Define a refracting surface.
Reflecting = 2        #: Define a reflecting surface,
Blocked = Unit3d()    #: Define blacoked as an invalid Units3d

"""
Define surface plotting parameter
"""
SurfacePlotPoints = 10

class SurfaceInteraction(object):
    """
    Class to hold the interaction of a vector skew ray with a general surface.
    It contains all the information needed to calualte the interaction and update the ray.

    :param type: the type of surface, Clear = 0, Refracting = 1, Reflecting = 2.
    :type type: int
    :param point: the surface reference point in global coordinate.
    :type point: Vector3d
Beispiel #10
0
    def drawAberrationPlot(self,angle,wavelength = None ,colour=["r","g","b"],legend = "lower left"):
        """
        Form and draw the plots at specified angle

        :param angle: the ray angle
        :type angle: float or Angle or Unit3d
        :param colour: line colours is three elemnts list, Default = ["r","g","b"])
        :param legend: location of ledgend, (Default = "lower left")
        :type legend: str
        """
        if isinstance(angle,float):
            u = Unit3d(Angle(angle))                     # direction of beam
        else:
            u = Unit3d(angle)
            angle = Angle(u).theta

        wavelength = getDefaultWavelength(wavelength)
        ref = self.lens.imagePoint(u,self.design)    # Get image point at design wavelength
        ip = OpticalPlane(ref)                        # Image plane

        nrays = 50
        ca = self.lens.entranceAperture()


        #         Make list for plots
        mvals = []                # Meridional
        svalsx = []               # Sagittal x
        svalsy = []               # Sagittal y


        #              Start of loop to make rays
        rscan = np.linspace(-ca.maxRadius,ca.maxRadius,nrays + 1)
        for r in rscan:
            # Make two rays
            mray = IntensityRay(ca.point + Vector3d(0.0, r, 0.0), u, wavelength)
            sray = IntensityRay(ca.point + Vector3d(r, 0.0, 0.0), u, wavelength)

            #       Add to pencil and propagate both back to clear lens
            pencil = RayPencil(mray,sray).propagate(-ca.maxRadius)
            #         propagate through lens to image surafce
            pencil *= self.lens
            pencil *= ip

            #            If rays valid (so not blocked), abberations to list
            if mray:
                mpos = mray.position - ref
                mvals.append(mpos.y)
            else:
                mvals.append(float("nan"))
            if sray:
                spos = sray.position - ref
                svalsx.append(spos.x)
                svalsy.append(spos.y)
            else:
                svalsx.append(float("nan"))
                svalsy.append(float("nan"))


        # plots with suitable labels to the current axis.

        plt.plot(rscan,mvals, color = colour[0], label="Meridional")
        plt.plot(rscan,svalsx,color = colour[1], label="Sagittal x")
        plt.plot(rscan,svalsy,color = colour[2], label="Sagittal y")
        plt.title("{0:s}: a: {1:4.2f} w: {2:4.2f} d: {3:4.2f}".\
                  format(self.lens.title,math.degrees(angle),wavelength,\
                  self.design))
        plt.legend(loc=legend,fontsize="small")
        plt.grid()
Beispiel #11
0
 def valueChange(self):  # For either spinned
     self.theta = self.thetaSpin.value()
     self.psi = self.psiSpin.value()
     u = Unit3d().setPolarDegrees(self.theta, self.psi)
     setCurrentAngle(u)
     self.unitLabel.setText(str(getCurrentAngle()))
Beispiel #12
0
    def addBeam(self,
                ca,
                source,
                key="vl",
                nrays=10,
                wavelength=None,
                intensity=1.0,
                index=AirIndex(),
                path=False):
        """
        Method to add a beam if intensity rays being either Collimated or Source Beam. The beam will fill the given circular aperture and will
        either come from a single SourcePoint or at a specified angle.

        :param ca: circular aperture to filled (any object with maxRadius attribute)
        :type ca: optics.surface.CircularAperture
        :param source: source or rays, either a SourcePoint or angle.
        :type source: SourcePoint or Vectore3d or Unit3d or Angle or float
        :param key: method of fill, allowed keys as "vl", "hl" and "array",(default is "vl")
        :type key: str
        :param nrays: number or rays across radius, (default = 10)
        :type nrays: int
        :param wavelenth: the wavelength, (default = Default)
        :type wavelength: float
        :param intensity: the ray intensity, (default = 1.0) only used for Collimated beam; for SourceBeam picked up from SourcePoint
        :type intensity: float
        :param index: the refratcive index, (Default = AirIndex())
        :type index: RefractiveIndex
        :param path: record pathlength, (default = False) is pathlength of each ray recorded
        :type path: bool
        :return: self

        """

        #          Sort out aperture to fill.
        if not hasattr(ca, "maxRadius"):
            ca = ca.entranceAperture()
        pt = ca.getPoint()  # Reference point
        radius = ca.maxRadius

        if isinstance(source, SourcePoint):  # Rays from a source
            s = Vector3d(source)
            intensity = source.getIntensity(wavelength)
        else:
            s = Vector3d().setInvalid(
            )  # Set s unvalid (will be used for testing)
            u = Unit3d().parseAngle(source)

        rscan = linspace(-radius, radius, 2 * nrays +
                         1)  # Point across radius (make sure one in centre)
        if key.startswith("ar"):
            xscan = rscan
            yscan = rscan
        elif key.startswith("vl"):
            xscan = [0.0]
            yscan = rscan
        elif key.startswith("hl"):
            xscan = rscan
            yscan = [0.0]
        else:
            print("Error")

        # Scan through making the rays
        for y in yscan:
            for x in xscan:
                if x * x + y * y <= radius * radius:  # Ignore if outside radius of aperture
                    p = Vector3d(
                        pt.x + x, pt.y + y,
                        pt.z)  # Point in aperture in global coordinates
                    if s:  # From source
                        u = Unit3d(p - s)
                        ray = IntensityRay(s, u, wavelength, intensity,
                                           index)  # Make source ray
                    else:  # Collimated beam
                        dist = float(radius + x * u.x + y * u.y)
                        p -= dist * u  # Propagate point to make it look nicer
                        ray = IntensityRay(p, u, wavelength, intensity,
                                           index)  # Make collimated
                    if path:
                        ray.pathlength = 0.0
                    self.append(ray)  # Append to self

        return self
Beispiel #13
0
"""
Set of classes to hold rays for optical ray tracing. This includes Paraxial and Intensity rays.
"""
import math
from poptics.vector import Vector3d, Vector2d, Unit3d, Angle
from poptics.wavelength import Spectrum, AirIndex, WavelengthColour, getDefaultWavelength
from poptics.matrix import ParaxialMatrix, ParaxialGroup, ParaxialPlane
from matplotlib.pyplot import plot
from numpy import linspace

Clear = 0  #: Defeine a clear surface.
Refracting = 1  #: Define a refracting surface.
Reflecting = 2  #: Define a reflecting surface,

#   Global Current Angle (mainly used by GUI)
CurrentAngle = Unit3d(0.0, 0.0, 1.0)


def getCurrentAngle():
    """
    Get the current angle used in the package, typically called from GUI interface.
    The Default is (0,0,1) so along the optical axis.

    :return: The current angle global value
    """
    return CurrentAngle


def setCurrentAngle(u):
    """
    Method to set a current angle, typivcally used by the GUI intreface