def planoConvex(self, lens1, lens2, diameters): """A function which calculates and plots the RMS spot radius for the range of diameters input""" lenses = [lens1, lens2] testRay = rt.Ray([0.1, 0, 0], [0, 0, 1]) for lens in lenses: lens.propagateRay(testRay) output = lenses[-1].paraxial( testRay ) #Setting the output plane at the paraxial focus of the setup lenses.append(output) focalLength = output.getz() - ( (lens1.getz0() + lens2.getz0()) / 2 ) #Calculating the focal length of the lens wavelength = 588e-6 #The wavelength of the light is 588nm (The units used in the simulation are mm) ray = rt.Ray([0, 0, 0], [0, 0, 1]) diameterList = [] RMSList = [] diffractionList = [] for i in diameters: diameterList.append(i) rays = rt.Bundle(10, i / 2, 10).getBundle( ray) #Creating a bundle of rays for each diameter for lens in lenses: lens.propagateBundle( rays) #Propagating the rays through the lenses plot = pt.Plot(rays) RMS = plot.rms( ) #Calculating the RMS spot radius of the rays at the output for each diameter RMSList.append(RMS) diffractionLimit = ( focalLength * wavelength ) / i #Also calculating the diffraction scale for each diameter diffractionList.append(diffractionLimit) fig = plt.figure() ax = fig.add_subplot(111) ax.set_xlabel('Diameter (mm)') ax.set_ylabel('RMS (mm)') ax.set_title('Diffaction Limit') plt.grid(True) ax.plot(diameterList, RMSList, 'green') #Plotting the RMS spot radius against diameter ax.plot(diameterList, diffractionList, 'red') #Plotting the diffraction scale against diameter RMSValues = np.array(RMSList, dtype='float') diffractionValues = np.array(diffractionList, dtype='float') difference = (diffractionValues - RMSValues).tolist() difference = [ abs(i) for i in difference ] #Calculating the differences between the RMS spot radius and the diffraction scale at each diameter index = difference.index(min(difference)) intersection = diameterList[ index] #Finding the point on the graph where the difference between the two functions is a minimum, and taking this to be the intersection point of the two plots. print 'Intersection is: ', intersection
def bundlerays(n, rmax, m): bund = [] R=numpy.arange(0,rmax,rmax/n) N=numpy.arange(1, n*m, m) for r,t in rtpairs(R, N): myRay = raytracer.Ray(r * numpy.cos(t), r * numpy.sin(t),-200.,0,0,1.) bund.append(myRay) return bund
def findzintercept(lens1,lens2): """Finds intersection point of ray with z-axis""" TR = rt.Ray([0.1,0.1,80],[0.0,0.0,1.0]) #test ray close to z-axis lens1.propagate_ray(TR) lens2.propagate_ray(TR) ratio = -(TR._p[0])/(TR._k[0]) intercept = TR._p + (ratio*TR._k) return intercept
def paraxial_focus(self): """ The paraxial_focus method calculates where the paraxial focus of a surface element is.It then returns a z0 value at which the output plane can be positioned. The exceptions prevent the use of the paraxial focus when the system is not converging """ elements = self.__list_of_elements test_ray = rt.Ray([0.1,0,0],[0,0,1]) for i in elements: i.propagate_ray(test_ray) if self.__use == 'yes' and len(elements) == 1: last = elements[-1] last_n1 = last._SphericalRefraction__n1 last_n2 = last._SphericalRefraction__n2 last_curvature = last._SphericalRefraction__curvature #print last_n1,last_n2,last_curvature if last_curvature > 0 and last_n1 > last_n2: raise Exception("cannot calculate paraxial focus for divering lens, set, use='no' ") else: if last_curvature < 0 and last_n2 > last_n1: raise Exception("cannot calculate paraxial focus for divering lens, set, use='no' ") else: if last_curvature != 0: direction = test_ray.k() position = test_ray.p() L = -position[0]/direction[0] if L > 0: paraxial_position = position[2] + L * direction[2] return paraxial_position else: raise Exception("cannot calculate paraxial focus for plane refractive surface ,set, use='no' ") elif self.__use == 'yes' and len(elements) > 1: direction = test_ray.k() position = test_ray.p() L = -position[0]/direction[0] if L > 0: paraxial_position = position[2] + L * direction[2] return paraxial_position elif self.__use == 'no': return self.__z_choice
def optimalRMS(self, curvatures): """A function which calculates and returns the log of the RMS spot radius for two given curvatures of a biconvex lens""" lens1 = op.SphericalRefraction(100, 20, curvatures[0], 1, 1.5168) lens2 = op.SphericalRefraction(105, 20, curvatures[1], 1.5168, 1) output = op.OutputPlane(200) #The output plane is set at z=200mm lenses = [lens1, lens2, output] ray = rt.Ray([0, 0, 0], [0, 0, 1]) rays = rt.Bundle(10, 5, 10).getBundle(ray) #A bundle of rays is created for lens in lenses: lens.propagateBundle( rays) #The rays are propagated through the biconvex lens plot = pt.Plot(rays) RMS = plot.rms( ) #Calculating the RMS spot radius of the rays at the output for the given curvatures log = np.log(RMS) return log
def bundle(n=5, rmax=5, m=4, initial_z=0, direction=[0, 0, 1], x1=0, y1=0): """ The bundle function takes 5 parameters. The parameters n ,rmax and m are used when calling rtuniform. (see it's docstring for further information) The intial_z parmeter determines where the bundle of rays starts at on the z axis. The initial direction parameter determines the initial direction of the bundle of rays. The parameters x1,y1 allow the x and y coordinates to be offset. Note bundle of rays is returned as list_of_rays. """ list_of_rays = [] for r, t in gen.rtuniform(n, rmax, m): ith_ray = rt.Ray([(r * np.cos(t) + x1), (r * np.sin(t) + y1), initial_z], direction) # Creates a ray instance for each pair of r, theta coordinates. # The rays are then appended to a list. list_of_rays.append(ith_ray) return list_of_rays
print "lens 1 curvature = %s, lens 2 curvature = %s, rms = %s" % ( m[0], m[1], m[1]) def MinList(ls, m): """Finding the lowest rms values, returned with the two corresponding curvatures In a list of lists, return the list with the smallest index 2 element""" if ls == []: return m if ls[0][2] < m[2]: return MinList(ls[1:], ls[0]) else: return MinList(ls[1:], m) r = rt.Ray([0.0, 0.0, 0.0], [0.0, 0.0, 1.0]) b = rt.CollimatedBeam(r, 5, 50) optimiselens(b, 10) """Rainbow Test Suite r = rt.Ray([5,5,0.0],[0.0,0.0,1.0], 580*10**(-9)) t = rt.Ray([0,-1,0.0],[0.2,0.1,2.0]) b = rt.CollimatedBeam(r, 1, 50) outputplane = rt.OutputPlane(0) semi1 = rt.DispersiveRefraction('water', 50, 0.05, 20, 1.0) semi2 = rt.SphericalReflection(90, -0.05, 20) #b.trace2dispersed(semi1, semi2, outputplane) Beams = [] for t in np.linspace(0.1,5.0,10):
def plotspots(a=1): """Produces three plots: 1) Spot diagram of initial bundle of rays in x-y plane. 2) Ray diagram in x-z plane showing rays passing through the lens. 3) Spot diagram of ray bundle at the output plane i.e. the detector. Produces plots for either orientation of the lens depending on a.""" if a == 1: lens1 = SR1 lens2 = SR2 else: lens1 = SR3 lens2 = SR4 x = findzintercept(lens1,lens2) focal = x[2] output = rt.OutputPlane(focal) print "Focal length for orientation %g is %g mm." % (a, focal) bundle = [] for r,t in gp.rtuniform(7, 5.0, 6): #rmax (5.0) must be a float xcoord = r*np.cos(t) ycoord = r*np.sin(t) ray = rt.Ray([xcoord,ycoord,0.0],[0.0,0.0,0.1]) lens1.propagate_ray(ray) lens2.propagate_ray(ray) output.propagate_ray(ray) bundle.append(ray) plt.figure(a) if a == 1: plt.suptitle('Planoconvex Lens Orientation 1', size=16) else: plt.suptitle('Planoconvex Lens Orientation 2', size=16) ax1 = plt.subplot(2,2,1) ax1.plot(xcoord, ycoord, 'bo') ax1.set_title('Bundle of Rays at Source, z=0', size=12) ax1.axis('equal') ax2 = plt.subplot(2,2,2) x2 = [j[2] for j in ray.vertices()] y2 = [j[0] for j in ray.vertices()] ax2.plot(x2,y2,'r-') ax2.set_title('Propagation of Rays in xz Plane', size=12) x3 = [j._p[0] for j in bundle] y3 = [j._p[1] for j in bundle] ax3 = plt.subplot(2,2,3) ax3.plot(x3,y3,'bo') ax3.set_title('Bundle of Rays at Focus', size=12) ax3.locator_params(nbins=5) ax3.axis('equal') findrms(bundle) difflim = ((588*10**(-9))*focal)/10.0 print "The diffraction limit is %g m." % difflim
ax2 = plt.axes() ax2.set_title('paraxial focus') fig3 = plt.figure() ax3 = plt.axes(projection='3d') ax3.set_title('beam path') # empty lists for calculating rms deviation later foc_x = [] foc_y = [] # create each ray and propagate through lens, plotting at origin, at paraxial focus and the path for o in origins: x1 = [] y1 = [] r = rt.Ray(pos=[o[0], o[1], 0.], direc=[0., 0., 1.]) lens.propagate_ray(r) output.propagate_ray(r) points = r.vertices() x1.append(points[0][0]) y1.append(points[0][1]) ax1.plot(x1, y1, 'r.') x2 = [] y2 = [] x2.append(points[-1][0]) y2.append(points[-1][1]) foc_x.append(x2) foc_y.append(y2)
# get points of rays into individual arrays and plot them for o in origins: x = [] y = [] z = [] r = rt.Ray(pos = [o[0], o[1], 0.], direc=[0., 0., 1.]) surface.propagate_ray(r) output.propagate_ray(r) points = r.vertices() for point in points: x.append(point[0]) y.append(point[1]) z.append(point[2]) ax.plot3D(z, x, y, 'r-') """ for i in range(-10, 10): y = [] z = [] r = rt.Ray(pos=[0., i, 0.], direc=[0., 0., 1.]) surface.propagate_ray(r) output.propagate_ray(r) points = r.vertices() for point in points: y.append(point[1]) z.append(point[2]) plt.plot(z, y, 'r-') plt.show()
import raytracer s = raytracer.SphericalRefraction(z_0=1, curve=0.25, n1=1, n2=0.8, aperture=3) r = raytracer.Ray(pos=[1., 2., 3.], direc=[1., 2., 3.]) print(s.intercept(r)) s2 = raytracer.SphericalRefraction(z_0=0, curve=0.8, n1=1, n2=0.8, aperture=10) r2 = raytracer.Ray(pos=[4., 5., 6.], direc=[1., 2., 3.]) print(s2.intercept(r2)) # imag result, filtered as expected s3 = raytracer.SphericalRefraction(z_0=1, curve=0.4, n1=1, n2=0.8, aperture=5) r3 = raytracer.Ray(pos=[7., 8., 9.], direc=[4., 0., 1.]) print(s3.intercept(r3)) # imag result, filtered as expected # Would be much easier to see these intercepts are in the right place once plotting multiple rays
def run(self): """This function provides an input interface for the user when the module is imported into the terminal""" terminate = False #Asking the user if they want to investigate the performance of a planoconvex lens planoConvexInput = raw_input( "Do you want to investigate the imaging performance of a planoconvex lens? (Yes or No).\n" ) planoConvexInput = planoConvexInput.lower() if 'y' in planoConvexInput: #If yes, the user is asked to input the parameters for the two sides of their planoconvex lens, along with the range of diameters to investigate terminate = True #The interface will be terminated after the user has input all the parameters for the planoconvex investigation lens1Input = raw_input( "Enter z0, aperture, curvature, n1 and n2 values for your first lens, separated by commas.\n" ) lens1Input = lens1Input.split(",") lens1Input = [float(coordinate) for coordinate in lens1Input] lens1 = op.SphericalRefraction(lens1Input[0], lens1Input[1], lens1Input[2], lens1Input[3], lens1Input[4]) lens2Input = raw_input( "Enter z0, aperture, curvature, n1 and n2 values for your second lens, separated by commas.\n" ) lens2Input = lens2Input.split(",") lens2Input = [float(coordinate) for coordinate in lens2Input] lens2 = op.SphericalRefraction(lens2Input[0], lens2Input[1], lens2Input[2], lens2Input[3], lens2Input[4]) rangeInput = raw_input( "Enter the lower limit and upper limit for the range of diameters you want to investigate, followed by the incremental variation.\n" ) rangeInput = rangeInput.split(",") rangeInput = [float(coordinate) for coordinate in rangeInput] self.planoConvex( lens1, lens2, np.arange(rangeInput[0], rangeInput[1] + rangeInput[2], rangeInput[2])) plt.show() if terminate == False: #Asking the user if they want to find the optimal biconvex lens biConvexInput = raw_input( "Do you want to find the optimal biconvex lens? (Yes or No).\n" ) biConvexInput = biConvexInput.lower() if 'y' in biConvexInput: #If yes, the user is asked to input the parameters required for the scipy optimiser function terminate = True bounds1Input = raw_input( "Enter the lower and upper bounds for the first side of your lens, separated by commas.\n" ) bounds1Input = bounds1Input.split(",") bounds1Input = [ float(coordinate) for coordinate in bounds1Input ] bounds2Input = raw_input( "Enter the lower and upper bounds for the second side of your lens, separated by commas.\n" ) bounds2Input = bounds2Input.split(",") bounds2Input = [ float(coordinate) for coordinate in bounds2Input ] b = [(bounds1Input[0], bounds1Input[1]), (bounds2Input[0], bounds2Input[1])] curvaturesInput = raw_input( "Enter the initial curvatures of the two sides of your lens.\n" ) curvaturesInput = curvaturesInput.split(",") curvaturesInput = [ float(coordinate) for coordinate in curvaturesInput ] x0 = np.array([curvaturesInput[0], curvaturesInput[1]]) result = so.fmin_tnc(self.optimalRMS, x0, bounds=b, approx_grad=True) print result if terminate == False: allRays = [] #A list of all the rays created by the user moreRays = True while moreRays: #Asking the user to input the position and direction coordinates of their ray rayPositionInput = raw_input( "Enter 3 values for ray position, separated with commas.\n" ) rayPositionInput = rayPositionInput.split(",") rayPositionInput = [ float(coordinate) for coordinate in rayPositionInput ] rayDirectionInput = raw_input( "Enter 3 values for ray direction, separated by commas.\n") rayDirectionInput = rayDirectionInput.split(",") rayDirectionInput = [ float(coordinate) for coordinate in rayDirectionInput ] ray = rt.Ray(rayPositionInput, rayDirectionInput) allRays.append(ray) #Asking if the ray is to be collimated into a bundle of rays beamRequiredInput = raw_input( "Do you want to collimate the ray into a beam of finite thickness? (Yes or No).\n" ) beamRequiredInput = beamRequiredInput.lower() if 'y' in beamRequiredInput: #The paramters for the beam of rays are input beamParametersInput = raw_input( "Enter the number of circles, maximum diameter and multiplier in that order (separate them with commas).\n" ) beamParametersInput = beamParametersInput.split(",") beamParametersInput = [ float(parameter) for parameter in beamParametersInput ] beam = rt.Bundle( int(beamParametersInput[0]), 0.5 * beamParametersInput[1], int(beamParametersInput[2])).getBundle(ray) for i in range(1, len(beam)): allRays.append( beam[i] ) #The new rays formed are appended to the list of rays moreRaysInput = raw_input( "Do you want to add another ray/beam? (Yes or No)\n" ) #If the user says yes, the options are repeated so that more rays can be created moreRaysInput = moreRaysInput.lower() if 'n' in moreRaysInput: moreRays = False addLens = True lenses = [] #A list of all the lenses created by the user while addLens: #Asking the user to input the parameters for their lens lensInput = raw_input( "Enter z0, aperture, curvature, n1 and n2 values for your lens.\n" ) lensInput = lensInput.split(",") lensInput = [float(coordinate) for coordinate in lensInput] lens = op.SphericalRefraction(lensInput[0], lensInput[1], lensInput[2], lensInput[3], lensInput[4]) lenses.append(lens) #Asking the user if they want to create more lenses for the simulation addLensInput = raw_input( "Do you want to add another lens to the system? (Yes or No).\n" ) addLensInput = addLensInput.lower() if 'n' in addLensInput: addLens = False for lens in lenses: lens.propagateBundle(allRays) testRay = rt.Ray([0.1, 0, 0], [0, 0, 1]) for lens in lenses: lens.propagateRay(testRay) output = lenses[-1].paraxial( testRay) #The output plane is set at the paraxial focus if output is None: #If the rays do not converge, there is no paraxial focus, so the user is asked to input the position of the output plane outputInput = raw_input( "Your system does not have a paraxial focus. Enter the z coordinate for your Output plane.\n" ) outputInput = outputInput.split() outputInput = [float(coordinate) for coordinate in outputInput] output = op.OutputPlane(outputInput[0]) else: #The user is asked if they want to keep the output at the paraxial focus paraxialInput = raw_input( "Do you want to set your Output Plane as the paraxial focus? (Yes or No).\n" ) paraxialInput = paraxialInput.lower() if 'n' in paraxialInput: #If no, the user is asked to input the position of the output plane outputInput = raw_input( "Enter the z coordinate for your Output plane.\n") outputInput = outputInput.split() outputInput = [ float(coordinate) for coordinate in outputInput ] output = op.OutputPlane(outputInput[0]) output.propagateBundle( allRays ) #All the rays created by the user are propagated to the output plane self.plotRays( allRays) #All the plots of the simulation are shown at the end