Add help functionality for BL specific information on BEC command line

This commit is contained in:
gac-x07mb
2024-11-21 17:38:36 +01:00
parent 61b1385976
commit c86a5e3f4b
8 changed files with 429 additions and 70 deletions

View File

@ -71,6 +71,7 @@ print("autoreload loaded ")
@register_line_magic
def ph_reload(line):
"""reloads certain phoenix related script to the iphython shell"""
##########################################################################
#
@ -115,7 +116,7 @@ def ph_add_xmap(line):
# enddef
print("...... %ph_load_falcon ... to reload falcon configuration")
print("...... %ph_add_falcon ... to addd falcon to configuration")
@register_line_magic
@ -130,6 +131,9 @@ def ph_add_falcon(line):
## enddef
print("...... %ph_load_falcon ... to load falcon ")
@register_line_magic
def ph_load_falcon(line):
"""
@ -140,7 +144,7 @@ def ph_load_falcon(line):
print("elapsed time:", tt.time() - t0)
print("...... %ph_load_config ... to reload phoenix default configuration")
print("...... %ph_add_xmap ... to add xmap to default configuration")
@register_line_magic
@ -155,6 +159,9 @@ def ph_add_xmap(line):
## enddef
print("...... %ph_load_xmap ... to load xmap ")
@register_line_magic
def ph_load_xmap(line):
"""
@ -165,6 +172,9 @@ def ph_load_xmap(line):
print("elapsed time:", tt.time() - t0)
print("...... %ph_create_base_config ...load base devices ")
@register_line_magic
def ph_create_base_config(line):
"""
@ -179,12 +189,14 @@ def ph_create_base_config(line):
### enddef
print("...... %ph_restart_bec_server restarts bec-server in new terminal ")
@register_line_magic
def ph_restart_bec_server(line):
os.system("bec-server restart")
os.system(
'gnome-terminal --geometry 170X50 -- bash -c "source /data/test/x07mb-test-bec/bec_deployment/bec_venv/bin/activate ; bec-server attach; exec bash"'
'gnome-terminal --geometry 170X50 -- bash -c "source /data/test/x07mb-test-bec/production/bec_venv/bin/activate ; bec-server attach; exec bash"'
)
@ -200,11 +212,11 @@ def ph_restart_bec_server(line):
##
#####################################################################################
print("###############################################################")
#############################################")
print(" ")
print("init phoenix_bec/scripts/phoenix.py in two different ways")
print(" 1) phoenix_server = PhoenixBL() ... takes code from server version ")
print("SERVR VERSION DOES NOT WORK ANYMORE ")
print("FOLDER SCRIPT SEEMS TO BE NON_STANDARD!!!!!!! ")
phoenix_server = PhoenixBL()
@ -213,7 +225,9 @@ print(" 2) phoenix=PH.PhoenixBL() ... on inpython shell only! (for debuggin
from phoenix_bec.scripts import phoenix as PH
phoenix = PH.PhoenixBL()
pheonix = phoenix # take care os a frequent typo
# from phoenix_bec.bec_ipython_client.plugins.phoenix import Phoenix
# from phoenix_bec.devices.falcon_phoenix_no_hdf5 import FalconHDF5Plugins
print("")
print("## HELP ########### HELP #### HELP ")
print("")
print(" for help type phoenix.help() ")

View File

@ -34,25 +34,29 @@ An example usage for a 4-element FalconX system. ::
falcon.mca1.spectrum.get()
"""
from ophyd import Component as Cpt
from ophyd import Kind, EpicsSignal, EpicsSignalRO, Device
from ophyd.mca import EpicsMCARecord as _EpicsMCARecord, EpicsDXPBaseSystem, EpicsDXPMultiElementSystem, EpicsDXPMapping
from ophyd.mca import (
EpicsMCARecord as _EpicsMCARecord,
EpicsDXPBaseSystem,
EpicsDXPMultiElementSystem,
EpicsDXPMapping,
)
from ophyd.areadetector import EpicsSignalWithRBV
__all__ = (
'EpicsMCARecord',
'EpicsDXPFalcon',
'Falcon',
'xMAP'
)
__all__ = ("EpicsMCARecord", "EpicsDXPFalcon", "Falcon", "xMAP")
class EpicsMCARecord(_EpicsMCARecord):
"""EpicsMCARecord with addtional fields"""
calo = Cpt(EpicsSignal, ".CALO")
cals = Cpt(EpicsSignal, ".CALS")
calq = Cpt(EpicsSignal, ".CALQ")
tth = Cpt(EpicsSignal, ".TTH")
class EpicsDXPFalcon(Device):
"""All high-level DXP parameters for each channel"""
@ -88,6 +92,7 @@ class EpicsDXPFalcon(Device):
# Diagnostic trace
trace_data = Cpt(EpicsSignal, "TraceData")
class EpicsDXPFalconMultiElementSystem(EpicsDXPBaseSystem):
# Preset control
preset_events = Cpt(EpicsSignal, "PresetEvents")
@ -121,7 +126,9 @@ class EpicsDXPFalconMultiElementSystem(EpicsDXPBaseSystem):
copy_detection_filter = Cpt(EpicsSignal, "CopyDetectionFilter", kind=Kind.omitted)
copy_detection_threshold = Cpt(EpicsSignal, "CopyDetectionThreshold", kind=Kind.omitted)
copy_detector_polarity = Cpt(EpicsSignal, "CopyDetectorPolarity", kind=Kind.omitted)
copy_min_pulse_pair_separation = Cpt(EpicsSignal, "CopyMinPulsePairSeparation", kind=Kind.omitted)
copy_min_pulse_pair_separation = Cpt(
EpicsSignal, "CopyMinPulsePairSeparation", kind=Kind.omitted
)
copt_risetime_optimization = Cpt(EpicsSignal, "CopyRisetimeOptimization", kind=Kind.omitted)
copy_scale_factor = Cpt(EpicsSignal, "CopyScaleFactor", kind=Kind.omitted)
read_traces = Cpt(EpicsSignal, "ReadTraces", kind=Kind.omitted)
@ -154,8 +161,7 @@ class EpicsDxpFalconMapping(EpicsDXPMapping):
nd_array_mode = Cpt(EpicsSignalWithRBV, "NDArrayMode")
class Falcon(EpicsDXPFalconMultiElementSystem, EpicsDxpFalconMapping):
...
class Falcon(EpicsDXPFalconMultiElementSystem, EpicsDxpFalconMapping): ...
class xMAP(EpicsDXPMultiElementSystem, EpicsDXPMapping):

View File

@ -57,16 +57,17 @@ from bec_lib.logger import bec_logger
from ophyd import Component as Cpt
from ophyd import Device, EpicsSignal, EpicsSignalRO, EpicsSignalWithRBV
#from ophyd_devices.devices.dxp import Falcon, EpicsMCARecord, EpicsDXPFalcon
# from ophyd_devices.devices.dxp import Falcon, EpicsMCARecord, EpicsDXPFalcon
from phoenix_bec.devices.dxp_loc import Falcon, EpicsMCARecord, EpicsDXPFalcon
from ophyd_devices.devices.areadetector.plugins import HDF5Plugin_V35 as HDF5Plugin#
from ophyd_devices.devices.areadetector.plugins import HDF5Plugin_V35 as HDF5Plugin #
from ophyd_devices.interfaces.base_classes.psi_detector_base import (
CustomDetectorMixin,
PSIDetectorBase,
)
logger = bec_logger.logger
@ -108,15 +109,18 @@ class FalconSetup(CustomDetectorMixin):
"""
# Specify which functions are revealed to the user in BEC client
USER_ACCESS = ["My_routine"]
def __init__(self, *args, parent: Device = None, **kwargs) -> None:
super().__init__(*args, parent=parent, **kwargs)
self._lock = threading.RLock()
def on_init(self) -> None:
"""Initialize Falcon detector"""
#self.initialize_default_parameter()
#self.initialize_detector()
#self.initialize_detector_backend()
# self.initialize_default_parameter()
# self.initialize_detector()
# self.initialize_detector_backend()
def initialize_default_parameter(self) -> None:
"""
@ -317,10 +321,14 @@ class FalconSetup(CustomDetectorMixin):
self.parent.pixel_advance_mode.put(trigger)
self.parent.ignore_gate.put(ignore_gate)
def My_routine(self):
print("My routine in Falcon mixing class ")
class FalconPhoenix(PSIDetectorBase, Falcon):
"""
FalconX4 Sitoro detector for Phoenix
FalconX4 Sitoro detector for Phoenixdef My_routine(self):
print('My_routine')
Parent class: PSIDetectorBase, Falcon
@ -332,14 +340,10 @@ class FalconPhoenix(PSIDetectorBase, Falcon):
dxp<n> (EpicsDXPFalcon) : DXP parameters for Falcon detector
mca<n> (EpicsMCARecord) : MCA parameters for Falcon detector
hdf5 (FalconHDF5Plugins) : HDF5 parameters for Falcon detector
MIN_READOUT (float) : Minimum readout time for the detector
"""
MIN_READOUT (float)"""
# Specify which functions are revealed to the user in BEC client
USER_ACCESS = ["describe"]
USER_ACCESS = ["describe", "help"]
# specify Setup class
custom_prepare_cls = FalconSetup
@ -351,19 +355,25 @@ class FalconPhoenix(PSIDetectorBase, Falcon):
# DXP parameters
dxp1 = Cpt(EpicsDXPFalcon, "dxp1:")
#dxp2 = Cpt(EpicsDXPFalcon, "dxp2:")
#dxp3 = Cpt(EpicsDXPFalcon, "dxp3:")
#dxp4 = Cpt(EpicsDXPFalcon, "dxp4:")
# dxp2 = Cpt(EpicsDXPFalcon, "dxp2:")
# dxp3 = Cpt(EpicsDXPFalcon, "dxp3:")
# dxp4 = Cpt(EpicsDXPFalcon, "dxp4:")
# MCA record with spectrum data
mca1 = Cpt(EpicsMCARecord, "mca1")
#mca2 = Cpt(EpicsMCARecord, "mca2")
#mca3 = Cpt(EpicsMCARecord, "mca3")
#mca4 = Cpt(EpicsMCARecord, "mca4")
# mca2 = Cpt(EpicsMCARecord, "mca2")
# mca3 = Cpt(EpicsMCARecord, "mca3")
# mca4 = Cpt(EpicsMCARecord, "mca4")
# optionally with a HDF5 writer plugin
# hdf5 = Cpt(HDF5Plugin, "HDF1:")
def help(self):
help_text = """
PHOENIX FALCON
"""
if __name__ == "__main__":
falcon = FalconPhoenix(name="falcon_hdf5", prefix="X07MB-SITORO:", sim_mode=True)

View File

@ -174,7 +174,7 @@ class PhoenixTrigger(PSIDetectorBase):
#
##################################################################
USER_ACCESS = []
USER_ACCESS = ["describe", "help"]
####################################################################
#
@ -228,6 +228,50 @@ class PhoenixTrigger(PSIDetectorBase):
EpicsSignalRO, "SMPL-DONE", kind=Kind.config
) # show trigger is done, consider using string=True
def help(self):
help_text = """
PHOENIX TRIGGER
signal attributes vs Epics Channels
description device Epics Channel
attribute
Cont sampling on/off .start_csmpl ~ X07MB-OP2:SMPL
1: continous
0: continous off
Counter run up .intr_count ~ " :INTR-COUNT
Cycles set .total_cycles ~ " :TOTAL-CYCLES
1 cycle = 200 ms
Start sampling (aquiring) .smpl ~ " :SMPL
Show trigger is done .smpl_done ~ " :SMPL-DONE
1: aquiring
0: not aquiring
Assuming device is called dev.PH_TTL
Read Channel dev.PH_TTL.start_csmpl.get()
Write into Channel dev.PH_TTL.total_cycles.put(1)
dev.PH_TTL.total_cycles.set(1)
For further general help try the attributes
.describe() .describe_confguration() .summary()
._config ._info
"""
print("Name of device is", self.name)
print("")
print(help_text)
return
if __name__ == "__main__":

View File

@ -0,0 +1,63 @@
class X:
def print_dict(self,dict,level=4,_level=0):
"""
Utility to print structure of a dictionary
"""
_level=_level+1
if _level==3:
return
#print('............... LEVEL'+str(level))
for key in dict:
print(_level,'...'*(_level-1),key)
#print(dict[key])
if 'dict' in str(type(dict[key])):
print(' ')
self.print_dict(dict[key],level=level,_level=_level)
#endfor
if _level==1:
print('...... main level keys....')
print(dict.keys())
#endif
def print_signale(self,dict,level=1,_level=0):
"""
Utility to print structure of a dictionary
"""
_level=_level+1
if _level==3:
return
#print('............... LEVEL'+str(level))
for key in dict:
print(_level,'...'*(_level-1),key)
#print(dict[key])
if 'dict' in str(type(dict[key])):
print(' ')
self.print_dict(dict[key],level=level,_level=_level)
#endfor
if _level==1:
print('...... main level keys....')
print(dict.keys())
#endif
this_dev_ttl=dev.PH_TTL
this_dev_fa=dev.falcon
this_dev=this_dev_fa
w_dict=this_dev.__dict__
w_dir=this_dev.__dir__()
w_info=this_dev._info
print('Structure of dict')
print(w_dict.keys())
keys=w_dict.keys()
x=X()
x.print_dict(w_dict,level=1)

View File

@ -0,0 +1,14 @@
import time
from phoenix_bec.scripts.phoenix import PhoenixBL
print("imported")
time.sleep(2)
ph = PhoenixBL()
# ph.read_phoenix_config()
#
# how do we get this to iphython command line ?
# print('........... falkon.mca1 '
# ph.list_signals_falcon()
# ph.list_signals_xmap()

View File

@ -21,6 +21,8 @@ from ophyd import Device, EpicsMotor, EpicsSignal, EpicsSignalRO
from bec_lib.config_helper import ConfigHelper
from bec_lib.logger import bec_logger
from phoenix_bec.scripts.phoenix_help import PhoenixHelp
logger = bec_logger.logger
@ -32,7 +34,65 @@ logger = bec_logger.logger
# .. define base path for directory with scripts
class PhoenixBL:
class Utilities:
"""
Utiliy class for PHOENIX
"""
def __init__(self):
print("init phoenix.Utilities")
pass
# setattr(self, "description", description)
# atribute 'label' for compatibility woith La groups...
# setattr(self, "label", description)
# if type(NameTag)==list:
# for i in NameTag:
# setattr(self,i,None)
# #endfor
# else:
# setattr(self,NameTag,None)
# endif
def list_signals_(self, cls=None, check=False):
"""
Create a list of all signals in a device
including name of Epics channel
"""
print("List of all Signals")
print("......try also attributes")
print(" .describe_configuration()")
print(" ._info")
try:
name = cls.name
n_name = len(name)
except:
Name = " "
try:
config = cls._info["describe"]
except:
config = " "
# endexcept
# print(config)
try:
for kk in config.keys():
print(kk[n_name + 1 : 40], config[kk]["source"])
# print('dev.'+def __init__():
# kk.replace('_','.'),' ',config[kk]['source'])
# endexcept
except:
print(config)
print("no key")
def list_signals_xmap(self):
HelpPhoenix
class PhoenixBL(Utilities, PhoenixHelp):
"""
#
# General class for PHOENIX beamline located in phoenix_bec/phoenic_bec/scripts
@ -48,18 +108,24 @@ class PhoenixBL:
"""
import os
# self.silent = False
# self.help()
# self.help_phoenix()
# self.help_attributes()
self.silent = False
print("..... init PhoenixBL from phoenix_bec/scripts/phoenix.py")
# Define important paths
self.base_path = "/data/test/x07mb-test-bec/production/phoenix_bec/"
self.path_phoenix_bec = self.base_path+"phoenix_bec/"
self.path_phoenix_bec = self.base_path + "phoenix_bec/"
self.path_devices = self.path_phoenix_bec + "device_configs/"
self.path_scripts = self.path_phoenix_bec + "scripts/"
self.path_scans = self.path_phoenix_bec + "scans/"
self.path_scripts_local = self.path_phoenix_bec+"local_scripts/"
self.path_scripts_local = self.path_phoenix_bec + "local_scripts/"
self.path_config_local = self.path_scripts_local + "TEST_ConfigPhoenix/"
# yamal file for default configuration
@ -69,13 +135,12 @@ class PhoenixBL:
self.file_devices_xmap = self.path_devices + "phoenix_xmap.yaml"
self.file_devices_falcon = self.path_devices + "phoenix_falcon.yaml"
# temporary yaml file to allow adding devices with one single comamnd
self.file_devices_tmp = self.path_devices + "current_devices_tmp.yaml"
self.t0 = time.time()
#def read_local_phoenix_config(self):
# def read_local_phoenix_config(self):
# print("read file ")
# print(self.file_phoenix_devices_file)
# bec.config.update_session_with_file(self.file_devices_file_local)
@ -101,27 +166,23 @@ class PhoenixBL:
def load_xmap(self):
print("load_xmap")
os.system(
"cat " + self.file_devices_xmap + " > " + self.file_devices_tmp)
os.system("cat " + self.file_devices_xmap + " > " + self.file_devices_tmp)
bec.config.update_session_with_file(self.file_devices_xmap)
def add_falcon(self):
print("add_falcon to existing configuration ")
os.system(
"cat " + self.file_devices_falcon + " >> " + self.file_devices_tmp
)
os.system("cat " + self.file_devices_falcon + " >> " + self.file_devices_tmp)
bec.config.update_session_with_file(self.file_devices_tmp)
def load_falcon(self):
print("load_falcon")
os.system(
"cat " + self.file_devices_falcon + " > " + self.file_devices_tmp)
os.system("cat " + self.file_devices_falcon + " > " + self.file_devices_tmp)
bec.config.update_session_with_file(self.file_devices_falcon)
#def show_phoenix_setup(self):
# def show_phoenix_setup(self):
# print(self.path_phoenix_bec)
# os.system("cat " + self.path_phoenix_bec + "phoenix_bec/scripts/Current_setup.txt")
@ -146,7 +207,6 @@ class PhoenixBL:
file.close
class PhGroup:
"""
Class to create data groups
@ -265,24 +325,24 @@ class PhGroup:
# endfor
# endfor
print(time.time())
# enddef
if __name__ == "__main__":
PH = PhoenixBL()
for x in PH.__dir__():
if 'path' in x:
#print(x)
if "path" in x:
# print(x)
pa = getattr(PH, x)
if os.path.isdir(pa) :
print(pa,' exists')
if os.path.isdir(pa):
print(pa, " exists")
else:
print('!!- ' , pa,' does not exist')
if 'file' in x:
print("!!- ", pa, " does not exist")
if "file" in x:
pa = getattr(PH, x)
if os.path.isfile(pa) :
print(pa,' exists')
if os.path.isfile(pa):
print(pa, " exists")
else:
print('!!- ' , pa,' does not exist')
print("!!- ", pa, " does not exist")

View File

@ -0,0 +1,148 @@
from IPython import get_ipython
class PhoenixHelp:
def pm(self, x):
if self.silent == False:
print(x)
# endif
def help(self):
self.__on_help = """HelpPhoenix
HELP ON BEC
General online documentation of BEC
https://beamline-experiment-control.readthedocs.io/en/latest/
code in git
https://gitlab.psi.ch/bec
For help on BL specific topics see
phoenix.help()
phoenix.help_phoenix() ... etc...
find attributes using tab extension on command line
BL related MAGIC COMMANDS on iphython shell start with ph:
Example:
%ph_create_base_config
.. etc .. find all commands by tab extension, description in phoenix.help_magic
"""
self.pm(self.__on_help)
# self.pm(self.on_attributes)
def help_phoenix_file_structure():
self.__on_phoenix_file_structure = """
phoenix_bec/scripts -- directory for general BL scripts
(auto read to server)
....... phoenix.py -- base classes for BL
....... phoenix_help.py -- contains classes for help as relevant
for BEC @ PHOENIX operation
phoenix_bec/scans -- location of dedicated scan types
phoenix_bec/bec_iphython_client -- directory for startup files
....... post_startup.py -- BL specific definitions, read when bec starts
Definiton of BL related magic commands
phoenix_bec/devcices -- Location for specific devices
phoenix_bec/device_configs -- location of yaml configuration files
phoenix_bec/local_scripts -- space for local and test script
(NOT auto read to server)
#######################################################################
IT IS ABSOLUTELY FORBIDDEN FOR USERS TO MAKE ANY CHANGES TO ANY OF THE FILES
#######################################################################
"""
def help_phoenix(self):
self.__on_phoenix = """
General setup of bec @ PHOENIX
important files
phoenix_bec/scripts/phoenix.py
phoenix_bec/scripts/phoenix.py
"""
self.pm(self.__on_phoenix)
def help_devices(self):
"""
help of frequently used attributes
"""
self.__on_devices = """
WORK ON EPICS CHANNELS:
.get() : read signal: value only
.read() : read signal, into dictionary including timestamp
.put() : write signal --- seems to have a callback ????
.set() : write signal --- seems to have no callback ??
OTHER;
.name : name of device
GET INFORMATION ABOUT DEVICES
._info --- seems to be most complete information dictionarty
.describe() --- = ._info['describe']
--- info about Signals/Epics channels (dictionary)
.describe_configuration
--- = ._info['describe_configuration']
--- similar to .describe
.summary -- lists attributes/names and classes of signals (on screen)
.info --
._config ._info
"""
self.pm(self.__on_devices)
def help_scans(self):
self.__on_scans = """
HELP ON SCANS --- missing
"""
self.pm(self.__on_scans)
def help_magic(self):
self.__on_magic = """
HELP ON MAGIC COMMANDS
Magic comamnd are called from the iphython shell.
BL related magic comamnd are defined in post_startup.py
All magic command start with %, BL related ones use the name convention
%ph_{name}
Example:
PHOENIX [8/225] %ph_create_base_config??
will initialzes certain %ph_load_xmap
%ph_add_xmap
%ph_restart_bec_server -- restart the bec server and opens a new terminal with tmux
"""
self.pm(self.__on_magic)