pyobs-core 2.0.0.dev18__tar.gz → 2.0.0.dev19__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 (447) hide show
  1. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/PKG-INFO +1 -1
  2. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/cli/pyobsd.py +2 -2
  3. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/comm.py +12 -20
  4. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/local/localcomm.py +4 -0
  5. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/serializer.py +8 -0
  6. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xmppcomm.py +7 -3
  7. pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingBody.py +29 -0
  8. pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingHeliocentricPolar.py +41 -0
  9. pyobs_core-2.0.0.dev18/pyobs/interfaces/IPointingHGS.py → pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingHeliographicStonyhurst.py +7 -6
  10. pyobs_core-2.0.0.dev19/pyobs/interfaces/IPointingOrbitalElements.py +47 -0
  11. pyobs_core-2.0.0.dev19/pyobs/interfaces/ITrackingMode.py +54 -0
  12. pyobs_core-2.0.0.dev19/pyobs/interfaces/ITrackingRate.py +54 -0
  13. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/__init__.py +20 -3
  14. pyobs_core-2.0.0.dev19/pyobs/interfaces/interface.py +77 -0
  15. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/fitsheader.py +16 -12
  16. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/basevideo.py +3 -9
  17. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/module.py +10 -17
  18. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/_baseguiding.py +2 -1
  19. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/acquisition.py +2 -1
  20. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/mastermind.py +1 -1
  21. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/scheduler.py +3 -3
  22. pyobs_core-2.0.0.dev19/pyobs/modules/telescope/__init__.py +13 -0
  23. pyobs_core-2.0.0.dev18/pyobs/modules/telescope/dummytelescope.py → pyobs_core-2.0.0.dev19/pyobs/modules/telescope/_dummytelescopebase.py +52 -30
  24. pyobs_core-2.0.0.dev19/pyobs/modules/telescope/basetelescope.py +815 -0
  25. pyobs_core-2.0.0.dev19/pyobs/modules/telescope/dummyaltaztelescope.py +46 -0
  26. pyobs_core-2.0.0.dev19/pyobs/modules/telescope/dummyradectelescope.py +55 -0
  27. pyobs_core-2.0.0.dev19/pyobs/modules/telescope/dummysolartelescope.py +149 -0
  28. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/__init__.py +1 -2
  29. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/object.py +15 -17
  30. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/flatfielder.py +1 -1
  31. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/enums.py +6 -0
  32. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/filters.py +6 -6
  33. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/serialization.py +0 -3
  34. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyproject.toml +1 -1
  35. pyobs_core-2.0.0.dev18/pyobs/interfaces/interface.py +0 -36
  36. pyobs_core-2.0.0.dev18/pyobs/modules/telescope/__init__.py +0 -11
  37. pyobs_core-2.0.0.dev18/pyobs/modules/telescope/basetelescope.py +0 -353
  38. pyobs_core-2.0.0.dev18/pyobs/modules/utils/autonomouswarning.py +0 -153
  39. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/.gitignore +0 -0
  40. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/LICENSE +0 -0
  41. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/__init__.py +0 -0
  42. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/application.py +0 -0
  43. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/background_task.py +0 -0
  44. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/cli/__init__.py +0 -0
  45. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/cli/_cli.py +0 -0
  46. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/cli/pyobs.py +0 -0
  47. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/cli/pyobsw.py +0 -0
  48. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/__init__.py +0 -0
  49. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/commlogging.py +0 -0
  50. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/dummy/__init__.py +0 -0
  51. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/dummy/dummycomm.py +0 -0
  52. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/local/__init__.py +0 -0
  53. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/local/localnetwork.py +0 -0
  54. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/proxy.py +0 -0
  55. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/__init__.py +0 -0
  56. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/rpc.py +0 -0
  57. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
  58. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
  59. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
  60. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
  61. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
  62. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
  63. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
  64. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/comm/xmpp/xmppclient.py +0 -0
  65. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/__init__.py +0 -0
  66. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/badweather.py +0 -0
  67. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/event.py +0 -0
  68. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/exposurestatuschanged.py +0 -0
  69. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/filterchanged.py +0 -0
  70. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/focusfound.py +0 -0
  71. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/goodweather.py +0 -0
  72. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/log.py +0 -0
  73. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/modechanged.py +0 -0
  74. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/moduleclosed.py +0 -0
  75. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/moduleopened.py +0 -0
  76. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/motionstatuschanged.py +0 -0
  77. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/move.py +0 -0
  78. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/newimage.py +0 -0
  79. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/newspectrum.py +0 -0
  80. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/offsets.py +0 -0
  81. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/roofclosing.py +0 -0
  82. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/roofopened.py +0 -0
  83. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/taskfailed.py +0 -0
  84. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/taskfinished.py +0 -0
  85. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/taskstarted.py +0 -0
  86. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/events/testevent.py +0 -0
  87. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/__init__.py +0 -0
  88. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/image.py +0 -0
  89. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/__init__.py +0 -0
  90. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/altazoffsets.py +0 -0
  91. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/exptime.py +0 -0
  92. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/genericoffset.py +0 -0
  93. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/onskydistance.py +0 -0
  94. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/pixeloffsets.py +0 -0
  95. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/radecoffsets.py +0 -0
  96. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/meta/skyoffsets.py +0 -0
  97. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processor.py +0 -0
  98. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/__init__.py +0 -0
  99. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/_daobackgroundremover.py +0 -0
  100. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/__init__.py +0 -0
  101. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/_pillow.py +0 -0
  102. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/circle.py +0 -0
  103. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/crosshair.py +0 -0
  104. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/annotation/text.py +0 -0
  105. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/__init__.py +0 -0
  106. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
  107. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
  108. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
  109. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
  110. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/astrometry.py +0 -0
  111. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/astrometry/dotnet.py +0 -0
  112. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/__init__.py +0 -0
  113. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
  114. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
  115. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/calibration/calibration.py +0 -0
  116. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/__init__.py +0 -0
  117. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
  118. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/_source_catalog.py +0 -0
  119. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/daophot.py +0 -0
  120. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/pysep.py +0 -0
  121. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/simpledisk.py +0 -0
  122. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/detection/sourcedetection.py +0 -0
  123. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/exptime/__init__.py +0 -0
  124. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/exptime/exptime.py +0 -0
  125. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/exptime/star.py +0 -0
  126. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/__init__.py +0 -0
  127. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/addfitsheaders.py +0 -0
  128. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/download.py +0 -0
  129. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/flip.py +0 -0
  130. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/grayscale.py +0 -0
  131. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/httpserver.py +0 -0
  132. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/normalize.py +0 -0
  133. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/save.py +0 -0
  134. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/saveimage.py +0 -0
  135. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/smooth.py +0 -0
  136. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/image/softbin.py +0 -0
  137. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/__init__.py +0 -0
  138. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/addmask.py +0 -0
  139. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
  140. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/circularmask.py +0 -0
  141. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/createfilename.py +0 -0
  142. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
  143. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/misc/removebackground.py +0 -0
  144. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/modules/__init__.py +0 -0
  145. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
  146. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/__init__.py +0 -0
  147. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/astrometry.py +0 -0
  148. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/brighteststar.py +0 -0
  149. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
  150. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
  151. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
  152. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/fitsheader.py +0 -0
  153. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/offsets.py +0 -0
  154. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
  155. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/projected.py +0 -0
  156. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/offsets/spilled_light.py +0 -0
  157. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/__init__.py +0 -0
  158. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
  159. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
  160. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
  161. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
  162. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/photometry.py +0 -0
  163. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/photutil.py +0 -0
  164. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/photometry/pysep.py +0 -0
  165. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/wcs/__init__.py +0 -0
  166. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
  167. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAbortable.py +0 -0
  168. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAcquisition.py +0 -0
  169. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAutoFocus.py +0 -0
  170. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAutoGuiding.py +0 -0
  171. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IAutonomous.py +0 -0
  172. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IBinning.py +0 -0
  173. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ICalibrate.py +0 -0
  174. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ICamera.py +0 -0
  175. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IConfig.py +0 -0
  176. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ICooling.py +0 -0
  177. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IData.py +0 -0
  178. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IDome.py +0 -0
  179. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IExposure.py +0 -0
  180. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IExposureTime.py +0 -0
  181. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFilters.py +0 -0
  182. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
  183. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
  184. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFlatField.py +0 -0
  185. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFocusModel.py +0 -0
  186. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IFocuser.py +0 -0
  187. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IGain.py +0 -0
  188. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IImageFormat.py +0 -0
  189. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IImageType.py +0 -0
  190. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IMode.py +0 -0
  191. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IModule.py +0 -0
  192. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IMotion.py +0 -0
  193. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IMultiFiber.py +0 -0
  194. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
  195. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
  196. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingAltAz.py +0 -0
  197. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
  198. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingRaDec.py +0 -0
  199. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IPointingSeries.py +0 -0
  200. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IReady.py +0 -0
  201. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRoof.py +0 -0
  202. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRotation.py +0 -0
  203. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRunnable.py +0 -0
  204. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IRunning.py +0 -0
  205. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IScriptRunner.py +0 -0
  206. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ISpectrograph.py +0 -0
  207. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IStartStop.py +0 -0
  208. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IStructuredConfig.py +0 -0
  209. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ISyncTarget.py +0 -0
  210. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ITelescope.py +0 -0
  211. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/ITemperatures.py +0 -0
  212. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IVideo.py +0 -0
  213. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IWeather.py +0 -0
  214. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/interfaces/IWindow.py +0 -0
  215. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/__init__.py +0 -0
  216. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/camerasettings.py +0 -0
  217. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/fitsnamespace.py +0 -0
  218. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/follow.py +0 -0
  219. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/motionstatus.py +0 -0
  220. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/pipeline.py +0 -0
  221. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/waitformotion.py +0 -0
  222. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/mixins/weatheraware.py +0 -0
  223. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/__init__.py +0 -0
  224. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/__init__.py +0 -0
  225. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/adaptive.py +0 -0
  226. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/basecamera.py +0 -0
  227. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/basespectrograph.py +0 -0
  228. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/dummycamera.py +0 -0
  229. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/dummyspectrograph.py +0 -0
  230. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/dummyvideo.py +0 -0
  231. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/camera/pipelinecamera.py +0 -0
  232. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/__init__.py +0 -0
  233. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/flatfield.py +0 -0
  234. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/pointing.py +0 -0
  235. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/flatfield/scheduler.py +0 -0
  236. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/__init__.py +0 -0
  237. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/dummyautofocus.py +0 -0
  238. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/focusmodel.py +0 -0
  239. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/focus/focusseries.py +0 -0
  240. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/__init__.py +0 -0
  241. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/imagewatcher.py +0 -0
  242. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/imagewriter.py +0 -0
  243. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/pipeline.py +0 -0
  244. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/image/seeing.py +0 -0
  245. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/__init__.py +0 -0
  246. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/_base.py +0 -0
  247. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/autoguiding.py +0 -0
  248. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/dummyacquisition.py +0 -0
  249. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/dummyguiding.py +0 -0
  250. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
  251. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
  252. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
  253. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
  254. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
  255. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
  256. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/__init__.py +0 -0
  257. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/pointing.py +0 -0
  258. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/robotic/scriptrunner.py +0 -0
  259. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/__init__.py +0 -0
  260. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/basedome.py +0 -0
  261. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/baseroof.py +0 -0
  262. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/roof/dummyroof.py +0 -0
  263. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/test/__init__.py +0 -0
  264. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/test/standalone.py +0 -0
  265. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/dummymode.py +0 -0
  266. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/fluentlogger.py +0 -0
  267. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/httpfilecache.py +0 -0
  268. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/kiosk.py +0 -0
  269. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/matrix.py +0 -0
  270. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/stellarium.py +0 -0
  271. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/telegram.py +0 -0
  272. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/utils/trigger.py +0 -0
  273. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/__init__.py +0 -0
  274. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/mockweather.py +0 -0
  275. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/weather.py +0 -0
  276. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/weather_api.py +0 -0
  277. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/modules/weather/weather_state.py +0 -0
  278. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/py.typed +0 -0
  279. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/__init__.py +0 -0
  280. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/observation.py +0 -0
  281. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/__init__.py +0 -0
  282. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
  283. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
  284. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
  285. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
  286. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
  287. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
  288. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
  289. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
  290. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/dataprovider.py +0 -0
  291. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
  292. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
  293. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
  294. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/constant.py +0 -0
  295. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/follow.py +0 -0
  296. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/interval.py +0 -0
  297. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/merit.py +0 -0
  298. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
  299. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/random.py +0 -0
  300. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
  301. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/merits/transit.py +0 -0
  302. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
  303. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
  304. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
  305. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
  306. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
  307. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
  308. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
  309. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
  310. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
  311. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
  312. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/targets/target.py +0 -0
  313. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
  314. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/__init__.py +0 -0
  315. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
  316. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
  317. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
  318. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
  319. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/__init__.py +0 -0
  320. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/cases.py +0 -0
  321. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/conditional.py +0 -0
  322. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/parallel.py +0 -0
  323. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/selector.py +0 -0
  324. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/control/sequential.py +0 -0
  325. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
  326. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
  327. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
  328. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
  329. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/script.py +0 -0
  330. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/__init__.py +0 -0
  331. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
  332. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
  333. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/scripts/utils/log.py +0 -0
  334. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/__init__.py +0 -0
  335. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/backend/__init__.py +0 -0
  336. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
  337. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
  338. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
  339. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
  340. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
  341. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/__init__.py +0 -0
  342. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/_portal.py +0 -0
  343. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
  344. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
  345. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/configdb.py +0 -0
  346. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
  347. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
  348. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
  349. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
  350. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
  351. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
  352. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/task.py +0 -0
  353. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
  354. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
  355. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/memory/__init__.py +0 -0
  356. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
  357. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
  358. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/observationarchive.py +0 -0
  359. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/storage/taskarchive.py +0 -0
  360. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/task.py +0 -0
  361. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/taskrunner.py +0 -0
  362. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/__init__.py +0 -0
  363. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/__init__.py +0 -0
  364. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/archive.py +0 -0
  365. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/local_archive.py +0 -0
  366. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
  367. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/exptime/__init__.py +0 -0
  368. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/exptime/exptime.py +0 -0
  369. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
  370. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
  371. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
  372. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
  373. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
  374. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
  375. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
  376. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
  377. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
  378. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
  379. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
  380. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/__init__.py +0 -0
  381. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/average.py +0 -0
  382. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/cache.py +0 -0
  383. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/config.py +0 -0
  384. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/config_schema.py +0 -0
  385. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/coordinates.py +0 -0
  386. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/curvefit.py +0 -0
  387. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/exceptions.py +0 -0
  388. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/fits.py +0 -0
  389. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/__init__.py +0 -0
  390. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/base.py +0 -0
  391. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/photometry.py +0 -0
  392. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/focusseries/projection.py +0 -0
  393. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/__init__.py +0 -0
  394. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/grid.py +0 -0
  395. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/gridnode.py +0 -0
  396. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/grids/pipeline.py +0 -0
  397. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/__init__.py +0 -0
  398. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/__init__.py +0 -0
  399. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/binningwidget.py +0 -0
  400. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
  401. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/exposewidget.py +0 -0
  402. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
  403. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
  404. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
  405. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
  406. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/http.py +0 -0
  407. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/influxdb.py +0 -0
  408. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/logger.py +0 -0
  409. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/logging/__init__.py +0 -0
  410. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/logging/context.py +0 -0
  411. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/logging/resolvableerror.py +0 -0
  412. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/modulegui.py +0 -0
  413. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/__init__.py +0 -0
  414. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
  415. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/applyoffsets.py +0 -0
  416. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
  417. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/parallel.py +0 -0
  418. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/pipeline/__init__.py +0 -0
  419. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/pipeline/night.py +0 -0
  420. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/pipeline/pipeline.py +0 -0
  421. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/__init__.py +0 -0
  422. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/csv.py +0 -0
  423. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/http.py +0 -0
  424. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/log.py +0 -0
  425. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/multi.py +0 -0
  426. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/publisher/publisher.py +0 -0
  427. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/shellcommand.py +0 -0
  428. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/threads/__init__.py +0 -0
  429. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/threads/lockwithabort.py +0 -0
  430. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/time.py +0 -0
  431. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/utils/units.py +0 -0
  432. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/version.py +0 -0
  433. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/__init__.py +0 -0
  434. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/archivefile.py +0 -0
  435. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/bufferedfile.py +0 -0
  436. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/file.py +0 -0
  437. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/filelists/__init__.py +0 -0
  438. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/filelists/filelist.py +0 -0
  439. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/filelists/testing.py +0 -0
  440. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/httpfile.py +0 -0
  441. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/localfile.py +0 -0
  442. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/memfile.py +0 -0
  443. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/sftpfile.py +0 -0
  444. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/smbfile.py +0 -0
  445. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/sshfile.py +0 -0
  446. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/tempfile.py +0 -0
  447. {pyobs_core-2.0.0.dev18 → pyobs_core-2.0.0.dev19}/pyobs/vfs/vfs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyobs-core
3
- Version: 2.0.0.dev18
3
+ Version: 2.0.0.dev19
4
4
  Summary: robotic telescope software
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
@@ -91,7 +91,7 @@ class PyobsDaemonCLI(CLI):
91
91
  case "status":
92
92
  daemon.status(print_json=self._config["json"])
93
93
  case "list":
94
- daemon.list()
94
+ daemon.list_modules()
95
95
  case "logs":
96
96
  daemon.logs(self._config["args"])
97
97
 
@@ -295,7 +295,7 @@ class PyobsDaemon:
295
295
  else:
296
296
  print(f"{module:<30} {'stopped':<8}")
297
297
 
298
- def list(self) -> None:
298
+ def list_modules(self) -> None:
299
299
  print("\n".join(self._list_configs()))
300
300
 
301
301
  def logs(self, args: list[str]) -> None:
@@ -7,9 +7,9 @@ import logging
7
7
  from collections.abc import Callable, Coroutine
8
8
  from typing import TYPE_CHECKING, Any, overload
9
9
 
10
- import pyobs.interfaces
11
10
  from pyobs.events import Event, LogEvent, ModuleClosedEvent
12
11
  from pyobs.interfaces import Interface
12
+ from pyobs.interfaces.interface import get_registered_interface
13
13
  from pyobs.utils.enums import ModuleState
14
14
 
15
15
  from .commlogging import CommLoggingHandler
@@ -337,28 +337,13 @@ class Comm:
337
337
  list of interface classes.
338
338
  """
339
339
 
340
- # get interface classes
341
- inspection = inspect.getmembers(pyobs.interfaces, predicate=inspect.isclass)
342
-
343
340
  # loop interfaces
344
341
  interface_classes = []
345
342
  for interface_name in interfaces:
346
- # loop all classes
347
- found = False
348
- for cls_name, cls in inspection:
349
- # class needs to face same name and implement Interface
350
- if interface_name == cls_name and issubclass(cls, Interface):
351
- # found it!
352
- found = True
353
-
354
- # then add it to the list of all interfaces
355
- interface_classes.append(cls)
356
-
357
- # there can only be one...
358
- break
359
-
360
- # not found?
361
- if not found:
343
+ cls = get_registered_interface(interface_name)
344
+ if cls is not None:
345
+ interface_classes.append(cls)
346
+ else:
362
347
  log.error('Could not find interface "%s" for client.', interface_name)
363
348
  return interface_classes
364
349
 
@@ -541,6 +526,13 @@ class Comm:
541
526
  def _get_own_state(self, interface: type[Interface]) -> Any:
542
527
  return None
543
528
 
529
+ def get_own_capabilities(self, interface: type[Interface]) -> Any:
530
+ """Return the capabilities published by this module for the given interface, or None."""
531
+ return self._get_own_capabilities(interface)
532
+
533
+ def _get_own_capabilities(self, interface: type[Interface]) -> Any:
534
+ return None
535
+
544
536
  async def subscribe_state(
545
537
  self,
546
538
  module: str,
@@ -117,6 +117,10 @@ class LocalComm(Comm):
117
117
  """Store capabilities locally."""
118
118
  self._capabilities[interface] = capabilities
119
119
 
120
+ def _get_own_capabilities(self, interface: type[Interface]) -> Any:
121
+ """Return this client's own published capabilities."""
122
+ return self._capabilities.get(interface)
123
+
120
124
  async def _get_capabilities(self, module: str, interface: type[Interface]) -> Any | None:
121
125
  """Fetch capabilities from a remote module."""
122
126
  if interface.capabilities is None:
@@ -32,6 +32,7 @@ import types as _builtin_types
32
32
  from enum import StrEnum
33
33
  from typing import Annotated, Any, Union, get_args, get_origin, get_type_hints
34
34
 
35
+ import numpy as np
35
36
  from slixmpp.xmlstream import ET
36
37
 
37
38
  from ...interfaces.interface import Interface as _Interface
@@ -65,6 +66,13 @@ def value_to_xml(value: Any, type_hint: Any) -> ET.Element:
65
66
  if get_origin(type_hint) is Annotated:
66
67
  type_hint = get_args(type_hint)[0]
67
68
 
69
+ # Normalize numpy scalars (np.float64, np.int64, np.bool_, ...) to native
70
+ # Python types. np.float64 subclasses float but repr()s as "np.float64(x)"
71
+ # since numpy 2.0, which corrupts <double> text; numpy integer types don't
72
+ # subclass int at all and would otherwise fall through to <string>.
73
+ if isinstance(value, np.generic):
74
+ value = value.item()
75
+
68
76
  # None / void
69
77
  if value is None:
70
78
  elem = ET.Element("nil")
@@ -18,11 +18,11 @@ from slixmpp.xmlstream import ET
18
18
  from slixmpp.xmlstream.handler import Callback
19
19
  from slixmpp.xmlstream.matcher import MatchXMLMask
20
20
 
21
- import pyobs.interfaces
22
21
  from pyobs.comm import Comm
23
22
  from pyobs.events import Event, LogEvent, ModuleClosedEvent, ModuleOpenedEvent
24
23
  from pyobs.events.event import EventFactory
25
24
  from pyobs.interfaces import Interface
25
+ from pyobs.interfaces.interface import get_registered_interface
26
26
  from pyobs.utils import exceptions as exc
27
27
  from pyobs.utils.enums import ModuleState
28
28
 
@@ -406,8 +406,8 @@ class XmppComm(Comm):
406
406
  interface_names = []
407
407
  for feature in features:
408
408
  name, _, version = feature[len(prefix) :].rpartition(":")
409
- local_cls = getattr(pyobs.interfaces, name, None)
410
- if local_cls is not None and issubclass(local_cls, Interface) and str(local_cls.version) == version:
409
+ local_cls = get_registered_interface(name)
410
+ if local_cls is not None and str(local_cls.version) == version:
411
411
  interface_names.append(name)
412
412
 
413
413
  # IModule not in list?
@@ -896,6 +896,10 @@ class XmppComm(Comm):
896
896
  self._capabilities[interface] = capabilities
897
897
  log.info("Published capabilities for %s", interface.__name__)
898
898
 
899
+ def _get_own_capabilities(self, interface: type[Interface]) -> Any:
900
+ """Return this client's own published capabilities."""
901
+ return self._capabilities.get(interface)
902
+
899
903
  async def _get_capabilities(self, module: str, interface: type[Interface]) -> Any | None:
900
904
  """Fetch and deserialize capabilities for a remote module's interface."""
901
905
  if interface.capabilities is None:
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from typing import Any
5
+
6
+ from .interface import Interface
7
+
8
+
9
+ class IPointingBody(Interface, metaclass=ABCMeta):
10
+ """Points at and tracks a named solar-system body."""
11
+
12
+ __module__ = "pyobs.interfaces"
13
+
14
+ @abstractmethod
15
+ async def track_body(self, body: str, **kwargs: Any) -> None:
16
+ """Starts tracking a named solar-system body.
17
+
18
+ Args:
19
+ body: Name resolvable to an ephemeris (e.g. 'moon', 'mars', 'jupiter', or an
20
+ asteroid/comet designation known to JPL Horizons).
21
+
22
+ Raises:
23
+ MoveError: If telescope could not be moved.
24
+ ValueError: If body name is not resolvable.
25
+ """
26
+ ...
27
+
28
+
29
+ __all__ = ["IPointingBody"]
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from dataclasses import dataclass, field
5
+ from typing import Annotated, Any
6
+
7
+ from ..utils.enums import Unit
8
+ from ..utils.time import Time
9
+ from .interface import Interface
10
+
11
+
12
+ @dataclass
13
+ class HeliocentricPolarState:
14
+ mu: float
15
+ psi: Annotated[float, Unit.DEGREES]
16
+ time: Time = field(default_factory=Time.now)
17
+
18
+
19
+ class IPointingHeliocentricPolar(Interface, metaclass=ABCMeta):
20
+ """The module can move to Heliocentric Polar (Mu/Psi) coordinates, usually combined with
21
+ :class:`~pyobs.interfaces.ITelescope`."""
22
+
23
+ __module__ = "pyobs.interfaces"
24
+
25
+ state = HeliocentricPolarState
26
+
27
+ @abstractmethod
28
+ async def move_heliocentric_polar(self, mu: float, psi: Annotated[float, Unit.DEGREES], **kwargs: Any) -> None:
29
+ """Moves on given coordinates.
30
+
31
+ Args:
32
+ mu: Cosine of the angular distance from Sun centre, dimensionless (0..1).
33
+ psi: Position angle around the solar disk, in degrees.
34
+
35
+ Raises:
36
+ MoveError: If device could not be moved.
37
+ """
38
+ ...
39
+
40
+
41
+ __all__ = ["IPointingHeliocentricPolar", "HeliocentricPolarState"]
@@ -10,21 +10,22 @@ from .interface import Interface
10
10
 
11
11
 
12
12
  @dataclass
13
- class HGSState:
13
+ class HeliographicStonyhurstState:
14
14
  lon: Annotated[float, Unit.DEGREES]
15
15
  lat: Annotated[float, Unit.DEGREES]
16
16
  time: Time = field(default_factory=Time.now)
17
17
 
18
18
 
19
- class IPointingHGS(Interface, metaclass=ABCMeta):
20
- """The module can move to Mu/Psi coordinates, usually combined with :class:`~pyobs.interfaces.ITelescope`."""
19
+ class IPointingHeliographicStonyhurst(Interface, metaclass=ABCMeta):
20
+ """The module can move to Heliographic Stonyhurst (lon/lat) coordinates, a frame fixed to the Sun's
21
+ rotating surface, usually combined with :class:`~pyobs.interfaces.ITelescope`."""
21
22
 
22
23
  __module__ = "pyobs.interfaces"
23
24
 
24
- state = HGSState
25
+ state = HeliographicStonyhurstState
25
26
 
26
27
  @abstractmethod
27
- async def move_hgs_lon_lat(
28
+ async def move_heliographic_stonyhurst(
28
29
  self, lon: Annotated[float, Unit.DEGREES], lat: Annotated[float, Unit.DEGREES], **kwargs: Any
29
30
  ) -> None:
30
31
  """Moves on given coordinates.
@@ -39,4 +40,4 @@ class IPointingHGS(Interface, metaclass=ABCMeta):
39
40
  ...
40
41
 
41
42
 
42
- __all__ = ["IPointingHGS", "HGSState"]
43
+ __all__ = ["IPointingHeliographicStonyhurst", "HeliographicStonyhurstState"]
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from dataclasses import dataclass
5
+ from typing import Annotated, Any
6
+
7
+ from ..utils.enums import Unit
8
+ from ..utils.time import Time
9
+ from .interface import Interface
10
+
11
+
12
+ @dataclass
13
+ class OrbitalElements:
14
+ epoch: Time
15
+ semi_major_axis: Annotated[float, Unit.AU]
16
+ eccentricity: float
17
+ inclination: Annotated[float, Unit.DEGREES]
18
+ longitude_ascending_node: Annotated[float, Unit.DEGREES]
19
+ argument_of_periapsis: Annotated[float, Unit.DEGREES]
20
+ mean_anomaly: Annotated[float, Unit.DEGREES] | None = None
21
+ """Mean anomaly at epoch, in degrees. Required for elliptical orbits (eccentricity < 1)."""
22
+ perihelion_time: Time | None = None
23
+ """Time of perihelion passage. Required for near-parabolic/cometary orbits
24
+ (eccentricity close to or at 1), where mean anomaly is not well-defined."""
25
+
26
+
27
+ class IPointingOrbitalElements(Interface, metaclass=ABCMeta):
28
+ """Points at and tracks a body defined by orbital elements (asteroid, comet, NEO)."""
29
+
30
+ __module__ = "pyobs.interfaces"
31
+
32
+ @abstractmethod
33
+ async def track_orbital_elements(self, elements: OrbitalElements, **kwargs: Any) -> None:
34
+ """Starts tracking a body defined by orbital elements.
35
+
36
+ Args:
37
+ elements: Orbital elements of the body to track.
38
+
39
+ Raises:
40
+ MoveError: If telescope could not be moved.
41
+ ValueError: If elements are incomplete or inconsistent (neither mean_anomaly
42
+ nor perihelion_time given).
43
+ """
44
+ ...
45
+
46
+
47
+ __all__ = ["IPointingOrbitalElements", "OrbitalElements"]
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from dataclasses import dataclass, field
5
+ from enum import StrEnum
6
+ from typing import Any
7
+
8
+ from ..utils.time import Time
9
+ from .interface import Interface
10
+
11
+
12
+ class TrackingMode(StrEnum):
13
+ """Discrete, hardware-native tracking rate."""
14
+
15
+ SIDEREAL = "sidereal"
16
+ SOLAR = "solar"
17
+ LUNAR = "lunar"
18
+ OFF = "off"
19
+
20
+
21
+ @dataclass
22
+ class TrackingModeState:
23
+ mode: TrackingMode
24
+ time: Time = field(default_factory=Time.now)
25
+
26
+
27
+ @dataclass
28
+ class TrackingModeCapabilities:
29
+ modes: list[TrackingMode]
30
+
31
+
32
+ class ITrackingMode(Interface, metaclass=ABCMeta):
33
+ """The module supports switching between discrete, hardware-native tracking rates."""
34
+
35
+ __module__ = "pyobs.interfaces"
36
+
37
+ state = TrackingModeState
38
+ capabilities = TrackingModeCapabilities
39
+
40
+ @abstractmethod
41
+ async def set_tracking_mode(self, mode: TrackingMode, **kwargs: Any) -> None:
42
+ """Switches to the given tracking mode.
43
+
44
+ Args:
45
+ mode: Tracking mode to switch to.
46
+
47
+ Raises:
48
+ MoveError: If mode could not be set.
49
+ ValueError: If mode is not in this module's capabilities.
50
+ """
51
+ ...
52
+
53
+
54
+ __all__ = ["ITrackingMode", "TrackingMode", "TrackingModeState", "TrackingModeCapabilities"]
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+ from dataclasses import dataclass, field
5
+ from typing import Annotated, Any
6
+
7
+ from ..utils.enums import Unit
8
+ from ..utils.time import Time
9
+ from .interface import Interface
10
+
11
+
12
+ @dataclass
13
+ class TrackingRateState:
14
+ ra_rate: Annotated[float, Unit.ARCSEC_PER_SEC]
15
+ dec_rate: Annotated[float, Unit.ARCSEC_PER_SEC]
16
+ time: Time = field(default_factory=Time.now)
17
+
18
+
19
+ @dataclass
20
+ class TrackingRateCapabilities:
21
+ min_update_interval: Annotated[float, Unit.SECONDS]
22
+ """Minimum time between successive set_tracking_rate calls this hardware/protocol accepts,
23
+ independent of whether the value actually changed. Populated per-driver from whatever its
24
+ protocol allows; 0 if the hardware has no such floor."""
25
+
26
+
27
+ class ITrackingRate(Interface, metaclass=ABCMeta):
28
+ """The module accepts an arbitrary non-sidereal tracking rate as an absolute RA/Dec offset."""
29
+
30
+ __module__ = "pyobs.interfaces"
31
+
32
+ state = TrackingRateState
33
+ capabilities = TrackingRateCapabilities
34
+
35
+ @abstractmethod
36
+ async def set_tracking_rate(
37
+ self,
38
+ ra_rate: Annotated[float, Unit.ARCSEC_PER_SEC],
39
+ dec_rate: Annotated[float, Unit.ARCSEC_PER_SEC],
40
+ **kwargs: Any,
41
+ ) -> None:
42
+ """Sets an absolute tracking rate on the sky, in arcsec/sec.
43
+
44
+ Args:
45
+ ra_rate: Rate in RA, arcsec/sec on the sky.
46
+ dec_rate: Rate in Dec, arcsec/sec on the sky.
47
+
48
+ Raises:
49
+ MoveError: If rate could not be set.
50
+ """
51
+ ...
52
+
53
+
54
+ __all__ = ["ITrackingRate", "TrackingRateState", "TrackingRateCapabilities"]
@@ -43,8 +43,11 @@ from .interface import Interface
43
43
  from .IOffsetsAltAz import AltAzOffsetState, IOffsetsAltAz
44
44
  from .IOffsetsRaDec import IOffsetsRaDec, RaDecOffsetState
45
45
  from .IPointingAltAz import AltAzState, IPointingAltAz
46
+ from .IPointingBody import IPointingBody
47
+ from .IPointingHeliocentricPolar import HeliocentricPolarState, IPointingHeliocentricPolar
48
+ from .IPointingHeliographicStonyhurst import HeliographicStonyhurstState, IPointingHeliographicStonyhurst
46
49
  from .IPointingHelioprojective import HelioprojectiveState, IPointingHelioprojective
47
- from .IPointingHGS import HGSState, IPointingHGS
50
+ from .IPointingOrbitalElements import IPointingOrbitalElements, OrbitalElements
48
51
  from .IPointingRaDec import IPointingRaDec, RaDecState
49
52
  from .IPointingSeries import IPointingSeries
50
53
  from .IReady import IReady, ReadyState
@@ -59,6 +62,8 @@ from .IStructuredConfig import ConfigAppliedState, ConfigFieldSchema, ConfigSche
59
62
  from .ISyncTarget import ISyncTarget
60
63
  from .ITelescope import ITelescope
61
64
  from .ITemperatures import ITemperatures, SensorReading, TemperaturesState
65
+ from .ITrackingMode import ITrackingMode, TrackingMode, TrackingModeCapabilities, TrackingModeState
66
+ from .ITrackingRate import ITrackingRate, TrackingRateCapabilities, TrackingRateState
62
67
  from .IVideo import IVideo, VideoCapabilities
63
68
  from .IWeather import IWeather, WeatherSensorReading, WeatherState
64
69
  from .IWindow import IWindow, WindowCapabilities, WindowState
@@ -127,10 +132,15 @@ __all__ = [
127
132
  "MultiFiberState",
128
133
  "IPointingAltAz",
129
134
  "AltAzState",
135
+ "IPointingBody",
136
+ "IPointingHeliocentricPolar",
137
+ "HeliocentricPolarState",
138
+ "IPointingHeliographicStonyhurst",
139
+ "HeliographicStonyhurstState",
130
140
  "IPointingHelioprojective",
131
141
  "HelioprojectiveState",
132
- "IPointingHGS",
133
- "HGSState",
142
+ "IPointingOrbitalElements",
143
+ "OrbitalElements",
134
144
  "IPointingRaDec",
135
145
  "RaDecState",
136
146
  "IPointingSeries",
@@ -153,6 +163,13 @@ __all__ = [
153
163
  "ITemperatures",
154
164
  "SensorReading",
155
165
  "TemperaturesState",
166
+ "ITrackingMode",
167
+ "TrackingMode",
168
+ "TrackingModeState",
169
+ "TrackingModeCapabilities",
170
+ "ITrackingRate",
171
+ "TrackingRateState",
172
+ "TrackingRateCapabilities",
156
173
  "IOffsetsAltAz",
157
174
  "AltAzOffsetState",
158
175
  "IOffsetsRaDec",
@@ -0,0 +1,77 @@
1
+ from abc import ABCMeta
2
+ from typing import Any, ClassVar
3
+
4
+ _REGISTRY: dict[str, "type[Interface]"] = {}
5
+
6
+
7
+ class Interface(metaclass=ABCMeta):
8
+ """Base class for all interfaces in pyobs."""
9
+
10
+ version: int = 1
11
+ state: ClassVar[type | None] = None
12
+ capabilities: ClassVar[type | None] = None
13
+
14
+ __module__ = "pyobs.interfaces"
15
+
16
+ def __init_subclass__(cls, **kwargs: Any) -> None:
17
+ super().__init_subclass__(**kwargs)
18
+
19
+ # only genuine interface definitions get registered. Concrete module
20
+ # classes (e.g. `class BaseCamera(Module, ICamera, IExposureTime,
21
+ # IImageType)`) also transitively subclass Interface, but always mix
22
+ # in at least one base that isn't itself an Interface subclass
23
+ # (Module, a FITS-header mixin, ...). A base only counts as "pure"
24
+ # if it's Interface itself or is already registered -- issubclass(
25
+ # base, Interface) alone isn't enough, since e.g. BaseCamera
26
+ # transitively satisfies that (via ICamera) despite mixing in
27
+ # Module, which would let DummyCamera(BaseCamera, ...) register
28
+ # too. Checking registry membership instead propagates purity down
29
+ # the whole chain, since BaseCamera itself never gets registered.
30
+ def _is_pure(base: type) -> bool:
31
+ return base is Interface or _REGISTRY.get(base.__name__) is base
32
+
33
+ if not all(_is_pure(base) for base in cls.__bases__):
34
+ return
35
+
36
+ existing = _REGISTRY.get(cls.__name__)
37
+ if existing is not None and existing is not cls:
38
+ raise TypeError(
39
+ f"Interface name '{cls.__name__}' is already registered by "
40
+ f"{existing.__module__}.{existing.__qualname__}; "
41
+ f"choose a distinct name for {cls.__module__}.{cls.__qualname__}."
42
+ )
43
+ _REGISTRY[cls.__name__] = cls
44
+
45
+ def get_state(self, interface: "type[Interface]") -> Any | None:
46
+ """Return the last received state for the given interface, or None."""
47
+ return None
48
+
49
+ def get_capabilities(self, interface: "type[Interface]") -> Any | None:
50
+ """Return the capabilities for the given interface, or None."""
51
+ return None
52
+
53
+ async def wait_for_state(self, interface: "type[Interface]", timeout: float = 10.0) -> Any | None:
54
+ """Return state immediately if available, otherwise wait for the first update."""
55
+ return None
56
+
57
+ @classmethod
58
+ def has_own_state(cls) -> bool:
59
+ """True if this interface defines its own state, as opposed to merely inheriting
60
+ one from a component interface it combines (e.g. ICamera inheriting IExposure's
61
+ state). Modules publish state under the interface that actually defines it, so
62
+ composite interfaces would otherwise be (wrongly) treated as publishing state too.
63
+ """
64
+ return "state" in cls.__dict__
65
+
66
+
67
+ def get_registered_interface(name: str) -> "type[Interface] | None":
68
+ """Look up a registered interface class by name, or None if unknown."""
69
+ return _REGISTRY.get(name)
70
+
71
+
72
+ def registered_interfaces() -> "dict[str, type[Interface]]":
73
+ """All currently-registered interface classes, keyed by name."""
74
+ return dict(_REGISTRY)
75
+
76
+
77
+ __all__ = ["Interface", "get_registered_interface", "registered_interfaces"]
@@ -161,26 +161,25 @@ class FitsHeaderMixin:
161
161
  # basic stuff
162
162
  hdr["EQUINOX"] = (2000.0, "Equinox of celestial coordinate system")
163
163
 
164
- # do we have a location?
165
- if module._location is not None:
166
- loc = module._location
164
+ # do we have an observer (and thus a location)?
165
+ if module._observer is not None:
166
+ loc = module._observer.location
167
167
  # add location of telescope
168
168
  hdr["LONGITUD"] = (float(loc.lon.degree), "Longitude of the telescope [deg E]")
169
169
  hdr["LATITUDE"] = (float(loc.lat.degree), "Latitude of the telescope [deg N]")
170
170
  hdr["HEIGHT"] = (float(loc.height.value), "Altitude of the telescope [m]")
171
171
 
172
172
  # add local sidereal time
173
- if module._observer is not None:
174
- lst = module._observer.local_sidereal_time(date_obs)
175
- lst_hours = float(lst.hour)
176
- h = int(lst_hours)
177
- m = int((lst_hours - h) * 60)
178
- s = (lst_hours - h - m / 60) * 3600
179
- hdr["LST"] = (f"{h:02d}:{m:02d}:{s:05.2f}", "Local sidereal time")
173
+ lst = module._observer.local_sidereal_time(date_obs)
174
+ lst_hours = float(lst.hour)
175
+ h = int(lst_hours)
176
+ m = int((lst_hours - h) * 60)
177
+ s = (lst_hours - h - m / 60) * 3600
178
+ hdr["LST"] = (f"{h:02d}:{m:02d}:{s:05.2f}", "Local sidereal time")
180
179
 
181
180
  # date of night this observation is in
182
- if self._fitsheadermixin_night_obs:
183
- hdr["DAY-OBS"] = (date_obs.night_obs(module._observer).strftime("%Y-%m-%d"), "Night of observation") # type: ignore[arg-type]
181
+ if self._fitsheadermixin_night_obs and module._observer is not None:
182
+ hdr["DAY-OBS"] = (date_obs.night_obs(module._observer).strftime("%Y-%m-%d"), "Night of observation")
184
183
  else:
185
184
  hdr["DAY-OBS"] = (date_obs.strftime("%Y-%m-%d"), "Day of observation")
186
185
 
@@ -195,6 +194,11 @@ class FitsHeaderMixin:
195
194
  # get header
196
195
  hdr = image.header
197
196
 
197
+ # need DAY-OBS, which is only set if DATE-OBS was found earlier
198
+ if "DAY-OBS" not in hdr:
199
+ log.warning("No DAY-OBS found in FITS header, cannot add FRAMENUM.")
200
+ return
201
+
198
202
  # get night from header
199
203
  night = hdr["DAY-OBS"]
200
204
 
@@ -121,7 +121,6 @@ class BaseVideo(Module, ImageFitsHeaderMixin, IVideo, IImageType, metaclass=ABCM
121
121
  self._is_listening = False
122
122
  self._port = http_port
123
123
  self._interval = interval
124
- self._new_image_event = asyncio.Event()
125
124
  self._video_path = video_path
126
125
  self._frame_num = 0
127
126
  self._live_view = live_view
@@ -377,10 +376,6 @@ class BaseVideo(Module, ImageFitsHeaderMixin, IVideo, IImageType, metaclass=ABCM
377
376
  self._last_image = LastImage(data=data, image=image, jpeg=jpeg, filename=filename)
378
377
  self._frame_num += 1
379
378
 
380
- # signal it
381
- self._new_image_event.set()
382
- self._new_image_event = asyncio.Event()
383
-
384
379
  # prepare next image
385
380
  if len(self._image_requests) > 0:
386
381
  # broadcast?
@@ -395,9 +390,6 @@ class BaseVideo(Module, ImageFitsHeaderMixin, IVideo, IImageType, metaclass=ABCM
395
390
  broadcast=broadcast,
396
391
  )
397
392
 
398
- # reset
399
- self._image_request = None
400
-
401
393
  async def _create_image(self, data: NDArray[Any], next_image: NextImage) -> tuple[Image, str]:
402
394
  """Create an Image object from numpy array.
403
395
 
@@ -436,6 +428,7 @@ class BaseVideo(Module, ImageFitsHeaderMixin, IVideo, IImageType, metaclass=ABCM
436
428
  filename = self.format_filename(image)
437
429
  if filename is None:
438
430
  filename = "image.fits"
431
+ image.header["FNAME"] = filename
439
432
 
440
433
  # store it and return filename
441
434
  log.info("Writing image %s to cache...", filename)
@@ -475,7 +468,8 @@ class BaseVideo(Module, ImageFitsHeaderMixin, IVideo, IImageType, metaclass=ABCM
475
468
  await asyncio.sleep(0.01)
476
469
 
477
470
  # remove from list
478
- self._image_requests.remove(image_request)
471
+ async with self._image_request_lock:
472
+ self._image_requests.remove(image_request)
479
473
 
480
474
  # no image?
481
475
  if image_request.image is None or image_request.filename is None: