Skip to content
Snippets Groups Projects
Commit be704a31 authored by mwyman's avatar mwyman
Browse files

Continuing refactor of transfocator code; added screens (still need work)

parent b82fb421
No related branches found
No related tags found
No related merge requests found
......@@ -6,20 +6,40 @@ record(ao, "$(P)CRL$(N):energy"){
field(OUT, "@$(OBJ).updateE('VAL')")
}
record(ai, "$(P)CRL$(N):energy_RBV"){
field(DTYP, "pydev")
field(INP, "@pydev.iointr('updated_E')")
field(SCAN, "I/O Intr")
field(PREC, "5")
}
record(ao, "$(P)CRL$(N):focalSize"){
field(EGU, "m")
field(DTYP, "pydev")
field(OUT, "@$(OBJ).updateFsize('VAL')")
}
record(bo, "$(P)CRL$(N):fSize_twk_up"){
field(DTYP, "pydev")
field(OUT, "@$(OBJ).tweakUp()")
#record(bo, "$(P)CRL$(N):fSize_twk_up"){
# field(DTYP, "pydev")
# field(OUT, "@$(OBJ).tweakUp()")
#}
#
#record(bo, "$(P)CRL$(N):fSize_twk_dn"){
# field(DTYP, "pydev")
# field(OUT, "@$(OBJ).tweakDn()")
#}
record(calcout, "$(P)CRL$(N):fSize_twk_up"){
field(INPA, "$(P)CRL$(N):sortedIndex_RBV")
field(CALC, "MIN(A+1,2**$(NUM)-1)")
field(OUT, "$(P)Filter$(N):sortedIndex PP")
}
record(bo, "$(P)CRL$(N):fSize_twk_dn"){
field(DTYP, "pydev")
field(OUT, "@$(OBJ).tweakDn()")
record(calcout, "$(P)CRL$(N):fSize_twk_dn"){
field(INPA, "$(P)CRL$(N):sortedIndex_RBV")
field(CALC, "MAX(0,A-1)")
field(OUT, "$(P)Filter$(N):sortedIndex PP")
}
record(ao, "$(P)CRL$(N):slitSize_H"){
......@@ -28,6 +48,14 @@ record(ao, "$(P)CRL$(N):slitSize_H"){
field(OMSL, "closed_loop")
field(DTYP, "pydev")
field(OUT, "@$(OBJ).updateSlitSize('VAL', 'hor')")
field(FLNK, "$(P)CRL$(N):recalc_table.PROC CA")
}
record(ai, "$(P)CRL$(N):slitSize_H_RBV"){
field(DTYP, "pydev")
field(INP, "@pydev.iointr('updated_slitSize_H')")
field(SCAN, "I/O Intr")
field(PREC, "5")
}
record(ao, "$(P)CRL$(N):slitSize_V"){
......@@ -36,6 +64,32 @@ record(ao, "$(P)CRL$(N):slitSize_V"){
field(OMSL, "closed_loop")
field(DTYP, "pydev")
field(OUT, "@$(OBJ).updateSlitSize('VAL', 'vert')")
field(FLNK, "$(P)CRL$(N):recalc_table.PROC CA")
}
record(ai, "$(P)CRL$(N):slitSize_V_RBV"){
field(DTYP, "pydev")
field(INP, "@pydev.iointr('updated_slitSize_V')")
field(SCAN, "I/O Intr")
field(PREC, "5")
}
# Not sure this would work -- how to get a PV to simply trigger code?
record(bo, "$(P)CRL$(N):recalc_table"){
field(DTYP, "pydev")
field(OUT, "@$(OBJ).construct_lookup_table()")
field(FLNK, "$(P)CRL$(N):refind_config.PROC CA")
}
# Not sure this would work -- how to get a PV to simply trigger code?
record(bo, "$(P)CRL$(N):refind_config"){
field(DTYP, "pydev")
field(OUT, "@$(OBJ).find_config()")
}
record(bo, "$(P)CRL$(N):thickerr_flag"){
field(DTYP, "pydev")
field(OUT, "@$(OBJ).updateThickerrFlag()")
}
record(longin, "$(P)CRL$(N):lenses") {
......@@ -89,8 +143,20 @@ record(ai, "$(P)CRL$(N):fSize_actual"){
field(PREC, "5")
}
record(longout, "$(P)CRL$(N):sortedIndex") {
field(DTYP, "pydev")
field(OUT, "@$(OBJ).updateIndex('VAL')")
}
record(longin, "$(P)CRL$(N):sortedIndex_RBV") {
field(DTYP, "pydev")
field(INP, "@pydev.iointr('new_index')")
field(SCAN, "I/O Intr")
}
record(bo, "$(P)CRL$(N):verbosity"){
field(DTYP, "pydev")
field(OUT, "@$(OBJ).updateVerbosity('VAL')")
field(ZNAM, "Off")
field(ONAM, "On")
}
08/08/2024 - 05:57:01 - ravioli
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import xraylib
__all__ = """
lookup_diameter
materials_to_deltas
materials_to_linear_attenuation
calc_lookup_table
lookup_diameter
materials_to_deltas
materials_to_linear_attenuation
calc_lookup_table
""".split()
# Lookup table where each entry is a tuple (column1, column2)
......@@ -137,66 +137,90 @@ def materials_to_linear_attenuation(material_list, energy):
return mu_list
def calc_lookup_table(num_configs, radii, materials, energy_keV, numlens, lens_loc):
lookupTable = np.empty(num_configs)
L1_D = np.zeros(len(radii)) # CRL1 diameters for each stack
for i in range(len(radii)):
L1_D[i] = lookup_diameter(radii[i])
L1_delta = materials_to_deltas(materials, energy_keV) # delta values for CRL1 stacks
L1_mu = materials_to_linear_attenuation(material, energy_keV) # mu values for CRL1 stacks
L1_Feq = radii/(2*numlens*L1_delta) + lens_loc # CRL1 equivalent f in m for each stack
#------------------> Needs refactoring <--------------------------------
L1_index_n = 2**L1_Feq.size # Total number of combinations for CRL1
L1_invF_list= np.zeros(L1_index_n) # List of equivalent 1/f in m^-1 for CRL1
for i in range(L1_index_n):
L1_invF_list[i] = np.sum(index_to_binary_list(i, L1_Feq.size)/L1_Feq)
# Sort the L1_invF list (to avoid zigzagging)
L1_invF_list_sort_indices = np.argsort(L1_invF_list)
L1_invF_list_sorted = L1_invF_list[L1_invF_list_sort_indices]
q1_list = 1/(L1_invF_list_sorted - 1/d_StoL1) # focal position of CRL1 for all configurations (sorted)
dq1_list = q1_list - (d_Stof - d_StoL1)
# Start generating focal size list as a function of CRL1 setting
sigma1H = (sigmaH**2 + (sigmaHp*d_StoL1)**2)**0.5 # sigma beam size before CRL1
sigma1V = (sigmaV**2 + (sigmaVp*d_StoL1)**2)**0.5 # sigma beam size before CRL1
L1_n1mud_list = np.zeros(L1_index_n) # List of n1*mu*d_min for all possible CRL1 configurations
L1_n1muR_list = np.zeros(L1_index_n) # List of n1*mu/R for all possible CRL1 configurations
aperL1H_list = np.zeros(L1_index_n) # absorption H aperture of CRL1 for all configurations
aperL1V_list = np.zeros(L1_index_n) # absorption V aperture of CRL1 for all configurations
diameter1_list = np.zeros(L1_index_n) # CRL1 diameter for all possible configurations
FWHM1H_list = np.zeros(L1_index_n) # H focal size at the focus of CRL1
FWHM1V_list = np.zeros(L1_index_n) # V focal size at the focus of CRL1
Strehl_list = np.zeros(L1_index_n) # Strehl ratio based on lens thickness error
for i in range(L1_index_n):
# absorption aperture is a function of CRL absorption/physical aperture, incident beam size, and physical slits
L1_n1mud_list[i] = np.sum(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)*np.array(L1_mu*L1_n*d_min))
L1_n1muR_list[i] = np.sum(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)*np.array(L1_mu*L1_n/L1_R))
solution = root_scalar(absorptionaperture, args=(L1_n1mud_list[i], sigma1H, L1_n1muR_list[i]), bracket=[0.0, 2*sigma1H], method='bisect')
aperL1H_list[i] = solution.root*2.0
solution = root_scalar(absorptionaperture, args=(L1_n1mud_list[i], sigma1V, L1_n1muR_list[i]), bracket=[0.0, 2*sigma1V], method='bisect')
aperL1V_list[i] = solution.root*2.0
mask = (np.array(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)) == 1)
if np.all(mask == False):
diameter1_list[i] = np.inf
else:
diameter1_list[i] = np.min(L1_D[mask])
aperL1H_list[i] = min(aperL1H_list[i], diameter1_list[i], slit1_H)
aperL1V_list[i] = min(aperL1V_list[i], diameter1_list[i], slit1_V)
phase_error_tmp = np.linalg.norm(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)*np.array(L1_HE*L1_delta)*2*np.pi/wl)
Strehl_list[i] = np.exp(-phase_error_tmp**2)
# FWHMbeam size at CRL1 focus
FWHM1H_list = ((0.88*wl*q1_list/aperL1H_list)**2 + (2.355*sigmaH*q1_list/d_StoL1)**2)**0.5
FWHM1V_list = ((0.88*wl*q1_list/aperL1V_list)**2 + (2.355*sigmaV*q1_list/d_StoL1)**2)**0.5
if flag_HE:
FWHM1H_list *= (Strehl_list)**(-0.5)
FWHM1V_list *= (Strehl_list)**(-0.5)
FWHM_list = (FWHM1H_list*FWHM1V_list)**0.5
#------------------> End refactoring <--------------------------------
return FWHM_list
def absorptionaperture(x, n1mud, sigma, n1mur):
'''
Description:
TODO
Parameters:
TODO
Returns:
TODO
'''
numerator = np.exp(-(x**2/(2*sigma**2))) * np.exp(-n1mur*(x**2) - n1mud)
denominator = np.exp(-n1mud)
return numerator / denominator - 0.5
def calc_lookup_table(num_configs, radii, materials, energy_keV, numlens, lens_loc, beam, bl, crl
slit1_H, slit1_V, thickerr, flag_HE = False):
lookupTable = np.empty(num_configs)
sigmaH = beam['sigmaH']
sigmaV = beam['sigmaV']
sigmaHp = beam['sigmaHp']
sigmaVp = beam['sigmaVp']
d_StoL1 = bl['d_StoL']
d_StoF = bl['d_Stof']
d_min = crl['d_min']
L1_D = np.zeros(len(radii)) # CRL1 diameters for each stack
for i in range(len(radii)):
L1_D[i] = lookup_diameter(radii[i])
L1_delta = materials_to_deltas(materials, energy_keV) # delta values for CRL1 stacks
L1_mu = materials_to_linear_attenuation(materials, energy_keV) # mu values for CRL1 stacks
L1_Feq = radii/(2*numlens*L1_delta) + lens_loc # CRL1 equivalent f in m for each stack
L1_index_n = 2**L1_Feq.size # Total number of combinations for CRL1
L1_invF_list= np.zeros(L1_index_n) # List of equivalent 1/f in m^-1 for CRL1
for i in range(L1_index_n):
L1_invF_list[i] = np.sum(index_to_binary_list(i, L1_Feq.size)/L1_Feq)
# Sort the L1_invF list (to avoid zigzagging)
L1_invF_list_sort_indices = np.argsort(L1_invF_list)
L1_invF_list_sorted = L1_invF_list[L1_invF_list_sort_indices]
q1_list = 1/(L1_invF_list_sorted - 1/d_StoL1) # focal position of CRL1 for all configurations (sorted)
dq1_list = q1_list - (d_Stof - d_StoL1)
# Start generating focal size list as a function of CRL1 setting
sigma1H = (sigmaH**2 + (sigmaHp*d_StoL1)**2)**0.5 # sigma beam size before CRL1
sigma1V = (sigmaV**2 + (sigmaVp*d_StoL1)**2)**0.5 # sigma beam size before CRL1
L1_n1mud_list = np.zeros(L1_index_n) # List of n1*mu*d_min for all possible CRL1 configurations
L1_n1muR_list = np.zeros(L1_index_n) # List of n1*mu/R for all possible CRL1 configurations
aperL1H_list = np.zeros(L1_index_n) # absorption H aperture of CRL1 for all configurations
aperL1V_list = np.zeros(L1_index_n) # absorption V aperture of CRL1 for all configurations
diameter1_list = np.zeros(L1_index_n) # CRL1 diameter for all possible configurations
FWHM1H_list = np.zeros(L1_index_n) # H focal size at the focus of CRL1
FWHM1V_list = np.zeros(L1_index_n) # V focal size at the focus of CRL1
Strehl_list = np.zeros(L1_index_n) # Strehl ratio based on lens thickness error
for i in range(L1_index_n):
# absorption aperture is a function of CRL absorption/physical aperture, incident beam size, and physical slits
L1_n1mud_list[i] = np.sum(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)*np.array(L1_mu*numlens*d_min))
L1_n1muR_list[i] = np.sum(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)*np.array(L1_mu*numlens/radii))
solution = root_scalar(absorptionaperture, args=(L1_n1mud_list[i], sigma1H, L1_n1muR_list[i]), bracket=[0.0, 2*sigma1H], method='bisect')
aperL1H_list[i] = solution.root*2.0
solution = root_scalar(absorptionaperture, args=(L1_n1mud_list[i], sigma1V, L1_n1muR_list[i]), bracket=[0.0, 2*sigma1V], method='bisect')
aperL1V_list[i] = solution.root*2.0
mask = (np.array(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)) == 1)
if np.all(mask == False):
diameter1_list[i] = np.inf
else:
diameter1_list[i] = np.min(L1_D[mask])
aperL1H_list[i] = min(aperL1H_list[i], diameter1_list[i], slit1_H)
aperL1V_list[i] = min(aperL1V_list[i], diameter1_list[i], slit1_V)
phase_error_tmp = np.linalg.norm(index_to_binary_list(L1_invF_list_sort_indices[i], L1_Feq.size)*np.array(thickerr*L1_delta)*2*np.pi/wl)
Strehl_list[i] = np.exp(-phase_error_tmp**2)
# FWHMbeam size at CRL1 focus
FWHM1H_list = ((0.88*wl*q1_list/aperL1H_list)**2 + (2.355*sigmaH*q1_list/d_StoL1)**2)**0.5
FWHM1V_list = ((0.88*wl*q1_list/aperL1V_list)**2 + (2.355*sigmaV*q1_list/d_StoL1)**2)**0.5
if flag_HE:
FWHM1H_list *= (Strehl_list)**(-0.5)
FWHM1V_list *= (Strehl_list)**(-0.5)
FWHM_list = (FWHM1H_list*FWHM1V_list)**0.5
return FWHM_list
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment