Skip to content

Commit 4e74846

Browse files
authored
Merge pull request #380 from tangkong/rel_v1.19.0
REL: v1.19.0
2 parents 63ea790 + 753d038 commit 4e74846

2 files changed

Lines changed: 65 additions & 39 deletions

File tree

docs/source/releases.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,28 @@ Release History
22
###############
33

44

5+
v1.19.0 (2024-04-15)
6+
====================
7+
8+
Features
9+
--------
10+
- Updates EpicsArch script, adding several debug/testin flags and ensuring
11+
information is up-to-date. Includes:
12+
13+
- ``update_file``: feature that updates EpicsArch based on current questionnaire
14+
- ``--softlink``: point arch file to new experiment via symbolic link
15+
- ``--level``: specify a debug level
16+
- ``--cds-items``: displays questionnaire data for a given run and experiment
17+
- ``--link-path``: allows user to provide custom filepath for softlinks
18+
- Adds load_level conf.yaml key for choosing the method used to gather happi devices
19+
20+
Contributors
21+
------------
22+
- c-tsoi
23+
- tangkong
24+
25+
26+
527
v1.18.5 (2023-09-14)
628
====================
729

hutch_python/epics_arch.py

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,18 @@ def _create_parser():
5555
help='Change the logging level, e.g. DEBUG to show the debug logging stream')
5656

5757
parser.add_argument('--cds-items', nargs=2, action='store', default=None,
58-
help="Pulls all data from CDS tab in the form of a dictionary. E.g.: xppx1003221 --cds-items run_xx experiment_name, where xx is the run number. This option will not automatically update the archfile.")
59-
60-
parser.add_argument('--softlink', '-sl', action='store_true', default=None, help=" create softlink for experiment. This is run after the archfile has been updated/created.")
61-
parser.add_argument('--link-path', '-sl_path', action='store', default=EPICS_ARCH_FILE_PATH, help="Provide user with option to supply custom path for softlink. Defaults to: /cds/group/pcds/dist/pds/{}/misc/.")
58+
help="Pulls all data from CDS tab in the form of a "
59+
"dictionary. E.g.: xppx1003221 --cds-items run_xx "
60+
"experiment_name, where xx is the run number. This option "
61+
"will not automatically update the archfile.")
62+
63+
parser.add_argument('--softlink', '-sl', action='store_true', default=None,
64+
help="create softlink for experiment. This is run after "
65+
"the archfile has been updated/created.")
66+
parser.add_argument('--link-path', '-sl_path', action='store',
67+
default=EPICS_ARCH_FILE_PATH,
68+
help="Provide user with option to supply custom path for "
69+
"softlink. Defaults to: /cds/group/pcds/dist/pds/{}/misc/.")
6270
return parser
6371

6472

@@ -78,7 +86,8 @@ def logger_setup(args):
7886
logger.setLevel(args.level)
7987

8088

81-
def create_arch_file(experiment, level=None, hutch=None, path=None, dry_run=False, cds_items=None, softlink=None, link_path=None):
89+
def create_arch_file(experiment, level=None, hutch=None, path=None, dry_run=False,
90+
cds_items=None, softlink=None, link_path=None):
8291
"""
8392
Create an epicsArch file for the experiment.
8493
@@ -163,14 +172,10 @@ def pull_cds_data(exp, run):
163172
Outputs
164173
-------
165174
PrettyTable visualization of cds objects
166-
167-
168-
"""
169-
"""
170-
pull run data from questionnaire api, then take the data and sort it
171-
create Pretty Table instance and if the values from the run data contain pcdssetup
172-
then put them into a seperate dictionary as they are cds items
173175
"""
176+
# pull run data from questionnaire api, then take the data and sort it
177+
# create PrettyTable instance and if the values from the run data contain
178+
# pcdssetup then put them into a seperate dictionary as they are cds items
174179
logger.debug('pull_cds_items(%s)', exp)
175180
client = QuestionnaireClient()
176181
logger.debug("in cds items, run numb:", str(run[1]))
@@ -182,14 +187,12 @@ def pull_cds_data(exp, run):
182187
if "pcdssetup" in keys:
183188
cds_dict[keys] = vals
184189

185-
"""
186-
names are as follows:
187-
pcdssetup-motors, pcdssetup-areadet, pcdssetup-ao, pcdssetup-devs
188-
pcdssetup-ps, pcdssetup-trig, pcdssetup-vacuum, pcdssetup-temp
190+
# names are as follows:
191+
# pcdssetup-motors, pcdssetup-areadet, pcdssetup-ao, pcdssetup-devs
192+
# pcdssetup-ps, pcdssetup-trig, pcdssetup-vacuum, pcdssetup-temp
189193

190-
iterate through all cds items and label them based on their type
191-
use the struct members to identify
192-
"""
194+
# iterate through all cds items and label them based on their type
195+
# use the struct members to identify
193196
displayList = []
194197
for k, v in cds_dict.items():
195198
if re.match('pcdssetup-motors.*-name', k):
@@ -224,21 +227,25 @@ def pull_cds_data(exp, run):
224227

225228
def create_softlink(experiment, link_path):
226229
"""
227-
This removes the softlink in the /cds/group/pcds/dist/pds/{}/misc/ and overwrites it with the new active experiment.
228-
230+
This removes the softlink in the /cds/group/pcds/dist/pds/{}/misc/ and
231+
overwrites it with the new active experiment.
229232
"""
230-
231233
# Defaults new softlink in /cds/group/pcds/dist/pds/{}/misc/
232234
if not os.path.exists(link_path):
233235
raise OSError('Path does not exist path: %s' % link_path)
234236

235-
subprocess.run(['ln', '-sf', link_path.format(experiment[0:3]) + 'epicsArch_' + experiment + '.txt', link_path.format(experiment[0:3]) + 'epicsArch_' + experiment[0:3].upper() + '_exp_specific.txt'])
237+
subprocess.run(['ln', '-sf', link_path.format(experiment[0:3]) + 'epicsArch_'
238+
+ experiment + '.txt', link_path.format(experiment[0:3])
239+
+ 'epicsArch_' + experiment[0:3].upper() + '_exp_specific.txt'])
236240

237241

238242
def check_for_duplicates(qs_data, af_data):
239243
"""
240-
Check for duplicate PVs in the questionnaire, the code already throws a warning for duplicate aliases.
241-
If duplicates (PV or Alias) are found in the questionnaire throw error and prompt user to fix and re-run. If they are found in the epicsArch file then step through each match and update accordingly.
244+
Check for duplicate PVs in the questionnaire, the code already throws a
245+
warning for duplicate aliases. If duplicates (PV or Alias) are found in the
246+
questionnaire throw error and prompt user to fix and re-run. If they are
247+
found in the epicsArch file then step through each match and update
248+
accordingly.
242249
243250
Parameters
244251
----------
@@ -254,15 +261,9 @@ def check_for_duplicates(qs_data, af_data):
254261
updated_arch_list : list
255262
Updated list containing sorted alias, PVs.
256263
"""
257-
258-
"""
259-
Part 1: Parse Data from the questionnaire and the archfile
260-
Part 2: Check the questionnaire for pv duplicates
261-
"""
262-
263264
# PART 1
264-
265-
# Convert lists to dictionaries to sort as a key - value pair while also removing any whitespice in the aliases.
265+
# Convert lists to dictionaries to sort as a key - value pair while also
266+
# removing any whitespice in the aliases.
266267

267268
# Questionnaire Data, removing whitespaces and newline chars
268269
qsDict = dict(zip(qs_data[::2], qs_data[1::2]))
@@ -286,7 +287,6 @@ def check_for_duplicates(qs_data, af_data):
286287
sorted_afDict = {}
287288

288289
# PART 2
289-
290290
# Check the questionaire for duplicate PVs
291291
# Making reverse multidict to help identify duplicate values in questionnaire.
292292
rev_keyDict = {}
@@ -295,11 +295,12 @@ def check_for_duplicates(qs_data, af_data):
295295

296296
pvDuplicate = [key for key, values in rev_keyDict.items() if len(values) > 1]
297297
# Looking for duplicates of PVs in the questionaire
298-
# also print out the alias for PV, change removing to warning operater to remove dup then rerun
298+
# also print out the alias for PV, change removing to warning operator to remove dup then rerun
299299
for dup in pvDuplicate:
300300
logger.debug("!Duplicate PV in questionnaire!:" + str(dup))
301301
for value in rev_keyDict[dup][1:]:
302-
logger.debug("Found PV duplicate(s) from questionnaire: " + value + ", " + sorted_qsDict[value])
302+
logger.debug("Found PV duplicate(s) from questionnaire: " + value
303+
+ ", " + sorted_qsDict[value])
303304
raise ValueError("Please remove duplicates and re-run script!")
304305

305306
# Check to see if the archfile has any data in it
@@ -308,20 +309,23 @@ def check_for_duplicates(qs_data, af_data):
308309
cleaned_qs_data = [x for item in sorted_qsDict.items() for x in item]
309310
return cleaned_qs_data
310311

311-
# Once we have cleared any duplicates in the questionnaire we moving on to updating values according to the which field matches.
312+
# Once we have cleared any duplicates in the questionnaire we moving on to
313+
# updating values according to the which field matches.
312314

313315
# Checking for matching PVs in questionnaire and archfile
314316
# if the PV matches update the alias by removing the old key and making a new one
315317
for (k, val) in sorted_qsDict.items():
316318
# this looks up the key in the af Dictionary by finding the value
317319
foundKey = get_key(val, sorted_afDict)
318320
if k in sorted_afDict:
319-
logger.debug("!Alias Match in questionnaire and archfile! Updating PV: " + k + ", " + sorted_qsDict[k])
321+
logger.debug("!Alias Match in questionnaire and archfile! Updating PV: "
322+
+ k + ", " + sorted_qsDict[k])
320323
sorted_afDict[k] = sorted_qsDict[k]
321324
elif foundKey:
322325
del sorted_afDict[foundKey]
323326
sorted_afDict[k] = val
324-
logger.debug("!PV Match in questionnaire and archfile! Updating Alias: " + k + ", " + val)
327+
logger.debug("!PV Match in questionnaire and archfile! Updating Alias: "
328+
+ k + ", " + val)
325329

326330
sorted_afDict = dict(sorted(sorted_afDict.items()))
327331
updated_arch_list = [x for item in sorted_afDict.items() for x in item]

0 commit comments

Comments
 (0)