Time series
A uniformly sampled time series whose samples are a NumPy or a JAX array.
:class:TimeSeries holds an array and the few numbers that place it in time: the GPS time of the
first sample and the sample rate. Time runs along the last axis; leading axes are allowed and
share that timing, so the strain of several detectors over one segment can be a single series of
shape (n_detectors, n_samples).
The array is kept as given. A NumPy array stays on the host, and a JAX array stays where it is,
on a GPU included, through every method here: each works through the array's own namespace
(data.__array_namespace__()), never by converting to NumPy. :meth:TimeSeries.to_numpy and
:meth:TimeSeries.to_jax move data deliberately.
The class is deliberately small. It has no arithmetic, spectral or plotting methods: code that
needs them works on :attr:TimeSeries.data, and a caller who wants GWpy's API converts with
:meth:TimeSeries.to_gwpy. Conversions to and from GWpy and PyCBC import those packages only when
called.
Under JAX, :func:register_pytree makes a series a pytree, so it passes through jax.jit and
jax.vmap. The samples and t0 are leaves; the sample rate, name and unit are static. The
modules that use JAX register it; importing this module never imports JAX. JAX must be in 64-bit mode
(jax.config.update("jax_enable_x64", True)): GPS times need float64, and in 32-bit mode the
methods that would lose it raise instead.
TimeSeries
dataclass
¶
A uniformly sampled series: sample k along the last axis is at t0 + k / sample_rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Any
|
The samples, an array with at least one axis; time is the last. A NumPy or a JAX
array is kept as given. Anything else is converted with :func: |
required |
t0
|
float
|
GPS time of the first sample, in seconds. |
required |
sample_rate
|
float
|
Samples per second, in Hz. |
required |
name
|
str | None
|
Optional label, such as a detector or channel name. It labels the whole series. |
None
|
unit
|
str | None
|
Optional unit of the samples, such as |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If |
Two series are equal only if they are the same object: comparing arrays elementwise has no single truth value, and a JAX array cannot be compared without a device round trip.
Source code in src/gwmock_data/timeseries.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 | |
dt
property
¶
Seconds between samples.
duration
property
¶
Seconds spanned by the samples: n_samples * dt.
end
property
¶
GPS time of the sample after the last, on the series' lattice: t0 + n_samples * dt.
grid
property
¶
The sample lattice of this series.
n_samples
property
¶
Number of samples along the time axis.
times
property
¶
GPS time of each sample, in the namespace of :attr:data, as float64.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the namespace cannot hold float64, as JAX cannot outside its 64-bit mode. In single precision a GPS time near 1.4e9 s resolves only to 128 s, so every sample of a typical series would get the same time. |
value
property
¶
The samples; an alias of :attr:data, the name GWpy uses.
xp
property
¶
The array namespace of :attr:data, such as numpy or jax.numpy.
__array__(dtype=None, copy=None)
¶
Return the samples as a NumPy array, so numpy.asarray(series) works as for GWpy.
Follows NumPy's protocol: copy=True always copies, None copies only when the dtype
or the array library requires it, and False raises ValueError when a copy would be
required -- a dtype change, or samples that are not a NumPy array.
Source code in src/gwmock_data/timeseries.py
240 241 242 243 244 245 246 247 248 249 250 251 | |
__post_init__()
¶
Validate the timing and normalise the samples to an array.
Source code in src/gwmock_data/timeseries.py
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
copy()
¶
Return a series whose samples are a copy of these.
Source code in src/gwmock_data/timeseries.py
165 166 167 | |
crop(start=None, end=None)
¶
Return the samples at GPS times in [start, end).
The bounds decide the result's length, so crop needs a concrete t0: it cannot run
inside a JAX transformation over the series.
The result starts at the first sample at or after start and stops before the first at
or after end. A bound that falls on a sample, to within the float64 resolution of GPS
times (:meth:~gwmock_data.sampling_grid.SamplingGrid.lattice_tolerance_samples), counts
as on it, so cropping at a sample's own timestamp keeps that sample however large the GPS
time. Bounds outside the series are clipped to it.
GWpy differs for a bound between samples: it rounds down, keeping the sample before
start. Here every kept sample is at or after start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
float | None
|
First GPS time to keep; |
None
|
end
|
float | None
|
GPS time to stop before; |
None
|
Returns:
| Type | Description |
|---|---|
TimeSeries
|
The cropped series, possibly with no samples. Its samples are a view where the array |
TimeSeries
|
library makes one. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a bound is not finite, or |
Source code in src/gwmock_data/timeseries.py
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
from_gwpy(series)
classmethod
¶
Return a series with the samples, timing, name and unit of a GWpy TimeSeries.
The samples are GWpy's array itself, not a copy. A dimensionless GWpy series gets
unit=None.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the GWpy series is irregularly sampled. |
Source code in src/gwmock_data/timeseries.py
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | |
from_pycbc(series, *, name=None, unit=None)
classmethod
¶
Return a series with the samples and timing of a PyCBC TimeSeries.
Source code in src/gwmock_data/timeseries.py
335 336 337 338 339 340 341 342 343 344 345 346 | |
is_compatible(other)
¶
Return whether other has the same sample rate and unit, so the two can be combined.
Source code in src/gwmock_data/timeseries.py
227 228 229 | |
pad(before=0, after=0)
¶
Return the series with before zeros prepended and after appended, in samples.
t0 moves back by before samples, so the existing samples keep their times. The
counts decide the result's length, so inside a JAX transformation they must be Python
integers, not traced values.
Raises:
| Type | Description |
|---|---|
ValueError
|
If either count is negative. |
Source code in src/gwmock_data/timeseries.py
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
to_gwpy()
¶
Return a GWpy TimeSeries with the same samples, timing, name and unit.
NumPy samples are shared, not copied, as :meth:from_gwpy shares GWpy's, so a write through
either object is seen by the other. JAX samples are brought to the host with
:func:numpy.asarray; for a CPU array that is a read-only view of JAX's buffer.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the series has more than one axis; GWpy's is one-dimensional. |
ModuleNotFoundError
|
If GWpy is not installed. |
Source code in src/gwmock_data/timeseries.py
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | |
to_jax(device=None)
¶
Return the series with its samples as a JAX array, on device if given.
Raises:
| Type | Description |
|---|---|
ModuleNotFoundError
|
If JAX is not installed. |
RuntimeError
|
If JAX is not in 64-bit mode, in which it would round double-precision samples to single precision. |
Source code in src/gwmock_data/timeseries.py
260 261 262 263 264 265 266 267 268 269 270 | |
to_numpy()
¶
Return the series with its samples as a NumPy array on the host.
Source code in src/gwmock_data/timeseries.py
256 257 258 | |
to_pycbc()
¶
Return a PyCBC TimeSeries with the same samples and timing.
PyCBC series carry neither a name nor a unit.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the series has more than one axis; PyCBC's is one-dimensional. |
ModuleNotFoundError
|
If PyCBC is not installed. |
Source code in src/gwmock_data/timeseries.py
321 322 323 324 325 326 327 328 329 330 331 332 333 | |
with_data(data)
¶
Return a series with the same timing, name and unit, holding data.
Source code in src/gwmock_data/timeseries.py
161 162 163 | |
as_timeseries(series)
¶
Return series as a :class:TimeSeries: itself, or converted from a GWpy TimeSeries.
Functions that take a time series call this on their input, so they accept either kind.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Source code in src/gwmock_data/timeseries.py
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | |
register_pytree()
¶
Register :class:TimeSeries as a JAX pytree; safe to call more than once, from any thread.
The samples and t0 are leaves, so a batch of series differing in start time can be mapped
over without recompiling. The sample rate, name and unit are static: they decide shapes and
meaning, not values.
Unflattening bypasses validation, because inside a transformation the leaves are tracers,
which cannot be checked as numbers. A series rebuilt with its start time as a JAX array that is
not float64 -- what jit, vmap, grad and device_put produce in JAX's 32-bit mode --
raises RuntimeError; structural uses that leave it a Python float, such as jax.tree.map
or jax.device_get, work in either mode.
Raises:
| Type | Description |
|---|---|
ModuleNotFoundError
|
If JAX is not installed. |
Source code in src/gwmock_data/timeseries.py
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | |