ahrs_calibration.py 5.41 KiB
#!/usr/bin/env python
# coding=utf-8
# vim: ts=4 sw=4 et
"""
Runs the AHRS calibration online.
Usage:
ahrs_calibration.py [options]
ahrs_calibration.py (-h | --help)
Options:
-l LIGIER_IP The IP of the ligier [default: 127.0.0.1].
-p LIGIER_PORT The port of the ligier [default: 5553].
-d DET_ID Detector ID [default: 29].
-o PLOT_DIR The directory to save the plot [default: plots].
-h --help Show this screen.
"""
from __future__ import division
from datetime import datetime
from collections import deque, defaultdict
from functools import partial
import io
import os
import time
import threading
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as md
import seaborn as sns
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
import km3pipe as kp
from km3pipe.io.daq import TMCHData
from km3modules.ahrs import fit_ahrs, get_latest_ahrs_calibration
import km3pipe.style
km3pipe.style.use('km3pipe')
class CalibrateAHRS(kp.Module):
def configure(self):
self.plots_path = self.require('plots_path')
det_id = self.require('det_id')
self.time_range = self.get('time_range', default=24 * 3) # hours
self.detector = kp.hardware.Detector(det_id=det_id)
self.dus = set()
self.clbmap = kp.db.CLBMap(det_oid=det_id)
self.cuckoo = kp.time.Cuckoo(60, self.create_plot)
self.cuckoo_log = kp.time.Cuckoo(10, print)
self.data = {}
self.queue_size = 5000
self.lock = threading.Lock()
self.index = 0
def _register_du(self, du):
"""Create data cache for DU"""
self.data[du] = {}
for ahrs_param in ('yaw', 'pitch', 'roll'):
self.data[du][ahrs_param] = defaultdict(
partial(deque, maxlen=self.queue_size))
self.data[du]['times'] = defaultdict(
partial(deque, maxlen=self.queue_size))
self.dus.add(du)
def process(self, blob):
self.index += 1
if self.index % 29 != 0:
return blob
now = datetime.utcnow()
tmch_data = TMCHData(io.BytesIO(blob['CHData']))
dom_id = tmch_data.dom_id
clb = self.clbmap.dom_ids[dom_id]
if clb.floor == 0:
self.log.info("Skipping base CLB")
return blob
yaw = tmch_data.yaw
calib = get_latest_ahrs_calibration(clb.upi, max_version=4)
if calib is None:
self.log.warning("No calibration found for CLB UPI '%s'", clb.upi)
return blob
du = clb.du
if du not in self.dus:
self._register_du(du)
cyaw, cpitch, croll = fit_ahrs(tmch_data.A, tmch_data.H, *calib)
self.cuckoo_log("DU{}-DOM{} (random pick): calibrated yaw={}".format(
clb.du, clb.floor, cyaw))
with self.lock:
self.data[du]['yaw'][clb.floor].append(cyaw)
self.data[du]['pitch'][clb.floor].append(cpitch)
self.data[du]['roll'][clb.floor].append(croll)
self.data[du]['times'][clb.floor].append(now)
self.cuckoo.msg()
return blob
def create_plot(self):
print(self.__class__.__name__ + ": updating plot.")
if self.time_range > 24:
xfmt = md.DateFormatter('%Y-%m-%d %H:%M')
else:
xfmt = md.DateFormatter('%H:%M')
xlim = (datetime.utcfromtimestamp(time.time() -
self.time_range * 60 * 60),
datetime.utcnow())
for du in self.dus:
data = self.data[du]
for ahrs_param in data.keys():
fig, ax = plt.subplots(figsize=(16, 6))
sns.set_palette("husl", 18)
ax.set_title("AHRS {} Calibration on DU{}\n{}".format(
ahrs_param, du, datetime.utcnow()))
ax.set_xlabel("UTC time")
ax.xaxis.set_major_formatter(xfmt)
ax.set_ylabel(ahrs_param)
with self.lock:
for floor in sorted(data[ahrs_param].keys()):
ax.plot(data['times'][floor],
data[ahrs_param][floor],
marker='.',
linestyle='none',
label="Floor {}".format(floor))
ax.set_xlim(xlim)
lgd = plt.legend(bbox_to_anchor=(1.005, 1),
loc=2,
borderaxespad=0.)
fig.tight_layout()
plt.savefig(os.path.join(
self.plots_path,
ahrs_param + '_calib_du{}.png'.format(du)),
bbox_extra_artists=(lgd, ),
bbox_inches='tight')
plt.close('all')
def main():
from docopt import docopt
args = docopt(__doc__)
det_id = int(args['-d'])
plots_path = args['-o']
ligier_ip = args['-l']
ligier_port = int(args['-p'])
pipe = kp.Pipeline()
pipe.attach(kp.io.ch.CHPump,
host=ligier_ip,
port=ligier_port,
tags='IO_MONIT',
timeout=60 * 60 * 24 * 7,
max_queue=2000)
pipe.attach(kp.io.daq.DAQProcessor)
pipe.attach(CalibrateAHRS, det_id=det_id, plots_path=plots_path)
pipe.drain()
if __name__ == '__main__':
main()