diff --git a/siriuspy/siriuspy/VERSION b/siriuspy/siriuspy/VERSION index 0eed1a29e..feaae22ba 100644 --- a/siriuspy/siriuspy/VERSION +++ b/siriuspy/siriuspy/VERSION @@ -1 +1 @@ -1.12.0 +1.13.0 diff --git a/siriuspy/siriuspy/computer.py b/siriuspy/siriuspy/computer.py deleted file mode 100644 index a165c1a0e..000000000 --- a/siriuspy/siriuspy/computer.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Computer interface Class.""" - - -class Computer: - """Computer class. - - Computer interface class. - """ - - def compute_update(self, computed_pv, updated_pv_name, value): - """Return dict with updated values. - - Update of property values in returned dict are triggered by - 'update_pv_name'. - """ - raise NotImplementedError - - def compute_put(self, computed_pv, value): - """Put value to all associated PVs.""" - raise NotImplementedError - - def compute_limits(self, computed_pv, updated_pv_name=None): - """Compute limits of associated PVs.""" - raise NotImplementedError diff --git a/siriuspy/siriuspy/diagnostics/bpms/bpm_plugins.py b/siriuspy/siriuspy/diagnostics/bpms/bpm_plugins.py index d58de4c9b..f3c9dc82f 100644 --- a/siriuspy/siriuspy/diagnostics/bpms/bpm_plugins.py +++ b/siriuspy/siriuspy/diagnostics/bpms/bpm_plugins.py @@ -1,9 +1,13 @@ -import numpy as _np +"""BPM plugins module.""" + from threading import Event as _Event from threading import Thread as _Thread + +import numpy as _np from epics import PV as _PV -from siriuspy.epics.fake_pv import PVFake as _PVFake -from siriuspy.epics.fake_pv import add_to_database as _add_to_database + +from siriuspy.epics.pv_fake import PVFake as _PVFake +from siriuspy.epics.pv_fake import add_to_database as _add_to_database from siriuspy.csdevice.bpms import get_bpm_database as _get_bpm_db from siriuspy.csdevice.bpms import FFTWritableProps @@ -12,6 +16,7 @@ def get_prop_and_suffix(name): + """.""" prop = name.lower().replace('-', '_').replace('.', '') prop = prop.split('_') suf = prop[1] if len(prop) > 1 else '' @@ -34,9 +39,11 @@ def run(self): self.function(*self.args) def restart(self): + """.""" self.run_now = True def stop(self): + """.""" self.run_now = False @@ -75,9 +82,12 @@ def {0}_{1}_run_callbacks(self): class BPM: + """BPM class.""" + _PV_class = None def __init__(self, bpm_name, prefix='', callback=None): + """.""" self.pv_prefix = prefix + bpm_name + ':' _add_to_database(pvDB, prefix=self.pv_prefix) self.pvs = dict() @@ -101,11 +111,15 @@ def __init__(self, bpm_name, prefix='', callback=None): class BPMEpics(BPM): + """BPM Epics.""" + _PV_class = _PV _PV_add_class = _PVFake class BPMFake(BPM): + """BPM Fake.""" + _PV_class = _PVFake _PV_add_class = _PVFake M = _np.array([[-2, -2, 0, 0], @@ -114,6 +128,7 @@ class BPMFake(BPM): [-2, -2, -2, -2]]) def __init__(self, bpm_name, prefix='', callback=None): + """.""" super().__init__(bpm_name=bpm_name, prefix=prefix, callback=callback) self._x_ref = 0 self._y_ref = 0 @@ -141,6 +156,7 @@ def __init__(self, bpm_name, prefix='', callback=None): self.timer.start() def set_ref_pos(self, x=None, y=None, q=None): + """.""" if x is not None: self._x_ref = float(x) if y is not None: diff --git a/siriuspy/siriuspy/epics/psdiag_pv.py b/siriuspy/siriuspy/epics/psdiag_pv.py deleted file mode 100644 index 5510209e6..000000000 --- a/siriuspy/siriuspy/epics/psdiag_pv.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/local/bin/python-sirius -"""PS Diag PVs.""" - -import numpy as _np -from siriuspy.csdevice.pwrsupply import Const as _PSConst -from siriuspy.csdevice.pwrsupply import ETypes as _ETypes -from siriuspy.search import PSSearch as _PSSearch -from siriuspy.computer import Computer -from siriuspy.namesys import SiriusPVName as _PVName - - -class PSDiffPV(Computer): - """Diff of a PS current setpoint and a readback.""" - - CURRT_SP = 0 - CURRT_MON = 1 - - def compute_update(self, computed_pv, updated_pv_name, value): - """Compute difference between SP and Mon current values.""" - disconnected = \ - not computed_pv.pvs[PSDiffPV.CURRT_SP].connected or \ - not computed_pv.pvs[PSDiffPV.CURRT_MON].connected - if disconnected: - return None - sp = computed_pv.pvs[PSDiffPV.CURRT_SP].value - rb = computed_pv.pvs[PSDiffPV.CURRT_MON].value - diff = rb - sp - return {'value': diff} - - def compute_put(self, computed_pv, value): - """Not needed.""" - - def compute_limits(self, computed_pv, updated_pv_name=None): - """Not needed.""" - - -class PSStatusPV(Computer): - """Power Supply Status PV.""" - - # TODO: Add other interlocks for some PS types - - BIT_PSCONNECT = 0b000001 - BIT_PWRSTATON = 0b000010 - BIT_OPMODEDIF = 0b000100 - BIT_CURRTDIFF = 0b001000 - BIT_INTERLKOK = 0b010000 - BIT_BOWFMDIFF = 0b100000 - - PWRSTE_STS = 0 - INTLK_SOFT = 1 - INTLK_HARD = 2 - OPMODE_SEL = 3 - OPMODE_STS = 4 - CURRT_DIFF = 5 - WAVFRM_MON = 6 - - DTOLWFM_DICT = dict() - - def compute_update(self, computed_pv, updated_pv_name, value): - """Compute PS Status PV.""" - psname = _PVName(computed_pv.pvs[0].pvname).device_name - value = 0 - # ps connected? - disconnected = \ - not computed_pv.pvs[PSStatusPV.PWRSTE_STS].connected or \ - not computed_pv.pvs[PSStatusPV.INTLK_SOFT].connected or \ - not computed_pv.pvs[PSStatusPV.INTLK_HARD].connected or \ - not computed_pv.pvs[PSStatusPV.OPMODE_SEL].connected or \ - not computed_pv.pvs[PSStatusPV.OPMODE_STS].connected or \ - not computed_pv.pvs[PSStatusPV.CURRT_DIFF].connected - if disconnected: - value |= PSStatusPV.BIT_PSCONNECT - value |= PSStatusPV.BIT_PWRSTATON - value |= PSStatusPV.BIT_INTERLKOK - value |= PSStatusPV.BIT_OPMODEDIF - value |= PSStatusPV.BIT_CURRTDIFF - value |= PSStatusPV.BIT_BOWFMDIFF - return {'value': value} - - # pwrstate? - pwrsts = computed_pv.pvs[PSStatusPV.PWRSTE_STS].value - if pwrsts != _PSConst.PwrStateSts.On or pwrsts is None: - value |= PSStatusPV.BIT_PWRSTATON - - # opmode? - sel = computed_pv.pvs[PSStatusPV.OPMODE_SEL].value - sts = computed_pv.pvs[PSStatusPV.OPMODE_STS].value - if sel is not None and sts is not None: - opmode_sel = _ETypes.OPMODES[sel] - opmode_sts = _ETypes.STATES[sts] - if opmode_sel != opmode_sts: - value |= PSStatusPV.BIT_OPMODEDIF - # current-diff? - if sts == _PSConst.States.SlowRef: - severity = computed_pv.pvs[PSStatusPV.CURRT_DIFF].severity - if severity != 0: - value |= PSStatusPV.BIT_CURRTDIFF - # waveform diff? - elif (psname.sec == 'BO') and (sts == _PSConst.States.RmpWfm): - mon = computed_pv.pvs[PSStatusPV.WAVFRM_MON].value - if psname not in PSStatusPV.DTOLWFM_DICT.keys(): - pstype = _PSSearch.conv_psname_2_pstype(psname) - PSStatusPV.DTOLWFM_DICT[psname] = _PSSearch.get_splims( - pstype, 'DTOL_WFM') - if not _np.allclose(mon, 0.0, - atol=PSStatusPV.DTOLWFM_DICT[psname]): - value |= PSStatusPV.BIT_BOWFMDIFF - else: - value |= PSStatusPV.BIT_OPMODEDIF - - # interlocks? - intlksoft = computed_pv.pvs[PSStatusPV.INTLK_SOFT].value - intlkhard = computed_pv.pvs[PSStatusPV.INTLK_HARD].value - if intlksoft != 0 or intlksoft is None or \ - intlkhard != 0 or intlkhard is None: - value |= PSStatusPV.BIT_INTERLKOK - return {'value': value} - - def compute_put(self, computed_pv, value): - """Not needed.""" - - def compute_limits(self, computed_pv, updated_pv_name=None): - """Not needed.""" diff --git a/siriuspy/siriuspy/epics/fake_pv.py b/siriuspy/siriuspy/epics/pv_fake.py similarity index 100% rename from siriuspy/siriuspy/epics/fake_pv.py rename to siriuspy/siriuspy/epics/pv_fake.py diff --git a/siriuspy/siriuspy/epics/computed_pv.py b/siriuspy/siriuspy/epics/pv_psdiag.py similarity index 62% rename from siriuspy/siriuspy/epics/computed_pv.py rename to siriuspy/siriuspy/epics/pv_psdiag.py index 37f3663f2..67f291cc5 100644 --- a/siriuspy/siriuspy/epics/computed_pv.py +++ b/siriuspy/siriuspy/epics/pv_psdiag.py @@ -1,7 +1,15 @@ -"""Definition of ComputedPV class that simulates a PV composed of epics PVs.""" +#!/usr/local/bin/python-sirius +"""PS Diag PVs.""" + import numpy as _np + from epics import PV as _PV + from siriuspy.epics import connection_timeout as _connection_timeout +from siriuspy.csdevice.pwrsupply import Const as _PSConst +from siriuspy.csdevice.pwrsupply import ETypes as _ETypes +from siriuspy.search import PSSearch as _PSSearch +from siriuspy.namesys import SiriusPVName as _PVName class ComputedPV: @@ -13,8 +21,6 @@ class ComputedPV: computed process variables. """ - # NOTE: currently this is being used only in as-ps-diag IOC classes. - def __init__(self, pvname, computer, queue, pvs, monitor=True): """Initialize PVs.""" # print('compute_pv: ', pvname, pvs) @@ -108,7 +114,7 @@ def run_callbacks(self): 'lolim': self.lower_disp_limit, 'low': self.lower_warning_limit, 'lolo': self.lower_alarm_limit, - }) + }) def wait_for_connection(self, timeout): """Wait util computed PV is connected or until timeout.""" @@ -197,3 +203,106 @@ def _value_update_callback(self, pvname, value, **kwargs): def _issue_callback(self, **kwargs): for index, callback in self._callbacks.items(): callback(**kwargs) + + +class PSDiffPV: + """Diff of a PS current setpoint and a readback.""" + + CURRT_SP = 0 + CURRT_MON = 1 + + + def compute_update(self, computed_pv, updated_pv_name, value): + """Compute difference between SP and Mon current values.""" + disconnected = \ + not computed_pv.pvs[PSDiffPV.CURRT_SP].connected or \ + not computed_pv.pvs[PSDiffPV.CURRT_MON].connected + if disconnected: + return None + value_sp = computed_pv.pvs[PSDiffPV.CURRT_SP].value + value_rb = computed_pv.pvs[PSDiffPV.CURRT_MON].value + diff = value_rb - value_sp + return {'value': diff} + + +class PSStatusPV: + """Power Supply Status PV.""" + + # TODO: Add other interlocks for some PS types + + BIT_PSCONNECT = 0b000001 + BIT_PWRSTATON = 0b000010 + BIT_OPMODEDIF = 0b000100 + BIT_CURRTDIFF = 0b001000 + BIT_INTERLKOK = 0b010000 + BIT_BOWFMDIFF = 0b100000 + + PWRSTE_STS = 0 + INTLK_SOFT = 1 + INTLK_HARD = 2 + OPMODE_SEL = 3 + OPMODE_STS = 4 + CURRT_DIFF = 5 + WAVFRM_MON = 6 + + DTOLWFM_DICT = dict() + + def compute_update(self, computed_pv, updated_pv_name, value): + """Compute PS Status PV.""" + psname = _PVName(computed_pv.pvs[0].pvname).device_name + value = 0 + # ps connected? + disconnected = \ + not computed_pv.pvs[PSStatusPV.PWRSTE_STS].connected or \ + not computed_pv.pvs[PSStatusPV.INTLK_SOFT].connected or \ + not computed_pv.pvs[PSStatusPV.INTLK_HARD].connected or \ + not computed_pv.pvs[PSStatusPV.OPMODE_SEL].connected or \ + not computed_pv.pvs[PSStatusPV.OPMODE_STS].connected or \ + not computed_pv.pvs[PSStatusPV.CURRT_DIFF].connected + if disconnected: + value |= PSStatusPV.BIT_PSCONNECT + value |= PSStatusPV.BIT_PWRSTATON + value |= PSStatusPV.BIT_INTERLKOK + value |= PSStatusPV.BIT_OPMODEDIF + value |= PSStatusPV.BIT_CURRTDIFF + value |= PSStatusPV.BIT_BOWFMDIFF + return {'value': value} + + # pwrstate? + pwrsts = computed_pv.pvs[PSStatusPV.PWRSTE_STS].value + if pwrsts != _PSConst.PwrStateSts.On or pwrsts is None: + value |= PSStatusPV.BIT_PWRSTATON + + # opmode? + sel = computed_pv.pvs[PSStatusPV.OPMODE_SEL].value + sts = computed_pv.pvs[PSStatusPV.OPMODE_STS].value + if sel is not None and sts is not None: + opmode_sel = _ETypes.OPMODES[sel] + opmode_sts = _ETypes.STATES[sts] + if opmode_sel != opmode_sts: + value |= PSStatusPV.BIT_OPMODEDIF + # current-diff? + if sts == _PSConst.States.SlowRef: + severity = computed_pv.pvs[PSStatusPV.CURRT_DIFF].severity + if severity != 0: + value |= PSStatusPV.BIT_CURRTDIFF + # waveform diff? + elif (psname.sec == 'BO') and (sts == _PSConst.States.RmpWfm): + mon = computed_pv.pvs[PSStatusPV.WAVFRM_MON].value + if psname not in PSStatusPV.DTOLWFM_DICT.keys(): + pstype = _PSSearch.conv_psname_2_pstype(psname) + PSStatusPV.DTOLWFM_DICT[psname] = _PSSearch.get_splims( + pstype, 'DTOL_WFM') + if not _np.allclose(mon, 0.0, + atol=PSStatusPV.DTOLWFM_DICT[psname]): + value |= PSStatusPV.BIT_BOWFMDIFF + else: + value |= PSStatusPV.BIT_OPMODEDIF + + # interlocks? + intlksoft = computed_pv.pvs[PSStatusPV.INTLK_SOFT].value + intlkhard = computed_pv.pvs[PSStatusPV.INTLK_HARD].value + if intlksoft != 0 or intlksoft is None or \ + intlkhard != 0 or intlkhard is None: + value |= PSStatusPV.BIT_INTERLKOK + return {'value': value} diff --git a/siriuspy/tests/test_computer.py b/siriuspy/tests/test_computer.py deleted file mode 100755 index a7dab58cd..000000000 --- a/siriuspy/tests/test_computer.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python-sirius - -"""Unittest module for computer.py.""" - -from unittest import TestCase -import siriuspy.util as util -import siriuspy.computer as computer - - -public_interface = ( - 'Computer', -) - - -class TestComputer(TestCase): - """Test computer module.""" - - def test_public_interface(self): - """Test module's public interface.""" - valid = util.check_public_interface_namespace(computer, - public_interface) - self.assertTrue(valid) - - -class TestComputerClass(TestCase): - """Test Computer Class.""" - - public_interface = ( - 'compute_update', - 'compute_put', - 'compute_limits', - ) - - def test_public_interface(self): - """Test module's public interface.""" - valid = util.check_public_interface_namespace( - computer.Computer, - TestComputerClass.public_interface) - self.assertTrue(valid) - - def test_computer_update(self): - """Test compute_update method.""" - c = computer.Computer() - self.assertRaises(NotImplementedError, c.compute_update, - computed_pv=None, - updated_pv_name=None, - value=None) - - def test_computer_put(self): - """Test compute_put method.""" - c = computer.Computer() - self.assertRaises(NotImplementedError, c.compute_put, - computed_pv=None, - value=None) - - def test_computer_limits(self): - """Test compute_put method.""" - c = computer.Computer() - self.assertRaises(NotImplementedError, c.compute_limits, - computed_pv=None,)