pyobs-core 2.0.0.dev51__tar.gz → 2.0.0.dev53__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.
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/PKG-INFO +1 -1
- pyobs_core-2.0.0.dev53/pyobs/images/processor.py +63 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +2 -1
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/dotnet.py +34 -26
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/pipeline.py +16 -2
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/focus/focusseries.py +3 -2
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/acquisition.py +3 -2
- pyobs_core-2.0.0.dev53/pyobs/robotic/scheduler/_executor.py +28 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +1 -1
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +3 -4
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +2 -3
- pyobs_core-2.0.0.dev53/pyobs/robotic/scheduler/dataprovider.py +78 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/ondemandscheduler.py +6 -3
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/vfs.py +15 -6
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyproject.toml +1 -1
- pyobs_core-2.0.0.dev51/pyobs/images/processor.py +0 -28
- pyobs_core-2.0.0.dev51/pyobs/robotic/scheduler/dataprovider.py +0 -49
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/comm/xmpp/xmppcomm.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IDataSequence.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/basecamera.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/basespectrograph.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/robotic/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/telescope/basetelescope.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/task.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/pipeline/night.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/vfs/tempfile.py +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from abc import ABCMeta, abstractmethod
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from pyobs.images import Image
|
|
5
|
+
from pyobs.object import Object
|
|
6
|
+
from pyobs.utils.exceptions import ImageError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ImageProcessor(Object, metaclass=ABCMeta):
|
|
10
|
+
VALID_ERROR_MODES = frozenset(("raise", "error", "info", "ignore"))
|
|
11
|
+
|
|
12
|
+
def __init__(self, on_error: str = "raise", **kwargs: Any):
|
|
13
|
+
"""Init new image processor.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
on_error: How the pipeline should handle an ImageError raised by this step. One of:
|
|
17
|
+
- "raise" (default): re-raise the exception, aborting the pipeline.
|
|
18
|
+
- "error": call handle_error(), pass its return value downstream.
|
|
19
|
+
- "info": log at INFO level, pass the pre-step image downstream unmodified.
|
|
20
|
+
- "ignore": silently pass the pre-step image downstream unmodified.
|
|
21
|
+
"""
|
|
22
|
+
Object.__init__(self, **kwargs)
|
|
23
|
+
|
|
24
|
+
self._on_error = on_error
|
|
25
|
+
if self._on_error not in self.VALID_ERROR_MODES:
|
|
26
|
+
raise ValueError(f"on_error must be one of {sorted(self.VALID_ERROR_MODES)}, got {self._on_error!r}.")
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def on_error(self) -> str:
|
|
30
|
+
"""The error handling mode for this step."""
|
|
31
|
+
return self._on_error
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
async def __call__(self, image: Image) -> Image:
|
|
35
|
+
"""Processes an image.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
image: Image to process.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Processed image.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def handle_error(self, image: Image, error: ImageError) -> Image:
|
|
45
|
+
"""Handle an ImageError raised by this step, when on_error == "error".
|
|
46
|
+
|
|
47
|
+
Override this to customize error handling (e.g. tag the image with a FITS header).
|
|
48
|
+
The default implementation re-raises the error.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
image: The image that caused the error.
|
|
52
|
+
error: The ImageError that was raised.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
The image to pass to the next pipeline step.
|
|
56
|
+
"""
|
|
57
|
+
raise error
|
|
58
|
+
|
|
59
|
+
async def reset(self) -> None:
|
|
60
|
+
"""Resets state of image processor"""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
__all__ = ["ImageProcessor"]
|
|
@@ -51,7 +51,8 @@ class _ResponseImageWriter:
|
|
|
51
51
|
astrometry.net gives a CD matrix, so we have to delete the PC matrix and the CDELT* parameters
|
|
52
52
|
"""
|
|
53
53
|
for keyword in ["PC1_1", "PC1_2", "PC2_1", "PC2_2", "CDELT1", "CDELT2"]:
|
|
54
|
-
|
|
54
|
+
if keyword in self._image.header:
|
|
55
|
+
del self._image.header[keyword]
|
|
55
56
|
|
|
56
57
|
def _generate_image_wcs(self) -> None:
|
|
57
58
|
# astrometry.net's CD matrix is sometimes under-constrained, which astropy silently repairs
|
{pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/images/processors/astrometry/dotnet.py
RENAMED
|
@@ -31,11 +31,15 @@ class AstrometryDotNet(Astrometry):
|
|
|
31
31
|
(commonly degrees for astrometry.net). Default: ``3.0``.
|
|
32
32
|
:param int timeout: Timeout in seconds for the network call to the astrometry
|
|
33
33
|
web service. Default: ``10``.
|
|
34
|
-
:param bool exceptions:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
:param bool exceptions: Deprecated, use ``on_error`` instead. ``exceptions=False`` is
|
|
35
|
+
equivalent to ``on_error="error"``; ``exceptions=True`` (the
|
|
36
|
+
default) is equivalent to ``on_error="raise"``.
|
|
37
|
+
:param str on_error: How the pipeline should handle a failed solve: ``"raise"`` (default,
|
|
38
|
+
abort the pipeline), ``"error"`` (mark ``WCSERR=1`` in the header, log
|
|
39
|
+
a warning, and pass the image through -- see ``handle_error``),
|
|
40
|
+
``"info"``, or ``"ignore"``. Only takes effect when this processor
|
|
41
|
+
runs as a step in a ``PipelineMixin`` pipeline; a direct call always
|
|
42
|
+
raises on failure.
|
|
39
43
|
:param kwargs: Additional keyword arguments forwarded to
|
|
40
44
|
:class:`pyobs.images.processors.astrometry.Astrometry`.
|
|
41
45
|
|
|
@@ -48,11 +52,9 @@ class AstrometryDotNet(Astrometry):
|
|
|
48
52
|
- On success, receives solver output and writes the resulting WCS into a copy of
|
|
49
53
|
the input image using :class:`pyobs.images.processors.astrometry._ResponseImageWriter`.
|
|
50
54
|
- Logs the outcome, including WCS information, and returns the result image.
|
|
51
|
-
- On failure:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- If ``exceptions=False``, sets ``WCSERR=1`` in the FITS header, logs a warning, and returns the original
|
|
55
|
-
image unchanged.
|
|
55
|
+
- On failure, raises the underlying :class:`pyobs.images.exceptions.ImageError`. When run as
|
|
56
|
+
a pipeline step with ``on_error="error"``, the pipeline calls ``handle_error``, which sets
|
|
57
|
+
``WCSERR=1`` in the FITS header, logs a warning, and returns the original image unchanged.
|
|
56
58
|
|
|
57
59
|
Input/Output
|
|
58
60
|
------------
|
|
@@ -69,20 +71,20 @@ class AstrometryDotNet(Astrometry):
|
|
|
69
71
|
class: pyobs.images.processors.astrometry.AstrometryDotNet
|
|
70
72
|
url: "http://localhost:8080/api"
|
|
71
73
|
|
|
72
|
-
Handle failures without
|
|
74
|
+
Handle failures without aborting the pipeline:
|
|
73
75
|
|
|
74
76
|
.. code-block:: yaml
|
|
75
77
|
|
|
76
78
|
class: pyobs.images.processors.astrometry.AstrometryDotNet
|
|
77
79
|
url: "http://localhost:8080/api"
|
|
78
|
-
|
|
80
|
+
on_error: error
|
|
79
81
|
|
|
80
82
|
Notes
|
|
81
83
|
-----
|
|
82
84
|
- The ``_DotNetRequestBuilder`` determines how sources are extracted and how the
|
|
83
85
|
request is formed (including any unit conventions for ``radius``). Consult its
|
|
84
86
|
documentation for details.
|
|
85
|
-
- ``WCSERR`` is used as a failure marker in the FITS header when ``
|
|
87
|
+
- ``WCSERR`` is used as a failure marker in the FITS header when ``handle_error`` runs.
|
|
86
88
|
"""
|
|
87
89
|
|
|
88
90
|
__module__ = "pyobs.images.processors.astrometry"
|
|
@@ -93,7 +95,8 @@ class AstrometryDotNet(Astrometry):
|
|
|
93
95
|
source_count: int = 50,
|
|
94
96
|
radius: float = 3.0,
|
|
95
97
|
timeout: int = 10,
|
|
96
|
-
exceptions: bool =
|
|
98
|
+
exceptions: bool | None = None,
|
|
99
|
+
on_error: str = "raise",
|
|
97
100
|
**kwargs: Any,
|
|
98
101
|
):
|
|
99
102
|
"""Init new astronomy.net processor.
|
|
@@ -103,17 +106,28 @@ class AstrometryDotNet(Astrometry):
|
|
|
103
106
|
source_count: Number of sources to send.
|
|
104
107
|
radius: Radius to search in.
|
|
105
108
|
timeout: Timeout in seconds for call to astrometry web service.
|
|
106
|
-
exceptions: Whether to raise Exceptions.
|
|
109
|
+
exceptions: Deprecated, use on_error instead. Whether to raise Exceptions.
|
|
110
|
+
on_error: How to handle a failed solve. One of "raise", "error", "info", "ignore".
|
|
111
|
+
On "error", handle_error() marks the image with WCSERR=1 and logs a warning.
|
|
107
112
|
"""
|
|
108
|
-
Astrometry.__init__(self, **kwargs)
|
|
113
|
+
Astrometry.__init__(self, on_error=on_error, **kwargs)
|
|
109
114
|
|
|
110
115
|
self.url = url
|
|
111
116
|
|
|
112
117
|
self.timeout = timeout
|
|
113
|
-
|
|
118
|
+
|
|
119
|
+
# backwards compat: if 'exceptions' is set but 'on_error' is left at its default,
|
|
120
|
+
# derive on_error from it.
|
|
121
|
+
if exceptions is not None and on_error == "raise":
|
|
122
|
+
self._on_error = "raise" if exceptions else "error"
|
|
114
123
|
|
|
115
124
|
self._request_builder = _DotNetRequestBuilder(source_count, radius)
|
|
116
125
|
|
|
126
|
+
@property
|
|
127
|
+
def exceptions(self) -> bool:
|
|
128
|
+
"""Deprecated, use on_error instead."""
|
|
129
|
+
return self.on_error != "error"
|
|
130
|
+
|
|
117
131
|
async def _process(self, image: Image) -> Image:
|
|
118
132
|
# build the request
|
|
119
133
|
request = self._request_builder(image)
|
|
@@ -132,10 +146,7 @@ class AstrometryDotNet(Astrometry):
|
|
|
132
146
|
|
|
133
147
|
return result_image
|
|
134
148
|
|
|
135
|
-
def
|
|
136
|
-
if self.exceptions:
|
|
137
|
-
raise error
|
|
138
|
-
|
|
149
|
+
def handle_error(self, image: Image, error: exc.ImageError) -> Image:
|
|
139
150
|
image.header["WCSERR"] = 1
|
|
140
151
|
|
|
141
152
|
log.warning(error.message)
|
|
@@ -145,16 +156,13 @@ class AstrometryDotNet(Astrometry):
|
|
|
145
156
|
async def __call__(self, image: Image) -> Image:
|
|
146
157
|
"""Find astrometric solution on given image.
|
|
147
158
|
|
|
148
|
-
Writes WCSERR=1 into FITS header on failure.
|
|
159
|
+
Writes WCSERR=1 into FITS header on failure (see handle_error).
|
|
149
160
|
|
|
150
161
|
Args:
|
|
151
162
|
image: Image to analyse.
|
|
152
163
|
"""
|
|
153
164
|
|
|
154
|
-
|
|
155
|
-
return await self._process(image)
|
|
156
|
-
except exc.ImageError as e:
|
|
157
|
-
return self._handle_error(image, e)
|
|
165
|
+
return await self._process(image)
|
|
158
166
|
|
|
159
167
|
|
|
160
168
|
__all__ = ["AstrometryDotNet"]
|
|
@@ -5,6 +5,7 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
from pyobs.images import Image, ImageProcessor
|
|
7
7
|
from pyobs.object import Object
|
|
8
|
+
from pyobs.utils.exceptions import ImageError
|
|
8
9
|
|
|
9
10
|
log = logging.getLogger(__name__)
|
|
10
11
|
|
|
@@ -37,6 +38,10 @@ class PipelineMixin:
|
|
|
37
38
|
async def run_pipeline(self, image: Image) -> Image:
|
|
38
39
|
"""Run the pipeline on the given image.
|
|
39
40
|
|
|
41
|
+
Each step is run, and an ImageError it raises is handled according to the step's
|
|
42
|
+
on_error setting (default "raise"): re-raised, dispatched to the step's handle_error(),
|
|
43
|
+
logged, or ignored. Non-ImageError exceptions always propagate.
|
|
44
|
+
|
|
40
45
|
Args:
|
|
41
46
|
image: Image to run pipeline on.
|
|
42
47
|
|
|
@@ -44,9 +49,18 @@ class PipelineMixin:
|
|
|
44
49
|
Image after pipeline run.
|
|
45
50
|
"""
|
|
46
51
|
|
|
47
|
-
# loop steps, just let any exception pass
|
|
48
52
|
for step in self.__pipeline_steps:
|
|
49
|
-
|
|
53
|
+
try:
|
|
54
|
+
image = await step(image)
|
|
55
|
+
except ImageError as e:
|
|
56
|
+
if step.on_error == "raise":
|
|
57
|
+
raise
|
|
58
|
+
elif step.on_error == "error":
|
|
59
|
+
image = step.handle_error(image, e)
|
|
60
|
+
elif step.on_error == "info":
|
|
61
|
+
log.info("Step %s: %s", type(step).__name__, e)
|
|
62
|
+
elif step.on_error == "ignore":
|
|
63
|
+
pass
|
|
50
64
|
|
|
51
65
|
# finished
|
|
52
66
|
return image
|
|
@@ -135,8 +135,9 @@ class AutoFocusSeries(Module, CameraSettingsMixin, IAutoFocus):
|
|
|
135
135
|
# do camera settings
|
|
136
136
|
async with self.proxy(self._camera, ICamera) as camera:
|
|
137
137
|
await self._do_camera_settings(camera)
|
|
138
|
-
async with self.
|
|
139
|
-
|
|
138
|
+
async with self.safe_proxy(self._camera, IImageType) as proxy:
|
|
139
|
+
if proxy:
|
|
140
|
+
await proxy.set_image_type(ImageType.FOCUS)
|
|
140
141
|
|
|
141
142
|
# get filter wheel and current filter
|
|
142
143
|
filter_name = "unknown"
|
|
@@ -134,8 +134,9 @@ class Acquisition(BasePointing, CameraSettingsMixin, IAcquisition):
|
|
|
134
134
|
# do camera settings
|
|
135
135
|
async with self.proxy(self._camera, ICamera) as camera:
|
|
136
136
|
await self._do_camera_settings(camera)
|
|
137
|
-
async with self.
|
|
138
|
-
|
|
137
|
+
async with self.safe_proxy(self._camera, IImageType) as camera:
|
|
138
|
+
if camera:
|
|
139
|
+
await camera.set_image_type(ImageType.ACQUISITION)
|
|
139
140
|
|
|
140
141
|
# try given number of attempts
|
|
141
142
|
for a in range(self._attempts):
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from collections.abc import Callable, Coroutine
|
|
5
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
6
|
+
from typing import Any, TypeVar
|
|
7
|
+
|
|
8
|
+
_T = TypeVar("_T")
|
|
9
|
+
|
|
10
|
+
# single worker: evaluate_constraints_and_merits calls are always awaited sequentially by the
|
|
11
|
+
# caller (never fired concurrently), and DataProvider's functools.cache is not safe under real
|
|
12
|
+
# concurrent access -- one worker keeps that access serialized while still freeing the main loop.
|
|
13
|
+
_executor = ThreadPoolExecutor(max_workers=1, thread_name_prefix="pyobs-scheduler")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def run_cpu_bound(coro_fn: Callable[..., Coroutine[Any, Any, _T]], *args: object) -> _T:
|
|
17
|
+
"""Runs an async callable to completion on a dedicated worker thread, off the caller's loop.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
coro_fn: An async callable whose body does not itself need to run on the caller's
|
|
21
|
+
event loop (no dependency on the caller's other tasks, timers, or comm state).
|
|
22
|
+
args: Positional args for coro_fn.
|
|
23
|
+
"""
|
|
24
|
+
loop = asyncio.get_running_loop()
|
|
25
|
+
return await loop.run_in_executor(_executor, lambda: asyncio.run(coro_fn(*args)))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
__all__ = ["run_cpu_bound"]
|
|
@@ -24,7 +24,7 @@ class MoonIlluminationConstraint(Constraint):
|
|
|
24
24
|
return astroplan.MoonIlluminationConstraint(max=self.max_phase)
|
|
25
25
|
|
|
26
26
|
async def __call__(self, time: Time, task: Task, data: DataProvider) -> bool:
|
|
27
|
-
moon_illumination =
|
|
27
|
+
moon_illumination = data.moon_illumination(time)
|
|
28
28
|
return moon_illumination <= self.max_phase
|
|
29
29
|
|
|
30
30
|
|
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
import astroplan
|
|
6
|
-
import astropy.coordinates
|
|
7
6
|
import astropy.units as u
|
|
8
7
|
import numpy as np
|
|
9
8
|
from astropy.coordinates import SkyCoord
|
|
@@ -32,12 +31,12 @@ class MoonSeparationConstraint(Constraint):
|
|
|
32
31
|
if task.target is None:
|
|
33
32
|
return True
|
|
34
33
|
coord = task.target.coordinates(time)
|
|
35
|
-
moon_separation =
|
|
34
|
+
moon_separation = data.moon(time).separation(coord, origin_mismatch="ignore") # type: ignore[unexpected-keyword]
|
|
36
35
|
return float(moon_separation.degree) >= self.min_distance
|
|
37
36
|
|
|
38
37
|
async def filter_skycoord(self, time: Time, coords: SkyCoord, data: DataProvider) -> np.ndarray:
|
|
39
|
-
moon =
|
|
40
|
-
separations = moon.separation(coords, origin_mismatch="ignore").deg
|
|
38
|
+
moon = data.moon(time)
|
|
39
|
+
separations = moon.separation(coords, origin_mismatch="ignore").deg # type: ignore[unexpected-keyword]
|
|
41
40
|
return np.asarray(separations >= self.min_distance, dtype=np.bool_)
|
|
42
41
|
|
|
43
42
|
|
|
@@ -5,7 +5,6 @@ from typing import TYPE_CHECKING, Literal
|
|
|
5
5
|
|
|
6
6
|
import astroplan
|
|
7
7
|
import astropy.units as u
|
|
8
|
-
from astropy.coordinates import get_sun
|
|
9
8
|
from pydantic import Field
|
|
10
9
|
|
|
11
10
|
from pyobs.utils.time import Time
|
|
@@ -34,12 +33,12 @@ class SolarElevationConstraint(Constraint):
|
|
|
34
33
|
return astroplan.AtNightConstraint(max_solar_altitude=self.max_elevation * u.deg)
|
|
35
34
|
|
|
36
35
|
async def __call__(self, time: Time, task: Task, data: DataProvider) -> bool:
|
|
37
|
-
sun = data.
|
|
36
|
+
sun = data.sun_altaz(time)
|
|
38
37
|
in_range = self.min_elevation <= float(sun.alt.degree) <= self.max_elevation
|
|
39
38
|
if self.direction == "both":
|
|
40
39
|
return in_range
|
|
41
40
|
else:
|
|
42
|
-
sun_coord =
|
|
41
|
+
sun_coord = data.sun(time)
|
|
43
42
|
transit = data.observer.target_meridian_transit_time(time, sun_coord, which="nearest")
|
|
44
43
|
midnight = data.observer.midnight(time, which="nearest")
|
|
45
44
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from functools import cache
|
|
6
|
+
|
|
7
|
+
import astropy.coordinates
|
|
8
|
+
from astroplan import Observer
|
|
9
|
+
from astropy.coordinates import SkyCoord
|
|
10
|
+
|
|
11
|
+
from pyobs.robotic.scheduler.observationarchiveevolution import (
|
|
12
|
+
ObservationArchiveEvolution,
|
|
13
|
+
)
|
|
14
|
+
from pyobs.utils.time import Time
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class TaskSuccess:
|
|
19
|
+
date: Time
|
|
20
|
+
night: Time
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class DataProvider:
|
|
24
|
+
"""Data provider for Merit classes.
|
|
25
|
+
|
|
26
|
+
The ``@cache``d methods below are only safe to call from a single thread at a time -- they're
|
|
27
|
+
used exclusively from within the scheduler's dedicated single-worker executor
|
|
28
|
+
(`pyobs.robotic.scheduler._executor.run_cpu_bound`), never concurrently from the caller's main
|
|
29
|
+
event loop. A new `DataProvider` is created per `schedule()` call, so cache lifetime is bounded
|
|
30
|
+
to one schedule computation and never leaks stale values across runs.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, observer: Observer, archive: ObservationArchiveEvolution | None = None):
|
|
34
|
+
self.observer = observer
|
|
35
|
+
self.archive = archive if archive else ObservationArchiveEvolution(observer)
|
|
36
|
+
|
|
37
|
+
@cache
|
|
38
|
+
def last_sunset(self, time: Time) -> Time:
|
|
39
|
+
"""Returns the time of the last sunset."""
|
|
40
|
+
|
|
41
|
+
# get last sunset
|
|
42
|
+
return Time(self.observer.sun_set_time(time, which="previous"))
|
|
43
|
+
|
|
44
|
+
@cache
|
|
45
|
+
def last_sunrise(self, time: Time) -> Time:
|
|
46
|
+
"""Returns the time of the last sunrise."""
|
|
47
|
+
|
|
48
|
+
# get last sunset
|
|
49
|
+
return Time(self.observer.sun_rise_time(time, which="previous"))
|
|
50
|
+
|
|
51
|
+
@cache
|
|
52
|
+
def night(self, time: Time) -> datetime.date:
|
|
53
|
+
"""Returns the time of the last sunset."""
|
|
54
|
+
sunset = self.last_sunset(time)
|
|
55
|
+
return sunset.to_datetime().date()
|
|
56
|
+
|
|
57
|
+
@cache
|
|
58
|
+
def sun(self, time: Time) -> SkyCoord:
|
|
59
|
+
"""Returns the Sun's coordinates at the given time."""
|
|
60
|
+
return astropy.coordinates.get_sun(time)
|
|
61
|
+
|
|
62
|
+
@cache
|
|
63
|
+
def sun_altaz(self, time: Time) -> SkyCoord:
|
|
64
|
+
"""Returns the Sun's AltAz coordinates at the given time, as seen by the observer."""
|
|
65
|
+
return self.observer.sun_altaz(time)
|
|
66
|
+
|
|
67
|
+
@cache
|
|
68
|
+
def moon(self, time: Time) -> SkyCoord:
|
|
69
|
+
"""Returns the Moon's coordinates at the given time."""
|
|
70
|
+
return astropy.coordinates.get_body("moon", time)
|
|
71
|
+
|
|
72
|
+
@cache
|
|
73
|
+
def moon_illumination(self, time: Time) -> float:
|
|
74
|
+
"""Returns the Moon's illumination fraction at the given time."""
|
|
75
|
+
return float(self.observer.moon_illumination(time))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
__all__ = ["DataProvider"]
|
{pyobs_core-2.0.0.dev51 → pyobs_core-2.0.0.dev53}/pyobs/robotic/scheduler/ondemandscheduler.py
RENAMED
|
@@ -14,6 +14,7 @@ from pyobs.robotic.storage.observationarchive import ObservationArchive
|
|
|
14
14
|
from pyobs.utils.time import Time
|
|
15
15
|
|
|
16
16
|
from . import DataProvider
|
|
17
|
+
from ._executor import run_cpu_bound
|
|
17
18
|
from .constraints import Constraint
|
|
18
19
|
from .observationarchiveevolution import ObservationArchiveEvolution
|
|
19
20
|
from .taskscheduler import TaskScheduler
|
|
@@ -250,7 +251,7 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
250
251
|
) -> tuple[Task | None, float]:
|
|
251
252
|
|
|
252
253
|
# evaluate all merit functions at given time
|
|
253
|
-
merits = await self.evaluate_constraints_and_merits
|
|
254
|
+
merits = await run_cpu_bound(self.evaluate_constraints_and_merits, tasks, projects, start, end, data)
|
|
254
255
|
|
|
255
256
|
# find max one
|
|
256
257
|
idx = np.argmax(merits)
|
|
@@ -274,7 +275,7 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
274
275
|
other_tasks = [t for t in tasks if t is not task]
|
|
275
276
|
t = start + TimeDelta(step * u.second)
|
|
276
277
|
while t < start + TimeDelta(task.estimate_duration(time=start) * u.second):
|
|
277
|
-
merits = await self.evaluate_constraints_and_merits
|
|
278
|
+
merits = await run_cpu_bound(self.evaluate_constraints_and_merits, other_tasks, projects, t, end, data)
|
|
278
279
|
for i, m in enumerate(merits):
|
|
279
280
|
if m > merit:
|
|
280
281
|
return other_tasks[i], t, m
|
|
@@ -295,7 +296,9 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
295
296
|
better_start: Time = start + TimeDelta(task.estimate_duration(time=start) * u.second)
|
|
296
297
|
|
|
297
298
|
# evaluate merit of better_task at new start time
|
|
298
|
-
merit = (
|
|
299
|
+
merit = (
|
|
300
|
+
await run_cpu_bound(self.evaluate_constraints_and_merits, [better_task], projects, better_start, end, data)
|
|
301
|
+
)[0]
|
|
299
302
|
|
|
300
303
|
# if it got better, return it, otherwise return Nones
|
|
301
304
|
if merit >= better_merit:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import asyncio
|
|
3
4
|
import io
|
|
4
5
|
import logging
|
|
5
6
|
from collections.abc import Awaitable, Callable
|
|
@@ -114,11 +115,15 @@ class VirtualFileSystem:
|
|
|
114
115
|
hdulist: hdu list to write.
|
|
115
116
|
"""
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
async with self.open_file(filename, "wb") as f:
|
|
118
|
+
def _serialize() -> bytes:
|
|
119
119
|
with io.BytesIO() as bio:
|
|
120
120
|
hdulist.writeto(bio, *args, **kwargs)
|
|
121
|
-
|
|
121
|
+
return bio.getvalue()
|
|
122
|
+
|
|
123
|
+
# open file
|
|
124
|
+
async with self.open_file(filename, "wb") as f:
|
|
125
|
+
data = await asyncio.to_thread(_serialize)
|
|
126
|
+
await f.write(data)
|
|
122
127
|
|
|
123
128
|
async def read_image(self, filename: str) -> Image:
|
|
124
129
|
"""Convenience function that wraps around open_file() to read an Image.
|
|
@@ -145,11 +150,15 @@ class VirtualFileSystem:
|
|
|
145
150
|
image: Image to write.
|
|
146
151
|
"""
|
|
147
152
|
|
|
148
|
-
|
|
149
|
-
async with self.open_file(filename, "wb") as f:
|
|
153
|
+
def _serialize() -> bytes:
|
|
150
154
|
with io.BytesIO() as bio:
|
|
151
155
|
image.writeto(bio, *args, **kwargs)
|
|
152
|
-
|
|
156
|
+
return bio.getvalue()
|
|
157
|
+
|
|
158
|
+
# open file
|
|
159
|
+
async with self.open_file(filename, "wb") as f:
|
|
160
|
+
data = await asyncio.to_thread(_serialize)
|
|
161
|
+
await f.write(data)
|
|
153
162
|
|
|
154
163
|
async def write_bytes(self, filename: str, data: bytes, *args: Any, **kwargs: Any) -> None:
|
|
155
164
|
"""Convenience function for writing bytes to a file.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
from abc import ABCMeta, abstractmethod
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from pyobs.images import Image
|
|
5
|
-
from pyobs.object import Object
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ImageProcessor(Object, metaclass=ABCMeta):
|
|
9
|
-
def __init__(self, **kwargs: Any):
|
|
10
|
-
"""Init new image processor."""
|
|
11
|
-
Object.__init__(self, **kwargs)
|
|
12
|
-
|
|
13
|
-
@abstractmethod
|
|
14
|
-
async def __call__(self, image: Image) -> Image:
|
|
15
|
-
"""Processes an image.
|
|
16
|
-
|
|
17
|
-
Args:
|
|
18
|
-
image: Image to process.
|
|
19
|
-
|
|
20
|
-
Returns:
|
|
21
|
-
Processed image.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
async def reset(self) -> None:
|
|
25
|
-
"""Resets state of image processor"""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
__all__ = ["ImageProcessor"]
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from functools import cache
|
|
6
|
-
|
|
7
|
-
from astroplan import Observer
|
|
8
|
-
|
|
9
|
-
from pyobs.robotic.scheduler.observationarchiveevolution import (
|
|
10
|
-
ObservationArchiveEvolution,
|
|
11
|
-
)
|
|
12
|
-
from pyobs.utils.time import Time
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass
|
|
16
|
-
class TaskSuccess:
|
|
17
|
-
date: Time
|
|
18
|
-
night: Time
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class DataProvider:
|
|
22
|
-
"""Data provider for Merit classes."""
|
|
23
|
-
|
|
24
|
-
def __init__(self, observer: Observer, archive: ObservationArchiveEvolution | None = None):
|
|
25
|
-
self.observer = observer
|
|
26
|
-
self.archive = archive if archive else ObservationArchiveEvolution(observer)
|
|
27
|
-
|
|
28
|
-
@cache
|
|
29
|
-
def last_sunset(self, time: Time) -> Time:
|
|
30
|
-
"""Returns the time of the last sunset."""
|
|
31
|
-
|
|
32
|
-
# get last sunset
|
|
33
|
-
return Time(self.observer.sun_set_time(time, which="previous"))
|
|
34
|
-
|
|
35
|
-
@cache
|
|
36
|
-
def last_sunrise(self, time: Time) -> Time:
|
|
37
|
-
"""Returns the time of the last sunrise."""
|
|
38
|
-
|
|
39
|
-
# get last sunset
|
|
40
|
-
return Time(self.observer.sun_rise_time(time, which="previous"))
|
|
41
|
-
|
|
42
|
-
@cache
|
|
43
|
-
def night(self, time: Time) -> datetime.date:
|
|
44
|
-
"""Returns the time of the last sunset."""
|
|
45
|
-
sunset = self.last_sunset(time)
|
|
46
|
-
return sunset.to_datetime().date()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
__all__ = ["DataProvider"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|