From a0acd1e5b43434289863134dff96e4c53c2896f1 Mon Sep 17 00:00:00 2001 From: Ferdi Franceschini Date: Thu, 21 Aug 2014 10:19:55 +1000 Subject: [PATCH] SICS-458: Add dsc command to run a DSC acquisition on Quokka. Also added dsc.py utility which finds the start of a DSC profile in hdf files. --- .../sans/config/commands/growfile.tcl | 96 +++++++++++++++++++ .../instrument/sans/quokka_configuration.tcl | 1 + site_ansto/instrument/sans/util/dsc.py | 94 ++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 site_ansto/instrument/sans/config/commands/growfile.tcl create mode 100755 site_ansto/instrument/sans/util/dsc.py diff --git a/site_ansto/instrument/sans/config/commands/growfile.tcl b/site_ansto/instrument/sans/config/commands/growfile.tcl new file mode 100644 index 00000000..b92c8703 --- /dev/null +++ b/site_ansto/instrument/sans/config/commands/growfile.tcl @@ -0,0 +1,96 @@ +# \file Implements 'dsc actime interval' command. +set GROWFILE_STATE "DISABLED" +set growfileSaveIndex 0 + + +proc doGrowFile {} { + global GROWFILE_STATE + global growfileSaveIndex + +# Reset the GROWFILE_STATE variable in case some naughty user sets it directly + set GROWFILE_STATE "ENABLED" + set HMSTATE [SplitReply [hmm configure daq]] + set FSTATE [SplitReply [file_status]] +# broadcast CALLED: [info level 0], HMSTATE = $HMSTATE, FSTATE = $FSTATE + if { $FSTATE != "UNKNOWN" && $FSTATE != "OPEN" && $HMSTATE == "Started"} { +# broadcast growfile $growfileSaveIndex + save $growfileSaveIndex "growfile" + incr growfileSaveIndex + } else { + if {$growfileSaveIndex == 0} { + broadcast ERROR: GROWFILE HMSTATE = $HMSTATE, FSTATE = $FSTATE. The histmem must be running and you must create a newfile before calling "growfile" + } else { + broadcast STOP GROWFILE Acquisition finished. HMSTATE = $HMSTATE, FSTATE = $FSTATE. + save $growfileSaveIndex "growfile" + newfile clear + broadcast Saved [hval /experiment/file_name] + } + set growfileSaveIndex 0 + sicspoll del doGrowFile + set GROWFILE_STATE "DISABLED" + hsetprop /instrument/detector/hmm mutable true + } +} +publish doGrowFile user + + +proc growfile { {interval 300} } { + global GROWFILE_STATE + global growfileSaveIndex + + set GROWFILE_STATE "DISABLED" + set growfileSaveIndex 0 + + set as_error 0 + + set myrights [set_rights manager] + if {$myrights == -1} { + return -code error "ERROR: You are not authorized for this operation" + } + set interval [string tolower $interval] + if {$interval == "check" || $interval == "status"} { + if { $GROWFILE_STATE == "ENABLED" } { + return "GROWFILE $GROWFILE_STATE [sicspoll intervall doGrowFile]" + } else { + return "GROWFILE $GROWFILE_STATE" + } + } elseif {[string is integer $interval]} { + if {$interval <= 0} { + if { $GROWFILE_STATE == "ENABLED" } { + sicspoll del doGrowFile + set GROWFILE_STATE "DISABLED" + } + } else { + if {$GROWFILE_STATE == "DISABLED"} { + sicspoll add doGrowFile script $interval doGrowFile +# sicspoll listen # WARNING:When the listening client exits it leaves SICSPOLL task with a corrupt connection object. + set GROWFILE_STATE "ENABLED" + } else { + sicspoll intervall doGrowFile $interval + } + } + } else { + set as_error 1 + } + + set_rights $myrights + + if {$as_error} { + return -code error "ERROR: Invalid argument in '[info level 0]', should be an integer or 'check'" + } +} +publish growfile user + +# \brief Run histogram for the specified time and save XY binned data at the given interval. +# \param actime Acquisition time in seconds. +# \param saveint Save interval in seconds. +proc dsc {actime saveint} { + hsetprop /instrument/detector/hmm mutable false + newfile HISTOGRAM_XY + histmem mode time + histmem preset $actime + histmem start + growfile $saveint +} + +publish dsc user diff --git a/site_ansto/instrument/sans/quokka_configuration.tcl b/site_ansto/instrument/sans/quokka_configuration.tcl index 6bdce7e5..3bf7f0d0 100644 --- a/site_ansto/instrument/sans/quokka_configuration.tcl +++ b/site_ansto/instrument/sans/quokka_configuration.tcl @@ -73,6 +73,7 @@ fileeval $cfPath(environment)/sct_antonparr_MCR500.tcl fileeval $cfPath(beamline)/spin_flipper.tcl fileeval $cfPath(commands)/pulser.tcl fileeval $cfPath(commands)/hvcommands.tcl +fileeval $cfPath(commands)/growfile.tcl source gumxml.tcl diff --git a/site_ansto/instrument/sans/util/dsc.py b/site_ansto/instrument/sans/util/dsc.py new file mode 100755 index 00000000..379900f2 --- /dev/null +++ b/site_ansto/instrument/sans/util/dsc.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# vim: ft=python ts=8 sts=4 sw=4 expandtab autoindent smartindent +""" Find the trigger time for Differenctial Scanning Calorimetry data in nx.hdf files. """ + +import sys +import os +import h5py +import argparse +import time +from collections import defaultdict + +class SkipFile(BaseException): + """This exception should be raised to skip processing a file""" + pass + +PARSER = argparse.ArgumentParser( + description = """Report the time offset for the start of the DSC profile relative to the start time of the histogram data. + This program can process multiple hdf files by specifying the path to the first file and the number of files to process. + You can also speficy a list of 'file_path numfile' pairs.""", + usage='dsc file_path numfile {file_path numfile}' +) +PARSER.add_argument('files', nargs='+', help = 'List of "file_path numfile" pairs') +ARGS = PARSER.parse_args() + +FAILS = defaultdict(list) +for startfile, num in zip(ARGS.files[0::2], ARGS.files[1::2]): + numfiles = int(num) + hfdir = os.path.dirname(startfile) + hfbase = os.path.basename(startfile) + idx = hfbase.find('.') + startFID = hfbase[:idx] + ext = hfbase[idx:] + idnum = int(startFID[3:]) + inst_abname = hfbase[:3] + + hfval = {} + print + for i in range(numfiles): + try: + currid = idnum + i + fileID = inst_abname + '%07d' % currid + if (hfdir == ''): + nxfile = fileID + ext + else: + nxfile = hfdir + '/' + fileID + ext + + try: + hf = h5py.File(nxfile, 'r') + except: + FAILS['badfile'].append(nxfile) + continue + + if (hfbase.startswith('QKK')): + rootpath = fileID + '/' + else: + rootpath = 'entry1/' + + for dpath in ['time_stamp', 'instrument/detector/start_time', 'sample/dsc_val']: + dscpath = rootpath + dpath + if dscpath in hf: + hfval[dpath] = hf[dscpath][:] + else: + FAILS['badpath:{0}'.format(dpath)].append(nxfile) + hf.close() + raise SkipFile + + print fileID + datiter = {} + dat_hasnext = 0 + time_tuple = time.strptime(hf[rootpath + 'start_time'][0], '%Y-%m-%d %H:%M:%S') + hfval['time_stamp'] += time.mktime(time_tuple) + hfval['time_stamp'] -= hfval['instrument/detector/start_time'] + dsc0 = hfval['sample/dsc_val'][0] + no_transition = True + for i in range(1, len(hfval['sample/dsc_val'][1:])): + dsc1 = hfval['sample/dsc_val'][i] + if abs(dsc1 - dsc0) > 1.9: + no_transition = False + msg = 'dsc_val transition from {dsc0} to {dsc1} volts at {time} seconds from detector start time, array index = {index}' + print msg.format(dsc0=dsc0, dsc1=dsc1, time=hfval['time_stamp'][i], index=i) + dsc0 = dsc1 + + if no_transition: + print 'dsc_val no transition' + + print + hf.close() + except SkipFile: + continue + +for k in FAILS.keys(): + if (len(FAILS[k])): + print >> sys.stderr, 'Skipped following files. Reason = ', k + print >> sys.stderr, FAILS[k]