pyobs-core 2.0.0.dev24__tar.gz → 2.0.0.dev26__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.dev24 → pyobs_core-2.0.0.dev26}/PKG-INFO +1 -1
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/image.py +41 -1
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/calibration/_ccddata_calibrator.py +2 -8
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/circularmask.py +21 -14
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/projected.py +3 -11
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ICamera.py +1 -2
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IDataSequence.py +8 -2
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ISpectrograph.py +1 -2
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/camerasettings.py +5 -1
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/basecamera.py +22 -4
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/basespectrograph.py +1 -1
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/pipelinecamera.py +2 -11
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/robotic/scheduler.py +9 -2
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/telescope/basetelescope.py +12 -2
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/scripts/script.py +7 -1
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/task.py +6 -3
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/task.py +7 -2
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/fits.py +42 -15
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/pipeline/pipeline.py +2 -21
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/time.py +4 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyproject.toml +1 -1
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/comm.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/proxy.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xmppclient.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/comm/xmpp/xmppcomm.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/motionstatus.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/flatfield/flatfield.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/focus/focusmodel.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/autoguiding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/pointing/scienceframeguiding.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/roof/baseroof.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/telescope/_dummytelescopebase.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/telescope/dummysolartelescope.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/dummymode.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/flatfielder.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/pipeline/night.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/vfs/vfs.py +0 -0
|
@@ -13,7 +13,7 @@ from astropy.table import Table
|
|
|
13
13
|
from numpy.typing import NDArray
|
|
14
14
|
|
|
15
15
|
import pyobs.utils.exceptions as exc
|
|
16
|
-
from pyobs.utils.fits import FilenameFormatter
|
|
16
|
+
from pyobs.utils.fits import FilenameFormatter, parse_section_bounds
|
|
17
17
|
|
|
18
18
|
MetaClass = TypeVar("MetaClass")
|
|
19
19
|
|
|
@@ -378,6 +378,46 @@ class Image:
|
|
|
378
378
|
unit="adu",
|
|
379
379
|
)
|
|
380
380
|
|
|
381
|
+
def trim(self) -> Image:
|
|
382
|
+
"""Return a copy of this image cropped to its TRIMSEC header, if present.
|
|
383
|
+
|
|
384
|
+
If no TRIMSEC is set, returns an unmodified copy. CRPIX1/CRPIX2 are shifted to
|
|
385
|
+
account for the new origin if present. TRIMSEC/DATASEC/BIASSEC are removed from
|
|
386
|
+
the result's header, since none remain valid coordinates into the trimmed data.
|
|
387
|
+
|
|
388
|
+
Raises:
|
|
389
|
+
ValueError: If TRIMSEC is malformed, or a catalog is already attached (its
|
|
390
|
+
pixel coordinates would silently go stale against the trimmed frame).
|
|
391
|
+
"""
|
|
392
|
+
|
|
393
|
+
if self._catalog is not None:
|
|
394
|
+
raise ValueError("Cannot trim an image with an attached catalog.")
|
|
395
|
+
|
|
396
|
+
bounds = parse_section_bounds(self._header, "TRIMSEC")
|
|
397
|
+
trimmed = self.copy()
|
|
398
|
+
if bounds is None:
|
|
399
|
+
return trimmed
|
|
400
|
+
|
|
401
|
+
x0, x1, y0, y1 = bounds
|
|
402
|
+
trimmed._data = None if self._data is None else self._data[y0:y1, x0:x1]
|
|
403
|
+
trimmed._mask = None if self._mask is None else self._mask[y0:y1, x0:x1]
|
|
404
|
+
trimmed._uncertainty = None if self._uncertainty is None else self._uncertainty[y0:y1, x0:x1]
|
|
405
|
+
|
|
406
|
+
if trimmed._data is not None:
|
|
407
|
+
trimmed._header["NAXIS1"] = trimmed._data.shape[1]
|
|
408
|
+
trimmed._header["NAXIS2"] = trimmed._data.shape[0]
|
|
409
|
+
|
|
410
|
+
if "CRPIX1" in trimmed._header:
|
|
411
|
+
trimmed._header["CRPIX1"] -= x0
|
|
412
|
+
if "CRPIX2" in trimmed._header:
|
|
413
|
+
trimmed._header["CRPIX2"] -= y0
|
|
414
|
+
|
|
415
|
+
for keyword in ("TRIMSEC", "DATASEC", "BIASSEC"):
|
|
416
|
+
if keyword in trimmed._header:
|
|
417
|
+
del trimmed._header[keyword]
|
|
418
|
+
|
|
419
|
+
return trimmed
|
|
420
|
+
|
|
381
421
|
def format_filename(self, formatter: FilenameFormatter) -> str:
|
|
382
422
|
"""Format filename with given formatter."""
|
|
383
423
|
self._header["FNAME"] = formatter(self._header)
|
|
@@ -4,17 +4,16 @@ import astropy.units as u
|
|
|
4
4
|
from astropy.nddata import CCDData
|
|
5
5
|
|
|
6
6
|
from pyobs.images import Image
|
|
7
|
-
from pyobs.utils.pipeline import Pipeline
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
class _CCDDataCalibrator:
|
|
11
10
|
def __init__(self, image: Image, bias: Image | None = None, dark: Image | None = None, flat: Image | None = None):
|
|
12
|
-
self._image = image
|
|
11
|
+
self._image = image.trim()
|
|
13
12
|
self._bias = self._optional_to_ccddata(bias)
|
|
14
13
|
self._dark = self._optional_to_ccddata(dark)
|
|
15
14
|
self._flat = self._optional_to_ccddata(flat)
|
|
16
15
|
|
|
17
|
-
self._ccd_data =
|
|
16
|
+
self._ccd_data = self._image.to_ccddata()
|
|
18
17
|
|
|
19
18
|
if dark is not None:
|
|
20
19
|
self._dark_exp_time = dark.header["EXPTIME"]
|
|
@@ -26,16 +25,11 @@ class _CCDDataCalibrator:
|
|
|
26
25
|
return image.to_ccddata()
|
|
27
26
|
|
|
28
27
|
def __call__(self) -> Image:
|
|
29
|
-
self._trim_image()
|
|
30
|
-
|
|
31
28
|
calibrated_ccd_data = self._calibrate_image()
|
|
32
29
|
|
|
33
30
|
calibrated = Image.from_ccddata(calibrated_ccd_data)
|
|
34
31
|
return calibrated
|
|
35
32
|
|
|
36
|
-
def _trim_image(self) -> None:
|
|
37
|
-
self._ccd_data = Pipeline.trim_ccddata(self._ccd_data)
|
|
38
|
-
|
|
39
33
|
def _calibrate_image(self) -> CCDData:
|
|
40
34
|
import ccdproc
|
|
41
35
|
|
{pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/misc/circularmask.py
RENAMED
|
@@ -17,8 +17,9 @@ class CircularMask(ImageProcessor):
|
|
|
17
17
|
|
|
18
18
|
This processor reads the circle center from two FITS header keywords
|
|
19
19
|
(e.g., CRPIX1/CRPIX2) and constructs a circular mask in pixel coordinates. Pixels
|
|
20
|
-
outside the circle are
|
|
21
|
-
|
|
20
|
+
outside the circle are flagged in ``image.mask``; pixel data are left untouched. Any
|
|
21
|
+
pre-existing mask on the image is combined (logical OR) with the new one rather than
|
|
22
|
+
being overwritten.
|
|
22
23
|
|
|
23
24
|
:param float radius: Radius of the circular pass region in pixels. Pixels with
|
|
24
25
|
squared distance to the center less than or equal to
|
|
@@ -33,17 +34,19 @@ class CircularMask(ImageProcessor):
|
|
|
33
34
|
--------
|
|
34
35
|
- Reads the circle center from ``image.header[center[0]]`` and
|
|
35
36
|
``image.header[center[1]]``.
|
|
36
|
-
- Builds a boolean
|
|
37
|
-
``
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
- Builds a boolean mask on the 2D pixel grid that is ``True`` outside the circle
|
|
38
|
+
and ``False`` inside it (boundary inclusive), and assigns it to a copy of the
|
|
39
|
+
image's ``mask``. If the image already has a mask, the new mask is combined with
|
|
40
|
+
it via logical OR instead of replacing it.
|
|
41
|
+
- Returns a copy of the image with the updated mask; pixel data, header, and
|
|
40
42
|
catalog are not changed.
|
|
41
43
|
|
|
42
44
|
Input/Output
|
|
43
45
|
------------
|
|
44
46
|
- Input: :class:`pyobs.images.Image` with 2D pixel data and FITS header containing
|
|
45
47
|
the specified center keywords.
|
|
46
|
-
- Output: :class:`pyobs.images.Image` with
|
|
48
|
+
- Output: :class:`pyobs.images.Image` (copied) with pixels outside the circle
|
|
49
|
+
marked in ``mask``; pixel data are unchanged.
|
|
47
50
|
|
|
48
51
|
Configuration (YAML)
|
|
49
52
|
--------------------
|
|
@@ -70,8 +73,6 @@ class CircularMask(ImageProcessor):
|
|
|
70
73
|
ensure consistency to avoid off-by-one shifts.
|
|
71
74
|
- The implementation operates on 2D images. Multi-plane/color images are not
|
|
72
75
|
supported by this processor as written.
|
|
73
|
-
- Masking is performed in place; if you need to preserve the original image data,
|
|
74
|
-
copy the image before applying this processor.
|
|
75
76
|
"""
|
|
76
77
|
|
|
77
78
|
__module__ = "pyobs.images.processors.misc"
|
|
@@ -90,13 +91,13 @@ class CircularMask(ImageProcessor):
|
|
|
90
91
|
self._radius = radius
|
|
91
92
|
|
|
92
93
|
async def __call__(self, image: Image) -> Image:
|
|
93
|
-
"""
|
|
94
|
+
"""Mask everything outside the given radius from the image.
|
|
94
95
|
|
|
95
96
|
Args:
|
|
96
97
|
image: Image to mask.
|
|
97
98
|
|
|
98
99
|
Returns:
|
|
99
|
-
|
|
100
|
+
Image with pixels outside the circle marked in its mask.
|
|
100
101
|
"""
|
|
101
102
|
|
|
102
103
|
center_x, center_y = image.header[self._center[0]], image.header[self._center[1]]
|
|
@@ -105,10 +106,16 @@ class CircularMask(ImageProcessor):
|
|
|
105
106
|
x, y = np.arange(0, nx), np.arange(0, ny)
|
|
106
107
|
x_coordinates, y_coordinates = np.meshgrid(x, y)
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
outside_circle = (x_coordinates - center_x) ** 2 + (y_coordinates - center_y) ** 2 > self._radius**2
|
|
110
|
+
outside_circle = outside_circle.transpose()
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
output_image = image.copy()
|
|
113
|
+
if output_image.safe_mask is not None:
|
|
114
|
+
output_image.mask = np.logical_or(output_image.mask, outside_circle)
|
|
115
|
+
else:
|
|
116
|
+
output_image.mask = outside_circle
|
|
117
|
+
|
|
118
|
+
return output_image
|
|
112
119
|
|
|
113
120
|
|
|
114
121
|
__all__ = ["CircularMask"]
|
{pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/images/processors/offsets/projected.py
RENAMED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
import re
|
|
3
2
|
from typing import Any, cast
|
|
4
3
|
|
|
5
4
|
import numpy as np
|
|
@@ -9,6 +8,7 @@ from scipy.optimize import fmin
|
|
|
9
8
|
|
|
10
9
|
from pyobs.images import Image
|
|
11
10
|
from pyobs.images.meta import PixelOffsets
|
|
11
|
+
from pyobs.utils.fits import fitssec
|
|
12
12
|
|
|
13
13
|
from .offsets import Offsets
|
|
14
14
|
|
|
@@ -155,16 +155,8 @@ class ProjectedOffsets(Offsets):
|
|
|
155
155
|
Projected images.
|
|
156
156
|
"""
|
|
157
157
|
|
|
158
|
-
#
|
|
159
|
-
data
|
|
160
|
-
|
|
161
|
-
# trimsec
|
|
162
|
-
if "TRIMSEC" in hdr:
|
|
163
|
-
m = re.match(r"\[([0-9]+):([0-9]+),([0-9]+):([0-9]+)\]", hdr["TRIMSEC"])
|
|
164
|
-
if m is None:
|
|
165
|
-
raise ValueError("Invalid trimsec.")
|
|
166
|
-
x0, x1, y0, y1 = [int(f) for f in m.groups()]
|
|
167
|
-
data = data[y0 - 1 : y1, x0 - 1 : x1]
|
|
158
|
+
# trim to trimsec, if set
|
|
159
|
+
data = fitssec(image)
|
|
168
160
|
|
|
169
161
|
# collapse
|
|
170
162
|
sum_x = np.nansum(data, 0)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
from abc import ABCMeta
|
|
2
2
|
|
|
3
3
|
from .IData import IData
|
|
4
|
-
from .IExposure import IExposure
|
|
5
4
|
|
|
6
5
|
|
|
7
|
-
class ICamera(IData,
|
|
6
|
+
class ICamera(IData, metaclass=ABCMeta):
|
|
8
7
|
"""The module controls a camera."""
|
|
9
8
|
|
|
10
9
|
__module__ = "pyobs.interfaces"
|
|
@@ -2,8 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from abc import ABCMeta, abstractmethod
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Annotated, Any
|
|
6
6
|
|
|
7
|
+
from ..utils.enums import Unit
|
|
7
8
|
from ..utils.time import Time
|
|
8
9
|
from .IAbortable import IAbortable
|
|
9
10
|
|
|
@@ -23,13 +24,18 @@ class IDataSequence(IAbortable, metaclass=ABCMeta):
|
|
|
23
24
|
state = DataSequenceState
|
|
24
25
|
|
|
25
26
|
@abstractmethod
|
|
26
|
-
async def grab_sequence(
|
|
27
|
+
async def grab_sequence(
|
|
28
|
+
self, count: int, broadcast: bool = True, delay: Annotated[float, Unit.SECONDS] = 0, **kwargs: Any
|
|
29
|
+
) -> None:
|
|
27
30
|
"""Start a sequence of `count` grabs. Returns immediately; progress is available via
|
|
28
31
|
the pushed DataSequenceState.
|
|
29
32
|
|
|
30
33
|
Args:
|
|
31
34
|
count: Number of grabs to take.
|
|
32
35
|
broadcast: Broadcast existence of each grab.
|
|
36
|
+
delay: Seconds to wait between the end of one grab and the start of the next.
|
|
37
|
+
Does not apply after the last grab. Skipped early if the sequence is aborted
|
|
38
|
+
during the wait.
|
|
33
39
|
|
|
34
40
|
Raises:
|
|
35
41
|
GrabImageError: If the device is already busy (exposing or already running a
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
from abc import ABCMeta
|
|
2
2
|
|
|
3
3
|
from .IData import IData
|
|
4
|
-
from .IExposure import IExposure
|
|
5
4
|
|
|
6
5
|
|
|
7
|
-
class ISpectrograph(IData,
|
|
6
|
+
class ISpectrograph(IData, metaclass=ABCMeta):
|
|
8
7
|
"""The module controls a camera."""
|
|
9
8
|
|
|
10
9
|
__module__ = "pyobs.interfaces"
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import Any, cast
|
|
5
5
|
|
|
6
|
+
from pyobs.comm.proxy import Proxy
|
|
6
7
|
from pyobs.interfaces import IBinning, IData, IFilters, IWindow
|
|
7
8
|
from pyobs.modules import Module
|
|
8
9
|
|
|
@@ -54,7 +55,10 @@ class CameraSettingsMixin:
|
|
|
54
55
|
await camera.set_binning(self.__camerasettings_binning, self.__camerasettings_binning)
|
|
55
56
|
if isinstance(camera, IWindow):
|
|
56
57
|
log.info("Set window to full frame...")
|
|
57
|
-
|
|
58
|
+
if isinstance(camera, Proxy):
|
|
59
|
+
cap = await camera.wait_for_capabilities(IWindow)
|
|
60
|
+
else:
|
|
61
|
+
cap = camera.get_capabilities(IWindow)
|
|
58
62
|
if cap is not None:
|
|
59
63
|
await camera.set_window(cap.full_frame_x, cap.full_frame_y, cap.full_frame_width, cap.full_frame_height)
|
|
60
64
|
else:
|
|
@@ -46,7 +46,9 @@ async def calc_expose_timeout(camera: BaseCamera, *args: Any, **kwargs: Any) ->
|
|
|
46
46
|
return camera._exposure_time + 30
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
class BaseCamera(
|
|
49
|
+
class BaseCamera(
|
|
50
|
+
Module, ImageFitsHeaderMixin, ICamera, IExposure, IExposureTime, IImageType, IDataSequence, metaclass=ABCMeta
|
|
51
|
+
):
|
|
50
52
|
"""Base class for all camera modules."""
|
|
51
53
|
|
|
52
54
|
__module__ = "pyobs.modules.camera"
|
|
@@ -108,6 +110,7 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
108
110
|
# (also between individual grabs, while _camera_status is briefly IDLE again)
|
|
109
111
|
self._sequence_count_left = 0
|
|
110
112
|
self._sequence_task: asyncio.Task[None] | None = None
|
|
113
|
+
self._sequence_delay_abort = asyncio.Event()
|
|
111
114
|
|
|
112
115
|
# register exception
|
|
113
116
|
exc.register_exception(exc.GrabImageError, 3, timespan=600, callback=self._default_remote_error_callback)
|
|
@@ -370,19 +373,23 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
370
373
|
# return filename
|
|
371
374
|
return filename
|
|
372
375
|
|
|
373
|
-
async def grab_sequence(self, count: int, broadcast: bool = True, **kwargs: Any) -> None:
|
|
376
|
+
async def grab_sequence(self, count: int, broadcast: bool = True, delay: float = 0, **kwargs: Any) -> None:
|
|
374
377
|
"""Start a sequence of `count` images. Returns immediately; progress is available via
|
|
375
378
|
the pushed DataSequenceState.
|
|
376
379
|
|
|
377
380
|
Args:
|
|
378
381
|
count: Number of images to take.
|
|
379
382
|
broadcast: Broadcast existence of each image.
|
|
383
|
+
delay: Seconds to wait between the end of one image and the start of the next.
|
|
384
|
+
Does not apply after the last image.
|
|
380
385
|
|
|
381
386
|
Raises:
|
|
382
387
|
CameraException: If camera is already busy (exposing or already running a sequence).
|
|
383
388
|
"""
|
|
384
389
|
if count < 1:
|
|
385
390
|
raise ValueError("count must be >= 1.")
|
|
391
|
+
if delay < 0:
|
|
392
|
+
raise ValueError("delay must be >= 0.")
|
|
386
393
|
|
|
387
394
|
# already running a sequence, or mid-exposure outside of one?
|
|
388
395
|
if self._sequence_count_left > 0 or self._camera_status != ExposureStatus.IDLE:
|
|
@@ -391,9 +398,9 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
391
398
|
log.info("Starting sequence of %d images...", count)
|
|
392
399
|
self._sequence_count_left = count
|
|
393
400
|
await self.comm.set_state(IDataSequence, DataSequenceState(count_total=count, count_left=count))
|
|
394
|
-
self._sequence_task = asyncio.create_task(self._run_sequence(count, broadcast))
|
|
401
|
+
self._sequence_task = asyncio.create_task(self._run_sequence(count, broadcast, delay))
|
|
395
402
|
|
|
396
|
-
async def _run_sequence(self, count_total: int, broadcast: bool) -> None:
|
|
403
|
+
async def _run_sequence(self, count_total: int, broadcast: bool, delay: float) -> None:
|
|
397
404
|
"""Runs a sequence of grab_data() calls, started by grab_sequence()."""
|
|
398
405
|
try:
|
|
399
406
|
while self._sequence_count_left > 0:
|
|
@@ -406,6 +413,15 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
406
413
|
await self.comm.set_state(
|
|
407
414
|
IDataSequence, DataSequenceState(count_total=count_total, count_left=self._sequence_count_left)
|
|
408
415
|
)
|
|
416
|
+
|
|
417
|
+
# wait between images, unless this was the last one or the sequence was
|
|
418
|
+
# aborted in the meantime -- either abort_sequence() or abort() cuts this short
|
|
419
|
+
if self._sequence_count_left > 0 and delay > 0:
|
|
420
|
+
self._sequence_delay_abort.clear()
|
|
421
|
+
try:
|
|
422
|
+
await asyncio.wait_for(self._sequence_delay_abort.wait(), timeout=delay)
|
|
423
|
+
except TimeoutError:
|
|
424
|
+
pass
|
|
409
425
|
finally:
|
|
410
426
|
log.info("Finished sequence.")
|
|
411
427
|
self._sequence_count_left = 0
|
|
@@ -418,6 +434,7 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
418
434
|
"""
|
|
419
435
|
log.info("Aborting sequence after current image...")
|
|
420
436
|
self._sequence_count_left = 0
|
|
437
|
+
self._sequence_delay_abort.set()
|
|
421
438
|
|
|
422
439
|
async def _abort_exposure(self) -> None:
|
|
423
440
|
"""Abort the running exposure. Should be implemented by derived class.
|
|
@@ -438,6 +455,7 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
438
455
|
log.info("Aborting current image and sequence...")
|
|
439
456
|
self.expose_abort.set()
|
|
440
457
|
self._sequence_count_left = 0
|
|
458
|
+
self._sequence_delay_abort.set()
|
|
441
459
|
|
|
442
460
|
# do camera-specific abort
|
|
443
461
|
await self._abort_exposure()
|
|
@@ -23,7 +23,7 @@ class ExposureInfo(NamedTuple):
|
|
|
23
23
|
start: datetime
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
class BaseSpectrograph(Module, SpectrumFitsHeaderMixin, ISpectrograph, metaclass=ABCMeta):
|
|
26
|
+
class BaseSpectrograph(Module, SpectrumFitsHeaderMixin, ISpectrograph, IExposure, metaclass=ABCMeta):
|
|
27
27
|
"""Base class for all spectrograph modules."""
|
|
28
28
|
|
|
29
29
|
__module__ = "pyobs.modules.camera"
|
|
@@ -3,11 +3,11 @@ from typing import Any
|
|
|
3
3
|
|
|
4
4
|
from pyobs.events import NewImageEvent
|
|
5
5
|
from pyobs.images import Image
|
|
6
|
-
from pyobs.interfaces import
|
|
6
|
+
from pyobs.interfaces import ICamera
|
|
7
7
|
from pyobs.mixins import ImageFitsHeaderMixin
|
|
8
8
|
from pyobs.mixins.pipeline import PipelineMixin
|
|
9
9
|
from pyobs.modules import Module
|
|
10
|
-
from pyobs.utils.enums import
|
|
10
|
+
from pyobs.utils.enums import ImageType
|
|
11
11
|
from pyobs.utils.exceptions import GrabImageError
|
|
12
12
|
|
|
13
13
|
log = logging.getLogger(__name__)
|
|
@@ -24,15 +24,6 @@ class PipelineCamera(Module, ICamera, ImageFitsHeaderMixin, PipelineMixin):
|
|
|
24
24
|
PipelineMixin.__init__(self, **kwargs)
|
|
25
25
|
ImageFitsHeaderMixin.__init__(self, **kwargs)
|
|
26
26
|
|
|
27
|
-
async def open(self) -> None:
|
|
28
|
-
"""Open module."""
|
|
29
|
-
await Module.open(self)
|
|
30
|
-
|
|
31
|
-
# publish initial state
|
|
32
|
-
await self.comm.set_state(
|
|
33
|
-
IExposure, ExposureState(status=ExposureStatus.IDLE, progress=0.0, exposure_time_left=0.0)
|
|
34
|
-
)
|
|
35
|
-
|
|
36
27
|
async def grab_data(self, broadcast: bool = True, **kwargs: Any) -> str:
|
|
37
28
|
"""Grabs an image and returns reference.
|
|
38
29
|
|
|
@@ -281,14 +281,21 @@ class Scheduler(Module, IStartStop, IRunnable):
|
|
|
281
281
|
# sleep a little
|
|
282
282
|
await asyncio.sleep(1)
|
|
283
283
|
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
def _log_scheduled_task(self, scheduled_tasks: ObservationList) -> None:
|
|
285
|
+
try:
|
|
286
|
+
observer = self._scheduler.observer
|
|
287
|
+
except AttributeError:
|
|
288
|
+
observer = None
|
|
286
289
|
for scheduled_task in scheduled_tasks:
|
|
287
290
|
msg = f" - {scheduled_task.start.strftime('%H:%M:%S')} to {scheduled_task.end.strftime('%H:%M:%S')}: "
|
|
288
291
|
msg += f"{scheduled_task.task.name} ({scheduled_task.task.id}"
|
|
289
292
|
if scheduled_task.priority is not None:
|
|
290
293
|
msg += f", priority: {scheduled_task.priority}"
|
|
291
294
|
msg += ")"
|
|
295
|
+
if scheduled_task.target is not None and observer is not None:
|
|
296
|
+
start = Time(scheduled_task.start)
|
|
297
|
+
altaz = observer.altaz(start, scheduled_task.target.coordinates(start))
|
|
298
|
+
msg += f" [{scheduled_task.target.name}: alt={altaz.alt.degree:.1f}°, airmass={float(altaz.secz):.2f}]"
|
|
292
299
|
log.info(msg)
|
|
293
300
|
|
|
294
301
|
async def run(self, **kwargs: Any) -> None:
|
|
@@ -308,7 +308,14 @@ class BaseTelescope(
|
|
|
308
308
|
|
|
309
309
|
# check altitude
|
|
310
310
|
if alt_az.alt.degree < self._min_altitude:
|
|
311
|
-
raise ValueError(
|
|
311
|
+
raise ValueError(
|
|
312
|
+
f"Destination altitude below limit: alt={alt_az.alt.degree:.2f}° "
|
|
313
|
+
f"az={alt_az.az.degree:.2f}° (min={self._min_altitude:.2f}°) for "
|
|
314
|
+
f"ra={ra:.5f}° dec={dec:.5f}° at {Time.now().isot} from "
|
|
315
|
+
f"lon={self.observer.location.lon.degree:.4f}° "
|
|
316
|
+
f"lat={self.observer.location.lat.degree:.4f}° "
|
|
317
|
+
f"height={self.observer.location.height.value:.1f}m."
|
|
318
|
+
)
|
|
312
319
|
|
|
313
320
|
# acquire lock
|
|
314
321
|
async with LockWithAbort(self._lock_moving, self._abort_move):
|
|
@@ -382,7 +389,10 @@ class BaseTelescope(
|
|
|
382
389
|
|
|
383
390
|
# check altitude
|
|
384
391
|
if alt < self._min_altitude:
|
|
385
|
-
raise ValueError(
|
|
392
|
+
raise ValueError(
|
|
393
|
+
f"Destination altitude below limit: alt={alt:.2f}° az={az:.2f}° "
|
|
394
|
+
f"(min={self._min_altitude:.2f}°) at {Time.now().isot}."
|
|
395
|
+
)
|
|
386
396
|
|
|
387
397
|
# acquire lock
|
|
388
398
|
async with LockWithAbort(self._lock_moving, self._abort_move):
|
{pyobs_core-2.0.0.dev24 → pyobs_core-2.0.0.dev26}/pyobs/robotic/storage/lco/scripts/script.py
RENAMED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
|
+
from pydantic import PrivateAttr
|
|
7
|
+
|
|
6
8
|
from pyobs.interfaces import FitsHeaderEntry
|
|
7
9
|
from pyobs.robotic.scripts import Script
|
|
8
10
|
from pyobs.robotic.storage.lco._portal import LcoRequest
|
|
@@ -24,6 +26,8 @@ class LcoScript(Script):
|
|
|
24
26
|
request: LcoRequest
|
|
25
27
|
scripts: dict[str, dict[str, Any]] = {}
|
|
26
28
|
|
|
29
|
+
_running_script: Script | None = PrivateAttr(default=None)
|
|
30
|
+
|
|
27
31
|
def _create_script(self) -> Script:
|
|
28
32
|
"""Build the script selected via the configuration's extra_params["script_name"].
|
|
29
33
|
|
|
@@ -55,6 +59,7 @@ class LcoScript(Script):
|
|
|
55
59
|
InterruptedError: If interrupted
|
|
56
60
|
"""
|
|
57
61
|
script = self._create_script()
|
|
62
|
+
self._running_script = script
|
|
58
63
|
try:
|
|
59
64
|
await script.run(data)
|
|
60
65
|
finally:
|
|
@@ -69,7 +74,8 @@ class LcoScript(Script):
|
|
|
69
74
|
Returns:
|
|
70
75
|
Dictionary containing FITS headers.
|
|
71
76
|
"""
|
|
72
|
-
|
|
77
|
+
script = self._running_script if self._running_script is not None else self._create_script()
|
|
78
|
+
return script.get_fits_headers(namespaces)
|
|
73
79
|
|
|
74
80
|
def estimate_duration(self, data: TaskData | None = None, time: Time | None = None) -> float:
|
|
75
81
|
"""Estimate duration based on the duration calculated by the LCO portal."""
|
|
@@ -184,6 +184,7 @@ class LcoTask(Task):
|
|
|
184
184
|
# at least we tried...
|
|
185
185
|
config_status = ConfigStatus()
|
|
186
186
|
script = self.pyobs_model_validate(Script, self.script, by_alias=True)
|
|
187
|
+
self._running_script = script
|
|
187
188
|
|
|
188
189
|
try:
|
|
189
190
|
# run it
|
|
@@ -232,9 +233,11 @@ class LcoTask(Task):
|
|
|
232
233
|
Dictionary containing FITS headers.
|
|
233
234
|
"""
|
|
234
235
|
|
|
235
|
-
#
|
|
236
|
-
|
|
237
|
-
script = self.
|
|
236
|
+
# use the actively running script instance if there is one, so we pick up its
|
|
237
|
+
# accumulated state (e.g. current target name); otherwise fall back to a fresh one
|
|
238
|
+
script = self._running_script
|
|
239
|
+
if script is None:
|
|
240
|
+
script = self.pyobs_model_validate(Script, self.script, by_alias=True)
|
|
238
241
|
hdr = script.get_fits_headers(namespaces)
|
|
239
242
|
|
|
240
243
|
# return it
|
|
@@ -41,6 +41,7 @@ class Task(BaseModel):
|
|
|
41
41
|
|
|
42
42
|
_resolved_target: Target | None = PrivateAttr(default=None)
|
|
43
43
|
_cant_run_reason: str | None = None
|
|
44
|
+
_running_script: Script | None = PrivateAttr(default=None)
|
|
44
45
|
|
|
45
46
|
model_config = ConfigDict(populate_by_name=True)
|
|
46
47
|
|
|
@@ -85,7 +86,9 @@ class Task(BaseModel):
|
|
|
85
86
|
async def run(self, data: TaskData | None) -> None:
|
|
86
87
|
"""Run a task"""
|
|
87
88
|
if self.script is not None:
|
|
88
|
-
|
|
89
|
+
script = self.create_script()
|
|
90
|
+
self._running_script = script
|
|
91
|
+
await script.run(data)
|
|
89
92
|
|
|
90
93
|
def is_finished(self) -> bool:
|
|
91
94
|
"""Whether task is finished."""
|
|
@@ -100,7 +103,9 @@ class Task(BaseModel):
|
|
|
100
103
|
Returns:
|
|
101
104
|
Dictionary containing FITS headers.
|
|
102
105
|
"""
|
|
103
|
-
|
|
106
|
+
if self._running_script is None:
|
|
107
|
+
return {}
|
|
108
|
+
return self._running_script.get_fits_headers(namespaces)
|
|
104
109
|
|
|
105
110
|
def estimate_duration(self, time: Time | None = None) -> float:
|
|
106
111
|
if self.script:
|
|
@@ -17,6 +17,43 @@ from pyobs.utils.time import Time
|
|
|
17
17
|
log = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def parse_section_bounds(header: fits.Header, keyword: str = "TRIMSEC") -> tuple[int, int, int, int] | None:
|
|
21
|
+
"""Parse a FITS section keyword (e.g. TRIMSEC) into 0-based, half-open slice bounds.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
header: Header to look up the keyword in.
|
|
25
|
+
keyword: Header keyword for section.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
(x0, x1, y0, y1) such that data[y0:y1, x0:x1] gives the section, or None if
|
|
29
|
+
the keyword is not present in the header.
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
ValueError: If the keyword is present but its value is malformed.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# keyword not given?
|
|
36
|
+
if keyword not in header:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
# get value of section
|
|
40
|
+
sec = header[keyword]
|
|
41
|
+
|
|
42
|
+
# split values
|
|
43
|
+
try:
|
|
44
|
+
s = sec[1:-1].split(",")
|
|
45
|
+
x = s[0].split(":")
|
|
46
|
+
y = s[1].split(":")
|
|
47
|
+
x0 = int(x[0]) - 1
|
|
48
|
+
x1 = int(x[1])
|
|
49
|
+
y0 = int(y[0]) - 1
|
|
50
|
+
y1 = int(y[1])
|
|
51
|
+
except (IndexError, ValueError) as e:
|
|
52
|
+
raise ValueError(f"Invalid {keyword} value: {sec!r}") from e
|
|
53
|
+
|
|
54
|
+
return x0, x1, y0, y1
|
|
55
|
+
|
|
56
|
+
|
|
20
57
|
def fitssec(hdu: Any, keyword: str = "TRIMSEC") -> NDArray[Any]:
|
|
21
58
|
"""Trim an image to TRIMSEC or BIASSEC.
|
|
22
59
|
|
|
@@ -28,24 +65,14 @@ def fitssec(hdu: Any, keyword: str = "TRIMSEC") -> NDArray[Any]:
|
|
|
28
65
|
Numpy array with image data.
|
|
29
66
|
"""
|
|
30
67
|
|
|
31
|
-
#
|
|
32
|
-
|
|
68
|
+
# parse section bounds
|
|
69
|
+
bounds = parse_section_bounds(hdu.header, keyword)
|
|
70
|
+
if bounds is None:
|
|
33
71
|
# return whole data
|
|
34
72
|
return cast(NDArray[Any], hdu.data)
|
|
35
73
|
|
|
36
|
-
# get value of section
|
|
37
|
-
sec = hdu.header[keyword]
|
|
38
|
-
|
|
39
|
-
# split values
|
|
40
|
-
s = sec[1:-1].split(",")
|
|
41
|
-
x = s[0].split(":")
|
|
42
|
-
y = s[1].split(":")
|
|
43
|
-
x0 = int(x[0]) - 1
|
|
44
|
-
x1 = int(x[1])
|
|
45
|
-
y0 = int(y[0]) - 1
|
|
46
|
-
y1 = int(y[1])
|
|
47
|
-
|
|
48
74
|
# return data
|
|
75
|
+
x0, x1, y0, y1 = bounds
|
|
49
76
|
return cast(NDArray[Any], hdu.data[y0:y1, x0:x1])
|
|
50
77
|
|
|
51
78
|
|
|
@@ -284,4 +311,4 @@ def format_filename(hdr: fits.Header, fmt: str | list[str], keys: dict[str, Any]
|
|
|
284
311
|
return ff(hdr)
|
|
285
312
|
|
|
286
313
|
|
|
287
|
-
__all__ = ["format_filename", "FilenameFormatter", "fitssec"]
|
|
314
|
+
__all__ = ["format_filename", "FilenameFormatter", "fitssec", "parse_section_bounds"]
|