Closed capitanevs closed 3 years ago
CONCLUSION
I have two options: 1) Attach an "offset" parameter to the numerical source 2) Follow the pattern of "VirtualSource" + "WavefrontSource", where I use the "VirtualSource" to set the reference and the "WavefrontSource" to provide photons
Comments on 1) The distance b.w. optical element MUST not change The distance from the source should be added "offset"
This introduces a weird behavior: GetDistanceFromParent and GetDistanceFromSource could return different values.
Changing this can be very painful, but more compact in the end.
Comments on 2) The concept of "source" within the beamline is ill-posed. The geometry would be set by the VirtualSource (distances etc), but the wavelength and direction of propagation would be set in "WavefrontSource".
The problem could be circumvented, in principle, by replacing the attribute Beamline.Source
with the two more specific Beamline.SourceReference
and Beamline.SourceWavefront
, which coincide in normal cases.
Changing this should be easier, but ultimatelly requires the usage of 4 widgets instead of 2.
I am still wondering what the best solution is.
HOW TO
The following lines show how to use SourceVirtual
and SourceWavefront
#---Virtual source (H,V)
#------------------------------------------------------------
s0 = OpticalElement(
Name = 'virtual source',
IsSource = True,
CoreOpticsElement = Optics.SourceVirtual(),
PositioningDirectives = Foundation.PositioningDirectives(
ReferTo = 'absolute',
XYCentre = [0,0],
Angle = 0)
)
#---SOURCE (H,V)
#------------------------------------------------------------
DeltaSource = 0
Field = np.array(10000*[1])
s2 = OpticalElement(
Name = 'wavewource',
IsSource = False,
CoreOpticsElement = Optics.SourceWavefront(
Lambda = S['Lambda'],
L = S['DummySourceL'],
Field = Field,
Orientation = Optics.OPTICS_ORIENTATION.HORIZONTAL),
PositioningDirectives = Foundation.PositioningDirectives(
PlaceWhat = 'centre',
PlaceWhere = 'centre',
ReferTo = 'source',
Distance = 4 )
)
s2.ComputationData = s2.CoreOptics.GetInitComputationData() # This line handles the cross-link b.w. Optics and Foundation
Then as usual they are appended in the beamline:
Beamline = None Beamline = Foundation.BeamlineElements()
Beamline.Append(s0) Beamline.Append(s2) if S['UseSlits']: Beamline.Append(slit_h) Beamline.Append(fm_h) Beamline.Append(det_h)
Beamline.RefreshPositions() Beamline.Name = BeamlineName
Which widget should we do?
The alternatives are the one proposed at the beginning.
WISER needs two OpticalElements (SourceVirtual and SourceWavefront) + a line to store data from wofrywavefront to ComputationData.
We can make 3 widgets "Source Origin" + "Wiser Wavefront" + "Wofry2Wiser wavefront" Pro: very clear, as workflow, and mantaineable. Con: longest
Or 2 widgets "Source Origin" + "Wofry 2 wiser wavefront"
Or just 1 "Wofry2wiser wavefront" pro: the most compact. Hides all the unnecessary stuff cons: it is not clear to generalize it for input from file.
Even after the upgrade and implementation of SourceVirtual + SourceWavefront, the following fields are None:
- Action
- NSamples
- X
- Y
How to populate them? It seems that GetInitComputationData
is not populating them.
A remark:
the virtual source has defaulted data in ComputationData (so None and 0 fields), because there is not actual need of using them. This is why it is called "Virtual".
The SourceWavefront in my code has correct data. Try check the following code (clumsy, byt working if you change the working path)
# -*- coding: utf-8 -*-
"""
Created on Wed Jun 9 13:53:34 2021
@author: Mike
This script simulate the main beamline contained in the ows file
Source-Slit-focussing mirror-Detector
"""
from LibWiser.EasyGo import *
WorkingFolder = MakePath('D:\Topics\WISEr\Examples 2020\OASYS Tests')
PathMetrology = WorkingFolder / 'Metrology'
PathLayout = WorkingFolder / 'Layout Files'
#%% DEFAULT SETTINGS: You can change parameter here or in a similar <Settings> dictionary
#%=============================================================================
BeamlineName = 'DIDEROT'
SettingsDefault = {
'Lambda' : 20e-9,
'Waist0' : 127e-6,
'SourceAngle' : 0,
'DummySourceL' : 40e-3,
'UseSlits' : False,
'SlitAperture' : 0.005,
'SlitDistance' : 95,
'f1h' : 100,
'f2h' : 1.5,
'GrazingAngleDeg' : 2.5,
'UseFigureErrorOnFocusing' : False,
'FigureErrorKbh' : "ldm-kbh/Scan_Motor5_56_res.dat",
'DetectorSize' : 200e-6,
'DetectorDefocus' : 0,
'OrientationToPropagate' : [Enums.OPTICS_ORIENTATION.HORIZONTAL],
'NSamples' : 5000,
'UseCustomSampling' : True
}
#=============================================================================
S = SettingsDefault
# Creating aliases and selecting FERMI initial source offset
#%=============================================================================
#---SOURCE (H,V)
#------------------------------------------------------------
DeltaSource = 0
s = OpticalElement(
Name = 's',
IsSource = True,
CoreOpticsElement = Optics.SourceGaussian(
Lambda = S['Lambda'],
Waist0 = S['Waist0'],
Orientation = Optics.OPTICS_ORIENTATION.ISOTROPIC),
PositioningDirectives = Foundation.PositioningDirectives(
ReferTo = 'absolute',
XYCentre = [0,0],
Angle = 0)
)
s.CoreOptics.SmallDisplacements.Rotation = S['SourceAngle']
#---Virtual source (H,V)
#------------------------------------------------------------
s0 = OpticalElement(
Name = 'virtual source',
IsSource = True,
CoreOpticsElement = Optics.SourceVirtual(),
PositioningDirectives = Foundation.PositioningDirectives(
ReferTo = 'absolute',
XYCentre = [0,0],
Angle = 0)
)
#---SOURCE (H,V)
#------------------------------------------------------------
DeltaSource = 0
Field = np.array(10000*[1])
s2 = OpticalElement(
Name = 'wavewource',
IsSource = False,
CoreOpticsElement = Optics.SourceWavefront(
Lambda = S['Lambda'],
L = S['DummySourceL'],
Field = Field,
Orientation = Optics.OPTICS_ORIENTATION.HORIZONTAL),
PositioningDirectives = Foundation.PositioningDirectives(
PlaceWhat = 'centre',
PlaceWhere = 'centre',
ReferTo = 'source',
Distance = 4 )
)
s2.ComputationData = s2.CoreOptics.GetInitComputationData() # This line handles the cross-link b.w. Optics and Foundation
slit_h = OpticalElement(
Name = 'slit',
CoreOpticsElement = Optics.Slits(
L = S['SlitAperture'],
Orientation = HORIZONTAL),
PositioningDirectives = Foundation.PositioningDirectives(
PlaceWhat = 'centre',
PlaceWhere = 'centre',
ReferTo = 'source',
Distance = S['SlitDistance'] ) )
#---fm_v
#------------------------------------------------------------
fm_h= OpticalElement(
Name = 'fm_h',
CoreOpticsElement = Optics.MirrorElliptic(
L = 0.4,
f1 = S['f1h'],
f2 = S['f2h'],
Alpha = np.deg2rad(S['GrazingAngleDeg']),
Orientation = Optics.OPTICS_ORIENTATION.HORIZONTAL),
PositioningDirectives = Foundation.PositioningDirectives(
PlaceWhat = 'upstream focus',
PlaceWhere = 'centre',
ReferTo = 'source'))
_ = fm_h
FileFigureErrorKbv = PathMetrology / S['FigureErrorKbh']
_.CoreOptics.FigureErrorLoadFromFile(PathFile = FileFigureErrorKbv,
FileType = Enums.FIGURE_ERROR_FILE_FORMAT.ELETTRA_LTP_JAVA1,
YSign = +1)
#---Detector_h
#------------------------------------------------------------
det_h = OpticalElement(
Name = 'det_h',
CoreOpticsElement = Optics.Detector(
L = S['DetectorSize'],
AngleGrazing = np.deg2rad(90),
Orientation = Optics.OPTICS_ORIENTATION.HORIZONTAL),
PositioningDirectives = Foundation.PositioningDirectives(
PlaceWhat = 'centre',
PlaceWhere = 'downstream focus',
ReferTo = 'upstream',
Distance = 0 + S['DetectorDefocus'])
)
# Create Beamlinee beamline starting from Beamlinee Beamline Elements Objects
#------------------------------------------------------------------------------------------------
Beamline = None
Beamline = Foundation.BeamlineElements()
Beamline.Append(s0)
Beamline.Append(s2)
if S['UseSlits']:
Beamline.Append(slit_h)
Beamline.Append(fm_h)
Beamline.Append(det_h)
Beamline.RefreshPositions()
Beamline.Name = BeamlineName
#%% LAYOUT MACROS, modifing the behavior of the beamline
#===============================================================================================
# Set the Direction to propagate
#-----------------------------------------------------------------------------------------------
Beamline.ComputationSettings.OrientationToCompute = S['OrientationToPropagate']
print(Beamline) #
# Set Use Figure error?
#-----------------------------------------------------------------------------------------------
for Item in [fm_h]:
Item.CoreOptics.ComputationSettings.UseFigureError = S['UseFigureErrorOnFocusing']
#--- Set the Sampling
for Item in Beamline.ItemList:
Item.ComputationSettings.UseCustomSampling = S['UseCustomSampling']
Item.ComputationSettings.NSamples = S['NSamples']
#%% TEST
Beamline.ComputeFields()
Beamline.PlotIntensity()
#%%
if 1==0:
Beamline.Print()
print(s2._VirtualOffset)
print(s2.CoreOptics.XYCentre)
print(s2.GetDistanceFromSource())
print(s2.DistanceFromParent)
print(s2.GetDistanceFromParent())
print(slit_h.CoreOptics.XYCentre)
print(fm_h.CoreOptics.XYCentre)
if 1==0:
slit_h.GetDistanceFromParent()
slit_h.DistanceFromParent
slit_h.DistanceFromSource
fm_h.GetDistanceFromParent()
fm_h.GetDistanceFromParent(SameOrientation = True,OnlyReference = True)
fm_h.DistanceFromParent
fm_h.DistanceFromSource
This is the code in the widget, seems ok...
I am a bit lost, maybe I would have to do a propagation in between or something... Give me some time to think about it.
UPDATES of 19.02.2021
What we did
Problem (apparently)
I Created this to inspect what Wofy2Wiser is doing.
1) The Intensities on the numerical source is as expected => GOOD
2) I plot the (x,y) of SourceWavefront and Detector. They should coincide. They do not:
The size seems to be correct, but the effective size is not. How can it be?
Using the code above (https://github.com/oasys-elettra-kit/OASYS1-Wiser/issues/53#issuecomment-874820294)
the detector has no problem
https://github.com/oasys-elettra-kit/OASYS1-Wiser/issues/53#issuecomment-874820294
This is the code:
Solved.
we still have to think about the ReadWavefrontFromFile, but this is for the future
Personal Note
Problem: Considering the structure of LibWiser, I found difficult to introduce the "NumericalSource" object, which was supposed to be used in either of the two ways:
It would be easier to me (perhaps not to the user) something like that
WHY? The word "source" can refers to two things: 1) the "nominal source of a facility", where distances are taken from (source=origin) 2) the optical element that delivers photons (i.e. the complex array of the Field) to all the others. This is just a wavefront assigned to a certain longitudinal position of the transport.
What SRW delivers is 2). What WISER uses for positioning is 1).