oasys-elettra-kit / OASYS1-Wiser

The implementation of WISER into OASYS
MIT License
0 stars 1 forks source link

Numerical Source / CrossLink with SRW (PART 2) #53

Closed capitanevs closed 3 years ago

capitanevs commented 3 years ago

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:

immagine

It would be easier to me (perhaps not to the user) something like that immagine

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).

capitanevs commented 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.Sourcewith 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.

capitanevs commented 3 years ago

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:

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

capitanevs commented 3 years ago

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.

aljosahafner commented 3 years ago

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.

capitanevs commented 3 years ago

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)

capitanevs commented 3 years ago
# -*- 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
capitanevs commented 3 years ago

immagine

aljosahafner commented 3 years ago

This is the code in the widget, seems ok...

image

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.

capitanevs commented 3 years ago

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 immagine

immagine

immagine

2) I plot the (x,y) of SourceWavefront and Detector. They should coincide. They do not:

immagine immagine

The size seems to be correct, but the effective size is not. How can it be? immagine immagine

capitanevs commented 3 years ago

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

immagine

aljosahafner commented 3 years ago

This is the code: image

capitanevs commented 3 years ago

Solved.

we still have to think about the ReadWavefrontFromFile, but this is for the future