gwpy 3.0.8__py3-none-any.whl → 3.0.9__py3-none-any.whl

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.

Potentially problematic release.


This version of gwpy might be problematic. Click here for more details.

gwpy/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '3.0.8'
16
- __version_tuple__ = version_tuple = (3, 0, 8)
15
+ __version__ = version = '3.0.9'
16
+ __version_tuple__ = version_tuple = (3, 0, 9)
gwpy/astro/range.py CHANGED
@@ -25,7 +25,7 @@ import warnings
25
25
  from functools import wraps
26
26
  from math import pi
27
27
 
28
- from scipy.integrate import trapz
28
+ from scipy.integrate import trapezoid
29
29
  from scipy.interpolate import interp1d
30
30
 
31
31
  from astropy import (
@@ -238,7 +238,7 @@ def sensemon_range(psd, snr=8, mass1=1.4, mass2=1.4, fmin=None, fmax=None,
238
238
  integrand = sensemon_range_psd(psd[frange], snr=snr, mass1=mass1,
239
239
  mass2=mass2, horizon=horizon)
240
240
  return (units.Quantity(
241
- trapz(integrand.value, f.value[frange]),
241
+ trapezoid(integrand.value, f.value[frange]),
242
242
  unit=integrand.unit * units.Hertz,
243
243
  ) ** (1/2.)).to('Mpc')
244
244
 
@@ -528,7 +528,7 @@ def burst_range(psd, snr=8, energy=1e-2, fmin=100, fmax=500):
528
528
  # calculate integrand and integrate
529
529
  integrand = burst_range_spectrum(
530
530
  psd[frange], snr=snr, energy=energy) ** 3
531
- out = trapz(integrand.value, f[frange])
531
+ out = trapezoid(integrand.value, f[frange])
532
532
  # normalize and return
533
533
  return (units.Quantity(
534
534
  out / (fmax - fmin),
@@ -24,7 +24,7 @@ from unittest import mock
24
24
  import pytest
25
25
 
26
26
  from astropy import units
27
- from scipy.integrate import trapz
27
+ from scipy.integrate import trapezoid
28
28
 
29
29
  from ... import astro
30
30
  from ...testing import utils
@@ -71,7 +71,7 @@ def test_sensemon_range_psd(psd):
71
71
  r = astro.sensemon_range_psd(psd[frange])
72
72
  assert isinstance(r, FrequencySeries)
73
73
  utils.assert_quantity_almost_equal(
74
- trapz(r, r.frequencies) ** (1/2.),
74
+ trapezoid(r, r.frequencies) ** (1/2.),
75
75
  TEST_RESULTS['sensemon_range'],
76
76
  )
77
77
  assert r.f0.value > 0
@@ -103,9 +103,8 @@ def test_inspiral_range_psd(psd):
103
103
  frange = (psd.frequencies.value < 4096)
104
104
  r = astro.inspiral_range_psd(psd[frange])
105
105
  assert isinstance(r, FrequencySeries)
106
- print(trapz(r, r.frequencies) ** (1/2.))
107
106
  utils.assert_quantity_almost_equal(
108
- trapz(r, r.frequencies) ** (1/2.),
107
+ trapezoid(r, r.frequencies) ** (1/2.),
109
108
  TEST_RESULTS['inspiral_range'],
110
109
  )
111
110
  assert r.f0.value > 0
@@ -129,7 +128,7 @@ def test_burst_range_spectrum(psd):
129
128
  r = astro.burst_range_spectrum(psd[frange])
130
129
  assert isinstance(r, FrequencySeries)
131
130
  utils.assert_quantity_almost_equal(
132
- (trapz(r**3, f[frange]) / (400 * units.Hz)) ** (1/3.),
131
+ (trapezoid(r**3, f[frange]) / (400 * units.Hz)) ** (1/3.),
133
132
  TEST_RESULTS['burst_range'],
134
133
  )
135
134
  assert r.f0.value > 0
gwpy/cli/qtransform.py CHANGED
@@ -215,7 +215,7 @@ class Qtransform(Spectrogram):
215
215
  outseg = Segment(gps, gps).protract(args.plot[self.plot_num])
216
216
 
217
217
  # use the precomputed ASD as the whitener if needed
218
- if self.qxfrm_args.get("whiten"):
218
+ if self.qxfrm_args.get("whiten") is True:
219
219
  self.qxfrm_args["whiten"] = asd
220
220
 
221
221
  # This section tries to optimize the amount of data that is
gwpy/detector/units.py CHANGED
@@ -167,6 +167,7 @@ for unit, aliases in [
167
167
  # GW observatories like to record 'time' as the unit
168
168
  (units.Unit('second'), (
169
169
  'time',
170
+ 'time (s)',
170
171
  'time [s]',
171
172
  'Time [sec]',
172
173
  'Time (sec)',
gwpy/io/datafind.py CHANGED
@@ -65,6 +65,7 @@ GRB_TYPE = re.compile(r'^(?!.*_GRB\d{6}([A-Z])?$)') # *_GRBYYMMDD{A}
65
65
  HIGH_PRIORITY_TYPE = re.compile("({})".format("|".join((
66
66
  r'\A[A-Z]\d_HOFT_C\d\d(_T\d{7}_v\d)?\Z', # X1_HOFT_CXY
67
67
  r'\AV1Online\Z',
68
+ r'\AHoftOnline\Z',
68
69
  r'\AV1O[0-9]+([A-Z]+)?Repro[0-9]+[A-Z]+\Z', # V1OXReproXY
69
70
  ))))
70
71
  LOW_PRIORITY_TYPE = re.compile("({})".format("|".join((
gwpy/io/ffldatafind.py CHANGED
@@ -28,8 +28,9 @@ __author__ = "Duncan Macleod <duncan.macleod@ligo.org>"
28
28
 
29
29
  import os
30
30
  import re
31
- from warnings import warn
31
+ from collections import defaultdict
32
32
  from functools import lru_cache
33
+ from warnings import warn
33
34
 
34
35
  from ligo.segments import (
35
36
  segment,
@@ -37,8 +38,10 @@ from ligo.segments import (
37
38
  )
38
39
 
39
40
  from .cache import (
41
+ _CacheEntry,
40
42
  _iter_cache,
41
43
  cache_segments,
44
+ file_segment,
42
45
  read_cache_entry,
43
46
  )
44
47
 
@@ -123,10 +126,10 @@ def _find_ffl_files(basedir=None):
123
126
  def _find_ffls(basedir=None):
124
127
  """Find all readable FFL files.
125
128
  """
126
- ffls = {}
129
+ ffls = defaultdict(list)
127
130
  for path in _find_ffl_files(basedir=basedir):
128
131
  try:
129
- ffls[_get_site_tag(path)] = path
132
+ ffls[_get_site_tag(path)].append(path)
130
133
  except (
131
134
  OSError, # file is empty (or cannot be read at all)
132
135
  AttributeError, # last entry didn't match _SITE_REGEX
@@ -135,8 +138,8 @@ def _find_ffls(basedir=None):
135
138
  return ffls
136
139
 
137
140
 
138
- def _ffl_path(site, tag, basedir=None):
139
- """Return the path of the FFL file for a given site and tag.
141
+ def _ffl_paths(site, tag, basedir=None):
142
+ """Return the paths of all FFL files for a given site and tag.
140
143
  """
141
144
  try:
142
145
  return _find_ffls(basedir=basedir)[(site, tag)]
@@ -147,15 +150,18 @@ def _ffl_path(site, tag, basedir=None):
147
150
 
148
151
 
149
152
  @lru_cache()
150
- def _read_ffl(site, tag, basedir=None):
151
- """Read an FFL file as a list of `CacheEntry` objects
153
+ def _read_ffls(site, tag, basedir=None):
154
+ """Read all FFL files for a given site and tag
155
+ as a list of `CacheEntry` objects.
152
156
  """
153
- ffl = _ffl_path(site, tag, basedir=basedir)
154
- with open(ffl, "r") as fobj:
155
- return [
156
- type(entry)(site, tag, entry.segment, entry.path)
157
- for entry in _iter_cache(fobj, gpstype=float)
158
- ]
157
+ entries = []
158
+ for ffl in _ffl_paths(site, tag, basedir=basedir):
159
+ with open(ffl, "r") as fobj:
160
+ entries.extend(
161
+ _CacheEntry(site, tag, entry.segment, entry.path)
162
+ for entry in _iter_cache(fobj, gpstype=float)
163
+ )
164
+ return entries
159
165
 
160
166
 
161
167
  def _handle_error(action, message):
@@ -261,7 +267,7 @@ def find_urls(
261
267
  span = segment(gpsstart, gpsend)
262
268
 
263
269
  cache = [
264
- e for e in _read_ffl(site, tag) if (
270
+ e for e in _read_ffls(site, tag) if (
265
271
  e.observatory == site
266
272
  and e.description == tag
267
273
  and e.segment.intersects(span)
@@ -305,11 +311,16 @@ def find_latest(site, tag, on_missing="warn"):
305
311
  for a specific site and tag.
306
312
  """
307
313
  try:
308
- fflfile = _ffl_path(site, tag)
314
+ fflfiles = _ffl_paths(site, tag)
309
315
  except ValueError: # no readable FFL file
310
316
  urls = []
311
317
  else:
312
- urls = [read_cache_entry(_read_last_line(fflfile), gpstype=float)]
318
+ urls = [
319
+ read_cache_entry(_read_last_line(fflfile), gpstype=float)
320
+ for fflfile in fflfiles
321
+ ]
322
+ if urls: # if multiple, find the latest one
323
+ urls = sorted(urls, key=file_segment)[-1:]
313
324
 
314
325
  if not urls:
315
326
  _handle_error(on_missing, "No files found")
@@ -96,9 +96,11 @@ def test_is_ffl_file(path, result):
96
96
  # -- test ffl UI ------------
97
97
 
98
98
  FFLS = {
99
- "test.ffl": [
99
+ "a/test.ffl": [
100
100
  "/tmp/X-test-0-1.gwf 0 1 0 0",
101
101
  "/tmp/X-test-1-1.gwf 1 1 0 0",
102
+ ],
103
+ "b/test.ffl": [
102
104
  "/tmp/X-test-2-1.gwf 2 1 0 0",
103
105
  ],
104
106
  "test2.ffl": [
@@ -114,7 +116,11 @@ FFLS = {
114
116
  "test-empty.ffl": [],
115
117
  "test-bad.ffl": ["badness"],
116
118
  }
117
- TEST_URLS = [x.split()[0] for x in FFLS["test.ffl"]]
119
+ TEST_URLS = [
120
+ x.split()[0]
121
+ for key in ("a/test.ffl", "b/test.ffl")
122
+ for x in FFLS[key]
123
+ ]
118
124
 
119
125
 
120
126
  @pytest.fixture(autouse=True)
@@ -124,6 +130,7 @@ def mock_ffl(tmp_path):
124
130
  """
125
131
  for path, lines in FFLS.items():
126
132
  ffl = tmp_path / path
133
+ ffl.parent.mkdir(parents=True, exist_ok=True)
127
134
  ffl.write_text("\n".join(lines))
128
135
  with mock.patch.dict(
129
136
  "os.environ",
@@ -190,7 +197,7 @@ def test_find_latest():
190
197
  assert ffldatafind.find_latest(
191
198
  "X",
192
199
  "test",
193
- ) == sorted(x.split()[0] for x in FFLS["test.ffl"])[-1:]
200
+ ) == sorted(x.split()[0] for x in FFLS["b/test.ffl"])[-1:]
194
201
 
195
202
 
196
203
  @pytest.mark.parametrize(("on_missing", "ctx"), (
gwpy/plot/tex.py CHANGED
@@ -39,10 +39,12 @@ def _test_usetex():
39
39
  from matplotlib import (pyplot, rc_context)
40
40
  with rc_context({"text.usetex": True}):
41
41
  fig = pyplot.figure()
42
- ax = fig.gca()
43
- ax.set_xlabel(r"\LaTeX")
44
- fig.canvas.draw()
45
- pyplot.close(fig)
42
+ try:
43
+ ax = fig.gca()
44
+ ax.set_xlabel(r"\LaTeX")
45
+ fig.canvas.draw()
46
+ finally:
47
+ pyplot.close(fig)
46
48
 
47
49
 
48
50
  @lru_cache(maxsize=None)
@@ -30,6 +30,7 @@ from scipy import signal
30
30
 
31
31
  from astropy.units import (Unit, Quantity)
32
32
 
33
+ from ..types.array import COPY_IF_NEEDED
33
34
  from .window import (get_window, planck)
34
35
 
35
36
  __author__ = "Duncan Macleod <duncan.macleod@ligo.org>"
@@ -89,7 +90,7 @@ def _design_fir(wp, ws, sample_rate, gpass, gstop, window='hamming', **kwargs):
89
90
  kwargs.setdefault('pass_zero', False)
90
91
  if ws.shape == (1,):
91
92
  kwargs.setdefault('width', ws - wp)
92
- kwargs.setdefault('nyq', sample_rate/2.)
93
+ kwargs.setdefault('fs', sample_rate)
93
94
  return signal.firwin(nt, wp, window=window, **kwargs)
94
95
 
95
96
 
@@ -281,9 +282,9 @@ def bilinear_zpk(zeros, poles, gain, fs=1.0, unit='Hz'):
281
282
  zpk : `tuple`
282
283
  digital version of input zpk
283
284
  """
284
- zeros = numpy.array(zeros, dtype=float, copy=False)
285
+ zeros = numpy.array(zeros, dtype=float, copy=COPY_IF_NEEDED)
285
286
  zeros = zeros[numpy.isfinite(zeros)]
286
- poles = numpy.array(poles, dtype=float, copy=False)
287
+ poles = numpy.array(poles, dtype=float, copy=COPY_IF_NEEDED)
287
288
  gain = gain
288
289
 
289
290
  # convert from Hz to rad/s if needed
@@ -50,7 +50,7 @@ LOWPASS_IIR_100HZ = signal.iirdesign(
50
50
  analog=False, ftype='cheby1', output='zpk',
51
51
  )
52
52
  LOWPASS_FIR_100HZ = signal.firwin(
53
- 30, 100, window='hamming', width=50., nyq=512.,
53
+ 30, 100, window='hamming', width=50., fs=1024.,
54
54
  )
55
55
 
56
56
  HIGHPASS_IIR_100HZ = signal.iirdesign(
@@ -60,7 +60,7 @@ HIGHPASS_IIR_100HZ = signal.iirdesign(
60
60
  analog=False, ftype='cheby1', output='zpk',
61
61
  )
62
62
  HIGHPASS_FIR_100HZ = signal.firwin(
63
- 45, 100, window='hamming', pass_zero=False, width=-100/3., nyq=512.,
63
+ 45, 100, window='hamming', pass_zero=False, width=-100/3., fs=1024.,
64
64
  )
65
65
 
66
66
  BANDPASS_IIR_100HZ_200HZ = signal.iirdesign(
@@ -70,7 +70,7 @@ BANDPASS_IIR_100HZ_200HZ = signal.iirdesign(
70
70
  analog=False, ftype='cheby1', output='zpk',
71
71
  )
72
72
  BANDPASS_FIR_100HZ_200HZ = signal.firwin(
73
- 45, (100, 200.), window='hamming', pass_zero=False, nyq=512.,
73
+ 45, (100, 200.), window='hamming', pass_zero=False, fs=1024.,
74
74
  )
75
75
 
76
76
 
@@ -175,11 +175,11 @@ class TestSpectrogram(_TestArray2D):
175
175
 
176
176
  # test simple filter
177
177
  a2 = array.filter(*zpk)
178
- utils.assert_array_equal(array * fresp, a2)
178
+ utils.assert_quantity_sub_equal(array * fresp, a2)
179
179
 
180
180
  # test inplace filtering
181
181
  array.filter(lti, inplace=True)
182
- utils.assert_array_equal(array, a2)
182
+ utils.assert_quantity_sub_equal(array, a2)
183
183
 
184
184
  # test errors
185
185
  with pytest.raises(TypeError):
gwpy/testing/fixtures.py CHANGED
@@ -52,25 +52,8 @@ def tmpfile():
52
52
 
53
53
  # -- plotting -----------------------------------------------------------------
54
54
 
55
- def _test_usetex():
56
- """Return `True` if we can render figures using `text.usetex`.
57
- """
58
- from matplotlib import pyplot
59
- with rc_context(rc={'text.usetex': True}):
60
- fig = pyplot.figure()
61
- fig.gca()
62
- try:
63
- fig.canvas.draw()
64
- except RuntimeError:
65
- return False
66
- else:
67
- return True
68
- finally:
69
- pyplot.close(fig)
70
-
71
-
72
55
  SKIP_TEX = pytest.mark.skipif(
73
- not has_tex() or not _test_usetex(),
56
+ not has_tex(),
74
57
  reason='TeX is not available',
75
58
  )
76
59
 
gwpy/testing/utils.py CHANGED
@@ -34,12 +34,14 @@ from numpy.testing import (assert_array_equal, assert_allclose)
34
34
 
35
35
  from astropy.time import Time
36
36
 
37
- from ..utils.decorators import deprecated_function
37
+ from gwpy.io.cache import file_segment
38
+ from gwpy.utils.decorators import deprecated_function
38
39
 
39
40
  # -- useful constants ---------------------------------------------------------
40
41
 
41
42
  TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
42
43
  TEST_GWF_FILE = os.path.join(TEST_DATA_DIR, 'HLV-HW100916-968654552-1.gwf')
44
+ TEST_GWF_SPAN = file_segment(TEST_GWF_FILE)
43
45
  TEST_HDF5_FILE = os.path.join(TEST_DATA_DIR, 'HLV-HW100916-968654552-1.hdf')
44
46
 
45
47
 
@@ -328,11 +330,18 @@ def TemporaryFilename(*args, **kwargs): # pylint: disable=invalid-name
328
330
  os.remove(name)
329
331
 
330
332
 
331
- def test_read_write(data, format,
332
- extension=None, autoidentify=True,
333
- read_args=[], read_kw={},
334
- write_args=[], write_kw={},
335
- assert_equal=assert_array_equal, assert_kw={}):
333
+ def test_read_write(
334
+ data,
335
+ format,
336
+ extension=None,
337
+ autoidentify=True,
338
+ read_args=[],
339
+ read_kw={},
340
+ write_args=[],
341
+ write_kw={},
342
+ assert_equal=assert_quantity_sub_equal,
343
+ assert_kw={},
344
+ ):
336
345
  """Test that data can be written to and read from a file in some format
337
346
 
338
347
  Parameters
@@ -19,22 +19,34 @@
19
19
  """I/O utilities for reading `TimeSeries` from a `list` of file paths.
20
20
  """
21
21
 
22
- from ...io.cache import (FILE_LIKE, read_cache, file_segment, sieve)
22
+ from io import BytesIO
23
+ from math import inf
24
+ from os import PathLike
25
+
26
+ from ...io.cache import (
27
+ FILE_LIKE,
28
+ file_segment,
29
+ read_cache,
30
+ write_cache,
31
+ )
23
32
  from ...segments import Segment
24
33
 
25
34
  __author__ = "Duncan Macleod <duncan.macleod@ligo.org>"
26
35
 
27
36
 
28
- def preformat_cache(cache, start=None, end=None):
37
+ def preformat_cache(cache, start=None, end=None, sort=file_segment):
29
38
  """Preprocess a `list` of file paths for reading.
30
39
 
31
- - read the cache from the file (if necessary)
32
- - sieve the cache to only include data we need
40
+ This function does the following:
41
+
42
+ - read the list of paths cache file (if necessary),
43
+ - sort the cache in time order (if possible),
44
+ - sieve the cache to only include data we need.
33
45
 
34
46
  Parameters
35
47
  ----------
36
- cache : `list`, `str`
37
- List of file paths, or path to a LAL-format cache file on disk.
48
+ cache : `list`, `str`, `pathlib.Path`
49
+ List of file paths, or path to a cache file.
38
50
 
39
51
  start : `~gwpy.time.LIGOTimeGPS`, `float`, `str`, optional
40
52
  GPS start time of required data, defaults to start of data found;
@@ -44,31 +56,37 @@ def preformat_cache(cache, start=None, end=None):
44
56
  GPS end time of required data, defaults to end of data found;
45
57
  any input parseable by `~gwpy.time.to_gps` is fine.
46
58
 
59
+ sort : `callable`, optional
60
+ A callable key function by which to sort the file paths.
61
+
47
62
  Returns
48
63
  -------
49
64
  modcache : `list`
50
65
  A parsed, sieved list of paths based on the input arguments.
66
+
67
+ See also
68
+ --------
69
+ gwpy.io.cache.read_cache
70
+ For details of how the sorting and sieving is implemented
51
71
  """
52
- # open cache file
53
- if isinstance(cache, (str,) + FILE_LIKE):
54
- return read_cache(cache, sort=file_segment,
55
- segment=Segment(start, end))
56
-
57
- # format existing cache file
58
- cache = type(cache)(cache) # copy cache
59
-
60
- # sort cache
61
- try:
62
- cache.sort(key=file_segment) # sort
63
- except ValueError:
64
- # if this failed, then the sieving will also fail, but lets proceed
65
- # anyway, since the user didn't actually ask us to do this (but
66
- # its a very good idea)
67
- return cache
68
-
69
- # sieve cache
70
- if start is None: # start time of earliest file
71
- start = file_segment(cache[0])[0]
72
- if end is None: # end time of latest file
73
- end = file_segment(cache[-1])[-1]
74
- return sieve(cache, segment=Segment(start, end))
72
+ # if given a list of paths, write it to a file-like structure
73
+ # so that we can use read_cache to do all the work
74
+ if not isinstance(cache, (str, PathLike) + FILE_LIKE):
75
+ cachef = BytesIO()
76
+ write_cache(cache, cachef)
77
+ cachef.seek(0)
78
+ cache = cachef
79
+
80
+ # need start and end times to sieve the cache
81
+ if start is None:
82
+ start = -inf
83
+ if end is None:
84
+ end = +inf
85
+
86
+ # read the cache
87
+ return read_cache(
88
+ cache,
89
+ coltype=type(start),
90
+ sort=sort,
91
+ segment=Segment(start, end),
92
+ )
@@ -149,6 +149,14 @@ def read(source, channels, start=None, end=None, series_class=TimeSeries,
149
149
  end = epoch + streamdur
150
150
  end = min(epoch + streamdur, lalutils.to_lal_ligotimegps(end))
151
151
  duration = float(end - start)
152
+ if start >= (epoch + streamdur):
153
+ raise ValueError(
154
+ "cannot read data starting after stream ends",
155
+ )
156
+ if duration < 0:
157
+ raise ValueError(
158
+ "cannot read data with negative duration",
159
+ )
152
160
 
153
161
  # read data
154
162
  out = series_class.DictClass()
@@ -0,0 +1,74 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) Cardiff University 2023
3
+ #
4
+ # This file is part of GWpy.
5
+ #
6
+ # GWpy is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # GWpy is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with GWpy. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ """Tests for :mod:`gwpy.timeseries.io.cache`
20
+ """
21
+
22
+ import pytest
23
+
24
+ from ...io.cache import write_cache
25
+ from ..io import cache as ts_io_cache
26
+
27
+
28
+ @pytest.fixture
29
+ def cache():
30
+ """List of files over which to test sorting/sieving.
31
+ """
32
+ return [
33
+ "/tmp/A-TEST-0-10.tmp",
34
+ "/tmp/A-TEST-10-10.tmp",
35
+ "/tmp/A-TEST-20-10.tmp",
36
+ "/tmp/A-TEST-30-5.tmp",
37
+ "/tmp/A-TEST-35-15.tmp",
38
+ ]
39
+
40
+
41
+ @pytest.fixture
42
+ def cache_file(tmp_path, cache):
43
+ """File version of `cache()`.
44
+ """
45
+ path = tmp_path / "cache.txt"
46
+ write_cache(cache, path)
47
+ return path
48
+
49
+
50
+ @pytest.mark.parametrize("source", ("cache", "cache_file"))
51
+ @pytest.mark.parametrize(("start", "end", "idx"), [
52
+ # use everything in the cache
53
+ (None, None, slice(None)),
54
+ # use only GPS time '25' onwards, which is cache[2:]
55
+ (25, None, slice(2, None)),
56
+ # use only up to GPS time '25', which is cache[:3]
57
+ (None, 25, slice(None, 3)),
58
+ # use interval [10, 35), which needs cache[1:4]
59
+ (10, 35, slice(1, 4)),
60
+ ])
61
+ def test_preformat_cache(request, cache, source, start, end, idx):
62
+ """Test that `gwpy.timeseries.io.cache.preformat_cache` works properly.
63
+
64
+ Here `[start, end)` is a GPS segment, and `idx` the corresponding slice
65
+ needed to restrict the cache object.
66
+
67
+ Loops over a variety of input arguments, using `request` to dynamically
68
+ loop over `cache` or `cache_file` as the input.
69
+ """
70
+ assert ts_io_cache.preformat_cache(
71
+ request.getfixturevalue(source), # cache or cache_file
72
+ start=start,
73
+ end=end,
74
+ ) == cache[idx]
@@ -253,28 +253,29 @@ class TestTimeSeries(_TestTimeSeriesBase):
253
253
  exclude=['channel'])
254
254
 
255
255
  @pytest.mark.parametrize('api', GWF_APIS)
256
- def test_read_write_gwf_gps_errors(self, tmp_path, api):
256
+ def test_read_gwf_end_error(self, api):
257
+ """Test that reading past the end of available data fails.
258
+ """
257
259
  fmt = "gwf" if api is None else "gwf." + api
258
- array = self.create(name='TEST')
259
- tmp = tmp_path / "test.gwf"
260
- array.write(tmp, format=fmt)
261
-
262
- # check that reading past the end of the array fails
263
- with pytest.raises((ValueError, RuntimeError)):
260
+ with pytest.raises(ValueError):
264
261
  self.TEST_CLASS.read(
265
- tmp,
266
- array.name,
262
+ utils.TEST_GWF_FILE,
263
+ "L1:LDAS-STRAIN",
267
264
  format=fmt,
268
- start=array.span[1],
265
+ start=utils.TEST_GWF_SPAN[1],
269
266
  )
270
267
 
271
- # check that reading before the start of the array also fails
272
- with pytest.raises((ValueError, RuntimeError)):
268
+ @pytest.mark.parametrize('api', GWF_APIS)
269
+ def test_read_gwf_negative_duration_error(self, api):
270
+ """Test that reading a negative duration fails.
271
+ """
272
+ fmt = "gwf" if api is None else "gwf." + api
273
+ with pytest.raises(ValueError):
273
274
  self.TEST_CLASS.read(
274
- tmp,
275
- array.name,
275
+ utils.TEST_GWF_FILE,
276
+ "L1:LDAS-STRAIN",
276
277
  format=fmt,
277
- end=array.span[0]-1,
278
+ end=utils.TEST_GWF_SPAN[0]-1,
278
279
  )
279
280
 
280
281
  @pytest.mark.parametrize('api', GWF_APIS)
@@ -1073,18 +1074,22 @@ class TestTimeSeries(_TestTimeSeriesBase):
1073
1074
  fgram = gw150914.fftgram(1)
1074
1075
  fs = int(gw150914.sample_rate.value)
1075
1076
  f, t, sxx = signal.spectrogram(
1076
- gw150914, fs,
1077
+ gw150914,
1078
+ fs,
1077
1079
  window='hann',
1078
1080
  nperseg=fs,
1079
1081
  mode='complex',
1080
1082
  )
1081
1083
  utils.assert_array_equal(gw150914.t0.value + t, fgram.xindex.value)
1082
1084
  utils.assert_array_equal(f, fgram.yindex.value)
1083
- utils.assert_array_equal(sxx.T, fgram)
1085
+ utils.assert_array_equal(sxx.T, fgram.value)
1084
1086
 
1087
+ def test_fftgram_overlap(self, gw150914):
1085
1088
  fgram = gw150914.fftgram(1, overlap=0.5)
1089
+ fs = int(gw150914.sample_rate.value)
1086
1090
  f, t, sxx = signal.spectrogram(
1087
- gw150914, fs,
1091
+ gw150914,
1092
+ fs,
1088
1093
  window='hann',
1089
1094
  nperseg=fs,
1090
1095
  noverlap=fs//2,
@@ -1092,7 +1097,7 @@ class TestTimeSeries(_TestTimeSeriesBase):
1092
1097
  )
1093
1098
  utils.assert_array_equal(gw150914.t0.value + t, fgram.xindex.value)
1094
1099
  utils.assert_array_equal(f, fgram.yindex.value)
1095
- utils.assert_array_equal(sxx.T, fgram)
1100
+ utils.assert_array_equal(sxx.T, fgram.value)
1096
1101
 
1097
1102
  def test_spectral_variance(self, gw150914):
1098
1103
  variance = gw150914.spectral_variance(.5, method="median")
@@ -1381,7 +1386,9 @@ class TestTimeSeries(_TestTimeSeriesBase):
1381
1386
 
1382
1387
  def test_convolve(self):
1383
1388
  data = self.TEST_CLASS(
1384
- signal.hann(1024), sample_rate=512, epoch=-1
1389
+ signal.get_window("hann", 1024),
1390
+ sample_rate=512,
1391
+ epoch=-1,
1385
1392
  )
1386
1393
  filt = numpy.array([1, 0])
1387
1394
 
gwpy/types/array.py CHANGED
@@ -34,6 +34,11 @@ from math import modf
34
34
  import numpy
35
35
 
36
36
  from astropy.units import Quantity
37
+ try:
38
+ from astropy.utils.compat.numpycompat import COPY_IF_NEEDED
39
+ except ImportError: # astropy < 6.1
40
+ from astropy.utils import minversion
41
+ COPY_IF_NEEDED = None if minversion(numpy, "2.0.0.dev") else False
37
42
 
38
43
  from ..detector import Channel
39
44
  from ..detector.units import parse_unit
@@ -119,8 +124,16 @@ class Array(Quantity):
119
124
  unit = parse_unit(unit, parse_strict='warn')
120
125
 
121
126
  # create new array
122
- new = super().__new__(cls, value, unit=unit, dtype=dtype, copy=False,
123
- order=order, subok=subok, ndmin=ndmin)
127
+ new = super().__new__(
128
+ cls,
129
+ value,
130
+ unit=unit,
131
+ dtype=dtype,
132
+ copy=COPY_IF_NEEDED,
133
+ order=order,
134
+ subok=subok,
135
+ ndmin=ndmin,
136
+ )
124
137
 
125
138
  # explicitly copy here to get ownership of the data,
126
139
  # see (astropy/astropy#7244)
@@ -397,7 +410,7 @@ class Array(Quantity):
397
410
  out = super().__array_ufunc__(function, method, *inputs, **kwargs)
398
411
  # if a ufunc returns a scalar, return a Quantity
399
412
  if not out.ndim:
400
- return Quantity(out, copy=False)
413
+ return Quantity(out, copy=COPY_IF_NEEDED)
401
414
  # otherwise return an array
402
415
  return out
403
416
 
gwpy/types/index.py CHANGED
@@ -23,6 +23,8 @@ import numpy
23
23
 
24
24
  from astropy.units import Quantity
25
25
 
26
+ from .array import COPY_IF_NEEDED
27
+
26
28
 
27
29
  class Index(Quantity):
28
30
  """1-D `~astropy.units.Quantity` array for indexing a `Series`
@@ -57,11 +59,11 @@ class Index(Quantity):
57
59
  """
58
60
  if dtype is None:
59
61
  dtype = max(
60
- numpy.array(start, subok=True, copy=False).dtype,
61
- numpy.array(step, subok=True, copy=False).dtype,
62
+ numpy.array(start, subok=True, copy=COPY_IF_NEEDED).dtype,
63
+ numpy.array(step, subok=True, copy=COPY_IF_NEEDED).dtype,
62
64
  )
63
- start = Quantity(start, dtype=dtype, copy=False)
64
- step = Quantity(step, dtype=dtype, copy=False).to(start.unit)
65
+ start = Quantity(start, dtype=dtype, copy=COPY_IF_NEEDED)
66
+ step = Quantity(step, dtype=dtype, copy=COPY_IF_NEEDED).to(start.unit)
65
67
  stop = start + step * num
66
68
  return cls(
67
69
  numpy.arange(
@@ -71,7 +73,7 @@ class Index(Quantity):
71
73
  dtype=dtype,
72
74
  )[:num],
73
75
  unit=start.unit,
74
- copy=False,
76
+ copy=COPY_IF_NEEDED,
75
77
  )
76
78
 
77
79
  @property
@@ -19,6 +19,8 @@
19
19
  """Tests for :mod:`gwpy.utils.sphinx.zenodo`.
20
20
  """
21
21
 
22
+ from functools import wraps
23
+
22
24
  import pytest
23
25
 
24
26
  import requests
@@ -83,8 +85,23 @@ MOCK_ZENODO_API_RST = """
83
85
  """.strip()
84
86
 
85
87
 
88
+ def pytest_skip_rate_limit(func):
89
+ """Execute `func` but skip if it raises a rate limit error
90
+ """
91
+ @wraps(func)
92
+ def wrapper(*args, **kwargs):
93
+ try:
94
+ return func(*args, **kwargs)
95
+ except requests.HTTPError as exc: # pragma: no cover
96
+ if str(exc).startswith("403 Client Error: rate limit exceeded"):
97
+ pytest.skip(str(exc))
98
+ raise
99
+ return wrapper
100
+
101
+
86
102
  @pytest.fixture
87
103
  @pytest_skip_network_error
104
+ @pytest_skip_rate_limit
88
105
  def latest():
89
106
  """Get the latest release of GWpy from the GitHub API.
90
107
  """
@@ -97,6 +114,7 @@ def latest():
97
114
 
98
115
 
99
116
  @pytest_skip_network_error
117
+ @pytest_skip_rate_limit
100
118
  def test_zenodo_format_citations_latest(latest):
101
119
  """Check that :func:`gwpy.utils.sphinx.zenodo.format_citations` includes
102
120
  the latest actual release in the output.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gwpy
3
- Version: 3.0.8
3
+ Version: 3.0.9
4
4
  Summary: A python package for gravitational-wave astrophysics
5
5
  Author-email: Duncan Macleod <duncan.macleod@ligo.org>
6
6
  License: GPL-3.0-or-later
@@ -37,7 +37,7 @@ Requires-Dist: matplotlib >=3.3.0
37
37
  Requires-Dist: numpy >=1.19
38
38
  Requires-Dist: python-dateutil
39
39
  Requires-Dist: requests
40
- Requires-Dist: scipy >=1.5.0
40
+ Requires-Dist: scipy >=1.6.0
41
41
  Requires-Dist: tqdm >=4.10.0
42
42
  Provides-Extra: astro
43
43
  Requires-Dist: inspiral-range >=0.5.0 ; extra == 'astro'
@@ -1,16 +1,16 @@
1
1
  gwpy/__init__.py,sha256=3chu5cxfVA08qkFYk3lyXBlFXO6lrgytIIdh_nL9YzU,1533
2
- gwpy/_version.py,sha256=UsWpfolO3V5lhkRSzLYHaglRPoxe1Nfcc4kMi3j-8W8,411
2
+ gwpy/_version.py,sha256=tG9pPVh8tGuhiLuhmkU2HBdW-0Eea4piRXA-Q5yaT30,411
3
3
  gwpy/conftest.py,sha256=nMqidKFNcwTCvDb-vHzzCmzUyyL0TH9DwbmagfdE1II,1639
4
4
  gwpy/astro/__init__.py,sha256=DtaqsbVdlI4Qy6eRlXuLtraTCLXjpQYadk5pEFwXrM8,1909
5
- gwpy/astro/range.py,sha256=ah1TLCNk8Pq8YBHaXKuglShO8rFbmDgO2z4SOuWlDEc,24880
5
+ gwpy/astro/range.py,sha256=BcRrJkgxiceL1QsOy1uUtCMslEeic0MUxWFs76LgY0Y,24892
6
6
  gwpy/astro/tests/__init__.py,sha256=jDVhmCPpiwaMzDz1Dq_TQTd4rfY5it5qfZ17bohcCOo,746
7
- gwpy/astro/tests/test_range.py,sha256=o1WFz2rRzqqI1V_RdIVb2GaPxWZpIDHjc0MzD_M8zn4,6032
7
+ gwpy/astro/tests/test_range.py,sha256=ikKMYljmQe6IMWRMi2Vn48y5So_RVibD0U-ioLoEODk,6003
8
8
  gwpy/cli/__init__.py,sha256=3DnwWaykhjk-bT0h3n-f8vSHNtGzpi7RVG3rbOkFQhM,1404
9
9
  gwpy/cli/cliproduct.py,sha256=9OPACkQyjQmRtEmIgis4O3NaQLQV7AvEET1T44rSyLM,34269
10
10
  gwpy/cli/coherence.py,sha256=CbGwFl9pLHNncBMRdEr5mv-6EJLuML56Tp_kMD4F-Ds,4048
11
11
  gwpy/cli/coherencegram.py,sha256=mpGG3fHBR2OfjhfnRm3VgewAdr6wUgB6kwtsCeWnc64,3353
12
12
  gwpy/cli/gwpy_plot.py,sha256=CaxV0CsLUjsj24hGjjn5pwmKGq10I3-4qJoZvOKlSf0,5099
13
- gwpy/cli/qtransform.py,sha256=aXtgnc0Jb6UnHsaVDHuYhZclj4jsS6OPN5VnKrMg-dk,9140
13
+ gwpy/cli/qtransform.py,sha256=jC44b5YLmR5N5CC6YN5FrnntOEPD1wb-Sk8N4Dif840,9148
14
14
  gwpy/cli/spectrogram.py,sha256=NlNHVJhjb162j5P5e0G_6ngcbPlCW31Umw-IqKmsqGs,7131
15
15
  gwpy/cli/spectrum.py,sha256=IpBhoi70h1Cx1R6qlA3RMCyB7BXWrNFyQEVRpEIOSWE,4899
16
16
  gwpy/cli/timeseries.py,sha256=GWRQnUzc0oI2cJlDTTGnwRdFaL2X0ky8nlzMZF6dlvs,3891
@@ -27,7 +27,7 @@ gwpy/cli/tests/test_timeseries.py,sha256=HCYeRdk1Y7owMHTURmV-G9N4iSPZpoKXKvfigOr
27
27
  gwpy/cli/tests/test_transferfunction.py,sha256=VCve5NgBQo7tBgM5zaBlqY29R0ymc7Tfk9pRpJLsBdg,1999
28
28
  gwpy/detector/__init__.py,sha256=gsC_0ca8m8xRQzQ8ns6fpwFQ14_uxUu1LRh1B-sN6EA,2252
29
29
  gwpy/detector/channel.py,sha256=2X37knAbqzDg3GavKheXnOHOAgVaPHrOFQ4f4WpmvPc,26786
30
- gwpy/detector/units.py,sha256=4Ne7sq5oliJQlTVVbASBzwdLXvxdvB6gQo8Sz100vxI,7303
30
+ gwpy/detector/units.py,sha256=W_a50ebj_OJ82-yHoSCtxNni8jKOXhhqOLHINY5ui5I,7323
31
31
  gwpy/detector/io/__init__.py,sha256=dAsz8ii5RVhwI_BNVjYrsnX1Pt3nfjh8jqVl4xqLTec,1037
32
32
  gwpy/detector/io/cis.py,sha256=gHGnB68xMAv0xQUG4eazA-4Jp0BesYlrttPBXt2g2Qs,3184
33
33
  gwpy/detector/io/clf.py,sha256=AusPzKEEuJM6qRyrAzBKmVeYrpnU8Tniql1DPtVHW28,5689
@@ -49,8 +49,8 @@ gwpy/frequencyseries/tests/test_hist.py,sha256=rfd6PEjp30TwoTD8ajlUkdTKOkqZs5hs3
49
49
  gwpy/io/__init__.py,sha256=Y-QjvthCmjEKRHxix-0iZjx9-VKT30ynPT4bWbKdAA4,831
50
50
  gwpy/io/_framecpp.py,sha256=1CTZgxJ7YD8tZv_zP9Hucj9_TE0oMrtdhFWSncZ5jzo,4250
51
51
  gwpy/io/cache.py,sha256=6kX4akC7a9m3B8AvDmwVYgiVkBb2L6B3IiPFyoweAnw,15124
52
- gwpy/io/datafind.py,sha256=QDuGUXZwr4rJHpM-nLbBxCIa_mxs1TOs19fTywE1f3M,18462
53
- gwpy/io/ffldatafind.py,sha256=LMJQpZ5BmaybzxuFwHKo9UwVFmgmQt6GJrLZMag_4hY,8399
52
+ gwpy/io/datafind.py,sha256=MEgH8n2YjIT21AY_jAIUJDtT994F87n2rEwTMMCwF0w,18485
53
+ gwpy/io/ffldatafind.py,sha256=OFcMEPT8FqKFMV_tnwRIggqvLgUSgVYWcdP1FnRrwnk,8766
54
54
  gwpy/io/gwf.py,sha256=6MxFq9-59nwOcHe7d13zF9BYpDfVCXaINK-KvntF7ZU,18966
55
55
  gwpy/io/hdf5.py,sha256=Pg8zIv1dy7I9Z0sBM6vtry97igHej5gFnBukjsTiiX0,5257
56
56
  gwpy/io/kerberos.py,sha256=4tFPQ5iOy6cOe9MCEJqVqJZZ287EKh8VF64BPPiOPH0,6928
@@ -62,7 +62,7 @@ gwpy/io/utils.py,sha256=xLn9EI1VrSX2NqhsTvLvBLg8vLKQXPD6L0MOL8Z9WDg,7341
62
62
  gwpy/io/tests/__init__.py,sha256=4QFcOfH6EHMs-fH0nYKYwgKlf2-c5bINDOjhULDWc20,743
63
63
  gwpy/io/tests/test_cache.py,sha256=-FB4qcbFDKkzdC4gyt-vFnqIyhvfPw0EiZ1RJgjAFEQ,8567
64
64
  gwpy/io/tests/test_datafind.py,sha256=LERgMx4kkEOlrFhugYqPv3Aahp5THC0-q36oTwGsU9c,10597
65
- gwpy/io/tests/test_ffldatafind.py,sha256=dKKRrFOUIScwTQC7ZWMu_kI5FLp1QLwXlkJqpJu49eE,6277
65
+ gwpy/io/tests/test_ffldatafind.py,sha256=IS6cILpWRdkxSribsRt15wvhGxhVEOjwjHEmF9lPV00,6409
66
66
  gwpy/io/tests/test_gwf.py,sha256=qCnxxjGKlKv73YcmUxGJJoLQPlTCTvbPu2ivj5V1lN8,4228
67
67
  gwpy/io/tests/test_kerberos.py,sha256=LsH2ux8B3biMT9XGHvmpbH84Twu3nqZtAPVoTifmVH0,6492
68
68
  gwpy/io/tests/test_ligolw.py,sha256=62XIFD8T5Omfz4qoZcoDtPHuwgSUYccYSZBEouVgdy0,10701
@@ -80,7 +80,7 @@ gwpy/plot/log.py,sha256=Sn1BJRB5ml0oqE8UXBphb7MDhwu7ru-UtlvG4i5qTyE,5030
80
80
  gwpy/plot/plot.py,sha256=Ci8bxBgld4PjbeFtQQ_19ryYENJ1EHcIQN7f18Xi99c,21866
81
81
  gwpy/plot/rc.py,sha256=cK8pOzcvuRsMv_16k9Hl2mkn_dk8FaRrIVhtNhBzyp8,4816
82
82
  gwpy/plot/segments.py,sha256=HhjQEv8G00Rp7iRun98CGIk91-c_vAvEsv-uch3CbyU,16943
83
- gwpy/plot/tex.py,sha256=KZXQzqloDFuv5sfVw7-qNjk54FalYHg7Qjae0cs3-Cs,4819
83
+ gwpy/plot/tex.py,sha256=W1EPjdd9T6H2irDsbbbNNLL_CqBcYRTcAWx9OlsCcFg,4869
84
84
  gwpy/plot/text.py,sha256=SPVO-QQe6B6SaPiycS38EwZGmVbwQfxQfQ1cjbGeOiI,1989
85
85
  gwpy/plot/units.py,sha256=D0bWwYIAg-QuWpsNvze9UFuHoBX9p81B-Dlj5kbDxRQ,1825
86
86
  gwpy/plot/utils.py,sha256=uRz9Gqy_2Mxk-2Nvw9wy-kIoAKUDeSDALMRkSziQyZY,1670
@@ -110,7 +110,7 @@ gwpy/segments/tests/test_flag.py,sha256=LdpG9PUjlirl-54rdMDRv4d4ASJbhWmpA6RVVltR
110
110
  gwpy/segments/tests/test_segments.py,sha256=VSvjy3p4MuVyucK_QB5PfOjZ0FvJU-jd4pNHv7ppiE8,5360
111
111
  gwpy/signal/__init__.py,sha256=1FcrzAPP5fkp9OzrpQyrDswINDqGuLYY_cdtJQttB64,972
112
112
  gwpy/signal/fft.py,sha256=YS2g5Urh5Y4x_L2rGts11O5t-M5Y_yAtAvrFkqTv4KQ,1189
113
- gwpy/signal/filter_design.py,sha256=cqCl0Yu_PrSOgGC2j_jjtFdtPzsl6d0F1jKuG_fMWok,20270
113
+ gwpy/signal/filter_design.py,sha256=AzRxYJKGaIz7dAmv0qbTvqzCo1nSpzRepV6KORWzdpI,20325
114
114
  gwpy/signal/qtransform.py,sha256=3yhxkioNa3EdwKvsmvYoXnQqA8VPAZW58OnAuE4YHxw,24471
115
115
  gwpy/signal/window.py,sha256=ukwcyoAtmLC6LWGyvcOh-gyh0s8paIVk3Z5gjCUk9F8,5927
116
116
  gwpy/signal/spectral/__init__.py,sha256=dEKuHIaekXqgmoBJ-gvE0xWym9d7STcAAmewY8qo8xI,1818
@@ -123,7 +123,7 @@ gwpy/signal/spectral/_ui.py,sha256=MbB3aSUFS4bS5S39fEcSqyhbC6Foq15PGlazVJalWjM,1
123
123
  gwpy/signal/spectral/_utils.py,sha256=qSaj1GctqOd4HmiVwtfUUrBXvZAh0WJYbKiePUKEa1E,1669
124
124
  gwpy/signal/tests/__init__.py,sha256=k8yHNX5UvKYZCwZQA4oDEK7gNAYMX7JLhztV67_JoOY,747
125
125
  gwpy/signal/tests/test_coherence.py,sha256=Rk3l7vbvoG4uHIMJodsjchocKWaaKMD0KH3tq_NgDFw,5119
126
- gwpy/signal/tests/test_filter_design.py,sha256=16BgVPMAFcHML4gsvioT3rLkagiV2vengGNxLJDnGHM,4349
126
+ gwpy/signal/tests/test_filter_design.py,sha256=_TyguEED-zkv594XdcKaYkic0EhVFBYHPAHza8UyzAg,4349
127
127
  gwpy/signal/tests/test_qtransform.py,sha256=LKBow9vIYI7jRNjuzw53WgsJYMSv9EwkQt-T_Xti1Uk,4017
128
128
  gwpy/signal/tests/test_spectral_lal.py,sha256=b7LkyTYtSMVBxikwHQQG042SS1_Zj8WHYqHXWB8lXvo,3543
129
129
  gwpy/signal/tests/test_spectral_median_mean.py,sha256=K5436i5He7_f9N4xI3pyziIKkKaVQOO_lr9kWR4Q3_E,2195
@@ -139,7 +139,7 @@ gwpy/spectrogram/spectrogram.py,sha256=O5Q8I3iGKRJPuw2abgGElXgpDTc1tyNTpRxCLteDj
139
139
  gwpy/spectrogram/io/__init__.py,sha256=JV8rlAcWqxqxMDhPOeGpOHZplqEfMij7KCIJjyJKhWE,846
140
140
  gwpy/spectrogram/io/hdf5.py,sha256=lhYN6Sz8NbjwjiDg9uMwsJyyrUfOJyIDFA93LcuEafs,963
141
141
  gwpy/spectrogram/tests/__init__.py,sha256=wbvEjFoPSs3mjTQEn93ZBYxSmZeK7Qkx9IFyUplQXco,752
142
- gwpy/spectrogram/tests/test_spectrogram.py,sha256=0NU-walZSbBIKMInn1xzbtdkE7esCSldBxQYLAN8tE8,6590
142
+ gwpy/spectrogram/tests/test_spectrogram.py,sha256=HNvTZ78HAlk1sPDCoGKui3r36Si6LjTaOt8ityyMgLI,6604
143
143
  gwpy/table/__init__.py,sha256=RQrS8y375ofpT1qOTyL4eh-QZ8wA9NIfOqu14GK58g0,1418
144
144
  gwpy/table/filter.py,sha256=TV2Krai3cVgHMCJ4oBScwrDDecMShhLRjGRyXeOqEFk,7918
145
145
  gwpy/table/filters.py,sha256=SbUWB-yid0G8_2q577-VvJxOsNt_qBGFDYS6cbKjJAM,2645
@@ -169,10 +169,10 @@ gwpy/table/tests/test_io_pycbc.py,sha256=65f_AXgD2DCeIcz-rDOucjRStWRd__VQRfK1gcY
169
169
  gwpy/table/tests/test_table.py,sha256=HthR885GqcBQSB8vD5Q6sOSPHojo8m5fa8HPeFx5m6w,30399
170
170
  gwpy/testing/__init__.py,sha256=_dtbhI4nOnnUPu8hLZUTUZxgPCq2KB2ATZiLEns9ybw,745
171
171
  gwpy/testing/errors.py,sha256=WeRm5QbqfFNxvNvXnrTBj7NOueJPMQJErmiGstZBL50,2783
172
- gwpy/testing/fixtures.py,sha256=G2wyCcVFYaeSG5zZ_MiKbRrieIGk0KHitHVXvQyRyAk,3774
172
+ gwpy/testing/fixtures.py,sha256=pu0sA3l3rcs0osVj97C0lmENYDa-1SF5B44uXey5cb0,3344
173
173
  gwpy/testing/marks.py,sha256=BIZ2Q4yfJSS9YQWCWSOwt66JKFnrhbx5XPXbvwfuFyo,1480
174
174
  gwpy/testing/mocks.py,sha256=3GoAT1z-1LJXNuoskCmpSi3GTqAa_quO7Tm5pyns0SA,4131
175
- gwpy/testing/utils.py,sha256=9ifPU06_yKE1icqHGOxVs5TKkHLTYRspoMYC5j9-7yE,12002
175
+ gwpy/testing/utils.py,sha256=yb6HFq_bmqlXiYkM1f-dzKkMBqBtipFhdQwSpI3yDSU,12058
176
176
  gwpy/testing/data/H1-LDAS_STRAIN-968654552-10.xml.gz,sha256=sEScnAbXjkcGtlY3GN_x0ual25EUWRaAGK31hvLOpW4,58124
177
177
  gwpy/testing/data/HLV-HW100916-968654552-1.gwf,sha256=AE5d5_T2MgQ7nnNC-cbnkKhRwc0USW_VjGXHEJzg5Hc,377295
178
178
  gwpy/testing/data/HLV-HW100916-968654552-1.hdf,sha256=5Yedvju4PUFFa17sZVIiBdbSwFlLTMF6UgrB7QvMJTw,382679
@@ -190,7 +190,7 @@ gwpy/timeseries/statevector.py,sha256=Ns65za6o1L49mXUN-WukP-Lz3vxQw330Od2FzPjQGb
190
190
  gwpy/timeseries/timeseries.py,sha256=lg28EEMASBR2IS_4gJfcU0j3uo7tEfFEVjK-Uv64ziw,87809
191
191
  gwpy/timeseries/io/__init__.py,sha256=qviFCaeTVeTZ7ZiIQKQyU1xxh76Ba60yE9vVtm9y1bY,938
192
192
  gwpy/timeseries/io/ascii.py,sha256=M05FDTCa06KLJ1Sb0jDh3NxrmMboV73j38nyMacVPkQ,1185
193
- gwpy/timeseries/io/cache.py,sha256=x80oku7oIbq-6FnHiEu4Ug85TWDLg09gBU-fh2Z0iLA,2602
193
+ gwpy/timeseries/io/cache.py,sha256=xN-lSjsBy7Heo_9X7FVRYneA4HaEMpLs4Q1Zc7lJSoA,2794
194
194
  gwpy/timeseries/io/core.py,sha256=1hp7f7UgcEEqw1T9Oa0DGMMg6uyKJih8h4A3rNkx0SQ,4692
195
195
  gwpy/timeseries/io/hdf5.py,sha256=eGiqWQIdD3Lu-74F6qiw9dKq6GSjBHoroanNsdzcy2E,4214
196
196
  gwpy/timeseries/io/losc.py,sha256=QwBdN-E2CU7L27QRg80RLM1U3TwJ_4abpudci3STt8M,9419
@@ -199,18 +199,19 @@ gwpy/timeseries/io/wav.py,sha256=E_EjIa43nzpps18x-ekollMvgPbrKyqt1v_VAXicbPQ,359
199
199
  gwpy/timeseries/io/gwf/__init__.py,sha256=C1HRu4OVns8pTPQG7hLTZFxqIS7PZnt1cLmKKf5m4OQ,13156
200
200
  gwpy/timeseries/io/gwf/framecpp.py,sha256=sFrsWr5uiE5p7wym-u3oMPsKih4OckZoXLdnTLKbfS0,17223
201
201
  gwpy/timeseries/io/gwf/framel.py,sha256=UQuydhR9reAgSmYSI0lqHJ7120gDyXHoImaQUjXz0mc,4776
202
- gwpy/timeseries/io/gwf/lalframe.py,sha256=dH-rwLkqgoiUYQAcZvitT-rmCIOXrYoL2tCezlFqNGY,7485
202
+ gwpy/timeseries/io/gwf/lalframe.py,sha256=zXaDxnSWW9d3xdkwm8hQLnQAN_hEmTuZ4ibsJYndBzw,7729
203
203
  gwpy/timeseries/tests/__init__.py,sha256=QJdnWz_IQOTYq6MvKuBzz2HFiNVf6QMXrZ-kDks-lDI,751
204
204
  gwpy/timeseries/tests/test_core.py,sha256=9tJ5_ifgdW91Ga_l7AoExLN9QAMNaTcgNep3eu7Rvbc,19685
205
+ gwpy/timeseries/tests/test_io_cache.py,sha256=nEEDjEaJ8Nf9KV2p6k9LchbmhvU-O5xcmJT2gbC5QZw,2294
205
206
  gwpy/timeseries/tests/test_io_gwf_framecpp.py,sha256=2EHmlVLbM3J-6YQmaxiCHNL1Fiw7Lur4fRiMJDCY1kM,2265
206
207
  gwpy/timeseries/tests/test_io_gwf_lalframe.py,sha256=iD9m01menvAgUXoGJnX7Xv-O5t3mgX2C2N2nRN-gitY,5479
207
208
  gwpy/timeseries/tests/test_io_losc.py,sha256=E_bLM3bc4TO2-cMOEF3vDG8cr6TKgQwPY-EBN6DzyUg,1833
208
209
  gwpy/timeseries/tests/test_statevector.py,sha256=NOSe4BRwIKoaax_YnxoP2UQ1mpy4Zbw8zJPbcI8OHzE,12935
209
- gwpy/timeseries/tests/test_timeseries.py,sha256=7J7KjGFtkphtec09ZqRwSzZviDvJLpECJFxAdZWg1Tk,57276
210
+ gwpy/timeseries/tests/test_timeseries.py,sha256=wKjGLCJAx_sgX9DIHk1-Kv-GpgqRQ3j6fwxXB_MCx3I,57513
210
211
  gwpy/types/__init__.py,sha256=JIpXRdi0av2V0BkynOwUhijxQShSAqE5gLrowJ6Nckg,1159
211
- gwpy/types/array.py,sha256=JiwmwXmSIYY-Y08yrs5sUJu3a0iAQT3kE0mWmKT3g7M,15282
212
+ gwpy/types/array.py,sha256=D4EwGC80hKFhrRuFD3xnHaqJR7jdT88v5nik-3o-RU0,15595
212
213
  gwpy/types/array2d.py,sha256=NtwW5T6PWHiAS6kFYUfF8fm3WE4qQdPbXN01iaBET0k,12367
213
- gwpy/types/index.py,sha256=JMvhf5HyT8mIRemj3aBY0A6aliEKMgyt6rDGNoiPO0Y,3074
214
+ gwpy/types/index.py,sha256=35bEHsDmxTyDFItjngxZUrfk2l-bw1TkTse4KCLqTBk,3154
214
215
  gwpy/types/series.py,sha256=zcRvwoFoVJbpxBs8-eTdx7zV3Vb_B4oEtv3dXwj0lWM,36490
215
216
  gwpy/types/sliceutils.py,sha256=Eaqbn0ZCCQ4couMm4JuL51-3tIcykotk5vPnGBYqD20,3619
216
217
  gwpy/types/io/__init__.py,sha256=B5A4gqpldCnd9LjZ0BEWU5qaJI-tWU-Du0n_gEcw1Cs,905
@@ -243,10 +244,10 @@ gwpy/utils/tests/test_misc.py,sha256=rkTxdu7gv9Dxs0OI6IvGivGiAs3PuK8ckMtNF5_kE6I
243
244
  gwpy/utils/tests/test_mp.py,sha256=kZXUTFqCPi4wvCkGgSSk8XrG9pHPGakPNuNUykgSp-k,2062
244
245
  gwpy/utils/tests/test_shell.py,sha256=arHzI96Rmje5JPhbQ33vEN0ByRh8qwRVqfl4-jzLUv4,2334
245
246
  gwpy/utils/tests/test_sphinx_ex2rst.py,sha256=KcIBPWTsPp00iTdYT6bZ8g2F7bN66PaX5uLJlcWu0J0,2263
246
- gwpy/utils/tests/test_sphinx_zenodo.py,sha256=j40acUCrU8OjO0kPwzxWqq5yTqwTAJHgWJmvvrtB9KM,4556
247
- gwpy-3.0.8.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
248
- gwpy-3.0.8.dist-info/METADATA,sha256=KO4nJzOIEgKR0QPkyKmId50ePUTl0CmWFHhehyOKoCc,5191
249
- gwpy-3.0.8.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
250
- gwpy-3.0.8.dist-info/entry_points.txt,sha256=pcO_XRknobU7b1uuxFb3nTdGMk8FrHQsWBOflnj6Ev8,54
251
- gwpy-3.0.8.dist-info/top_level.txt,sha256=0XRdsSjFdBe_QF_Qst002-CCxuuO13ag2n-11nBpZ4E,5
252
- gwpy-3.0.8.dist-info/RECORD,,
247
+ gwpy/utils/tests/test_sphinx_zenodo.py,sha256=9mtDwuB9J75I8azfUaU4ebAH24-SROS2A6XAv8yp0ng,5059
248
+ gwpy-3.0.9.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
249
+ gwpy-3.0.9.dist-info/METADATA,sha256=tQyNrVzUMXeRAgG2DWNf-E-DpOxdchssHzNsuDVntZQ,5191
250
+ gwpy-3.0.9.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
251
+ gwpy-3.0.9.dist-info/entry_points.txt,sha256=pcO_XRknobU7b1uuxFb3nTdGMk8FrHQsWBOflnj6Ev8,54
252
+ gwpy-3.0.9.dist-info/top_level.txt,sha256=0XRdsSjFdBe_QF_Qst002-CCxuuO13ag2n-11nBpZ4E,5
253
+ gwpy-3.0.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (70.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes