diff --git a/hveto/cli/tests/__init__.py b/hveto/cli/tests/__init__.py
new file mode 100644
index 0000000..41db37d
--- /dev/null
+++ b/hveto/cli/tests/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) Alex Urban (2020)
+#
+# This file is part of the hveto python package.
+#
+# hveto is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# hveto is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with hveto. If not, see .
+
+"""Unit tests for hveto.cli
+"""
+
+__author__ = "Alex Urban "
diff --git a/hveto/cli/tests/test_trace.py b/hveto/cli/tests/test_trace.py
new file mode 100644
index 0000000..5391271
--- /dev/null
+++ b/hveto/cli/tests/test_trace.py
@@ -0,0 +1,105 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) Alex Urban (2020)
+#
+# This file is part of the hveto python package.
+#
+# hveto is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# hveto is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with hveto. If not, see .
+
+"""Tests for :mod:`hveto.cli.trace`
+"""
+
+import os.path
+import pytest
+import shutil
+
+from gwpy.segments import (
+ Segment,
+ SegmentList,
+)
+
+from .. import trace
+
+__author__ = "Alex Urban "
+
+
+# -- test configuration
+
+VALID_RESULTS = """{
+ "rounds": [{
+ "files": {"VETO_SEGS": ["TEST-HVETO-SEGMENTS.txt"]},
+ "name": "L1:ASC-X_TR_A_NSUM_OUT_DQ",
+ "significance": 78.93832125380759,
+ "snr": 11.0,
+ "window": 0.4
+ }]
+}"""
+
+EMPTY_RESULTS = '{"rounds": [{"files": {"VETO_SEGS": []}}]}'
+TEST_SEGMENTS = SegmentList([Segment(0, 8)])
+
+
+# -- cli tests ----------------------------------------------------------------
+
+def test_main(caplog, tmpdir):
+ indir = str(tmpdir)
+ summary_stats = os.path.join(indir, 'summary-stats.json')
+ print(VALID_RESULTS, file=open(summary_stats, 'w'))
+ TEST_SEGMENTS.write(os.path.join(indir, 'TEST-HVETO-SEGMENTS.txt'))
+ args = [
+ '--trigger-time', '4',
+ '--directory', indir,
+ '--verbose',
+ ]
+ # test output
+ trace.main(args)
+ assert "Running in verbose mode" in caplog.text
+ assert "Search directory: {}".format(indir) in caplog.text
+ assert ("Trigger time 4.0 was vetoed in round 1 "
+ "by segment [0 ... 8)" in caplog.text)
+ assert "Round winner: L1:ASC-X_TR_A_NSUM_OUT_DQ" in caplog.text
+ assert "Significance: 78.93832125380759" in caplog.text
+ assert "SNR: 11.0" in caplog.text
+ assert "Window: 0.4" in caplog.text
+ # clean up
+ shutil.rmtree(indir, ignore_errors=True)
+
+
+def test_main_no_input(caplog, tmpdir):
+ indir = str(tmpdir)
+ args = [
+ '--trigger-time', '0',
+ '--directory', indir,
+ ]
+ # test output
+ with pytest.raises(IOError):
+ trace.main(args)
+ assert ("'summary-stats.json' was not found in the "
+ "input directory" in caplog.text)
+ # clean up
+ shutil.rmtree(indir, ignore_errors=True)
+
+
+def test_main_empty_input(caplog, tmpdir):
+ indir = str(tmpdir)
+ summary_stats = os.path.join(indir, 'summary-stats.json')
+ print(EMPTY_RESULTS, file=open(summary_stats, 'w'))
+ args = [
+ '--trigger-time', '0',
+ '--directory', indir,
+ ]
+ # test output
+ trace.main(args)
+ assert "Trigger time 0.0 was not vetoed" in caplog.text
+ # clean up
+ shutil.rmtree(indir, ignore_errors=True)
diff --git a/hveto/cli/trace.py b/hveto/cli/trace.py
index 7f283e7..12e3029 100644
--- a/hveto/cli/trace.py
+++ b/hveto/cli/trace.py
@@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with hveto. If not, see .
-"""Check if a trigger was vetoed by a specified hveto run
+"""Check whether a specified trigger time was vetoed by an hveto analysis
"""
import os
@@ -60,7 +60,7 @@ def create_parser():
'--directory',
required=True,
type=_abs_path,
- help=('path to hveto-generated folder containing '
+ help=('path to the hveto output directory containing '
'a summary-stats.json file'),
)
parser.add_argument(
@@ -78,45 +78,51 @@ def create_parser():
# -- main code block ----------------------------------------------------------
def main(args=None):
- """Run the trace tool
+ """Run the hveto-trace command-line tool
"""
parser = create_parser()
args = parser.parse_args(args=args)
- directory = args.directory
+ # initialize variables
+ time = float(args.trigger_time)
+ segment = None
+
+ # initialize logger
logger = cli.logger(name=PROG.split('python -m ').pop(),
level=args.loglevel)
logger.debug('Running in verbose mode')
- logger.debug('Search directory: %s' % directory)
-
- trigger_time = float(args.trigger_time)
- if directory[-1] != '/':
- directory += '/'
+ logger.debug('Search directory: {}'.format(args.directory))
- try:
- segment_stats = json.load(open('%ssummary-stats.json' % directory))
+ try: # read veto segment statistics
+ segment_stats = json.load(open(os.path.join(
+ args.directory, 'summary-stats.json')))
except IOError:
- logger.error("'summary-stats.json' was not found "
- "in the input directory")
- sys.exit(0)
+ logger.critical("'summary-stats.json' was not found "
+ "in the input directory")
+ raise
- for i, cround in enumerate(segment_stats['rounds']):
+ # loop over and log results to output
+ for (i, cround) in enumerate(segment_stats['rounds']):
seg_files = filter(
- lambda f_name: '.txt' in f_name, cround[u'files'][u'VETO_SEGS'])
+ lambda f_name: '.txt' in f_name,
+ cround[u'files'][u'VETO_SEGS'])
for f in seg_files:
- segments = SegmentList.read(os.path.join(directory, f))
- for segment in segments:
- if segment[0] <= trigger_time <= segment[1]:
- logger.info('Signal was vetoed in round %d by '
- 'segment %s' % ((i + 1), segment))
- logger.debug('Winner: %s' % cround['name'])
- logger.debug('Significance: %s' % cround['significance'])
- logger.debug('SNR: %s' % cround['snr'])
- logger.debug('Window: %s' % cround['window'])
- sys.exit(0)
-
- logger.info('Signal was not vetoed.')
-
+ segments = SegmentList.read(os.path.join(args.directory, f))
+ if time in segments:
+ segment = segments[segments.find(time)]
+ logger.info('Trigger time {0} was vetoed in round {1} by '
+ 'segment {2}'.format(time, (i + 1), segment))
+ logger.debug('Round winner: {}'.format(cround['name']))
+ logger.debug('Significance: {}'.format(cround['significance']))
+ logger.debug('SNR: {}'.format(cround['snr']))
+ logger.debug('Window: {}'.format(cround['window']))
+
+ if segment is None:
+ # if we got here, the signal was not vetoed
+ logger.info('Trigger time {} was not vetoed'.format(time))
+
+
+# -- run from command-line ----------------------------------------------------
if __name__ == "__main__":
main()