Skip to content

Commit edea708

Browse files
committed
MNT #168
1 parent 88e8d92 commit edea708

File tree

2 files changed

+322
-0
lines changed

2 files changed

+322
-0
lines changed

apstools/migration/config

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# ID @(#)getinfo.c 6.6 01/15/16 CSS
2+
# Device nodes
3+
SDEV_0 = /dev/ttyUSB0 19200 raw
4+
SDEV_1 = /dev/ttyUSB2 19200 raw
5+
#SDEV_2 = /dev/ttyUSB2 19200 raw
6+
VM_EPICS_M1 = 9idcLAX:m58:c0: 8
7+
VM_EPICS_M1 = 9idcLAX:m58:c1: 8
8+
VM_EPICS_M1 = 9idcLAX:m58:c2: 8
9+
VM_EPICS_M1 = 9idcLAX:mxv:c0: 8
10+
VM_EPICS_M1 = 9idcLAX:pi:c0: 4
11+
VM_EPICS_M1 = 9idcLAX:xps:c0: 8
12+
VM_EPICS_M1 = 9idcLAX:aero:c0: 1
13+
VM_EPICS_M1 = 9idcLAX:mxv:c1: 8
14+
VM_EPICS_M1 = 9idcLAX:aero:c1: 1
15+
VM_EPICS_M1 = 9idcLAX:aero:c2: 1
16+
PSE_MAC_MOT = kohzuE 1
17+
VM_EPICS_M1 = 9ida: 60
18+
VM_EPICS_M1 = 9idcLAX:aero:c3: 1
19+
VM_EPICS_SC = 9idcLAX:vsc:c0 16
20+
# CAMAC Slot Assignments
21+
# CA_name_unit = slot [crate_number]
22+
# Motor cntrl steps sign slew base backl accel nada flags mne name
23+
MOT000 = EPICS_M2:0/1 2000 1 2000 200 50 125 0 0x003 un0 unused0
24+
MOT001 = EPICS_M2:0/2 2000 1 2000 200 50 125 0 0x003 mx mx
25+
MOT002 = EPICS_M2:0/3 2000 1 2000 200 50 125 0 0x003 my my
26+
MOT003 = EPICS_M2:0/4 2000 1 2000 200 50 125 0 0x003 waxsx WAXS X
27+
MOT004 = EPICS_M2:0/5 2000 1 2000 200 50 125 0 0x003 ax ax
28+
MOT005 = EPICS_M2:0/6 2000 1 2000 200 50 125 0 0x003 gslity Gslit_Y
29+
MOT006 = EPICS_M2:0/7 2000 1 2000 200 50 125 0 0x003 az az
30+
MOT007 = EPICS_M2:0/8 2000 1 2000 200 50 125 0 0x003 un7 unused7
31+
MOT008 = EPICS_M2:1/1 2000 1 2000 200 50 125 0 0x003 msx msx
32+
MOT009 = EPICS_M2:1/2 2000 1 2000 200 50 125 0 0x003 msy msy
33+
MOT010 = EPICS_M2:1/3 2000 1 2000 200 50 125 0 0x003 art ART50-100
34+
MOT011 = EPICS_M2:1/4 2000 1 2000 200 50 125 0 0x003 asy asy
35+
MOT012 = EPICS_M2:1/5 2000 1 2000 200 50 125 0 0x003 gslitx Gslit_X
36+
MOT013 = EPICS_M2:1/6 2000 1 2000 200 50 125 0 0x003 tcam tcam
37+
MOT014 = EPICS_M2:1/7 2000 1 2000 200 50 125 0 0x003 camy cam_y
38+
MOT015 = EPICS_M2:1/8 2000 1 2000 200 50 125 0 0x003 tens Tension
39+
MOT016 = EPICS_M2:2/1 2000 1 2000 200 50 125 0 0x003 sx sx
40+
MOT017 = EPICS_M2:2/2 2000 1 2000 200 50 125 0 0x003 sy sy
41+
MOT018 = EPICS_M2:2/3 2000 1 2000 200 50 125 0 0x003 dx dx
42+
MOT019 = EPICS_M2:2/4 2000 1 2000 200 50 125 0 0x003 un19 un19
43+
MOT020 = EPICS_M2:2/5 2000 1 2000 200 50 125 0 0x003 uslvcen uslitvercen
44+
MOT021 = EPICS_M2:2/6 2000 1 2000 200 50 125 0 0x003 uslhcen uslithorcen
45+
MOT022 = EPICS_M2:2/7 2000 1 2000 200 50 125 0 0x003 uslvap uslitverap
46+
MOT023 = EPICS_M2:2/8 2000 1 2000 200 50 125 0 0x003 uslhap uslithorap
47+
MOT024 = EPICS_M2:3/1 2000 1 2000 200 50 125 0 0x003 pin_x pin_x
48+
MOT025 = EPICS_M2:3/2 2000 1 2000 200 50 125 0 0x003 pin_z pin_z
49+
MOT026 = EPICS_M2:3/3 2000 1 2000 200 50 125 0 0x003 gslout GSlit_outb
50+
MOTPAR:read_mode = 7
51+
MOT027 = EPICS_M2:3/4 2000 1 2000 200 50 125 0 0x003 gslinb GSlit_inb
52+
MOTPAR:read_mode = 7
53+
MOT028 = EPICS_M2:3/5 2000 1 2000 200 50 125 0 0x003 gsltop GSlit_top
54+
MOTPAR:read_mode = 7
55+
MOT029 = EPICS_M2:3/6 2000 1 2000 200 50 125 0 0x003 gslbot GSlit_bot
56+
MOTPAR:read_mode = 7
57+
MOT030 = EPICS_M2:3/7 2000 1 2000 200 50 125 0 0x003 un30 unused30
58+
MOT031 = EPICS_M2:3/8 2000 1 2000 200 50 125 0 0x003 pin_y pin_y
59+
MOT032 = EPICS_M2:4/1 2000 1 2000 200 50 125 0 0x003 a2rp USAXS.a2rp
60+
MOT033 = EPICS_M2:4/2 2000 1 2000 200 50 125 0 0x003 m2rp USAXS.m2rp
61+
MOT034 = EPICS_M2:4/3 2000 1 2000 200 50 125 0 0x003 msrp USAXS.msrp
62+
MOT035 = EPICS_M2:4/4 2000 1 2000 200 50 125 0 0x003 asrp USAXS.asrp
63+
MOT036 = EPICS_M2:5/1 2000 1 2000 200 50 125 0 0x003 un36 unused36
64+
MOT037 = EPICS_M2:5/2 2000 1 2000 200 50 125 0 0x003 un37 unused37
65+
MOT038 = EPICS_M2:5/3 2000 1 2000 200 50 125 0 0x003 mst mst
66+
MOT039 = EPICS_M2:5/4 2000 1 2000 200 50 125 0 0x003 ast ast
67+
MOT040 = EPICS_M2:5/5 2000 1 2000 200 50 125 0 0x003 msr msr
68+
MOT041 = EPICS_M2:5/6 2000 1 2000 200 50 125 0 0x003 asr asr
69+
MOT042 = EPICS_M2:5/7 2000 1 2000 200 50 125 0 0x003 un42 unused42
70+
MOT043 = EPICS_M2:5/8 2000 1 2000 200 50 125 0 0x003 un43 unused43
71+
MOT044 = EPICS_M2:6/1 2000 1 2000 200 50 125 0 0x003 ar ar
72+
MOT045 = EPICS_M2:7/1 2000 1 2000 200 50 125 0 0x003 un45 un45
73+
MOT046 = EPICS_M2:7/2 2000 1 2000 200 50 125 0 0x003 un46 un46
74+
MOT047 = EPICS_M2:7/3 2000 1 2000 200 50 125 0 0x003 un47 un47
75+
MOT048 = EPICS_M2:7/4 2000 1 2000 200 50 125 0 0x003 un48 un48
76+
MOT049 = EPICS_M2:7/5 2000 1 2000 200 50 125 0 0x003 un49 un49
77+
MOT050 = EPICS_M2:7/6 2000 1 2000 200 50 125 0 0x003 un50 un50
78+
MOT051 = EPICS_M2:7/7 2000 1 2000 200 50 125 0 0x003 un51 un51
79+
MOT052 = EPICS_M2:7/8 2000 1 2000 200 50 125 0 0x003 un52 un52
80+
MOT053 = EPICS_M2:8/1 2000 1 2000 200 50 125 0 0x003 ay ay
81+
MOT054 = EPICS_M2:9/1 2000 1 2000 200 50 125 0 0x003 dy dy
82+
MOT055 = MAC_MOT:0/0 2000 1 2000 200 50 125 0 0x003 en en
83+
MOTPAR:read_mode = 7
84+
MOT056 = EPICS_M2:10/43 2000 1 2000 200 50 125 0 0x003 InbMS MonoSl_inb
85+
MOT057 = EPICS_M2:10/44 2000 1 2000 200 50 125 0 0x003 OutMS MonoSl_out
86+
MOT058 = EPICS_M2:10/45 2000 1 2000 200 50 125 0 0x003 TopMS MonoSl_top
87+
MOT059 = EPICS_M2:10/46 2000 1 2000 200 50 125 0 0x003 BotMS MonoSl_bot
88+
MOT060 = EPICS_M2:11/1 2000 1 2000 200 50 125 0 0x003 mr mr
89+
# Counter ctrl unit chan scale flags mne name
90+
CNT000 = EPICS_SC 0 0 10000000 0x001 sec seconds
91+
CNT001 = EPICS_SC 0 1 1 0x002 I0 I0
92+
CNT002 = EPICS_SC 0 2 1 0x000 I00 I00
93+
CNT003 = EPICS_SC 0 3 1 0x000 upd2 USAXS_PD
94+
CNT004 = EPICS_SC 0 4 1 0x000 trd TR_diode
95+
CNT005 = EPICS_SC 0 5 1 0x000 I000 I000

apstools/migration/spec_config.py

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
read SPEC config file and convert to ophyd setup commands
5+
"""
6+
7+
8+
from collections import OrderedDict
9+
import re
10+
11+
12+
CONFIG_FILE = 'config'
13+
KNOWN_DEVICES = "PSE_MAC_MOT VM_EPICS_M1 VM_EPICS_SC".split()
14+
15+
16+
class SpecDeviceBase(object):
17+
"""
18+
SPEC configuration of a device, such as a multi-channel motor controller
19+
"""
20+
21+
def __init__(self, config_text):
22+
"""parse the line from the SPEC config file"""
23+
# VM_EPICS_M1 = 9idcLAX:m58:c0: 8
24+
self.name, args = config_text.split("=")
25+
prefix, num_channels = args.split()
26+
self.prefix = prefix
27+
self.index = None
28+
self.num_channels = int(num_channels)
29+
30+
def __str__(self):
31+
fmt = "SpecDeviceBase(index={}, name={}, prefix={}, num_channels={})"
32+
return fmt.format(
33+
self.index,
34+
self.name,
35+
self.prefix,
36+
self.num_channels
37+
)
38+
39+
40+
class ItemNameBase(object):
41+
def item_name_value(self, item):
42+
if hasattr(self, item):
43+
return f"{item}={self.__getattribute__(item)}"
44+
45+
46+
class SpecMotor(ItemNameBase):
47+
"""
48+
SPEC configuration of a motor channel
49+
"""
50+
51+
def __init__(self, config_text):
52+
"""parse the line from the SPEC config file"""
53+
# Motor cntrl steps sign slew base backl accel nada flags mne name
54+
# MOT002 = EPICS_M2:0/3 2000 1 2000 200 50 125 0 0x003 my my
55+
lr = config_text.split(sep="=", maxsplit=1)
56+
self.index = int(lr[0].strip("MOT"))
57+
58+
def pop_word(line, int_result=False):
59+
line = line.strip()
60+
pos = line.find(" ")
61+
l, r = line[:pos].strip(), line[pos:].strip()
62+
if int_result:
63+
l = int(l)
64+
return l, r
65+
66+
self.cntrl, r = pop_word(lr[1])
67+
self.steps, r = pop_word(r, True)
68+
self.sign, r = pop_word(r, True)
69+
self.slew, r = pop_word(r, True)
70+
self.base, r = pop_word(r, True)
71+
self.backl, r = pop_word(r, True)
72+
self.accel, r = pop_word(r, True)
73+
self.nada, r = pop_word(r, True)
74+
self.flags, r = pop_word(r)
75+
self.mne, self.name = pop_word(r)
76+
self.device = None
77+
self.pvname = None
78+
79+
def __str__(self):
80+
items = [self.item_name_value(k) for k in "index mne name".split()]
81+
txt = self.item_name_value("pvname")
82+
if txt is not None:
83+
items.append(txt)
84+
else:
85+
items.append(self.item_name_value("cntrl"))
86+
return "SpecMotor({})".format(", ".join(items))
87+
88+
def setDevice(self, devices):
89+
if self.cntrl.startswith("EPICS_M2"):
90+
device_list = devices.get("VM_EPICS_M1")
91+
if device_list is not None:
92+
uc_str = self.cntrl[len("EPICS_M2:"):]
93+
unit, chan = list(map(int, uc_str.split("/")))
94+
self.device = device_list[unit]
95+
self.pvname = "{}m{}".format(self.device.prefix, chan)
96+
97+
98+
class SpecCounter(ItemNameBase):
99+
"""
100+
SPEC configuration of a counter channel
101+
"""
102+
103+
def __init__(self, config_text):
104+
"""parse the line from the SPEC config file"""
105+
# # Counter ctrl unit chan scale flags mne name
106+
# CNT000 = EPICS_SC 0 0 10000000 0x001 sec seconds
107+
108+
def pop_word(line, int_result=False):
109+
line = line.strip()
110+
pos = line.find(" ")
111+
l, r = line[:pos].strip(), line[pos:].strip()
112+
if int_result:
113+
l = int(l)
114+
return l, r
115+
116+
l, r = pop_word(config_text)
117+
self.index = int(l.strip("CNT"))
118+
l, r = pop_word(r) # ignore "="
119+
self.ctrl, r = pop_word(r)
120+
self.unit, r = pop_word(r, True)
121+
self.chan, r = pop_word(r, True)
122+
self.scale, r = pop_word(r, True)
123+
self.flags, r = pop_word(r)
124+
self.mne, self.name = pop_word(r)
125+
self.device = None
126+
self.pvname = None
127+
128+
def __str__(self):
129+
items = [self.item_name_value(k) for k in "index mne name".split()]
130+
txt = self.item_name_value("pvname")
131+
if txt is not None:
132+
items.append(txt)
133+
else:
134+
items.append(self.item_name_value("ctrl"))
135+
return "SpecCounter({})".format(", ".join(items))
136+
137+
def setDevice(self, devices):
138+
if self.ctrl.startswith("EPICS_SC"):
139+
device_list = devices.get("VM_EPICS_SC")
140+
if device_list is not None:
141+
self.device = device_list[self.unit]
142+
# scalers are goofy, SPEC uses 0-based numbering, scaler uses 1-based
143+
self.pvname = "{}.S{}".format(self.device.prefix, self.chan+1)
144+
145+
146+
class SpecConfig(object):
147+
"""
148+
SPEC configuration
149+
"""
150+
151+
def __init__(self, config_file):
152+
self.config_file = config_file or CONFIG_FILE
153+
self.devices = OrderedDict()
154+
self.motors = OrderedDict()
155+
self.counters = OrderedDict()
156+
self.unhandled = []
157+
158+
def read_config(self, config_file=None):
159+
self.config_file = config_file or self.config_file
160+
with open(self.config_file, 'r') as f:
161+
for line in f.readlines():
162+
line = line.strip()
163+
164+
if line.startswith("#"):
165+
continue
166+
167+
word0 = line.split(sep="=", maxsplit=1)[0].strip()
168+
if word0 in KNOWN_DEVICES:
169+
device = SpecDeviceBase(line)
170+
if device.name not in self.devices:
171+
self.devices[device.name] = []
172+
# 0-based numbering
173+
device.index = len(self.devices[device.name])
174+
self.devices[device.name].append(device)
175+
elif word0 == "MOTPAR:read_mode":
176+
self.unhandled.append(line)
177+
elif re.match("CNT\d*", line) is not None:
178+
counter = SpecCounter(line)
179+
counter.setDevice(self.devices)
180+
self.counters[counter.mne] = counter
181+
elif re.match("MOT\d*", line) is not None:
182+
motor = SpecMotor(line)
183+
motor.setDevice(self.devices)
184+
self.motors[motor.mne] = motor
185+
else:
186+
self.unhandled.append(line)
187+
188+
189+
def create_ophyd_setup(spec_config):
190+
# ophyd configures the counters by device, not by channel
191+
device_list = spec_config.devices.get("VM_EPICS_SC")
192+
if device_list is not None:
193+
import_shown = False
194+
for device in device_list:
195+
mne = "scaler{}".format(device.index)
196+
if not import_shown:
197+
print("from ophyd.scaler import ScalerCH")
198+
import_shown = True
199+
print("{} = {}('{}', name='{}')".format(
200+
mne, "ScalerCH", device.prefix, mne))
201+
chans = []
202+
for counter in spec_config.counters.values():
203+
if counter.device == device:
204+
key = "chan%02d" % (counter.chan+1)
205+
print("# {} : {} ({})".format(key, counter.mne, counter.name))
206+
chans.append(key)
207+
if len(chans) > 0:
208+
print("{}.channels.read_attrs = {}".format(mne, chans))
209+
210+
mne_list = []
211+
for mne, motor in sorted(spec_config.motors.items()):
212+
if motor.pvname is not None:
213+
mne = mne.replace(".", "_")
214+
mne_list.append(mne)
215+
print("{} = {}('{}', name='{}') # {}".format(
216+
mne, "EpicsMotor", motor.pvname, mne, motor.name))
217+
218+
219+
220+
def main():
221+
spec_cfg = SpecConfig(CONFIG_FILE)
222+
spec_cfg.read_config()
223+
create_ophyd_setup(spec_cfg)
224+
225+
226+
if __name__ == "__main__":
227+
main()

0 commit comments

Comments
 (0)