pytesdaqx 0.2.3__tar.gz → 0.2.4__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 (227) hide show
  1. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/PKG-INFO +2 -2
  2. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/cli/data_inspection.md +49 -0
  3. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/cli/index.md +1 -0
  4. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pyproject.toml +3 -2
  5. pytesdaqx-0.2.4/pytesdaqx/cli/repair_readout.py +168 -0
  6. pytesdaqx-0.2.4/pytesdaqx/cli/signal_generator.py +438 -0
  7. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/builtins.py +64 -9
  8. pytesdaqx-0.2.4/pytesdaqx/instruments/scpi_errors.py +44 -0
  9. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/signal_generator/agilent33500B.py +79 -8
  10. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/metadata_compat.py +37 -33
  11. pytesdaqx-0.2.4/pytesdaqx/testing/check_33500b_pulse.py +243 -0
  12. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx.egg-info/PKG-INFO +2 -2
  13. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx.egg-info/SOURCES.txt +5 -0
  14. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx.egg-info/entry_points.txt +1 -0
  15. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx.egg-info/requires.txt +1 -1
  16. pytesdaqx-0.2.4/tests/test_agilent33500B_pulse.py +298 -0
  17. pytesdaqx-0.2.4/tests/test_repair_readout.py +186 -0
  18. pytesdaqx-0.2.4/tests/test_signal_generator_cli.py +441 -0
  19. pytesdaqx-0.2.3/pytesdaqx/cli/signal_generator.py +0 -217
  20. pytesdaqx-0.2.3/tests/test_signal_generator_cli.py +0 -189
  21. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/MANIFEST.in +0 -0
  22. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/README.md +0 -0
  23. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/acquisition_pipeline.md +0 -0
  24. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/adding_hardware.md +0 -0
  25. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/architecture.md +0 -0
  26. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/configuration_pipeline.md +0 -0
  27. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/data_io.md +0 -0
  28. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/hardware_support.md +0 -0
  29. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/index.md +0 -0
  30. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/package_structure.md +0 -0
  31. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/release_process.md +0 -0
  32. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/developer/testing.md +0 -0
  33. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/index.md +0 -0
  34. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/installation/index.md +0 -0
  35. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/installation/rocky_linux_9.md +0 -0
  36. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/installation/troubleshooting.md +0 -0
  37. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/installation/ubuntu.md +0 -0
  38. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/installation/validation.md +0 -0
  39. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/installation/visa.md +0 -0
  40. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/cli/acquisition.md +0 -0
  41. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/cli/instrument_control.md +0 -0
  42. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/cli/lab_diagnostics.md +0 -0
  43. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/acquisition_config.md +0 -0
  44. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/hardware_yaml.md +0 -0
  45. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/index.md +0 -0
  46. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/resolution.md +0 -0
  47. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/run_setup_yaml.md +0 -0
  48. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/scans.md +0 -0
  49. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/configuration/temperature_controllers.md +0 -0
  50. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/data_format.md +0 -0
  51. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/quickstart.md +0 -0
  52. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/terminology.md +0 -0
  53. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/troubleshooting.md +0 -0
  54. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/docs/user/workflows.md +0 -0
  55. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/README.md +0 -0
  56. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/basic/acquisition_background.yaml +0 -0
  57. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/basic/acquisition_didv_background.yaml +0 -0
  58. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/basic/acquisition_notebook_demo.yaml +0 -0
  59. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/basic/hardware_fake.yaml +0 -0
  60. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/basic/hardware_feb_signal_generator.yaml +0 -0
  61. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/basic/run_setup.yaml +0 -0
  62. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/blinded/acquisition_blinded_75_25.yaml +0 -0
  63. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/blinded/generate_blinded_sequence.py +0 -0
  64. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/calibration/acquisition_laser.yaml +0 -0
  65. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/pxi_loopback/README.md +0 -0
  66. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/pxi_loopback/acquisition_didv.yaml +0 -0
  67. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/pxi_loopback/acquisition_iv_restore.yaml +0 -0
  68. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/scans/acquisition_didv_ac.yaml +0 -0
  69. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/scans/acquisition_didv_frequency_focus.yaml +0 -0
  70. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/scans/acquisition_temperature_fake.yaml +0 -0
  71. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/scans/acquisition_tes_bias_iv_didv.yaml +0 -0
  72. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/scans/acquisition_transducer_vibration_scan.yaml +0 -0
  73. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/temperature/hardware_lakeshore372.yaml +0 -0
  74. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/temperature/hardware_macrt.yaml +0 -0
  75. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/temperature/run_setup_lakeshore372.yaml +0 -0
  76. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/temperature/run_setup_macrt.yaml +0 -0
  77. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/vibration/hardware_fake.yaml +0 -0
  78. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/configuration/vibration/run_setup.yaml +0 -0
  79. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/simulation/README.md +0 -0
  80. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/examples/simulation/write_simulated_zarr.py +0 -0
  81. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/mkdocs.yml +0 -0
  82. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/__init__.py +0 -0
  83. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/acquisition/__init__.py +0 -0
  84. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/acquisition/fake.py +0 -0
  85. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/acquisition/nidaq_ai.py +0 -0
  86. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/acquisition/segment.py +0 -0
  87. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/acquisition/session.py +0 -0
  88. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/acquisition/streaming.py +0 -0
  89. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/analysis/__init__.py +0 -0
  90. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/analysis/continuity.py +0 -0
  91. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/__init__.py +0 -0
  92. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/build_manifest.py +0 -0
  93. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/display_metadata.py +0 -0
  94. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/laser.py +0 -0
  95. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/run.py +0 -0
  96. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/squid.py +0 -0
  97. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/temperature.py +0 -0
  98. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/tes_bias.py +0 -0
  99. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/transducer.py +0 -0
  100. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/validate_config.py +0 -0
  101. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/cli/view_traces.py +0 -0
  102. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/__init__.py +0 -0
  103. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/durations.py +0 -0
  104. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/models.py +0 -0
  105. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/resolver.py +0 -0
  106. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/scan_values.py +0 -0
  107. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/schema.py +0 -0
  108. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/temperature.py +0 -0
  109. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/config/validators.py +0 -0
  110. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/control/__init__.py +0 -0
  111. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/control/coordinator.py +0 -0
  112. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/hardware/__init__.py +0 -0
  113. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/hardware/base.py +0 -0
  114. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/hardware/factory.py +0 -0
  115. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/hardware/legacy.py +0 -0
  116. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/hardware/registry.py +0 -0
  117. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/__init__.py +0 -0
  118. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/base.py +0 -0
  119. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/communication.py +0 -0
  120. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/external.py +0 -0
  121. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/remote.py +0 -0
  122. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/signal_generator/__init__.py +0 -0
  123. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/signal_generator/keithley2400.py +0 -0
  124. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/signal_generator/keysightDSOX1200.py +0 -0
  125. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/signal_generator/rigoldg800.py +0 -0
  126. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/temperature_controller/__init__.py +0 -0
  127. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/temperature_controller/base.py +0 -0
  128. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/temperature_controller/lakeshore.py +0 -0
  129. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/temperature_controller/macrt.py +0 -0
  130. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/temperature_controller/macrt_module.py +0 -0
  131. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/tes_squid/__init__.py +0 -0
  132. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/tes_squid/feb.py +0 -0
  133. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/instruments/tes_squid/magnicon.py +0 -0
  134. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/__init__.py +0 -0
  135. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/acquisition_catalog.py +0 -0
  136. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/catalog.py +0 -0
  137. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/hdf5_layout.py +0 -0
  138. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/hdf5_reader.py +0 -0
  139. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/raw_data_reader.py +0 -0
  140. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/raw_data_writer.py +0 -0
  141. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/reader_utils.py +0 -0
  142. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/stream_reader.py +0 -0
  143. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/zarr_reader.py +0 -0
  144. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/io/zarr_utils.py +0 -0
  145. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/naming.py +0 -0
  146. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/processing/__init__.py +0 -0
  147. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/processing/downsample.py +0 -0
  148. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/recorder/__init__.py +0 -0
  149. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/recorder/async_writer.py +0 -0
  150. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/recorder/base.py +0 -0
  151. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/recorder/hdf5.py +0 -0
  152. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/recorder/zarr.py +0 -0
  153. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/run/__init__.py +0 -0
  154. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/run/runner.py +0 -0
  155. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/run/yaml_run.py +0 -0
  156. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/sequencer/__init__.py +0 -0
  157. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/sequencer/scan.py +0 -0
  158. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/sequencer/sequencer.py +0 -0
  159. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/__init__.py +0 -0
  160. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/laser.py +0 -0
  161. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/signal_generator_load.py +0 -0
  162. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/squid.py +0 -0
  163. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/temperature.py +0 -0
  164. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/tes_bias.py +0 -0
  165. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/services/transducer.py +0 -0
  166. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/__init__.py +0 -0
  167. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/analyze_continuity.py +0 -0
  168. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/lab_check.py +0 -0
  169. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/ni_cli_common.py +0 -0
  170. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/real_ni_benchmark.py +0 -0
  171. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/real_ni_continuity_test.py +0 -0
  172. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/real_ni_run_continuous.py +0 -0
  173. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/real_ni_smoke.py +0 -0
  174. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx/testing/real_ni_trigger_test.py +0 -0
  175. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx.egg-info/dependency_links.txt +0 -0
  176. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/pytesdaqx.egg-info/top_level.txt +0 -0
  177. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/setup.cfg +0 -0
  178. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_accelerometer_readout.py +0 -0
  179. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_acquisition_catalog_api_cleanup.py +0 -0
  180. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_acquisition_catalog_naming.py +0 -0
  181. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_api_cleanup.py +0 -0
  182. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_cli_contract.py +0 -0
  183. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_code_cleanup_regressions.py +0 -0
  184. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_detector_settings_normalization.py +0 -0
  185. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_developer_documentation.py +0 -0
  186. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_distribution_readiness.py +0 -0
  187. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_facility_catalog_metadata.py +0 -0
  188. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_feb_driver.py +0 -0
  189. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_feb_signal_generator_didv.py +0 -0
  190. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_finite_record_metadata.py +0 -0
  191. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_io_coordinate_cleanup.py +0 -0
  192. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_lakeshore372_driver.py +0 -0
  193. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_laser_configuration_ownership.py +0 -0
  194. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_macrt_driver.py +0 -0
  195. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_magnicon_driver.py +0 -0
  196. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_manifest_and_zarr_metadata.py +0 -0
  197. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_metadata_canonical_schema.py +0 -0
  198. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_optional_hdf5_import.py +0 -0
  199. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_partition_planning.py +0 -0
  200. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_raw_data_writer.py +0 -0
  201. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_read_block_defaults.py +0 -0
  202. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_release_cleanup.py +0 -0
  203. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_repository_layout.py +0 -0
  204. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_run_cli_cleanup.py +0 -0
  205. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_scan_documentation.py +0 -0
  206. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_scan_values.py +0 -0
  207. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_signal_generator_drivers.py +0 -0
  208. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_signal_generator_load_policy.py +0 -0
  209. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_stream_id_uniqueness.py +0 -0
  210. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_stream_reader_api_cleanup.py +0 -0
  211. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_temperature_acquisition_integration.py +0 -0
  212. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_temperature_cli.py +0 -0
  213. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_temperature_configuration.py +0 -0
  214. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_temperature_safety_cleanup.py +0 -0
  215. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_temperature_service.py +0 -0
  216. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_transducer_configuration_ownership.py +0 -0
  217. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_unit_conversion.py +0 -0
  218. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_user_documentation.py +0 -0
  219. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_view_trace_partitions.py +0 -0
  220. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_chunking_and_sharding.py +0 -0
  221. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_compression.py +0 -0
  222. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_default_and_naming.py +0 -0
  223. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_manifest_sidecars.py +0 -0
  224. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_metadata_layout.py +0 -0
  225. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_native_backend.py +0 -0
  226. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_read_block_terminology.py +0 -0
  227. {pytesdaqx-0.2.3 → pytesdaqx-0.2.4}/tests/test_zarr_trace_labels.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytesdaqx
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: TES detector acquisition, instrument control, and raw-data recording
5
5
  Author: TESSERACT DAQ developers
6
6
  Classifier: Development Status :: 3 - Alpha
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Topic :: Scientific/Engineering :: Physics
13
13
  Requires-Python: <3.13,>=3.11
14
14
  Description-Content-Type: text/markdown
15
- Requires-Dist: numpy<2.0,>=1.26
15
+ Requires-Dist: numpy>=1.26
16
16
  Requires-Dist: PyYAML
17
17
  Requires-Dist: h5py>=3.10
18
18
  Requires-Dist: matplotlib
@@ -142,3 +142,52 @@ pytesdaqx-build-manifest --acquisition-dir acquisition_I2_D20260727_T120000 --dr
142
142
  Do not routinely rewrite the manifest of an active acquisition. Work on a completed copy unless a documented recovery procedure explicitly says otherwise.
143
143
 
144
144
  The command summary reports the singular acquisition `storage_format` (`zarr` or `hdf5`) and acquisition timing when available, including `fridge_run`, `fridge_run_start`, `acquisition_start`, and the first/last `stream_start`. When rebuilding a Zarr manifest, missing acquisition-wide timing fields in individual stream stores are filled from the top-level acquisition `zarr.json`; each stream's own `stream_start` remains resource-specific. Older pytesdaqx/pytesdaq metadata using `group_*`/`series_*` and `group_start`/`series_start` is accepted on input and converted to the canonical acquisition/stream schema in the rebuilt manifest.
145
+
146
+ ## `pytesdaqx-repair-readout`
147
+
148
+ Readout constants come from `run_setup.yaml` and are stored with every stream.
149
+ A channel recorded without them cannot be converted to physical units
150
+ afterwards, which stops processing with an error such as
151
+ `Cannot convert rigolTTL to amps: missing/invalid close_loop_norm=nan`.
152
+ This happens for a channel configured with an ADC assignment but no
153
+ `readout_circuit`, typically a TTL or other monitor line that has no SQUID
154
+ path.
155
+
156
+ Use this command to write the missing constants into the stored channel map of
157
+ an existing acquisition. Sample data are never modified.
158
+
159
+ ```bash
160
+ # Report what would change (default)
161
+ pytesdaqx-repair-readout /data/raw/calibration_I2_D20260924_T152603.zarr \
162
+ --channel rigolTTL --set close_loop_norm=1
163
+
164
+ # Write the change
165
+ pytesdaqx-repair-readout /data/raw/calibration_I2_D20260924_T152603.zarr \
166
+ --channel rigolTTL --set close_loop_norm=1 --apply
167
+ ```
168
+
169
+ Only streams that recorded the channel are updated. In a mixed acquisition the
170
+ IV, dIdV, and background streams usually do not contain an auxiliary channel,
171
+ and are left untouched; the summary reports how many streams were skipped for
172
+ that reason. Repeat `--set` for several constants. `--set` accepts the readout
173
+ keys listed in `pytesdaqx.io.metadata_compat.READOUT_SETTING_KEYS`; other keys
174
+ are rejected, because readers would ignore them.
175
+
176
+ For a monitor line digitized without a SQUID readout, `close_loop_norm=1` makes
177
+ the "amps" conversion return the measured volts, which keeps threshold settings
178
+ in the units the trigger was tuned against.
179
+
180
+ This command repairs data already on disk. Add the same constants to the
181
+ channel's `readout_circuit` in `run_setup.yaml` so future acquisitions record
182
+ them directly:
183
+
184
+ ```yaml
185
+ rigolTTL:
186
+ adc:
187
+ device: adc1
188
+ channel: 4
189
+ record_for: [calibration]
190
+ readout_circuit:
191
+ close_loop_norm: 1
192
+ ```
193
+
@@ -18,6 +18,7 @@ See [Acquisition and validation](acquisition.md).
18
18
  | `pytesdaqx-display-metadata` | Display acquisition, stream, and legacy HDF5 metadata |
19
19
  | `pytesdaqx-view-traces` | Plot continuous partitions or finite traces |
20
20
  | `pytesdaqx-build-manifest` | Rebuild or inspect acquisition manifest information |
21
+ | `pytesdaqx-repair-readout` | Write missing readout constants into recorded metadata |
21
22
 
22
23
  See [Data inspection](data_inspection.md).
23
24
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pytesdaqx"
7
- version = "0.2.3"
7
+ version = "0.2.4"
8
8
  description = "TES detector acquisition, instrument control, and raw-data recording"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11,<3.13"
@@ -21,7 +21,7 @@ classifiers = [
21
21
  "Topic :: Scientific/Engineering :: Physics",
22
22
  ]
23
23
  dependencies = [
24
- "numpy>=1.26,<2.0",
24
+ "numpy>=1.26",
25
25
  "PyYAML",
26
26
  "h5py>=3.10",
27
27
  "matplotlib",
@@ -82,6 +82,7 @@ pytesdaqx-validate-config = "pytesdaqx.cli.validate_config:main"
82
82
  pytesdaqx-display-metadata = "pytesdaqx.cli.display_metadata:main"
83
83
  pytesdaqx-view-traces = "pytesdaqx.cli.view_traces:main"
84
84
  pytesdaqx-build-manifest = "pytesdaqx.cli.build_manifest:main"
85
+ pytesdaqx-repair-readout = "pytesdaqx.cli.repair_readout:main"
85
86
  [tool.pytest.ini_options]
86
87
  testpaths = ["tests"]
87
88
  python_files = ["test_*.py"]
@@ -0,0 +1,168 @@
1
+ """Write readout-circuit constants into an already recorded acquisition.
2
+
3
+ Readout constants come from ``run_setup.yaml`` and are stored with each
4
+ stream. A channel recorded without them -- a TTL or other monitor line with
5
+ no SQUID path, or a detector channel whose ``readout_circuit`` was left out
6
+ of the run setup -- cannot be converted to amps afterwards, which stops
7
+ processing. This command writes the missing constants into the stored
8
+ channel map so existing data can be processed. Sample data are never touched.
9
+
10
+ Only streams that actually recorded the channel are changed: the IV, dIdV and
11
+ background streams of a mixed acquisition normally do not contain an
12
+ auxiliary channel, and are left alone.
13
+
14
+ Example, for a TTL monitor line digitized without a SQUID readout, where the
15
+ "amps" conversion should just return the measured volts::
16
+
17
+ pytesdaqx-repair-readout /data/raw/calibration_I2_D20260924_T152603.zarr \\
18
+ --channel rigolTTL --set close_loop_norm=1 --apply
19
+
20
+ The same constants belong in ``run_setup.yaml`` under the channel's
21
+ ``readout_circuit`` so that future acquisitions record them directly.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import argparse
27
+ from pathlib import Path
28
+ from typing import Any
29
+
30
+ from pytesdaqx.io.acquisition_catalog import AcquisitionCatalog
31
+ from pytesdaqx.io.metadata_compat import READOUT_SETTING_KEYS
32
+ from pytesdaqx.io.zarr_utils import read_attrs, write_attrs
33
+
34
+ CHANNEL_MAP_KEY = "channel_map"
35
+ READOUT_KEY = "readout_circuit"
36
+
37
+
38
+ def parse_setting(text: str) -> tuple[str, Any]:
39
+ """Parse one ``key=value`` setting, keeping numeric values numeric."""
40
+ key, sep, raw = text.partition("=")
41
+ key, raw = key.strip(), raw.strip()
42
+ if not sep or not key:
43
+ raise argparse.ArgumentTypeError(f"--set expects key=value, got {text!r}")
44
+ if key not in READOUT_SETTING_KEYS:
45
+ raise argparse.ArgumentTypeError(
46
+ f"Unknown readout setting {key!r}. Readers ignore unknown keys, so "
47
+ f"writing one would have no effect. Valid keys: "
48
+ f"{', '.join(sorted(READOUT_SETTING_KEYS))}"
49
+ )
50
+ for cast in (int, float):
51
+ try:
52
+ return key, cast(raw)
53
+ except ValueError:
54
+ continue
55
+ return key, raw
56
+
57
+
58
+ def stream_stores(acquisition: str | Path) -> list[tuple[str, Path]]:
59
+ """Return ``(stream id, store path)`` for every stream of the acquisition."""
60
+ catalog = AcquisitionCatalog(acquisition)
61
+ storage_format = str(catalog.storage_format or "").lower()
62
+ if storage_format != "zarr":
63
+ raise ValueError(
64
+ f"Only Zarr acquisitions can be repaired, got storage_format="
65
+ f"{catalog.storage_format!r}"
66
+ )
67
+ stores: dict[str, Path] = {}
68
+ for entry in catalog.entries:
69
+ store = catalog.resource_path(entry)
70
+ stores.setdefault(str(entry.get("stream_id") or store.stem), store)
71
+ return sorted(stores.items())
72
+
73
+
74
+ def repair_stream(
75
+ store: Path, channel: str, settings: dict[str, Any], *, apply: bool
76
+ ) -> dict[str, Any] | None:
77
+ """Update one stream's channel map.
78
+
79
+ Returns the before/after values, or ``None`` when the stream does not
80
+ record ``channel``.
81
+ """
82
+ array_path = Path(store) / "raw"
83
+ attrs = read_attrs(array_path)
84
+ rows = attrs.get(CHANNEL_MAP_KEY)
85
+ if not isinstance(rows, list):
86
+ raise ValueError(f"{Path(store).name}: no stored channel map in {array_path}")
87
+
88
+ for row in rows:
89
+ if not isinstance(row, dict) or row.get("detector_channel") != channel:
90
+ continue
91
+ circuit = dict(row.get(READOUT_KEY) or {})
92
+ before = {key: circuit.get(key) for key in settings}
93
+ circuit.update(settings)
94
+ if apply:
95
+ row[READOUT_KEY] = circuit
96
+ write_attrs(array_path, attrs)
97
+ return {"before": before, "after": {key: circuit[key] for key in settings}}
98
+ return None
99
+
100
+
101
+ def build_parser() -> argparse.ArgumentParser:
102
+ parser = argparse.ArgumentParser(
103
+ description=(
104
+ "Write readout-circuit constants into the stored metadata of a "
105
+ "recorded acquisition, so a channel recorded without them can be "
106
+ "converted to physical units. Sample data are never modified."
107
+ ),
108
+ )
109
+ parser.add_argument("acquisition", help="Raw pytesdaqx acquisition path")
110
+ parser.add_argument(
111
+ "--channel",
112
+ required=True,
113
+ help="Detector channel whose readout_circuit should be updated",
114
+ )
115
+ parser.add_argument(
116
+ "--set",
117
+ dest="settings",
118
+ required=True,
119
+ action="append",
120
+ type=parse_setting,
121
+ metavar="KEY=VALUE",
122
+ help=(
123
+ "Readout constant to write, for example close_loop_norm=1. "
124
+ "Repeat the option for several constants."
125
+ ),
126
+ )
127
+ parser.add_argument(
128
+ "--apply",
129
+ action="store_true",
130
+ help="Write the changes. Without it, only report what would change.",
131
+ )
132
+ return parser
133
+
134
+
135
+ def main(argv: list[str] | None = None) -> int:
136
+ args = build_parser().parse_args(argv)
137
+ settings = dict(args.settings)
138
+
139
+ stores = stream_stores(args.acquisition)
140
+ changed: list[tuple[str, dict[str, Any]]] = []
141
+ skipped: list[str] = []
142
+ for stream_id, store in stores:
143
+ result = repair_stream(store, args.channel, settings, apply=args.apply)
144
+ if result is None:
145
+ skipped.append(stream_id)
146
+ else:
147
+ changed.append((stream_id, result))
148
+
149
+ print(f"Acquisition: {args.acquisition}")
150
+ print(f"Channel: {args.channel}")
151
+ print(f"Settings: {settings}")
152
+ print(
153
+ f"{'Updated' if args.apply else 'Would update'} {len(changed)} of "
154
+ f"{len(stores)} stream(s); {len(skipped)} stream(s) do not record "
155
+ f"this channel."
156
+ )
157
+ for stream_id, result in changed:
158
+ print(f" {stream_id}: {result['before']} -> {result['after']}")
159
+ if not changed:
160
+ print(f" No stream records channel {args.channel!r}: nothing to do.")
161
+ return 1
162
+ if not args.apply:
163
+ print("\nRe-run with --apply to write these changes.")
164
+ return 0
165
+
166
+
167
+ if __name__ == "__main__":
168
+ raise SystemExit(main())