def trace_rays(): ln = pyz.createLink() filename = os.path.join(ln.zGetPath()[1], 'Sequential', 'Objectives', 'Cooke 40 degree field.zmx') ln.zLoadFile(filename) print("Loaded zemax file:", ln.zGetFile()) ln.zGetUpdate() # In general this should be done ... if not ln.zPushLensPermission(): print("\nERROR: Extensions not allowed to push lenses. Please enable in Zemax.") ln.close() sys.exit(0) ln.zPushLens(1) # FOR SOME REASON, THE ARRAY RAY TRACING SEEMS TO # BE WORKING ON THE LENS THAT IS IN THE MAIN ZEMAX APPLICATION WINDOW!!!! ln.zNewLens() # THIS IS JUST TO PROVE THE ABOVE POINT!!! RAY TRACING STILL ON THE LENS # IN THE MAIN ZEMAX APPLICATION, EVENTHOUGH THE LENS IN THE DDE SERVER IS A "NEW LENS" numRays = 101**2 # 10201 rd = at.getRayDataArray(numRays, tType=0, mode=0, endSurf=-1) radius = int(sqrt(numRays)/2) # Fill the rest of the ray data array k = 0 for i in xrange(-radius, radius + 1, 1): for j in xrange(-radius, radius + 1, 1): k += 1 rd[k].z = i/(2*radius) # px rd[k].l = j/(2*radius) # py rd[k].intensity = 1.0 rd[k].wave = 1 # Trace the rays ret = at.zArrayTrace(rd, timeout=5000) # Dump the ray trace data into a file outputfile = os.path.join(cd, "arrayTraceOutput.txt") if ret==0: k = 0 with open(outputfile, 'w') as f: f.write("Listing of Array trace data\n") f.write(" px py error xout yout" " l m n opd Exr Exi" " Eyr Eyi Ezr Ezi trans\n") for i in xrange(-radius, radius + 1, 1): for j in xrange(-radius, radius + 1, 1): k += 1 line = ("{:7.3f} {:7.3f} {:5d} {:15.6E} {:15.6E} {:9.5f} " "{:9.5f} {:9.5f} {:7.3f} {:7.3f} {:7.3f} {:7.3f} " "{:7.3f} {:7.3f} {:7.3f} {:7.4f}\n" .format(i/(2*radius), j/(2*radius), rd[k].error, rd[k].x, rd[k].y, rd[k].l, rd[k].m, rd[k].n, rd[k].opd, rd[k].Exr, rd[k].Exi, rd[k].Eyr, rd[k].Eyi, rd[k].Ezr, rd[k].Ezi, rd[k].intensity)) f.write(line) print("Success") print("Ray trace data outputted to the file {}".format(outputfile)) else: print("There was some problem in ray tracing") ln.zNewLens() ln.zPushLens() ln.close()
def get_time_zArrayTrace(numRays, retRd=False): """return the time taken to perform ray tracing for the given number of rays using zArrayTrace() function. """ radius = int(sqrt(numRays) / 2) startTime = time.clock() rd = at.getRayDataArray(numRays, tType=0, mode=0) # Fill the rest of the ray data array, # hx, hy are zeros; mode = 0 (real), surf = img surf, waveNum = 1 k = 0 for i in xrange(-radius, radius + 1, 1): for j in xrange(-radius, radius + 1, 1): k += 1 rd[k].z = i / (2 * radius) # px rd[k].l = j / (2 * radius) # py rd[k].intensity = 1.0 rd[k].wave = 1 # Trace the rays ret = at.zArrayTrace(rd, timeout=5000) endTime = time.clock() if ret == 0 and no_error_in_ray_trace(rd, numRays): if retRd: return (endTime - startTime) * 10e3, rd else: return (endTime - startTime) * 10e3 # time in milliseconds
def trace_rays(): ln = pyz.createLink() filename = os.path.join(ln.zGetPath()[1], 'Sequential', 'Objectives', 'Cooke 40 degree field.zmx') ln.zLoadFile(filename) print("Loaded zemax file:", ln.zGetFile()) ln.zGetUpdate() # In general this should be done ... if not ln.zPushLensPermission(): print("\nERROR: Extensions not allowed to push lenses. Please enable in Zemax.") ln.close() sys.exit(0) ln.zPushLens(1) # FOR SOME REASON, THE ARRAY RAY TRACING SEEMS TO # BE WORKING ON THE LENS THAT IS IN THE MAIN ZEMAX APPLICATION WINDOW!!!! ln.zNewLens() # THIS IS JUST TO PROVE THE ABOVE POINT!!! RAY TRACING STILL ON THE LENS # IN THE MAIN ZEMAX APPLICATION, EVENTHOUGH THE LENS IN THE DDE SERVER IS A "NEW LENS" numRays = 101**2 # 10201 rd = at.getRayDataArray(numRays, tType=0, mode=0, endSurf=-1) radius = int(sqrt(numRays)/2) # Fill the rest of the ray data array k = 0 for i in range(-radius, radius + 1, 1): for j in range(-radius, radius + 1, 1): k += 1 rd[k].z = i/(2*radius) # px rd[k].l = j/(2*radius) # py rd[k].intensity = 1.0 rd[k].wave = 1 # Trace the rays ret = at.zArrayTrace(rd, timeout=5000) # Dump the ray trace data into a file outputfile = os.path.join(cd, "arrayTraceOutput.txt") if ret==0: k = 0 with open(outputfile, 'w') as f: f.write("Listing of Array trace data\n") f.write(" px py error xout yout" " l m n opd Exr Exi" " Eyr Eyi Ezr Ezi trans\n") for i in range(-radius, radius + 1, 1): for j in range(-radius, radius + 1, 1): k += 1 line = ("{:7.3f} {:7.3f} {:5d} {:15.6E} {:15.6E} {:9.5f} " "{:9.5f} {:9.5f} {:7.3f} {:7.3f} {:7.3f} {:7.3f} " "{:7.3f} {:7.3f} {:7.3f} {:7.4f}\n" .format(i/(2*radius), j/(2*radius), rd[k].error, rd[k].x, rd[k].y, rd[k].l, rd[k].m, rd[k].n, rd[k].opd, rd[k].Exr, rd[k].Exi, rd[k].Eyr, rd[k].Eyi, rd[k].Ezr, rd[k].Ezi, rd[k].intensity)) f.write(line) print("Success") print("Ray trace data outputted to the file {}".format(outputfile)) else: print("There was some problem in ray tracing") ln.zNewLens() ln.zPushLens() ln.close()
def get_time_zArrayTrace(numRays, retRd=False): """return the time taken to perform ray tracing for the given number of rays using zArrayTrace() function. """ radius = int(sqrt(numRays)/2) startTime = time.clock() rd = at.getRayDataArray(numRays, tType=0, mode=0) # Fill the rest of the ray data array, # hx, hy are zeros; mode = 0 (real), surf = img surf, waveNum = 1 k = 0 for i in xrange(-radius, radius + 1, 1): for j in xrange(-radius, radius + 1, 1): k += 1 rd[k].z = i/(2*radius) # px rd[k].l = j/(2*radius) # py rd[k].intensity = 1.0 rd[k].wave = 1 # Trace the rays ret = at.zArrayTrace(rd, timeout=5000) endTime = time.clock() if ret == 0 and no_error_in_ray_trace(rd, numRays): if retRd: return (endTime - startTime)*10e3, rd else: return (endTime - startTime)*10e3 # time in milliseconds
def spiralSpot_using_zArrayTrace(hx=0.0, hy=0.4, waveNum=1, spirals=10, numRays=600): """function replicates ``zSpiralSpot()`` using the ``pyzdde.arraytrace`` module functions ``getRayDataArray()`` and ``zArrayTrace()`` """ startTime = time.clock() deltaTheta = (spirals*2.0*pi)/(numRays-1) # construct the ray data structure rd = at.getRayDataArray(numRays, tType=0, mode=0, endSurf=-1) for i in range(0, numRays): theta = i*deltaTheta r = i/(numRays-1) px, py = r*cos(theta), r*sin(theta) rd[i+1].x = hx rd[i+1].y = hy rd[i+1].z = px rd[i+1].l = py rd[i+1].wave = waveNum # send ray data structure to Zemax for performing array tracing ret = at.zArrayTrace(rd) # retrieve the traced data from the ray data structure x, y = [0.0]*numRays, [0.0]*numRays if ret==0: for i in range(1, numRays+1): x[i-1] = rd[i].x y[i-1] = rd[i].y endTime = time.clock() print("Execution time = {:4.2f}".format((endTime - startTime)*10e3), "ms") plotTracedData(x, y) else: print("Error in tracing rays")
def test_cross_check_zArrayTrace_vs_zGetTraceNumpy_OLD(self): print("\nTEST: comparison of zArrayTrace and zGetTraceNumpy OLD") # Load a lens file into the LDE filename = get_test_file() self.ln.zLoadFile(filename) self.ln.zPushLens(1); # set-up field and pupil sampling nr = 22; rd = at.getRayDataArray(nr) hx,hy,px,py = 2*np.random.rand(4,nr)-1; for k in range(nr): rd[k+1].x = hx[k]; rd[k+1].y = hy[k]; rd[k+1].z = px[k]; rd[k+1].l = py[k]; rd[k+1].intensity = 1.0; rd[k+1].wave = 1; rd[k+1].want_opd = 0; # results of zArrayTrace ret = at.zArrayTrace(rd); self.assertEqual(ret,0); results = np.asarray( [[r.error,r.vigcode,r.x,r.y,r.z,r.l,r.m,r.n,\ r.Exr,r.Eyr,r.Ezr,r.opd,r.intensity] for r in rd[1:]] ); # results of GetTraceArray (error,vigcode,pos,dir,normal,intensity) = \ nt.zGetTraceArray(hx,hy,px,py,bParaxial=0); # compare self.assertTrue(np.array_equal(error,results[:,0]),msg="error differs"); self.assertTrue(np.array_equal(vigcode,results[:,1]),msg="vigcode differs"); self.assertTrue(np.array_equal(pos,results[:,2:5]),msg="pos differs"); self.assertTrue(np.array_equal(dir,results[:,5:8]),msg="dir differs"); self.assertTrue(np.array_equal(normal,results[:,8:11]),msg="normal differs"); self.assertTrue(np.array_equal(intensity,results[:,12]),msg="intensity differs");
def spiralSpot_using_zArrayTrace(hx=0.0, hy=0.4, waveNum=1, spirals=10, numRays=600): """function replicates ``zSpiralSpot()`` using the ``pyzdde.arraytrace`` module functions ``getRayDataArray()`` and ``zArrayTrace()`` """ startTime = time.clock() deltaTheta = (spirals * 2.0 * pi) / (numRays - 1) # construct the ray data structure rd = at.getRayDataArray(numRays, tType=0, mode=0, endSurf=-1) for i in range(0, numRays): theta = i * deltaTheta r = i / (numRays - 1) px, py = r * cos(theta), r * sin(theta) rd[i + 1].x = hx rd[i + 1].y = hy rd[i + 1].z = px rd[i + 1].l = py rd[i + 1].wave = waveNum # send ray data structure to Zemax for performing array tracing ret = at.zArrayTrace(rd) # retrieve the traced data from the ray data structure x, y = [0.0] * numRays, [0.0] * numRays if ret == 0: for i in range(1, numRays + 1): x[i - 1] = rd[i].x y[i - 1] = rd[i].y endTime = time.clock() print( "Execution time (zArrayTrace) = {:4.2f}".format( (endTime - startTime) * 10e3), "ms") plotTracedData(x, y) else: print("Error in tracing rays")
def trace_rays(self, x, y, px, py, waveNum, mode=0, surf=-1): """ array trace of rays Parameters ---------- x,y : vectors of length nRays reduced field coordinates for each ray (normalized between -1 and 1) px,py : vectors of length nRays reduced pupil coordinates for each ray (normalized between -1 and 1) waveNum : integer wavelength number mode : integer, optional 0= real (default), 1 = paraxial surf : integer, optional surface to trace the ray to. Usually, the ray data is only needed at the image surface (``surf = -1``, default) Returns -------- numpy array of shape (nRays,8) containing following parameters for each ray err : error flag * 0 = ray traced successfully; * +ve number = the ray missed the surface; * -ve number = the ray total internal reflected (TIR) at surface given by the absolute value of the ``error`` vigcode : integer The first surface where the ray was vignetted. Raytrace is continued. x,y,z : float cartesian coordinates of ray on requested surface (local coordinates) l,m,n : float direction cosines after requested surface (local coordinates) l2,m2,n2 : float direction cosines of surface normal at point of incidence (local coordinates) """ # enlarge all vector arguments to same size nRays = max(map(np.size, (x, y, px, py, waveNum))) if np.isscalar(x): x = np.zeros(nRays) + x if np.isscalar(y): y = np.zeros(nRays) + y if np.isscalar(px): px = np.zeros(nRays) + px if np.isscalar(py): py = np.zeros(nRays) + py if np.isscalar(waveNum): waveNum = np.zeros(nRays, np.int) + waveNum assert (all(args.size == nRays for args in [x, y, px, py, waveNum])) print("number of rays: %d" % nRays) import time t = time.time() # fill in ray data array (following Zemax notation!) rays = at.getRayDataArray(nRays, tType=0, mode=mode, endSurf=surf) for k in range(nRays): rays[k + 1].x = x[k] rays[k + 1].y = y[k] rays[k + 1].z = px[k] rays[k + 1].l = py[k] rays[k + 1].wave = waveNum[k] print("set pupil values: %ds" % (time.time() - t)) # Trace the rays ret = at.zArrayTrace(rays, timeout=100000) print(("zArrayTrace: %ds" % (time.time() - t))) # collect results results = np.asarray([(r.error, r.vigcode, r.x, r.y, r.z, r.l, r.m, r.n, r.Exr, r.Eyr, r.Ezr) for r in rays[1:]]) print(("retrive data: %ds" % (time.time() - t))) return results
def trace_rays(self,x,y, px,py, waveNum, mode=0, surf=-1): """ array trace of rays Parameters ---------- x,y : vectors of length nRays reduced field coordinates for each ray (normalized between -1 and 1) px,py : vectors of length nRays reduced pupil coordinates for each ray (normalized between -1 and 1) waveNum : integer wavelength number mode : integer, optional 0= real (default), 1 = paraxial surf : integer, optional surface to trace the ray to. Usually, the ray data is only needed at the image surface (``surf = -1``, default) Returns -------- numpy array of shape (nRays,8) containing following parameters for each ray err : error flag * 0 = ray traced successfully; * +ve number = the ray missed the surface; * -ve number = the ray total internal reflected (TIR) at surface given by the absolute value of the ``error`` vigcode : integer The first surface where the ray was vignetted. Raytrace is continued. x,y,z : float cartesian coordinates of ray on requested surface (local coordinates) l,m,n : float direction cosines after requested surface (local coordinates) l2,m2,n2 : float direction cosines of surface normal at point of incidence (local coordinates) """ # enlarge all vector arguments to same size nRays = max(map(np.size,(x,y,px,py,waveNum))); if np.isscalar(x): x = np.zeros(nRays)+x; if np.isscalar(y): y = np.zeros(nRays)+y; if np.isscalar(px): px = np.zeros(nRays)+px; if np.isscalar(py): py = np.zeros(nRays)+py; if np.isscalar(waveNum): waveNum=np.zeros(nRays,np.int)+waveNum; assert(all(args.size == nRays for args in [x,y,px,py,waveNum])) print("number of rays: %d"%nRays); import time; t = time.time(); # fill in ray data array (following Zemax notation!) rays = at.getRayDataArray(nRays, tType=0, mode=mode, endSurf=surf) for k in range(nRays): rays[k+1].x = x[k] rays[k+1].y = y[k] rays[k+1].z = px[k] rays[k+1].l = py[k] rays[k+1].wave = waveNum[k]; print("set pupil values: %ds"%(time.time()-t)) # Trace the rays ret = at.zArrayTrace(rays, timeout=100000); print(("zArrayTrace: %ds"%(time.time()-t))) # collect results results = np.asarray( [(r.error,r.vigcode,r.x,r.y,r.z,r.l,r.m,r.n,r.Exr,r.Eyr,r.Ezr) for r in rays[1:]] ); print(("retrive data: %ds"%(time.time()-t))) return results;