Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • iain.morton/locklost
  • oli.patane/locklost-olifork
  • timothy.ohanlon/locklost
  • benjaminrobert.mannix/locklost
  • austin.jennings/locklost
  • camilla.compton/locklost
  • arnaud.pele/locklost
  • yamamoto/locklost
  • marc.lormand/locklost
  • saravanan.tiruppatturrajamanikkam/locklost
  • nikhil-mukund/locklost
  • patrick.godwin/locklost
  • yannick.lecoeuche/locklost
  • jameson.rollins/locklost
14 results
Show changes
Showing
with 548 additions and 102 deletions
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import matplotlib.patches as mpatches
from gwpy.segments import Segment
from .. import logger
from .. import config
from .. import data
from .. import plotutils
##############################################
itmx = mpatches.Patch(color='#F05039', label='ITMX')
itmy = mpatches.Patch(color='#EEBAB4', label='ITMY')
etmx = mpatches.Patch(color='#1F449C', label='ETMX')
etmy = mpatches.Patch(color='#7CA1CC', label='ETMY')
tag = mpatches.Patch(color='k', label='Tag Threshold')
def plot_color(string):
if 'ITMX' in string:
return '#F05039'
elif 'ITMY' in string:
return '#EEBAB4'
elif 'ETMX' in string:
return '#1F449C'
else:
return '#7CA1CC'
def check_violin(event):
"""Checks violin 1st, 2nd, and 3rd order violin modes
"""
if config.IFO == 'H1':
logger.info('NOT SET UP FOR LHO')
plotutils.set_rcparams()
mod_window = [config.VIOLIN_SEARCH_WINDOW[0], config.VIOLIN_SEARCH_WINDOW[1]]
segment = Segment(mod_window).shift(int(event.gps))
VIOLIN_channels = data.fetch(config.VIOLIN_CHANNELS, segment)
saturating = False
for buf in VIOLIN_channels:
srate = buf.sample_rate
t = np.arange(segment[0], segment[1], 1/srate)
idxs = ((t-event.gps) < -2)
if np.max(buf.data[idxs]) > config.VIOLIN_SAT_THRESH:
saturating = True
if saturating:
# ADD H1 code here
if config.IFO == 'L1':
if event.transition_index[0] >= 1020:
event.add_tag('VIOLIN')
else:
if config.IFO == 'L1':
logger.info('VIOLINS are ok')
gs = gridspec.GridSpec(2, 4)
gs.update(wspace=0.5)
fig = plt.figure(figsize=(22*3, 16*3))
ax1 = fig.add_subplot(gs[0, :2])
ax2 = fig.add_subplot(gs[1, :2])
ax3 = fig.add_subplot(gs[1, 2:])
for idx, buf in enumerate(VIOLIN_channels):
srate = buf.sample_rate
t = np.arange(segment[0], segment[1], 1/srate)
if any(substring in buf.channel for substring in ['MODE3', 'MODE4', 'MODE5', 'MODE6']):
ax1.plot(
t-event.gps,
buf.data,
label=buf.channel,
alpha=0.8,
lw=8,
color=plot_color(buf.channel),
)
elif any(substring in buf.channel for substring in ['MODE11', 'MODE12', 'MODE13', 'MODE14']):
ax2.plot(
t-event.gps,
buf.data,
label=buf.channel,
alpha=0.8,
lw=8,
color=plot_color(buf.channel),
)
else:
ax3.plot(
t-event.gps,
buf.data,
label=buf.channel,
alpha=0.8,
lw=8,
color=plot_color(buf.channel),
)
if config.IFO == 'L1':
ax1.axhline(
config.VIOLIN_SAT_THRESH,
linestyle='--',
color='black',
label='Violin threshold',
lw=5,
)
ax2.axhline(
config.VIOLIN_SAT_THRESH,
linestyle='--',
color='black',
label='Violin threshold',
lw=5,
)
ax3.axhline(
config.VIOLIN_SAT_THRESH,
linestyle='--',
color='black',
label='Violin threshold',
lw=5,
)
ax1.set_xlabel('Time [s] since lock loss at {}'.format(event.gps), labelpad=10)
ax2.set_xlabel('Time [s] since lock loss at {}'.format(event.gps), labelpad=10)
ax3.set_xlabel('Time [s] since lock loss at {}'.format(event.gps), labelpad=10)
ax1.set_ylabel('Violin Magnitude [log]')
ax2.set_ylabel('Violin Magnitude [log]')
ax3.set_ylabel('Violin Magnitude [log]')
ax1.set_xlim(t[0]-event.gps, t[-1]-event.gps)
ax2.set_xlim(t[0]-event.gps, t[-1]-event.gps)
ax3.set_xlim(t[0]-event.gps, t[-1]-event.gps)
'''
if config.IFO == 'L1':
ax1.set_ylim(-18, -14)
ax2.set_ylim(-18, -14)
ax3.set_ylim(-18, -14)
'''
ax1.legend(handles=[itmx, itmy, etmx, etmy, tag], loc='best')
ax2.legend(handles=[itmx, itmy, etmx, etmy, tag], loc='best')
ax3.legend(handles=[itmx, itmy, etmx, etmy, tag], loc='best')
# ax1.legend(loc='best')
ax1.set_title('1st Order Violins')
ax2.set_title('2nd Order Violins')
ax3.set_title('3rd Order Violins')
ax1.grid()
ax2.grid()
ax3.grid()
outfile_plot = 'VIOLIN_monitor.png'
outpath_plot = event.path(outfile_plot)
fig.savefig(outpath_plot, bbox_inches='tight')
import os
import logging
import numpy as np
import matplotlib.pyplot as plt
from gwpy.segments import Segment
from .. import logger
from .. import config
from .. import data
from .. import plotutils
##############################################
def check_wind(event):
"""Checks for elevated windspeed.
......@@ -40,9 +41,9 @@ def check_wind(event):
if windy:
event.add_tag('WINDY')
else:
logging.info("wind speed below threshold")
logger.info("wind speed below threshold")
fig, ax = plt.subplots(1, figsize=(22,16))
fig, ax = plt.subplots(1, figsize=(22, 16))
for buf in wind_channels:
srate = buf.sample_rate
t = np.arange(segment[0], segment[1], 1/srate)
......@@ -66,7 +67,7 @@ def check_wind(event):
ax.grid()
ax.set_xlabel('Time [s] since lock loss at {}'.format(event.gps), labelpad=10)
ax.set_ylabel('Velocity [mph]')
ax.set_ylim(0, max_windspeed+1)
# ax.set_ylim(0, max_windspeed+1)
ax.set_xlim(t[0]-event.gps, t[-1]-event.gps)
ax.legend(loc='best')
ax.set_title('End/corner station wind speeds', y=1.04)
......
import os
import argparse
import logging
import importlib
from gwpy.segments import Segment, SegmentList
from . import set_signal_handlers
from . import config_logger
from . import logger
from . import config
from . import data
from .event import LocklossEvent
from . import segments
from . import condor
##################################################
def search_buf(buf, previous=None, event_callback=None):
"""Search for lock lock events in buffer
......@@ -27,18 +30,18 @@ def search_buf(buf, previous=None, event_callback=None):
nevents = 0
for time, pval, val in data.gen_transitions(buf, previous):
trans = (int(pval), int(val))
logging.debug("transition: {:0.3f} {}->{}".format(time, trans[0], trans[1]))
logger.debug("transition: {:0.3f} {}->{}".format(time, trans[0], trans[1]))
if val not in lockloss_indices:
continue
logging.info("lockloss found: {} {}->{}".format(time, *trans))
logger.info("lockloss found: {} {}->{}".format(time, *trans))
nevents += 1
try:
event = LocklossEvent.create(time, trans)
except OSError as e:
logging.info(e)
logger.info(e)
event = LocklossEvent(time)
if event_callback:
logging.info("executing event callback: {}({})".format(
logger.info("executing event callback: {}({})".format(
event_callback.__name__, event.id))
event_callback(event)
return nevents
......@@ -48,29 +51,32 @@ def search(segment):
"""Search segment for events
"""
logging.debug("searching segment {}...".format(segment))
logger.debug("searching segment {}...".format(segment))
channel = config.GRD_STATE_N_CHANNEL
buf = data.fetch([channel], segment)[0]
nevents = search_buf(buf)
segments.write_segments(config.SEG_DIR, [(int(buf.gps_start), int(buf.gps_stop))])
logging.info("{} events found".format(nevents))
logger.info("{} events found".format(nevents))
def search_iterate(segment=None, event_callback=None, stat_file=None):
"""Iterative search for events (NDS-only)
"""
channel = config.GRD_STATE_N_CHANNEL
if segment:
logging.info("searching segment {}...".format(segment))
logger.info(f"searching channel {channel} segment {segment}...")
else:
logging.info("searching online...")
logger.info(f"searching channel {channel} online...")
previous = None
nevents = 0
nbufs = 0
progress = None
channel = config.GRD_STATE_N_CHANNEL
for bufs in data.nds_iterate([channel], start_end=segment):
buf = bufs[0]
if previous is None:
logger.info("initial state: {} @{:0.3f}".format(
buf.data[0], buf.gps_start))
nevents += search_buf(
buf,
previous=previous,
......@@ -93,11 +99,12 @@ def search_iterate(segment=None, event_callback=None, stat_file=None):
if segment is None:
raise RuntimeError("NDS iteration returned unexpectedly.")
else:
logging.info("{} events found".format(nevents))
logger.info("{} events found".format(nevents))
# segments.compress_segdir(config.SEG_DIR)
##################################################
def _parser_add_arguments(parser):
from .util import GPSTimeParseAction
parser.add_argument('start', action=GPSTimeParseAction,
......@@ -137,9 +144,9 @@ def main(args=None):
completed_segs = segments.load_segments(config.SEG_DIR)
reduced_segs = SegmentList([full_seg]) - completed_segs
if not reduced_segs:
logging.info("All segments analyzed")
logger.info("All segments analyzed")
raise SystemExit()
logging.debug("segments: {}".format(reduced_segs))
logger.debug("segments: {}".format(reduced_segs))
def condor_args_gen():
for s in segments.slice_segments(
......@@ -177,10 +184,7 @@ def main(args=None):
# direct execution of this module intended for condor jobs
if __name__ == '__main__':
set_signal_handlers()
logging.basicConfig(
level='DEBUG',
format=config.LOG_FMT,
)
config_logger()
parser = argparse.ArgumentParser()
parser.add_argument('start', type=int,
help="search start time")
......
import os
import shutil
import logging
from gwpy.segments import Segment, SegmentList
from . import logger
def load_segments(segdir, intersect=None):
"""Load segments from directory
......@@ -16,7 +17,7 @@ def load_segments(segdir, intersect=None):
for i, sf in enumerate(os.listdir(segdir)):
s, e = map(int, sf.split('-'))
seglist.append(Segment(s, e))
logging.debug("{} segments loaded".format(i+1))
logger.debug("{} segments loaded".format(i+1))
return seglist.coalesce()
......@@ -66,16 +67,14 @@ def compress_segdir(segdir):
"""
if not os.path.exists(segdir):
#raise RuntimeError("segdir does not exist")
logging.warning("segdir does not exist")
logger.warning("segdir does not exist")
return
tmpdir = segdir+'.tmp'
if os.path.exists(tmpdir):
#raise RuntimeError("segdir compression in progress")
logging.warning("segdir compression in progress, skipping")
logger.warning("segdir compression in progress, skipping")
return
logging.info("compressing segdir: {}".format(segdir))
logger.info("compressing segdir: {}".format(segdir))
shutil.move(segdir, tmpdir)
n = write_segments(segdir, load_segments(tmpdir))
logging.debug("{} segments written".format(n))
logger.debug("{} segments written".format(n))
shutil.rmtree(tmpdir)
This diff is collapsed.
......@@ -17,6 +17,7 @@ WEB_SCRIPT = config.WEB_ROOT + '/index.cgi'
##################################################
def query_parse(query):
"""parse query and return dictionary
......@@ -46,8 +47,7 @@ def query_parse(query):
if not val:
continue
if key == 'tag':
val = [tag for tag in bottle.request.query.getall('tag') \
if isinstance(tag, str)]
val = [tag for tag in bottle.request.query.getall('tag') if isinstance(tag, str)]
try:
out_query[key] = val_conv[key](val)
except ValueError:
......@@ -61,7 +61,7 @@ def online_status():
"""HTML-formatted online status information
"""
stat_file = os.path.join(config.CONDOR_ONLINE_DIR, 'stat')
stat_file = config.ONLINE_STAT_FILE
if not os.path.exists(stat_file):
return '<span style="color:red">ONLINE ANALYSIS NOT RUNNING</span>'
stat = os.stat(stat_file)
......@@ -73,18 +73,18 @@ def online_status():
color = 'red'
else:
color = 'green'
wcroot = os.path.join(config.WEB_ROOT, 'events', '.condor_online')
return '<span style="color: {}">online last update: {:0.1f} min ago ({}) [<a href="{}">log</a>]</span>'.format(
return '<span style="color: {}">online last update: {:0.1f} min ago ({})</span>'.format(
color,
tsecs/60,
dt,
os.path.join(wcroot, 'out'),
)
##################################################
app = bottle.Bottle()
@app.route("/")
@app.route("/tag/<tag>")
def index(tag='all'):
......@@ -94,7 +94,7 @@ def index(tag='all'):
gps = bottle.request.query.get('event')
try:
event = LocklossEvent(gps)
except (ValueError, OSError) as e:
except (ValueError, OSError):
bottle.abort(404, {'error': {'code': 404, 'message': 'Unknown event: {}'.format(gps)}})
return event.to_dict()
......@@ -109,7 +109,7 @@ def index(tag='all'):
gps = bottle.request.query.get('event')
try:
event = LocklossEvent(gps)
except (ValueError, OSError) as e:
except (ValueError, OSError):
bottle.abort(404, 'Unknown event: {}'.format(gps))
sat_channels = []
......@@ -143,6 +143,7 @@ def index(tag='all'):
query=query,
)
@app.route("/summary")
@app.route("/summary/<epoch>")
def summary_route(epoch=None):
......@@ -157,6 +158,7 @@ def summary_route(epoch=None):
epoch=epoch,
)
@app.route("/event/<gps>")
def event_route(gps):
bottle.redirect('{}?event={}'.format(WEB_SCRIPT, gps))
......@@ -181,5 +183,6 @@ def json_route(tag='all'):
##################################################
if __name__ == '__main__':
bottle.run(app, server='cgi', debug=True)
This diff is collapsed.
import os
from datetime import datetime
from .. import config
from ..event import find_events
##################################################
def event_gen(query):
"""generate events from query
......
[flake8]
ignore = E226,E501
exclude = locklost/plugins/__init__.py
......@@ -9,21 +9,21 @@ setup(
'write_to': 'locklost/version.py',
},
name = 'locklost',
description = 'LIGO lock loss tracking and analysis',
author = 'Jameson Graef Rollins',
author_email = 'jameson.rollins@ligo.org',
url = 'https://git.ligo.org/jameson.rollins/locklost.git',
license = 'GPLv3+',
name='locklost',
description='LIGO lock loss tracking and analysis',
author='Jameson Graef Rollins',
author_email='jameson.rollins@ligo.org',
url='https://git.ligo.org/jameson.rollins/locklost.git',
license='GPLv3+',
packages = [
packages=[
'locklost',
'locklost.plugins',
'locklost.web',
'locklost.web.templates',
],
package_data = {
package_data={
'locklost.web.templates': ['*.tpl'],
},
......
This diff is collapsed.
#!/bin/bash
tail -F ~/events/.condor_online/{log,out} | \
ts %Y-%m-%d_%H:%M:%S | \
tee --append ~/online.log
[Unit]
Description=Locklost analyze backfill
[Service]
Type=oneshot
# use system environment settings, for e.g. NDSSERVER, if available
EnvironmentFile=-/etc/sysconfig/ligo
EnvironmentFile=%h/config
Environment=LOG_FMT_NOTIME=t
ExecStart=%h/opt/locklost/bin/locklost analyze --condor '2 weeks ago' now
TimeoutSec=300
LogLevelMax=emerg
[Install]
WantedBy=default.target
[Unit]
Description=Lockloss analyze backfill timer
# FIXME: LHO systems are not recognizing the FQDN
#ConditionHost=detchar.ligo-*.caltech.edu
ConditionHost=|detchar.ligo-la.caltech.edu
ConditionHost=|detchar
[Timer]
OnCalendar=Wed *-*-* 2:00:00
Persistent=true
[Install]
WantedBy=timers.target
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.