From 8b6e4dad4b077b5f2b8f0933e44753cae62b2c0c Mon Sep 17 00:00:00 2001 From: mwyman <mwyman@anl.gov> Date: Fri, 15 Nov 2024 16:13:13 -0600 Subject: [PATCH] CRL refactor continues --- 100idPyApp/Db/pyDevCRLdouble.db | 339 ------------ 100idPyApp/Db/pyDevCRLsingle.db | 325 ------------ 100idPyApp/python/pyTransfocator_general.py | 548 -------------------- 100idPyApp/python/pyTransfocator_single.py | 500 ------------------ 4 files changed, 1712 deletions(-) delete mode 100644 100idPyApp/Db/pyDevCRLdouble.db delete mode 100644 100idPyApp/Db/pyDevCRLsingle.db delete mode 100644 100idPyApp/python/pyTransfocator_general.py delete mode 100644 100idPyApp/python/pyTransfocator_single.py diff --git a/100idPyApp/Db/pyDevCRLdouble.db b/100idPyApp/Db/pyDevCRLdouble.db deleted file mode 100644 index 7f8405b..0000000 --- a/100idPyApp/Db/pyDevCRLdouble.db +++ /dev/null @@ -1,339 +0,0 @@ -# Select the source field for the energy -record(bo, "$(P)$(CRLID):EnergySelect") { - field(DESC, "energy selection") - field(DTYP, "Soft Channel") - field(ZNAM, "Mono") - field(ONAM, "Local") - field(VAL, "1") - field(FLNK, "$(P)$(CRLID):EnergyCalc") -} - -# The local energy -record(ao, "$(P)$(CRLID):EnergyLocal") { - field(DESC, "local energy") - field(VAL, "12.398") - field(PREC, "4") - field(EGU, "keV") - field(FLNK, "$(P)$(CRLID):EnergyCalc") -} - -# The beamline energy -record(ao, "$(P)$(CRLID):EnergyBeamline") { - field(DESC, "beamline energy") - field(DOL, "$(KEV) CP") - field(OMSL, "closed_loop") - field(PREC, "4") - field(EGU, "keV") - field(FLNK, "$(P)$(CRLID):EnergyCalc") -} - -# Calculate the energy to be used -record(calcout, "$(P)$(CRLID):EnergyCalc"){ - field(DESC, "Energy select calc") - field(SCAN, "Passive") - field(INPA, "$(P)$(CRLID):EnergySelect.RVAL") - field(INPB, "$(P)$(CRLID):EnergyBeamline") - field(INPC, "$(P)$(CRLID):EnergyLocal") - field(CALC, "(A==0)?B:C") - field(OUT, "$(P)$(CRLID):energy PP") - field(PREC, "4") - field(SCAN, "Passive") -} - -record(ao, "$(P)$(CRLID):energy"){ - field(EGU, "keV") - field(DOL, "$(KEV) CP") - field(OMSL, "closed_loop") - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateE(VAL)") - field(FLNK, "$(P)$(CRLID):recalc_table.PROC CA") -} - -record(ai, "$(P)$(CRLID):energy_RBV"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('updated_E')") - field(SCAN, "I/O Intr") - field(PREC, "5") -} - - -record(ao, "$(P)$(CRLID):focalSize"){ - field(EGU, "m") - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateFsize(VAL)") -} - -record(calcout, "$(P)$(CRLID):fSize_twk_up"){ - field(INPA, "$(P)$(CRLID):sortedIndex_RBV") - field(CALC, "MIN(A+1,$(ELEM)-1)") - field(OUT, "$(P)$(CRLID):sortedIndex PP") -} - -record(calcout, "$(P)$(CRLID):fSize_twk_dn"){ - field(INPA, "$(P)$(CRLID):sortedIndex_RBV") - field(CALC, "MAX(0,A-1)") - field(OUT, "$(P)$(CRLID):sortedIndex PP") -} - - - -record(bo, "$(P)$(CRLID):recalc_enable"){ - field(DESC, "Lookup table calc enable") - field(SCAN, "Passive") - field(ZNAM, "Disabled") - field(ONAM, "Enabled") -} - -# Not sure this would work -- how to get a PV to simply trigger code? -record(bo, "$(P)$(CRLID):recalc_table"){ - field(DTYP, "pydev") - field(OUT, "@$(OBJ).construct_lookup_table()") - field(FLNK, "$(P)$(CRLID):refind_config.PROC CA") - field(SDIS, "$(P)$(CRLID):recalc_enable") - field(DISV, "0") -} - -# Not sure this would work -- how to get a PV to simply trigger code? -record(bo, "$(P)$(CRLID):refind_config"){ - field(DTYP, "pydev") - field(OUT, "@$(OBJ).find_config()") -} - -record(bo, "$(P)$(CRLID):thickerr_flag"){ - field(DTYP, "pydev") - field(ZNAM, "Off") - field(ONAM, "On") - field(OUT, "@$(OBJ).setThickerrFlag(VAL)") - field(FLNK, "$(P)$(CRLID):recalc_table.PROC CA") -} - -record(bi, "$(P)$(CRLID):thickerr_flag_RBV"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('updated_thickerr_Flag')") - field(SCAN, "I/O Intr") -} - -#------------------------------------------------------------------------------- -# CRL 1 config/encode/decode - -record(longin, "$(P)$(CRLID):1:lenses") { - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_lenses_1')") - field(SCAN, "I/O Intr") - field(FLNK, "$(P)$(CRLID):1:lens_decode.PROC CA") -} - -record(transform, "$(P)$(CRLID):1:lens_decode"){ - field(INPA, "$(P)$(CRLID):1:lenses PP") - field(CLCB, "A % 2") - field(CLCC, "(A >> 1) % 2") - field(CLCD, "(A >> 2) % 2") - field(CLCE, "(A >> 3) % 2") - field(CLCF, "(A >> 4) % 2") - field(CLCG, "(A >> 5) % 2") - field(CLCH, "(A >> 6) % 2") - field(CLCI, "(A >> 7) % 2") - field(CLCJ, "(A >> 8) % 2") - field(CLCK, "(A >> 9) % 2") -# field(CLCL, "(A >> 10) % 2") -# field(CLCM, "(A >> 11) % 2") -} - -record(calcout, "$(P)$(CRLID):1:lens_encode"){ - field(OUT, "$(P)$(CRLID):1:lensConfig_BW PP") - field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -} - -record(calcout, "$(P)$(CRLID):1:lens_RBV_encode"){ - field(OUT, "$(P)$(CRLID):1:lensConfig_RBV PP") - field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -} - -record(longin, "$(P)$(CRLID):1:lensConfig_RBV") { -} - -record(longout, "$(P)$(CRLID):1:lensConfig_BW") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateConfig1(VAL)") -} - -#------------------------------------------------------------------------------- -# CRL 2 config/encode/decode - -record(longin, "$(P)$(CRLID):2:lenses") { - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_lenses_2')") - field(SCAN, "I/O Intr") - field(FLNK, "$(P)$(CRLID):2:lens_decode.PROC CA") -} - -record(transform, "$(P)$(CRLID):2:lens_decode"){ - field(INPA, "$(P)$(CRLID):2:lenses PP") - field(CLCB, "A % 2") - field(CLCC, "(A >> 1) % 2") - field(CLCD, "(A >> 2) % 2") - field(CLCE, "(A >> 3) % 2") - field(CLCF, "(A >> 4) % 2") - field(CLCG, "(A >> 5) % 2") - field(CLCH, "(A >> 6) % 2") - field(CLCI, "(A >> 7) % 2") - field(CLCJ, "(A >> 8) % 2") - field(CLCK, "(A >> 9) % 2") -# field(CLCL, "(A >> 10) % 2") -# field(CLCM, "(A >> 11) % 2") -} - -record(calcout, "$(P)$(CRLID):2:lens_encode"){ - field(OUT, "$(P)$(CRLID):2:lensConfig_BW PP") - field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -} - -record(calcout, "$(P)$(CRLID):2:lens_RBV_encode"){ - field(OUT, "$(P)$(CRLID):2:lensConfig_RBV PP") - field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -} - -record(longin, "$(P)$(CRLID):2:lensConfig_RBV") { -} - -record(longout, "$(P)$(CRLID):2:lensConfig_BW") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateConfig2(VAL)") -} - -#------------------------------------------------------------------------------- - -record(ai, "$(P)$(CRLID):fSize_actual"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_fSize')") - field(SCAN, "I/O Intr") - field(PREC, "5") -} - -record(longout, "$(P)$(CRLID):sortedIndex") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateIndex(VAL)") -} - -record(longin, "$(P)$(CRLID):sortedIndex_RBV") { - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_index')") - field(SCAN, "I/O Intr") -} - -record(longout, "$(P)$(CRLID):previewIndex") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).getPreviewFocalSize(VAL)") -} - -record(ai, "$(P)$(CRLID):fSize_preview"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_preview')") - field(SCAN, "I/O Intr") - field(PREC, "6") -} - -record(bo, "$(P)$(CRLID):verbosity"){ - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateVerbosity(VAL)") - field(ZNAM, "Off") - field(ONAM, "On") - -} - -record(waveform, "$(P)$(CRLID):fSizes"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_lookupTable')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "DOUBLE") - field(NELM, "$(ELEM)") -} - -record(waveform, "$(P)$(CRLID):invF_indices"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_invFind_list')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "DOUBLE") - field(NELM, "$(ELEM)") -} - -record(waveform, "$(P)$(CRLID):invF"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_invF_list')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "DOUBLE") - field(NELM, "$(ELEM)") -} - -record(waveform, "$(P)$(CRLID):configs"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_configs')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "LONG") - field(NELM, "$(ELEM)") - } - -# The commented out records below were meant to replicate the lock feature used -# in filter control. BL staff indicated not required but kept in case needed. -# Will also have to update python code (in/out masks, culled tables/indices need -# to be uncommented). -# MW 2024.09.04 - -#!record(calcout, "$(P)$(CRLID):outMask_encode"){ -#! field(OUT, "$(P)$(CRLID):outMask PP") -#! field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -#!} -#! -#!record(longout, "$(P)$(CRLID):outMask") { -#! field(DTYP, "pydev") -#! field(DESC, "Fixed-out lens mask") -#! field(OUT, "@$(OBJ).setOutMask(VAL)") -#!} -#! -#!record(calcout, "$(P)$(CRLID):inMask_encode"){ -#! field(OUT, "$(P)$(CRLID):inMask PP") -#! field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -#!} -#! -#!record(longout, "$(P)$(CRLID):inMask") { -#! field(DTYP, "pydev") -#! field(DESC, "Fixed-in lens mask") -#! field(OUT, "@$(OBJ).setInMask(VAL)") -#!} - - - - -#!record(longin, "$(P)$(CRLID):inMask_RBV") { -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_inMask')") -#! field(SCAN, "I/O Intr") -#!} -#! -#!record(longin, "$(P)$(CRLID):outMask_RBV") { -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_outMask')") -#! field(SCAN, "I/O Intr") -#!} - - -#! record(waveform, "$(P)$(CRLID):fSizes_culled"){ -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_culledTable')") -#! field(SCAN, "I/O Intr") -#! field(PREC, "6") -#! field(FTVL, "DOUBLE") -#! field(NELM, "$(ELEM)") -#! } -#! record(waveform, "$(P)$(CRLID):configs_culled"){ -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_culledConfigs')") -#! field(SCAN, "I/O Intr") -#! field(PREC, "6") -#! field(FTVL, "LONG") -#! field(NELM, "$(ELEM)") -#! } diff --git a/100idPyApp/Db/pyDevCRLsingle.db b/100idPyApp/Db/pyDevCRLsingle.db deleted file mode 100644 index b2e60b4..0000000 --- a/100idPyApp/Db/pyDevCRLsingle.db +++ /dev/null @@ -1,325 +0,0 @@ -# Select the source field for the energy -record(bo, "$(P)$(CRLID):EnergySelect") { - field(DESC, "energy selection") - field(DTYP, "Soft Channel") - field(ZNAM, "Mono") - field(ONAM, "Local") - field(VAL, "1") - field(FLNK, "$(P)$(CRLID):EnergyCalc") -} - -# The local energy -record(ao, "$(P)$(CRLID):EnergyLocal") { - field(DESC, "local energy") - field(VAL, "12.398") - field(PREC, "4") - field(EGU, "keV") - field(FLNK, "$(P)$(CRLID):EnergyCalc") -} - -# The beamline energy -record(ao, "$(P)$(CRLID):EnergyBeamline") { - field(DESC, "beamline energy") - field(DOL, "$(KEV) CP") - field(OMSL, "closed_loop") - field(PREC, "4") - field(EGU, "keV") - field(FLNK, "$(P)$(CRLID):EnergyCalc") -} - -# Calculate the energy to be used -record(calcout, "$(P)$(CRLID):EnergyCalc"){ - field(DESC, "Energy select calc") - field(SCAN, "Passive") - field(INPA, "$(P)$(CRLID):EnergySelect.RVAL") - field(INPB, "$(P)$(CRLID):EnergyBeamline") - field(INPC, "$(P)$(CRLID):EnergyLocal") - field(CALC, "(A==0)?B:C") - field(OUT, "$(P)$(CRLID):energy PP") - field(PREC, "4") - field(SCAN, "Passive") -} - -record(ao, "$(P)$(CRLID):energy"){ - field(EGU, "keV") - field(DOL, "$(KEV) CP") - field(OMSL, "closed_loop") - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateE(VAL)") - field(FLNK, "$(P)$(CRLID):recalc_table.PROC CA") -} - -record(ai, "$(P)$(CRLID):energy_RBV"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('updated_E')") - field(SCAN, "I/O Intr") - field(PREC, "5") -} - - -record(ao, "$(P)$(CRLID):focalSize"){ - field(EGU, "m") - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateFsize(VAL)") -} - -record(calcout, "$(P)$(CRLID):fSize_twk_up"){ - field(INPA, "$(P)$(CRLID):sortedIndex_RBV") - field(CALC, "MIN(A+1,$(ELEM)-1)") - field(OUT, "$(P)$(CRLID):sortedIndex PP") -} - -record(calcout, "$(P)$(CRLID):fSize_twk_dn"){ - field(INPA, "$(P)$(CRLID):sortedIndex_RBV") - field(CALC, "MAX(0,A-1)") - field(OUT, "$(P)$(CRLID):sortedIndex PP") -} - -record(ao, "$(P)$(CRLID):slitSize_H"){ - field(EGU, "m") - field(DOL, "$(SLITH) CP") - field(OMSL, "closed_loop") - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateSlitSize(VAL, 'hor')") - field(FLNK, "$(P)$(CRLID):recalc_table.PROC CA") - field(PREC, "6") -} - -record(ai, "$(P)$(CRLID):slitSize_H_RBV"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('updated_slitSize_H')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(EGU, "m") -} - -record(ao, "$(P)$(CRLID):slitSize_V"){ - field(EGU, "m") - field(DOL, "$(SLITV) CP") - field(OMSL, "closed_loop") - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateSlitSize(VAL, 'vert')") - field(FLNK, "$(P)$(CRLID):recalc_table.PROC CA") - field(PREC, "6") -} - -record(ai, "$(P)$(CRLID):slitSize_V_RBV"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('updated_slitSize_V')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(EGU, "m") -} - -record(bo, "$(P)$(CRLID):recalc_enable"){ - field(DESC, "Lookup table calc enable") - field(SCAN, "Passive") - field(ZNAM, "Disabled") - field(ONAM, "Enabled") -} - -# Not sure this would work -- how to get a PV to simply trigger code? -record(bo, "$(P)$(CRLID):recalc_table"){ - field(DTYP, "pydev") - field(OUT, "@$(OBJ).construct_lookup_table()") - field(FLNK, "$(P)$(CRLID):refind_config.PROC CA") - field(SDIS, "$(P)$(CRLID):recalc_enable") - field(DISV, "0") -} - -# Not sure this would work -- how to get a PV to simply trigger code? -record(bo, "$(P)$(CRLID):refind_config"){ - field(DTYP, "pydev") - field(OUT, "@$(OBJ).find_config()") -} - -record(bo, "$(P)$(CRLID):thickerr_flag"){ - field(DTYP, "pydev") - field(ZNAM, "Off") - field(ONAM, "On") - field(OUT, "@$(OBJ).setThickerrFlag(VAL)") - field(FLNK, "$(P)$(CRLID):recalc_table.PROC CA") -} - -record(bi, "$(P)$(CRLID):thickerr_flag_RBV"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('updated_thickerr_Flag')") - field(SCAN, "I/O Intr") -} - - -record(longin, "$(P)$(CRLID):lenses") { - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_lenses')") - field(SCAN, "I/O Intr") - field(FLNK, "$(P)$(CRLID):lens_decode.PROC CA") -} - -record(transform, "$(P)$(CRLID):lens_decode"){ - field(INPA, "$(P)$(CRLID):lenses PP") - field(CLCB, "A % 2") - field(CLCC, "(A >> 1) % 2") - field(CLCD, "(A >> 2) % 2") - field(CLCE, "(A >> 3) % 2") - field(CLCF, "(A >> 4) % 2") - field(CLCG, "(A >> 5) % 2") - field(CLCH, "(A >> 6) % 2") - field(CLCI, "(A >> 7) % 2") - field(CLCJ, "(A >> 8) % 2") - field(CLCK, "(A >> 9) % 2") -# field(CLCL, "(A >> 10) % 2") -# field(CLCM, "(A >> 11) % 2") -} - -record(calcout, "$(P)$(CRLID):lens_encode"){ - field(OUT, "$(P)$(CRLID):lensConfig_BW PP") - field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -} - -record(calcout, "$(P)$(CRLID):lens_RBV_encode"){ - field(OUT, "$(P)$(CRLID):lensConfig_RBV PP") - field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -} - -record(longin, "$(P)$(CRLID):lensConfig_RBV") { -} - -record(longout, "$(P)$(CRLID):lensConfig_BW") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateConfig(VAL)") -} - -record(ai, "$(P)$(CRLID):fSize_actual"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_fSize')") - field(SCAN, "I/O Intr") - field(PREC, "5") -} - -record(longout, "$(P)$(CRLID):sortedIndex") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateIndex(VAL)") -} - -record(longin, "$(P)$(CRLID):sortedIndex_RBV") { - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_index')") - field(SCAN, "I/O Intr") -} - -record(longout, "$(P)$(CRLID):previewIndex") { - field(DTYP, "pydev") - field(OUT, "@$(OBJ).getPreviewFocalSize(VAL)") -} - -record(ai, "$(P)$(CRLID):fSize_preview"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_preview')") - field(SCAN, "I/O Intr") - field(PREC, "6") -} - -record(bo, "$(P)$(CRLID):verbosity"){ - field(DTYP, "pydev") - field(OUT, "@$(OBJ).updateVerbosity(VAL)") - field(ZNAM, "Off") - field(ONAM, "On") - -} - -record(waveform, "$(P)$(CRLID):fSizes"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_lookupTable')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "DOUBLE") - field(NELM, "$(ELEM)") -} - -record(waveform, "$(P)$(CRLID):invF_indices"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_invFind_list')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "DOUBLE") - field(NELM, "$(ELEM)") -} - -record(waveform, "$(P)$(CRLID):invF"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_invF_list')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "DOUBLE") - field(NELM, "$(ELEM)") -} - -record(waveform, "$(P)$(CRLID):configs"){ - field(DTYP, "pydev") - field(INP, "@pydev.iointr('new_configs')") - field(SCAN, "I/O Intr") - field(PREC, "6") - field(FTVL, "LONG") - field(NELM, "$(ELEM)") - } - -# The commented out records below were meant to replicate the lock feature used -# in filter control. BL staff indicated not required but kept in case needed. -# Will also have to update python code (in/out masks, culled tables/indices need -# to be uncommented). -# MW 2024.09.04 - -#!record(calcout, "$(P)$(CRLID):outMask_encode"){ -#! field(OUT, "$(P)$(CRLID):outMask PP") -#! field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -#!} -#! -#!record(longout, "$(P)$(CRLID):outMask") { -#! field(DTYP, "pydev") -#! field(DESC, "Fixed-out lens mask") -#! field(OUT, "@$(OBJ).setOutMask(VAL)") -#!} -#! -#!record(calcout, "$(P)$(CRLID):inMask_encode"){ -#! field(OUT, "$(P)$(CRLID):inMask PP") -#! field(CALC, "A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+I*256+J*512") -#!} -#! -#!record(longout, "$(P)$(CRLID):inMask") { -#! field(DTYP, "pydev") -#! field(DESC, "Fixed-in lens mask") -#! field(OUT, "@$(OBJ).setInMask(VAL)") -#!} - - - - -#!record(longin, "$(P)$(CRLID):inMask_RBV") { -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_inMask')") -#! field(SCAN, "I/O Intr") -#!} -#! -#!record(longin, "$(P)$(CRLID):outMask_RBV") { -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_outMask')") -#! field(SCAN, "I/O Intr") -#!} - - -#! record(waveform, "$(P)$(CRLID):fSizes_culled"){ -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_culledTable')") -#! field(SCAN, "I/O Intr") -#! field(PREC, "6") -#! field(FTVL, "DOUBLE") -#! field(NELM, "$(ELEM)") -#! } -#! record(waveform, "$(P)$(CRLID):configs_culled"){ -#! field(DTYP, "pydev") -#! field(INP, "@pydev.iointr('new_culledConfigs')") -#! field(SCAN, "I/O Intr") -#! field(PREC, "6") -#! field(FTVL, "LONG") -#! field(NELM, "$(ELEM)") -#! } diff --git a/100idPyApp/python/pyTransfocator_general.py b/100idPyApp/python/pyTransfocator_general.py deleted file mode 100644 index a8c3fc5..0000000 --- a/100idPyApp/python/pyTransfocator_general.py +++ /dev/null @@ -1,548 +0,0 @@ -import numpy as np -import tomllib -import xraylib -from transfocator_calcs import lookup_diameter, materials_to_deltas, materials_to_linear_attenuation -from transfocator_calcs import find_levels, calc_lookup_table, get_densities - - -MAT_MACRO = 'MAT' -NLENS_MACRO = 'NUMLENS' -RADIUS_MACRO = 'RADIUS' -LOC_MACRO = 'LOC' -THICKERR_MACRO = 'THICKERR' - -''' -Config variables - -Beam Properties - energy : energy in keV - L_und : undulator length in m - sigmaH_e : Sigma electron source size in H direction in m - sigmaV_e : Sigma electron source size in V direction in m - sigmaHp : Sigma electron divergence in H direction in rad - sigmaVp_e : Sigma electron divergence in V direction in rad -Beamline properties - d_StoL1 : Source-to-CRL1 distance, in m - d_StoL2 : Source-to-CRL2 distance, in m - d_Stof : Source-to-focus distance, in m -CRL properties - d_min : Minimum thickness at the apex in m - stack_d : Stack thickness in m -''' -DEFAULT_CONFIG = {'beam':{'energy': 15, 'L_und': 4.7, 'sigmaH_e': 14.8e-6, - 'sigmaV_e': 3.7e-6, 'sigmaHp_e': 2.8e-6, 'sigmaVp_e': 1.5e-6}, - 'beamline': {'d_StoL1': 51.9, 'd_StoL2': 62.1, 'd_Stof': 66.2}, - 'crl':{'stack_d': 50.0e-3, 'd_min': 3.0e-5}} - - -class transfocator(): - - - def __init__(self, crl_setup = None, beam_config = DEFAULT_CONFIG['beam'], - beamline_config = DEFAULT_CONFIG['beamline'], - crl_config = DEFAULT_CONFIG['crl']): - - self.verbose = True - - if crl_setup is None: - beam = beam_config - beamline = beamline_config - crl = crl_config -# slits = slits_config - else: - with open(crl_setup, "rb") as f: - config = tomllib.load(f) - beam = config['beam'] - beamline = config['beamline'] - crl = config['crl'] - # slits = config['slits'] - - self.beam = {} - self.setupSource(beam) - - self.bl = {} - self.setupBeamline(beamline) - - self.crl = {} - self.setupCRL(crl) - - self.slits = [{'H':0,'V':0}] - -# self.slit1_H = 0 -# self.slit1_V = 0 - - # Initialize lens variables -- TODO -- this is done via a subs file -- are any of these needed prior to that loading? - self.numlens = np.array([1, 1, 1, 1, 1, 1, 2, 4, 8, 16]) # CRL1 number of lenses in each stack (was L1_n) - self.radius = np.array([2.0e-3, 1.0e-3, 5.0e-4, 3.0e-4, 2.0e-4, 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4]) # CRL1 lens radius in each stack (was L1_R) - self.materials = np.array(["Be", "Be", "Be", "Be", "Be", "Be", "Be", "Be", "Be", "Be"]) # CRL1 lens material in each stack (was L1_mater) - self.lens_loc = np.array([4.5, 3.5, 2.5, 1.5, 0.5, -0.5, -1.5, -2.5, -3.5, -4.5])*self.crl['stack_d'] # CRL1 lens stack location relative to center stack, positive means upstream (was L1_Loc) - self.lens_thickerr = np.array([1.0e-6, 1.0e-6, 1.0e-6, 1.0e-6, 1.0e-6, 1.0e-6, 1.4e-6, 2.0e-6, 2.8e-6, 4.0e-6]) # CRL1 lens RMS thickness error (was L1_HE) - - - self.Lens_diameter_table = [ - (50, 450.0), - (100, 632.0), - (200, 894.0), - (300, 1095.0), - (500, 1414.0), - (1000, 2000.0), - (1500, 2450.0), - ] - # Convert the lookup table to a dictionary for faster lookup - self.Lens_diameter_dict = {int(col1): col2 for col1, col2 in self.Lens_diameter_table} - - self.energy = 0 # gets value from an ao (incoming beam energy) - self.focalSize = 0 # get value from an ao (desired focal length) - self.lenses = 0 # sets integer (2^10) whose binary representation indicates which lenses are in or out - - self.num_stacks = 10 # Number of lenses in system - - self.lookupTable = [] - - self.thickerr_flag = True - - def setupSource(self, beam_properties): - ''' - Beam properties can have entries for the following - - energy : energy in keV - L_und : undulator length in m - sigmaH_e : Sigma electron source size in H direction in m - sigmaV_e : Sigma electron source size in V direction in m - sigmaHp_e : Sigma electron divergence in H direction in rad - sigmaVp_e : Sigma electron divergence in V direction in rad - ''' - - self.setEnergy(beam_properties['energy']) - self.L_und = beam_properties['L_und'] - self.sigmaH_e = beam_properties['sigmaH_e'] - self.sigmaV_e = beam_properties['sigmaV_e'] - self.sigmaHp_e = beam_properties['sigmaHp_e'] - self.sigmaVp_e = beam_properties['sigmaVp_e'] - - self.setupSourceEnergyDependent() - - def setupSourceEnergyDependent(self): - ''' - Fill in later - ''' - self.beam['sigmaH'] = (self.sigmaH_e**2 + self.wl*self.L_und/2/np.pi/np.pi)**0.5 - self.beam['sigmaV'] = (self.sigmaV_e**2 + self.wl*self.L_und/2/np.pi/np.pi)**0.5 - self.beam['sigmaHp'] = (self.sigmaHp_e**2 + self.wl/self.L_und/2)**0.5 - self.beam['sigmaVp'] = (self.sigmaVp_e**2 + self.wl/self.L_und/2)**0.5 - - def setupBeamline(self, beamline_properties, num=1): - ''' - Beamline properties can contain entries for the following - - d_StoL1 : Source-to-CRL1 distance, in m - d_Stof : Source-to-sample distance, in m - ''' - - self.bl['d_StoL1'] = beamline_properties['d_StoL1'] - self.bl['d_Stof'] = beamline_properties['d_Stof'] - - - def setupCRL(self, crl_properties): - ''' - CRL properties can contiain entries for the following - - d_min : Minimum thickness at the apex in m - stack_d : Stack thickness in m - ''' - self.crl['d_min'] = crl_properties['d_min'] - self.crl['stack_d'] = crl_properties['stack_d'] - - def setupSlits(self, slit_properties): - ''' - Slit properties can contain entries for the following - - ''' - pass - - def setupLookupTable(self, subs_file, n_lenses): - ''' - lookup table created after IOC startup - energy and slit size are updated before this is called - ''' - print(80*'#') - print('Setting up lens control...') - - self.num_stacks = n_lenses - self.num_configs = 2**self.num_stacks - self.configs = np.arange(self.num_configs) - -# self.energy = energy - - #read in substitutions file - try: - subsFile = open(subs_file,"r") - except: - raise RuntimeError(f"Substiution file ({subsFile}) not found.") - subsFileContent = subsFile.readlines() - subsFile.close() - - macros = subsFileContent[2].replace('{','').replace('}','').replace(',','').split() - lens_properties = {key: [] for key in macros} # dictionary of lists - for i in range(self.num_stacks): - try: - xx = subsFileContent[3+i].replace('{','').replace('}','').replace(',','').replace('"','').split() - lens_properties[macros[0]].append(xx[0]) - lens_properties[macros[1]].append(xx[1]) - lens_properties[macros[2]].append(xx[2]) - lens_properties[macros[3]].append(xx[3]) - lens_properties[macros[4]].append(xx[4]) - lens_properties[macros[5]].append(xx[5]) - lens_properties[macros[6]].append(xx[6]) - except: - raise RuntimeError(f"Number of lenses ({self.num_stacks}) doesn't match substitution file") - - self.numlens = [] - self.radius = [] - self.materials = [] - self.lens_loc = [] - self.lens_thickerr = [] - - # get number of lens for each lens stack from lens properties dictionary-list - print('Getting lens materials...') - if NLENS_MACRO in macros: - self.numlens = np.array([int(i) for i in lens_properties[NLENS_MACRO]]) - print('Number of lens read in.\n') - else: - raise RuntimeError(f"Number of lenses macro ({NLENS_MACRO}) not found in substituion file") - - # get radii for each lens from lens properties dictionary-list - print('Getting lens\' radii...') - if RADIUS_MACRO in macros: - self.radius = np.array([float(i) for i in lens_properties[RADIUS_MACRO]]) - print('Radius of lenses read in.\n') - else: - raise RuntimeError(f"Radius macro ({RADIUS_MACRO}) not found in substituion file") - - # get materials from lens properties dictionary-list - print('Getting lens materials...') - if MAT_MACRO in macros: - self.materials = lens_properties[MAT_MACRO] - print('Lens material read in.\n') - else: - raise RuntimeError(f"Material macro ({MAT_MACRO}) not found in substituion file") - - # get densities from local definition (for compounds) or from xraylib (for elements) - densities = get_densities(self.materials) - self.densities = np.array([densities[material] for material in self.materials]) - - # get location of each lens from lens properties dictionary-list - print('Getting lens\' locations...') - if LOC_MACRO in macros: - self.lens_loc = np.array([float(i)*self.crl['stack_d'] for i in lens_properties[LOC_MACRO]]) - print('Location of lenses read in.\n') - else: - raise RuntimeError(f"Location macro ({LOC_MACRO}) not found in substituion file") - - # get thicknesses errprfrom lens properties dictionary-list - print('Getting lens thickness error...') - if THICKERR_MACRO in macros: - self.lens_thickerr = np.array([float(i) for i in lens_properties[THICKERR_MACRO]]) - print('Lens thickness errors read in.\n') - else: - raise RuntimeError(f"Thickness errors macro ({THICKERR_MACRO}) not found in substituion file") - - print('Constructing lookup table...') - self.construct_lookup_table() - print('Lookup table calculation complete.\n') - - print('Transfocator control setup complete.') - print(80*'#') - - def construct_lookup_table(self): - arr_a, arr_b, arr_c = calc_lookup_table(self.num_configs, self.radius, - self.materials, self.energy, self.wl, - self.numlens, - self.lens_loc, self.beam, self.bl, - self.crl, self.slits[0]['H'], self.slits[0]['V'], - self.lens_thickerr, flag_HE = self.thickerr_flag, - verbose = self.verbose) - self.lookupTable = arr_a - self.sorted_invF_index = arr_b - self.sorted_invF = arr_c - -# self.sort_lookup_table() - self.updateEnergyRBV() - self.updateSlitSizeRBV('hor') - self.updateSlitSizeRBV('vert') - self.updateLookupWaveform() - self.updateInvFWaveform() - self.updateLookupConfigs() - - - def setFocalSizeActual(self): - ''' - - ''' -# self.focalSize_actual = self.culledTable[self.culledIndex] - self.focalSize_actual = self.lookupTable[self.indexSorted] - - def find_config(self): - ''' - User selected focal size, this function finds nearest acheivable focal - size from the lookup table - ''' - # Code to search lookup table for nearest focal size to desired; note the - # lookup table is already sorted by 1/f - if self.verbose: print(f'Searching for config closest to {self.focalSize}') -# simple approach -# self.indexSorted = np.argmin(np.abs(self.lookupTable - self.focalSize)) - - # XS approach -- can handle nan but in pydev application don't have a good - # way to "transmit" errors (i.e. no solution found) to user. - indices, _ = find_levels(self.lookupTable, self.focalSize, direction='forward')[0] - self.indexSorted = indices[0] - - - if self.verbose: print(f'1/f-sorted config index found at {self.indexSorted}') - - self.index = self.sorted_invF_index[self.indexSorted] - if self.verbose: print(f'Config index found at {self.index}') - - # Update PVs - self.setFocalSizeActual() - self.updateLensConfigPV() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - def getPreviewFocalSize(self, sortedIndex): - ''' - - ''' - fSize_preview = self.lookupTable[sortedIndex] - if self.verbose: print(f'Preview focal sizes for {sortedIndex} is {fSize_preview}') - pydev.iointr('new_preview', fSize_preview) - - def setSlitSize(self, size, slit): - ''' - Update proper slit size - ''' - - if slit == 'hor': -# self.slit1_H = float(size) # H slit size before CRL 1 - self.slits[0]['H'] = float(size) # H slit size before CRL 1 - elif slit == 'vert': -# self.slit1_V = float(size) # V slit size before CRL 1 - self.slits[0]['V'] = float(size) # V slit size before CRL 1 - else: - raise RuntimeError(f"Slit identifier ({slit}) not recognized. Should be 'hor' or 'vert'") - - - def updateSlitSize(self, size, slit): - ''' - Slit size updates are propagated to CRL object from EPICS. The beam - size lookup table is then recalculated. - ''' - self.setSlitSize(size, slit) - - if self.verbose: - if slit == 'hor': -# print(f'Horizontal slit size updated to {self.slit1_H} m') - print(f"Horizontal slit size updated to {self.slits[0]['H']} m") - elif slit == 'vert': -# print(f'Vertical slit size updated to {self.slit1_V} m') - print(f"Vertical slit size updated to {self.slits[0]['V']} m") - - - def setEnergy(self, energy): - ''' - Sets various forms of energy - ''' - if energy > 0.0001: - self.energy = float(energy) - self.energy_eV = self.energy*1000.0 # Energy in keV - self.wl = 1239.84 / (self.energy_eV * 10**9) #Wavelength in nm(?) - if self.verbose: print(f'Setting energy to {self.energy} keV') - - def updateE(self, energy): - ''' - Beam energy updates are propagated to CRL object from EPICS. The beam - size lookup table is then recalculated. - ''' - - if energy > 0.0001: - # Energy variable sent from IOC as a string - self.setEnergy(energy) - # Update beam properties that are dependent on energy - self.setupSourceEnergyDependent() - else: - if verbose: print(f'Invalid energy setting: {energy} kev; staying at {self.energy} keV') - - def updateFsize(self, focalSize): - ''' - User updates desired focal size. Lookup table is traversed to find nearest - to desired. - ''' - # focalPoint variable sent from IOC as a string - self.focalSize = float(focalSize) - self.find_config() - - def updateIndex(self, sortedIndex): - ''' - User has updated desired sorted index - ''' - self.indexSorted = int(sortedIndex) - self.index = self.sorted_invF_index[self.indexSorted] - - # Update PVs - self.setFocalSizeActual() - self.updateLensConfigPV() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - def setThickerrFlag(self, flag): - ''' - User has updated thickness error flag so that ... - ''' - self.thickerr_flag = int(flag) - if self.verbose: print(f'Thickness Error Flag set to {flag}') - self.updateThickerrFlagRBV() - - def updateThickerrFlagRBV(self): - ''' - Thickness error flag has been updated - ''' - if self.verbose: print(f'Thickness Error Flag RBV set to {self.thickerr_flag}') - pydev.iointr('updated_thickerr_Flag', self.thickerr_flag) - - - def updateLensConfigPV(self): - ''' - - ''' - self.config = self.configs[self.index] - pydev.iointr('new_lenses', int(self.config)) - - def updateLensRBV(self): - ''' - - ''' - pydev.iointr('new_index', int(self.indexSorted)) - - def updateEnergyRBV(self): - ''' - - ''' - pydev.iointr('updated_E', float(self.energy)) - - def updateSlitSizeRBV(self, slit): - ''' - Update proper slit size - ''' - - if slit == 'hor': -# pydev.iointr('updated_slitSize_H', float(self.slit1_H)) -# if self.verbose: print(f'Horizontal slit size RBV updated to {self.slit1_H} m') - pydev.iointr('updated_slitSize_H', float(self.slits[0]['H'])) - if self.verbose: print(f"Horizontal slit size RBV updated to {self.slits[0]['H']} m") - elif slit == 'vert': -# pydev.iointr('updated_slitSize_V', float(self.slit1_V)) -# if self.verbose: print(f'Vertical slit size RBV updated to {self.slit1_V} m') - pydev.iointr('updated_slitSize_V', float(self.slits[0]['V'])) - if self.verbose: print(f"Vertical slit size RBV updated to {self.slits[0]['V']} m") - - - - def updateFocalSizeRBVs(self): - ''' - - ''' - pydev.iointr('new_fSize', self.focalSize_actual) - - def updateVerbosity(self, verbosity): - ''' - Turn on minor printing - ''' - print(f'Verbosity set to {verbosity}') - self.verbose = int(verbosity) - - def updateLookupWaveform(self): - ''' - Puts lookup table focal sizes into waveform PV - ''' - pydev.iointr('new_lookupTable', self.lookupTable.tolist()) - - def updateInvFWaveform(self): - ''' - Puts invF list into waveform PV - ''' - pydev.iointr('new_invFind_list', self.sorted_invF_index.tolist()) - pydev.iointr('new_invF_list', self.sorted_invF.tolist()) - - - def updateLookupConfigs(self): - ''' - Puts lookup table config integers into waveform PV - ''' - pydev.iointr('new_configs', self.configs.tolist()) - - -class singleTF(transfocator): - def __init__(self, crl_setup = None, beam_config = DEFAULT_CONFIG['beam'], - beamline_config = DEFAULT_CONFIG['beamline'], - crl_config = DEFAULT_CONFIG['crl']): - - super().__init__(crl_setup = crl_setup, beam_config = beam_config, - beamline_config = beamline_config, crl_config = crl_config) - - def updateConfig(self, config_BW): - ''' - When user manually changes lenses, this gets focal size and displays it - along with updated RBVs but it doesn't set the config PV - ''' - self.index = int(config_BW) - # Find the configuration in the 1/f sorted list - self.indexSorted = self.sorted_invF_index.tolist().index(self.index) - - self.setFocalSizeActual() - self.updateLensRBV() - self.updateFocalSizeRBVs() - -class doubleTF(transfocator): - def __init__(self, crl_setup = None, beam_config = DEFAULT_CONFIG['beam'], - beamline_config = DEFAULT_CONFIG['beamline'], - crl_config = DEFAULT_CONFIG['crl']): - - super().__init__(crl_setup = crl_setup, beam_config = beam_config, - beamline_config = beamline_config, crl_config = crl_config) - - - - def updateConfig1(self, config_BW): - ''' - When user manually changes lenses, this gets focal size and displays it - along with updated RBVs but it doesn't set the config PV - ''' - self.index = int(config_BW) - # Find the configuration in the 1/f sorted list - #TODO how to find in double-list? ????? - self.indexSorted = self.sorted_invF_index.tolist().index(self.index) - - self.setFocalSizeActual() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - def updateConfig2(self, config_BW): - ''' - When user manually changes lenses, this gets focal size and displays it - along with updated RBVs but it doesn't set the config PV - ''' - self.index = int(config_BW) - # Find the configuration in the 1/f sorted list - #TODO how to find in double-list? ????? - self.indexSorted = self.sorted_invF_index.tolist().index(self.index) - - self.setFocalSizeActual() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - - -class singeTFandKB(transfocator): - pass - diff --git a/100idPyApp/python/pyTransfocator_single.py b/100idPyApp/python/pyTransfocator_single.py deleted file mode 100644 index e8e6110..0000000 --- a/100idPyApp/python/pyTransfocator_single.py +++ /dev/null @@ -1,500 +0,0 @@ -import numpy as np -import tomllib -import xraylib -from transfocator_calcs import lookup_diameter, materials_to_deltas, materials_to_linear_attenuation -from transfocator_calcs import find_levels, calc_lookup_table, get_densities - -MAT_MACRO = 'MAT' -NLENS_MACRO = 'NUMLENS' -RADIUS_MACRO = 'RADIUS' -LOC_MACRO = 'LOC' -THICKERR_MACRO = 'THICKERR' - -''' -Config variables - -Beam Properties - energy : energy in keV - L_und : undulator length in m - sigmaH_e : Sigma electron source size in H direction in m - sigmaV_e : Sigma electron source size in V direction in m - sigmaHp : Sigma electron divergence in H direction in rad - sigmaVp_e : Sigma electron divergence in V direction in rad -Beamline properties - d_StoL1 : Source-to-CRL1 distance, in m - d_Stof : Source-to-sample distance, in m -CRL properties - d_min : Minimum thickness at the apex in m - stack_d : Stack thickness in m -''' -DEFAULT_CONFIG = {'beam':{'energy': 15, 'L_und': 4.7, 'sigmaH_e': 14.8e-6, - 'sigmaV_e': 3.7e-6, 'sigmaHp_e': 2.8e-6, 'sigmaVp_e': 1.5e-6}, - 'beamline': {'d_StoL1': 51.9, 'd_Stof': 66.2}, - 'crl':{'stack_d': 50.0e-3, 'd_min': 3.0e-5}} - -class singleTF(): - - def __init__(self, crl_setup = None, beam_config = DEFAULT_CONFIG['beam'], - beamline_config = DEFAULT_CONFIG['beamline'], - crl_config = DEFAULT_CONFIG['crl']): - - self.verbose = True - - if crl_setup is None: - beam = beam_config - beamline = beamline_config - crl = crl_config -# slits = slits_config - else: - with open(crl_setup, "rb") as f: - config = tomllib.load(f) - beam = config['beam'] - beamline = config['beamline'] - crl = config['crl'] - # slits = config['slits'] - - self.beam = {} - self.setupSource(beam) - - self.bl = {} - self.setupBeamline(beamline) - - self.crl = {} - self.setupCRL(crl) - - self.slits = [{'H':0,'V':0}] - -# self.slit1_H = 0 -# self.slit1_V = 0 - - # Initialize lens variables -- TODO -- this is done via a subs file -- are any of these needed prior to that loading? - self.numlens = np.array([1, 1, 1, 1, 1, 1, 2, 4, 8, 16]) # CRL1 number of lenses in each stack (was L1_n) - self.radius = np.array([2.0e-3, 1.0e-3, 5.0e-4, 3.0e-4, 2.0e-4, 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4, 1.0e-4]) # CRL1 lens radius in each stack (was L1_R) - self.materials = np.array(["Be", "Be", "Be", "Be", "Be", "Be", "Be", "Be", "Be", "Be"]) # CRL1 lens material in each stack (was L1_mater) - self.lens_loc = np.array([4.5, 3.5, 2.5, 1.5, 0.5, -0.5, -1.5, -2.5, -3.5, -4.5])*self.crl['stack_d'] # CRL1 lens stack location relative to center stack, positive means upstream (was L1_Loc) - self.lens_thickerr = np.array([1.0e-6, 1.0e-6, 1.0e-6, 1.0e-6, 1.0e-6, 1.0e-6, 1.4e-6, 2.0e-6, 2.8e-6, 4.0e-6]) # CRL1 lens RMS thickness error (was L1_HE) - - - self.Lens_diameter_table = [ - (50, 450.0), - (100, 632.0), - (200, 894.0), - (300, 1095.0), - (500, 1414.0), - (1000, 2000.0), - (1500, 2450.0), - ] - # Convert the lookup table to a dictionary for faster lookup - self.Lens_diameter_dict = {int(col1): col2 for col1, col2 in self.Lens_diameter_table} - - self.energy = 0 # gets value from an ao (incoming beam energy) - self.focalSize = 0 # get value from an ao (desired focal length) - self.lenses = 0 # sets integer (2^10) whose binary representation indicates which lenses are in or out - - self.num_stacks = 10 # Number of lenses in system - - self.lookupTable = [] - - self.thickerr_flag = True - - def setupSource(self, beam_properties): - ''' - Beam properties can have entries for the following - - energy : energy in keV - L_und : undulator length in m - sigmaH_e : Sigma electron source size in H direction in m - sigmaV_e : Sigma electron source size in V direction in m - sigmaHp_e : Sigma electron divergence in H direction in rad - sigmaVp_e : Sigma electron divergence in V direction in rad - ''' - - self.setEnergy(beam_properties['energy']) - self.L_und = beam_properties['L_und'] - self.sigmaH_e = beam_properties['sigmaH_e'] - self.sigmaV_e = beam_properties['sigmaV_e'] - self.sigmaHp_e = beam_properties['sigmaHp_e'] - self.sigmaVp_e = beam_properties['sigmaVp_e'] - - self.setupSourceEnergyDependent() - - def setupSourceEnergyDependent(self): - ''' - Fill in later - ''' - self.beam['sigmaH'] = (self.sigmaH_e**2 + self.wl*self.L_und/2/np.pi/np.pi)**0.5 - self.beam['sigmaV'] = (self.sigmaV_e**2 + self.wl*self.L_und/2/np.pi/np.pi)**0.5 - self.beam['sigmaHp'] = (self.sigmaHp_e**2 + self.wl/self.L_und/2)**0.5 - self.beam['sigmaVp'] = (self.sigmaVp_e**2 + self.wl/self.L_und/2)**0.5 - - def setupBeamline(self, beamline_properties, num=1): - ''' - Beamline properties can contain entries for the following - - d_StoL1 : Source-to-CRL1 distance, in m - d_Stof : Source-to-sample distance, in m - ''' - - self.bl['d_StoL1'] = beamline_properties['d_StoL1'] - self.bl['d_Stof'] = beamline_properties['d_Stof'] - - - def setupCRL(self, crl_properties): - ''' - CRL properties can contiain entries for the following - - d_min : Minimum thickness at the apex in m - stack_d : Stack thickness in m - ''' - self.crl['d_min'] = crl_properties['d_min'] - self.crl['stack_d'] = crl_properties['stack_d'] - - def setupSlits(self, slit_properties): - ''' - Slit properties can contain entries for the following - - ''' - pass - - def setupLookupTable(self, subs_file, n_lenses): - ''' - lookup table created after IOC startup - energy and slit size are updated before this is called - ''' - print(80*'#') - print('Setting up lens control...') - - self.num_stacks = n_lenses - self.num_configs = 2**self.num_stacks - self.configs = np.arange(self.num_configs) - -# self.energy = energy - - #read in substitutions file - try: - subsFile = open(subs_file,"r") - except: - raise RuntimeError(f"Substiution file ({subsFile}) not found.") - subsFileContent = subsFile.readlines() - subsFile.close() - - macros = subsFileContent[2].replace('{','').replace('}','').replace(',','').split() - lens_properties = {key: [] for key in macros} # dictionary of lists - for i in range(self.num_stacks): - try: - xx = subsFileContent[3+i].replace('{','').replace('}','').replace(',','').replace('"','').split() - lens_properties[macros[0]].append(xx[0]) - lens_properties[macros[1]].append(xx[1]) - lens_properties[macros[2]].append(xx[2]) - lens_properties[macros[3]].append(xx[3]) - lens_properties[macros[4]].append(xx[4]) - lens_properties[macros[5]].append(xx[5]) - lens_properties[macros[6]].append(xx[6]) - except: - raise RuntimeError(f"Number of lenses ({self.num_stacks}) doesn't match substitution file") - - self.numlens = [] - self.radius = [] - self.materials = [] - self.lens_loc = [] - self.lens_thickerr = [] - - # get number of lens for each lens stack from lens properties dictionary-list - print('Getting lens materials...') - if NLENS_MACRO in macros: - self.numlens = np.array([int(i) for i in lens_properties[NLENS_MACRO]]) - print('Number of lens read in.\n') - else: - raise RuntimeError(f"Number of lenses macro ({NLENS_MACRO}) not found in substituion file") - - # get radii for each lens from lens properties dictionary-list - print('Getting lens\' radii...') - if RADIUS_MACRO in macros: - self.radius = np.array([float(i) for i in lens_properties[RADIUS_MACRO]]) - print('Radius of lenses read in.\n') - else: - raise RuntimeError(f"Radius macro ({RADIUS_MACRO}) not found in substituion file") - - # get materials from lens properties dictionary-list - print('Getting lens materials...') - if MAT_MACRO in macros: - self.materials = lens_properties[MAT_MACRO] - print('Lens material read in.\n') - else: - raise RuntimeError(f"Material macro ({MAT_MACRO}) not found in substituion file") - - # get densities from local definition (for compounds) or from xraylib (for elements) - densities = get_densities(self.materials) - self.densities = np.array([densities[material] for material in self.materials]) - - # get location of each lens from lens properties dictionary-list - print('Getting lens\' locations...') - if LOC_MACRO in macros: - self.lens_loc = np.array([float(i)*self.crl['stack_d'] for i in lens_properties[LOC_MACRO]]) - print('Location of lenses read in.\n') - else: - raise RuntimeError(f"Location macro ({LOC_MACRO}) not found in substituion file") - - # get thicknesses errprfrom lens properties dictionary-list - print('Getting lens thickness error...') - if THICKERR_MACRO in macros: - self.lens_thickerr = np.array([float(i) for i in lens_properties[THICKERR_MACRO]]) - print('Lens thickness errors read in.\n') - else: - raise RuntimeError(f"Thickness errors macro ({THICKERR_MACRO}) not found in substituion file") - - print('Constructing lookup table...') - self.construct_lookup_table() - print('Lookup table calculation complete.\n') - - print('Transfocator control setup complete.') - print(80*'#') - - def construct_lookup_table(self): - arr_a, arr_b, arr_c = calc_lookup_table(self.num_configs, self.radius, - self.materials, self.energy, self.wl, - self.numlens, - self.lens_loc, self.beam, self.bl, - self.crl, self.slits[0]['H'], self.slits[0]['V'], - self.lens_thickerr, flag_HE = self.thickerr_flag, - verbose = self.verbose) - self.lookupTable = arr_a - self.sorted_invF_index = arr_b - self.sorted_invF = arr_c - -# self.sort_lookup_table() - self.updateEnergyRBV() - self.updateSlitSizeRBV('hor') - self.updateSlitSizeRBV('vert') - self.updateLookupWaveform() - self.updateInvFWaveform() - self.updateLookupConfigs() - - -# def sort_lookup_table(self): -# ''' -# -# ''' -# if self.verbose: print(f'Sorting lookup table of length {len(self.lookupTable)}') -# self.sorted_L_index = np.argsort(self.lookupTable) - - def updateConfig(self, config_BW): - ''' - When user manually changes lenses, this gets focal size and displays it - along with updated RBVs but it doesn't set the config PV - ''' - self.index = int(config_BW) - # Find the configuration in the 1/f sorted list - self.indexSorted = self.sorted_invF_index.tolist().index(self.index) - - self.setFocalSizeActual() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - - - def setFocalSizeActual(self): - ''' - - ''' -# self.focalSize_actual = self.culledTable[self.culledIndex] - self.focalSize_actual = self.lookupTable[self.indexSorted] - - def find_config(self): - ''' - User selected focal size, this function finds nearest acheivable focal - size from the lookup table - ''' - # Code to search lookup table for nearest focal size to desired; note the - # lookup table is already sorted by 1/f - if self.verbose: print(f'Searching for config closest to {self.focalSize}') -# simple approach -# self.indexSorted = np.argmin(np.abs(self.lookupTable - self.focalSize)) - - # XS approach -- can handle nan but in pydev application don't have a good - # way to "transmit" errors (i.e. no solution found) to user. - indices, _ = find_levels(self.lookupTable, self.focalSize, direction='forward')[0] - self.indexSorted = indices[0] - - - if self.verbose: print(f'1/f-sorted config index found at {self.indexSorted}') - - self.index = self.sorted_invF_index[self.indexSorted] - if self.verbose: print(f'Config index found at {self.index}') - - # Update PVs - self.setFocalSizeActual() - self.updateLensConfigPV() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - def getPreviewFocalSize(self, sortedIndex): - ''' - - ''' - fSize_preview = self.lookupTable[sortedIndex] - if self.verbose: print(f'Preview focal sizes for {sortedIndex} is {fSize_preview}') - pydev.iointr('new_preview', fSize_preview) - - def setSlitSize(self, size, slit): - ''' - Update proper slit size - ''' - - if slit == 'hor': -# self.slit1_H = float(size) # H slit size before CRL 1 - self.slits[0]['H'] = float(size) # H slit size before CRL 1 - elif slit == 'vert': -# self.slit1_V = float(size) # V slit size before CRL 1 - self.slits[0]['V'] = float(size) # V slit size before CRL 1 - else: - raise RuntimeError(f"Slit identifier ({slit}) not recognized. Should be 'hor' or 'vert'") - - - def updateSlitSize(self, size, slit): - ''' - Slit size updates are propagated to CRL object from EPICS. The beam - size lookup table is then recalculated. - ''' - self.setSlitSize(size, slit) - - if self.verbose: - if slit == 'hor': -# print(f'Horizontal slit size updated to {self.slit1_H} m') - print(f"Horizontal slit size updated to {self.slits[0]['H']} m") - elif slit == 'vert': -# print(f'Vertical slit size updated to {self.slit1_V} m') - print(f"Vertical slit size updated to {self.slits[0]['V']} m") - - - def setEnergy(self, energy): - ''' - Sets various forms of energy - ''' - if energy > 0.0001: - self.energy = float(energy) - self.energy_eV = self.energy*1000.0 # Energy in keV - self.wl = 1239.84 / (self.energy_eV * 10**9) #Wavelength in nm(?) - if self.verbose: print(f'Setting energy to {self.energy} keV') - - def updateE(self, energy): - ''' - Beam energy updates are propagated to CRL object from EPICS. The beam - size lookup table is then recalculated. - ''' - - if energy > 0.0001: - # Energy variable sent from IOC as a string - self.setEnergy(energy) - # Update beam properties that are dependent on energy - self.setupSourceEnergyDependent() - else: - if verbose: print(f'Invalid energy setting: {energy} kev; staying at {self.energy} keV') - - def updateFsize(self, focalSize): - ''' - User updates desired focal size. Lookup table is traversed to find nearest - to desired. - ''' - # focalPoint variable sent from IOC as a string - self.focalSize = float(focalSize) - self.find_config() - - def updateIndex(self, sortedIndex): - ''' - User has updated desired sorted index - ''' - self.indexSorted = int(sortedIndex) - self.index = self.sorted_invF_index[self.indexSorted] - - # Update PVs - self.setFocalSizeActual() - self.updateLensConfigPV() - self.updateLensRBV() - self.updateFocalSizeRBVs() - - def setThickerrFlag(self, flag): - ''' - User has updated thickness error flag so that ... - ''' - self.thickerr_flag = int(flag) - if self.verbose: print(f'Thickness Error Flag set to {flag}') - self.updateThickerrFlagRBV() - - def updateThickerrFlagRBV(self): - ''' - Thickness error flag has been updated - ''' - if self.verbose: print(f'Thickness Error Flag RBV set to {self.thickerr_flag}') - pydev.iointr('updated_thickerr_Flag', self.thickerr_flag) - - - def updateLensConfigPV(self): - ''' - - ''' - self.config = self.configs[self.index] - pydev.iointr('new_lenses', int(self.config)) - - def updateLensRBV(self): - ''' - - ''' - pydev.iointr('new_index', int(self.indexSorted)) - - def updateEnergyRBV(self): - ''' - - ''' - pydev.iointr('updated_E', float(self.energy)) - - def updateSlitSizeRBV(self, slit): - ''' - Update proper slit size - ''' - - if slit == 'hor': -# pydev.iointr('updated_slitSize_H', float(self.slit1_H)) -# if self.verbose: print(f'Horizontal slit size RBV updated to {self.slit1_H} m') - pydev.iointr('updated_slitSize_H', float(self.slits[0]['H'])) - if self.verbose: print(f"Horizontal slit size RBV updated to {self.slits[0]['H']} m") - elif slit == 'vert': -# pydev.iointr('updated_slitSize_V', float(self.slit1_V)) -# if self.verbose: print(f'Vertical slit size RBV updated to {self.slit1_V} m') - pydev.iointr('updated_slitSize_V', float(self.slits[0]['V'])) - if self.verbose: print(f"Vertical slit size RBV updated to {self.slits[0]['V']} m") - - - - def updateFocalSizeRBVs(self): - ''' - - ''' - pydev.iointr('new_fSize', self.focalSize_actual) - - def updateVerbosity(self, verbosity): - ''' - Turn on minor printing - ''' - print(f'Verbosity set to {verbosity}') - self.verbose = int(verbosity) - - def updateLookupWaveform(self): - ''' - Puts lookup table focal sizes into waveform PV - ''' - pydev.iointr('new_lookupTable', self.lookupTable.tolist()) - - def updateInvFWaveform(self): - ''' - Puts invF list into waveform PV - ''' - pydev.iointr('new_invFind_list', self.sorted_invF_index.tolist()) - pydev.iointr('new_invF_list', self.sorted_invF.tolist()) - - - def updateLookupConfigs(self): - ''' - Puts lookup table config integers into waveform PV - ''' - pydev.iointr('new_configs', self.configs.tolist()) -- GitLab