#!/usr/bin/env python # *-----------------------------------------------------------------------* # | | # | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) | # | Based on Zac great first implementation | # | Author Thierry Zamofing (thierry.zamofing@psi.ch) | # *-----------------------------------------------------------------------* # -*- coding: utf-8 -*- """ Optical system design demo """ #sys.path.insert(0, "/home/myname/pythonfiles") #/usr/lib/python3/dist-packages/pyqtgraph/examples/optics/ from pyoptic import * import pyqtgraph as pg import numpy as np from pyqtgraph import Point class VLSSG(Optic): # variable line space sperical grating def __init__(self, **params): defaults = { 'r1': 0, 'r2': 0, 'd': 0.01, } defaults.update(params) d = defaults.pop('d') defaults['x1'] = -d/2. defaults['x2'] = d/2. gitem = CircularSolid(brush=(100,100,100,255), **defaults) Optic.__init__(self, gitem, **defaults) def propagateRay(self, ray): """Refract, reflect, absorb, and/or scatter ray. This function may create and return new rays""" surface = self.surfaces[0] p1, ai = surface.intersectRay(ray) if p1 is not None: p1 = surface.mapToItem(ray, p1) rd = ray['dir'] a1 = np.arctan2(rd[1], rd[0]) ar = a1 + np.pi - 2*ai print(ray['wl']) ar+=(ray['wl']-800)/5000 ray.setEnd(p1) dp = Point(np.cos(ar), np.sin(ar)) ray = Ray(parent=ray, dir=dp) else: ray.setEnd(None) return [ray] def demoRIXS2(): app = pg.QtGui.QApplication([]) w = pg.GraphicsLayoutWidget(show=True, border=0.5) w.resize(1000, 900) w.show() ### Curved mirror demo vb = w.addViewBox() vb.setAspectLocked() grid =pg.GridItem(pen=(0, 255, 0), textPen=(0, 255, 0)) # green grid and labels vb.addItem(grid) vb.setRange(pg.QtCore.QRectF(-50, -30, 100, 100)) optics = [] rays = [] #m1 = Mirror(r1=-100, pos=(5,0), d=5, angle=-15) m1 = VLSSG(r1=-3120, r2=0, pos=(-3.459543, 10.6), d=5, angle=-68.38532441633484) optics.append(m1) allRays = [] #for y in np.linspace(-1, 10, 21): # r = Ray(start=Point(-100, y)) # view.addItem(r) # allRays.append(r) for wl in np.linspace(355,1040, 25): for y in [10,15]: #d=Point(1,(y-12.5)/300) d=Point(1,(y-12.5)/300) #r = Ray(start=Point(-100, y+wl/500), wl=wl, dir=d) r = Ray(start=Point(-100, y), wl=wl) vb.addItem(r) allRays.append(r) for o in optics: vb.addItem(o) t1 = Tracer(allRays, optics) if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() def demoRIXS1(): app = pg.QtGui.QApplication([]) w = pg.GraphicsLayoutWidget(show=True, border=0.5) w.resize(1000, 900) w.show() ### Curved mirror demo vb = w.addViewBox() vb.setAspectLocked() grid =pg.GridItem(pen=(0, 255, 0), textPen=(0, 255, 0)) # green grid and labels vb.addItem(grid) vb.setRange(pg.QtCore.QRectF(-50, -30, 100, 100)) optics = [] rays = [] #m1 = Mirror(r1=-100, pos=(5,0), d=5, angle=-15) m1 = Mirror(r1=-100, r2=0, pos=(-3.459543, 10.6), d=5, angle=-68.38532441633484) optics.append(m1) l1 = Lens(pos=(41, 52.9),r1=20, r2=20, d=10, angle=15, glass='Corning7980') optics.append(l1) allRays = [] #for y in np.linspace(-1, 10, 21): # r = Ray(start=Point(-100, y)) # view.addItem(r) # allRays.append(r) for wl in np.linspace(355,1040, 25): for y in [10,15]: d=Point(1,(y-12.5)/300) r = Ray(start=Point(-100, y+wl/500), wl=wl, dir=d) #r = Ray(start=Point(-100, y), wl=wl) vb.addItem(r) allRays.append(r) for o in optics: vb.addItem(o) t1 = Tracer(allRays, optics) if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() def demoOrig(): app = pg.QtGui.QApplication([]) w = pg.GraphicsLayoutWidget(show=True, border=0.5) w.resize(1000, 900) w.show() ### Curved mirror demo view = w.addViewBox() view.setAspectLocked() #grid = pg.GridItem() #view.addItem(grid) view.setRange(pg.QtCore.QRectF(-50, -30, 100, 100)) optics = [] rays = [] m1 = Mirror(r1=-100, pos=(5,0), d=5, angle=-15) optics.append(m1) m2 = Mirror(r1=-70, pos=(-40, 30), d=6, angle=180-15) optics.append(m2) allRays = [] for y in np.linspace(-10, 10, 21): r = Ray(start=Point(-100, y)) view.addItem(r) allRays.append(r) for o in optics: view.addItem(o) t1 = Tracer(allRays, optics) ### Dispersion demo optics = [] view = w.addViewBox() view.setAspectLocked() #grid = pg.GridItem() #view.addItem(grid) view.setRange(pg.QtCore.QRectF(-10, -50, 90, 60)) optics = [] rays = [] l1 = Lens(r1=20, r2=20, d=10, angle=8, glass='Corning7980') optics.append(l1) allRays = [] for wl in np.linspace(355,1040, 25): for y in [10]: r = Ray(start=Point(-100, y), wl=wl) view.addItem(r) allRays.append(r) for o in optics: view.addItem(o) t2 = Tracer(allRays, optics) ### Scanning laser microscopy demo w.nextRow() view = w.addViewBox(colspan=2) optics = [] #view.setAspectLocked() view.setRange(QtCore.QRectF(200, -50, 500, 200)) ## Scan mirrors scanx = 250 scany = 20 m1 = Mirror(dia=4.2, d=0.001, pos=(scanx, 0), angle=315) m2 = Mirror(dia=8.4, d=0.001, pos=(scanx, scany), angle=135) ## Scan lenses l3 = Lens(r1=23.0, r2=0, d=5.8, pos=(scanx+50, scany), glass='Corning7980') ## 50mm UVFS (LA4148) l4 = Lens(r1=0, r2=69.0, d=3.2, pos=(scanx+250, scany), glass='Corning7980') ## 150mm UVFS (LA4874) ## Objective obj = Lens(r1=15, r2=15, d=10, dia=8, pos=(scanx+400, scany), glass='Corning7980') IROptics = [m1, m2, l3, l4, obj] ## Scan mirrors scanx = 250 scany = 30 m1a = Mirror(dia=4.2, d=0.001, pos=(scanx, 2*scany), angle=315) m2a = Mirror(dia=8.4, d=0.001, pos=(scanx, 3*scany), angle=135) ## Scan lenses l3a = Lens(r1=46, r2=0, d=3.8, pos=(scanx+50, 3*scany), glass='Corning7980') ## 100mm UVFS (LA4380) l4a = Lens(r1=0, r2=46, d=3.8, pos=(scanx+250, 3*scany), glass='Corning7980') ## 100mm UVFS (LA4380) ## Objective obja = Lens(r1=15, r2=15, d=10, dia=8, pos=(scanx+400, 3*scany), glass='Corning7980') IROptics2 = [m1a, m2a, l3a, l4a, obja] for o in set(IROptics+IROptics2): view.addItem(o) IRRays = [] IRRays2 = [] for dy in [-0.4, -0.15, 0, 0.15, 0.4]: IRRays.append(Ray(start=Point(-50, dy), dir=(1, 0), wl=780)) IRRays2.append(Ray(start=Point(-50, dy+2*scany), dir=(1, 0), wl=780)) for r in set(IRRays+IRRays2): view.addItem(r) IRTracer = Tracer(IRRays, IROptics) IRTracer2 = Tracer(IRRays2, IROptics2) global phase phase = 0.0 def update(): global phase if phase % (8*np.pi) > 4*np.pi: m1['angle'] = 315 + 1.5*np.sin(phase) m1a['angle'] = 315 + 1.5*np.sin(phase) else: m2['angle'] = 135 + 1.5*np.sin(phase) m2a['angle'] = 135 + 1.5*np.sin(phase) phase += 0.2 timer = QtCore.QTimer() timer.timeout.connect(update) timer.start(40) if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() ## Start Qt event loop unless running in interactive mode or using pyside. if __name__=='__main__': import sys import argparse #(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>20 else sys.argv[0])+' ' #exampleCmd=('', '-m0xf -v0') epilog=__doc__ #+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n' parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("--mode", "-m", type=lambda x: int(x,0), help="mode default=0x%(default)x", default=0) args = parser.parse_args() if args.mode==0: demoOrig() elif args.mode==1: demoRIXS1() elif args.mode==2: demoRIXS2() else: demoRIXS()