예제 #1
0
    def __init__(self,
                 pos,
                 dirn,
                 wavelength=None,
                 intensity=1.0,
                 index=AirIndex()):
        """
        Constructor for to set parameters

        """
        if isinstance(pos, ParaxialRay):
            Ray.__init__(self, pos.wavelength, pos.intensity,
                         pos.refractiveindex)
            self.position = Vector3d(0.0, pos.h, pos.z)
            self.director = Unit3d(Angle(pos.u))
        else:
            if isinstance(pos, SourcePoint):
                intensity = pos.spectrum
            Ray.__init__(self, wavelength, intensity,
                         index)  # Set wavelnegth intensity and index in super
            self.position = Vector3d(
                pos
            )  # Make localcopy of Position and Director (since they get updated)
            self.director = Unit3d(dirn)
        self.pathlength = None  # Set opl to none (not calculated)
예제 #2
0
    def imagePoint(self, op):
        """
        Method to calcualte three-dimensional image of a point in object space in global
        coordinates using geometric optics. op be in range of formats:

        - float, Angle, Unit3d: assumes an infinite object.
        - Vector3d: finite object at specified vector location.

        :param op: Position of object point
        :type op: Vector3d or  Unit3d or Angle or float
        :return: Position the image point as vector.Vector3d

        This is

        """

        if isinstance(op, (float, int, Unit3d, Angle)):  # Infitite Object
            op = Unit3d().parseAngle(op)  # Sort out angle
            p = Vector3d(0, 0, self.backNodalPoint())
            return Vector3d(p + op * (self.backFocalLength() / op.z))

        elif isinstance(op, Vector3d):  # Finite object
            u = self.frontPrincipalPlane() - op.z
            v = u / (self.backPower() * u - 1)
            ip = self.backPrincipalPlane() + v  # Image location
            mag = -v / u
            return Vector3d(mag * op.x, mag * op.y, ip)

        else:
            raise TypeError(
                "matrix.ParaxialGroup.pointImage: called with unknown type {0:s}"
                .format(str(op)))
예제 #3
0
    def __init__(self, pt=0.0, radius=1.0):

        if isinstance(pt, (float, int)):
            self.point = Vector3d(0.0, 0.0, pt)
        else:
            self.point = Vector3d(pt)

        self.maxRadius = float(radius)
예제 #4
0
 def __init__(self, pos, s=1.0):
     """
     Create a 3d source point
     """
     if isinstance(pos, (float, int)):
         Vector3d.__init__(self, 0, 0, pos)
     else:
         Vector3d.__init__(self, pos)
     if isinstance(s, Spectrum):  # Add spectrum if given
         self.spectrum = s
     else:
         self.spectrum = Spectrum(s)  # Set constant spectrum
예제 #5
0
def getVector3d(prompt, default=None, maxabs=None):
    """
    Read a Vector3d from the terminal with checking.

    Format from terminal may be 'x,y,z'   OR   '[x,y,z]',  also each componet
    will be evaluated.

    :param prompt:  the prompt to be displayed
    :type prompt: str
    :param  default: the default value (may be None)
    :type default: Vector3d
    :param maxabs: abs max value of the Vector3d (defaults to None)
    :type maxabs: float
    :return: the set Vector3d

    Its also Tries to evaluate any sensible string as a Vector3d.
    """
    if maxabs == None:
        maxabs = float("Inf")
    while True:
        val = __getInput(prompt, default)
        try:
            if isinstance(val, str):          # Its a string
                val = eval(val)              # Eval list

            vec = Vector3d(val)

            if abs(vec) <= maxabs:
                return vec                  #  Success
            else:
                logger.error("Abs value of '{0:s}' greater than '{1:6.3e}'".\
                             format(repr(vec), maxabs))
        except (ValueError,NameError,ZeroDivisionError,SyntaxError):
            logger.error("Conversion of '{0:s}' to Vector3d failed.".format(str(val)))
예제 #6
0
def main():

    lens = DataBaseLens("Tessar-F6.3")
    lens.setIris(0.7)
    u = Unit3d().parseAngle("5")
    pencil = RayPencil().addBeam(lens, u, "array", path=True)

    pencil *= lens
    ep = lens.exitPupil()
    t.tprint(repr(ep))
    rpt = lens.imagePoint(u)
    rpt += Vector3d(0, 0, 0.2)
    t.tprint("Image point is ", repr(rpt))

    ws = WavePointSet(ep.getRadius()).setWithRays(pencil, ep, refpt=rpt)

    zw = ws.fitZernike(4)
    t.tprint(repr(zw))
    t.tprint("Error is : ",
             str(ws.zerr))  # Show the fitting error for each component
    zw.plot()

    ws.plot()

    inter = Interferometer(zw)
    inter.draw(0.0, 0.0)
    plt.show()
예제 #7
0
    def __init__(self,
                 pt=Vector3d(),
                 xpixel=256,
                 ypixel=None,
                 xsize=200,
                 ysize=None,
                 wave=TriColour):
        """
        Form the OpticalImage with either blank array of nmpy image array
        """

        if isinstance(pt, ImagePlane):  # Deal with ImagePlane
            ImagePlane.__init__(self, pt.point, pt.xsize, pt.ysize)
        else:
            if ysize == None:
                ysize = xsize
            ImagePlane.__init__(self, pt, xsize,
                                ysize)  # Set underying ImagePlane

        if isinstance(xpixel, int):
            if ypixel == None:
                ypixel = xpixel
            self.image = np.zeros((xpixel, ypixel, 3))  # Make array of zeros.
        else:
            self.image = xpixel  # assume numpy array given
        self.xpixel, self.ypixel, c = self.image.shape  # set xpixel and ypixel from image data
        self.wavelengths = wave
예제 #8
0
 def __init__(self,lens, design = None):
     """
     Constructor
     """
     self.lens = lens
     self.design = getDesignWavelength(design)
     self.refpt = Vector3d()
     self.ip = self.lens.backFocalPlane(self.design)              # Make back focal plane to proagate to
예제 #9
0
    def getPoint(self):
        """
        Method to get the group point, used by other optics classes.

        :return: get the group point Vector3d

        For compatibility for OpticalGroup.
        """
        return Vector3d(0.0, 0.0, self.input_plane)
예제 #10
0
    def getWavePointSet(self,source,wave = None,nrays = 10,refopt = 1):
        """
        Get the WavePointSet for collimated beam in the exitpupil of the lens

        :param source: source of input beeam, either SourcePoint, Unit3d or angle.
        :type source: SourcePoint, Unit3d, Angle or float
        :param wave: analysis wavelength
        :type wave: float
        :param nrays: number of raays across input aperture, (Default = 10)
        :type nrays: int
        :param refopt: reference point option, 0 = paraxial, 1 = centre of PSF in image plane, 2 = optimal area PSF
        :type refopt: int
        """
        #       Sort out angle
        if isinstance(source,SourcePoint):
            u = Vector3d(source)
        elif isinstance(source,float) or isinstance(source,int):
            u = Unit3d(Angle(source))
        else:
            u = Unit3d(source)

        #      Make pencil with array and record path, and propagate through lens
        pencil = RayPencil().addBeam(self.lens,u,"array",nrays=nrays,wavelength=wave,path=True)
        pencil *= self.lens

        #        Get image point of object
        self.refpt = self.lens.imagePoint(u,self.design)    # Paraxial point location
        pt = self.lens.getPoint()
        self.ip = OpticalPlane(Vector3d(pt.x,pt.y,self.refpt.z))

        if refopt == 0:       # got what we need aready
            None
        elif refopt == 1:
            self.refpt = Psf().setWithRays(pencil,self.ip)              # Centre of PSF in image plane
        elif refopt == 2:
            self.refpt = Psf().optimalArea(pencil,self.ip)              # Optimal area PSF, not in image plane
        else:
            print("Illegal ref type")

        ep = self.lens.exitPupil(self.design)         # Exit pupil of lens

        #     Form the wavefront
        wf = WavePointSet(ep.getRadius()).setWithRays(pencil,ep,self.refpt)
        return wf
예제 #11
0
def main():

    a = Vector3d(1,2,3)
    b = a.set([4,5,6])
    print(repr(b))
    u = Unit3d().parseAngle("35","71")
    print(repr(u))

    v = getUnit3d("Direction")
    print(repr(v))
예제 #12
0
파일: psf.py 프로젝트: will-hossack/Poptics
    def __init__(self,
                 pos=0.0,
                 intensity=1.0,
                 major=1.0,
                 minor=None,
                 alpha=0.0,
                 wavelength=None):
        """
        Constructor
        """

        if isinstance(pos, float):
            Vector3d.__init__(self, [0.0, 0.0, pos])
        else:
            Vector3d.__init__(self, pos)
        self.intensity = 1.0
        self.major = major
        if minor == None:
            self.minor = self.major
        else:
            self.minor = minor
        self.alpha = alpha
        self.wavelength = getDefaultWavelength(wavelength)
예제 #13
0
    def setPoint(self,pt = 0.0):
        """
        Method to set the surface reference point in a consistent way for
        all surfaces. The specified point can be copy from Surface, Vector3d,
        list, truple, Vector2d or float/int.

        :param pt: surface point can be Surface, Vector3d, 3 component list/truple, Vector2d with z = 0, float giving (0,0,z), (Default = 0.0)
        :type z_or_v: Vector3d, list[], Vector2d or float
        :return: self

        """
        if isinstance(pt,Surface):
            self.point = pt.point.copy()
        elif isinstance(pt,(Vector3d,list,tuple)):
            self.point = Vector3d(pt)
        elif isinstance(pt,Vector2d):
            self.point = Vector3d(pt.x,pt.y,0.0)
        elif isinstance(pt,(float,int)):
            self.point = Vector3d(0.0,0.0,pt)
        else:
            raise TypeError("surface.Surface.setPoint: called with unknown type")

        return self
예제 #14
0
    def getSurfaceInteraction(self,ray):
        """
        Method to get get  surface interaction information for a ray.

        :param ray: the Ray
        :type ray: poptics.ray.Ray
        :return: SurfaceInteration with reference point and other parameters invalid

        This is abstract surface, so only type, surface point and
        refarctive index will be valid.
        """
        pt = self.getPoint()
        return SurfaceInteraction(self.type,pt,float("nan"),\
                Vector3d().setInvalid(),Blocked,self.refractiveindex)
예제 #15
0
    def setKnife(self,knife = 0.0, theta = 0.0, shift = 0.0):
        """
        Set the knife parameters

        :param knife: distance of knife edge from axis (Default = 0.0)
        :type knife: float
        :param theta: angle of knife edge wrt to y-axis in radians (Default = 0.0)
        :type theta: float
        :param shift: distance along the z axis from the aperture position (Default = 0.0)
        :type shift: float

        """
        self.knife = float(knife)
        self.theta = float(theta)
        self.shift = Vector3d(0.0,0.0,shift)        # Hold shift as vector
        return self
예제 #16
0
    def incrementPoint(self,delta):
        """
        Move the reference point by specifed amount. Distance moved
        can be a Vector3d OR float where the movement will be along the
        z-axis.

        :param delta: distance moved
        :type delta: Vector3d or float
        :return: self
        """
        if isinstance(delta,(float,int)):
            self.point += Vector3d(0.0,0.0,float(delta))
        else:
            self.point += delta

        return self
예제 #17
0
    def getGradient(self, ray):
        """
        Method to calcualte the Gradient as specifed ray position
        """
        p = ray.position

        n = self.index.getValue(ray)

        x = p.x - self.point.x
        y = p.y - self.point.y
        rsqr = x * x + y * y

        dx = 2 * n * x * self.coef[1]
        dy = 2 * n * y * self.coef[1]
        """
        for i in range(2,len(self.coef)):
            r = math.pow(rsqr,i-1)
            dx += 2*x*n*i*coef[i]*r
            dy += 2*y*n*i*coef[i]*r
        """

        return Vector3d(dx, dy, 0.0)
예제 #18
0
def main():

    #        Form two apertures both 20mm with Iris closed to 0.5 ratio
    ca = CircularAperture(50, 20)
    iris = IrisAperture(80, 20, 0.5)
    #        source for the rays at (0,10,-50) in global coordinates
    source = SourcePoint(Vector3d(0.0, 10, -50))
    #        Form a pencil is the circular aperture as specified angle of 0.45 microns
    #        and add a RayPath to ech ray
    pencil = RayPencil().addBeam(ca, source,
                                 wavelength=0.65).addMonitor(RayPath())

    #        Propgate throgh the the both aperture and another 30 mm to make it visible
    pencil *= ca
    pencil *= iris
    pencil += 30

    #               Make a diagram
    ca.draw()
    iris.draw()
    pencil.draw()
    plt.axis("equal")
    plt.show()
예제 #19
0
 def __str__(self):
     """
     Implement str
     """
     return Vector3d.__str__(self) + " s: " + str(self.spectrum)
예제 #20
0
 def getPoint(self):
     """
     Method to get the input point. used by orher optics classes
     """
     return Vector3d(0.0, 0.0, self.getInputPlane())
예제 #21
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()
예제 #22
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
예제 #23
0
파일: psf.py 프로젝트: will-hossack/Poptics
 def __str__(self):
     """
     Implement str
     """
     return " {0:s} i: {1:7.4f} major: {2:7.4f} minor: {3:7.4f} alpha: {4:7.4f}".\
         format(Vector3d.__str__(self),self.intensity,self.major,self.minor,self.alpha)