Source code for gripspy.housekeeping.cc

"""
Module for analyzing card-cage information.
The information is currently split between CardCageControl and CardCageInfo because of the two types of packets.
This awkward implementation is likely to change in the future.
"""
from __future__ import division, absolute_import, print_function

import os
try:
    import cPickle as pickle
except ImportError:
    import pickle
import gzip

import numpy as np
import pandas as pd

from ..telemetry import parser_generator
from ..util.time import oeb2utc

__all__ = ['CardCageControl', 'CardCageInfo']


DIR = os.path.join(__file__, "..")


[docs]class CardCageControl(object): """Class for analyzing card-cage information from the housekeeping packet Parameters ---------- telemetry_file : str (or list) The name of the telemetry file to analyze. If None is specified, a save file must be specified. save_file : str The name of a save file from a telemetry file that was previously parsed. Notes ----- This implementation extracts only a subset of the information, and the API is subject to change. """ attributes_simple = ['systime', 'count_watchpup_reset', 'daq_running', 'last_cmdtype', 'mode_abort_ramp', 'mode_coincidence', 'mode_sample_last_edge', 'mode_veto_guard_ring_hv_hard', 'mode_veto_guard_ring_lv_hard', 'mode_veto_mult_trig_hard', 'mode_veto_shield_hard', 'mult_trig_threshold', 'window_coincidence', 'window_full_ramp', 'window_mult_trig_collect', 'window_mult_trig_veto', 'window_reset_adc', 'window_sample_hv', 'window_sample_lv', 'window_start_adc', 'window_trigger_wait'] # The following attributes need to be converted to seconds attributes_convert = ['period_counters', 'period_housekeeping', 'time_since_last_reset'] attributes_all = attributes_simple + attributes_convert def __init__(self, telemetry_file=None, save_file=None): if telemetry_file is not None: if isinstance(telemetry_file, list): self.filename = telemetry_file[0] else: self.filename = telemetry_file for attr in self.attributes_simple + self.attributes_convert: setattr(self, attr, [[], [], [], [], [], []]) count = 0 print("Parsing {0}".format(self.filename)) with open(self.filename, 'rb') as f: pg = parser_generator(f, filter_tmtype=0x02, verbose=True) for p in pg: if p['systemid'] & 0xF0 != 0x80: continue count += 1 cc_number = p['systemid'] & 0x0F for attr in self.attributes_simple: getattr(self, attr)[cc_number].append(p[attr]) # Convert from 10-ns steps to seconds for attr in self.attributes_convert: getattr(self, attr)[cc_number].append(p[attr] / 1e8) if count > 0: for i in range(6): for attr in self.attributes_simple + self.attributes_convert: getattr(self, attr)[i] = np.hstack(getattr(self, attr)[i]) print("Total packets: {0}".format(count)) else: print("No packets found") if isinstance(telemetry_file, list): for entry in telemetry_file[1:]: self.append(CardCageControl(entry)) elif save_file is not None: if isinstance(save_file, list): to_open = save_file[0] else: to_open = save_file print("Restoring {0}".format(to_open)) with gzip.open(to_open, 'rb') as f: try: saved = pickle.load(f, encoding='latin1') except TypeError: saved = pickle.load(f) self.filename = saved['filename'] for attr in self.attributes_all: setattr(self, attr, saved[attr]) if isinstance(save_file, list): for entry in save_file[1:]: self.append(CardCageControl(save_file=entry)) else: raise RuntimeError("Either a telemetry file or a save file must be specified") def __getitem__(self, key): if isinstance(key, int): if key >= 0 and key < 6: out_dict = {} for attr in self.attributes_all: if attr == 'systime': continue out_dict[attr] = getattr(self, attr)[key] return pd.DataFrame(out_dict, index=oeb2utc(self.systime[key])) else: raise IndexError("Only integers from 0 to 5 are valid") if isinstance(key, str): out_dict = {} for i in range(6): out_dict['CC' + str(i)] = pd.Series(getattr(self, key)[i], index=oeb2utc(self.systime[i])) return pd.DataFrame(out_dict) else: raise TypeError("Unsupported type")
[docs] def append(self, other): """Append the information in another CardCageControl instance""" self.filename = (self.filename if type(self.filename) == list else [self.filename]) +\ (other.filename if type(other.filename) == list else [other.filename]) for i in range(6): for attr in self.attributes_all: getattr(self, attr)[i] = np.hstack([getattr(self, attr)[i], getattr(other, attr)[i]])
[docs] def save(self, save_file=None, use_current_directory=False): """Save the parsed data for future reloading. The data is stored in gzip-compressed binary pickle format. Parameters ---------- save_file : str The name of the save file to create. If none is provided, the default is the name of the telemetry file with the extension ".cccontrol.pgz" appended if a single telemetry file is the source. use_current_directory : bool If True, remove any directory specification from `save_file` Notes ----- Save files may not be compatible between Python 2 and 3 """ if save_file is None: if type(self.filename) == str: to_save = self.filename + ".cccontrol.pgz" else: raise RuntimeError("The name for the save file needs to be explicitly specified here") else: to_save = save_file with gzip.open(to_save, 'wb') as f: print("Saving {0}".format(to_save)) out_dict = {'filename' : self.filename} for attr in self.attributes_all: out_dict[attr] = getattr(self, attr) pickle.dump(out_dict, f, 2)
[docs]class CardCageInfo(object): """Class for analyzing card-cage information from the counters packet Parameters ---------- telemetry_file : str (or list) The name of the telemetry file to analyze. If None is specified, a save file must be specified. save_file : str The name of a save file from a telemetry file that was previously parsed. Notes ----- This implementation extracts all of the information, but the API is subject to change. """ attributes_simple = ['systime', 'elapsed_time', 'busy_time', 'busy_count', 'veto_mult_trig_hard', 'veto_mult_trig_soft', 'busy_time_interface', 'busy_count_interface', 'busy_time_system', 'busy_count_system', 'guard_ring_lv_time', 'guard_ring_lv_count', 'guard_ring_hv_time', 'guard_ring_hv_count', 'shield_time', 'shield_count', 'reboot_count', 'event_count', 'veto_shield_soft', 'veto_guard_ring_lv_soft', 'veto_guard_ring_hv_soft', 'veto_shield_hard', 'veto_guard_ring_lv_hard', 'veto_guard_ring_hv_hard', 'dropped_event_count'] attributes_all = attributes_simple + ['busy_fraction'] def __init__(self, telemetry_file=None, save_file=None): if telemetry_file is not None: if isinstance(telemetry_file, list): self.filename = telemetry_file[0] else: self.filename = telemetry_file for attr in self.attributes_simple: setattr(self, attr, [[], [], [], [], [], []]) self.busy_fraction = [None]*6 count = 0 print("Parsing {0}".format(self.filename)) with open(self.filename, 'rb') as f: pg = parser_generator(f, filter_tmtype=0x08, verbose=True) for p in pg: if p['systemid'] & 0xF0 != 0x80: continue count += 1 cc_number = p['systemid'] & 0x0F for attr in self.attributes_simple: getattr(self, attr)[cc_number].append(p[attr]) if count > 0: for i in range(6): for attr in self.attributes_simple: getattr(self, attr)[i] = np.hstack(getattr(self, attr)[i]) self.busy_fraction[i] = self.busy_time[i] / self.elapsed_time[i] print("Total packets: {0}".format(count)) else: print("No packets found") if isinstance(telemetry_file, list): for entry in telemetry_file[1:]: self.append(CardCageInfo(entry)) elif save_file is not None: if isinstance(save_file, list): to_open = save_file[0] else: to_open = save_file print("Restoring {0}".format(to_open)) with gzip.open(to_open, 'rb') as f: try: saved = pickle.load(f, encoding='latin1') except TypeError: saved = pickle.load(f) self.filename = saved['filename'] for attr in self.attributes_all: setattr(self, attr, saved[attr]) if isinstance(save_file, list): for entry in save_file[1:]: self.append(CardCageInfo(save_file=entry)) else: raise RuntimeError("Either a telemetry file or a save file must be specified") def __getitem__(self, key): if isinstance(key, int): if key >= 0 and key < 6: out_dict = {} for attr in self.attributes_all: if attr == 'systime': continue out_dict[attr] = getattr(self, attr)[key] return pd.DataFrame(out_dict, index=oeb2utc(self.systime[key])) else: raise IndexError("Only integers from 0 to 5 are valid") if isinstance(key, str): out_dict = {} for i in range(6): out_dict['CC' + str(i)] = pd.Series(getattr(self, key)[i], index=oeb2utc(self.systime[i])) return pd.DataFrame(out_dict) else: raise TypeError("Unsupported type")
[docs] def append(self, other): """Append the information in another CardCageInfo instance""" self.filename = (self.filename if type(self.filename) == list else [self.filename]) +\ (other.filename if type(other.filename) == list else [other.filename]) for i in range(6): for attr in self.attributes_all: getattr(self, attr)[i] = np.hstack([getattr(self, attr)[i], getattr(other, attr)[i]])
[docs] def save(self, save_file=None, use_current_directory=False): """Save the parsed data for future reloading. The data is stored in gzip-compressed binary pickle format. Parameters ---------- save_file : str The name of the save file to create. If none is provided, the default is the name of the telemetry file with the extension ".ccinfo.pgz" appended if a single telemetry file is the source. use_current_directory : bool If True, remove any directory specification from `save_file` Notes ----- Save files may not be compatible between Python 2 and 3 """ if save_file is None: if type(self.filename) == str: to_save = self.filename + ".ccinfo.pgz" else: raise RuntimeError("The name for the save file needs to be explicitly specified here") else: to_save = save_file with gzip.open(to_save, 'wb') as f: print("Saving {0}".format(to_save)) out_dict = {'filename' : self.filename} for attr in self.attributes_all: out_dict[attr] = getattr(self, attr) pickle.dump(out_dict, f, 2)
def scan_for_daq_transitions(filename): """Utility function to quickly determine whether data acquisition is on in the detectors. A line is printed whenever data acquisition on any detector is toggled. Parameters ---------- filename : str or list One or more telemtry files. Notes ----- No attempt is made to convert gondola time to real time because this function is likely to be run on pre-flight data. It is recommended to use telemetry files with timestamps in the names. """ daq_running = [False] * 6 valid = [True] * 6 filelist = [filename] if type(filename) != list else filename for entry in filelist: with open(entry, 'rb') as f: pg = parser_generator(f, filter_tmtype=0x02, verbose=True) for p in pg: if p['systemid'] & 0xF0 != 0x80: continue cc_number = p['systemid'] & 0x0F valid[cc_number] = False if daq_running[cc_number] != p['daq_running']: daq_running[cc_number] = p['daq_running'] pretty = ['ON' if x else '??' if valid[i] else '--' for i, x in enumerate(daq_running)] print("{0} {1:15} {2:2} {3:2} {4:2} {5:2} {6:2} {7:2}".format(entry, p['systime'], *pretty))