gwsumm 2.2.0__tar.gz → 2.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gwsumm-2.2.0 → gwsumm-2.2.2}/PKG-INFO +1 -1
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/_version.py +2 -2
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/archive.py +2 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/channels.py +1 -1
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/__init__.py +2 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/builtin.py +25 -11
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/core.py +35 -1
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/range.py +17 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/segments.py +223 -27
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/segments.py +19 -10
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/data.py +2 -1
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_plot.py +3 -3
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/triggers.py +26 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm.egg-info/PKG-INFO +1 -1
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.codeclimate.yml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.codecov.yml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.flake8 +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.gitattributes +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.github/workflows/build.yml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.github/workflows/lint.yml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.gitignore +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/.readthedocs.yaml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/CONTRIBUTING.md +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/LICENSE +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/MANIFEST.in +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/README.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/Makefile +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/_static/css/custom.css +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/_templates/autoclass/class.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/_templates/autosummary/base.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/_templates/autosummary/class.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/_templates/autosummary/module.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/_templates/layout.html +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/api/index.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/automation.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/cli.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/conf.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/configuration/data.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/configuration/format.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/configuration/index.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/configuration/tabs.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/environment.yml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/examples/first.png +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/examples/imc.png +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/images/screenshot.png +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/index.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/make.bat +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/modes.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/overview.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/plots.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/states.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/tabs/api.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/tabs/index.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/tabs/modes.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/docs/tabs/websites.rst +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/__main__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/batch.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/config/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/config/defaults.ini +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/config/matplotlib.ini +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/coherence.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/mathutils.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/range.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/spectral.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/timeseries.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/data/utils.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/globalv.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/bootstrap.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/html5.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/static.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/tests/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/tests/test_bootstrap.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/tests/test_html5.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/html/tests/test_static.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/io.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/mode.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/guardian/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/guardian/__main__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/guardian/core.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/guardian/tests/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/guardian/tests/test_main.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/mixins.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/noisebudget.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/registry.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/sei.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/triggers/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/triggers/__main__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/triggers/core.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/triggers/tests/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/triggers/tests/test_main.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/plot/utils.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/state/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/state/all.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/state/core.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/state/registry.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/builtin.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/core.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/etg.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/fscan.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/gracedb.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/guardian.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/management.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/misc.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/registry.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/sei.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tabs/stamp.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/__init__.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/common.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_archive.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_batch.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_channels.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_config.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_data.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_mode.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_tabs.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/tests/test_utils.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/units.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm/utils.py +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm.egg-info/SOURCES.txt +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm.egg-info/dependency_links.txt +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm.egg-info/entry_points.txt +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm.egg-info/requires.txt +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/gwsumm.egg-info/top_level.txt +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/pyproject.toml +0 -0
- {gwsumm-2.2.0 → gwsumm-2.2.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gwsumm
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: A python toolbox used by the LIGO Scientific Collaboration for detector characterisation
|
|
5
5
|
Author-email: Alex Urban <alex.urban@ligo.org>, Duncan Macleod <duncan.macleod@ligo.org>
|
|
6
6
|
Maintainer-email: Evan Goetz <evan.goetz@ligo.org>
|
|
@@ -176,6 +176,8 @@ def write_data_archive(outfile, channels=True, timeseries=True,
|
|
|
176
176
|
|
|
177
177
|
# moves the new file to the backup directory
|
|
178
178
|
shutil.move(temp_outfile, outfile)
|
|
179
|
+
# Changes permission to allow reading from any user
|
|
180
|
+
os.chmod(outfile, 0o664)
|
|
179
181
|
|
|
180
182
|
except Exception:
|
|
181
183
|
# if it fails for any reason, raise and continue
|
|
@@ -32,7 +32,7 @@ from .utils import re_quote
|
|
|
32
32
|
|
|
33
33
|
__author__ = 'Duncan Macleod <duncan.macleod@ligo.org>'
|
|
34
34
|
|
|
35
|
-
NDS2_TYPES = Nds2ChannelType.
|
|
35
|
+
NDS2_TYPES = Nds2ChannelType.nds2names()
|
|
36
36
|
CIS_URL = 'https://cis.ligo.org'
|
|
37
37
|
re_channel = re.compile(r'[A-Z]\d:[a-zA-Z0-9]+' # core channel section L1:TEST
|
|
38
38
|
r'(?:[-_][a-zA-Z0-9_]+)?' # underscore-delimited parts
|
|
@@ -80,6 +80,7 @@ from .segments import (
|
|
|
80
80
|
ODCDataPlot,
|
|
81
81
|
SegmentPiePlot,
|
|
82
82
|
NetworkDutyPiePlot,
|
|
83
|
+
NetworkDutyBarPlot,
|
|
83
84
|
SegmentBarPlot,
|
|
84
85
|
SegmentHistogramPlot,
|
|
85
86
|
)
|
|
@@ -98,6 +99,7 @@ from .range import (
|
|
|
98
99
|
RangeSpectrogramDataPlot,
|
|
99
100
|
RangeSpectrumDataPlot,
|
|
100
101
|
RangeCumulativeSpectrumDataPlot,
|
|
102
|
+
RangeCumulativeHistogramPlot,
|
|
101
103
|
SimpleTimeVolumeDataPlot,
|
|
102
104
|
GWpyTimeVolumeDataPlot,
|
|
103
105
|
)
|
|
@@ -710,15 +710,14 @@ class TimeSeriesHistogramPlot(DataPlot):
|
|
|
710
710
|
|
|
711
711
|
# plot
|
|
712
712
|
for ax, arr, pargs in zip(cycle(axes), data, histargs):
|
|
713
|
-
# set range
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
)
|
|
713
|
+
# set range
|
|
714
|
+
pargs['range'] = self._get_range(
|
|
715
|
+
data,
|
|
716
|
+
# use range from first dataset if already calculated
|
|
717
|
+
range=histargs[0].get('range'),
|
|
718
|
+
# use xlim if manually set (user or INI)
|
|
719
|
+
xlim=None if ax.get_autoscalex_on() else ax.get_xlim(),
|
|
720
|
+
)
|
|
722
721
|
|
|
723
722
|
# plot histogram
|
|
724
723
|
_, _, patches = ax.hist(arr, **pargs)
|
|
@@ -759,8 +758,23 @@ class TimeSeriesHistogramPlot(DataPlot):
|
|
|
759
758
|
return self.finalize(outputfile=outputfile)
|
|
760
759
|
|
|
761
760
|
def _get_range(self, data, range=None, xlim=None):
|
|
762
|
-
if range is not None
|
|
763
|
-
|
|
761
|
+
if range is not None:
|
|
762
|
+
if range == 'autoscaling':
|
|
763
|
+
return None
|
|
764
|
+
else:
|
|
765
|
+
range = list(range)
|
|
766
|
+
try:
|
|
767
|
+
if range[0] == 'min':
|
|
768
|
+
range[0] = numpy.min(data)
|
|
769
|
+
if range[1] == 'max':
|
|
770
|
+
range[1] = numpy.max(data)
|
|
771
|
+
if range[0] < range[1]:
|
|
772
|
+
return range
|
|
773
|
+
except (ValueError, IndexError) as exc:
|
|
774
|
+
if not str(exc).startswith('zero-size array'):
|
|
775
|
+
raise
|
|
776
|
+
if xlim is not None:
|
|
777
|
+
return xlim
|
|
764
778
|
try:
|
|
765
779
|
return numpy.min(data), numpy.max(data)
|
|
766
780
|
except ValueError as exc:
|
|
@@ -212,7 +212,41 @@ class DataPlot(SummaryPlot):
|
|
|
212
212
|
#: plot() call style
|
|
213
213
|
_single_call = False
|
|
214
214
|
#: dict of default plotting kwargs
|
|
215
|
-
defaults = {
|
|
215
|
+
defaults = {
|
|
216
|
+
'animation.convert_args': ['-layers', 'OptimizePlus'],
|
|
217
|
+
'axes.axisbelow': False,
|
|
218
|
+
'axes.edgecolor': 'gray',
|
|
219
|
+
'axes.formatter.limits': [-3, 4],
|
|
220
|
+
'axes.formatter.use_mathtext': True,
|
|
221
|
+
'axes.grid': True,
|
|
222
|
+
'axes.labelpad': 5.0,
|
|
223
|
+
'axes.labelsize': 18.0,
|
|
224
|
+
'axes.titlesize': 22.0,
|
|
225
|
+
'contour.algorithm': 'mpl2014',
|
|
226
|
+
'figure.figsize': [12.0, 6.0],
|
|
227
|
+
'figure.labelsize': 'large',
|
|
228
|
+
'figure.labelweight': 'normal',
|
|
229
|
+
'font.sans-serif': ['Roboto'],
|
|
230
|
+
'grid.alpha': 0.5,
|
|
231
|
+
'grid.linewidth': 0.5,
|
|
232
|
+
'legend.edgecolor': 'inherit',
|
|
233
|
+
'legend.fancybox': False,
|
|
234
|
+
'legend.fontsize': 10.0,
|
|
235
|
+
'legend.handlelength': 1.0,
|
|
236
|
+
'legend.numpoints': 2,
|
|
237
|
+
'mathtext.bf': 'Roboto',
|
|
238
|
+
'mathtext.cal': 'Calligraffiti',
|
|
239
|
+
'mathtext.fontset': 'custom',
|
|
240
|
+
'mathtext.it': 'Roboto:italic',
|
|
241
|
+
'mathtext.rm': 'Roboto',
|
|
242
|
+
'mathtext.sf': 'Roboto',
|
|
243
|
+
'mathtext.tt': 'Roboto Slab',
|
|
244
|
+
'savefig.transparent': True,
|
|
245
|
+
'svg.fonttype': 'none',
|
|
246
|
+
'text.parse_math': True,
|
|
247
|
+
'xtick.labelsize': 14.0,
|
|
248
|
+
'ytick.labelsize': 14.0,
|
|
249
|
+
}
|
|
216
250
|
#: list of parameters parsed for `plot()` calls
|
|
217
251
|
DRAW_PARAMS = list(putils.ARTIST_PARAMS)
|
|
218
252
|
|
|
@@ -153,6 +153,23 @@ class RangeDataHistogramPlot(RangePlotMixin, get_plot('histogram')):
|
|
|
153
153
|
register_plot(RangeDataHistogramPlot)
|
|
154
154
|
|
|
155
155
|
|
|
156
|
+
class RangeCumulativeHistogramPlot(RangePlotMixin, get_plot('histogram')):
|
|
157
|
+
type = 'range-cumulative-histogram'
|
|
158
|
+
defaults = get_plot('histogram').defaults.copy()
|
|
159
|
+
defaults.update(RangePlotMixin.defaults.copy())
|
|
160
|
+
defaults.update({
|
|
161
|
+
'xlabel': 'Angle-averaged range [Mpc]',
|
|
162
|
+
'ylabel': 'Cumulative time duration',
|
|
163
|
+
'log': False,
|
|
164
|
+
'cumulative': True,
|
|
165
|
+
'density': True,
|
|
166
|
+
'range': (1, 'max'),
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
register_plot(RangeCumulativeHistogramPlot)
|
|
171
|
+
|
|
172
|
+
|
|
156
173
|
class RangeSpectrogramDataPlot(RangePlotMixin, get_plot('spectrogram')):
|
|
157
174
|
type = 'range-spectrogram'
|
|
158
175
|
defaults = get_plot('spectrogram').defaults.copy()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# Copyright (C) Duncan Macleod (2013)
|
|
3
|
+
# Evan Goetz (2023)
|
|
3
4
|
#
|
|
4
5
|
# This file is part of GWSumm.
|
|
5
6
|
#
|
|
@@ -31,7 +32,7 @@ from dateutil.relativedelta import relativedelta
|
|
|
31
32
|
|
|
32
33
|
from matplotlib import rcParams
|
|
33
34
|
from matplotlib.artist import setp
|
|
34
|
-
from matplotlib.colors import (rgb2hex, is_color_like)
|
|
35
|
+
from matplotlib.colors import (rgb2hex, is_color_like, TABLEAU_COLORS)
|
|
35
36
|
from matplotlib.patches import Rectangle
|
|
36
37
|
|
|
37
38
|
from glue import iterutils
|
|
@@ -1006,15 +1007,54 @@ class SegmentPiePlot(PiePlot, SegmentDataPlot):
|
|
|
1006
1007
|
wedgeargs = self.parse_wedge_kwargs()
|
|
1007
1008
|
plotargs = self.parse_plot_kwargs()
|
|
1008
1009
|
|
|
1010
|
+
# Boolean logic flags to determine if this code is currently running:
|
|
1011
|
+
# - before the span of interest (current time the code is running <
|
|
1012
|
+
# start of span)
|
|
1013
|
+
# - after the span of interest (current time the code is running >= end
|
|
1014
|
+
# of span)
|
|
1015
|
+
# - during the span of interest (any other time)
|
|
1016
|
+
# The flag is set to True for the appropriate noun (before, during, or
|
|
1017
|
+
# after).
|
|
1018
|
+
# These flags are then used to set plot titles and labels and determine
|
|
1019
|
+
# if there is any missing data.
|
|
1020
|
+
before = during = after = False
|
|
1021
|
+
if globalv.NOW < int(self.span[0]):
|
|
1022
|
+
before = True
|
|
1023
|
+
elif globalv.NOW >= int(self.span[1]):
|
|
1024
|
+
after = True
|
|
1025
|
+
else:
|
|
1026
|
+
during = True
|
|
1027
|
+
|
|
1009
1028
|
# use state to generate suptitle with GPS span
|
|
1029
|
+
# this will be different depending on if `include_future` is given
|
|
1030
|
+
# as an option or whether running before, during, or after the time
|
|
1031
|
+
# interval requested
|
|
1010
1032
|
if self.state:
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1033
|
+
if future or after:
|
|
1034
|
+
self.pargs.setdefault(
|
|
1035
|
+
'suptitle',
|
|
1036
|
+
(f'[{self.span[0]}-{self.span[1]}, '
|
|
1037
|
+
f'state: {texify(str(self.state))}]'))
|
|
1038
|
+
elif before:
|
|
1039
|
+
self.pargs.setdefault(
|
|
1040
|
+
'suptitle',
|
|
1041
|
+
(f'[{self.span[0]}-{self.span[0]}, '
|
|
1042
|
+
f'state: {texify(str(self.state))}]'))
|
|
1043
|
+
else:
|
|
1044
|
+
self.pargs.setdefault(
|
|
1045
|
+
'suptitle',
|
|
1046
|
+
(f'[{self.span[0]}-{globalv.NOW}, '
|
|
1047
|
+
f'state: {texify(str(self.state))}]'))
|
|
1015
1048
|
else:
|
|
1016
|
-
|
|
1017
|
-
|
|
1049
|
+
if future or after:
|
|
1050
|
+
self.pargs.setdefault(
|
|
1051
|
+
'suptitle', f'[{self.span[0]}-{self.span[1]}]')
|
|
1052
|
+
elif before:
|
|
1053
|
+
self.pargs.setdefault(
|
|
1054
|
+
'suptitle', f'[{self.span[0]}-{self.span[0]}]')
|
|
1055
|
+
else:
|
|
1056
|
+
self.pargs.setdefault(
|
|
1057
|
+
'suptitle', f'[{self.span[0]}-{globalv.NOW}]')
|
|
1018
1058
|
|
|
1019
1059
|
# get segments
|
|
1020
1060
|
data = []
|
|
@@ -1028,12 +1068,39 @@ class SegmentPiePlot(PiePlot, SegmentDataPlot):
|
|
|
1028
1068
|
padding=self.padding).coalesce()
|
|
1029
1069
|
data.append(float(abs(segs.active)))
|
|
1030
1070
|
|
|
1031
|
-
# handle missing
|
|
1071
|
+
# handle missing (undefined) segments
|
|
1072
|
+
# if running before then all the time is future because segments
|
|
1073
|
+
# haven't been generated
|
|
1074
|
+
# if running after then some segments may not cover the whole time
|
|
1075
|
+
# if during, it is somewhere in between
|
|
1032
1076
|
total = float(sum(data))
|
|
1033
|
-
|
|
1034
|
-
|
|
1077
|
+
undefined = future_seg = 0
|
|
1078
|
+
if before:
|
|
1079
|
+
future_seg = alltime
|
|
1080
|
+
elif after:
|
|
1081
|
+
undefined = alltime - total
|
|
1082
|
+
elif during:
|
|
1083
|
+
future_seg = int(self.span[1]) - globalv.NOW
|
|
1084
|
+
undefined = alltime - future_seg - total
|
|
1085
|
+
current_total = globalv.NOW - int(self.span[0])
|
|
1086
|
+
|
|
1087
|
+
# figure out the extra pieces to include in the pie chart and labels
|
|
1088
|
+
# TODO: There is something messed up about "labels" and
|
|
1089
|
+
# "label" that should be cleaned up
|
|
1090
|
+
if undefined > 0:
|
|
1091
|
+
data.append(undefined)
|
|
1092
|
+
if 'labels' in plotargs:
|
|
1093
|
+
plotargs['labels'] = list(plotargs['labels']) + ['Undefined']
|
|
1094
|
+
elif 'label' in plotargs:
|
|
1095
|
+
plotargs['label'] = list(plotargs['label']) + ['Undefined']
|
|
1096
|
+
if 'colors' in plotargs:
|
|
1097
|
+
plotargs['colors'] = list(plotargs['colors']) + ['black']
|
|
1098
|
+
if future or before:
|
|
1099
|
+
data.append(future_seg)
|
|
1035
1100
|
if 'labels' in plotargs:
|
|
1036
1101
|
plotargs['labels'] = list(plotargs['labels']) + [' ']
|
|
1102
|
+
elif 'label' in plotargs:
|
|
1103
|
+
plotargs['label'] = list(plotargs['label']) + [' ']
|
|
1037
1104
|
if 'colors' in plotargs:
|
|
1038
1105
|
plotargs['colors'] = list(plotargs['colors']) + ['white']
|
|
1039
1106
|
|
|
@@ -1058,7 +1125,12 @@ class SegmentPiePlot(PiePlot, SegmentDataPlot):
|
|
|
1058
1125
|
pclabels.append(label)
|
|
1059
1126
|
else:
|
|
1060
1127
|
try:
|
|
1061
|
-
|
|
1128
|
+
if future or after:
|
|
1129
|
+
pc = d / alltime * 100
|
|
1130
|
+
elif during:
|
|
1131
|
+
pc = d / current_total * 100
|
|
1132
|
+
else:
|
|
1133
|
+
pc = 0.0
|
|
1062
1134
|
except ZeroDivisionError:
|
|
1063
1135
|
pc = 0.0
|
|
1064
1136
|
pclabels.append(texify(
|
|
@@ -1150,28 +1222,45 @@ class NetworkDutyPiePlot(SegmentPiePlot):
|
|
|
1150
1222
|
# construct compound flags for each network size
|
|
1151
1223
|
flags = dict((f[:2], f) for f in self.flags)
|
|
1152
1224
|
network = ''.join(sorted(set(flags)))
|
|
1153
|
-
self.pargs.setdefault('title', '
|
|
1225
|
+
self.pargs.setdefault('title', f'{network} network duty factor')
|
|
1154
1226
|
networkflags = []
|
|
1155
1227
|
colors = []
|
|
1156
1228
|
labels = []
|
|
1229
|
+
# define an exclude DQ flag so that each subsequent time through
|
|
1230
|
+
# We exclude triple time from double time and double time from single
|
|
1231
|
+
# time
|
|
1157
1232
|
exclude = DataQualityFlag()
|
|
1158
1233
|
for i in list(range(len(flags)+1))[::-1]:
|
|
1159
1234
|
name = self.NETWORK_NAME[i]
|
|
1160
|
-
flag = '
|
|
1235
|
+
flag = f'{network}:{name}'
|
|
1161
1236
|
networksegs = DataQualityFlag(flag, known=valid)
|
|
1237
|
+
# loop over the possible combinations inserting the flag to the
|
|
1238
|
+
# network segments dictionary
|
|
1162
1239
|
for ifoset in combinations(flags, i):
|
|
1163
1240
|
if not ifoset:
|
|
1164
|
-
compound = '
|
|
1241
|
+
compound = f"!{'!'.join(list(flags.values()))}"
|
|
1165
1242
|
else:
|
|
1166
1243
|
compound = '&'.join(flags[ifo] for ifo in ifoset)
|
|
1167
|
-
segs = get_segments(
|
|
1168
|
-
|
|
1244
|
+
segs = get_segments(
|
|
1245
|
+
compound, validity=valid, query=False,
|
|
1246
|
+
padding=self.padding, ignore_undefined=True).coalesce()
|
|
1169
1247
|
networksegs += segs
|
|
1248
|
+
# Final step in the loop for no detectors: if not wanting to plot
|
|
1249
|
+
# future times, then exclude the time from now to the end of the
|
|
1250
|
+
# span from the no detector network
|
|
1251
|
+
if (i == 0 and
|
|
1252
|
+
not self.pargs.get('include_future', False) and
|
|
1253
|
+
globalv.NOW < self.span[1]):
|
|
1254
|
+
exclude.active += SegmentList(
|
|
1255
|
+
[Segment(globalv.NOW, self.span[1])])
|
|
1256
|
+
# insert this flag into the segments global variable and exclude
|
|
1257
|
+
# any of the previous network (more detectors) time from this time
|
|
1170
1258
|
globalv.SEGMENTS[flag] = networksegs.copy()
|
|
1171
1259
|
globalv.SEGMENTS[flag].active -= exclude.active
|
|
1260
|
+
# update the segements of times to exclude
|
|
1172
1261
|
exclude = networksegs
|
|
1173
1262
|
networkflags.append(flag)
|
|
1174
|
-
labels.append('
|
|
1263
|
+
labels.append(f'{name.title()} interferometer')
|
|
1175
1264
|
colors.append(self.NETWORK_COLOR.get(name))
|
|
1176
1265
|
|
|
1177
1266
|
self.pargs.setdefault('colors', colors)
|
|
@@ -1197,7 +1286,6 @@ class SegmentBarPlot(BarPlot, SegmentDataPlot):
|
|
|
1197
1286
|
'color': GREEN,
|
|
1198
1287
|
'edgecolor': 'green',
|
|
1199
1288
|
'alpha': .6,
|
|
1200
|
-
'align': 'edge', # FIXME, updated for mpl 2.0, can simplify code
|
|
1201
1289
|
}
|
|
1202
1290
|
SCALE_UNIT = {
|
|
1203
1291
|
None: 'seconds',
|
|
@@ -1208,17 +1296,24 @@ class SegmentBarPlot(BarPlot, SegmentDataPlot):
|
|
|
1208
1296
|
}
|
|
1209
1297
|
|
|
1210
1298
|
def draw(self, outputfile=None):
|
|
1299
|
+
# Check if ylabel has been previously defined
|
|
1300
|
+
# to avoid overwriting it
|
|
1301
|
+
if 'ylabel' in self.pargs:
|
|
1302
|
+
set_ylabel = False
|
|
1303
|
+
else:
|
|
1304
|
+
set_ylabel = True
|
|
1305
|
+
|
|
1211
1306
|
plot = self.init_plot(projection='rectilinear')
|
|
1212
1307
|
ax = plot.gca()
|
|
1213
1308
|
|
|
1214
1309
|
if self.state:
|
|
1215
1310
|
self.pargs.setdefault(
|
|
1216
1311
|
'suptitle',
|
|
1217
|
-
'[
|
|
1218
|
-
|
|
1312
|
+
f'[{self.span[0]}-{self.span[1]},'
|
|
1313
|
+
f'state: {texify(str(self.state))}]')
|
|
1219
1314
|
else:
|
|
1220
1315
|
self.pargs.setdefault(
|
|
1221
|
-
'suptitle', '[
|
|
1316
|
+
'suptitle', f'[{self.span[0]}-{self.span[1]}]')
|
|
1222
1317
|
suptitle = self.pargs.pop('suptitle', None)
|
|
1223
1318
|
if suptitle:
|
|
1224
1319
|
plot.suptitle(suptitle, y=0.993, va='top')
|
|
@@ -1228,11 +1323,13 @@ class SegmentBarPlot(BarPlot, SegmentDataPlot):
|
|
|
1228
1323
|
self.pargs.setdefault('ylim', (0, 100))
|
|
1229
1324
|
elif isinstance(scale, (int, float)):
|
|
1230
1325
|
self.pargs.setdefault('ylim', (0, abs(self.span) / scale))
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1326
|
+
|
|
1327
|
+
if set_ylabel:
|
|
1328
|
+
try:
|
|
1329
|
+
self.pargs.setdefault('ylabel',
|
|
1330
|
+
f'Livetime [{self.SCALE_UNIT[scale]}]')
|
|
1331
|
+
except KeyError:
|
|
1332
|
+
self.pargs.setdefault('ylabel', 'Livetime')
|
|
1236
1333
|
|
|
1237
1334
|
# extract plotting arguments
|
|
1238
1335
|
sort = self.pargs.pop('sorted', False)
|
|
@@ -1263,7 +1360,7 @@ class SegmentBarPlot(BarPlot, SegmentDataPlot):
|
|
|
1263
1360
|
|
|
1264
1361
|
# make bar chart
|
|
1265
1362
|
width = plotargs.pop('width', .8)
|
|
1266
|
-
x = numpy.arange(len(data))
|
|
1363
|
+
x = numpy.arange(len(data))
|
|
1267
1364
|
ax.bar(x, data, width=width, **plotargs)
|
|
1268
1365
|
|
|
1269
1366
|
# set labels
|
|
@@ -1287,6 +1384,105 @@ class SegmentBarPlot(BarPlot, SegmentDataPlot):
|
|
|
1287
1384
|
register_plot(SegmentBarPlot)
|
|
1288
1385
|
|
|
1289
1386
|
|
|
1387
|
+
class NetworkDutyBarPlot(SegmentBarPlot):
|
|
1388
|
+
|
|
1389
|
+
"""Special case of the `SegmentPiePlot` for network duty factors.
|
|
1390
|
+
"""
|
|
1391
|
+
type = 'network-duty-segment-bar'
|
|
1392
|
+
NETWORK_NAME = {
|
|
1393
|
+
0: 'no',
|
|
1394
|
+
1: 'single',
|
|
1395
|
+
2: 'double',
|
|
1396
|
+
3: 'triple',
|
|
1397
|
+
4: 'quadruple',
|
|
1398
|
+
5: 'quintuple',
|
|
1399
|
+
6: 'sextuple',
|
|
1400
|
+
}
|
|
1401
|
+
NETWORK_COLOR = GW_OBSERVATORY_COLORS.copy()
|
|
1402
|
+
defaults = SegmentBarPlot.defaults.copy()
|
|
1403
|
+
# remove SegmentBarPlot default colors as they overwrite
|
|
1404
|
+
# the ones defined later.
|
|
1405
|
+
defaults.pop('color')
|
|
1406
|
+
defaults.pop('edgecolor')
|
|
1407
|
+
defaults.update({
|
|
1408
|
+
'title': 'Network duty factor',
|
|
1409
|
+
'ylabel': 'Duty factor [%]',
|
|
1410
|
+
})
|
|
1411
|
+
|
|
1412
|
+
def draw(self):
|
|
1413
|
+
# get segments
|
|
1414
|
+
if self.state and not self.all_data:
|
|
1415
|
+
valid = self.state.active
|
|
1416
|
+
else:
|
|
1417
|
+
valid = SegmentList([self.span])
|
|
1418
|
+
|
|
1419
|
+
# construct compound flags for each network size
|
|
1420
|
+
flags = dict((f[:2], f) for f in self.flags)
|
|
1421
|
+
# construct all possible network combinations
|
|
1422
|
+
networks = {}
|
|
1423
|
+
for size in range(1, len(flags) + 1):
|
|
1424
|
+
ifocombs = combinations(sorted(set(flags)), size)
|
|
1425
|
+
for ifocomb in ifocombs:
|
|
1426
|
+
key = "".join(ifocomb)
|
|
1427
|
+
networks[key] = (size, ifocomb)
|
|
1428
|
+
|
|
1429
|
+
networkflags = []
|
|
1430
|
+
colors = []
|
|
1431
|
+
labels = []
|
|
1432
|
+
color_id = 0
|
|
1433
|
+
for network, values in networks.items():
|
|
1434
|
+
i = values[0]
|
|
1435
|
+
ifoset = values[1]
|
|
1436
|
+
name = self.NETWORK_NAME[i]
|
|
1437
|
+
if i == 1:
|
|
1438
|
+
# this avoid having a redundant X1:single
|
|
1439
|
+
# in the Segment information table
|
|
1440
|
+
flag = flags[network]
|
|
1441
|
+
|
|
1442
|
+
else:
|
|
1443
|
+
flag = f'{network}:{name}'
|
|
1444
|
+
|
|
1445
|
+
networksegs = DataQualityFlag(flag, known=valid)
|
|
1446
|
+
if not ifoset:
|
|
1447
|
+
compound = f"!{'!'.join(list(flags.values()))}"
|
|
1448
|
+
else:
|
|
1449
|
+
compound = '&'.join(flags[ifo] for ifo in ifoset)
|
|
1450
|
+
|
|
1451
|
+
segs = get_segments(compound, validity=valid, query=False,
|
|
1452
|
+
padding=self.padding).coalesce()
|
|
1453
|
+
networksegs += segs
|
|
1454
|
+
globalv.SEGMENTS[flag] = networksegs.copy()
|
|
1455
|
+
combined_flag = flag.split(':')[0]
|
|
1456
|
+
if flag.startswith(tuple(networks.keys())):
|
|
1457
|
+
networkflags.append(flag)
|
|
1458
|
+
|
|
1459
|
+
labels.append(combined_flag)
|
|
1460
|
+
if self.NETWORK_COLOR.get(combined_flag) is not None:
|
|
1461
|
+
colors.append(self.NETWORK_COLOR.get(combined_flag))
|
|
1462
|
+
else:
|
|
1463
|
+
# if color is not defined, use standard matplotlib colors
|
|
1464
|
+
colors.append(list(TABLEAU_COLORS.values())[color_id])
|
|
1465
|
+
if color_id < len(TABLEAU_COLORS) - 1:
|
|
1466
|
+
color_id += 1
|
|
1467
|
+
else:
|
|
1468
|
+
color_id = 0
|
|
1469
|
+
|
|
1470
|
+
self.pargs.setdefault('colors', colors)
|
|
1471
|
+
self.pargs.setdefault('edgecolor', colors)
|
|
1472
|
+
self.pargs.setdefault('labels', labels)
|
|
1473
|
+
|
|
1474
|
+
# reset flags and generate plot
|
|
1475
|
+
flags_ = self.flags
|
|
1476
|
+
outputfile = self.outputfile
|
|
1477
|
+
self.flags = networkflags
|
|
1478
|
+
out = super(NetworkDutyBarPlot, self).draw(outputfile=outputfile)
|
|
1479
|
+
self.flags = flags_
|
|
1480
|
+
return out
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
register_plot(NetworkDutyBarPlot)
|
|
1484
|
+
|
|
1485
|
+
|
|
1290
1486
|
class SegmentHistogramPlot(get_plot('histogram'), SegmentDataPlot):
|
|
1291
1487
|
"""Histogram of segment duration
|
|
1292
1488
|
"""
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
# Copyright (C) Duncan Macleod (2013)
|
|
3
|
+
# Evan Goetz (2023)
|
|
3
4
|
#
|
|
4
5
|
# This file is part of GWSumm.
|
|
5
6
|
#
|
|
@@ -22,7 +23,6 @@
|
|
|
22
23
|
import sys
|
|
23
24
|
import operator
|
|
24
25
|
import warnings
|
|
25
|
-
from functools import reduce
|
|
26
26
|
from collections import OrderedDict
|
|
27
27
|
from configparser import (
|
|
28
28
|
DEFAULTSECT,
|
|
@@ -34,7 +34,7 @@ from configparser import (
|
|
|
34
34
|
from astropy.io.registry import IORegistryError
|
|
35
35
|
|
|
36
36
|
from gwpy.segments import (DataQualityFlag, DataQualityDict,
|
|
37
|
-
SegmentList, Segment)
|
|
37
|
+
SegmentListDict, SegmentList, Segment)
|
|
38
38
|
|
|
39
39
|
from . import globalv
|
|
40
40
|
from .utils import (
|
|
@@ -56,7 +56,8 @@ SEGDB_URLS = [
|
|
|
56
56
|
|
|
57
57
|
def get_segments(flag, validity=None, config=ConfigParser(), cache=None,
|
|
58
58
|
query=True, return_=True, coalesce=True, padding=None,
|
|
59
|
-
segdb_error='raise', url=None,
|
|
59
|
+
ignore_undefined=False, segdb_error='raise', url=None,
|
|
60
|
+
**read_kw):
|
|
60
61
|
"""Retrieve the segments for a given flag
|
|
61
62
|
|
|
62
63
|
Segments will be loaded from global memory if already defined,
|
|
@@ -97,6 +98,11 @@ def get_segments(flag, validity=None, config=ConfigParser(), cache=None,
|
|
|
97
98
|
`(start, end)` padding with which to pad segments that are
|
|
98
99
|
downloaded/read
|
|
99
100
|
|
|
101
|
+
ignore_undefined : `bool`, optional, default: `False`
|
|
102
|
+
Special case needed for network calculation compound flags so that
|
|
103
|
+
when this is True, DataQualityFlag.known values are set to the same
|
|
104
|
+
value as ``validity``
|
|
105
|
+
|
|
100
106
|
segdb_error : `str`, optional, default: ``'raise'``
|
|
101
107
|
how to handle errors returned from the segment database, one of
|
|
102
108
|
|
|
@@ -168,11 +174,12 @@ def get_segments(flag, validity=None, config=ConfigParser(), cache=None,
|
|
|
168
174
|
for f in allflags:
|
|
169
175
|
globalv.SEGMENTS.setdefault(f, DataQualityFlag(f))
|
|
170
176
|
|
|
171
|
-
# read segments from global memory and get the
|
|
177
|
+
# read segments from global memory and get the intersection of needed times
|
|
172
178
|
try:
|
|
173
|
-
old =
|
|
174
|
-
|
|
175
|
-
|
|
179
|
+
old = SegmentListDict()
|
|
180
|
+
for f in flags:
|
|
181
|
+
old[f] = globalv.SEGMENTS.get(f, DataQualityFlag(f)).known
|
|
182
|
+
old = SegmentList(old.intersection(flags))
|
|
176
183
|
except TypeError:
|
|
177
184
|
old = SegmentList()
|
|
178
185
|
newsegs = validity - old
|
|
@@ -260,15 +267,17 @@ def get_segments(flag, validity=None, config=ConfigParser(), cache=None,
|
|
|
260
267
|
for compound in flags:
|
|
261
268
|
union, intersection, exclude, notequal = split_compound_flag(
|
|
262
269
|
compound)
|
|
263
|
-
if len(union + intersection) == 1:
|
|
264
|
-
out[compound].description = globalv.SEGMENTS[f].description
|
|
265
|
-
out[compound].padding = padding.get(f, (0, 0))
|
|
270
|
+
if len(f := (union + intersection)) == 1:
|
|
271
|
+
out[compound].description = globalv.SEGMENTS[f[0]].description
|
|
272
|
+
out[compound].padding = padding.get(f[0], (0, 0))
|
|
266
273
|
for flist, op in zip([exclude, intersection, union, notequal],
|
|
267
274
|
[operator.sub, operator.and_, operator.or_,
|
|
268
275
|
not_equal]):
|
|
269
276
|
for f in flist:
|
|
270
277
|
pad = padding.get(f, (0, 0))
|
|
271
278
|
segs = globalv.SEGMENTS[f].copy()
|
|
279
|
+
if ignore_undefined:
|
|
280
|
+
segs.known = validity
|
|
272
281
|
if isinstance(pad, (float, int)):
|
|
273
282
|
segs = segs.pad(pad, pad)
|
|
274
283
|
elif pad is not None:
|
|
@@ -266,7 +266,8 @@ class DataTab(ProcessedTab, ParentTab):
|
|
|
266
266
|
if cp.has_section(pdef):
|
|
267
267
|
type_ = cp.get(pdef, 'type')
|
|
268
268
|
PlotClass = get_plot(type_)
|
|
269
|
-
elif (pdef not in ['range-histogram', 'segment-histogram'
|
|
269
|
+
elif (pdef not in ['range-histogram', 'segment-histogram',
|
|
270
|
+
'range-cumulative-histogram'] and
|
|
270
271
|
pdef.endswith('-histogram')):
|
|
271
272
|
type_ = None
|
|
272
273
|
etg, column = pdef.rsplit('-', 2)[:2]
|
|
@@ -27,7 +27,7 @@ from configparser import ConfigParser
|
|
|
27
27
|
|
|
28
28
|
from gwpy.detector import ChannelList
|
|
29
29
|
from gwpy.plot import Plot
|
|
30
|
-
from gwpy.plot.tex import
|
|
30
|
+
from gwpy.plot.tex import has_tex
|
|
31
31
|
from gwpy.segments import Segment
|
|
32
32
|
|
|
33
33
|
from .. import plot as gwsumm_plot
|
|
@@ -250,7 +250,7 @@ class TestDataPlot(TestSummaryPlot):
|
|
|
250
250
|
assert plot.channels == [get_channel('X1:TEST'),
|
|
251
251
|
get_channel('Y1:TEST')]
|
|
252
252
|
assert plot.pargs == {'marker': 'o'}
|
|
253
|
-
assert plot.rcParams
|
|
253
|
+
assert plot.rcParams['figure.figsize'] == (2, 1)
|
|
254
254
|
|
|
255
255
|
cp.set('plot', 'type', 'blah')
|
|
256
256
|
with pytest.warns(UserWarning):
|
|
@@ -281,7 +281,7 @@ class TestDataPlot(TestSummaryPlot):
|
|
|
281
281
|
pytest.param(
|
|
282
282
|
True,
|
|
283
283
|
[{'label': r'TEST\_WITH\_UNDERSCORE'}, {'label': r'TEST\_QUOTED'}],
|
|
284
|
-
marks=pytest.mark.skipif(not
|
|
284
|
+
marks=pytest.mark.skipif(not has_tex(),
|
|
285
285
|
reason='TeX is not available'),
|
|
286
286
|
),
|
|
287
287
|
])
|
|
@@ -243,6 +243,24 @@ def get_triggers(channel, etg, segments, config=GWSummConfigParser(),
|
|
|
243
243
|
else:
|
|
244
244
|
trigs = read_cache(segcache, SegmentList([segment]), etg,
|
|
245
245
|
nproc=nproc, **read_kw)
|
|
246
|
+
|
|
247
|
+
# extend columns if possible to include bandwidth, central
|
|
248
|
+
# frequency, and duration
|
|
249
|
+
if trigs is not None:
|
|
250
|
+
if 'fstart' in columns and 'fend' in columns:
|
|
251
|
+
if 'bandwidth' not in columns:
|
|
252
|
+
trigs.add_column(trigs['fend'] - trigs['fstart'],
|
|
253
|
+
name='bandwidth')
|
|
254
|
+
if 'central_freq' not in columns:
|
|
255
|
+
trigs.add_column(
|
|
256
|
+
0.5*(trigs['fstart'] + trigs['fend']),
|
|
257
|
+
name='central_freq')
|
|
258
|
+
if ('tstart' in columns and
|
|
259
|
+
'tend' in columns and
|
|
260
|
+
'duration' not in columns):
|
|
261
|
+
trigs.add_column(trigs['tend'] - trigs['tstart'],
|
|
262
|
+
name='duration')
|
|
263
|
+
|
|
246
264
|
# record triggers
|
|
247
265
|
if trigs is not None:
|
|
248
266
|
# add metadata
|
|
@@ -260,6 +278,14 @@ def get_triggers(channel, etg, segments, config=GWSummConfigParser(),
|
|
|
260
278
|
raise KeyError
|
|
261
279
|
TableClass = get_etg_table(etg)
|
|
262
280
|
except KeyError: # build simple table
|
|
281
|
+
if 'fstart' in columns and 'fend' in columns:
|
|
282
|
+
for colval in ['bandwidth', 'central_freq']:
|
|
283
|
+
if colval not in columns:
|
|
284
|
+
columns.extend([colval])
|
|
285
|
+
if ('tstart' in columns and
|
|
286
|
+
'tend' in columns and
|
|
287
|
+
'duration' not in columns):
|
|
288
|
+
columns.extend(['duration'])
|
|
263
289
|
tab = EventTable(names=columns)
|
|
264
290
|
else: # map to LIGO_LW table with full column listing
|
|
265
291
|
tab = EventTable(lsctables.New(TableClass))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: gwsumm
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: A python toolbox used by the LIGO Scientific Collaboration for detector characterisation
|
|
5
5
|
Author-email: Alex Urban <alex.urban@ligo.org>, Duncan Macleod <duncan.macleod@ligo.org>
|
|
6
6
|
Maintainer-email: Evan Goetz <evan.goetz@ligo.org>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|