Commit cbc4c320 authored by Antoine Laudrain's avatar Antoine Laudrain
Browse files

Merge branch 'MSO_dump_ttags' into 'master'

MSO: write event ttags to file

See merge request !22
parents f9d0e707 a40a4318
Pipeline #142082 passed with stages
in 3 minutes and 42 seconds
......@@ -31,9 +31,19 @@ The last directory in the tree is created if not existing (if the above one don'
A more complete example would look like:
```bash
python take_data.py /localscratch/data/210305_24403_cosmics/cosmics --nevents 500 --nruns 20 -c 1 3 4 --wait 1800 --log both
python take_data.py /localscratch/data/210305_24403_cosmics/cosmics --nevents 500 --nruns 20 -c 1 3 --wait 1800 --log both --ttags
```
which would output 20 groups of the following files (changing the timestamp for every run):
- `.../cosmics.yymmdd_HHMMSS.ttags.txt`, a plain text file containing the time tags of each trigger (time difference in seconds to the first trigger), one per line
- `.../cosmics.yymmdd_HHMMSS.CHAN1.raw`
- `.../cosmics.yymmdd_HHMMSS.CHAN1.dat`
- `.../cosmics.yymmdd_HHMMSS.CHAN3.raw`
- `.../cosmics.yymmdd_HHMMSS.CHAN3.dat`
plus some log files (one `.../cosmics.log` and 20 `.../cosmics.yymmdd_HHMMSS.log`).
### Run control options
......@@ -43,6 +53,9 @@ specifies from which oscilloscope channels the waveform is to be retrieved (seve
The number of events per run is set with the `--nevents <N>` option.
The number of runs is 1 by default but can be set using the `--nruns <N>` option.
The TTAGs dumping to disk is switched off by default, but can be activated with the `--ttags` switch.
The name of the output file is similar to the other output: `<path>/<run_name>.yymmdd_HHMMSS.ttags.txt`.
### Monitoring and logging options
......@@ -161,6 +174,17 @@ events = process_sequence(raw_data, npoints, yinc, yorigin)
```
### Reading the events time stamps
Since the time tags file is in plain text (one tag per line), retrieving the ttags is super easy:
```python
import numpy as np
ttags = np.loadtxt("path/to/data.yymmdd_HHMMSS.ttags.txt", dtype=np.float64)
# The default dtype should be float64 anyway, so this is optional.
```
### Plot various waveforms
To quickly explore data files, the following utility is provided: [`plot_waveforms.py`](./plot_waveforms.py).
......
......@@ -100,6 +100,7 @@ def info_acquire(instr):
print_module_query(instr, ':ACQuire:MODE?')
print_module_query(instr, ':ACQuire:SEGMented:COUNt?')
print_module_query(instr, ':ACQuire:SEGMented:INDex?')
print_module_query(instr, ':ACQuire:SEGMented:TTAGs?')
def info_waveform(instr):
......
......@@ -39,6 +39,7 @@ def setup_datataking(instr, n_wvfm):
log_write(instr, ':ACQ:SRATe:ANALog 5e9')
log_write(instr, ':ACQ:POINts:ANALog AUTO')
log_write(instr, ':ACQ:MODE SEGMented')
log_write(instr, 'ACQ:SEGM:TTAGs ON')
log_write(instr, f':ACQ:SEGMented:COUNt {n_wvfm}')
def setup_channel(instr, channel, offset=None, scale=None, skew=None):
......@@ -96,28 +97,52 @@ def write_output(instr, channel, outpath):
@param[in] outpath: string, see `main`
"""
logger.info("Writing output for CHAN%d", channel)
setup_readout(instr)
log_write(instr, f':WAV:SOURce CHAN{channel}')
outpath += f".CHAN{channel}"
outpath_pre = outpath + ".dat"
log_write(instr, 'WAV:PRE?')
preamble = instr.read_raw()
logger.info("Writing preamble file: %s", outpath_pre)
with open(outpath_pre, 'w') as outf:
outf.write(preamble.decode('ascii'))
logger.info("Written preamble file: %s", outpath_pre)
outpath_data = outpath + ".raw"
log_write(instr, 'WAV:DATA?')
data = instr.read_raw()
logger.info("Writing data file: %s", outpath_data)
with open(outpath_data, 'wb') as outf:
outf.write(data)
logger.info("Written data file : %s", outpath_data)
def write_ttags(instr, trigger_channel, outpath):
"""Retrieve the TTAGs from the trigger channel and dump to file.
@param[in] instr: instrument
@param[in] trigger_channel: string,
Name of the trigger channel, used to get the TTAGs info.
@param[in] outpath: string, see `main`
"""
logger.info("Writing ttags... (using %s)", trigger_channel)
setup_readout(instr)
log_write(instr, ':WAV:FORMat ASCii') # Overwrite format to be ascii.
log_write(instr, f':WAV:SOURce {trigger_channel}')
outpath += ".ttags.txt"
log_write(instr, ':WAV:SEGMented:XLISt? TTAG')
ttags = instr.read_raw().decode('ascii').rstrip('\n')
with open(outpath, 'w') as outf:
outf.write(ttags.replace(',', '\n'))
logger.info("Writing ttags file : %s", outpath)
###############################################################################
ALLOWED_LOGTYPE = ['no', 'single', 'each', 'both']
def main(outpath, nevents, nruns, read_channels, wait_seconds=60,
logtype="single", logfile_path=None, debug=False):
dump_ttags=False, logtype="single", logfile_path=None, debug=False):
"""Main callable: do the setup and loop over runs.
@param[in] outpath: string
......@@ -131,6 +156,8 @@ def main(outpath, nevents, nruns, read_channels, wait_seconds=60,
List of channel number to extract data from.
@param[in] wait_seconds: float, default: 60
Duration in seconds between two pollings for end of run.
@param[in] dump_ttags: bool, default = False
Switch to turn on dumping of TTAGs information.
@param[in] logtype: string, one of ALLOWED_LOGTYPE, default: 'single'.
How logging to file is handled:
- 'no' -> None
......@@ -238,11 +265,13 @@ def main(outpath, nevents, nruns, read_channels, wait_seconds=60,
setup_channel(instr, channel=4, offset=-100e-3, scale=50e-3, skew=0)
setup_trigger(instr, channel=1, level=-230e-3, slope='-')
# Use trigger channel for taking waveform counts and ttag info.
trigger_channel = process_query_answer(instr.query(':TRIGger:EDGE:SOURce?'))
logger.info("Default info will be taken from trigger channel: %s",
trigger_channel)
setup_datataking(instr, nevents)
setup_readout(instr)
# Setup one default waveform source (used to get how many waveform are
# recorded).
log_write(instr, f':WAVeform:SOURce CHAN{read_channels[0]}')
info_channels(instr)
info_timebase(instr)
......@@ -278,6 +307,10 @@ def main(outpath, nevents, nruns, read_channels, wait_seconds=60,
for irun in range(nruns):
outpath_time = outpath + "." + strftime("%y%m%d_%H%M%S")
# Setup one default waveform source (used to get how many waveform are
# recorded).
log_write(instr, f':WAVeform:SOURce {trigger_channel}')
if log_each_run:
# Add log file for this run.
file_handler = logging.FileHandler(outpath_time + ".log")
......@@ -301,6 +334,8 @@ def main(outpath, nevents, nruns, read_channels, wait_seconds=60,
break
log_write(instr, ':STOP')
if dump_ttags:
write_ttags(instr, trigger_channel, outpath_time)
for channel in read_channels:
write_output(instr, channel, outpath_time)
......@@ -317,12 +352,14 @@ EPILOG = """
Examples:
---------
python take_data data/cosmics --nevents 500 --nruns 5 -c 4
python take_data data/cosmics --nevents 500 --nruns 5 -c 4 --ttags
will take 5 runs of 500 events each data.
Data from channel 4 will be dumped to output files at the end of each run.
Each run outputs several files:
- The waveform time tags (time since first waveform in serie) is written as
plaintex in `data/cosmics.yymmdd_HHMMSS.ttags.txt`.
- The raw waveform (byte-string flux from the scope) is written in
`data/cosmics.yymmdd_HHMMSS.CHAN4.raw`.
- The metadata (preamble) as plaintex is written in
......@@ -354,6 +391,8 @@ def parse_args(argv):
metavar="SECONDS", type=float, default=60,
help="Poll if acquisition finished every SECONDS seconds. "
"Default: %(default)s seconds.")
parser.add_argument("--ttags", dest="dump_ttags", action="store_true",
help="Switch to store the TTAGs information to file (default is OFF).")
args_log = parser.add_argument_group("logging")
args_log.add_argument("--log", dest="logtype",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment