Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PV Comparison in NALMS #61

Closed
wants to merge 6 commits into from

Conversation

KaushikMalapati
Copy link
Contributor

@KaushikMalapati KaushikMalapati commented Jan 15, 2025

This pr will allow users to add pv comparison expressions to nalms configuration files which will automatically be parsed and used to generate ioc configuration files, which alongside a new nalms ioc (analogous to ads-ioc) will host calc records to perform those calculations and provide pvs with user specified alarm states based on the calculated value that nalms can use to create alarms. The motivation comes from https://jira.slac.stanford.edu/browse/ECS-6818.

I have written some of the non boilerplate-part of the nalms ioc

comparison.db

record(calcout, "$(PV):_CALC"){
    field(INPA, "$(A=)")
    field(INPB, "$(B=)")
    field(INPC, "$(C=)")
    field(INPD, "$(D=)")
    field(INPE, "$(E=)")
    field(INPF, "$(F=)")
    field(INPG, "$(G=)")
    field(INPH, "$(H=)")
    field(INPI, "$(I=)")
    field(INPJ, "$(J=)")
    field(INPK, "$(K=)")
    field(INPL, "$(L=)")
    field(CALC, "$(EXPR)")
    field(OOPT, "On Change")
}
record(ai, "$(PV)"){
    field(LOLO,"$(LOLO=)")
    field(LLSV,"$(LLSV=)")
    field(LOW,"$(LOW=)")
    field(LSV,"$(LSV=)")
    field(HIGH,"$(HIGH=)")
    field(HSV,"$(HSV=)")
    field(HIHI,"$(HIHI=)")
    field(HHSV,"$(HHSV=)")
}

st.cmd

$$LOOP(CMP)
dbLoadRecords( "db/comparison.db", "PV=$$PV,EXPR=$$EXPR,LOLO=$$LOLO,LLSV=$$LLSV,LOW=$$LOW,LSV=$$LSV,HIGH=$$HIGH,HSV=$$HSV,HIHI=$$HIHI,HHSV=$$HHSV,A=$$A,B=$$B,C=$$C,D=$$D,E=$$E,F=$$F,G=$$G,H=$$H,I=$$I,J=$$J,K=$$K,L=$$L")
$$ENDLOOP(CMP)

The spreadsheets, with the use of nine new columns allows users to specify

  • The name of the created pv that will have its alarm show up in nalms
  • The expression that will calculate a value based on constants, pvs, and operators
  • The value that will trigger each alarm state and the corresponding severity - if not set, this will default to treating the expression as a binary condition where an evaluation of any non zero value will be interpreted as a major alarm

Ideally, whenever pcds-nalms is pushed to these iocs cfgs would not only be generated but also automatically deployed just like the phoebus alarm servers are. Alternatively, the cfgs could be used by users to make deployment as simple as possible. I think there is a lot of flexibility in how to do this, so I am open to suggestions/questions.

@pcds-bot
Copy link

--- a/Spreadsheet/KFE/TMO-alarms.csv
+++ b/Spreadsheet/KFE/TMO-alarms.csv
Ignored overflowing row 1 with cell 'Branch' after: #Indent
Ignored overflowing row 1 with cell 'PV' after: #Indent
Ignored overflowing row 1 with cell 'Description' after: #Indent
Ignored overflowing row 1 with cell 'Latch' after: #Indent
Ignored overflowing row 1 with cell 'Delay' after: #Indent
Ignored overflowing row 1 with cell 'Filter' after: #Indent
Ignored overflowing row 1 with cell 'Guidance' after: #Indent
Ignored overflowing row 2 with cell 'TMO Beamline Devices' after: 0
Ignored overflowing row 3 with cell 'Mirrors' after: 1
Ignored overflowing row 4 with cell 'MR1K4' after: 2
Ignored overflowing row 5 with cell 'MR1K4:SOMS:FWM:1_RBV' after:
Ignored overflowing row 5 with cell 'Flow sensor 1' after:
Ignored overflowing row 6 with cell 'MR1K4:SOMS:FWM:2_RBV' after:
Ignored overflowing row 6 with cell 'Flow sensor 2' after:
Ignored overflowing row 7 with cell 'MR1K4:SOMS:PRSM:1_RBV' after:
Ignored overflowing row 7 with cell 'Cool pressure' after:
Ignored overflowing row 8 with cell 'MR1K4:SOMS:PIP:01:PRESS_RBV' after:
Ignored overflowing row 8 with cell 'MR1K4 ion pump' after:
Ignored overflowing row 9 with cell 'MR1K4:SOMS:GCC:1:PRESS_RBV' after:
Ignored overflowing row 9 with cell 'GCC' after:
Ignored overflowing row 10 with cell 'MR1K4:SOMS:COATING:STATE:GET_RBV' after:
Ignored overflowing row 10 with cell 'MR1K4 Coating' after:
Ignored overflowing row 10 with cell 'SIOC:SYS0:ML00:AO628 <= 400 & MR1K1:BEND:COATING:STATE:GET_RBV==B4C' after:
Ignored overflowing row 11 with cell 'MR1K4:SOMS:GANTRY_X_RBV' after:
Ignored overflowing row 11 with cell 'Gantry X' after:
Ignored overflowing row 12 with cell 'MR1K4:SOMS:GANTRY_Y_RBV' after:
Ignored overflowing row 12 with cell 'Gantry Y' after:
Ignored overflowing row 13 with cell 'MR1K4:SOMS:COATING:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 13 with cell 'MR1K4 arbiter status' after:
Ignored overflowing row 14 with cell 'MR2K4' after: 2
Ignored overflowing row 15 with cell 'MR2K4:KBO:FWM:1_RBV' after:
Ignored overflowing row 15 with cell 'Flow sensor' after:
Ignored overflowing row 16 with cell 'MR2K4:KBO:PRSM:1_RBV' after:
Ignored overflowing row 16 with cell 'Cool pressure' after:
Ignored overflowing row 17 with cell 'MR2K4:KBO:PIP:01:PRESS_RBV' after:
Ignored overflowing row 17 with cell 'MR2K4 ion pump' after:
Ignored overflowing row 18 with cell 'MR2K4:KBO:RTD:CHIN:R:TEMP_RBV' after:
Ignored overflowing row 18 with cell 'Temperature' after:
Ignored overflowing row 19 with cell 'MR2K4:KBO:RTD:CHIN:L:TEMP_RBV' after:
Ignored overflowing row 19 with cell 'Temperature' after:
Ignored overflowing row 20 with cell 'MR2K4:KBO:GCC:01:PRESS_RBV' after:
Ignored overflowing row 20 with cell 'GCC' after:
Ignored overflowing row 21 with cell 'MR2K4:KBO:COATING:STATE:GET_RBV' after:
Ignored overflowing row 21 with cell 'MR2K4 Coating' after:
Ignored overflowing row 21 with cell 'SIOC:SYS0:ML00:AO628 <= 400 & PPS:NEH1:1:ST3K4INSUM!=1' after:
Ignored overflowing row 22 with cell 'MR2K4:KBO:COATING:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 22 with cell 'MR2K4 arbiter status' after:
Ignored overflowing row 23 with cell 'MR3K4' after: 2
Ignored overflowing row 24 with cell 'MR3K4:KBO:FWM:1_RBV' after:
Ignored overflowing row 24 with cell 'Flow sensor' after:
Ignored overflowing row 25 with cell 'MR3K4:KBO:RTD:CHIN:R:TEMP_RBV' after:
Ignored overflowing row 25 with cell 'Temperature' after:
Ignored overflowing row 26 with cell 'MR3K4:KBO:RTD:CHIN:L:TEMP_RBV' after:
Ignored overflowing row 26 with cell 'Temperature' after:
Ignored overflowing row 27 with cell 'MR3K4:KBO:COATING:STATE:GET_RBV' after:
Ignored overflowing row 27 with cell 'MR3K4 Coating' after:
Ignored overflowing row 27 with cell 'SIOC:SYS0:ML00:AO628 <= 400 & PPS:NEH1:1:ST3K4INSUM!=1' after:
Ignored overflowing row 28 with cell 'MR3K4:KBO:COATING:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 28 with cell 'MR3K4 arbiter status' after:
Ignored overflowing row 29 with cell 'MR4K4' after: 2
Ignored overflowing row 30 with cell 'MR4K4:KBO:RTD:CHIN:L:TEMP_RBV' after:
Ignored overflowing row 30 with cell 'Temperature' after:
Ignored overflowing row 31 with cell 'MR4K4:KBO:PIP:01:PRESS_RBV' after:
Ignored overflowing row 31 with cell 'MR4K4 ion pump' after:
Ignored overflowing row 32 with cell 'MR4K4:KBO:GCC:01:PRESS_RBV' after:
Ignored overflowing row 32 with cell 'GCC' after:
Ignored overflowing row 33 with cell 'MR5K4' after: 2
Ignored overflowing row 34 with cell 'MR5K4:KBO:RTD:CHIN:L:TEMP_RBV' after:
Ignored overflowing row 34 with cell 'Temperature' after:
Ignored overflowing row 35 with cell 'Imagers' after: 1
Ignored overflowing row 36 with cell 'IM1K4' after: 2
Ignored overflowing row 37 with cell 'IM1K4:XTES:MMS:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 37 with cell 'IM1K4 arbiter status' after:
Ignored overflowing row 38 with cell 'IM2K4' after: 2
Ignored overflowing row 39 with cell 'IM2K4:PPM:FWM:VAL_RBV' after:
Ignored overflowing row 39 with cell 'Flow sensor ' after:
Ignored overflowing row 40 with cell 'IM2K4:PPM:SPM:STC:TEMP_RBV' after:
Ignored overflowing row 40 with cell 'PM thermocouple' after:
Ignored overflowing row 41 with cell 'IM2K4:PPM:YAG:STC:TEMP_RBV' after:
Ignored overflowing row 41 with cell 'YAG thermocouple' after:
Ignored overflowing row 42 with cell 'IM2K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 42 with cell 'IM2K4 arbiter status' after:
Ignored overflowing row 43 with cell 'IM3K4' after: 2
Ignored overflowing row 44 with cell 'IM4K4:PPM:FWM:VAL_RBV' after:
Ignored overflowing row 44 with cell 'Flow sensor ' after:
Ignored overflowing row 45 with cell 'IM3K4:PPM:SPM:STC:TEMP_RBV' after:
Ignored overflowing row 45 with cell 'PM thermocouple' after:
Ignored overflowing row 46 with cell 'IM3K4:PPM:YAG:STC:TEMP_RBV' after:
Ignored overflowing row 46 with cell 'YAG thermocouple' after:
Ignored overflowing row 47 with cell 'IM3K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 47 with cell 'IM3K4 arbiter status' after:
Ignored overflowing row 48 with cell 'IM4K4' after: 2
Ignored overflowing row 49 with cell 'IM4K4:PPM:FWM:VAL_RBV' after:
Ignored overflowing row 49 with cell 'Flow sensor ' after:
Ignored overflowing row 50 with cell 'IM4K4:PPM:SPM:STC:TEMP_RBV' after:
Ignored overflowing row 50 with cell 'PM thermocouple' after:
Ignored overflowing row 51 with cell 'IM4K4:PPM:YAG:STC:TEMP_RBV' after:
Ignored overflowing row 51 with cell 'YAG thermocouple' after:
Ignored overflowing row 52 with cell 'IM4K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 52 with cell 'IM4K4 arbiter status' after:
Ignored overflowing row 53 with cell 'IM5K4' after: 2
Ignored overflowing row 54 with cell 'IM5K4:PPM:FWM:VAL_RBV' after:
Ignored overflowing row 54 with cell 'Flow sensor' after:
Ignored overflowing row 55 with cell 'IM5K4:PPM:SPM:STC:TEMP_RBV' after:
Ignored overflowing row 55 with cell 'PM thermocouple' after:
Ignored overflowing row 56 with cell 'IM5K4:PPM:YAG:STC:TEMP_RBV' after:
Ignored overflowing row 56 with cell 'YAG thermocouple' after:
Ignored overflowing row 57 with cell 'IM5K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 57 with cell 'IM5K4 arbiter status' after:
Ignored overflowing row 58 with cell 'IM6K4' after: 2
Ignored overflowing row 59 with cell 'IM6K4:PPM:FWM:VAL_RBV' after:
Ignored overflowing row 59 with cell 'Flow sensor' after:
Ignored overflowing row 60 with cell 'IM6K4:PPM:SPM:STC:TEMP_RBV' after:
Ignored overflowing row 60 with cell 'PM thermocouple' after:
Ignored overflowing row 61 with cell 'IM6K4:PPM:YAG:STC:TEMP_RBV' after:
Ignored overflowing row 61 with cell 'YAG thermocouple' after:
Ignored overflowing row 62 with cell 'IM6K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after:
Ignored overflowing row 62 with cell 'IM6K4 arbiter status' after:
Ignored overflowing row 63 with cell 'WFS' after: 1
Ignored overflowing row 64 with cell 'PF1K4' after: 2
Ignored overflowing row 65 with cell 'IM5K4:PPM:FWM:VAL_RBV' after:

!(#Indent)---------------------
@@<<<<<<< HEADBranchPVDescriptionLatchDelayFilterGuidance
+++#Indent
+++1
+++2
+++
+++
+++
+++
+++
+++
+++
+++
+++
+++2
+++
+++
+++
+++
+++
+++
+++
+++
+++2
+++
+++
+++
+++
+++
+++2
+++
+++
+++
+++2
+++
+++1
+++2
+++
+++2
+++
+++
+++
+++
+++2
+++
+++
+++
+++
+++2
+++
+++
+++
+++
+++2
+++
+++
+++
+++
+++2
+++
+++
+++
+++
---2MR1K4
---MR1K4:SOMS:FWM:1_RBVFlow sensor 1
---MR1K4:SOMS:FWM:2_RBVFlow sensor 2
---MR1K4:SOMS:PRSM:1_RBVCool pressure
---MR1K4:SOMS:PIP:01:PRESS_RBVMR1K4 ion pump
---MR1K4:SOMS:GCC:1:PRESS_RBVGCC
---MR1K4:SOMS:COATING:STATE:GET_RBVMR1K4 CoatingSIOC:SYS0:ML00:AO628 <= 400 & MR1K1:BEND:COATING:STATE:GET_RBV==B4C
---MR1K4:SOMS:GANTRY_X_RBVGantry X
---MR1K4:SOMS:GANTRY_Y_RBVGantry Y
---MR1K4:SOMS:COATING:STATE:PMPS:ARB:ENABLE_RBVMR1K4 arbiter status
---2MR2K4
---MR2K4:KBO:FWM:1_RBVFlow sensor
---MR2K4:KBO:PRSM:1_RBVCool pressure
---MR2K4:KBO:PIP:01:PRESS_RBVMR2K4 ion pump
---MR2K4:KBO:RTD:CHIN:R:TEMP_RBVTemperature
---MR2K4:KBO:RTD:CHIN:L:TEMP_RBVTemperature
---MR2K4:KBO:GCC:01:PRESS_RBVGCC
---MR2K4:KBO:COATING:STATE:GET_RBVMR2K4 CoatingSIOC:SYS0:ML00:AO628 <= 400 & PPS:NEH1:1:ST3K4INSUM!=1
---MR2K4:KBO:COATING:STATE:PMPS:ARB:ENABLE_RBVMR2K4 arbiter status
---MR3K4:KBO:FWM:1_RBVFlow sensor
---2MR5K4
---2IM1K4
---IM1K4:XTES:MMS:STATE:PMPS:ARB:ENABLE_RBVIM1K4 arbiter status
---2IM2K4
---IM2K4:PPM:FWM:VAL_RBVFlow sensor
---IM2K4:PPM:SPM:STC:TEMP_RBVPM thermocouple
---IM2K4:PPM:YAG:STC:TEMP_RBVYAG thermocouple
---IM2K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBVIM2K4 arbiter status
---2IM3K4
---IM4K4:PPM:FWM:VAL_RBVFlow sensor
---IM3K4:PPM:SPM:STC:TEMP_RBVPM thermocouple
---IM3K4:PPM:YAG:STC:TEMP_RBVYAG thermocouple
---IM3K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBVIM3K4 arbiter status
---2IM4K4
---IM4K4:PPM:FWM:VAL_RBVFlow sensor
---IM4K4:PPM:SPM:STC:TEMP_RBVPM thermocouple
---IM4K4:PPM:YAG:STC:TEMP_RBVYAG thermocouple
---IM4K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBVIM4K4 arbiter status
---2IM5K4
---IM5K4:PPM:FWM:VAL_RBVFlow sensor
---IM5K4:PPM:SPM:STC:TEMP_RBVPM thermocouple
---IM5K4:PPM:YAG:STC:TEMP_RBVYAG thermocouple
---IM5K4:PPM:MMS:STATE:PMPS:ARB:ENABLE_RBVIM5K4 arbiter status
---2IM6K4
---IM5K4:PPM:FWM:VAL_RBVFlow sensor
---IM6K4:PPM:FWM:VAL_RBVFlow sensor
---PF2K4:WFS:STC:01:TEMP_RBVThermocouple 1
---PF2K4:WFS:STC:02:TEMP_RBVThermocouple 2
---PF2K4:WFS:MMS:STATE:PMPS:ARB:ENABLE_RBVPF2K4 arbiter status
---1SP1K4
---SP1K4:FZP:STATE:PMPS:ARB:ENABLE_RBVSP1K4 zoneplate arbiter status
---2TM1K4
---IM5K4:PPM:FWM:VAL_RBVFlow sensor
---TM1K4:ATM:STC:01:TEMP_RBVThermocouple 1
---TM1K4:ATM:MMS:STATE:PMPS:ARB:ENABLE_RBVTM1K4 arbiter status
---IM6K4:PPM:FWM:VAL_RBVFlow sensor
---TM2K4:ATM:STC:01:TEMP_RBVThermocouple 1
---1STOPPER
---2ST1K4
---LM1K4:QADC:01:OUT0_EDGE1QADC signal monitorLM1K4:QADC:01:OUT0_EDGE1>0
---LM1K4:QADC:01:OUT0_EDGE2QADC signal monitorLM1K4:QADC:01:OUT0_EDGE2>0
Ignored overflowing row 65 with cell 'Flow sensor' after: Ignored overflowing row 66 with cell 'PF1K4:WFS:STC:01:TEMP_RBV' after: Ignored overflowing row 66 with cell 'Thermocouple 1' after: Ignored overflowing row 67 with cell 'PF1K4:WFS:STC:02:TEMP_RBV' after: Ignored overflowing row 67 with cell 'Thermocouple 2' after: Ignored overflowing row 68 with cell 'PF1K4:WFS:MMS:STATE:PMPS:ARB:ENABLE_RBV' after: Ignored overflowing row 68 with cell 'PF1K4 arbiter status' after: Ignored overflowing row 69 with cell 'PF2K4' after: 2 Ignored overflowing row 70 with cell 'IM6K4:PPM:FWM:VAL_RBV' after: Ignored overflowing row 70 with cell 'Flow sensor' after: Ignored overflowing row 71 with cell 'PF2K4:WFS:STC:01:TEMP_RBV' after: Ignored overflowing row 71 with cell 'Thermocouple 1' after: Ignored overflowing row 72 with cell 'PF2K4:WFS:STC:02:TEMP_RBV' after: Ignored overflowing row 72 with cell 'Thermocouple 2' after: Ignored overflowing row 73 with cell 'PF2K4:WFS:MMS:STATE:PMPS:ARB:ENABLE_RBV' after: Ignored overflowing row 73 with cell 'PF2K4 arbiter status' after: Ignored overflowing row 74 with cell 'SP1K4' after: 1 Ignored overflowing row 75 with cell 'SP1K4:FZP:STATE:PMPS:ARB:ENABLE_RBV' after: Ignored overflowing row 75 with cell 'SP1K4 zoneplate arbiter status' after: Ignored overflowing row 76 with cell 'TMO:SPEC:FWM:VAL_RBV' after: Ignored overflowing row 76 with cell 'Flow sensor' after: Ignored overflowing row 77 with cell 'TMO:SPEC:RTD:01:TEMP_RBV' after: Ignored overflowing row 77 with cell 'Temperature sensor' after: Ignored overflowing row 78 with cell 'TMO:SPEC:RTD:02:TEMP_RBV' after: Ignored overflowing row 78 with cell 'Temperature sensor' after: Ignored overflowing row 79 with cell 'ATM' after: 1 Ignored overflowing row 80 with cell 'TM1K4' after: 2 Ignored overflowing row 81 with cell 'IM5K4:PPM:FWM:VAL_RBV' after: Ignored overflowing row 81 with cell 'Flow sensor' after: Ignored overflowing row 82 with cell 'TM1K4:ATM:STC:01:TEMP_RBV' after: Ignored overflowing row 82 with cell 'Thermocouple 1' after: Ignored overflowing row 83 with cell 'TM1K4:ATM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after: Ignored overflowing row 83 with cell 'TM1K4 arbiter status' after: Ignored overflowing row 84 with cell 'TM2K4' after: 2 Ignored overflowing row 85 with cell 'IM6K4:PPM:FWM:VAL_RBV' after: Ignored overflowing row 85 with cell 'Flow sensor' after: Ignored overflowing row 86 with cell 'TM2K4:ATM:STC:01:TEMP_RBV' after: Ignored overflowing row 86 with cell 'Thermocouple 1' after: Ignored overflowing row 87 with cell 'TM2K4:ATM:MMS:STATE:PMPS:ARB:ENABLE_RBV' after: Ignored overflowing row 87 with cell 'TM2K4 arbiter status' after: Ignored overflowing row 88 with cell 'STOPPER' after: 1 Ignored overflowing row 89 with cell 'ST1K4' after: 2 Ignored overflowing row 90 with cell 'ST1K4:TEST:MMS:STATE:ERR_RBV' after: Ignored overflowing row 90 with cell 'ST1K4 error state' after: Ignored overflowing row 91 with cell 'ST1K4:TEST:MMS:STATE:GET_RBV' after: Ignored overflowing row 91 with cell 'ST1K4 state' after: Ignored overflowing row 91 with cell 'PPS:NEH1:1:ST3K4INSUM!=0' after: Ignored overflowing row 92 with cell 'ST1K4:TEST:MMS:STATE:ST3K4_AUTO_RBV' after: Ignored overflowing row 92 with cell 'ST1K4 follow ST3K4 status' after: Ignored overflowing row 93 with cell 'CMP:ST1K4:TEST:MMS:STATE:GET_RBV' after: Ignored overflowing row 93 with cell 'ST1K4 and ST3K4 state' after: Ignored overflowing row 93 with cell 'PPS:NEH1:1:ST3K4INSUM!=0&ST1K4:TEST:MMS:STATE:GET_RBV=2' after: Ignored overflowing row 94 with cell 'IP1' after: 1 Ignored overflowing row 95 with cell 'Main Chamber Pressure' after: 2 Ignored overflowing row 96 with cell 'TMO:IP1:MAIN:GAUGE:PRESS_RBV' after: Ignored overflowing row 96 with cell 'Gauge pressure' after: Ignored overflowing row 97 with cell 'LI2K4' after: 1 Ignored overflowing row 98 with cell 'Failing gauges (2 out of 3)' after: 2 Ignored overflowing row 99 with cell 'LI2K4:IP1:GFS:01:PRESS_RBV' after: Ignored overflowing row 99 with cell 'GCC' after: Ignored overflowing row 100 with cell 'LI2K4:IP1:GFS:02:PRESS_RBV' after: Ignored overflowing row 100 with cell 'GCC' after: Ignored overflowing row 101 with cell 'LI2K4:IP1:GFS:03:PRESS_RBV' after: Ignored overflowing row 101 with cell 'GCC' after: Ignored overflowing row 102 with cell 'PMPS' after: 1 Ignored overflowing row 103 with cell 'PLC:KFE:GATT:FFO:01:FaultHWO_RBV' after: Ignored overflowing row 103 with cell 'KFE PMPS fault' after: Ignored overflowing row 104 with cell 'PLC:TMO:MOTION:FFO:01:FaultHWO_RBV' after: Ignored overflowing row 104 with cell 'TMO motion PMPS fault' after: Ignored overflowing row 105 with cell 'PLC:TMO:MOTION:FFO:02:FaultHWO_RBV' after: Ignored overflowing row 105 with cell 'TMO motion PMPS fault' after: Ignored overflowing row 106 with cell 'TMO DAQ' after: 0 Ignored overflowing row 107 with cell 'DAQ Damage' after: 1 Ignored overflowing row 108 with cell 'pva://DAQ:NEH:tmo:0:DeadFrac' after: Ignored overflowing row 109 with cell 'pva://DAQ:NEH:tmo:0:Damage_hsd' after: Ignored overflowing row 110 with cell 'pva://DAQ:NEH:tmo:0:Damage_bld' after: Ignored overflowing row 111 with cell 'pva://DAQ:NEH:tmo:0:Damage_epics' after: Ignored overflowing row 112 with cell 'pva://DAQ:NEH:tmo:0:Damage_atm' after: Ignored overflowing row 113 with cell 'SP1K4' after: 1 Ignored overflowing row 114 with cell 'SP1K4:PPM:CAM:TSS:SyncStatus' after: Ignored overflowing row 114 with cell 'Camera Sync Status' after: Ignored overflowing row 114 with cell 'SP1K4:PPM:CAM:TriggerMode_RBV!=0' after: Ignored overflowing row 115 with cell 'SP1K4:PPM:CAM:TSS:DiffVsIntAvg' after: Ignored overflowing row 115 with cell 'Sync Diff' after: Ignored overflowing row 116 with cell 'IM5K4' after: 1 Ignored overflowing row 117 with cell 'IM5K4:PPM:CAM:TSS:SyncStatus' after: Ignored overflowing row 117 with cell 'Camera Sync Status' after: Ignored overflowing row 117 with cell 'IM5K4:PPM:CAM:TriggerMode_RBV!=0' after: Ignored overflowing row 118 with cell 'IM5K4:PPM:CAM:TSS:DiffVsIntAvg' after: Ignored overflowing row 118 with cell 'Sync Diff' after: Ignored overflowing row 119 with cell 'IM6K4' after: 1 Ignored overflowing row 120 with cell 'IM6K4:PPM:CAM:TSS:SyncStatus' after: Ignored overflowing row 120 with cell 'Camera Sync Status' after: Ignored overflowing row 120 with cell 'IM6K4:PPM:CAM:TriggerMode_RBV!=0' after: Ignored overflowing row 121 with cell 'IM6K4:PPM:CAM:TSS:DiffVsIntAvg' after: Ignored overflowing row 121 with cell 'Sync Diff' after: Ignored overflowing row 122 with cell 'TMO LASER' after: 0 Ignored overflowing row 123 with cell 'QADC' after: 1 Ignored overflowing row 124 with cell 'LM1K4:QADC:01:OUT0_EDGE1' after: Ignored overflowing row 124 with cell 'QADC signal monitor' after: Ignored overflowing row 124 with cell 'LM1K4:QADC:01:OUT0_EDGE1>0' after: Ignored overflowing row 125 with cell 'LM1K4:QADC:01:OUT0_EDGE2' after: Ignored overflowing row 125 with cell 'QADC signal monitor' after: Ignored overflowing row 125 with cell 'LM1K4:QADC:01:OUT0_EDGE2>0' after:

@@ -90,6 +91,7 @@
,,ST1K4:TEST:MMS:STATE:ERR_RBV,ST1K4 error state,,,,
,,ST1K4:TEST:MMS:STATE:GET_RBV,ST1K4 state,,,PPS:NEH1:1:ST3K4INSUM!=0,
,,ST1K4:TEST:MMS:STATE:ST3K4_AUTO_RBV,ST1K4 follow ST3K4 status,,,,
,,CMP:ST1K4:TEST:MMS:STATE:GET_RBV,ST1K4 and ST3K4 state,,,,,PPS:NEH1:1:ST3K4INSUM!=0&ST1K4:TEST:MMS:STATE:GET_RBV=2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
,,CMP:ST1K4:TEST:MMS:STATE:GET_RBV,ST1K4 and ST3K4 state,,,,,PPS:NEH1:1:ST3K4INSUM!=0&ST1K4:TEST:MMS:STATE:GET_RBV=2
,,CMP:ST1K4:TEST:MMS:STATE:GET_RBV,ST1K4 and ST3K4 state,,,,PPS:NEH1:1:ST3K4INSUM!=0&ST1K4:TEST:MMS:STATE:GET_RBV=2,

I think you've misplaced the expression here, we should have a trailing comma

Copy link
Contributor Author

@KaushikMalapati KaushikMalapati Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I messed up some stuff when I was resolving the merge conflict. I think I've fixed it in my latest commits

@tangkong
Copy link
Contributor

An interesting take on the problem. While I'm in favor of keeping all of the nalms config in one place, this does toe the line as something that might be outside of the scope of pcds-nalms.

Interestingly the example expression you provided in this PR is not a comparison between two PVs, but rather two independent expressions that you want to both be true? (or at least that's how it reads to me)

On that note, it's interesting to consider the order of operations for these comparison operators. Python evaluates logical (and/or/not) operators after relational (>, <, ==) operators, but does your IOC? Have you built one of these IOCS yet?

Comment on lines +60 to +63
def get_field(match):
nonlocal index
index = index + 1
return ascii_uppercase[index]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also just be a generator of ascii_uppercase

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I initially tried, but re.sub wouldn't accept a generator only a function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something like this:

In [8]: gen_upper = (letter for letter in ascii_uppercase)

In [9]: gen_upper
Out[9]: <generator object <genexpr> at 0x7f63b21d6c80>

In [10]: def get_field(match):
    ...:     return next(gen_upper)
    ...:

In [11]: get_field('s')
Out[11]: 'A'

In [12]: get_field('s')
Out[12]: 'B'

In [13]: get_field('s')
Out[13]: 'C'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or even making that function a lambda

@@ -41,6 +44,8 @@ def csvtoxml(infile, outfile, cname):
if 'Guidance' in row and row['Guidance']:
guidance = ET.SubElement(pv, 'guidance')
guidance.text = row['Guidance']
if 'Expression' in row and row['Expression']:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So are we adding an additional column here? I don't see this column in the CSV you modified

Copy link
Contributor Author

@KaushikMalapati KaushikMalapati Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to header now,

#Indent,Branch,PV,Description,Latch,Delay,Filter,Guidance,Expression,LOLO,LLSV,LOW,LSV,HIGH,HSV,HIHI,HHSV
but I only have the commas for the extra columns on the one alarm I added

@pcds-bot
Copy link

--- a/Spreadsheet/KFE/TMO-alarms.csv
+++ b/Spreadsheet/KFE/TMO-alarms.csv

!+++++++++++++++++++++++++++
@@#IndentBranchPVDescriptionLatchDelayFilterGuidanceExpressionLOLOLLSVLOWLSVHIGHHSVHIHIHHSV
+++ST1K4:TEST:MMS:STATE:COMPST1K4 state comparedPPS:NEH1:1:ST3K4INSUM!=0&ST1K4:TEST:MMS:STATE:GET_RBV=2

@KaushikMalapati
Copy link
Contributor Author

An interesting take on the problem. While I'm in favor of keeping all of the nalms config in one place, this does toe the line as something that might be outside of the scope of pcds-nalms.

I originally wanted to make this part of the repo to piggyback off of the existing scripts that parse the csvs and because I thought it'd be nice if the ioc building process was done by a workflow so the "comparison" pvs nalms looks for are made at around the same time that the iocs that host them are built, but I would be fine splitting this off.

Interestingly the example expression you provided in this PR is not a comparison between two PVs, but rather two independent expressions that you want to both be true? (or at least that's how it reads to me)

Calling it a comparison is not a great name. I just used it because it was the name of the ticket.

On that note, it's interesting to consider the order of operations for these comparison operators. Python evaluates logical (and/or/not) operators after relational (>, <, ==) operators, but does your IOC? Have you built one of these IOCS yet?

I don't think the order that python would evaluate operators matters here, since Python is only extracting PV strings out of the expression field and replacing them with alphabetical variable names that a calc record would expect. epics does have operator precedence which I assume matches how c does it. https://github.com/slac-epics/epics-base/blob/308e234c41f59b9103b6d309f3256262a3175da2/modules/libcom/src/calc/postfix.c#L133. Parentheses have the highest priority so you can also right an expression and evaluates in the expected order, and I think it makes sense that you would write this expression the same way you would the calc field of a calc record (which is what this is used for).

I have built an ioc for this. The parent is /cds/group/pcds/epics-dev/kaushikm/ioc/common/nalms, the ioc is ioc-nalms-TMO-alarms in the tst iocmanager with the one alarm that I added in this pr.

@tangkong
Copy link
Contributor

Now that you've added the columns to the csv, I see more clearly what you're trying to accomplish here. I think I'm leaning even more toward the camp of having these IOCs be defined by config files separate from the nalms config. There is already confusion as to where the alarm thresholds come from, and I don't want to suggest that the user can set them through the NALMS csv.

I do think that this can reasonably live in the pcds-nalms repo, just maybe as a different config?

Does this properly handle the comparison between two PVs? That was brought up in the ticket and was what I understood to be the missing feature here.

@jbellister-slac
Copy link

I'm just seeing first seeing this now (looking at this repo for something else, I'll add myself as a watcher as well), but if I'm understanding the request right I think this could potentially be handled by the PyDM data plugin for NALMS?

https://slaclab.github.io/slac-alarm-manager/pydm/

Basically you can put in nalms://PV:NAME:DEFINED:IN:NALMS to a PyDM widget channel. It can be a completely new name like the summary alarms example in the documentation. Or the name of an existing PV, in which case it should reflect the alarm status in NALMS rather than that of the actual underlying EPICS PV.

The main restriction is the nalms:// protocol in PyDM will get alarm updates only, not the values of the PV or anything else (at least as currently implemented).

@KaushikMalapati
Copy link
Contributor Author

KaushikMalapati commented Jan 28, 2025

I'm just seeing first seeing this now (looking at this repo for something else, I'll add myself as a watcher as well), but if I'm understanding the request right I think this could potentially be handled by the PyDM data plugin for NALMS?

https://slaclab.github.io/slac-alarm-manager/pydm/

Basically you can put in nalms://PV:NAME:DEFINED:IN:NALMS to a PyDM widget channel. It can be a completely new name like the summary alarms example in the documentation. Or the name of an existing PV, in which case it should reflect the alarm status in NALMS rather than that of the actual underlying EPICS PV.

The main restriction is the nalms:// protocol in PyDM will get alarm updates only, not the values of the PV or anything else (at least as currently implemented).

From the page you linked, it looks like the data plugin only lets you make channels to pvs in nalms or components which have the highest severity out of all of their subcomponents. Based on what I read in the ticket, they wanted a system where you could make a nalms alarm based on a certain condition or a comparison between pvs. The example James gave is an alarm that goes off when the photon energy is below 400eV and the a mirror is using the B4C stripe. Can the plugin do something like that? What would happen if you put a new name that didn't match any pvs or components?

@jbellister-slac
Copy link

The example of highest severity was used in the documentation as it is specific to an accelerator use case, but more generally the data plugin will just match the alarm state of NALMS rather than EPICS.

So for that example, you'd have the PV with its normal EPICS alarm that will go off when the energy drops below 400eV, and then the enabling filter from NALMS that looks at the mirror and prevents the alarm from being raised unless that condition is hit too.

The enabling filter is just exactly what Phoebus uses, no changes in NALMS.

https://github.com/ControlSystemStudio/phoebus/blob/5d07c7d63b5ad281eb9c9b7759d2e86996cbca66/services/alarm-server/src/main/java/org/phoebus/applications/alarm/server/Filter.java#L106-L119

https://control-system-studio.readthedocs.io/en/latest/core/formula/doc/index.html

So you should be able to use multiple combinations of PVs in expressions supported by that Formula class.

The name does have to match either a PV or component though. It will just be ignored if it doesn't.

@ZLLentz
Copy link
Member

ZLLentz commented Jan 29, 2025

Is this nalms:// protocol available for use in slam? Naively to me it looks like the applications are independent PyDM screens, but maybe I'm misunderstanding.

I think part of the issue on the photon side though is that the native EPICS alarms aren't necessarily what people want to be warned on, e.g. different users disagree on what counts as an issue for their different instruments.

For example, a steering mirror may have many valid states and therefore be NO_ALARM in many positions, but this mirror actually picks between TMO and RIX as destinations, so either instrument may want to see an alarm when the beam is sent to the other.

To this end the standard approach would be to create new PVs with unique alarm states to then ingest into NALMS, and this PR is a step in one option to automate this process.

@jbellister-slac
Copy link

Is this nalms:// protocol available for use in slam? Naively to me it looks like the applications are independent PyDM screens, but maybe I'm misunderstanding.

Yep, that is exactly correct. Not used in slam, for PyDM only.

To this end the standard approach would be to create new PVs with unique alarm states to then ingest into NALMS, and this PR is a step in one option to automate this process.

Yes, that makes sense! Just wanted to double check since NALMS does provide some flexibility in setting up additional conditions on alarms with enabling filters. But new PVs will work just fine and also be able to be queried outside of NALMS/PyDM if needed.

@KaushikMalapati
Copy link
Contributor Author

KaushikMalapati commented Feb 6, 2025

@jbellister-slac according to
https://control-system-studio.readthedocs.io/en/latest/core/pv/doc/#formulas
and
https://control-system-studio.readthedocs.io/en/latest/core/formula/doc/index.html#alarm

If I made an entry in one of our configs where the value for pv is
eq://majorAlarm(`PPS:NEH1:1:ST3K4INSUM`!=0&`ST1K4:TEST:MMS:STATE:GET_RBV`=2,"An arbitrary string")

would nalms deploy it as an alarm that has major severity when the formula evaluates to true that shows up in slam just like a normal pv alarm without any other work?

@jbellister-slac
Copy link

Hmm.. at a minimum I'd need to update slam to work with eq:// - which would be fine, it would not be difficult.

However, I'm not actually sure what happens if you use a non ca:// or pva:// for an alarm PV in Phoebus, I've never tried it before so would need to test to know whether it actually works or not.

@KaushikMalapati
Copy link
Contributor Author

Hmm.. at a minimum I'd need to update slam to work with eq:// - which would be fine, it would not be difficult.

However, I'm not actually sure what happens if you use a non ca:// or pva:// for an alarm PV in Phoebus, I've never tried it before so would need to test to know whether it actually works or not.

Where would slam need to be updated at? Doesn't it get all its information from kafka? Testing this first is agood idea.

@jbellister-slac
Copy link

I just need to fix how I parse the key returned from kafka. It was originally done in a channel-access-only world where I didn't have any consideration for any other protocol's prefix and the // gets in the way of later processing. It's simple and should be ready by Monday since it's something I needed to update anyway for pva support too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants