def spiralSpot_using_zGetTraceArray(hx=0.0, hy=0.4, waveNum=1, spirals=10, numRays=600): """function replicates ``zSpiralSpot()`` using the ``pyzdde.arraytrace`` module helper function ``zGetTraceArray()`` """ startTime = time.clock() # create the hx, hy, px, py grid r = np.linspace(0, 1, numRays) theta = np.linspace(0, spirals * 2.0 * pi, numRays) px = (r * np.cos(theta)).tolist() py = (r * np.sin(theta)).tolist() # trace the rays tData = at.zGetTraceArray(numRays, [hx] * numRays, [hy] * numRays, px, py, waveNum=waveNum) # parse traced data and plot err, _, x, y, _, _, _, _, _, _, _, _, _ = tData endTime = time.clock() print( "Execution time (zGetTraceArray) = {:4.2f}".format( (endTime - startTime) * 10e3), "ms") if sum(err) == 0: plotTracedData(x, y) else: print("Error in tracing rays")
def parity_zGetTraceDirect_zGetTraceDirectArray(ln, numRays): """function to check the parity between the ray traced data returned by zGetTraceDirect() and zGetTraceDirectArray() """ # use zGetTraceArray to surface # 2 to get ray coordinates and direction # cosines at surface 2 radius = int(sqrt(numRays)/2) flatGrid = [(x/(2*radius),y/(2*radius)) for x in xrange(-radius, radius + 1, 1) for y in xrange(-radius, radius + 1, 1)] px = [e[0] for e in flatGrid] py = [e[1] for e in flatGrid] tData0 = at.zGetTraceArray(numRays=numRays, px=px, py=py, waveNum=1, surf=2) assert sum(tData0[0]) == 0 # use zGetTraceDirectArray to trace rays to the image surface using the # the ray coordinates and direction cosines at surface 2 tData1 = at.zGetTraceDirectArray(numRays=numRays, x=tData0[2], y=tData0[3], z=tData0[4], l=tData0[5], m=tData0[6], n=tData0[7], waveNum=1, mode=0, startSurf=2, lastSurf=-1) assert sum(tData1[0]) == 0 tol = 1e-10 # use zGetTraceDirect to trace single rays per dde call for i in range(numRays): tData2 = ln.zGetTraceDirect(waveNum=1, mode=0, startSurf=2, stopSurf=-1, x=tData0[2][i], y=tData0[3][i], z=tData0[4][i], l=tData0[5][i], m=tData0[6][i], n=tData0[7][i]) assert tData2[0] == 0 for k in [2, 3, 4, 5, 6, 7]: assert abs(tData2[k] - tData1[k][i]) < tol, \ ("tData2[{}] = {}, tData1[{}][{}] = {}" .format(k, tData2[k], k, i, tData1[k][i])) print("Parity test bw zGetTraceDirect() & zGetTraceDirectArray() successful")
def test_zGetTraceArrayOLd(self): print("\nTEST: arraytrace.zGetTraceArray()") # 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 with random values nr = 22; np.random.seed(0); hx,hy,px,py = 2*np.random.rand(4,nr)-1; w = 1; # wavenum # run array trace (C-extension), returns (error,vig,x,y,z,l,m,n,l2,m2,n2,opd,intensity) mode_descr = ("real","paraxial") for mode in (0,1): print(" compare with GetTrace for %s raytrace"% mode_descr[mode]); ret = at.zGetTraceArray(nr,list(hx),list(hy),list(px),list(py), intensity=1,waveNum=w,mode=mode,surf=-1,want_opd=0) mask = np.ones(13,dtype=np.bool); mask[-2]=False; # mask array for removing opd from ret ret = np.asarray(ret)[mask]; # compare with results from GetTrace, returns (error,vig,x,y,z,l,m,n,l2,m2,n2,intensity) ret_descr = ('error','vigcode','x','y','z','l','m','n','Exr','Eyr','Ezr','intensity') for i in range(nr): reference = self.ln.zGetTrace(w,mode,-1,hx[i],hy[i],px[i],py[i]); is_close = np.isclose(ret[:,i], np.asarray(reference)); msg = 'zGetTraceArray differs from GetTrace for %s ray #%d:\n' % (mode_descr[mode],i); msg+= ' field: (%f,%f), pupil: (%f,%f) \n' % (hx[i],hy[i],px[i],py[i]); msg+= ' parameter zGetTraceArray zGetTrace \n'; for j in np.arange(12)[~is_close]: msg+= '%10s %12g %12g \n'%(ret_descr[j],ret[j,i],reference[j]); self.assertTrue(np.all(is_close), msg=msg);
def spot_radius_map(nFields= 15, N=51, EE=80, zoom=10, bsavefig=False): ''' create spot diagrams for nFields x nFields calculate spot radii and generate density map ''' print('Computing Spot Radius Map') # Define rays nx = ny = N # number of rays in x- and y-direction px = np.repeat(np.linspace(-1, 1, nx), nx) py = np.tile(np.linspace(-1, 1, ny), ny) r = np.sqrt(px**2 + py**2) numRays = nx*ny fields = [(x,y) for y in np.linspace(1, -1, nFields) for x in np.linspace(-1, 1, nFields)] fig, ax = plt.subplots(figsize=(10, 10)) X, Y, X_MEAN, Y_MEAN, R = [], [], [], [], [] for i, field in enumerate(fields): hx = np.repeat(field[0], numRays) hy = np.repeat(field[1], numRays) rd = at.zGetTraceArray(numRays, px=px.tolist(), py=py.tolist(), hx=hx.tolist(), hy=hy.tolist(), waveNum=1) # remove vignetted rays and rays outside a circular pupil (r>1) vig = np.array(rd[1]) valid_rays = np.logical_and(vig < 1, r <= 1) x = np.array(rd[2])[valid_rays] y = np.array(rd[3])[valid_rays] xMean, yMean = np.mean(x), np.mean(y) x_c, y_c = x - xMean, y - yMean radius = np.sqrt(x_c**2 + y_c**2) X.append(xMean) Y.append(yMean) X_MEAN.append(xMean) Y_MEAN.append(yMean) R.append(np.sort(radius)[int(EE/100*len(radius))]*1000) ax.scatter(xMean + zoom * x_c, yMean + zoom * y_c, s=0.2, c='k', lw=0) X, Y = np.array(X), np.array(Y) xi = np.linspace(np.min(X), np.max(X), 50) yi = np.linspace(np.min(Y), np.max(Y), 50) zi = griddata((X, Y), np.array(R), (xi[None,:], yi[:,None]), method='cubic') ax.set_xlim(np.min(xi), np.max(xi)) ax.set_ylim(np.min(yi), np.max(yi)) ax.set_xlabel('Detector x [mm]') ax.set_ylabel('Detector y [mm]') ax.set_title('Encircled Energy Map') im = ax.imshow(zi, interpolation='bilinear', cmap=plt.cm.jet, extent=[np.min(xi), np.max(xi), np.min(yi), np.max(yi)]) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) cb = plt.colorbar(im, cax=cax) cb.set_label('EE' + str(EE) + ' radius [micron]') fig.tight_layout() handle_figure(fig, 'map.png', bsavefig)
def parity_zGetTraceDirect_zGetTraceDirectArray(ln, numRays): """function to check the parity between the ray traced data returned by zGetTraceDirect() and zGetTraceDirectArray() """ # use zGetTraceArray to surface # 2 to get ray coordinates and direction # cosines at surface 2 radius = int(sqrt(numRays) / 2) flatGrid = [(x / (2 * radius), y / (2 * radius)) for x in xrange(-radius, radius + 1, 1) for y in xrange(-radius, radius + 1, 1)] px = [e[0] for e in flatGrid] py = [e[1] for e in flatGrid] tData0 = at.zGetTraceArray(numRays=numRays, px=px, py=py, waveNum=1, surf=2) assert sum(tData0[0]) == 0 # use zGetTraceDirectArray to trace rays to the image surface using the # the ray coordinates and direction cosines at surface 2 tData1 = at.zGetTraceDirectArray(numRays=numRays, x=tData0[2], y=tData0[3], z=tData0[4], l=tData0[5], m=tData0[6], n=tData0[7], waveNum=1, mode=0, startSurf=2, lastSurf=-1) assert sum(tData1[0]) == 0 tol = 1e-10 # use zGetTraceDirect to trace single rays per dde call for i in range(numRays): tData2 = ln.zGetTraceDirect(waveNum=1, mode=0, startSurf=2, stopSurf=-1, x=tData0[2][i], y=tData0[3][i], z=tData0[4][i], l=tData0[5][i], m=tData0[6][i], n=tData0[7][i]) assert tData2[0] == 0 for k in [2, 3, 4, 5, 6, 7]: assert abs(tData2[k] - tData1[k][i]) < tol, \ ("tData2[{}] = {}, tData1[{}][{}] = {}" .format(k, tData2[k], k, i, tData1[k][i])) print( "Parity test bw zGetTraceDirect() & zGetTraceDirectArray() successful")
def spots_matrix(nFields=5, N=51, zoom=75., box=25, bsavefig=False): '''create spot diagrams for nFields x nFields ray color by pupil position ''' print('Computing Spots Matrix') # Define rays nx = ny = N # number of rays in x- and y-direction px = np.repeat(np.linspace(-1, 1, nx), nx) py = np.tile(np.linspace(-1, 1, ny), ny) r = np.sqrt(px**2 + py**2) numRays = nx*ny fields = [(x, y) for y in np.linspace(1, -1, nFields) for x in np.linspace(-1, 1, nFields)] ENPD = ln.zGetPupil().ENPD fig, ax = plt.subplots(figsize=(10, 10)) # box around spots in mm box_size = box / 1000 for i, field in enumerate(fields): hx = np.repeat(field[0], numRays) hy = np.repeat(field[1], numRays) rd = at.zGetTraceArray(numRays, px=px.tolist(), py=py.tolist(), hx=hx.tolist(), hy=hy.tolist(), waveNum=1) # remove vignetted rays and rays outside a circular pupil (r>1) vig = np.array(rd[1]) valid_rays = np.logical_and(vig < 1, r <= 1) x = np.array(rd[2])[valid_rays] y = np.array(rd[3])[valid_rays] xMean = np.mean(x) yMean = np.mean(y) x_c = x - xMean y_c = y - yMean spotSTD = np.std(np.sqrt(x_c**2 + y_c**2)) adaptivezoom = zoom/(spotSTD*100) box = plt.Rectangle((xMean - box_size/2 * adaptivezoom, yMean - box_size/2 * adaptivezoom), adaptivezoom * box_size, adaptivezoom * box_size, fill=False) ax.add_patch(box) scatter = ax.scatter(xMean + adaptivezoom * x_c, yMean + adaptivezoom * y_c, s=0.5, c=r[valid_rays]*ENPD, cmap=plt.cm.jet, lw=0) ax.set_ylim((-20, 20)) ax.set_xlim((-20, 20)) ax.set_xlabel('Detector x [mm]') ax.set_ylabel('Detector y [mm]') divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) cb = fig.colorbar(scatter, cax=cax) cb.set_label('Pupil Diameter [mm]') ax.set_title('Adaptive Zoom Spots / Pupil size') ax.set_aspect('equal') fig.tight_layout() handle_figure(fig, 'coloredpupil.png', bsavefig)
def parity_zGetPolTraceDirect_zGetPolTraceDirectArray(ln, numRays): """function to check the parity between the ray traced data returned by zGetPolTraceDirect() and zGetPolTraceDirectArray() """ # use zGetTraceArray to surface # 2 to get ray coordinates and direction # cosines at surface 2 radius = int(sqrt(numRays)/2) flatGrid = [(x/(2*radius),y/(2*radius)) for x in xrange(-radius, radius + 1, 1) for y in xrange(-radius, radius + 1, 1)] px = [e[0] for e in flatGrid] py = [e[1] for e in flatGrid] tData0 = at.zGetTraceArray(numRays=numRays, px=px, py=py, waveNum=1, surf=2) assert sum(tData0[0]) == 0 # use zGetPolTraceDirectArray to trace rays to the image surface using the # the ray coordinates and direction cosines at surface 2 ptData1 = at.zGetPolTraceDirectArray(numRays=numRays, x=tData0[2], y=tData0[3], z=tData0[4], l=tData0[5], m=tData0[6], n=tData0[7], Ey=1.0, waveNum=1, mode=0, startSurf=2, lastSurf=-1) assert sum(ptData1[0]) == 0 tol = 1e-10 # Trace rays using single DDE call for i in range(numRays): ptData2 = ln.zGetPolTraceDirect(waveNum=1, mode=0, startSurf=2, stopSurf=-1, x=tData0[2][i], y=tData0[3][i], z=tData0[4][i], l=tData0[5][i], m=tData0[6][i], n=tData0[7][i], Ex=0, Ey=1.0, Phax=0, Phay=0) assert ptData2.error == 0 assert (ptData2.intensity - ptData1[1][i]) < tol, \ ("ptData2.intensity = {}, ptData1[1][{}] = {}" .format(ptData2.intensity, i, ptData1[1][i])) assert (ptData2.Exr - ptData1[2][i]) < tol, \ ("ptData2.Exr = {}, ptData1[2][{}] = {}" .format(ptData2.Exr, i, ptData1[2][i])) assert (ptData2.Exi - ptData1[3][i]) < tol, \ ("ptData2.Exi = {}, ptData1[3][{}] = {}" .format(ptData2.Exi, i, ptData1[3][i])) assert (ptData2.Eyr - ptData1[4][i]) < tol, \ ("ptData2.Eyr = {}, ptData1[4][{}] = {}" .format(ptData2.Eyr, i, ptData1[4][i])) assert (ptData2.Eyi - ptData1[5][i]) < tol, \ ("ptData2.Eyi = {}, ptData1[5][{}] = {}" .format(ptData2.Eyi, i, ptData1[5][i])) assert (ptData2.Ezr - ptData1[6][i]) < tol, \ ("ptData2.Ezr = {}, ptData1[6][{}] = {}" .format(ptData2.Ezr, i, ptData1[6][i])) assert (ptData2.Ezi - ptData1[7][i]) < tol, \ ("ptData2.Ezi = {}, ptData1[7][{}] = {}" .format(ptData2.Ezi, i, ptData1[7][i])) print("Parity test bw zGetPolTraceDirect() & zGetPolTraceDirectArray() successful")
def full_field_spot_diagramm(N=51, zoom=75, box=25, bsavefig=False): '''creates spot diagramm over the full field, similar to Zemax ''' print('Computing Full Field Spot Diagramm') # Define rays nx = ny = N # number of rays in x- and y-direction px = np.repeat(np.linspace(-1, 1, nx), nx) py = np.tile(np.linspace(-1, 1, ny), ny) r = np.sqrt(px**2 + py**2) numRays = nx * ny # Get field data and create Plot fieldData = ln.zGetField(0) fig, ax = plt.subplots(figsize=(fieldData.maxX * 2, fieldData.maxY * 2)) fields = ln.zGetFieldTuple() # Box around spots in mm box_size = box / 1000 for field in fields: hx = np.repeat(field.xf / fieldData.maxX, numRays) hy = np.repeat(field.yf / fieldData.maxY, numRays) rd = at.zGetTraceArray(numRays, px=px.tolist(), py=py.tolist(), hx=hx.tolist(), hy=hy.tolist(), waveNum=1) # remove vignetted rays and rays outside a circular pupil (r>1) vig = np.array(rd[1]) valid_rays = np.logical_and(vig < 1, r <= 1) x = np.array(rd[2])[valid_rays] y = np.array(rd[3])[valid_rays] xMean, yMean = np.mean(x), np.mean(y) x_c, y_c = x - xMean, y - yMean ax.scatter(xMean + zoom * x_c, yMean + zoom * y_c, s=0.3, c='blue', lw=0) box = plt.Rectangle( (xMean - box_size / 2 * zoom, yMean - box_size / 2 * zoom), zoom * box_size, zoom * box_size, fill=False) ax.add_patch(box) ax.grid() ax.set_title('Full Field Spot Diagram') ax.set_xlabel('Detector x [mm]') ax.set_ylabel('Detector y [mm]') handle_figure(fig, 'fullfield.png', bsavefig)
def get_time_zGetTraceArray(numRays, rettData=False): """return the time taken to perform tracing for the given number of rays using zGetTraceArray() function. """ radius = int(sqrt(numRays)/2) startTime = time.clock() flatGrid = [(x/(2*radius),y/(2*radius)) for x in xrange(-radius, radius + 1, 1) for y in xrange(-radius, radius + 1, 1)] px = [e[0] for e in flatGrid] py = [e[1] for e in flatGrid] tData = at.zGetTraceArray(numRays=numRays, px=px, py=py, waveNum=1) endTime = time.clock() if tData not in [-1, -999, -998] and sum(tData[0])==0: # tData[0] == error if rettData: return (endTime - startTime)*10e3, tData else: return (endTime - startTime)*10e3
def get_time_zGetTraceArray(numRays, rettData=False): """return the time taken to perform tracing for the given number of rays using zGetTraceArray() function. """ radius = int(sqrt(numRays) / 2) startTime = time.clock() flatGrid = [(x / (2 * radius), y / (2 * radius)) for x in xrange(-radius, radius + 1, 1) for y in xrange(-radius, radius + 1, 1)] px = [e[0] for e in flatGrid] py = [e[1] for e in flatGrid] tData = at.zGetTraceArray(numRays=numRays, px=px, py=py, waveNum=1) endTime = time.clock() if tData not in [-1, -999, -998] and sum( tData[0]) == 0: # tData[0] == error if rettData: return (endTime - startTime) * 10e3, tData else: return (endTime - startTime) * 10e3
def spiralSpot_using_zGetTraceArray(hx=0.0, hy=0.4, waveNum=1, spirals=10, numRays=600): """function replicates ``zSpiralSpot()`` using the ``pyzdde.arraytrace`` module helper function ``zGetTraceArray()`` """ startTime = time.clock() # create the hx, hy, px, py grid r = np.linspace(0, 1, numRays) theta = np.linspace(0, spirals*2.0*pi, numRays) px = (r*np.cos(theta)).tolist() py = (r*np.sin(theta)).tolist() # trace the rays tData = at.zGetTraceArray(numRays, [hx]*numRays, [hy]*numRays, px, py, waveNum=waveNum) # parse traced data and plot err, _, x, y, _, _, _, _, _, _, _, _, _ = tData endTime = time.clock() print("Execution time = {:4.2f}".format((endTime - startTime)*10e3), "ms") if sum(err)==0: plotTracedData(x, y) else: print("Error in tracing rays")
def full_field_spot_diagramm(N=51, zoom=75, box=25, bsavefig=False): '''creates spot diagramm over the full field, similar to Zemax ''' print('Computing Full Field Spot Diagramm') # Define rays nx = ny = N # number of rays in x- and y-direction px = np.repeat(np.linspace(-1, 1, nx), nx) py = np.tile(np.linspace(-1, 1, ny), ny) r = np.sqrt(px**2 + py**2) numRays = nx*ny # Get field data and create Plot fieldData = ln.zGetField(0) fig, ax = plt.subplots(figsize=(fieldData.maxX*2, fieldData.maxY*2)) fields = ln.zGetFieldTuple() # Box around spots in mm box_size = box / 1000 for field in fields: hx = np.repeat(field.xf / fieldData.maxX, numRays) hy = np.repeat(field.yf / fieldData.maxY, numRays) rd = at.zGetTraceArray(numRays, px=px.tolist(), py=py.tolist(), hx=hx.tolist(), hy=hy.tolist(), waveNum=1) # remove vignetted rays and rays outside a circular pupil (r>1) vig = np.array(rd[1]) valid_rays = np.logical_and(vig < 1, r <= 1) x = np.array(rd[2])[valid_rays] y = np.array(rd[3])[valid_rays] xMean, yMean = np.mean(x), np.mean(y) x_c, y_c = x - xMean, y - yMean ax.scatter(xMean + zoom * x_c, yMean + zoom * y_c, s=0.3, c='blue', lw=0) box = plt.Rectangle((xMean - box_size/2 * zoom, yMean - box_size/2 * zoom), zoom * box_size, zoom * box_size, fill=False) ax.add_patch(box) ax.grid() ax.set_title('Full Field Spot Diagram') ax.set_xlabel('Detector x [mm]') ax.set_ylabel('Detector y [mm]') handle_figure(fig, 'fullfield.png', bsavefig)
def parity_zGetPolTraceDirect_zGetPolTraceDirectArray(ln, numRays): """function to check the parity between the ray traced data returned by zGetPolTraceDirect() and zGetPolTraceDirectArray() """ # use zGetTraceArray to surface # 2 to get ray coordinates and direction # cosines at surface 2 radius = int(sqrt(numRays) / 2) flatGrid = [(x / (2 * radius), y / (2 * radius)) for x in xrange(-radius, radius + 1, 1) for y in xrange(-radius, radius + 1, 1)] px = [e[0] for e in flatGrid] py = [e[1] for e in flatGrid] tData0 = at.zGetTraceArray(numRays=numRays, px=px, py=py, waveNum=1, surf=2) assert sum(tData0[0]) == 0 # use zGetPolTraceDirectArray to trace rays to the image surface using the # the ray coordinates and direction cosines at surface 2 ptData1 = at.zGetPolTraceDirectArray(numRays=numRays, x=tData0[2], y=tData0[3], z=tData0[4], l=tData0[5], m=tData0[6], n=tData0[7], Ey=1.0, waveNum=1, mode=0, startSurf=2, lastSurf=-1) assert sum(ptData1[0]) == 0 tol = 1e-10 # Trace rays using single DDE call for i in range(numRays): ptData2 = ln.zGetPolTraceDirect(waveNum=1, mode=0, startSurf=2, stopSurf=-1, x=tData0[2][i], y=tData0[3][i], z=tData0[4][i], l=tData0[5][i], m=tData0[6][i], n=tData0[7][i], Ex=0, Ey=1.0, Phax=0, Phay=0) assert ptData2.error == 0 assert (ptData2.intensity - ptData1[1][i]) < tol, \ ("ptData2.intensity = {}, ptData1[1][{}] = {}" .format(ptData2.intensity, i, ptData1[1][i])) assert (ptData2.Exr - ptData1[2][i]) < tol, \ ("ptData2.Exr = {}, ptData1[2][{}] = {}" .format(ptData2.Exr, i, ptData1[2][i])) assert (ptData2.Exi - ptData1[3][i]) < tol, \ ("ptData2.Exi = {}, ptData1[3][{}] = {}" .format(ptData2.Exi, i, ptData1[3][i])) assert (ptData2.Eyr - ptData1[4][i]) < tol, \ ("ptData2.Eyr = {}, ptData1[4][{}] = {}" .format(ptData2.Eyr, i, ptData1[4][i])) assert (ptData2.Eyi - ptData1[5][i]) < tol, \ ("ptData2.Eyi = {}, ptData1[5][{}] = {}" .format(ptData2.Eyi, i, ptData1[5][i])) assert (ptData2.Ezr - ptData1[6][i]) < tol, \ ("ptData2.Ezr = {}, ptData1[6][{}] = {}" .format(ptData2.Ezr, i, ptData1[6][i])) assert (ptData2.Ezi - ptData1[7][i]) < tol, \ ("ptData2.Ezi = {}, ptData1[7][{}] = {}" .format(ptData2.Ezi, i, ptData1[7][i])) print( "Parity test bw zGetPolTraceDirect() & zGetPolTraceDirectArray() successful" )
def atrace(hx,hy,px,py): ret = at.zGetTraceArray(nr,list(hx),list(hy),list(px),list(py), intensity=1,waveNum=w,mode=mode,surf=-1,want_opd=-1); return np.column_stack(ret).T;
def spots_matrix(nFields=5, N=51, zoom=75., box=25, bsavefig=False): '''create spot diagrams for nFields x nFields ray color by pupil position ''' print('Computing Spots Matrix') # Define rays nx = ny = N # number of rays in x- and y-direction px = np.repeat(np.linspace(-1, 1, nx), nx) py = np.tile(np.linspace(-1, 1, ny), ny) r = np.sqrt(px**2 + py**2) numRays = nx * ny fields = [(x, y) for y in np.linspace(1, -1, nFields) for x in np.linspace(-1, 1, nFields)] ENPD = ln.zGetPupil().ENPD fig, ax = plt.subplots(figsize=(10, 10)) # box around spots in mm box_size = box / 1000 for i, field in enumerate(fields): hx = np.repeat(field[0], numRays) hy = np.repeat(field[1], numRays) rd = at.zGetTraceArray(numRays, px=px.tolist(), py=py.tolist(), hx=hx.tolist(), hy=hy.tolist(), waveNum=1) # remove vignetted rays and rays outside a circular pupil (r>1) vig = np.array(rd[1]) valid_rays = np.logical_and(vig < 1, r <= 1) x = np.array(rd[2])[valid_rays] y = np.array(rd[3])[valid_rays] xMean = np.mean(x) yMean = np.mean(y) x_c = x - xMean y_c = y - yMean spotSTD = np.std(np.sqrt(x_c**2 + y_c**2)) adaptivezoom = zoom / (spotSTD * 100) box = plt.Rectangle((xMean - box_size / 2 * adaptivezoom, yMean - box_size / 2 * adaptivezoom), adaptivezoom * box_size, adaptivezoom * box_size, fill=False) ax.add_patch(box) scatter = ax.scatter(xMean + adaptivezoom * x_c, yMean + adaptivezoom * y_c, s=0.5, c=r[valid_rays] * ENPD, cmap=plt.cm.jet, lw=0) ax.set_ylim((-20, 20)) ax.set_xlim((-20, 20)) ax.set_xlabel('Detector x [mm]') ax.set_ylabel('Detector y [mm]') divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) cb = fig.colorbar(scatter, cax=cax) cb.set_label('Pupil Diameter [mm]') ax.set_title('Adaptive Zoom Spots / Pupil size') ax.set_aspect('equal') fig.tight_layout() handle_figure(fig, 'coloredpupil.png', bsavefig)
def spot_radius_map(nFields=15, N=51, EE=80, zoom=10, bsavefig=False): ''' create spot diagrams for nFields x nFields calculate spot radii and generate density map ''' print('Computing Spot Radius Map') # Define rays nx = ny = N # number of rays in x- and y-direction px = np.repeat(np.linspace(-1, 1, nx), nx) py = np.tile(np.linspace(-1, 1, ny), ny) r = np.sqrt(px**2 + py**2) numRays = nx * ny fields = [(x, y) for y in np.linspace(1, -1, nFields) for x in np.linspace(-1, 1, nFields)] fig, ax = plt.subplots(figsize=(10, 10)) X, Y, X_MEAN, Y_MEAN, R = [], [], [], [], [] for i, field in enumerate(fields): hx = np.repeat(field[0], numRays) hy = np.repeat(field[1], numRays) rd = at.zGetTraceArray(numRays, px=px.tolist(), py=py.tolist(), hx=hx.tolist(), hy=hy.tolist(), waveNum=1) # remove vignetted rays and rays outside a circular pupil (r>1) vig = np.array(rd[1]) valid_rays = np.logical_and(vig < 1, r <= 1) x = np.array(rd[2])[valid_rays] y = np.array(rd[3])[valid_rays] xMean, yMean = np.mean(x), np.mean(y) x_c, y_c = x - xMean, y - yMean radius = np.sqrt(x_c**2 + y_c**2) X.append(xMean) Y.append(yMean) X_MEAN.append(xMean) Y_MEAN.append(yMean) R.append(np.sort(radius)[int(EE / 100 * len(radius))] * 1000) ax.scatter(xMean + zoom * x_c, yMean + zoom * y_c, s=0.2, c='k', lw=0) X, Y = np.array(X), np.array(Y) xi = np.linspace(np.min(X), np.max(X), 50) yi = np.linspace(np.min(Y), np.max(Y), 50) zi = griddata((X, Y), np.array(R), (xi[None, :], yi[:, None]), method='cubic') ax.set_xlim(np.min(xi), np.max(xi)) ax.set_ylim(np.min(yi), np.max(yi)) ax.set_xlabel('Detector x [mm]') ax.set_ylabel('Detector y [mm]') ax.set_title('Encircled Energy Map') im = ax.imshow(zi, interpolation='bilinear', cmap=plt.cm.jet, extent=[np.min(xi), np.max(xi), np.min(yi), np.max(yi)]) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%", pad=0.05) cb = plt.colorbar(im, cax=cax) cb.set_label('EE' + str(EE) + ' radius [micron]') fig.tight_layout() handle_figure(fig, 'map.png', bsavefig)
def atrace(hx,hy,px,py): ret = at.zGetTraceArray(nr,list(hx),list(hy),list(px),list(py), intensity=1,waveNum=w,mode=mode,surf=-1,want_opd=0); mask = np.ones(13,dtype=np.bool); mask[-2]=False; # mask array for removing opd from ret return np.column_stack(ret).T[mask];