lisainstrument 2.2.1__tar.gz → 2.3.0__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.
Files changed (104) hide show
  1. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/PKG-INFO +1 -1
  2. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/__init__.py +1 -1
  3. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/__init__.py +4 -0
  4. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_defaults.py +36 -36
  5. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_file_reader.py +49 -9
  6. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_file_reader_v2_0_0.py +35 -0
  7. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_file_reader_v2_1_0.py +35 -0
  8. lisainstrument-2.3.0/lisainstrument/instru/instru_file_reader_v2_2_0.py +461 -0
  9. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_formulas.py +4 -6
  10. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_model.py +55 -95
  11. lisainstrument-2.3.0/lisainstrument/instru/instru_model_config.py +87 -0
  12. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_orbsrc.py +28 -15
  13. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_store.py +19 -4
  14. lisainstrument-2.3.0/lisainstrument/instru/instru_store_v2_2_0.py +943 -0
  15. lisainstrument-2.3.0/lisainstrument/instru/instru_ttlsrc.py +120 -0
  16. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instrument.py +57 -64
  17. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/orbiting/constellation_enums.py +18 -9
  18. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/orbiting/orbit_source_interp.py +40 -5
  19. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/__init__.py +1 -0
  20. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/types_numpy.py +7 -0
  21. lisainstrument-2.3.0/lisainstrument/ttl/__init__.py +0 -0
  22. lisainstrument-2.3.0/lisainstrument/ttl/ttl_file_reader.py +39 -0
  23. lisainstrument-2.3.0/lisainstrument/ttl/ttl_file_writer.py +47 -0
  24. lisainstrument-2.3.0/lisainstrument/ttl/ttl_source.py +127 -0
  25. lisainstrument-2.3.0/lisainstrument/ttl/ttl_source_interp.py +214 -0
  26. lisainstrument-2.3.0/lisainstrument/ttl/ttl_source_static.py +87 -0
  27. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/pyproject.toml +1 -1
  28. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/LICENSE +0 -0
  29. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/README.md +0 -0
  30. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/__main__.py +0 -0
  31. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/cli/__init__.py +0 -0
  32. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/cli/run_simulation.py +0 -0
  33. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/freqplan/__init__.py +0 -0
  34. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/freqplan/fplan_file.py +0 -0
  35. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/freqplan/fplan_source.py +0 -0
  36. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/freqplan/fplan_source_interp.py +0 -0
  37. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/glitches/__init__.py +0 -0
  38. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/glitches/glitch_file.py +0 -0
  39. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/glitches/glitch_source.py +0 -0
  40. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/glitches/glitch_source_interp.py +0 -0
  41. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/gwsource/__init__.py +0 -0
  42. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/gwsource/gw_file.py +0 -0
  43. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/gwsource/gw_source.py +0 -0
  44. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/gwsource/hdf5util.py +0 -0
  45. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_filter.py +0 -0
  46. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_fplan.py +0 -0
  47. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_glitchsrc.py +0 -0
  48. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_gwsrc.py +0 -0
  49. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_locking.py +0 -0
  50. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_noises.py +0 -0
  51. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_store_v2_0_0.py +0 -0
  52. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/instru/instru_store_v2_1_0.py +0 -0
  53. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/__init__.py +0 -0
  54. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/containers.py +0 -0
  55. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/dsp.py +0 -0
  56. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/dynamic_delay_dsp.py +0 -0
  57. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/fixed_shift_dsp.py +0 -0
  58. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/hexagon.py +0 -0
  59. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/legacy_plots.py +0 -0
  60. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/noises.py +0 -0
  61. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/pyplnoise/LICENSE +0 -0
  62. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/pyplnoise/__init__.py +0 -0
  63. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/legacy/pyplnoise/pyplnoise.py +0 -0
  64. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/noisy/__init__.py +0 -0
  65. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/noisy/estimate_psd.py +0 -0
  66. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/noisy/noise_defs.py +0 -0
  67. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/noisy/noise_defs_lisa.py +0 -0
  68. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/noisy/noise_gen_numpy.py +0 -0
  69. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/orbiting/__init__.py +0 -0
  70. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/orbiting/orbit_file.py +0 -0
  71. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/orbiting/orbit_source.py +0 -0
  72. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/adaptive_delay_numpy.py +0 -0
  73. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/chunked_splines.py +0 -0
  74. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/dynamic_delay_numpy.py +0 -0
  75. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/fir_filters_numpy.py +0 -0
  76. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/fixed_shift_numpy.py +0 -0
  77. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/iir_filters_numpy.py +0 -0
  78. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/regular_interpolators.py +0 -0
  79. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/sigpro/shift_inversion_numpy.py +0 -0
  80. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/__init__.py +0 -0
  81. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/analysis.py +0 -0
  82. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/array.py +0 -0
  83. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/delay.py +0 -0
  84. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/derivative.py +0 -0
  85. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/expression.py +0 -0
  86. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/firfilter.py +0 -0
  87. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/graph_util.py +0 -0
  88. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/hdf5_store.py +0 -0
  89. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/iirfilter.py +0 -0
  90. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/integrate.py +0 -0
  91. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/noise.py +0 -0
  92. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/noise_alt.py +0 -0
  93. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/null_store.py +0 -0
  94. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/numpy_store.py +0 -0
  95. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/sampling.py +0 -0
  96. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/scheduler.py +0 -0
  97. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/scheduler_dask.py +0 -0
  98. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/scheduler_serial.py +0 -0
  99. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/segments.py +0 -0
  100. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/shift_inv.py +0 -0
  101. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/store.py +0 -0
  102. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/streams.py +0 -0
  103. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/streams/time.py +0 -0
  104. {lisainstrument-2.2.1 → lisainstrument-2.3.0}/lisainstrument/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lisainstrument
3
- Version: 2.2.1
3
+ Version: 2.3.0
4
4
  Summary: Simulates the LISA measurement chain (noise and signals) and generates telemetry data
5
5
  Home-page: https://gitlab.in2p3.fr/lisa-simulation/instrument
6
6
  License: BSD 3-Clause
@@ -2,7 +2,7 @@
2
2
 
3
3
  from .glitches import glitch_file
4
4
  from .gwsource import gw_file
5
- from .instru import SimResultFile, sim_result_file
5
+ from .instru import SimResultFile, sim_result_file, ttl_source_from_metadata
6
6
  from .instrument import Instrument
7
7
  from .orbiting import MosaID, SatID, orbit_file
8
8
  from .streams import SchedulerConfigParallel, SchedulerConfigSerial
@@ -19,3 +19,7 @@ from lisainstrument.instru.instru_store import (
19
19
  SimResultsNumpyFull,
20
20
  store_instru_hdf5,
21
21
  )
22
+ from lisainstrument.instru.instru_ttlsrc import (
23
+ init_ttl_source,
24
+ ttl_source_from_metadata,
25
+ )
@@ -72,13 +72,13 @@ Default based on LISANode
72
72
  """
73
73
 
74
74
 
75
- TTL_COEFFS_LOCAL_PHIS: Final[dict[str, float]] = {
76
- "12": 2.005835e-03,
77
- "23": 2.105403e-04,
78
- "31": -1.815399e-03,
79
- "13": -2.865050e-04,
80
- "32": -1.986657e-03,
81
- "21": 9.368319e-04,
75
+ TTL_COEFFS_LOCAL_PHIS: Final[dict[MosaID, float]] = {
76
+ MosaID.MOSA_12: 2.005835e-03,
77
+ MosaID.MOSA_23: 2.105403e-04,
78
+ MosaID.MOSA_31: -1.815399e-03,
79
+ MosaID.MOSA_13: -2.865050e-04,
80
+ MosaID.MOSA_32: -1.986657e-03,
81
+ MosaID.MOSA_21: 9.368319e-04,
82
82
  }
83
83
  """Value to use if ttl_coeffs == "default"
84
84
 
@@ -86,39 +86,39 @@ Default values were drawn from the same distributions used for ttl_coeffs == "ra
86
86
  """
87
87
 
88
88
 
89
- TTL_COEFFS_DISTANT_PHIS: Final[dict[str, float]] = {
90
- "12": 1.623910e-03,
91
- "23": 1.522873e-04,
92
- "31": -1.842871e-03,
93
- "13": -2.091585e-03,
94
- "32": 1.300866e-03,
95
- "21": -8.445374e-04,
89
+ TTL_COEFFS_DISTANT_PHIS: Final[dict[MosaID, float]] = {
90
+ MosaID.MOSA_12: 1.623910e-03,
91
+ MosaID.MOSA_23: 1.522873e-04,
92
+ MosaID.MOSA_31: -1.842871e-03,
93
+ MosaID.MOSA_13: -2.091585e-03,
94
+ MosaID.MOSA_32: 1.300866e-03,
95
+ MosaID.MOSA_21: -8.445374e-04,
96
96
  }
97
97
  """Value to use if ttl_coeffs == "default"
98
98
 
99
99
  Default values were drawn from the same distributions used for ttl_coeffs == "random"
100
100
  """
101
101
 
102
- TTL_COEFFS_LOCAL_ETAS: Final[dict[str, float]] = {
103
- "12": -1.670389e-03,
104
- "23": 1.460681e-03,
105
- "31": -1.039064e-03,
106
- "13": 1.640473e-04,
107
- "32": 1.205353e-03,
108
- "21": -9.205764e-04,
102
+ TTL_COEFFS_LOCAL_ETAS: Final[dict[MosaID, float]] = {
103
+ MosaID.MOSA_12: -1.670389e-03,
104
+ MosaID.MOSA_23: 1.460681e-03,
105
+ MosaID.MOSA_31: -1.039064e-03,
106
+ MosaID.MOSA_13: 1.640473e-04,
107
+ MosaID.MOSA_32: 1.205353e-03,
108
+ MosaID.MOSA_21: -9.205764e-04,
109
109
  }
110
110
  """Value to use if ttl_coeffs == "default"
111
111
 
112
112
  Default values were drawn from the same distributions used for ttl_coeffs == "random"
113
113
  """
114
114
 
115
- TTL_COEFFS_DISTANT_ETAS: Final[dict[str, float]] = {
116
- "12": -1.076470e-03,
117
- "23": 5.228848e-04,
118
- "31": -5.662766e-05,
119
- "13": 1.960050e-03,
120
- "32": 9.021890e-04,
121
- "21": 1.908239e-03,
115
+ TTL_COEFFS_DISTANT_ETAS: Final[dict[MosaID, float]] = {
116
+ MosaID.MOSA_12: -1.076470e-03,
117
+ MosaID.MOSA_23: 5.228848e-04,
118
+ MosaID.MOSA_31: -5.662766e-05,
119
+ MosaID.MOSA_13: 1.960050e-03,
120
+ MosaID.MOSA_32: 9.021890e-04,
121
+ MosaID.MOSA_21: 1.908239e-03,
122
122
  }
123
123
  """Value to use if ttl_coeffs == "default"
124
124
 
@@ -165,21 +165,21 @@ Those default PPRs are based on first samples of Keplerian orbits (v2.0.dev)
165
165
  """
166
166
 
167
167
 
168
- def random_ttl_coeffs_local_phis(low=-2.2e-3, high=2.2e-3) -> dict[str, float]:
168
+ def random_ttl_coeffs_local_phis(low=-2.2e-3, high=2.2e-3) -> dict[MosaID, float]:
169
169
  """Generate random value to use if ttl_coeffs == "random" """
170
- return {m.value: np.random.uniform(low, high) for m in MosaID}
170
+ return {m: np.random.uniform(low, high) for m in MosaID}
171
171
 
172
172
 
173
- def random_ttl_coeffs_distant_phis(low=-2.4e-3, high=2.4e-3) -> dict[str, float]:
173
+ def random_ttl_coeffs_distant_phis(low=-2.4e-3, high=2.4e-3) -> dict[MosaID, float]:
174
174
  """Generate random value to use if ttl_coeffs == "random" """
175
- return {m.value: np.random.uniform(low, high) for m in MosaID}
175
+ return {m: np.random.uniform(low, high) for m in MosaID}
176
176
 
177
177
 
178
- def random_ttl_coeffs_local_etas(low=-2.2e-3, high=2.2e-3) -> dict[str, float]:
178
+ def random_ttl_coeffs_local_etas(low=-2.2e-3, high=2.2e-3) -> dict[MosaID, float]:
179
179
  """Generate random value to use if ttl_coeffs == "random" """
180
- return {m.value: np.random.uniform(low, high) for m in MosaID}
180
+ return {m: np.random.uniform(low, high) for m in MosaID}
181
181
 
182
182
 
183
- def random_ttl_coeffs_distant_etas(low=-2.4e-3, high=2.4e-3) -> dict[str, float]:
183
+ def random_ttl_coeffs_distant_etas(low=-2.4e-3, high=2.4e-3) -> dict[MosaID, float]:
184
184
  """Generate random value to use if ttl_coeffs == "random" """
185
- return {m.value: np.random.uniform(low, high) for m in MosaID}
185
+ return {m: np.random.uniform(low, high) for m in MosaID}
@@ -17,7 +17,7 @@ file formats created by previous versions.
17
17
  import json
18
18
  import pathlib
19
19
  from collections import defaultdict
20
- from typing import Final, TypeVar
20
+ from typing import Any, Final, TypeAlias, TypeVar
21
21
 
22
22
  import h5py
23
23
  import numpy as np
@@ -30,6 +30,9 @@ from lisainstrument.instru.instru_file_reader_v2_0_0 import (
30
30
  from lisainstrument.instru.instru_file_reader_v2_1_0 import (
31
31
  SimResultFile as SimResultFile_V2_1_0,
32
32
  )
33
+ from lisainstrument.instru.instru_file_reader_v2_2_0 import (
34
+ SimResultFile as SimResultFile_V2_2_0,
35
+ )
33
36
  from lisainstrument.instru.instru_store import (
34
37
  IdxSpace,
35
38
  SimFullDatasetsMOSA,
@@ -175,7 +178,7 @@ class SimResultFile:
175
178
  def format_specifier() -> SpecifierSet:
176
179
  """Version specifier set compatible with file reader"""
177
180
  v = Version(__version__)
178
- return SpecifierSet(f"=={v}")
181
+ return SpecifierSet(f"=={v.major}.{v.minor}.*")
179
182
 
180
183
  @classmethod
181
184
  def check_file_version(cls, path: str | pathlib.Path) -> tuple[bool, Version]:
@@ -427,6 +430,41 @@ class SimResultFile:
427
430
  """
428
431
  return self._read_datasets(SimResultsNumpyCore, t_min, t_max)
429
432
 
433
+ def time_window_to_index_range(
434
+ self,
435
+ dsid: DatasetIdentifier,
436
+ t_min: float | None = None,
437
+ t_max: float | None = None,
438
+ ) -> tuple[int, int]:
439
+ """Return the index range contained within a given time period
440
+
441
+ For the time grid of a given dataset, the given time interval is
442
+ mapped to an equivalent index range. More precisely, this returns
443
+ indices `i0,i1` such that sample times `t_i` for indices in the range
444
+ `i0 <= i < i1` satisfy `t_min<=t_i<t_max`.
445
+
446
+ Beware of rounding errors for the case that `t_min` or `t_max` fall
447
+ onto a sample time. For application where precise control matters,
448
+ best use time intervals starting and ending between sample times.
449
+ Alternatively, one can re-use the same floating point number as
450
+ `t_max` in one call and `t_min` in the next. Given
451
+ ´i0,i1 = time_window_to_index_range(dsid, t_a, t_b)´ and
452
+ ´i2,i3 = time_window_to_index_range(dsid, t_b, t_c)´,
453
+ it is safe to assume that ´i2==i1`. Hence, the intervals
454
+ `i0 <= i < i1` and `i2 <= i < i3` have no overlap and cover the
455
+ range `i0 <= i < i3` without gap.
456
+
457
+ The default for `t_min` is such that `i0` is the first valid index
458
+ of the dataset. The default for `t_max` results in `i1` being the
459
+ last valid index + 1.
460
+
461
+ Arguments:
462
+ t_min: Left boundary, or None for start of dataset
463
+ t_max: Right boundary, or None for end of dataset
464
+ """
465
+ isp = self.idxspace_by_dataset_id(dsid)
466
+ return self._restrict_range_isp(isp, t_min, t_max)
467
+
430
468
  def as_stream_bundle(
431
469
  self,
432
470
  datasets: set[DatasetIdentifier] | None = None,
@@ -446,9 +484,14 @@ class SimResultFile:
446
484
  return instru_hdf5_file_as_stream_bundle(self._h5f, datasets, ranges=ranges)
447
485
 
448
486
 
487
+ SimResultFileTypes: TypeAlias = (
488
+ SimResultFile | SimResultFile_V2_0_0 | SimResultFile_V2_1_0 | SimResultFile_V2_2_0
489
+ )
490
+
491
+
449
492
  def sim_result_file(
450
493
  path: pathlib.Path | str, only_compatible: bool = False
451
- ) -> SimResultFile | SimResultFile_V2_0_0 | SimResultFile_V2_1_0:
494
+ ) -> SimResultFileTypes:
452
495
  """Open simulation result file
453
496
 
454
497
  This provides an interface with methods for reading the file.
@@ -465,12 +508,9 @@ def sim_result_file(
465
508
  SimResultFile instance for reading file data
466
509
  """
467
510
 
468
- readers: list[
469
- type[SimResultFile] | type[SimResultFile_V2_0_0] | type[SimResultFile_V2_1_0]
470
- ] = [SimResultFile]
471
- if not only_compatible:
472
- readers.append(SimResultFile_V2_0_0)
473
- readers.append(SimResultFile_V2_1_0)
511
+ legacy = [SimResultFile_V2_0_0, SimResultFile_V2_1_0, SimResultFile_V2_2_0]
512
+ readers: list[Any] = [] if only_compatible else legacy
513
+ readers.append(SimResultFile)
474
514
 
475
515
  version: Version
476
516
  for reader in readers:
@@ -407,6 +407,41 @@ class SimResultFile:
407
407
  """
408
408
  return self._read_datasets(SimResultsNumpyCore, t_min, t_max)
409
409
 
410
+ def time_window_to_index_range(
411
+ self,
412
+ dsid: DatasetIdentifier,
413
+ t_min: float | None = None,
414
+ t_max: float | None = None,
415
+ ) -> tuple[int, int]:
416
+ """Return the index range contained within a given time period
417
+
418
+ For the time grid of a given dataset, the given time interval is
419
+ mapped to an equivalent index range. More precisely, this returns
420
+ indices `i0,i1` such that sample times `t_i` for indices in the range
421
+ `i0 <= i < i1` satisfy `t_min<=t_i<t_max`.
422
+
423
+ Beware of rounding errors for the case that `t_min` or `t_max` fall
424
+ onto a sample time. For application where precise control matters,
425
+ best use time intervals starting and ending between sample times.
426
+ Alternatively, one can re-use the same floating point number as
427
+ `t_max` in one call and `t_min` in the next. Given
428
+ ´i0,i1 = time_window_to_index_range(dsid, t_a, t_b)´ and
429
+ ´i2,i3 = time_window_to_index_range(dsid, t_b, t_c)´,
430
+ it is safe to assume that ´i2==i1`. Hence, the intervals
431
+ `i0 <= i < i1` and `i2 <= i < i3` have no overlap and cover the
432
+ range `i0 <= i < i3` without gap.
433
+
434
+ The default for `t_min` is such that `i0` is the first valid index
435
+ of the dataset. The default for `t_max` results in `i1` being the
436
+ last valid index + 1.
437
+
438
+ Arguments:
439
+ t_min: Left boundary, or None for start of dataset
440
+ t_max: Right boundary, or None for end of dataset
441
+ """
442
+ isp = self.idxspace_by_dataset_id(dsid)
443
+ return self._restrict_range_isp(isp, t_min, t_max)
444
+
410
445
  def as_stream_bundle(
411
446
  self,
412
447
  datasets: set[DatasetIdentifier] | None = None,
@@ -407,6 +407,41 @@ class SimResultFile:
407
407
  """
408
408
  return self._read_datasets(SimResultsNumpyCore, t_min, t_max)
409
409
 
410
+ def time_window_to_index_range(
411
+ self,
412
+ dsid: DatasetIdentifier,
413
+ t_min: float | None = None,
414
+ t_max: float | None = None,
415
+ ) -> tuple[int, int]:
416
+ """Return the index range contained within a given time period
417
+
418
+ For the time grid of a given dataset, the given time interval is
419
+ mapped to an equivalent index range. More precisely, this returns
420
+ indices `i0,i1` such that sample times `t_i` for indices in the range
421
+ `i0 <= i < i1` satisfy `t_min<=t_i<t_max`.
422
+
423
+ Beware of rounding errors for the case that `t_min` or `t_max` fall
424
+ onto a sample time. For application where precise control matters,
425
+ best use time intervals starting and ending between sample times.
426
+ Alternatively, one can re-use the same floating point number as
427
+ `t_max` in one call and `t_min` in the next. Given
428
+ ´i0,i1 = time_window_to_index_range(dsid, t_a, t_b)´ and
429
+ ´i2,i3 = time_window_to_index_range(dsid, t_b, t_c)´,
430
+ it is safe to assume that ´i2==i1`. Hence, the intervals
431
+ `i0 <= i < i1` and `i2 <= i < i3` have no overlap and cover the
432
+ range `i0 <= i < i3` without gap.
433
+
434
+ The default for `t_min` is such that `i0` is the first valid index
435
+ of the dataset. The default for `t_max` results in `i1` being the
436
+ last valid index + 1.
437
+
438
+ Arguments:
439
+ t_min: Left boundary, or None for start of dataset
440
+ t_max: Right boundary, or None for end of dataset
441
+ """
442
+ isp = self.idxspace_by_dataset_id(dsid)
443
+ return self._restrict_range_isp(isp, t_min, t_max)
444
+
410
445
  def as_stream_bundle(
411
446
  self,
412
447
  datasets: set[DatasetIdentifier] | None = None,