"""Functions involved in the propagation of a wavefront."""importnumpyasnpfrom.importsrwlib
[docs]defgroupOpticalSystem(opticalSystem,groupSeq):"""Inspect the elements of an optical system and group a given sequence of elements. Useful if the user is not interested in the intensity on some intermediate planes (for instance just after a lens). The computation of a sequence is more efficicent because it is performed at the SRW level and requires also less memory cause the wavefront is overridden. Args: opticalSystem: the optical system dictionary. groupSeq: list of element types to group. Returns: list: list of optical containers where elements are grouped according to the specified sequence. """seqLen=len(groupSeq)optElTypes=[optEl["type"]foroptElinopticalSystem.values()]optEls=[{key:opticalSystem[key]}forkeyinopticalSystem.keys()]iflen(optElTypes)<len(groupSeq):# nothing to groupoptCnts=[optEls]else:optCnts=[]i=0whilei<len(optEls):ifseqLen!=0andoptElTypes[i:i+seqLen]==groupSeq:# sequence detected, group elements in one containeroptCnts.append([optElforoptElinoptEls[i:i+seqLen]])i+=seqLenelse:# spare element, add to list of optical containersoptCnts.append([optEls[i]])i+=1returnoptCnts
[docs]defcropOpticalSystem(opticalSystem,startPropAt=None,stopPropAt=None):"""Crop an optical system to propagate a wavefront only within a sub-sequence of the initial system. Args: opticalSystem: the dictionary of the whole optical system. startPropAt (optional): the name of the optical element to start from. If None, the first element is picked as start. Defaults to None. stopPropAt (optional): the name of the optical element to end with. If None, the last element is picked as stop. Defaults to None. Returns: dict: the dictionary of the cropped optical system. """optElKeys=list(opticalSystem.keys())startPropAt=optElKeys[0]ifstartPropAtisNoneelsestartPropAtstopPropAt=optElKeys[-1]ifstopPropAtisNoneelsestopPropAtstartIdx=optElKeys.index(startPropAt)stopIdx=optElKeys.index(stopPropAt)+1opticalSystemCropped={key:opticalSystem[key]forkeyinoptElKeys[startIdx:stopIdx]}returnopticalSystemCropped
# =============================== PARSE TO SRW ================================
[docs]defparsePropPar(autoResizeBefore=False,autoResizeAfter=False,autoResizePrecision=1.0,quadPhaseSemiAnal=False,resizeInFourier=False,hRangeChange=1.0,hResChange=1.0,vRangeChange=1.0,vResChange=1.0):"""Get the list of parameters for the propagation through an optical element. Args: autoResizeBefore (optional): if True, auto-resize the wfr before the propagation through the element. Defaults to False. autoResizeBefore (optional): if True, auto-resize the wfr after the propagation through the element. Defaults to False. autoResizePrecision (optional): relative precision for propagation with auto-resizing. Defaults to 1.0. quadPhaseSemiAnal (optional): use semi-analytical treatment of the quadratic (leading) phase. Defaults to False. resizeInFourier (optional): resize in frequency domain using FTT. Defaults to False. hRangeChange (optional): resize horizontal extension. Defaults to 1.0. hResChange (optional): resize horizontal resolution. Defaults to 1.0. vRangeChange (optional): resize vertical extension. Defaults to 1.0. vResChange (optional): resize vertical resolution. Defaults to 1.0. Returns: list: [description] """SRWpropPar=[int(autoResizeBefore),int(autoResizeAfter),float(autoResizePrecision),int(quadPhaseSemiAnal),int(resizeInFourier),hRangeChange,hResChange,vRangeChange,vResChange]returnSRWpropPar
[docs]defparseToSRWelement(optEl):"""Get the SRW element and propagation parameter from the PySRW definition. Args: optEl: dictionary with the definition of a valid PySRW optical element. Returns: list: a list with the SRW element and the propagation parameters. """optElType=optEl["type"]ifoptElType=="drift":SRWoptEl,SRWpropPar=_parseDrift(optEl)elifoptElTypein["rectAp","rectOb","circAp","circOb"]:SRWoptEl,SRWpropPar=_parseApOrObs(optEl)elifoptElType=="lens":SRWoptEl,SRWpropPar=_parseLens(optEl)elifoptElType=="transmission":SRWoptEl,SRWpropPar=_parseTransmission(optEl)else:raiseException(f"optical element type '{optElType}' not recognized")returnSRWoptEl,SRWpropPar
def_parseDrift(optEl):# convert PySRW drift element to SRWLOptDSRWoptEl=srwlib.SRWLOptD(optEl["length"])if"propParam"inoptEl.keys():SRWpropPar=parsePropPar(**optEl["propParam"])else:SRWpropPar=parsePropPar()# leave default values, mesh not adaptedreturnSRWoptEl,SRWpropPardef_parseApOrObs(optEl):# convert PySRW aperture/obstacle element to SRWLOptAelType=optEl["type"].lower()shape="c"if"circ"inelTypeelse"r"apOrObs="a"if"ap"inelTypeelse"o"SRWoptEl=srwlib.SRWLOptA(shape,apOrObs,_Dx=optEl["extension"][0],_Dy=optEl["extension"][1],_x=optEl["centre"][0],_y=optEl["centre"][1])if"propParam"inoptEl.keys():SRWpropPar=parsePropPar(**optEl["propParam"])else:SRWpropPar=parsePropPar()returnSRWoptEl,SRWpropPardef_parseLens(optEl):# convert PySRW lens element to SRWLOptLifisinstance(optEl["f"],(list,tuple)):# cylindrical lensfocal=optEl["f"]else:# axial lensfocal=[optEl["f"],optEl["f"]]SRWoptEl=srwlib.SRWLOptL(_Fx=focal[0],_Fy=focal[1],_x=optEl["centre"][0],_y=optEl["centre"][1])if"propParam"inoptEl.keys():SRWpropPar=parsePropPar(**optEl["propParam"])else:SRWpropPar=parsePropPar()returnSRWoptEl,SRWpropPardef_parseTransmission(optEl):# convert PySRW transmission element to SRWLOptTopd=optEl["opd"]*1e-9ampl=optEl["amp"]extension=optEl["extension"]centre=optEl["centre"]nx,ny=np.shape(opd)Tr=np.zeros(2*nx*ny)Tr[::2]=np.reshape(ampl,(nx*ny))Tr[1::2]=np.reshape(opd,(nx*ny))arTr=srwlib.array("d",Tr)SRWoptEl=srwlib.SRWLOptT(_nx=nx,_ny=ny,_rx=extension[0],_ry=extension[1],_arTr=arTr,_x=centre[0],_y=centre[1])if"propParam"inoptEl.keys():SRWpropPar=parsePropPar(**optEl["propParam"])else:SRWpropPar=parsePropPar()returnSRWoptEl,SRWpropPar