pyobs-core 2.0.0.dev66__tar.gz → 2.0.0.dev68__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.dev66 → pyobs_core-2.0.0.dev68}/PKG-INFO +1 -1
- pyobs_core-2.0.0.dev68/pyobs/robotic/scheduler/_executor.py +28 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +1 -1
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +3 -4
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +2 -3
- pyobs_core-2.0.0.dev68/pyobs/robotic/scheduler/dataprovider.py +78 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/observationarchiveevolution.py +32 -1
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/ondemandscheduler.py +12 -3
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/archive/local_archive.py +7 -1
- pyobs_core-2.0.0.dev68/pyobs/utils/pipeline/__init__.py +4 -0
- pyobs_core-2.0.0.dev66/pyobs/utils/pipeline/night.py → pyobs_core-2.0.0.dev68/pyobs/utils/pipeline/reduction.py +37 -16
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyproject.toml +1 -1
- pyobs_core-2.0.0.dev66/pyobs/robotic/scheduler/dataprovider.py +0 -49
- pyobs_core-2.0.0.dev66/pyobs/utils/pipeline/__init__.py +0 -4
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xmppcomm.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IDataSequence.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/basecamera.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/basespectrograph.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/camera/pipelinecamera.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/robotic/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/telescope/basetelescope.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/task.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/vfs/vfs.py +0 -0
|
@@ -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"]
|
|
@@ -9,6 +9,8 @@ from astroplan import Observer
|
|
|
9
9
|
from ...utils.time import Time
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Iterable
|
|
13
|
+
|
|
12
14
|
from pyobs.robotic import Observation, Task
|
|
13
15
|
from pyobs.robotic.observation import ObservationList
|
|
14
16
|
from pyobs.robotic.storage.observationarchive import ObservationArchive
|
|
@@ -20,6 +22,23 @@ class ObservationArchiveEvolution:
|
|
|
20
22
|
self._obs_for_task: dict[Any, ObservationList] = {}
|
|
21
23
|
self._obs_for_night: dict[datetime.date, ObservationList] = {}
|
|
22
24
|
self._observer = observer
|
|
25
|
+
self._current_night: datetime.date | None = None
|
|
26
|
+
self._frozen = False
|
|
27
|
+
|
|
28
|
+
async def prefetch(self, tasks: Iterable[Task], start: Time, night: datetime.date) -> None:
|
|
29
|
+
"""Populates the task cache and the one real night (anchored to `start`) up front. Call
|
|
30
|
+
once per schedule() run before any evaluation, then freeze(). Runs on the caller's
|
|
31
|
+
event loop (real I/O)."""
|
|
32
|
+
self._current_night = night
|
|
33
|
+
for task in tasks:
|
|
34
|
+
await self.observations_for_task(task)
|
|
35
|
+
await self.observations_for_night(night)
|
|
36
|
+
|
|
37
|
+
def freeze(self) -> None:
|
|
38
|
+
"""Freezes observation cache. After this: a task-id miss raises RuntimeError; a night
|
|
39
|
+
miss seeds an empty list (future nights are provably empty of COMPLETED observations,
|
|
40
|
+
since `start` is pinned at least `_safety_time` ahead of real wall-clock time)."""
|
|
41
|
+
self._frozen = True
|
|
23
42
|
|
|
24
43
|
async def evolve(self, scheduled_task: Observation, night: datetime.date) -> None:
|
|
25
44
|
from pyobs.robotic.observation import Observation, ObservationState
|
|
@@ -50,6 +69,11 @@ class ObservationArchiveEvolution:
|
|
|
50
69
|
from pyobs.robotic.observation import ObservationList, ObservationState
|
|
51
70
|
|
|
52
71
|
if task.id not in self._obs_for_task:
|
|
72
|
+
if self._frozen:
|
|
73
|
+
raise RuntimeError(
|
|
74
|
+
f"Task {task.id} not in observation cache after freeze(). "
|
|
75
|
+
f"This is a bug -- all task IDs must be prefetched before freeze().",
|
|
76
|
+
)
|
|
53
77
|
if self._obs_archive is not None:
|
|
54
78
|
self._obs_for_task[task.id] = await self._obs_archive.get_observations(
|
|
55
79
|
task=task, state=ObservationState.COMPLETED
|
|
@@ -70,7 +94,14 @@ class ObservationArchiveEvolution:
|
|
|
70
94
|
from pyobs.robotic.observation import ObservationList, ObservationState
|
|
71
95
|
|
|
72
96
|
if date not in self._obs_for_night:
|
|
73
|
-
if self.
|
|
97
|
+
if self._frozen:
|
|
98
|
+
# `start` is pinned at least `_safety_time` ahead of real wall-clock time, so any
|
|
99
|
+
# night after the prefetched one cannot possibly have COMPLETED observations yet.
|
|
100
|
+
assert (
|
|
101
|
+
self._current_night is not None and date > self._current_night
|
|
102
|
+
), f"Night {date} not prefetched and not strictly after current night {self._current_night}."
|
|
103
|
+
self._obs_for_night[date] = ObservationList()
|
|
104
|
+
elif self._obs_archive is not None:
|
|
74
105
|
start = Time(datetime.datetime.combine(date, datetime.time(0, 0, 0)))
|
|
75
106
|
end = Time(datetime.datetime.combine(date, datetime.time(23, 59, 59)))
|
|
76
107
|
self._obs_for_night[date] = await self._obs_archive.get_observations(
|
{pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/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
|
|
@@ -67,6 +68,12 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
67
68
|
data = DataProvider(self._observer, archive)
|
|
68
69
|
projects_dict = {project.code: project for project in projects}
|
|
69
70
|
|
|
71
|
+
# prefetch historical observations on the main loop (the only place aiohttp session works),
|
|
72
|
+
# then freeze to prevent any lazy archive fetches from the worker thread
|
|
73
|
+
night = data.night(start)
|
|
74
|
+
await data.archive.prefetch(tasks, start, night)
|
|
75
|
+
data.archive.freeze()
|
|
76
|
+
|
|
70
77
|
# schedule from start to end
|
|
71
78
|
async for task in self.schedule_in_interval(tasks, projects_dict, start, end, data):
|
|
72
79
|
# evolve archive -- night is keyed by the task's own scheduled time, not "now", since
|
|
@@ -252,7 +259,7 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
252
259
|
) -> tuple[Task | None, float]:
|
|
253
260
|
|
|
254
261
|
# evaluate all merit functions at given time
|
|
255
|
-
merits = await self.evaluate_constraints_and_merits
|
|
262
|
+
merits = await run_cpu_bound(self.evaluate_constraints_and_merits, tasks, projects, start, end, data)
|
|
256
263
|
|
|
257
264
|
# find max one
|
|
258
265
|
idx = np.argmax(merits)
|
|
@@ -276,7 +283,7 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
276
283
|
other_tasks = [t for t in tasks if t is not task]
|
|
277
284
|
t = start + TimeDelta(step * u.second)
|
|
278
285
|
while t < start + TimeDelta(task.estimate_duration(time=start) * u.second):
|
|
279
|
-
merits = await self.evaluate_constraints_and_merits
|
|
286
|
+
merits = await run_cpu_bound(self.evaluate_constraints_and_merits, other_tasks, projects, t, end, data)
|
|
280
287
|
for i, m in enumerate(merits):
|
|
281
288
|
if m > merit:
|
|
282
289
|
return other_tasks[i], t, m
|
|
@@ -297,7 +304,9 @@ class OnDemandScheduler(TaskScheduler):
|
|
|
297
304
|
better_start: Time = start + TimeDelta(task.estimate_duration(time=start) * u.second)
|
|
298
305
|
|
|
299
306
|
# evaluate merit of better_task at new start time
|
|
300
|
-
merit = (
|
|
307
|
+
merit = (
|
|
308
|
+
await run_cpu_bound(self.evaluate_constraints_and_merits, [better_task], projects, better_start, end, data)
|
|
309
|
+
)[0]
|
|
301
310
|
|
|
302
311
|
# if it got better, return it, otherwise return Nones
|
|
303
312
|
if merit >= better_merit:
|
{pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/robotic/utils/archive/local_archive.py
RENAMED
|
@@ -166,7 +166,13 @@ class LocalArchive(Archive):
|
|
|
166
166
|
return headers
|
|
167
167
|
|
|
168
168
|
async def upload_frames(self, images: list[Image]) -> None:
|
|
169
|
-
|
|
169
|
+
self._root_path.mkdir(parents=True, exist_ok=True)
|
|
170
|
+
for image in images:
|
|
171
|
+
filename = image.header.get("FNAME")
|
|
172
|
+
if not filename:
|
|
173
|
+
raise ValueError("Image has no FNAME header set, cannot determine output filename.")
|
|
174
|
+
image.writeto(str(self._root_path / filename), overwrite=True)
|
|
175
|
+
self._update_root() # refresh the in-memory index so newly-written frames are queryable
|
|
170
176
|
|
|
171
177
|
|
|
172
178
|
__all__ = ["LocalArchive"]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import os
|
|
4
5
|
import os.path
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
@@ -19,28 +20,27 @@ log = logging.getLogger(__name__)
|
|
|
19
20
|
FILENAME = "{SITEID}{TELID}-{INSTRUME}-{DAY-OBS|date:}-{IMAGETYP}-{XBINNING}x{YBINNING}{FILTER|filter}.fits"
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
class
|
|
23
|
+
class Reduction:
|
|
23
24
|
def __init__(
|
|
24
25
|
self,
|
|
25
26
|
archive: dict[str, Any] | Archive,
|
|
26
27
|
pipeline: dict[str, Any] | Pipeline,
|
|
27
|
-
worker_procs: int = 4,
|
|
28
28
|
filenames_calib: str = FILENAME,
|
|
29
29
|
min_flats: int = 10,
|
|
30
|
-
|
|
30
|
+
output: str | dict[str, Any] | Archive | None = None,
|
|
31
31
|
create_calibs: bool = True,
|
|
32
32
|
calib_science: bool = True,
|
|
33
|
-
**kwargs: Any,
|
|
34
33
|
):
|
|
35
|
-
"""Creates a
|
|
34
|
+
"""Creates a Reduction object for reducing a given observation period.
|
|
36
35
|
|
|
37
36
|
Args:
|
|
38
|
-
archive: Archive to fetch
|
|
37
|
+
archive: Archive to fetch raw and calibration frames from. Also the output
|
|
38
|
+
destination, unless output is set.
|
|
39
39
|
pipeline: Science pipeline.
|
|
40
|
-
worker_procs: Number of worker processes.
|
|
41
40
|
filenames_calib: Filename pattern for master calibration files.
|
|
42
41
|
min_flats: Minimum number of raw frames to create flat field.
|
|
43
|
-
|
|
42
|
+
output: Where to write results. A string is a local directory path; a dict or
|
|
43
|
+
Archive is an output archive. If not set, results are written back to archive.
|
|
44
44
|
create_calibs: If False, no calibration files are created for night.
|
|
45
45
|
calib_science: If False, no science frames are calibrated.
|
|
46
46
|
"""
|
|
@@ -50,12 +50,18 @@ class Night:
|
|
|
50
50
|
self._pipeline = get_object(pipeline, Pipeline, archive=archive)
|
|
51
51
|
|
|
52
52
|
# stuff
|
|
53
|
-
self._worker_processes = worker_procs
|
|
54
53
|
self._min_flats = min_flats
|
|
55
|
-
self._store_local =
|
|
54
|
+
self._store_local: str | None = output if isinstance(output, str) else None
|
|
55
|
+
self._output_archive = (
|
|
56
|
+
self._archive if output is None or isinstance(output, str) else get_object(output, Archive)
|
|
57
|
+
)
|
|
56
58
|
self._create_calibs = create_calibs
|
|
57
59
|
self._calib_science = calib_science
|
|
58
60
|
|
|
61
|
+
# make sure the local output directory exists
|
|
62
|
+
if self._store_local:
|
|
63
|
+
os.makedirs(self._store_local, exist_ok=True)
|
|
64
|
+
|
|
59
65
|
# cache for master calibration frames
|
|
60
66
|
self._master_frames: dict[tuple[ImageType, str, str, str | None], Image] = {}
|
|
61
67
|
|
|
@@ -128,6 +134,7 @@ class Night:
|
|
|
128
134
|
images = await self._archive.download_frames(infos)
|
|
129
135
|
if len(images) < 3:
|
|
130
136
|
log.warning("Too few (%d) frames found, skipping...", len(infos))
|
|
137
|
+
return None
|
|
131
138
|
|
|
132
139
|
# create master
|
|
133
140
|
calib: Image | None = None
|
|
@@ -191,7 +198,7 @@ class Night:
|
|
|
191
198
|
calib.writeto(path, overwrite=True)
|
|
192
199
|
else:
|
|
193
200
|
log.info("Uploading master calibration frame as %s...", calib.header["FNAME"])
|
|
194
|
-
await self.
|
|
201
|
+
await self._output_archive.upload_frames([calib])
|
|
195
202
|
|
|
196
203
|
# finished
|
|
197
204
|
return calib
|
|
@@ -230,7 +237,7 @@ class Night:
|
|
|
230
237
|
calibrated.writeto(path, overwrite=True)
|
|
231
238
|
else:
|
|
232
239
|
log.info("(%d/%d) Uploading calibrated images as %s...", i, total, calibrated.header["FNAME"])
|
|
233
|
-
await self.
|
|
240
|
+
await self._output_archive.upload_frames([calibrated])
|
|
234
241
|
|
|
235
242
|
except Exception:
|
|
236
243
|
log.exception("(%d/%d) Error processing image %s.", i, total, info.filename)
|
|
@@ -256,18 +263,32 @@ class Night:
|
|
|
256
263
|
for binning in options["binnings"]:
|
|
257
264
|
# create bias and dark
|
|
258
265
|
if self._create_calibs:
|
|
259
|
-
|
|
260
|
-
|
|
266
|
+
try:
|
|
267
|
+
await self._create_master_calib(night, instrument, ImageType.BIAS, binning)
|
|
268
|
+
except Exception:
|
|
269
|
+
log.exception("Error creating master bias for instrument %s, binning %s.", instrument, binning)
|
|
270
|
+
try:
|
|
271
|
+
await self._create_master_calib(night, instrument, ImageType.DARK, binning)
|
|
272
|
+
except Exception:
|
|
273
|
+
log.exception("Error creating master dark for instrument %s, binning %s.", instrument, binning)
|
|
261
274
|
|
|
262
275
|
# loop filters
|
|
263
276
|
for filter_name in options["filters"]:
|
|
264
277
|
# create flat
|
|
265
278
|
if self._create_calibs:
|
|
266
|
-
|
|
279
|
+
try:
|
|
280
|
+
await self._create_master_calib(night, instrument, ImageType.SKYFLAT, binning, filter_name)
|
|
281
|
+
except Exception:
|
|
282
|
+
log.exception(
|
|
283
|
+
"Error creating master flat for instrument %s, binning %s, filter %s.",
|
|
284
|
+
instrument,
|
|
285
|
+
binning,
|
|
286
|
+
filter_name,
|
|
287
|
+
)
|
|
267
288
|
|
|
268
289
|
# calibrate science data
|
|
269
290
|
if self._calib_science:
|
|
270
291
|
await self._calib_data(night, instrument, binning, filter_name)
|
|
271
292
|
|
|
272
293
|
|
|
273
|
-
__all__ = ["
|
|
294
|
+
__all__ = ["Reduction"]
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyobs_core-2.0.0.dev66 → pyobs_core-2.0.0.dev68}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py
RENAMED
|
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
|
|
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
|