pycontrails 0.52.2__tar.gz → 0.52.3__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.

Potentially problematic release.


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

Files changed (271) hide show
  1. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/workflows/release.yaml +1 -1
  2. {pycontrails-0.52.2 → pycontrails-0.52.3}/CHANGELOG.md +16 -0
  3. {pycontrails-0.52.2/pycontrails.egg-info → pycontrails-0.52.3}/PKG-INFO +1 -1
  4. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/api.rst +1 -0
  5. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/_version.py +2 -2
  6. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/interpolation.py +2 -1
  7. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/met.py +179 -2
  8. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/rgi_cython.c +1209 -1193
  9. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/cocip.py +96 -22
  10. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/cocip_params.py +21 -0
  11. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/output_formats.py +11 -2
  12. {pycontrails-0.52.2 → pycontrails-0.52.3/pycontrails.egg-info}/PKG-INFO +1 -1
  13. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_cocip.py +140 -0
  14. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_interpolation.py +122 -16
  15. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  16. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  17. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/dependabot.yaml +0 -0
  18. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/pull_request_template.md +0 -0
  19. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/workflows/docs.yaml +0 -0
  20. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/workflows/doctest.yaml +0 -0
  21. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/workflows/scorecard.yaml +0 -0
  22. {pycontrails-0.52.2 → pycontrails-0.52.3}/.github/workflows/test.yaml +0 -0
  23. {pycontrails-0.52.2 → pycontrails-0.52.3}/.gitignore +0 -0
  24. {pycontrails-0.52.2 → pycontrails-0.52.3}/.pre-commit-config.yaml +0 -0
  25. {pycontrails-0.52.2 → pycontrails-0.52.3}/.zenodo.json +0 -0
  26. {pycontrails-0.52.2 → pycontrails-0.52.3}/CONTRIBUTING.md +0 -0
  27. {pycontrails-0.52.2 → pycontrails-0.52.3}/LICENSE +0 -0
  28. {pycontrails-0.52.2 → pycontrails-0.52.3}/Makefile +0 -0
  29. {pycontrails-0.52.2 → pycontrails-0.52.3}/NOTICE +0 -0
  30. {pycontrails-0.52.2 → pycontrails-0.52.3}/README.md +0 -0
  31. {pycontrails-0.52.2 → pycontrails-0.52.3}/RELEASE.md +0 -0
  32. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/_static/css/style.css +0 -0
  33. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/_static/img/colab.png +0 -0
  34. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/_static/img/favicon.png +0 -0
  35. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/_static/img/logo-dark.png +0 -0
  36. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/_static/img/logo.png +0 -0
  37. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/_static/pycontrails.bib +0 -0
  38. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/changelog.rst +0 -0
  39. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/conf.py +0 -0
  40. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/contributing.rst +0 -0
  41. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/develop.rst +0 -0
  42. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/flight.rst +0 -0
  43. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/index.rst +0 -0
  44. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/install.rst +0 -0
  45. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/integrations/ACCF.ipynb +0 -0
  46. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/integrations/APCEMM.ipynb +0 -0
  47. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/literature.rst +0 -0
  48. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/meteorology.rst +0 -0
  49. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/models.rst +0 -0
  50. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/ARCO-ERA5.ipynb +0 -0
  51. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/AircraftPerformance.ipynb +0 -0
  52. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/Cache.ipynb +0 -0
  53. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/CoCiP.ipynb +0 -0
  54. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/ECMWF.ipynb +0 -0
  55. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/Flight.ipynb +0 -0
  56. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/GFS.ipynb +0 -0
  57. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/GOES.ipynb +0 -0
  58. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/ISSR.ipynb +0 -0
  59. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/Landsat.ipynb +0 -0
  60. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/Meteorology.ipynb +0 -0
  61. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/SAC.ipynb +0 -0
  62. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/Sentinel.ipynb +0 -0
  63. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/advection.ipynb +0 -0
  64. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/airports.ipynb +0 -0
  65. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/.gitignore +0 -0
  66. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/flight-ap.csv +0 -0
  67. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/flight-cocip.csv +0 -0
  68. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/flight-fdr.csv +0 -0
  69. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/flight-noisy.csv +0 -0
  70. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/flight.csv +0 -0
  71. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/iagos-flight-landsat.csv +0 -0
  72. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/data/iagos-flight-sentinel.csv +0 -0
  73. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/flightplan.ipynb +0 -0
  74. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/model-levels.ipynb +0 -0
  75. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/run-cocip-on-flight.ipynb +0 -0
  76. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/run-cocip-with-fdr.ipynb +0 -0
  77. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks/specific-humidity-interpolation.ipynb +0 -0
  78. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/notebooks.rst +0 -0
  79. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/observations.rst +0 -0
  80. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/tutorials.rst +0 -0
  81. {pycontrails-0.52.2 → pycontrails-0.52.3}/docs/utilities.rst +0 -0
  82. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/__init__.py +0 -0
  83. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/__init__.py +0 -0
  84. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/aircraft_performance.py +0 -0
  85. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/airports.py +0 -0
  86. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/cache.py +0 -0
  87. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/coordinates.py +0 -0
  88. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/fleet.py +0 -0
  89. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/flight.py +0 -0
  90. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/flightplan.py +0 -0
  91. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/fuel.py +0 -0
  92. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/met_var.py +0 -0
  93. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/models.py +0 -0
  94. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/polygon.py +0 -0
  95. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/rgi_cython.pyx +0 -0
  96. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/core/vector.py +0 -0
  97. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/__init__.py +0 -0
  98. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/_leo_utils/search.py +0 -0
  99. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/_leo_utils/static/bq_roi_query.sql +0 -0
  100. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/_leo_utils/vis.py +0 -0
  101. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/_met_utils/metsource.py +0 -0
  102. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/__init__.py +0 -0
  103. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/arco_era5.py +0 -0
  104. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/common.py +0 -0
  105. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/era5.py +0 -0
  106. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/era5_model_level.py +0 -0
  107. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/hres.py +0 -0
  108. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/hres_model_level.py +0 -0
  109. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/ifs.py +0 -0
  110. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/model_levels.py +0 -0
  111. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/static/model_level_dataframe_v20240418.csv +0 -0
  112. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/ecmwf/variables.py +0 -0
  113. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/gfs/__init__.py +0 -0
  114. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/gfs/gfs.py +0 -0
  115. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/gfs/variables.py +0 -0
  116. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/goes.py +0 -0
  117. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/landsat.py +0 -0
  118. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/sentinel.py +0 -0
  119. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/datalib/spire.py +0 -0
  120. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/ext/bada.py +0 -0
  121. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/ext/cirium.py +0 -0
  122. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/ext/empirical_grid.py +0 -0
  123. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/ext/synthetic_flight.py +0 -0
  124. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/__init__.py +0 -0
  125. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/accf.py +0 -0
  126. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/apcemm/__init__.py +0 -0
  127. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/apcemm/apcemm.py +0 -0
  128. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/apcemm/inputs.py +0 -0
  129. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/apcemm/static/apcemm_yaml_template.yaml +0 -0
  130. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/apcemm/utils.py +0 -0
  131. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/__init__.py +0 -0
  132. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/cocip_uncertainty.py +0 -0
  133. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/contrail_properties.py +0 -0
  134. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/radiative_forcing.py +0 -0
  135. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/radiative_heating.py +0 -0
  136. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/unterstrasser_wake_vortex.py +0 -0
  137. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/wake_vortex.py +0 -0
  138. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocip/wind_shear.py +0 -0
  139. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocipgrid/__init__.py +0 -0
  140. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocipgrid/cocip_grid.py +0 -0
  141. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/cocipgrid/cocip_grid_params.py +0 -0
  142. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/dry_advection.py +0 -0
  143. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/__init__.py +0 -0
  144. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/black_carbon.py +0 -0
  145. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/emissions.py +0 -0
  146. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/ffm2.py +0 -0
  147. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/static/default-engine-uids.csv +0 -0
  148. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/static/edb-gaseous-v29b-engines.csv +0 -0
  149. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/emissions/static/edb-nvpm-v29b-engines.csv +0 -0
  150. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/humidity_scaling/__init__.py +0 -0
  151. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/humidity_scaling/humidity_scaling.py +0 -0
  152. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/humidity_scaling/quantiles/era5-model-level-quantiles.pq +0 -0
  153. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/humidity_scaling/quantiles/era5-pressure-level-quantiles.pq +0 -0
  154. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/issr.py +0 -0
  155. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/pcc.py +0 -0
  156. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/pcr.py +0 -0
  157. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/__init__.py +0 -0
  158. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/ps_aircraft_params.py +0 -0
  159. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/ps_grid.py +0 -0
  160. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/ps_model.py +0 -0
  161. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/ps_operational_limits.py +0 -0
  162. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/static/ps-aircraft-params-20240524.csv +0 -0
  163. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/ps_model/static/ps-synonym-list-20240524.csv +0 -0
  164. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/sac.py +0 -0
  165. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/models/tau_cirrus.py +0 -0
  166. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/physics/__init__.py +0 -0
  167. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/physics/constants.py +0 -0
  168. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/physics/geo.py +0 -0
  169. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/physics/jet.py +0 -0
  170. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/physics/thermo.py +0 -0
  171. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/physics/units.py +0 -0
  172. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/py.typed +0 -0
  173. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/utils/__init__.py +0 -0
  174. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/utils/dependencies.py +0 -0
  175. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/utils/iteration.py +0 -0
  176. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/utils/json.py +0 -0
  177. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/utils/temp.py +0 -0
  178. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails/utils/types.py +0 -0
  179. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails.egg-info/SOURCES.txt +0 -0
  180. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails.egg-info/dependency_links.txt +0 -0
  181. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails.egg-info/requires.txt +0 -0
  182. {pycontrails-0.52.2 → pycontrails-0.52.3}/pycontrails.egg-info/top_level.txt +0 -0
  183. {pycontrails-0.52.2 → pycontrails-0.52.3}/pyproject.toml +0 -0
  184. {pycontrails-0.52.2 → pycontrails-0.52.3}/setup.cfg +0 -0
  185. {pycontrails-0.52.2 → pycontrails-0.52.3}/setup.py +0 -0
  186. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/__init__.py +0 -0
  187. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/_deprecated.py +0 -0
  188. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/Makefile +0 -0
  189. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/README.md +0 -0
  190. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/benchmark.py +0 -0
  191. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/compare.py +0 -0
  192. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/data.md +0 -0
  193. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/output.py +0 -0
  194. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip/review.ipynb +0 -0
  195. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/cocip-fortran/README.md +0 -0
  196. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/north-atlantic-study/.gcloudignore +0 -0
  197. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/north-atlantic-study/README.md +0 -0
  198. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/north-atlantic-study/support.py +0 -0
  199. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/benchmark/north-atlantic-study/validate.py +0 -0
  200. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/fixtures/cocip-met.py +0 -0
  201. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/fixtures/cocip-met2.py +0 -0
  202. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/fixtures/ecmwf-met.py +0 -0
  203. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/fixtures/gfs-met.py +0 -0
  204. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/__init__.py +0 -0
  205. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/conftest.py +0 -0
  206. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/NOAA_Solar_Calculations_day.csv +0 -0
  207. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/cocip-contrail-output.json +0 -0
  208. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/cocip-contrail-output2.json +0 -0
  209. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/cocip-flight-output.json +0 -0
  210. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/cocip-flight-output2.json +0 -0
  211. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/cocip-output-contrail-edges.json +0 -0
  212. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/cocip-output-flts-20190101-eu.pq +0 -0
  213. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/flight-cocip2.csv +0 -0
  214. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/flight-meridian.csv +0 -0
  215. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/flight-metadata.json +0 -0
  216. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/flight-spire-data-cleaning.pq +0 -0
  217. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/flight.csv +0 -0
  218. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/flt-wypts-20190101-eu.pq +0 -0
  219. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-20190101-eu.nc +0 -0
  220. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-accf-pl.nc +0 -0
  221. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-accf-sl.nc +0 -0
  222. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-ecmwf-pl.nc +0 -0
  223. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-ecmwf-sl.nc +0 -0
  224. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-era5-cocip1.nc +0 -0
  225. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-era5-cocip2.nc +0 -0
  226. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/met-gfs.nc +0 -0
  227. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/polygon-bug.nc +0 -0
  228. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/rad-20190101-eu.nc +0 -0
  229. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/rad-era5-cocip1.nc +0 -0
  230. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/rad-era5-cocip2.nc +0 -0
  231. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/static/rad-gfs.nc +0 -0
  232. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_accf.py +0 -0
  233. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_airports.py +0 -0
  234. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_apcemm.py +0 -0
  235. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_cache.py +0 -0
  236. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_cocip_grid.py +0 -0
  237. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_cocip_grid_parity.py +0 -0
  238. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_cocip_radiative_forcing.py +0 -0
  239. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_cocip_uncertainty.py +0 -0
  240. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_coordinates.py +0 -0
  241. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_datalib_metsource.py +0 -0
  242. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_dry_advection.py +0 -0
  243. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_dtypes.py +0 -0
  244. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_ecmwf.py +0 -0
  245. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_emissions.py +0 -0
  246. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_fleet.py +0 -0
  247. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_flight.py +0 -0
  248. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_flightplan.py +0 -0
  249. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_fuel.py +0 -0
  250. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_geo.py +0 -0
  251. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_gfs.py +0 -0
  252. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_goes.py +0 -0
  253. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_grid_to_netcdf.py +0 -0
  254. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_humidity_scaling.py +0 -0
  255. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_init.py +0 -0
  256. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_leo.py +0 -0
  257. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_met.py +0 -0
  258. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_met_cache.py +0 -0
  259. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_models.py +0 -0
  260. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_pcc.py +0 -0
  261. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_polygons.py +0 -0
  262. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_ps_model.py +0 -0
  263. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_sac_issr.py +0 -0
  264. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_spire.py +0 -0
  265. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_tau_cirrus.py +0 -0
  266. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_thermo_sac.py +0 -0
  267. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_units.py +0 -0
  268. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_unterstrasser_wake_vortex.py +0 -0
  269. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_utils.py +0 -0
  270. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_vector.py +0 -0
  271. {pycontrails-0.52.2 → pycontrails-0.52.3}/tests/unit/test_zarr.py +0 -0
@@ -40,7 +40,7 @@ jobs:
40
40
 
41
41
  # https://cibuildwheel.readthedocs.io/en/stable/options/#testing
42
42
  - name: Build wheels
43
- uses: pypa/cibuildwheel@v2.19
43
+ uses: pypa/cibuildwheel@v2.20
44
44
  env:
45
45
  CIBW_BUILD: cp39-* cp310-* cp311-* cp312-*
46
46
  CIBW_SKIP: '*-win32 *-manylinux_i686 *-musllinux*'
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.52.3
4
+
5
+ ### Features
6
+
7
+ - Add experimental `preprocess_lowmem` parameter to `Cocip`. When set to `True`, `Cocip` will attempt to reduce memory consumption during flight preprocessing and initial formation/persistence calculations by using an alternate implementation of `MetDataArray.interpolate` (see below).
8
+ - Add `lowmem` keyword-only argument to `MetDataArray.interpolate`. When `True`, attempt to reduce memory consumption by using an alternative interpolation strategy that loads at most two time steps of meteorology data into memory at a time.
9
+
10
+ ### Fixes
11
+
12
+ - Defer import of `matplotlib` in `models.cocip.output_formats`.
13
+ - Fix bug in `PycontrailsRegularGridInterpolator` that caused errors when dispatching to 1-d linear interpolation from in `rgi_cython.pyx`.
14
+
15
+ ### Internals
16
+
17
+ - Implement low-memory paths in `Cocip.eval` and `MetDataArray.interpolate`.
18
+
3
19
  ## v0.52.2
4
20
 
5
21
  ### Breaking changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycontrails
3
- Version: 0.52.2
3
+ Version: 0.52.3
4
4
  Summary: Python library for modeling aviation climate impacts
5
5
  Author-email: Breakthrough Energy <py@contrails.org>
6
6
  License: Apache-2.0
@@ -134,6 +134,7 @@ CoCiP
134
134
 
135
135
  models.cocip.Cocip
136
136
  models.cocip.CocipParams
137
+ models.cocip.CocipFlightParams
137
138
  models.cocip.contrail_properties
138
139
  models.cocip.radiative_forcing
139
140
  models.cocip.wake_vortex
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.52.2'
16
- __version_tuple__ = version_tuple = (0, 52, 2)
15
+ __version__ = version = '0.52.3'
16
+ __version_tuple__ = version_tuple = (0, 52, 3)
@@ -215,7 +215,8 @@ class PycontrailsRegularGridInterpolator(scipy.interpolate.RegularGridInterpolat
215
215
 
216
216
  if ndim == 1:
217
217
  # np.interp could be better ... although that may also promote the dtype
218
- return rgi_cython.evaluate_linear_1d(values, indices, norm_distances, out)
218
+ # 1-d view is required for evaluate_linear_1d
219
+ return rgi_cython.evaluate_linear_1d(values, indices[0, :], norm_distances[0, :], out)
219
220
 
220
221
  msg = f"Invalid number of dimensions: {ndim}"
221
222
  raise ValueError(msg)
@@ -9,7 +9,15 @@ import pathlib
9
9
  import typing
10
10
  import warnings
11
11
  from abc import ABC, abstractmethod
12
- from collections.abc import Hashable, Iterable, Iterator, Mapping, MutableMapping, Sequence
12
+ from collections.abc import (
13
+ Generator,
14
+ Hashable,
15
+ Iterable,
16
+ Iterator,
17
+ Mapping,
18
+ MutableMapping,
19
+ Sequence,
20
+ )
13
21
  from contextlib import ExitStack
14
22
  from datetime import datetime
15
23
  from typing import (
@@ -1502,6 +1510,7 @@ class MetDataArray(MetBase):
1502
1510
  bounds_error: bool = ...,
1503
1511
  fill_value: float | np.float64 | None = ...,
1504
1512
  localize: bool = ...,
1513
+ lowmem: bool = ...,
1505
1514
  indices: interpolation.RGIArtifacts | None = ...,
1506
1515
  return_indices: Literal[False] = ...,
1507
1516
  ) -> npt.NDArray[np.float64]: ...
@@ -1518,6 +1527,7 @@ class MetDataArray(MetBase):
1518
1527
  bounds_error: bool = ...,
1519
1528
  fill_value: float | np.float64 | None = ...,
1520
1529
  localize: bool = ...,
1530
+ lowmem: bool = ...,
1521
1531
  indices: interpolation.RGIArtifacts | None = ...,
1522
1532
  return_indices: Literal[True],
1523
1533
  ) -> tuple[npt.NDArray[np.float64], interpolation.RGIArtifacts]: ...
@@ -1533,6 +1543,7 @@ class MetDataArray(MetBase):
1533
1543
  bounds_error: bool = False,
1534
1544
  fill_value: float | np.float64 | None = np.nan,
1535
1545
  localize: bool = False,
1546
+ lowmem: bool = False,
1536
1547
  indices: interpolation.RGIArtifacts | None = None,
1537
1548
  return_indices: bool = False,
1538
1549
  ) -> npt.NDArray[np.float64] | tuple[npt.NDArray[np.float64], interpolation.RGIArtifacts]:
@@ -1540,7 +1551,9 @@ class MetDataArray(MetBase):
1540
1551
 
1541
1552
  Zero dimensional coordinates are reshaped to 1D arrays.
1542
1553
 
1543
- Method automatically loads underlying :attr:`data` into memory.
1554
+ If ``lowmem == False``, method automatically loads underlying :attr:`data` into
1555
+ memory. Otherwise, method iterates through smaller subsets of :attr:`data` and releases
1556
+ subsets from memory once interpolation against each subset is finished.
1544
1557
 
1545
1558
  If ``method == "nearest"``, the out array will have the same ``dtype`` as
1546
1559
  the underlying :attr:`data`.
@@ -1586,10 +1599,18 @@ class MetDataArray(MetBase):
1586
1599
  localize: bool, optional
1587
1600
  Experimental. If True, downselect gridded data to smallest bounding box containing
1588
1601
  all points. By default False.
1602
+ lowmem: bool, optional
1603
+ Experimental. If True, iterate through points binned by the time coordinate of the
1604
+ grided data, and downselect gridded data to the smallest bounding box containing
1605
+ each binned set of point *before loading into memory*. This can significantly reduce
1606
+ memory consumption with large numbers of points at the cost of increased runtime.
1607
+ By default False.
1589
1608
  indices: tuple | None, optional
1590
1609
  Experimental. See :func:`interpolation.interp`. None by default.
1591
1610
  return_indices: bool, optional
1592
1611
  Experimental. See :func:`interpolation.interp`. False by default.
1612
+ Note that values returned differ when ``lowmem=True`` and ``lowmem=False``,
1613
+ so output should only be re-used in calls with the same ``lowmem`` value.
1593
1614
 
1594
1615
  Returns
1595
1616
  -------
@@ -1632,10 +1653,29 @@ class MetDataArray(MetBase):
1632
1653
  >>> level = np.linspace(200, 300, 10)
1633
1654
  >>> time = pd.date_range("2022-03-01T14", periods=10, freq="5min")
1634
1655
  >>> mda.interpolate(longitude, latitude, level, time)
1656
+ array([220.44347694, 223.08900738, 225.74338924, 228.41642088,
1657
+ 231.10858599, 233.54857391, 235.71504913, 237.86478872,
1658
+ 239.99274623, 242.10792167])
1659
+
1660
+ >>> # Can easily switch to alternative low-memory implementation
1661
+ >>> mda.interpolate(longitude, latitude, level, time, lowmem=True)
1635
1662
  array([220.44347694, 223.08900738, 225.74338924, 228.41642088,
1636
1663
  231.10858599, 233.54857391, 235.71504913, 237.86478872,
1637
1664
  239.99274623, 242.10792167])
1638
1665
  """
1666
+ if lowmem:
1667
+ return self._interp_lowmem(
1668
+ longitude,
1669
+ latitude,
1670
+ level,
1671
+ time,
1672
+ method=method,
1673
+ bounds_error=bounds_error,
1674
+ fill_value=fill_value,
1675
+ indices=indices,
1676
+ return_indices=return_indices,
1677
+ )
1678
+
1639
1679
  # Load if necessary
1640
1680
  if not self.in_memory:
1641
1681
  self._check_memory("Interpolation over")
@@ -1660,6 +1700,100 @@ class MetDataArray(MetBase):
1660
1700
  return_indices=return_indices,
1661
1701
  )
1662
1702
 
1703
+ def _interp_lowmem(
1704
+ self,
1705
+ longitude: float | npt.NDArray[np.float64],
1706
+ latitude: float | npt.NDArray[np.float64],
1707
+ level: float | npt.NDArray[np.float64],
1708
+ time: np.datetime64 | npt.NDArray[np.datetime64],
1709
+ *,
1710
+ method: str = "linear",
1711
+ bounds_error: bool = False,
1712
+ fill_value: float | np.float64 | None = np.nan,
1713
+ minimize_memory: bool = False,
1714
+ indices: interpolation.RGIArtifacts | None = None,
1715
+ return_indices: bool = False,
1716
+ ) -> npt.NDArray[np.float64] | tuple[npt.NDArray[np.float64], interpolation.RGIArtifacts]:
1717
+ """Interpolate values against underlying DataArray.
1718
+
1719
+ This method is used by :meth:`interpolate` when ``lowmem=True``.
1720
+ Parameters and return types are identical to :meth:`interpolate`, except
1721
+ that the ``localize`` keyword argument is omitted.
1722
+ """
1723
+ # Convert all inputs to 1d arrays
1724
+ # Not validating against ndim >= 2
1725
+ longitude, latitude, level, time = np.atleast_1d(longitude, latitude, level, time)
1726
+
1727
+ if bounds_error:
1728
+ _lowmem_boundscheck(time, self.data)
1729
+
1730
+ # Create buffers for holding interpolation output
1731
+ # Use np.full rather than np.empty so points not covered
1732
+ # by masks are filled with correct out-of-bounds values.
1733
+ out = np.full(longitude.shape, fill_value, dtype=self.data.dtype)
1734
+ if return_indices:
1735
+ rgi_artifacts = interpolation.RGIArtifacts(
1736
+ xi_indices=np.full((4, longitude.size), -1, dtype=np.int64),
1737
+ norm_distances=np.full((4, longitude.size), np.nan, dtype=np.float64),
1738
+ out_of_bounds=np.full((longitude.size,), True, dtype=np.bool_),
1739
+ )
1740
+
1741
+ # Iterate over portions of points between adjacent time steps in gridded data
1742
+ for mask in _lowmem_masks(time, self.data["time"].values):
1743
+ if mask is None or not np.any(mask):
1744
+ continue
1745
+
1746
+ lon_sl = longitude[mask]
1747
+ lat_sl = latitude[mask]
1748
+ lev_sl = level[mask]
1749
+ t_sl = time[mask]
1750
+ if indices is not None:
1751
+ indices_sl = interpolation.RGIArtifacts(
1752
+ xi_indices=indices.xi_indices[:, mask],
1753
+ norm_distances=indices.norm_distances[:, mask],
1754
+ out_of_bounds=indices.out_of_bounds[mask],
1755
+ )
1756
+ else:
1757
+ indices_sl = None
1758
+
1759
+ coords = {"longitude": lon_sl, "latitude": lat_sl, "level": lev_sl, "time": t_sl}
1760
+ if any(np.all(np.isnan(coord)) for coord in coords.values()):
1761
+ continue
1762
+ da = interpolation._localize(self.data, coords)
1763
+ if not da._in_memory:
1764
+ logger.debug(
1765
+ "Loading %s MB subset of %s into memory.",
1766
+ round(da.nbytes / 1_000_000, 2),
1767
+ da.name,
1768
+ )
1769
+ da.load()
1770
+
1771
+ tmp = interpolation.interp(
1772
+ longitude=lon_sl,
1773
+ latitude=lat_sl,
1774
+ level=lev_sl,
1775
+ time=t_sl,
1776
+ da=da,
1777
+ method=method,
1778
+ bounds_error=bounds_error,
1779
+ fill_value=fill_value,
1780
+ localize=False, # would be no-op; da is localized already
1781
+ indices=indices_sl,
1782
+ return_indices=return_indices,
1783
+ )
1784
+
1785
+ if return_indices:
1786
+ out[mask], rgi_sl = tmp
1787
+ rgi_artifacts.xi_indices[:, mask] = rgi_sl.xi_indices
1788
+ rgi_artifacts.norm_distances[:, mask] = rgi_sl.norm_distances
1789
+ rgi_artifacts.out_of_bounds[mask] = rgi_sl.out_of_bounds
1790
+ else:
1791
+ out[mask] = tmp
1792
+
1793
+ if return_indices:
1794
+ return out, rgi_artifacts
1795
+ return out
1796
+
1663
1797
  def _check_memory(self, msg_start: str) -> None:
1664
1798
  """Check the memory usage of the underlying data.
1665
1799
 
@@ -2656,3 +2790,46 @@ def _add_vertical_coords(data: XArrayType) -> XArrayType:
2656
2790
  data.coords["altitude"] = data.coords["altitude"].astype(dtype, copy=False)
2657
2791
 
2658
2792
  return data
2793
+
2794
+
2795
+ def _lowmem_boundscheck(time: npt.NDArray[np.datetime64], da: xr.DataArray) -> None:
2796
+ """Extra bounds check required with low-memory interpolation strategy.
2797
+
2798
+ Because the main loop in `_interp_lowmem` processes points between time steps
2799
+ in gridded data, it will never encounter points that are out-of-bounds in time
2800
+ and may fail to produce requested out-of-bounds errors.
2801
+ """
2802
+ da_time = da["time"].to_numpy()
2803
+ if not np.all((time >= da_time.min()) & (time <= da_time.max())):
2804
+ axis = da.get_axis_num("time")
2805
+ msg = f"One of the requested xi is out of bounds in dimension {axis}"
2806
+ raise ValueError(msg)
2807
+
2808
+
2809
+ def _lowmem_masks(
2810
+ time: npt.NDArray[np.datetime64], t_met: npt.NDArray[np.datetime64]
2811
+ ) -> Generator[npt.NDArray[np.bool_], None, None]:
2812
+ """Generate sequence of masks for low-memory interpolation."""
2813
+ t_met_max = t_met.max()
2814
+ t_met_min = t_met.min()
2815
+ inbounds = (time >= t_met_min) & (time <= t_met_max)
2816
+ if not np.any(inbounds):
2817
+ return
2818
+
2819
+ earliest = np.nanmin(time)
2820
+ istart = 0 if earliest < t_met_min else np.flatnonzero(t_met <= earliest).max()
2821
+ latest = np.nanmax(time)
2822
+ iend = t_met.size - 1 if latest > t_met_max else np.flatnonzero(t_met >= latest).min()
2823
+ if istart == iend:
2824
+ yield inbounds
2825
+ return
2826
+
2827
+ # Sequence of masks covers elements in time in the interval [t_met[istart], t_met[iend]].
2828
+ # The first iteration masks elements in the interval [t_met[istart], t_met[istart+1]]
2829
+ # (inclusive of both endpoints).
2830
+ # Subsequent iterations mask elements in the interval (t_met[i], t_met[i+1]]
2831
+ # (inclusive of right endpoint only).
2832
+ for i in range(istart, iend):
2833
+ mask = ((time >= t_met[i]) if i == istart else (time > t_met[i])) & (time <= t_met[i + 1])
2834
+ if np.any(mask):
2835
+ yield mask