general_optics_example.py

Go to the documentation of this file.
00001 "a sample system using general_optics.py to model a 10 Joule Nd:Glass CPA laser system"
00002 _rcsid="$Id: general_optics_example.py,v 1.3 2003/05/30 13:31:55 mendenhall Release-20030716 $"
00003 
00004 from math import *
00005 import math
00006 import Numeric
00007 import types
00008 import traceback
00009 
00010 import general_optics 
00011 from general_optics import composite_optic, grating, lens, reflector, null_optic, beam, qtens, Infinity, euler, trace_path, vec_mag
00012 from general_optics import phase_plate, halfwave_plate, faraday_rotator
00013 
00014 import copy
00015 
00016 import abcd_optics
00017 
00018 class spitfire:
00019     optics=abcd_optics
00020     mm=1e-3
00021     inch=25.4*mm
00022     lambda0=1.054e-6
00023     spitfire_thermal=optics.lens(500.0*mm) #unsubstantiated guess
00024     spitfire_abcd=(optics. mirror(1000.0*mm)*optics.space(19.0*inch)*optics.mirror(500.0*mm)*optics.space(9.5*inch)*spitfire_thermal*
00025             optics.space(9.5*inch)*optics.mirror(500.0*mm)* optics.space(19.0*inch)*optics.mirror(1000.0*mm)*
00026             optics.space(19.0*inch)*optics.mirror(500.0*mm)*optics.space(9.5*inch)*spitfire_thermal*optics.space(9.5*inch)*
00027             optics.mirror(500.0*mm)*optics.space(19.0*inch) )
00028     
00029     resonator=optics.abcd_resonator(spitfire_abcd, lambda0)
00030     exit_window=resonator.qw(optics.space(900.0*mm))    
00031     q0=exit_window.q    
00032 
00033 
00034 clight=299792458. #m/sec
00035 deg=pi/180.0
00036 inch = 0.0254
00037 
00038 import graphite
00039 
00040 show_qd=0 #quickdraw graphics works on Macintosh only
00041 show_pdf=1 #output nice pdf from graphite
00042 
00043 def draw_layout(graph, optics):
00044     if optics is None:
00045         return
00046     
00047     colorline = graphite.PointPlot()
00048     colorline.lineStyle = graphite.LineStyle(width=1, color=graphite.orange, kind=graphite.SOLID)
00049     colorline.symbol = None
00050     for i in optics.keys():
00051         olist=optics[i].polygon_list()
00052         for o in olist:
00053             if o is not None:
00054                 d=graphite.Dataset()
00055                 d.x=o[:,2]
00056                 d.y=o[:,0]
00057                 d.z=o[:,1]
00058                 #set coordinates to z=+right, x=+up, y=+out of paper
00059                 graph.datasets.append(d)
00060                 graph.formats.append(colorline)
00061 
00062 def draw_trace(graph, optics_trace):
00063     if optics_trace is None:
00064         return
00065         
00066     colorline = graphite.PointPlot()
00067     if optics_trace.color is None:
00068         color=graphite.black
00069     else:
00070         color=optics_trace.color
00071     
00072     colorline.lineStyle = graphite.LineStyle(width=1, color=color, kind=graphite.SOLID)
00073     colorline.symbol = None
00074 
00075     count=len(optics_trace)
00076     coords=Numeric.zeros((count,3), Numeric.Float)
00077     for i in range(count):
00078         xy=optics_trace[i].x0
00079         coords[i]=(xy[2],xy[0], xy[1]) #z is horizontal, x is vertical!
00080     
00081     graph.datasets.append(graphite.Dataset(coords))
00082     graph.formats.append(colorline)
00083 
00084 def draw_everything(optics, trace, xrange, yrange, three_d=None):
00085     
00086     g=graphite.Graph()
00087     g.top=10
00088     g.left=100
00089     g.right=g.left+700
00090     g.bottom=g.top+300
00091     g.axes[graphite.X].range=xrange
00092     g.axes[graphite.Y].range=yrange
00093     g.formats=[]
00094     if three_d:
00095         g.axes[graphite.Z].range=(-0.5, 0.5)
00096         g.lookAt=(-.25,-1.0,0)
00097         g.eyePosition=(-.75,-2,0.25)
00098         
00099     draw_layout(g, optics)
00100     draw_trace(g, trace)
00101     
00102     g.axes[graphite.Y].tickMarks[0].labels = "%+.1f"
00103     g.axes[graphite.Y].label.text = "meters"
00104     g.axes[graphite.Y].tickMarks[0].inextent= 0.02
00105     g.axes[graphite.Y].tickMarks[0].labelStyle=graphite.TextStyle(hjust=graphite.RIGHT, vjust=graphite.CENTER, 
00106         font=graphite.Font(10,0,0,0,None), 
00107         color=graphite.Color(0.00,0.00,0.00))
00108     g.axes[graphite.Y].tickMarks[0].labeldist=-0.01
00109 
00110     g.axes[graphite.X].tickMarks[0].labels = "%+.1f"
00111     g.axes[graphite.X].label.text = "meters"
00112     g.axes[graphite.X].tickMarks[0].inextent= 0.02
00113     g.axes[graphite.X].tickMarks[0].labelStyle=graphite.TextStyle(hjust=graphite.CENTER, vjust=graphite.TOP, 
00114         font=graphite.Font(10,0,0,0,None), 
00115         color=graphite.Color(0.00,0.00,0.00))
00116     g.axes[graphite.X].tickMarks[0].labeldist=-0.01
00117     
00118     return g
00119     
00120 class mir(reflector):
00121     "a one inch mirror"
00122     def post_init(self):
00123         self.width=0.0254
00124         self.thickness=0.005
00125         reflector.post_init(self)
00126 
00127 class serrated_aperture(null_optic):
00128     pass
00129 
00130 class plain_aperture(null_optic):
00131     pass
00132 
00133 class alignment_aperture(null_optic):
00134     pass
00135         
00136 class laser_head(null_optic):
00137     "an optic with both an inner box (rod) and outer box (case)"
00138     def inner_polygon(self):
00139         savew, savet = self.width, self.thickness
00140         self.width=self.rodsize
00141         self.thickness=self.thickness*0.75
00142         try:
00143             p=self.polygon()
00144         finally:
00145             self.width=savew
00146             self.thickness=savet
00147         return p
00148     def polygon_list(self):
00149         return [self.polygon(), self.inner_polygon()]
00150 
00151 class PL_brewster_filter(reflector):
00152     def post_init(self):
00153         self.width=5.0*inch
00154         self.height=2.0*inch
00155         self.thickness=0.125*inch
00156         self.brewster_angle=56.0
00157         if not self.__dict__.has_key("transmit"):
00158             self.transmit=0
00159         if not self.__dict__.has_key("reversed"):
00160             self.eta=0
00161         else:
00162             self.eta=180
00163             
00164     def outer_polygon(self):
00165         savew, savet = self.width, self.thickness
00166         self.width=4*inch
00167         self.thickness=6*inch
00168         myrot=general_optics.eulermat(-self.brewster_angle,self.eta,0)
00169         self.rotate_in_local_frame(myrot)
00170         try:
00171             p=self.polygon()
00172         finally:
00173             self.width=savew
00174             self.thickness=savet
00175             self.rotate_in_local_frame(Numeric.transpose(myrot))
00176         return p
00177     
00178     def local_transform(self):
00179         if not self.transmit:
00180             reflector.local_transform(self)
00181 
00182     def q_transform(self):
00183         if not self.transmit:
00184             reflector.q_transform(self)
00185 
00186     def place_between(self, from_obj, to_obj, distance):
00187         reflector.place_between(self, from_obj, to_obj, distance)
00188         self.rotate_in_local_frame(general_optics.eulermat(self.brewster_angle,0,0))
00189         return self
00190     
00191     def rotate_axis(self, axis_theta): #must undo screwy angles for this object before rotating
00192         self.rotate_in_local_frame(general_optics.eulermat(-self.brewster_angle,0,0))
00193         self.rotate_in_local_frame(general_optics.eulermat(0,0,axis_theta))
00194         self.rotate_in_local_frame(general_optics.eulermat(self.brewster_angle,0,0))
00195         return self
00196         
00197     def polygon_list(self):
00198         return [self.polygon(), self.outer_polygon()]
00199     
00200 class vacuum_spatial_filter(null_optic):
00201     "an optic with both an inner box (aperture) and outer box (tube)"
00202     def inner_polygon(self):
00203         savew, savet = self.width, self.thickness
00204         self.thickness=0.01
00205         try:
00206             p=self.polygon()
00207         finally:
00208             self.width=savew
00209             self.thickness=savet
00210         return p
00211     def polygon_list(self):
00212         return [self.polygon(), self.inner_polygon()]
00213                         
00214 class blue_through_ylf(composite_optic):
00215     #assign reasonably arbitrary keys to each optic for future reference.  
00216     #The values are unique within this optic
00217     
00218     UVM1, UVM2, UVM3, UVM4, UVM5, UVM6, UVM7, UVM8, UVM9, UVM10, UVM11, UVM12= range(12)
00219     PS1u, PS1d='ps1u', 'ps1d'
00220     UVL1, UVL2, DEMAG1, DEMAG2=range(20,24)
00221     YLF_SPLIT='ylf_split'
00222     SERR='serr'
00223     FILTER='filt'
00224     
00225     def __init__(self, **extras):
00226         inch=0.0254
00227         entrance_y=5.0*inch
00228         y0=2.5*inch #height of main line off table)
00229         my=blue_through_ylf
00230         optics={}
00231         
00232         #first, list all mirrors, and point them at each other
00233         optics[my.UVM1]=mir("UVM1", (13*inch, entrance_y, 7.5*inch))
00234         optics[my.UVM2]=mir("UVM2", (7.5*inch, entrance_y, 7.5*inch))
00235         optics[my.PS1u]=mir("Blue Peri 1 upper", (8*inch, entrance_y, 37*inch))
00236         optics[my.PS1d]=mir("Blue Peri 1 lower", (8*inch, y0, 37*inch))
00237         optics[my.UVM3]=mir("UVM3", (36*inch, y0, 38*inch))
00238         optics[my.UVM4]=mir("UVM4", (36*inch, y0, 137.5*inch))
00239         optics[my.UVM5]=mir("UVM5", (43.5*inch, y0, 49.5*inch))
00240         optics[my.UVM6]=mir("UVM6", (46.5*inch, y0, 137.5*inch))
00241         optics[my.UVM7]=mir("UVM7", (38*inch, y0, 38*inch))
00242         optics[my.UVM8]=mir("UVM8", (41.5*inch, y0, 136*inch))
00243         optics[my.UVM9]=mir("UVM9", (53*inch, y0, 136*inch))
00244         optics[my.UVM10]=mir("UVM10", (53*inch, y0, 41*inch))
00245         optics[my.UVM11]=mir("UVM11", (48*inch, y0, 41*inch))
00246         optics[my.UVM12]=mir("YLF retro", (48*inch, y0,80.5*inch))
00247         optics[my.YLF_SPLIT]=mir("YLF exit splitter", (48*inch, y0, 47.8*inch))
00248         
00249         optics[my.UVL1]=lens("UVL1", f=+0.75).place_between(optics[my.UVM3], optics[my.UVM4], 4.0*inch)
00250         optics[my.UVL2]=lens("UVL2", f=+1.00).place_between(optics[my.UVL1], optics[my.UVM4], 83*inch-0.0*inch)
00251                 
00252         optics[my.DEMAG1]=lens("UVL3", f=+0.75).place_between(optics[my.UVM9], optics[my.UVM10], 23.0*inch)
00253         optics[my.DEMAG2]=lens("UVL4", f=+1.00).place_between(optics[my.DEMAG1], optics[my.UVM10], 1.7+5.0*inch)
00254 
00255         optics[my.SERR]=null_optic("Serr. Aperture", width=1.0*inch, thickness=0.1*inch).place_between(optics[my.DEMAG1], optics[my.DEMAG2], 3*inch)
00256         optics[my.FILTER]=null_optic("Filter Aperture", width=1.0*inch, thickness=0.1*inch).place_between(optics[my.DEMAG1], optics[my.DEMAG2], 0.75)
00257         
00258         looks=[my.UVM1, my.UVM2, my.PS1u, my.PS1d, my.UVM3, my.UVM4, my.UVM5, my.UVM6, my.UVM7,
00259             my.UVM8, my.UVM9, my.UVM10, my.UVM11, my.UVM12, my.YLF_SPLIT]
00260         #align all mirrors
00261         for i in range(1, len(looks)-1):
00262             optics[looks[i]].set_direction(optics[looks[i-1]], optics[looks[i+1]])
00263 
00264         order=[my.UVM1, my.UVM2, my.PS1u, my.PS1d, my.UVM3, my.UVL1, my.UVL2, my.UVM4, my.UVM5, my.UVM6, my.UVM7,
00265             my.UVM8, my.UVM9, my.DEMAG1, my.SERR, my.FILTER, my.DEMAG2, my.UVM10, my.UVM11, my.UVM12, my.YLF_SPLIT]
00266         
00267         #specify center and reference as (0,0,0) to make our coordinates absolute
00268         composite_optic.init(self, "blue line", optics, order, (0,0,0), (0,0,0), 0, extras=extras )
00269         
00270 class ir_line(composite_optic):
00271     M1, M2, M3, M4, M5, M6, M7, M8, M9, M10, M11, M12, M13, M14, M15= range(15)
00272     L1, L2, L3, L4, L5, L6, L7, L8, L7a=range(20,29)
00273     VSF1, VSF2, VSF3=range(30,33)
00274     SERR1='Serr1'
00275     SF1='SF1'
00276     FR12, FR25 = 'fr12', 'fr25'
00277     A1, A2, A3, A4, A5 = range(40,45)
00278     G9a, G9b, G25a, G25b, G50 = range(50,55)
00279     TrM1, TrM2, TrM3, TrM4 = range(60,64)
00280     BP2, BP3, BP4 = range(70,73)    
00281     QR1, QR2, QR3, QR4 =range(80,84)
00282     EXIT='exit'
00283         
00284     def __init__(self, **extras):
00285         inch=0.0254
00286         entrance_y=5.0*inch
00287         exit_y=13.5*inch
00288         my=ir_line
00289         optics={}
00290         
00291         #first, list all mirrors, and point them at each other
00292         optics[my.M1]=mir("M1", (2*inch, entrance_y, 10*inch))
00293         optics[my.M2]=mir("M2", (4*inch, entrance_y, 10*inch))
00294         optics[my.TrM1]=mir("TrM1", (4*inch, entrance_y, 96*inch))
00295         optics[my.TrM2]=mir("TrM2", (6*inch, entrance_y, 96*inch))
00296         optics[my.TrM3]=mir("TrM3", (6*inch, entrance_y, 82.5*inch))
00297         optics[my.TrM4]=mir("TrM4", (2*inch, entrance_y, 82.5*inch))
00298         optics[my.M3]=mir("M3", (4*inch, entrance_y, 135*inch))
00299         optics[my.M4]=mir("M4", (12*inch, entrance_y, 135*inch))
00300         optics[my.M5]=mir("M5", (13*inch, entrance_y, 105*inch))
00301         optics[my.M6]=mir("M6", (14*inch, entrance_y, 105*inch))
00302         optics[my.M7]=mir("M7", (16.5*inch, entrance_y, 3*inch))
00303         optics[my.M8]=mir("M8", (24*inch, entrance_y, 3*inch))
00304         optics[my.M9]=mir("M9", (23*inch, entrance_y, 135*inch))
00305         optics[my.M10]=mir("M10", (33*inch, entrance_y, 134.5*inch))
00306         optics[my.M11]=mir("M11", (33*inch, entrance_y, -6*inch))
00307         optics[my.BP4]=PL_brewster_filter("BP4", (33*inch, entrance_y, 27*inch), reversed=1)
00308         optics[my.M12]=mir("M12", (20*inch, entrance_y, 33*inch))
00309         optics[my.M13]=mir("M13", (20*inch, entrance_y, 12*inch))
00310         optics[my.M14]=mir("M14", (8.5*inch, entrance_y, 11.5*inch))
00311         optics[my.M15]=mir("M15", (8.5*inch, exit_y, 11.5*inch))
00312         
00313         optics[my.EXIT]=sys_exit=null_optic("exit", (10.0*inch, exit_y, 142.0*inch))
00314                 
00315         optics[my.L1]=lens("L1", f=+0.400).place_between(optics[my.M2], optics[my.TrM1], 12.0*inch)
00316         optics[my.L2]=lens("L2", f=+0.800).place_between(optics[my.L1], optics[my.TrM1], 1.30)
00317         optics[my.L3]=lens("L3", f=+0.750).place_between(optics[my.M6], optics[my.M7], 10*inch)
00318         optics[my.L4]=lens("L4", f=+1.500).place_between(optics[my.L3], optics[my.M7], 2.25)
00319         optics[my.L5]=lens("L5", f=+0.750).place_between(optics[my.M10], optics[my.M11], 5*inch)
00320         optics[my.L6]=lens("L6", f=+1.500).place_between(optics[my.L5], optics[my.M11], 95.5*inch)
00321         optics[my.L7]=lens("L7", f=+0.750).place_between(optics[my.M15], sys_exit, 4.5*inch)
00322         optics[my.L8]=lens("L8", f=+2.500, width=6*inch, thickness=0.25*inch).\
00323             place_between(optics[my.M15], sys_exit, -1*inch).tilt_off_axis((0,45,0))
00324         
00325         optics[my.G9a]=laser_head("9mm-1", width=2.0*inch, thickness=6.0*inch, rodsize=0.009).\
00326             place_between(optics[my.M4], optics[my.M5], 9*inch)
00327         optics[my.G9b]=laser_head("9mm-2", width=2.0*inch, thickness=6.0*inch, rodsize=0.009).\
00328             place_between(optics[my.M4], optics[my.M5], 23*inch)
00329         
00330         optics[my.G25a]=laser_head("25mm-1", width=6.0*inch, thickness=12.0*inch, rodsize=0.025).\
00331             place_between(optics[my.M8], optics[my.M9], 74*inch)
00332         optics[my.G25b]=laser_head("25mm-2", width=6.0*inch, thickness=12.0*inch, rodsize=0.025).\
00333             place_between(optics[my.M8], optics[my.M9], 94*inch)
00334 
00335         optics[my.G50]=laser_head("50mm", width=9.0*inch, thickness=15.0*inch, rodsize=0.050).\
00336             place_between(optics[my.M10], optics[my.M11], -19*inch)
00337 
00338         optics[my.SERR1]=serrated_aperture("serrated aperture", diameter=0.003).\
00339             place_between(optics[my.M2], optics[my.TrM1], 10*inch)      
00340         optics[my.SF1]=plain_aperture("spatial filter 1", diameter=0.001).\
00341             place_between(optics[my.M2], optics[my.TrM1], 35*inch)
00342         
00343         optics[my.QR1]=halfwave_plate("QR1", width=1*inch, thickness=0.5*inch).\
00344             place_between(optics[my.G9a], optics[my.G9b], 8*inch).rotate_axis(22.5) 
00345         optics[my.FR12]=faraday_rotator("FR12", width=0.5*inch, thickness=6*inch, rotation=45).\
00346             place_between(optics[my.M6], optics[my.M7], 5*inch)
00347         optics[my.VSF1]=vacuum_spatial_filter("VSF1", thickness=24*inch, width=2*inch).\
00348             place_between(optics[my.L3], optics[my.L4], 0.750)
00349             
00350         optics[my.QR2]=halfwave_plate("QR2", width=1*inch, thickness=0.5*inch).\
00351             place_between(optics[my.G25a], optics[my.G25b], 8*inch).rotate_axis(22.5)   
00352 
00353         optics[my.BP2]=PL_brewster_filter("BP2", transmit=1).\
00354             place_between(optics[my.G25b], optics[my.M9], 13*inch).rotate_axis(90)
00355         optics[my.QR3]=halfwave_plate("QR3", width=1*inch, thickness=0.5*inch).\
00356             place_between(optics[my.G25b], optics[my.M9], 19*inch).rotate_axis(22.5)    
00357         optics[my.FR25]=faraday_rotator("FR25", width=1.0*inch, thickness=6.0*inch, rotation=45).\
00358             place_between(optics[my.G25b], optics[my.M9], 23*inch)
00359         optics[my.BP3]=PL_brewster_filter("BP3", transmit=1).\
00360             place_between(optics[my.G25b], optics[my.M9], 30*inch).rotate_axis(0)
00361         
00362         looks=[my.M1, my.M2, my.TrM1, my.TrM2, my.TrM3, my.TrM4, my.M3, my.M4, my.M5,
00363             my.M6, my.M7, my.M8, my.M9, 
00364             my.M10, my.M11, my.BP4, my.M12, my.M13, my.M14, my.M15, my.EXIT]
00365         #align all mirrors
00366         for i in range(1, len(looks)-1):
00367             optics[looks[i]].set_direction(optics[looks[i-1]], optics[looks[i+1]])
00368 
00369         order=[my.M1, my.M2, my.SERR1, my.L1, my.SF1, my.L2, my.TrM1, my.TrM2, my.TrM3, my.TrM4, my.M3, my.M4, my.G9a, 
00370             my.QR1, my.G9b, my.M5,
00371             my.M6, my.FR12, my.L3, my.VSF1, my.L4, my.M7, my.M8, my.G25a, my.QR2, my.G25b, 
00372             my.BP2, my.QR3, my.FR25, my.BP3, 
00373             my.M9, my.M10, my.L5, my.L6, my.G50, my.M11, my.BP4, my.M12, 
00374             my.M13, my.M14, my.M15, my.L7, my.L8]
00375         
00376         #specify center and reference as (0,0,0) to make our coordinates absolute
00377         composite_optic.init(self, "IR line", optics, order, (0,0,0), (0,0,0), 0, extras=extras )
00378 
00379 class ir_compressor(composite_optic):
00380     INPUT='M1'
00381     OUTPUT='M2'
00382     FOCUS='L1'
00383     G1="grating 1"
00384     G2="grating 2"
00385     VR1='vert_retro_1'
00386     VR2='vert_retro_2'
00387     START='bc.start'
00388     END='bc.end'
00389                 
00390     def __init__(self, theta1=61.486, clen=1.02, lambda0=1.054e-6, center=(0,0,0), angle=0, **extras):
00391         self.init(theta1, clen, lambda0, center, angle, extras)
00392         
00393     def init(self, theta1, clen, lambda0, center, angle, extras):
00394         my=ir_compressor
00395         input_height=18*inch
00396         output_height=12*inch
00397         center_height=(input_height+output_height)/2.0
00398         
00399         basebeam=beam((0,input_height,-1.0), qtens(lambda0, w=0.005, r=Infinity))       
00400         optics={}
00401                     
00402         optics[my.INPUT]=m1=reflector("input mirror", center=(0, input_height, 0), width=8*inch, angle=-45)
00403         
00404         optics[my.G1]=g1=grating("g1", angle=theta1+90, center=(52*inch,center_height, 0), 
00405                 pitch=1740e3, order=1, width=16*inch, thickness=2.0*inch)
00406         mybeam=basebeam.clone()
00407         m1.transport_to_here(mybeam)
00408         m1.transform(mybeam)    
00409         g1.transport_to_here(mybeam)
00410         g1.transform(mybeam)
00411         mybeam.free_drift(clen) #this is where grating 2 should be
00412         optics[my.G2]=g2=grating("g2", angle=theta1-90, center=mybeam.x0+(0,0,1e-8), 
00413                 pitch=1740e3, order=1, width=16*inch, thickness=2.0*inch)
00414         
00415         optics[my.VR1]=reflector("retro", center=(40*inch, center_height, g2.center[2]),  angle=90.0, width=8*inch, thickness=1.0*inch)
00416         
00417         out=optics[my.OUTPUT]=reflector("output mirror", center=(8*inch, output_height, 0.0), 
00418                 width=8.0*inch, thickness=1.0*inch)
00419         focus=optics[my.FOCUS]=lens("output focus", center=out.center+(35*inch, 0, 7*inch), 
00420                 angle=90-math.atan(0.2)/deg, f=2.0, width=8.0*inch, 
00421                 height=8.0*inch, thickness=1.0*inch).tilt_off_axis(0)
00422         out.set_direction(g1.center-(0, center_height-output_height, 0), focus)
00423         
00424         comp_order=(my.INPUT, my.G1, my.G2, my.VR1, my.G2, my.G1, my.OUTPUT, my.FOCUS)
00425         
00426         composite_optic.init(self, "ir compressor", optics, comp_order, None, center=center, angle=0, extras=extras )       
00427 
00428         #prepare to handle to downslope in the beam through the compressor while we are still
00429         #not rotated to the funny beam axis
00430         m1label=self.mark_label(my.INPUT)
00431         g1label=self.mark_label(my.G1)
00432         m2label=self.mark_label(my.OUTPUT)
00433         ir_trace=trace_path(self, basebeam.clone())
00434         path_len=(ir_trace[(m2label,0)].total_drift-ir_trace[(m1label,0)].total_drift)
00435         slope=(output_height-input_height)/path_len
00436         
00437         #distance from entrance to first g1 hit
00438         g1_first_distance=(ir_trace[(g1label,0)].total_drift-ir_trace[(m1label,0)].total_drift) 
00439         #distance from entrance to second g1 hit
00440         g1_second_distance=(ir_trace[(g1label,1)].total_drift-ir_trace[(m1label,0)].total_drift) 
00441         
00442         #now, rotate us to the real beam direction
00443         self.update_coordinates(self.center, self.center, general_optics.eulermat(angle, 0, 0)) 
00444         
00445         #and set up the aiming points
00446         self.g1target1=g1.center+(0, (input_height-center_height)+g1_first_distance*slope, 0)       
00447         self.g1target2=g1.center+(0, (input_height-center_height)+g1_second_distance*slope, 0)  
00448         out.set_direction(self.g1target2, focus)
00449 
00450     def set_entrance_direction(self, look_to):
00451         my=ir_compressor
00452         self.optics_dict[my.INPUT].set_direction(look_to, self.g1target1)
00453         
00454 class blue_compressor(composite_optic):
00455     IR1="bc.ir1"
00456     IR2="bc.ir2"
00457     OR1="bc.or1"
00458     GRATE="bc.grating"
00459     VR1='bc.vert_retro_1'
00460     VR2='vbc.ert_retro_2'
00461     IPERI1='bc.ip1'
00462     IPERI2='bc.ip2'
00463     EXP1='bc.exp1'
00464     EXP2='bc.exp2'
00465     OPERI1='bc.op1'
00466     OPERI2='bc.op2'
00467     TM1='bc.turn1'
00468     TM2='bc.turn2'
00469     DEMAG1='bc.dmg1'
00470     DEMAG2='bc.dmg2'
00471     START='bc.start'
00472     END='bc.end'
00473     y_offset=0.5*inch
00474         
00475     def setup_retro_standard(self, beam, vertex_distance, retro_beam_offset, retro_err, y_center):
00476         """setup_retro_standard(diffracted_beam, vertex_distance, grating_beta, grating_spot_offset, retro_err) ->
00477         (retro_mirror_1, retro_mirror_2)"""
00478         my=blue_compressor
00479         c,s = beam.direction()[2], beam.direction()[0]
00480         vz, vx = c*vertex_distance, s*vertex_distance
00481         vz, vx = vz - s*retro_beam_offset, vx + c*retro_beam_offset
00482         beam_angle=math.atan2(s,c)/deg
00483         ir1=reflector(my.IR1, angle=(beam_angle-45-retro_err/2), center=(vx,y_center,vz), justify="left", width=0.05)
00484         ir2=reflector(my.IR2, angle=(beam_angle+45+retro_err/2), center=(vx,y_center,vz), justify="right", width=0.05)
00485         #print beam_angle, ir1,ir2
00486         return ir1, ir2
00487     
00488     def setup_reflectors_blue(self, basebeam, theta1, clen, grating_spot_offset, pitch=1.5e6, lam0=1.053e-6, inside_retro_err=0, zeta=0):
00489         my=blue_compressor
00490         y_offset=my.y_offset
00491         grate=grating(my.GRATE, angle=theta1, center=(0,y_offset/2, 0), pitch=pitch, order=1, justify=-.8, height=0.05, width=0.1)
00492         littrow, beta=grate.degree_angles(theta1, lam0)
00493         vertex_dist=(clen-grating_spot_offset*sin(beta*deg))*0.5
00494         retro_beam_offset=grating_spot_offset*math.cos(beta*deg)*0.5
00495         beam=basebeam.clone().set_lambda(lam0)
00496         grate.transport_to_here(beam)
00497         grate.transform(beam)
00498         return_x=-grating_spot_offset*math.cos(theta1*deg)
00499         vretvertex=Numeric.array((return_x, y_offset/2, -0.22))
00500         yvec=Numeric.array((0.,y_offset,0.))
00501         ir1, ir2 = self.setup_retro_standard(beam, vertex_dist, retro_beam_offset, inside_retro_err, y_offset/2)
00502         vr1=reflector('vert retro 1', angle=0, center=vretvertex-yvec/2, width=0.025, height=0.05, thickness=0.01)
00503         vr2=reflector('vert retro 2', angle=0, center=vretvertex+yvec/2, width=0.025, height=0.05)
00504         vr1.set_direction((return_x,0,0), vr2)
00505         vr2.set_direction(vr1, (return_x, y_offset, 0))
00506         return {my.GRATE:grate, my.IR1:ir1, my.IR2:ir2, my.VR1:vr1, my.VR2:vr2 }
00507     
00508     def __init__(self, theta1, clen, lambda0, center=(0,0,0), angle=0, **extras):
00509         self.init(theta1, clen, lambda0, center, angle, extras)
00510         
00511     def init(self, theta1, clen, lambda0, center, angle, extras):
00512         grating_offset=-0.075
00513         exit_height=-1.0*inch
00514         exit_z=-0.275
00515         my=blue_compressor
00516         basebeam=beam((0,0,-1.0), qtens(lambda0, w=0.001, r=Infinity))
00517         optics=self.setup_reflectors_blue(basebeam, theta1, clen, grating_offset, lam0=lambda0, inside_retro_err=0.0)
00518                     
00519         cs=Numeric.array((0, exit_height, -0.44)) #entrance to compressor, before rotation
00520     
00521         optics[my.IPERI1]=reflector("input peri bot", angle=0, center=cs, width=.025)
00522         optics[my.IPERI2]=reflector("input peri top", angle=0, center=cs+(0.0,-exit_height, 0), width=.025)
00523     
00524         optics[my.EXP1]=lens("expander diverge", f=-.15).place_between(cs+(-.1,0,0), optics[my.IPERI1], -0.09)
00525         optics[my.EXP2]=lens("expander re-coll", f=0.3).place_between(optics[my.IPERI2], (0,0,0), 0.037)    
00526         #optics[my.EXP2]=lens("expander re-coll", f=0.3).place_between(optics[my.IPERI2], (0,0,0), 0.0357)  
00527     
00528         optics[my.IPERI1].set_direction(optics[my.EXP1], optics[my.IPERI2])
00529         optics[my.IPERI2].set_direction(optics[my.IPERI1], optics[my.EXP2])
00530     
00531         optics[my.OPERI1]=reflector("output peri top", angle=0, center=(0,my.y_offset,exit_z), width=.025)
00532         optics[my.OPERI2]=reflector("output peri bot", angle=0, center=(0,exit_height,exit_z), width=.025)
00533 
00534         optics[my.TM1]=reflector("output turn 1", angle=90, center=(0.30, exit_height,exit_z), width=.025)
00535     
00536         optics[my.OPERI1].set_direction((0,my.y_offset,0), optics[my.OPERI2])
00537         optics[my.OPERI2].set_direction(optics[my.OPERI1], optics[my.TM1])
00538                 
00539         comp_order=(my.EXP1, my.IPERI1, my.IPERI2, my.EXP2, my.GRATE, 
00540                 my.IR2, my.IR1, my.GRATE, my.VR1, my.VR2, my.GRATE, my.IR1, my.IR2, 
00541                 my.GRATE, my.OPERI1, my.OPERI2, my.TM1)
00542                     
00543         composite_optic.init(self, "compressor", optics, comp_order, None, center=center, angle=angle, extras=extras )      
00544 
00545 
00546 def doit_bc(theta1, clen, lambda0, drawit=0):
00547     
00548     print "\n\n***start blue line trace***\n"
00549     grating_offset=-0.075
00550     exit_height=0
00551     exit_z=-0.3
00552     eta1=0.0
00553     
00554     optics={}
00555     
00556     END='end'
00557     optics[END]=null_optic("end", (0.15,exit_height,0), 0)
00558     START='start'
00559     optics[START]=null_optic("start", (0,0,-0.85))
00560 
00561     
00562     tracebeam=basebeam.clone()
00563     system_center=Numeric.array((-0.1, 0, -0.85))
00564     
00565     basebeam=beam(system_center, qtens(lambda0, q=spitfire.q0), lambda0)
00566     tracebeam.free_drift(-0.2)
00567         
00568     COMP='comp'
00569     comp=optics[COMP]=blue_compressor(theta1, clen, lambda0, center=system_center, angle=rotation)
00570     TM2='turn2'
00571     optics[TM2]=reflector("output turn 2", angle=0, center=(0.15,exit_height,-0.6), width=.025)
00572 
00573     optics[COMP].set_exit_direction(optics[TM2])
00574     optics[TM2].set_direction(optics[COMP], optics[END])
00575 
00576     sys_order=(START, COMP, TM2, DEMAG1, DEMAG2, END)
00577 
00578     GRATE=comp.mark_label(blue_compressor.GRATE)
00579     IR1=comp.mark_label(blue_compressor.IR1)
00580     IR2=comp.mark_label(blue_compressor.IR2)
00581     
00582     optic_sys=composite_optic("system", optics, sys_order, center=optics[START].center)
00583     
00584     trace0=trace_path(optic_sys, tracebeam.shift_lambda(0))
00585     trace0.color=graphite.green
00586     trace1=trace_path(optic_sys, tracebeam.shift_lambda(-0.5e-9))
00587     trace1.color=graphite.blue
00588     trace2=trace_path(optic_sys, tracebeam.shift_lambda(+0.5e-9))
00589     trace2.color=graphite.red
00590             
00591     try: #if one of the traces failed, this may not work
00592         print "Theta1=%.3f eta=%.3f len=%.3f lambda=%.4f" % (theta1, eta1, clen, lambda0*1e6)
00593         d0=trace0[-1]['total_drift']
00594         d1=trace1[-1]['total_drift']
00595         d2=trace2[-1]['total_drift']
00596         print ("d(lambda0-0.5nm)=%.3f m, d(lambda0+0.5nm)=%.3f m, dt/dl=%.0f ps/nm, " % (d1, d2, (d2-d1)*1e12/clight)), 
00597         print "d2t/dl2 = %.2f ps/nm^2" % ((d2+d1-2.0*d0)*(1e12/clight)*4)
00598         spot1info=trace0[(GRATE,0)] 
00599         spot2info=trace0[(GRATE,1)] 
00600         ir1info=trace0[(IR1,0)]
00601         ir2info=trace0[(IR2,0)]
00602         spot_offset=spot2info['position']-spot1info['position']
00603         retro_offset=ir2info['position']-ir1info['position']
00604         print "Grating offset = %.3f, retro_offset=%.3f" % (vec_mag(spot_offset), vec_mag(retro_offset))
00605         print "measured vertex length = %.3f" % vec_mag(comp[GRATE].center-comp[IR1].center)
00606         print "dispersion offset on grating = %.3f m / nm" % vec_mag(trace2[(GRATE,1)]['position']-trace1[(GRATE,1)]['position'])
00607         print "final q = ", trace0[-1]['q']
00608     except:
00609         traceback.print_exc()
00610         pass
00611                 
00612     if drawit:
00613         g=draw_everything({"sys":optic_sys}, trace0, (-.9, .1), (-.5, .5), three_d=0)
00614         #g=draw_everything(optics, trace0, (-2, 2), (-2, 2))
00615         draw_trace(g, trace1)
00616         draw_trace(g, trace2)
00617         graphite.genOutput(g,'QD',canvasname="Compressor layout", size=(600,500))
00618         #graphite.genOutput(g,'PDF',canvasname="mendenhall pbg3:compressor.pdf", size=(600,500))
00619 
00620 class quadrupler(composite_optic):
00621     L1, ENTRANCE, L2, DOUBLE, QUADRUPLE, EXIT = range(6)
00622 
00623     def __init__(self, center, from_optic, **extras):
00624         my=quadrupler
00625         optics={}
00626         ent=optics[my.ENTRANCE]=mir("quadrupler entrance")
00627         exit=optics[my.EXIT]=null_optic("quadrupler exit", (0,0,-1.0))
00628         l1=optics[my.L1]=lens("quadrupler telescope 1", f=+0.300)
00629         l2=optics[my.L2]=lens("quadrupler telescope 2", f=-0.150).place_between(ent, exit, 0.111).tilt_off_axis(4.0)
00630         #print l2.strength
00631         green=optics[my.DOUBLE]=null_optic("green crystal").place_between(l2, exit, 0.1)
00632         optics[my.QUADRUPLE]=null_optic("UV crystal").place_between(green, exit, 0.1)
00633 
00634         order=(my.L1, my.ENTRANCE, my.L2, my.DOUBLE, my.QUADRUPLE, my.EXIT)     
00635         composite_optic.init(self, "quadrupler", optics, order, (0,0,0), center, 0, extras=extras )
00636         l1.place_between(from_optic, ent, -0.04)
00637 
00638     def entrance_optics_tags(self):
00639         #the alignment element in the quadrupler is _not_ the first element (the lens)
00640         return quadrupler.ENTRANCE, quadrupler.EXIT
00641         
00642 def plotq(trace):
00643     qxl=[]
00644     qyl=[]
00645     zl=[]
00646     for i in trace:
00647         zl.append(i.total_drift)
00648         qi=i.incoming_q
00649         qix, qiy=i.transform_q_to_table(qi)
00650         #xform, qix, qiy=qi.qi_moments()
00651         qxl.append(qi.rw(qix)[1])
00652         qyl.append(qi.rw(qiy)[1])
00653         zl.append(i.total_drift)
00654         qi=i.q
00655         qix, qiy=i.transform_q_to_table(qi)
00656         #xform, qix, qiy=qi.qi_moments()
00657         qxl.append(qi.rw(qix)[1])
00658         qyl.append(qi.rw(qiy)[1])
00659     
00660     
00661     g=graphite.Graph()
00662     g.top=10
00663     g.left=100
00664     g.right=g.left+700
00665     g.bottom=g.top+300
00666     #g.axes[graphite.X].range=xrange
00667     #g.axes[graphite.Y].range=yrange
00668     g.formats=[]
00669     
00670     dsx=graphite.Dataset()
00671     dsx.x=zl
00672     dsx.y=qxl
00673     g.datasets.append(dsx)
00674     colorline = graphite.PointPlot()
00675     colorline.lineStyle = graphite.LineStyle(width=1, color=graphite.red, kind=graphite.SOLID)
00676     colorline.symbol = None
00677     g.formats.append(colorline) 
00678     
00679     dsy=graphite.Dataset()
00680     dsy.x=zl
00681     dsy.y=qyl
00682     g.datasets.append(dsy)
00683     colorline = graphite.PointPlot()
00684     colorline.lineStyle = graphite.LineStyle(width=1, color=graphite.blue, kind=graphite.SOLID)
00685     colorline.symbol = None
00686     g.formats.append(colorline)
00687 
00688     g.axes[graphite.Y].tickMarks[0].labels = "%+.3f"
00689     g.axes[graphite.Y].label.text = "meters"
00690     g.axes[graphite.Y].tickMarks[0].inextent= 0.02
00691     g.axes[graphite.Y].tickMarks[0].labelStyle=graphite.TextStyle(hjust=graphite.RIGHT, vjust=graphite.CENTER, 
00692         font=graphite.Font(10,0,0,0,None), 
00693         color=graphite.Color(0.00,0.00,0.00))
00694     g.axes[graphite.Y].tickMarks[0].labeldist=-0.01
00695 
00696     g.axes[graphite.X].tickMarks[0].labels = "%+.0f"
00697     g.axes[graphite.X].label.text = "meters"
00698     g.axes[graphite.X].tickMarks[0].inextent= 0.02
00699     g.axes[graphite.X].tickMarks[0].labelStyle=graphite.TextStyle(hjust=graphite.CENTER, vjust=graphite.TOP, 
00700         font=graphite.Font(10,0,0,0,None), 
00701         color=graphite.Color(0.00,0.00,0.00))
00702     g.axes[graphite.X].tickMarks[0].labeldist=-0.01
00703         
00704     if show_qd:
00705         graphite.genOutput(g,'QD',canvasname="Beam size", size=(900,500))
00706     if show_pdf:
00707         graphite.genOutput(g,'PDF',canvasname="Q_plot", size=(900,500))
00708             
00709 def show_table():
00710     inch=0.0254
00711     lambda0=1.054e-6
00712     spitfire_exit=Numeric.array((2*inch, 5*inch, -0.65))
00713     compressor_entrance=Numeric.array((45.5*inch, 2.5*inch, 46.5*inch))
00714     
00715     optics={}
00716     BLUELINE='bl'
00717     SPLIT='split'
00718     START='start'
00719     COMP='compressor'
00720     QUAD='quadrupler'
00721     IR='ir'
00722     IR_COMP='ir compressor'
00723     BE_TURN='be_turn'
00724     IZ_SCREEN='iz'
00725     
00726     optics[START]=null_optic("start", spitfire_exit)
00727     optics[BLUELINE]=blueline=blue_through_ylf()    
00728     optics[SPLIT]=split1=reflector("splitter1", center=(2*inch, 5*inch, 3*inch))
00729     optics[IR]=irline=ir_line()
00730     
00731     comp=optics[COMP]=blue_compressor(38.5, 1.28, lambda0, center=compressor_entrance, angle=270)
00732     mainbeam=beam( spitfire_exit, qtens(lambda0, spitfire.q0), lambda0)
00733     #print mainbeam.q
00734     split1.set_direction(spitfire_exit, blueline)
00735     blueline.set_entrance_direction(split1)
00736     blueline.set_exit_direction(comp)
00737     comp.rotate_to_axis(blueline)
00738     q=optics[QUAD]=quadrupler(center=(40*inch, 2.5*inch, 34.5*inch), from_optic=comp[blue_compressor.TM1])
00739     comp.set_exit_direction(q)
00740     q.set_entrance_direction(comp)
00741     blue_sys=composite_optic("blue_sys", optics, [START, SPLIT, BLUELINE, COMP, QUAD], (0,0,0), (0,0,0), 0)
00742     irline.set_entrance_direction(spitfire_exit)
00743     
00744     #align compressor table to output of main IR line
00745     ir_sys=composite_optic("ir_sys", optics, [START, IR], (0,0,0), (0,0,0), 0).clone()
00746     pointer=trace_path(ir_sys, mainbeam.clone())[-1]
00747     pointer.free_drift(1.0)
00748     optics[IR_COMP]=ircomp=ir_compressor(center=pointer.x0, angle=math.atan(0.2)/deg)
00749     ircomp.set_entrance_direction(irline)
00750 
00751     #now, align IZ
00752     ir_sys=composite_optic("ir_sys", optics, [START, IR, IR_COMP], (0,0,0), (0,0,0), 0).clone()
00753     pointer=trace_path(ir_sys, mainbeam.clone())[-1]
00754     pointer.free_drift(1.0)
00755     bemir=optics[BE_TURN]=reflector("be turn mirror", center=pointer.x0, angle=45.0)
00756     bemir.transport_to_here(pointer).transform(pointer)
00757     pointer.free_drift(0.1)
00758     dz=pointer.q.next_waist()
00759     pointer.free_drift(dz)
00760     optics[IZ_SCREEN]=null_optic("IZ", pointer.x0)
00761     ir_sys=composite_optic("ir_sys", optics, [START, IR, IR_COMP, BE_TURN, IZ_SCREEN], (0,0,0), (0,0,0), 0)
00762     
00763     whole_table=composite_optic("whole table", optics, [START, SPLIT, BLUELINE, COMP, QUAD, IR, IR_COMP, BE_TURN, IZ_SCREEN], (0,0,0), (0,0,0), 0)
00764     
00765     
00766     ir_trace=trace_path(ir_sys, mainbeam.clone())
00767     ir_trace.color=graphite.red
00768     blue_trace=trace_path(blue_sys, mainbeam.clone())
00769     blue_trace.color=graphite.blue
00770     
00771     if table_layout:
00772         g=draw_everything({"sys":whole_table}, ir_trace, (-.25,5), (0,2.5), three_d=0)
00773         draw_trace(g, blue_trace)
00774         
00775         #g=draw_everything({"sys":sys}, trace, (0.5,1.1), (0.8,1.1), three_d=0)
00776         #g=draw_everything({"sys":sys}, trace, (0.7,1.3), (0.9,1.2), three_d=0)
00777         if show_qd:
00778             graphite.genOutput(g,'QD',canvasname="Compressor layout", size=(900,500))
00779         if show_pdf:
00780             graphite.genOutput(g,'PDF',canvasname="Tablelayout", size=(900,500))
00781     #print trace[0]
00782     plotq(blue_trace)
00783     
00784     if 0:
00785         glabel=ircomp.mark_label(ircomp.INPUT)
00786         m=ir_trace[(glabel,0)]
00787         print "\n\n**start**\n\n"
00788         print m.incoming_direction, m.direction()
00789         print m.incoming_q
00790         print m.incoming_q.qi_moments()[1:3]
00791         print m.incoming_q.q_moments()[1:3]
00792         print m.incoming_q.qit, "\n"
00793         print m.localize_transform_tensor
00794         print m.footprint_q
00795         print m.footprint_q.qi_moments()[1:3]
00796         print m.footprint_q.q_moments()[1:3]
00797         print m.footprint_q.qit, "\n"
00798         print m.globalize_transform_tensor
00799         print m.q
00800         print m.q.qi_moments()[1:3]
00801         print m.q.q_moments()[1:3]
00802         print m.q.qit, "\n"
00803 
00804     glabel=ircomp.mark_label(ircomp.INPUT)
00805     #endpoint=ir_trace[(glabel,0)]  #get first hit on optic <glabel>
00806     endpoint=ir_trace[-1]
00807     q=endpoint.q
00808     
00809     t, qx0, qy0=q.qi_moments()
00810     theta=math.atan2(t[0,1].real, t[0,0].real)/deg
00811     qxx, qyy = endpoint.transform_q_to_table(q)
00812     dzx, dzy = (1e6/qxx).real, (1e6/qyy).real
00813     print ("qxx = %.1f, dzx = %.0f, qyy=%.1f, dzy=%.0f, (in um), theta=%.1f deg" % 
00814             (q.rw(qxx)[1]*1e6, dzx, q.rw(qyy)[1]*1e6, dzy, theta ) )
00815 
00816 show_pdf=0
00817 show_qd=1
00818 table_layout=1
00819 
00820 show_table()
00821     
00822 #doit_bc(38.5, 1.28, 1.054e-6, 1)

Generated on Wed Nov 21 10:18:31 2007 for analysis by  doxygen 1.5.4