7#include "adaptivefocus.h"
8#include "focusadaptor.h"
9#include "focusalgorithms.h"
11#include "aberrationinspector.h"
12#include "aberrationinspectorutils.h"
14#include "kstarsdata.h"
16#include "stellarsolver.h"
19#include "ekos/guide/guide.h"
20#include "ekos/manager.h"
23#include "auxiliary/kspaths.h"
24#include "auxiliary/ksmessagebox.h"
27#include "ekos/auxiliary/darklibrary.h"
28#include "ekos/auxiliary/darkprocessor.h"
29#include "ekos/auxiliary/profilesettings.h"
30#include "ekos/auxiliary/opticaltrainmanager.h"
31#include "ekos/auxiliary/opticaltrainsettings.h"
32#include "ekos/auxiliary/filtermanager.h"
33#include "ekos/auxiliary/stellarsolverprofileeditor.h"
36#include "fitsviewer/fitsdata.h"
37#include "fitsviewer/fitsview.h"
38#include "fitsviewer/fitsviewer.h"
41#include "indi/indifilterwheel.h"
42#include "ksnotification.h"
43#include "kconfigdialog.h"
45#include <basedevice.h>
46#include <gsl/gsl_fit.h>
47#include <gsl/gsl_vector.h>
48#include <gsl/gsl_min.h>
50#include <ekos_focus_debug.h>
54#define MAXIMUM_ABS_ITERATIONS 51
55#define MAXIMUM_RESET_ITERATIONS 3
56#define AUTO_STAR_TIMEOUT 45000
57#define MINIMUM_PULSE_TIMER 32
58#define MAX_RECAPTURE_RETRIES 3
59#define MINIMUM_POLY_SOLUTIONS 2
61const QString FOCUSER_SIMULATOR =
"Focuser Simulator";
95 connectSyncSettings();
98 adaptFocus.reset(
new AdaptiveFocus(
this));
106 button->setAutoDefault(
false);
108 appendLogText(
i18n(
"Idle."));
111 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
112 m_FocusMotionTimer.setSingleShot(
true);
118 m_FocusLogFile.setFileName(m_FocusLogFileName);
120 m_OpsFocusProcess->editFocusProfile->setIcon(
QIcon::fromTheme(
"document-edit"));
125 KConfigDialog *optionsEditor = new KConfigDialog(this,
"OptionsProfileEditor", Options::self());
126 optionsProfileEditor = new StellarSolverProfileEditor(this, Ekos::FocusProfiles, optionsEditor);
128 optionsEditor->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
130 KPageWidgetItem *mainPage = optionsEditor->addPage(optionsProfileEditor, i18n(
"Focus Options Profile Editor"));
131 mainPage->setIcon(QIcon::fromTheme(
"configure"));
132 connect(optionsProfileEditor, &StellarSolverProfileEditor::optionsProfilesUpdated, this, &Focus::loadStellarSolverProfiles);
133 optionsProfileEditor->loadProfile(m_OpsFocusProcess->focusSEPProfile->currentText());
134 optionsEditor->show();
137 loadStellarSolverProfiles();
151 m_DarkProcessor =
new DarkProcessor(
this);
153 connect(m_DarkProcessor, &DarkProcessor::darkFrameCompleted,
this, [
this](
bool completed)
155 m_OpsFocusSettings->useFocusDarkFrame->setChecked(completed);
156 m_FocusView->setProperty(
"suspended",
false);
159 m_FocusView->rescale(ZOOM_KEEP_LEVEL);
160 m_FocusView->updateFrame();
162 setCaptureComplete();
166 setupOpticalTrainManager();
168 connectFilterManager();
172void Focus::prepareGUI()
182 m_OpsFocusSettings =
new OpsFocusSettings();
190 m_OpsFocusProcess =
new OpsFocusProcess();
191 page = dialog->
addPage(m_OpsFocusProcess,
i18n(
"Process"),
nullptr,
i18n(
"Focus Process"),
false);
194 m_OpsFocusMechanics =
new OpsFocusMechanics();
195 page = dialog->
addPage(m_OpsFocusMechanics,
i18n(
"Mechanics"),
nullptr,
i18n(
"Focus Mechanics"),
false);
199 m_CFZDialog =
new QDialog(
this);
200 m_CFZUI.reset(
new Ui::focusCFZDialog());
201 m_CFZUI->setupUi(m_CFZDialog);
207 m_AdvisorDialog =
new QDialog(
this);
208 m_AdvisorUI.reset(
new Ui::focusAdvisorDialog());
209 m_AdvisorUI->setupUi(m_AdvisorDialog);
215 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
216 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
217 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
218 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
219 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
220 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThreshold);
221 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
222 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
223 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
224 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusTolerance);
225 delete m_OpsFocusProcess->gridLayoutProcessBucket;
228 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
229 m_OpsFocusMechanics->focusNumStepsLabel);
230 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
231 m_OpsFocusMechanics->focusNumSteps);
235 for (
int i = 0; i < m_OpsFocusProcess->focusStarMeasure->count(); i++)
236 m_StarMeasureText.append(m_OpsFocusProcess->focusStarMeasure->itemText(i));
237 for (
int i = 0; i < m_OpsFocusProcess->focusCurveFit->count(); i++)
238 m_CurveFitText.append(m_OpsFocusProcess->focusCurveFit->itemText(i));
239 for (
int i = 0; i < m_OpsFocusMechanics->focusWalk->count(); i++)
240 m_FocusWalkText.append(m_OpsFocusMechanics->focusWalk->itemText(i));
243void Focus::loadStellarSolverProfiles()
245 QString savedOptionsProfiles =
QDir(KSPaths::writableLocation(
250 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_NAME);
251 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_DONUT_NAME);
254 m_StellarSolverProfiles = getDefaultFocusOptionsProfiles();
255 m_OpsFocusProcess->focusSEPProfile->clear();
256 for(
auto &
param : m_StellarSolverProfiles)
257 m_OpsFocusProcess->focusSEPProfile->addItem(
param.listName);
258 auto profile = m_Settings[
"focusSEPProfile"];
259 if (profile.isValid())
260 m_OpsFocusProcess->focusSEPProfile->setCurrentText(profile.toString());
265 for(
auto params : m_StellarSolverProfiles)
267 if (params.listName == profile)
273 SSolver::Parameters params;
274 if (profile == FOCUS_DEFAULT_DONUT_NAME)
275 params = getFocusOptionsProfileDefaultDonut();
276 else if (profile == FOCUS_DEFAULT_NAME)
277 params = getFocusOptionsProfileDefault();
281 settings.beginGroup(params.listName);
287 settings.setValue(
it.key(),
it.value());
291 m_StellarSolverProfiles.append(params);
297 for (
auto param : m_StellarSolverProfiles)
298 profiles <<
param.listName;
306 toggleFocusingWidgetFullScreen();
308 m_FocusLogFile.close();
311void Focus::resetFrame()
313 if (m_Camera && m_Camera->isConnected())
315 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
320 targetChip->resetFrame();
323 targetChip->getFrame(&x, &y, &w, &h);
325 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Frame is reset. X:" << x <<
"Y:" << y <<
"W:" << w <<
"H:" << h <<
"binX:" << 1 <<
"binY:" <<
328 QVariantMap settings;
333 settings[
"binx"] = 1;
334 settings[
"biny"] = 1;
335 frameSettings[targetChip] = settings;
337 starSelected =
false;
341 m_FocusView->setTrackingBox(
QRect());
342 checkMosaicMaskLimits();
350 return m_Camera->getDeviceName();
355void Focus::checkCamera()
375 case FOCUS_CHANGING_FILTER:
380 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
381 if (targetChip && targetChip->isCapturing())
387 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
388 if (targetChip->canBin())
390 int subBinX = 1, subBinY = 1;
392 targetChip->getMaxBin(&subBinX, &subBinY);
393 for (
int i = 1; i <= subBinX; i++)
396 auto binning = m_Settings[
"focusBinning"];
397 if (binning.isValid())
401 connect(m_Camera, &ISD::Camera::videoStreamToggled,
this, &Ekos::Focus::setVideoStreamEnabled,
Qt::UniqueConnection);
402 liveVideoB->setEnabled(m_Camera->hasVideoStream());
403 if (m_Camera->hasVideoStream())
404 setVideoStreamEnabled(m_Camera->isStreamingEnabled());
414void Focus::syncCCDControls()
416 if (m_Camera ==
nullptr)
419 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
420 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
423 auto isoList = targetChip->getISOList();
436 focusISO->setCurrentIndex(targetChip->getISOIndex());
439 bool hasGain = m_Camera->hasGain();
441 focusGain->setEnabled(hasGain && m_Camera->getGainPermission() !=
IP_RO);
444 double gain = 0, min = 0, max = 0, step = 1;
445 m_Camera->getGainMinMaxStep(&min, &max, &step);
446 if (m_Camera->getGain(&gain))
449 GainSpinSpecialValue = min - step;
450 focusGain->setRange(GainSpinSpecialValue, max);
459 focusGain->setValue(GainSpinSpecialValue);
466void Focus::syncCameraInfo()
468 if (m_Camera ==
nullptr)
471 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
472 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
475 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
477 if (frameSettings.contains(targetChip) ==
false)
480 if (targetChip->getFrame(&x, &y, &w, &h))
483 targetChip->getBinning(&
binx, &
biny);
489 QVariantMap settings;
491 settings[
"x"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? x :
minX;
492 settings[
"y"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? y :
minY;
493 settings[
"w"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? w :
maxW;
494 settings[
"h"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? h :
maxH;
495 settings[
"binx"] =
binx;
496 settings[
"biny"] =
biny;
498 frameSettings[targetChip] = settings;
504bool Focus::setFilterWheel(ISD::FilterWheel *device)
506 if (m_FilterWheel && m_FilterWheel == device)
513 m_FilterWheel->disconnect(
this);
515 m_FilterWheel = device;
519 connect(m_FilterWheel, &ISD::ConcreteDevice::Connected,
this, [
this]()
525 connect(m_FilterWheel, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
533 auto isConnected = m_FilterWheel && m_FilterWheel->isConnected();
550 for (
auto &
oneSource : m_TemperatureSources)
552 if (
oneSource->getDeviceName() == device->getDeviceName())
556 m_TemperatureSources.append(device);
559 auto targetSource = m_Settings[
"defaultFocusTemperatureSource"];
565void Focus::checkTemperatureSource(
const QString &name )
571 if (source.isEmpty())
577 for (
auto &
oneSource : m_TemperatureSources)
579 if (
oneSource->getDeviceName() == source)
586 m_LastSourceDeviceAutofocusTemperature = currentSource;
593 for (
const auto &
oneSource : m_TemperatureSources)
597 if (findTemperatureElement(currentSource))
599 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
605 m_LastSourceAutofocusTemperature = INVALID_VALUE;
646 return m_FilterWheel->getDeviceName();
668void Focus::checkFilter()
680 m_FilterManager->disconnect(
this);
681 disconnect(m_FilterManager.get());
682 m_FilterManager.reset();
691 setupFilterManager();
693 focusFilter->addItems(m_FilterManager->getFilterLabels());
695 currentFilterPosition = m_FilterManager->getFilterPosition();
697 focusFilter->setCurrentIndex(currentFilterPosition - 1);
699 focusExposure->setValue(m_FilterManager->getFilterExposure());
704 if (m_Focuser && m_Focuser == device)
711 m_Focuser->disconnect(
this);
717 connect(m_Focuser, &ISD::ConcreteDevice::Connected,
this, [
this]()
721 connect(m_Focuser, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
734 return m_Focuser->getDeviceName();
739void Focus::checkFocuser()
744 m_FilterManager->setFocusReady(
false);
745 canAbsMove = canRelMove = canTimerMove =
false;
747 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
754 m_FilterManager->setFocusReady(m_Focuser->isConnected());
756 hasDeviation = m_Focuser->hasDeviation();
758 canAbsMove = m_Focuser->canAbsMove();
762 getAbsFocusPosition();
779 canRelMove = m_Focuser->canRelMove();
784 if (canAbsMove ==
false && canRelMove ==
true)
786 currentPosition = 50000;
787 absMotionMax = 100000;
791 canTimerMove = m_Focuser->canTimerMove();
797 if (!canAbsMove && !canRelMove && canTimerMove)
799 currentPosition = 50000;
800 absMotionMax = 100000;
804 m_FocusType = (canRelMove || canAbsMove || canTimerMove) ? FOCUS_AUTO : FOCUS_MANUAL;
805 profilePlot->setFocusAuto(m_FocusType == FOCUS_AUTO);
807 bool hasBacklash = m_Focuser->hasBacklash();
808 m_OpsFocusMechanics->focusBacklash->setEnabled(hasBacklash);
809 m_OpsFocusMechanics->focusBacklash->disconnect(
this);
812 double min = 0, max = 0, step = 0;
813 m_Focuser->getMinMaxStep(
"FOCUS_BACKLASH_STEPS",
"FOCUS_BACKLASH_VALUE", &min, &max, &step);
814 m_OpsFocusMechanics->focusBacklash->setMinimum(min);
815 m_OpsFocusMechanics->focusBacklash->setMaximum(max);
816 m_OpsFocusMechanics->focusBacklash->setSingleStep(step);
817 m_OpsFocusMechanics->focusBacklash->setValue(m_Focuser->getBacklash());
819 this, [
this](
int value)
823 if (m_Focuser->getBacklash() == value)
829 m_Focuser->setBacklash(value);
838 m_OpsFocusMechanics->focusBacklash->setValue(0);
844 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
849 if (m_Camera && m_Camera == device)
856 m_Camera->disconnect(
this);
862 connect(m_Camera, &ISD::ConcreteDevice::Connected,
this, [
this]()
868 connect(m_Camera, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
876 auto isConnected = m_Camera && m_Camera->isConnected();
887 checkMosaicMaskLimits();
891void Focus::getAbsFocusPosition()
896 auto absMove = m_Focuser->getNumber(
"ABS_FOCUS_POSITION");
901 currentPosition =
static_cast<int>(
it->getValue());
902 absMotionMax =
it->getMax();
903 absMotionMin =
it->getMin();
910 double const travel = std::abs(
it->getMax() -
it->getMin());
911 m_OpsFocusMechanics->focusMaxTravel->setMaximum(
travel);;
915 m_OpsFocusMechanics->focusTicks->setMaximum(
it->getMax() / 2);
919void Focus::processTemperatureSource(INDI::Property
prop)
921 if (m_LastSourceAutofocusTemperature == INVALID_VALUE && m_LastSourceDeviceAutofocusTemperature
922 && !currentTemperatureSourceElement )
924 if( findTemperatureElement( m_LastSourceDeviceAutofocusTemperature ) )
926 appendLogText(
i18n(
"Finally found temperature source %1",
QString(currentTemperatureSourceElement->nvp->name)));
927 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
932 if (currentTemperatureSourceElement && currentTemperatureSourceElement->nvp->name ==
prop.getName())
934 if (m_LastSourceAutofocusTemperature != INVALID_VALUE)
936 delta = currentTemperatureSourceElement->value - m_LastSourceAutofocusTemperature;
937 emit newFocusTemperatureDelta(
abs(delta), currentTemperatureSourceElement->value);
941 emit newFocusTemperatureDelta(0, currentTemperatureSourceElement->value);
955void Focus::setLastFocusTemperature()
957 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE;
963 emit newFocusTemperatureDelta(0, -1e6);
966void Focus::setLastFocusAlt()
969 m_LastSourceAutofocusAlt = INVALID_VALUE;
971 m_LastSourceAutofocusAlt = mountAlt;
975void Focus::resetAdaptiveFocus(
bool enabled)
978 Options::setFocusAdaptive(enabled);
981 adaptFocus.reset(
new AdaptiveFocus(
this));
982 adaptFocus->resetAdaptiveFocusCounters();
986void Focus::adaptiveFocus()
989 adaptFocus->runAdaptiveFocus(currentPosition, filter());
993void Focus::startAbIns()
995 m_abInsOn = canAbInsStart();
996 runAutoFocus(AutofocusReason::FOCUS_ABERRATION_INSPECTOR,
"");
1000void Focus::manualStart()
1002 runAutoFocus(AutofocusReason::FOCUS_MANUAL,
"");
1008 runAutoFocus(AutofocusReason::FOCUS_SCHEDULER,
"");
1015 m_AutofocusReasonInfo = reasonInfo;
1016 if (m_Focuser ==
nullptr)
1018 appendLogText(
i18n(
"No Focuser connected."));
1019 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_FOCUSER);
1023 if (m_Camera ==
nullptr)
1025 appendLogText(
i18n(
"No CCD connected."));
1026 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_CAMERA);
1030 if (!canAbsMove && !canRelMove && m_OpsFocusMechanics->focusTicks->value() <= MINIMUM_PULSE_TIMER)
1032 appendLogText(
i18n(
"Starting pulse step is too low. Increase the step size to %1 or higher...",
1033 MINIMUM_PULSE_TIMER * 5));
1034 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_LOW_PULSE);
1043 appendLogText(
i18n(
"Autofocus is already running, discarding start request."));
1050 appendLogText(
i18n(
"Build Offset is already running, Autofocus rejected."));
1051 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1058 appendLogText(
i18n(
"In Focus Loop, Autofocus rejected."));
1059 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1065 if (++AFStartRetries < MAXIMUM_RESET_ITERATIONS)
1070 appendLogText(
i18n(
"Autofocus start request - Waiting 10sec for AdjustFocus to complete."));
1073 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
1078 appendLogText(
i18n(
"Discarding Autofocus start request - AdjustFocus in progress."));
1079 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1083 if (adaptFocus->inAdaptiveFocus())
1086 if (++AFStartRetries < MAXIMUM_RESET_ITERATIONS)
1088 appendLogText(
i18n(
"Autofocus start request - Waiting 10sec for AdaptiveFocus to complete."));
1091 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
1096 appendLogText(
i18n(
"Discarding Autofocus start request - AdaptiveFocus in progress."));
1097 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1101 inBuildOffsets = (
autofocusReason == AutofocusReason::FOCUS_FILTER_OFFSETS);
1105 Options::setFocusForceInSeqAF(
false);
1110 m_LastFocusDirection = FOCUS_NONE;
1112 waitStarSelectTimer.stop();
1115 m_FocusMotionTimerCounter = 0;
1116 m_FocusMotionTimer.stop();
1117 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
1120 m_FocuserReconnectCounter = 0;
1123 m_FocuserReconnectCounter = 0;
1124 m_DebugFocuserCounter = 0;
1131 m_RestartState = RESTART_NONE;
1139 getAbsFocusPosition();
1140 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1142 else if (canRelMove)
1146 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1148 absMotionMax = 100000;
1153 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1155 absMotionMax = 100000;
1159 focuserAdditionalMovement = 0;
1160 starMeasureFrames.clear();
1172 profilePlot->clear();
1177 <<
" Reason: " << AutofocusReasonStr[m_AutofocusReason]
1178 <<
" Reason Info: " << m_AutofocusReasonInfo
1179 <<
" CanAbsMove: " << (canAbsMove ?
"yes" :
"no" )
1180 <<
" CanRelMove: " << (canRelMove ?
"yes" :
"no" )
1181 <<
" CanTimerMove: " << (canTimerMove ?
"yes" :
"no" )
1182 <<
" Position:" << currentPosition
1183 <<
" Filter:" << filter()
1187 <<
" ISO:" <<
focusISO->currentText();
1189 <<
" Auto Select Star:" << ( m_OpsFocusSettings->focusAutoStarEnabled->isChecked() ?
"yes" :
"no" )
1190 <<
" Dark Frame:" << ( m_OpsFocusSettings->useFocusDarkFrame->isChecked() ?
"yes" :
"no" )
1191 <<
" Sub Frame:" << ( m_OpsFocusSettings->focusSubFrame->isChecked() ?
"yes" :
"no" )
1192 <<
" Box:" << m_OpsFocusSettings->focusBoxSize->value()
1193 <<
" Full frame:" << ( m_OpsFocusSettings->focusUseFullField->isChecked() ?
"yes" :
"no " )
1194 <<
" Focus Mask: " << (m_OpsFocusSettings->focusNoMaskRB->isChecked() ?
"Use all stars" :
1195 (m_OpsFocusSettings->focusRingMaskRB->isChecked() ?
QString(
"Ring Mask: [%1%, %2%]").
1196 arg(m_OpsFocusSettings->focusFullFieldInnerRadius->value()).
arg(m_OpsFocusSettings->focusFullFieldOuterRadius->value()) :
1197 QString(
"Mosaic Mask: [%1%, space=%2px]").
1198 arg(m_OpsFocusSettings->focusMosaicTileWidth->value()).
arg(m_OpsFocusSettings->focusMosaicSpace->value())))
1199 <<
" Suspend Guiding:" << ( m_OpsFocusSettings->focusSuspendGuiding->isChecked() ?
"yes" :
"no " )
1200 <<
" Guide Settle:" << m_OpsFocusSettings->focusGuideSettleTime->value()
1201 <<
" Display Units:" << m_OpsFocusSettings->focusUnits->currentText()
1202 <<
" Adaptive Focus:" << ( m_OpsFocusSettings->focusAdaptive->isChecked() ?
"yes" :
"no" )
1203 <<
" Min Move:" << m_OpsFocusSettings->focusAdaptiveMinMove->value()
1204 <<
" Adapt Start:" << ( m_OpsFocusSettings->focusAdaptStart->isChecked() ?
"yes" :
"no" )
1205 <<
" Max Total Move:" << m_OpsFocusSettings->focusAdaptiveMaxMove->value();
1207 <<
" Detection:" << m_OpsFocusProcess->focusDetection->currentText()
1208 <<
" SEP Profile:" << m_OpsFocusProcess->focusSEPProfile->currentText()
1209 <<
" Algorithm:" << m_OpsFocusProcess->focusAlgorithm->currentText()
1210 <<
" Curve Fit:" << m_OpsFocusProcess->focusCurveFit->currentText()
1211 <<
" Measure:" << m_OpsFocusProcess->focusStarMeasure->currentText()
1212 <<
" PSF:" << m_OpsFocusProcess->focusStarPSF->currentText()
1213 <<
" Use Weights:" << ( m_OpsFocusProcess->focusUseWeights->isChecked() ?
"yes" :
"no" )
1214 <<
" R2 Limit:" << m_OpsFocusProcess->focusR2Limit->value()
1215 <<
" Refine Curve Fit:" << ( m_OpsFocusProcess->focusRefineCurveFit->isChecked() ?
"yes" :
"no" )
1216 <<
" Average Over:" << m_OpsFocusProcess->focusFramesCount->value()
1217 <<
" Average HFR Check Over:" << m_OpsFocusProcess->focusHFRFramesCount->value()
1218 <<
" Num.of Rows:" << m_OpsFocusProcess->focusMultiRowAverage->value()
1219 <<
" Sigma:" << m_OpsFocusProcess->focusGaussianSigma->value()
1220 <<
" Threshold:" << m_OpsFocusProcess->focusThreshold->value()
1221 <<
" Kernel size:" << m_OpsFocusProcess->focusGaussianKernelSize->value()
1222 <<
" Tolerance:" << m_OpsFocusProcess->focusTolerance->value()
1223 <<
" Donut Buster:" << ( m_OpsFocusProcess->focusDonut->isChecked() ?
"yes" :
"no" )
1224 <<
" Donut Time Dilation:" << m_OpsFocusProcess->focusTimeDilation->value()
1225 <<
" Outlier Rejection:" << m_OpsFocusProcess->focusOutlierRejection->value();
1227 <<
" Initial Step Size:" << m_OpsFocusMechanics->focusTicks->value()
1228 <<
" Out Step Multiple:" << m_OpsFocusMechanics->focusOutSteps->value()
1229 <<
" Number Steps:" << m_OpsFocusMechanics->focusNumSteps->value()
1230 <<
" Max Travel:" << m_OpsFocusMechanics->focusMaxTravel->value()
1231 <<
" Max Step Size:" << m_OpsFocusMechanics->focusMaxSingleStep->value()
1232 <<
" Driver Backlash:" << m_OpsFocusMechanics->focusBacklash->value()
1233 <<
" AF Overscan:" << m_OpsFocusMechanics->focusAFOverscan->value()
1234 <<
" Overscan Delay:" << m_OpsFocusMechanics->focusOverscanDelay->value()
1235 <<
" Focuser Settle:" << m_OpsFocusMechanics->focusSettleTime->value()
1236 <<
" Walk:" << m_OpsFocusMechanics->focusWalk->currentText()
1237 <<
" Capture Timeout:" << m_OpsFocusMechanics->focusCaptureTimeout->value()
1238 <<
" Motion Timeout:" << m_OpsFocusMechanics->focusMotionTimeout->value();
1240 <<
" Algorithm:" << m_CFZUI->focusCFZAlgorithm->currentText()
1241 <<
" Tolerance:" << m_CFZUI->focusCFZTolerance->value()
1242 <<
" Tolerance (Ï„):" << m_CFZUI->focusCFZTau->value()
1243 <<
" Display:" << ( m_CFZUI->focusCFZDisplayVCurve->isChecked() ?
"yes" :
"no" )
1244 <<
" Wavelength (λ):" << m_CFZUI->focusCFZWavelength->value()
1245 <<
" Aperture (A):" << m_CFZUI->focusCFZAperture->value()
1246 <<
" Focal Ratio (f):" << m_CFZUI->focusCFZFNumber->value()
1247 <<
" Step Size:" << m_CFZUI->focusCFZStepSize->value()
1248 <<
" FWHM (θ):" << m_CFZUI->focusCFZSeeing->value();
1250 const double temperature = (currentTemperatureSourceElement) ? currentTemperatureSourceElement->value : INVALID_VALUE;
1251 emit autofocusStarting(temperature, filter(), m_AutofocusReason, m_AutofocusReasonInfo);
1253 if (m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
1254 appendLogText(
i18n(
"Autofocus in progress..."));
1255 else if (!inAutoFocus)
1256 appendLogText(
i18n(
"Please wait until image capture is complete..."));
1261 if (m_GuidingSuspended ==
false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
1263 m_GuidingSuspended =
true;
1264 emit suspendGuiding();
1268 setState(Ekos::FOCUS_PROGRESS);
1270 KSNotification::event(
QLatin1String(
"FocusStarted"),
i18n(
"Autofocus operation started"), KSNotification::Focus);
1273 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1275 m_AFfilter = filter();
1276 int position = adaptFocus->adaptStartPosition(currentPosition, m_AFfilter);
1278 curveFitting.reset(
new CurveFitting());
1280 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1283 starFitting.reset(
new CurveFitting());
1284 focusFWHM.reset(
new FocusFWHM(m_ScaleCalc));
1285 focusFourierPower.reset(
new FocusFourierPower(m_ScaleCalc));
1287 if (initDonutProcessing())
1292 setupLinearFocuser(position);
1293 if (!changeFocus(linearRequestedPosition - currentPosition))
1294 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
1302void Focus::setupLinearFocuser(
int initialPosition)
1304 FocusAlgorithmInterface::FocusParams params(curveFitting.get(),
1305 m_OpsFocusMechanics->focusMaxTravel->value(), m_OpsFocusMechanics->focusTicks->value(), initialPosition, absMotionMin,
1306 absMotionMax, MAXIMUM_ABS_ITERATIONS, m_OpsFocusProcess->focusTolerance->value() / 100.0, m_AFfilter,
1307 currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE,
1310 m_StarMeasure, m_StarPSF, m_OpsFocusProcess->
focusRefineCurveFit->isChecked(), m_FocusWalk,
1314 initialFocuserAbsPosition = initialPosition;
1315 linearFocuser.reset(MakeLinearFocuser(params));
1316 linearRequestedPosition = linearFocuser->initialPosition();
1320bool Focus::initDonutProcessing()
1322 if (!m_OpsFocusProcess->focusDonut->isChecked())
1327 if (m_OpsFocusProcess->focusScanStartPos->isChecked())
1329 inScanStartPos =
true;
1330 initialFocuserAbsPosition = currentPosition;
1331 m_scanMeasure.clear();
1332 m_scanPosition.clear();
1334 appendLogText(
i18n(
"Starting scan for initial focuser position."));
1335 emit setTitle(
QString(
i18n(
"Scanning for starting position...")),
true);
1343void Focus::resetDonutProcessing()
1346 if (m_OpsFocusProcess->focusDonut->isChecked() && inAutoFocus)
1350int Focus::adjustLinearPosition(
int position,
int newPosition,
int overscan,
bool updateDir)
1362 focuserAdditionalMovementUpdateDir = updateDir;
1369void Focus::checkStopFocus(
bool abort)
1373 resetFocusIteration = MAXIMUM_RESET_ITERATIONS + 1;
1375 if (captureInProgress)
1377 if (inAutoFocus ==
false && inFocusLoop ==
false)
1382 appendLogText(
i18n(
"Capture aborted."));
1384 else if (inAutoFocus)
1387 appendLogText(
i18n(
"Capture in progress, retrying in 1s..."));
1390 checkStopFocus(abort);
1398 appendLogText(
i18n(
"Detection in progress, please wait."));
1401 checkStopFocus(abort);
1406 completeFocusProcedure(abort ? Ekos::FOCUS_ABORTED : Ekos::FOCUS_FAILED, Ekos::FOCUS_FAIL_ABORT);
1410void Focus::meridianFlipStarted()
1413 if (state() == FOCUS_IDLE || state() == FOCUS_COMPLETE || state() == FOCUS_FAILED || state() == FOCUS_ABORTED)
1417 int old = resetFocusIteration;
1421 resetFocusIteration =
old;
1427 if (state() <= FOCUS_ABORTED)
1431 checkStopFocus(
true);
1432 appendLogText(
i18n(
"Autofocus aborted."));
1443 captureTimeout.stop();
1444 m_FocusMotionTimer.stop();
1445 m_FocusMotionTimerCounter = 0;
1446 m_FocuserReconnectCounter = 0;
1449 resetDonutProcessing();
1450 inAutoFocus =
false;
1451 inAdjustFocus =
false;
1452 adaptFocus->setInAdaptiveFocus(
false);
1453 inBuildOffsets =
false;
1454 inScanStartPos =
false;
1455 m_AutofocusReason = AutofocusReason::FOCUS_NONE;
1456 m_AutofocusReasonInfo =
"";
1457 focuserAdditionalMovement = 0;
1458 focuserAdditionalMovementUpdateDir =
true;
1459 inFocusLoop =
false;
1460 captureInProgress =
false;
1461 isVShapeSolution =
false;
1462 captureFailureCounter = 0;
1463 minimumRequiredHFR = INVALID_STAR_MEASURE;
1465 starMeasureFrames.clear();
1473 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1475 if (rememberUploadMode != m_Camera->getUploadMode())
1476 m_Camera->setUploadMode(rememberUploadMode);
1479 if (m_RememberCameraFastExposure)
1481 m_RememberCameraFastExposure =
false;
1482 m_Camera->setFastExposureEnabled(
true);
1485 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1486 targetChip->abortExposure();
1495 if (m_GuidingSuspended)
1497 emit resumeGuiding();
1498 m_GuidingSuspended =
false;
1509 if (
settleTime > 0 && captureInProgress ==
false)
1511 captureTimer.start(
static_cast<int>(
settleTime * 1000));
1515 if (captureInProgress)
1517 qCWarning(
KSTARS_EKOS_FOCUS) <<
"Capture called while already in progress. Capture is ignored.";
1521 if (m_Camera ==
nullptr)
1523 appendLogText(
i18n(
"Error: No Camera detected."));
1524 checkStopFocus(
true);
1528 if (m_Camera->isConnected() ==
false)
1530 appendLogText(
i18n(
"Error: Lost connection to Camera."));
1531 checkStopFocus(
true);
1536 captureTimeout.stop();
1538 waitStarSelectTimer.stop();
1540 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1542 if (m_Camera->isBLOBEnabled() ==
false)
1544 m_Camera->setBLOBEnabled(
true);
1549 if (m_FilterWheel ==
nullptr)
1551 appendLogText(
i18n(
"Error: No Filter Wheel detected."));
1552 checkStopFocus(
true);
1555 if (m_FilterWheel->isConnected() ==
false)
1557 appendLogText(
i18n(
"Error: Lost connection to Filter Wheel."));
1558 checkStopFocus(
true);
1565 int targetPosition =
focusFilter->currentIndex() + 1;
1566 if (!inBuildOffsets)
1568 QString lockedFilter = m_FilterManager->getFilterLock(filter());
1573 if (lockedFilter !=
"--" && lockedFilter != filter())
1575 int lockedFilterIndex =
focusFilter->findText(lockedFilter);
1576 if (lockedFilterIndex >= 0)
1579 fallbackFilterPending =
true;
1580 fallbackFilterPosition = targetPosition;
1581 targetPosition = lockedFilterIndex + 1;
1586 filterPositionPending = (targetPosition != currentFilterPosition);
1587 if (filterPositionPending)
1592 FilterManager::FilterPolicy policy = (inAutoFocus) ?
1593 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY) :
1594 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY | FilterManager::OFFSET_POLICY);
1595 m_FilterManager->setFilterPosition(targetPosition, policy);
1598 else if (targetPosition !=
focusFilter->currentIndex() + 1)
1602 m_FocusView->setProperty(
"suspended", m_OpsFocusSettings->useFocusDarkFrame->isChecked());
1603 prepareCapture(targetChip);
1606 connect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1608 if (frameSettings.contains(targetChip))
1610 QVariantMap settings = frameSettings[targetChip];
1611 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
1612 settings[
"h"].toInt());
1615 frameSettings[targetChip] = settings;
1618 captureInProgress =
true;
1619 if (state() != FOCUS_PROGRESS)
1620 setState(FOCUS_PROGRESS);
1628 captureTimeout.start( (
focusExposure->value() + m_OpsFocusMechanics->focusCaptureTimeout->value()) * 1000);
1630 if (inFocusLoop ==
false)
1631 appendLogText(
i18n(
"Capturing image..."));
1635 else if (inAutoFocus)
1637 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
1643 if (m_Camera->getUploadMode() == ISD::Camera::UPLOAD_LOCAL)
1645 rememberUploadMode = ISD::Camera::UPLOAD_LOCAL;
1646 m_Camera->setUploadMode(ISD::Camera::UPLOAD_CLIENT);
1650 if (m_Camera->isFastExposureEnabled())
1652 m_RememberCameraFastExposure =
true;
1653 m_Camera->setFastExposureEnabled(
false);
1656 m_Camera->setEncodingFormat(
"FITS");
1657 targetChip->setBatchMode(
false);
1659 targetChip->setCaptureMode(FITS_FOCUS);
1660 targetChip->setFrameType(FRAME_LIGHT);
1661 targetChip->setCaptureFilter(FITS_NONE);
1663 if (isFocusISOEnabled() &&
focusISO->currentIndex() != -1 &&
1664 targetChip->getISOIndex() !=
focusISO->currentIndex())
1665 targetChip->setISOIndex(
focusISO->currentIndex());
1667 if (isFocusGainEnabled() &&
focusGain->value() != GainSpinSpecialValue)
1671bool Focus::focusIn(
int ms)
1673 if (currentPosition == absMotionMin)
1675 appendLogText(
i18n(
"At minimum focus position %1...", absMotionMin));
1682 ms = m_OpsFocusMechanics->focusTicks->value();
1683 if (currentPosition -
ms <= absMotionMin)
1685 ms = currentPosition - absMotionMin;
1686 appendLogText(
i18n(
"Moving to minimum focus position %1...", absMotionMin));
1688 return changeFocus(-
ms);
1691bool Focus::focusOut(
int ms)
1693 if (currentPosition == absMotionMax)
1695 appendLogText(
i18n(
"At maximum focus position %1...", absMotionMax));
1702 ms = m_OpsFocusMechanics->focusTicks->value();
1703 if (currentPosition +
ms >= absMotionMax)
1705 ms = absMotionMax - currentPosition;
1706 appendLogText(
i18n(
"Moving to maximum focus position %1...", absMotionMax));
1708 return changeFocus(
ms);
1713bool Focus::changeFocus(
int amount,
bool updateDir)
1719 capture(m_OpsFocusMechanics->focusSettleTime->value());
1723 if (m_Focuser ==
nullptr)
1725 appendLogText(
i18n(
"Error: No Focuser detected."));
1726 checkStopFocus(
true);
1730 if (m_Focuser->isConnected() ==
false)
1732 appendLogText(
i18n(
"Error: Lost connection to Focuser."));
1733 checkStopFocus(
true);
1737 const int newPosition = adjustLinearPosition(currentPosition, currentPosition +
amount,
1738 m_OpsFocusMechanics->focusAFOverscan->value(),
1749 m_LastFocusDirection = (
focusingOut) ? FOCUS_OUT : FOCUS_IN;
1752 m_Focuser->focusOut();
1754 m_Focuser->focusIn();
1757 m_FocusMotionTimer.start();
1765 else if (canRelMove)
1781void Focus::handleFocusMotionTimeout()
1801 qCDebug(
KSTARS_EKOS_FOCUS) <<
"handleFocusMotionTimeout() called while not in AutoFocus";
1805 m_FocusMotionTimerCounter++;
1807 if (m_FocusMotionTimerCounter > 4)
1810 appendLogText(
i18n(
"Focuser is still timing out. Aborting..."));
1811 stop(Ekos::FOCUS_ABORTED);
1814 else if (m_FocusMotionTimerCounter > 2)
1816 QString focuser = m_Focuser->getDeviceName();
1817 appendLogText(
i18n(
"Focus motion timed out (%1). Restarting focus driver %2", m_FocusMotionTimerCounter, focuser));
1818 emit focuserTimedout(focuser);
1822 Focus::reconnectFocuser(focuser);
1827 if (!changeFocus(m_LastFocusSteps - currentPosition))
1828 appendLogText(
i18n(
"Focus motion timed out (%1). Focusing to %2 steps...", m_FocusMotionTimerCounter, m_LastFocusSteps));
1831void Focus::selectImageMask()
1833 const bool useFullField = m_OpsFocusSettings->focusUseFullField->isChecked();
1835 if (m_OpsFocusSettings->focusRingMaskRB->isChecked())
1837 else if (m_OpsFocusSettings->focusMosaicMaskRB->isChecked())
1843 m_OpsFocusSettings->focusRingMaskRB->setEnabled(
useFullField);
1844 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(
useFullField);
1846 m_OpsFocusSettings->focusFullFieldInnerRadius->setEnabled(
useFullField &&
masktype == FOCUS_MASK_RING);
1847 m_OpsFocusSettings->focusFullFieldOuterRadius->setEnabled(
useFullField &&
masktype == FOCUS_MASK_RING);
1849 m_OpsFocusSettings->focusMosaicTileWidth->setEnabled(
useFullField &&
masktype == FOCUS_MASK_MOSAIC);
1850 m_OpsFocusSettings->focusSpacerLabel->setEnabled(
useFullField &&
masktype == FOCUS_MASK_MOSAIC);
1851 m_OpsFocusSettings->focusMosaicSpace->setEnabled(
useFullField &&
masktype == FOCUS_MASK_MOSAIC);
1855 m_FocusView->setImageMask(
new ImageRingMask(m_OpsFocusSettings->focusFullFieldInnerRadius->value() / 100.0,
1856 m_OpsFocusSettings->focusFullFieldOuterRadius->value() / 100.0));
1857 else if (
masktype == FOCUS_MASK_MOSAIC)
1858 m_FocusView->setImageMask(
new ImageMosaicMask(m_OpsFocusSettings->focusMosaicTileWidth->value(),
1859 m_OpsFocusSettings->focusMosaicSpace->value()));
1861 m_FocusView->setImageMask(
nullptr);
1863 checkMosaicMaskLimits();
1868void Focus::reconnectFocuser(
const QString &focuser)
1870 m_FocuserReconnectCounter++;
1872 if (m_Focuser && m_Focuser->getDeviceName() == focuser)
1874 appendLogText(
i18n(
"Attempting to reconnect focuser: %1", focuser));
1875 refreshOpticalTrain();
1876 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
1880 if (m_FocuserReconnectCounter > 12)
1883 appendLogText(
i18n(
"Cannot reconnect focuser: %1. Aborting...", focuser));
1884 stop(Ekos::FOCUS_ABORTED);
1890 reconnectFocuser(focuser);
1897 if (data->property(
"chip").
toInt() == ISD::CameraChip::GUIDE_CCD)
1902 m_FocusView->loadData(data);
1906 m_ImageData.reset();
1908 captureTimeout.stop();
1909 captureTimeoutCounter = 0;
1911 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1913 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1915 if (m_ImageData && m_OpsFocusSettings->useFocusDarkFrame->isChecked())
1917 QVariantMap settings = frameSettings[targetChip];
1918 uint16_t offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
1919 uint16_t offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
1921 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->
id(
opticalTrainCombo->currentText()),
1922 targetChip, m_ImageData,
focusExposure->value(), offsetX, offsetY);
1926 setCaptureComplete();
1930void Focus::starDetectionFinished()
1932 appendLogText(
i18n(
"Detection complete."));
1935 double hfr = INVALID_STAR_MEASURE;
1937 if (m_StarFinderWatcher.result() ==
false)
1943 if (m_OpsFocusSettings->focusUseFullField->isChecked())
1945 m_FocusView->filterStars();
1948 hfr = m_ImageData->getHFR(m_StarMeasure == FOCUS_STAR_HFR_ADJ ? HFR_ADJ_AVERAGE : HFR_AVERAGE);
1952 m_FocusView->setTrackingBoxEnabled(
true);
1957 if (starCenter.isNull() ==
false)
1958 hfr = m_ImageData->getHFR(starCenter.x(), starCenter.y());
1962 hfr = m_ImageData->getHFR(m_FocusDetection == ALGORITHM_SEP ? HFR_HIGH : HFR_MAX);
1966 hfrInProgress =
false;
1968 currentNumStars = m_ImageData->getDetectedStars();
1972 currentMeasure = currentHFR;
1975 if (m_StarMeasure == FOCUS_STAR_NUM_STARS)
1977 currentMeasure = currentNumStars;
1978 currentWeight = 1.0;
1980 else if (m_StarMeasure == FOCUS_STAR_FWHM)
1982 getFWHM(m_ImageData->getStarCenters(), ¤tFWHM, ¤tWeight);
1983 currentMeasure = currentFWHM;
1985 else if (m_StarMeasure == FOCUS_STAR_FOURIER_POWER)
1987 getFourierPower(¤tFourierPower, ¤tWeight);
1988 currentMeasure = currentFourierPower;
1992 currentMeasure = currentHFR;
1994 std::vector<double> hfrs(stars.size());
1995 std::transform(stars.constBegin(), stars.constEnd(), hfrs.begin(), [](Edge * edge)
1999 currentWeight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), hfrs);
2002 setCurrentMeasure();
2006void Focus::getFWHM(
const QList<Edge *> &stars,
double *FWHM,
double *weight)
2008 *FWHM = INVALID_STAR_MEASURE;
2013 switch (m_ImageData->getStatistics().dataType)
2016 focusFWHM->processFWHM(
reinterpret_cast<uint8_t
const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2020 focusFWHM->processFWHM(
reinterpret_cast<short const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2024 focusFWHM->processFWHM(
reinterpret_cast<unsigned short const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM,
2029 focusFWHM->processFWHM(
reinterpret_cast<long const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2033 focusFWHM->processFWHM(
reinterpret_cast<unsigned long const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2037 focusFWHM->processFWHM(
reinterpret_cast<float const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2041 focusFWHM->processFWHM(
reinterpret_cast<long long const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2045 focusFWHM->processFWHM(
reinterpret_cast<double const *
>(
imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2049 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2050 " Cannot calc FWHM";
2063 switch (m_ImageData->getStatistics().dataType)
2066 focusFourierPower->processFourierPower(
reinterpret_cast<uint8_t
const *
>(
imageBuffer), m_ImageData,
2071 focusFourierPower->processFourierPower(
reinterpret_cast<short const *
>(
imageBuffer), m_ImageData,
2076 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned short const *
>(
imageBuffer), m_ImageData,
2081 focusFourierPower->processFourierPower(
reinterpret_cast<long const *
>(
imageBuffer), m_ImageData,
2086 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned long const *
>(
imageBuffer), m_ImageData,
2091 focusFourierPower->processFourierPower(
reinterpret_cast<float const *
>(
imageBuffer), m_ImageData,
2096 focusFourierPower->processFourierPower(
reinterpret_cast<long long const *
>(
imageBuffer), m_ImageData,
2101 focusFourierPower->processFourierPower(
reinterpret_cast<double const *
>(
imageBuffer), m_ImageData,
2106 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2107 " Cannot calc Fourier Power";
2112double Focus::calculateStarWeight(
const bool useWeights,
const std::vector<double> values)
2114 if (!useWeights || values.size() <= 0)
2119 return Mathematics::RobustStatistics::ComputeWeight(m_ScaleCalc, values);
2122void Focus::analyzeSources()
2124 appendLogText(
i18n(
"Detecting sources..."));
2125 hfrInProgress =
true;
2128 extractionSettings[
"optionsProfileIndex"] = m_OpsFocusProcess->focusSEPProfile->currentIndex();
2134 if (m_OpsFocusSettings->focusUseFullField->isChecked())
2136 m_FocusView->setTrackingBoxEnabled(
false);
2138 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2139 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2141 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection));
2145 QRect searchBox = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2149 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection,
searchBox));
2154 m_FocusView->setTrackingBoxEnabled(
false);
2158 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2159 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2162 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection,
searchBox));
2174 samples.erase(std::remove_if(samples.begin(), samples.end(), [](
const double measure)
2176 return measure == INVALID_STAR_MEASURE;
2180 if (!samples.isEmpty())
2182 currentMeasure = Mathematics::RobustStatistics::ComputeLocation(
2183 Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, std::vector<double>(samples.begin(), samples.end()));
2185 switch(m_StarMeasure)
2187 case FOCUS_STAR_HFR:
2188 case FOCUS_STAR_HFR_ADJ:
2189 currentHFR = currentMeasure;
2191 case FOCUS_STAR_FWHM:
2192 currentFWHM = currentMeasure;
2194 case FOCUS_STAR_NUM_STARS:
2195 currentNumStars = currentMeasure;
2197 case FOCUS_STAR_FOURIER_POWER:
2198 currentFourierPower = currentMeasure;
2209 int framesCount = m_OpsFocusProcess->focusFramesCount->value();
2210 if ((minimumRequiredHFR > 0) || (inAutoFocus && !inBuildOffsets && !inScanStartPos && m_FocusAlgorithm == FOCUS_LINEAR1PASS
2211 && linearFocuser && !linearFocuser->isInFirstPass()))
2213 framesCount = m_OpsFocusProcess->focusHFRFramesCount->value();
2219 const AutofocusFailReason failCode,
const QString failCodeInfo)
2227 KSNotification::event(
QLatin1String(
"FocusSuccessful"),
i18n(
"Autofocus operation completed successfully"),
2228 KSNotification::Focus);
2230 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && curveFitting !=
nullptr)
2231 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2232 m_OpsFocusProcess->focusUseWeights->isChecked(),
2233 curveFitting->serialize(), linearFocuser->getTextStatus(R2));
2235 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2236 m_OpsFocusProcess->focusUseWeights->isChecked());
2240 KSNotification::event(
QLatin1String(
"FocusFailed"),
i18n(
"Autofocus operation failed"),
2241 KSNotification::Focus, KSNotification::Alert);
2242 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2253 m_FilterManager->setFilterAbsoluteFocusDetails(
focusFilter->currentIndex(), currentPosition,
2254 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
2258 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Settled. State:" << Ekos::getFocusStatusString(state());
2261 if (fallbackFilterPending)
2264 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY) :
2265 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY | FilterManager::OFFSET_POLICY);
2266 m_FilterManager->setFilterPosition(fallbackFilterPosition, policy);
2269 emit newStatus(state());
2273 m_FilterManager->autoFocusComplete(state(), currentPosition, m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
2278QString Focus::getAnalyzeData()
2282 for (
int i = 0; i < plot_position.size(); ++i)
2285 .arg(i == 0 ?
"" :
"|" )
2294void Focus::completeFocusProcedure(FocusState
completionState, AutofocusFailReason failCode,
QString failCodeInfo,
2300 updatePlotPosition();
2305 emit redrawHFRPlot(polynomialFit.get(), currentPosition, currentHFR);
2307 appendLogText(
i18np(
"Focus procedure completed after %1 iteration.",
2308 "Focus procedure completed after %1 iterations.", plot_position.count()));
2310 setLastFocusTemperature();
2312 resetAdaptiveFocus(m_OpsFocusSettings->focusAdaptive->isChecked());
2316 qCInfo(
KSTARS_EKOS_FOCUS) <<
"Autofocus values: position," << currentPosition <<
", temperature,"
2317 << m_LastSourceAutofocusTemperature <<
", filter," <<
filter()
2318 <<
", HFR," << currentHFR <<
", altitude," << m_LastSourceAutofocusAlt;
2320 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL)
2323 plot_position.append(currentPosition);
2324 plot_value.append(currentHFR);
2325 plot_weight.append(1.0);
2326 plot_outlier.append(
false);
2329 appendFocusLogText(
QString(
"%1, %2, %3, %4, %5\n")
2340 else if (canAbsMove && initialFocuserAbsPosition >= 0 && resetFocusIteration <= MAXIMUM_RESET_ITERATIONS
2341 && m_RestartState != RESTART_ABORT)
2344 bool const retry_focusing = m_RestartState == RESTART_NONE && ++resetFocusIteration < MAXIMUM_RESET_ITERATIONS;
2349 m_RestartState = RESTART_NOW;
2358 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2370 m_RestartState = RESTART_ABORT;
2376 resetFocusIteration = 0;
2383 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot)
2384 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
2387 int const settleTime = m_GuidingSuspended ? m_OpsFocusSettings->focusGuideSettleTime->value() : 0;
2401 appendLogText(
i18n(
"Settling complete."));
2405void Focus::resetFocuser()
2408 if (m_Focuser && m_Focuser->isConnected() && initialFocuserAbsPosition >= 0)
2411 if (currentPosition == initialFocuserAbsPosition)
2414 appendLogText(
i18n(
"Autofocus failed, moving back to initial focus position %1.", initialFocuserAbsPosition));
2415 changeFocus(initialFocuserAbsPosition - currentPosition);
2420void Focus::setCurrentMeasure()
2423 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Focus newFITS #" << starMeasureFrames.count() + 1 <<
": Current HFR " << currentHFR <<
2425 << (starSelected ? 1 : currentNumStars);
2428 if (appendMeasure(currentMeasure))
2433 else starMeasureFrames.clear();
2438 emit newHFR(currentHFR, currentPosition, inAutoFocus);
2440 emit newHFR(currentHFR, -1, inAutoFocus);
2443 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2444 if (m_StarMeasure == FOCUS_STAR_FWHM)
2445 FWHMOut->setText(
QString(
"%1").arg(currentFWHM * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2446 starsOut->setText(
QString(
"%1").arg(m_ImageData->getDetectedStars()));
2450 if (lastHFR == INVALID_STAR_MEASURE)
2451 appendLogText(
i18n(
"FITS received. No stars detected."));
2457 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && isVShapeSolution)
2459 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
2470 if (starCenter.isNull() ==
false && (inAutoFocus || minimumRequiredHFR >= 0))
2473 starSelected =
true;
2477 syncTrackingBoxPosition();
2491 if (currentHFR > maxHFR)
2492 maxHFR = currentHFR;
2500 if (inFocusLoop || (inAutoFocus && ! isPositionBased()))
2502 int pos = plot_position.empty() ? 1 : plot_position.last() + 1;
2503 addPlotPosition(pos, currentHFR);
2515 m_FocusView->updateFrame();
2519 if (m_abInsOn && !inScanStartPos)
2520 calculateAbInsData();
2524void Focus::saveFocusFrame()
2526 if (inAutoFocus && Options::focusLogging() && Options::saveFocusImages())
2531 now.toString(
"yyyy-MM-dd"));
2536 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && !inScanStartPos && linearFocuser)
2538 const int currentStep = linearFocuser->currentStep() + 1;
2539 detail =
QString(
"_%1_%2_%3").
arg(m_AFRun).
arg(currentStep).
arg(starMeasureFrames.count());
2544 QString name =
"autofocus_frame_" +
now.toString(
"HH-mm-ss") + detail +
".fits";
2546 m_ImageData->saveImage(filename);
2550void Focus::calculateAbInsData()
2552 ImageMosaicMask *
mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().get());
2554 auto stars = m_ImageData->getStarCenters();
2557 for (
int star = 0; star < stars.count(); star++)
2559 const int x = stars[star]->x;
2560 const int y = stars[star]->y;
2561 for (
int tile = 0; tile < NUM_TILES; tile++)
2573 for (
int tile = 0; tile <
tileStars.count(); tile++)
2577 if (m_StarMeasure == FOCUS_STAR_NUM_STARS)
2582 else if (m_StarMeasure == FOCUS_STAR_FWHM)
2586 else if (m_StarMeasure == FOCUS_STAR_FOURIER_POWER)
2588 getFourierPower(&
measure, &weight, tile);
2593 std::vector<double>
HFRs;
2595 for (
int star = 0; star <
tileStars[tile].count(); star++)
2599 measure = Mathematics::RobustStatistics::ComputeLocation(Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING,
HFRs, 2);
2600 weight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(),
HFRs);
2603 m_abInsMeasure[tile].append(
measure);
2604 m_abInsWeight[tile].append(weight);
2605 m_abInsNumStars[tile].append(
tileStars[tile].count());
2607 if (!linearFocuser->isInFirstPass())
2613 if (m_StarMeasure != FOCUS_STAR_FOURIER_POWER)
2617 for (
int star = 0; star <
tileStars[tile].count(); star++)
2629 m_abInsPosition.append(currentPosition);
2632void Focus::setCaptureComplete()
2634 DarkLibrary::Instance()->disconnect(
this);
2637 syncTrackingBoxPosition();
2640 if (inFocusLoop ==
false)
2641 appendLogText(
i18n(
"Image received."));
2643 if (captureInProgress && inFocusLoop ==
false && inAutoFocus ==
false)
2644 m_Camera->setUploadMode(rememberUploadMode);
2646 if (m_RememberCameraFastExposure && inFocusLoop ==
false && inAutoFocus ==
false)
2648 m_RememberCameraFastExposure =
false;
2649 m_Camera->setFastExposureEnabled(
true);
2652 captureInProgress =
false;
2654 checkMosaicMaskLimits();
2657 emit newImage(m_FocusView);
2659 emit newStarPixmap(m_FocusView->getTrackingBoxPixmap(10));
2665 if (inFocusLoop ==
false || (inFocusLoop && (m_FocusView->isTrackingBoxEnabled()
2666 || m_OpsFocusSettings->focusUseFullField->isChecked())))
2672void Focus::setHFRComplete()
2682 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
2685 int subBinX = 1, subBinY = 1;
2686 if (!targetChip->getBinning(&subBinX, &subBinY))
2687 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Warning: target chip is reporting no binning property, using 1x1.";
2694 if (m_OpsFocusSettings->focusUseFullField->isChecked() ==
false && starCenter.isNull())
2696 int x = 0, y = 0, w = 0, h = 0;
2699 if (frameSettings.contains(targetChip))
2701 QVariantMap settings = frameSettings[targetChip];
2702 x = settings[
"x"].toInt();
2703 y = settings[
"y"].toInt();
2704 w = settings[
"w"].toInt();
2705 h = settings[
"h"].toInt();
2709 targetChip->getFrame(&x, &y, &w, &h);
2712 if (m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
2719 appendLogText(
i18n(
"Failed to automatically select a star. Please select a star manually."));
2722 m_FocusView->setTrackingBox(
QRect(w - m_OpsFocusSettings->focusBoxSize->value() / (subBinX * 2),
2723 h - m_OpsFocusSettings->focusBoxSize->value() / (subBinY * 2),
2724 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
2725 m_FocusView->setTrackingBoxEnabled(
true);
2728 setState(Ekos::FOCUS_WAITING);
2731 waitStarSelectTimer.start();
2739 starCenter.setZ(subBinX);
2740 starSelected =
true;
2741 syncTrackingBoxPosition();
2744 if (subFramed ==
false && isFocusSubFrameEnabled() && m_OpsFocusSettings->focusSubFrame->isChecked())
2746 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
2749 int subW = offset * 2 * subBinX;
2750 int subH = offset * 2 * subBinY;
2760 if ((subW + subX) >
maxW)
2762 if ((subH + subY) >
maxH)
2767 QVariantMap settings = frameSettings[targetChip];
2768 settings[
"x"] = subX;
2769 settings[
"y"] = subY;
2770 settings[
"w"] = subW;
2771 settings[
"h"] = subH;
2772 settings[
"binx"] = subBinX;
2773 settings[
"biny"] = subBinY;
2775 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << subX <<
"Y:" << subY <<
"W:" << subW <<
"H:" << subH <<
"binX:" <<
2776 subBinX <<
"binY:" << subBinY;
2780 frameSettings[targetChip] = settings;
2783 starCenter.setX(subW / (2 * subBinX));
2784 starCenter.setY(subH / (2 * subBinY));
2785 starCenter.setZ(subBinX);
2789 m_FocusView->setFirstLoad(
true);
2800 starCenter.setZ(subBinX);
2813 appendLogText(
i18n(
"Capture complete. Select a star to focus."));
2815 starSelected =
false;
2819 int subBinX = 1, subBinY = 1;
2820 targetChip->getBinning(&subBinX, &subBinY);
2822 m_FocusView->setTrackingBox(
QRect((w - m_OpsFocusSettings->focusBoxSize->value()) / (subBinX * 2),
2823 (h - m_OpsFocusSettings->focusBoxSize->value()) / (2 * subBinY),
2824 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
2825 m_FocusView->setTrackingBoxEnabled(
true);
2828 setState(Ekos::FOCUS_WAITING);
2831 waitStarSelectTimer.start();
2837 if (minimumRequiredHFR >= 0)
2840 if (currentHFR == INVALID_STAR_MEASURE)
2842 if (noStarCount++ < MAX_RECAPTURE_RETRIES)
2844 appendLogText(
i18n(
"No stars detected while testing HFR, capturing again..."));
2846 if (noStarCount == MAX_RECAPTURE_RETRIES)
2855 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
2860 else if (currentHFR > minimumRequiredHFR)
2862 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is above required minimum HFR:" << minimumRequiredHFR <<
2863 ". Starting AutoFocus...";
2866 minimumRequiredHFR = INVALID_STAR_MEASURE;
2867 runAutoFocus(AutofocusReason::FOCUS_HFR_CHECK, reasonInfo);
2872 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is below required minimum HFR:" << minimumRequiredHFR <<
2873 ". Autofocus successful.";
2874 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
2882 if (inAutoFocus ==
false)
2886 if (state() != Ekos::FOCUS_IDLE)
2887 setState(Ekos::FOCUS_IDLE);
2894 if (state() != Ekos::FOCUS_PROGRESS)
2895 setState(Ekos::FOCUS_PROGRESS);
2900 else if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
2902 else if (canAbsMove || canRelMove)
2910QString Focus::getyAxisLabel(StarMeasure starMeasure)
2913 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
2917 switch (starMeasure)
2919 case FOCUS_STAR_HFR:
2921 case FOCUS_STAR_HFR_ADJ:
2923 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
2925 case FOCUS_STAR_FWHM:
2927 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
2929 case FOCUS_STAR_NUM_STARS:
2932 case FOCUS_STAR_FOURIER_POWER:
2933 str =
"Fourier Power";
2942void Focus::clearDataPoints()
2945 polynomialFit.reset();
2946 plot_position.
clear();
2948 plot_weight.clear();
2949 plot_outlier.clear();
2950 isVShapeSolution =
false;
2951 m_abInsPosition.clear();
2952 m_abInsTileCenterOffset.clear();
2953 if (m_abInsMeasure.count() != NUM_TILES)
2955 m_abInsMeasure.resize(NUM_TILES);
2956 m_abInsWeight.resize(NUM_TILES);
2957 m_abInsNumStars.resize(NUM_TILES);
2961 for (
int i = 0; i < m_abInsMeasure.count(); i++)
2963 m_abInsMeasure[i].clear();
2964 m_abInsWeight[i].clear();
2965 m_abInsNumStars[i].clear();
2969 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
2970 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(),
2971 inFocusLoop ==
false && isPositionBased());
2974bool Focus::autoFocusChecks()
2976 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
2978 appendLogText(
i18n(
"Autofocus failed: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
2979 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
2984 if (currentHFR == INVALID_STAR_MEASURE)
2986 if (noStarCount < MAX_RECAPTURE_RETRIES)
2989 appendLogText(
i18n(
"No stars detected, capturing again..."));
2993 else if (m_FocusAlgorithm == FOCUS_LINEAR)
2995 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
2998 else if(!m_OpsFocusProcess->focusDonut->isChecked())
3001 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
3002 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3012void Focus::plotLinearFocus()
3021 linearFocuser->getMeasurements(&positions, &values, &weights);
3022 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3030 if (positions.size() > 1 && positions.size() ==
lastPositions.size() + 1)
3033 for (
int i = 0; i < positions.size() - 1; ++i)
3046 emit newHFRPlotPosition(
static_cast<double>(positions.last()), values.last(), (
pow(weights.last(), -0.5)),
3050 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3051 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, params.useWeights,
plt);
3052 for (
int i = 0; i < positions.size(); ++i)
3053 emit newHFRPlotPosition(
static_cast<double>(positions[i]), values[i], (
pow(weights.last(), -0.5)),
3058 if (values.size() > 3)
3065 double searchMin = std::max(params.minPositionAllowed, params.startPosition - params.maxTravel);
3066 double searchMax = std::min(params.maxPositionAllowed, params.startPosition + params.maxTravel);
3068 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3069 if (m_FocusAlgorithm == FOCUS_LINEAR || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3073 polynomialFit.reset(
new PolynomialFit(2, pass1Positions, pass1Values));
3077 emit drawPolynomial(polynomialFit.get(),
true,
true,
plt);
3081 if (linearFocuser->isDone())
3082 emit minimumFound(-1, -1,
plt);
3089 emit drawPolynomial(polynomialFit.get(),
false,
false,
plt);
3090 emit minimumFound(-1, -1,
plt);
3097 params.optimisationDirection))
3099 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3100 emit drawCurve(curveFitting.get(),
true,
true,
plt);
3108 emit drawCurve(curveFitting.get(),
false,
false,
plt);
3109 emit minimumFound(-1, -1,
plt);
3115 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
3117 emit setTitle(linearFocuser->getTextStatus(R2));
3123CurveFitting::FittingGoal Focus::getGoal(
int numSteps)
3126 if (m_FocusWalk == FOCUS_WALK_CLASSIC)
3127 return CurveFitting::FittingGoal::STANDARD;
3130 return (numSteps >= m_OpsFocusMechanics->focusNumSteps->value()) ? CurveFitting::FittingGoal::BEST :
3131 CurveFitting::FittingGoal::STANDARD;
3137void Focus::plotLinearFinalUpdates()
3140 if (!m_OpsFocusProcess->focusRefineCurveFit->isChecked())
3143 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3144 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3146 emit finalUpdates(linearFocuser->getTextStatus(R2),
plt);
3156 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3157 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3159 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3160 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(),
plt);
3162 for (
int i = 0; i < pass1Positions.size(); ++i)
3163 emit newHFRPlotPosition(
static_cast<double>(pass1Positions[i]), pass1Values[i], (
pow(pass1Weights[i], -0.5)),
3164 pass1Outliers[i], params.initialStepSize,
plt);
3166 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3167 emit drawCurve(curveFitting.get(),
true,
true,
false);
3170 emit minimumFound(linearFocuser->solution(), linearFocuser->solutionValue(),
plt);
3172 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3173 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3175 emit setTitle(linearFocuser->getTextStatus(R2),
plt);
3179void Focus::startAberrationInspector()
3182 AberrationInspector::abInsData data;
3184 ImageMosaicMask *
mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().get());
3187 appendLogText(
i18n(
"Unable to launch Aberration Inspector run %1...", m_abInsRun));
3192 data.run = ++m_abInsRun;
3193 data.curveFit = m_CurveFit;
3194 data.useWeights = m_OpsFocusProcess->focusUseWeights->isChecked();
3195 data.optDir = m_OptDir;
3196 data.sensorWidth = m_CcdWidth;
3197 data.sensorHeight = m_CcdHeight;
3198 data.pixelSize = m_CcdPixelSizeX;
3199 data.tileWidth =
mosaicmask->tiles()[0].width();
3200 data.focuserStepMicrons = m_CFZUI->focusCFZStepSize->value();
3201 data.yAxisLabel = getyAxisLabel(m_StarMeasure);
3202 data.starUnits = getStarUnits(m_StarMeasure, m_StarUnits);
3203 data.cfzSteps = m_cfzSteps;
3204 data.isPositionBased = isPositionBased();
3207 appendLogText(
i18n(
"Launching Aberration Inspector run %1...", m_abInsRun));
3209 m_abInsNumStars, m_abInsTileCenterOffset));
3215void Focus::scanStartPos()
3218 if (currentHFR == INVALID_STAR_MEASURE)
3220 if (noStarCount < MAX_RECAPTURE_RETRIES)
3223 appendLogText(
i18n(
"No stars detected, capturing again..."));
3230 appendLogText(
i18n(
"Failed to detect any stars. Aborting..."));
3231 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3237 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3239 appendLogText(
i18n(
"Scan Start Pos: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3240 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3245 m_scanPosition.push_back(currentPosition);
3246 m_scanMeasure.push_back(currentMeasure);
3249 const int step = m_scanPosition.size();
3250 const int maxSteps = m_OpsFocusProcess->focusScanDatapoints->value();
3251 const int stepSize = m_OpsFocusMechanics->focusTicks->value() * m_OpsFocusProcess->focusScanStepSizeFactor->value();
3252 emit newHFRPlotPosition(
static_cast<double>(currentPosition), currentMeasure,
pow(currentWeight, -0.5),
false, stepSize,
3258 deltaPos = step * stepSize * std::pow(-1, step + 1);
3263 auto it = std::min_element(std::begin(m_scanMeasure), std::end(m_scanMeasure));
3264 auto min = std::distance(std::begin(m_scanMeasure),
it);
3265 if (min >= m_OpsFocusProcess->focusScanDatapoints->value() - 2)
3268 deltaPos = m_scanPosition[min] - currentPosition;
3269 m_scanPosition.clear();
3270 m_scanMeasure.clear();
3276 const int initialPosition = m_scanPosition[min];
3277 setupLinearFocuser(initialPosition);
3278 inScanStartPos =
false;
3280 deltaPos = linearRequestedPosition - currentPosition;
3281 emit setTitle(
QString(
i18n(
"Scan Start Position %1 Found", initialPosition)),
true);
3282 appendLogText(
i18n(
"Scan Start Position %1 found", initialPosition));
3286 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3289void Focus::autoFocusLinear()
3291 if (!autoFocusChecks())
3294 if (!canAbsMove && !canRelMove && canTimerMove)
3297 if (linearRequestedPosition != currentPosition)
3300 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Linear: warning, changing position " << currentPosition <<
" to "
3301 << linearRequestedPosition;
3303 currentPosition = linearRequestedPosition;
3309 && m_OpsFocusProcess->focusFramesCount->value() == 1;
3312 linearRequestedPosition = linearFocuser->newMeasurement(currentPosition, currentMeasure, currentWeight,
focusStars);
3313 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser->isDone() && linearFocuser->solution() != -1)
3316 plotLinearFinalUpdates();
3318 startAberrationInspector();
3324 if (linearFocuser->isDone())
3326 if (linearFocuser->solution() != -1)
3330 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3332 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3333 else if (R2 >= m_OpsFocusProcess->focusR2Limit->value())
3336 m_OpsFocusProcess->focusR2Limit->value());
3337 completeFocusProcedure(Ekos::FOCUS_COMPLETE, FOCUS_FAIL_NONE,
"",
false);
3340 else if (R2Retries == 0)
3343 appendLogText(
i18n(
"Curve Fit check failed R2=%1 focusR2Limit=%2 retrying...", R2,
3344 m_OpsFocusProcess->focusR2Limit->value()));
3347 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_R2, failCodeInfo,
false);
3353 appendLogText(
i18n(
"Curve Fit check failed again R2=%1 focusR2Limit=%2 but continuing...", R2,
3354 m_OpsFocusProcess->focusR2Limit->value()));
3355 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3362 AutofocusFailReason failCode = linearFocuser->getFailCode();
3363 appendLogText(
i18n(
"Linear autofocus algorithm aborted: %1", AutofocusFailReasonStr[failCode]));
3364 completeFocusProcedure(Ekos::FOCUS_ABORTED, failCode,
"",
false);
3370 const int delta = linearRequestedPosition - currentPosition;
3372 if (!changeFocus(delta))
3373 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE,
"",
false);
3379void Focus::autoFocusAbs()
3385 double targetPosition = 0;
3392 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Current HFR: " << currentHFR <<
" Current Position: " << currentPosition;
3398 appendLogText(
i18n(
"FITS received. HFR %1 @ %2. Delta (%3%)",
HFRText, currentPosition,
deltaTxt));
3400 appendLogText(
i18n(
"FITS received. HFR %1 @ %2.",
HFRText, currentPosition));
3402 if (!autoFocusChecks())
3405 addPlotPosition(currentPosition, currentHFR);
3407 switch (m_LastFocusDirection)
3410 lastHFR = currentHFR;
3411 initialFocuserAbsPosition = currentPosition;
3423 if (absMotionMax < currentPosition + pulseDuration)
3425 if (currentPosition < absMotionMax)
3427 pulseDuration = absMotionMax - currentPosition;
3432 m_LastFocusDirection = FOCUS_IN;
3435 else if (currentPosition + pulseDuration < absMotionMin)
3437 if (absMotionMin < currentPosition)
3439 pulseDuration = currentPosition - absMotionMin;
3444 m_LastFocusDirection = FOCUS_OUT;
3448 m_LastFocusDirection = (pulseDuration > 0) ? FOCUS_OUT : FOCUS_IN;
3449 if (!changeFocus(pulseDuration,
false))
3450 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3457 fabs(currentHFR -
minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
3459 if (absIterations <= 2)
3461 QString message =
i18n(
"Change in HFR is too small. Try increasing the step size or decreasing the tolerance.");
3462 appendLogText(message);
3463 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3464 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_SMALL_HFR);
3466 else if (noStarCount > 0)
3468 QString message =
i18n(
"Failed to detect focus star in frame. Capture and select a focus star.");
3469 appendLogText(message);
3470 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3471 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3475 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3479 else if (currentHFR < lastHFR)
3488 fabs(currentHFR - lastHFR) > 0.1)
3494 double factor = std::max(1.0, HFRDec / 2.0);
3495 if (m_LastFocusDirection == FOCUS_IN)
3496 targetPosition = currentPosition - (pulseDuration * factor);
3498 targetPosition = currentPosition + (pulseDuration * factor);
3500 qCDebug(
KSTARS_EKOS_FOCUS) <<
"current Position" << currentPosition <<
" targetPosition " << targetPosition;
3502 lastHFR = currentHFR;
3519 if (plot_position.count() >= 2)
3521 plot_position.remove(plot_position.count() - 2);
3522 plot_value.remove(plot_value.count() - 2);
3536 lastHFR = currentHFR;
3549 if (m_LastFocusDirection == FOCUS_IN)
3560 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot_position.count() > 4)
3562 polynomialFit.reset(
new PolynomialFit(2, 5, plot_position, plot_value));
3563 double a = *std::min_element(plot_position.constBegin(), plot_position.constEnd());
3564 double b = *std::max_element(plot_position.constBegin(), plot_position.constEnd());
3567 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Found Minimum?" << (isVShapeSolution ?
"Yes" :
"No");
3568 if (isVShapeSolution)
3575 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
3580 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
false);
3590 targetPosition = currentPosition +
lastDelta;
3592 targetPosition = currentPosition + pulseDuration;
3594 else if (isVShapeSolution ==
false)
3598 if (m_LastFocusDirection == FOCUS_OUT)
3599 targetPosition =
minHFRPos - pulseDuration / 2;
3601 targetPosition =
minHFRPos + pulseDuration / 2;
3611 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus in limit " << targetPosition;
3616 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus out limit " << targetPosition;
3620 if (targetPosition < absMotionMin)
3621 targetPosition = absMotionMin;
3622 else if (targetPosition > absMotionMax)
3623 targetPosition = absMotionMax;
3626 if (targetPosition == currentPosition)
3630 if (targetPosition ==
minHFRPos || isVShapeSolution)
3632 appendLogText(
"Stopping at minimum recorded HFR position.");
3633 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3637 QString message =
i18n(
"Focuser cannot move further, device limits reached. Autofocus aborted.");
3638 appendLogText(message);
3639 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3640 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3648 QString message =
i18n(
"Unstable fluctuations. Try increasing initial step size or exposure time.");
3649 appendLogText(message);
3650 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3651 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FLUCTUATIONS);
3658 QString message =
i18n(
"Deadlock reached. Please try again with different settings.");
3659 appendLogText(message);
3660 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3661 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_DEADLOCK);
3666 if (
fabs(targetPosition - initialFocuserAbsPosition) > m_OpsFocusMechanics->focusMaxTravel->value())
3668 int minTravelLimit =
qMax(0.0, initialFocuserAbsPosition - m_OpsFocusMechanics->focusMaxTravel->value());
3669 int maxTravelLimit =
qMin(absMotionMax, initialFocuserAbsPosition + m_OpsFocusMechanics->focusMaxTravel->value());
3684 qCDebug(
KSTARS_EKOS_FOCUS) <<
"targetPosition (" << targetPosition <<
") - initHFRAbsPos ("
3685 << initialFocuserAbsPosition <<
") exceeds maxTravel distance of " << m_OpsFocusMechanics->focusMaxTravel->value();
3687 QString message =
i18n(
"Maximum travel limit reached. Autofocus aborted.");
3688 appendLogText(message);
3689 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3690 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3696 lastDelta = (targetPosition - currentPosition);
3703 double limitedDelta =
qMax(-1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(),
3704 qMin(1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(),
lastDelta));
3707 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Limited delta to maximum permitted single step " <<
3708 m_OpsFocusMechanics->focusMaxSingleStep->value();
3713 m_LastFocusDirection = (
lastDelta > 0) ? FOCUS_OUT : FOCUS_IN;
3715 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3721void Focus::addPlotPosition(
int pos,
double value,
bool plot)
3723 plot_position.append(pos);
3724 plot_value.append(value);
3726 emit newHFRPlotPosition(
static_cast<double>(pos), value, 1.0,
false, pulseDuration);
3732void Focus::updatePlotPosition()
3734 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3740 plot_position.clear();
3742 plot_weight.clear();
3743 plot_outlier.clear();
3747 linearFocuser->getPass1Measurements(&positions, &plot_value, &plot_weight, &plot_outlier);
3748 plot_position.clear();
3749 for (
int i = 0; i < positions.count(); i++)
3750 plot_position.append(positions[i]);
3753 if (linearFocuser && linearFocuser->isDone() && linearFocuser->solution() != -1)
3755 plot_position.append(linearFocuser->solution());
3756 plot_value.append(linearFocuser->solutionValue());
3757 plot_weight.append(linearFocuser->solutionWeight());
3758 plot_outlier.append(
false);
3762 else if (m_FocusAlgorithm == FOCUS_LINEAR)
3765 linearFocuser->getMeasurements(&positions, &plot_value, &plot_weight);
3766 plot_position.clear();
3767 plot_outlier.clear();
3768 for (
int i = 0; i < positions.count(); i++)
3770 plot_position.append(positions[i]);
3772 plot_outlier.append(
false);
3778 for (
int i = 0; i < plot_position.count(); i++)
3780 plot_weight.append(1.0);
3781 plot_outlier.append(
false);
3786void Focus::autoFocusRel()
3788 static int noStarCount = 0;
3789 static double minHFR = 1e6;
3796 if (pulseDuration <= MINIMUM_PULSE_TIMER)
3798 appendLogText(
i18n(
"Autofocus failed to reach proper focus. Try adjusting the tolerance value."));
3799 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_TOLERANCE);
3804 if (currentHFR == INVALID_STAR_MEASURE)
3806 if (noStarCount < MAX_RECAPTURE_RETRIES)
3809 appendLogText(
i18n(
"No stars detected, capturing again..."));
3813 else if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3815 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
3818 else if(!m_OpsFocusProcess->focusDonut->isChecked())
3821 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
3822 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3829 switch (m_LastFocusDirection)
3832 lastHFR = currentHFR;
3834 m_LastFocusDirection = FOCUS_IN;
3835 changeFocus(-pulseDuration,
false);
3840 if (
fabs(currentHFR -
minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
3842 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3844 else if (currentHFR < lastHFR)
3849 lastHFR = currentHFR;
3850 changeFocus(m_LastFocusDirection == FOCUS_IN ? -pulseDuration : pulseDuration,
false);
3857 lastHFR = currentHFR;
3861 pulseDuration *= 0.75;
3863 if (!changeFocus(m_LastFocusDirection == FOCUS_IN ? pulseDuration : -pulseDuration,
false))
3864 completeFocusProcedure(
Ekos::FOCUS_ABORTED,
Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3867 m_LastFocusDirection = (m_LastFocusDirection == FOCUS_IN) ? FOCUS_OUT : FOCUS_IN;
3873void Focus::autoFocusProcessPositionChange(IPState state)
3881 if (focuserAdditionalMovement > 0)
3883 int temp = focuserAdditionalMovement;
3884 focuserAdditionalMovement = 0;
3887 .
arg(temp).
arg(m_OpsFocusMechanics->focusOverscanDelay->value());
3889 QTimer::singleShot(m_OpsFocusMechanics->focusOverscanDelay->value() * 1000,
this, [
this, temp]()
3891 if (!changeFocus(-temp, focuserAdditionalMovementUpdateDir))
3893 appendLogText(i18n(
"Focuser error, check INDI panel."));
3894 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3898 else if (inAutoFocus)
3901 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3902 if (
abs(linearRequestedPosition - currentPosition) > m_OpsFocusMechanics->focusTicks->value())
3904 .
arg(linearRequestedPosition).
arg(currentPosition);
3907 currentPosition).
arg(m_OpsFocusMechanics->focusSettleTime->value());
3909 if (m_OpsFocusProcess->focusDonut->isChecked())
3910 donutTimeDilation();
3911 capture(m_OpsFocusMechanics->focusSettleTime->value());
3916 appendLogText(
i18n(
"Focuser error, check INDI panel."));
3917 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
3921 QString(
"autoFocusProcessPositionChange called with state %1 (%2), focuserAdditionalMovement=%3, inAutoFocus=%4, captureInProgress=%5, currentPosition=%6")
3923 .
arg(currentPosition);
3927void Focus::donutTimeDilation()
3929 if (m_OpsFocusProcess->focusTimeDilation->value() == 1.0 || inScanStartPos)
3933 const double centre = (m_OpsFocusMechanics->focusNumSteps->value() + 1.0) / 2.0;
3935 const int currentStep = linearFocuser->currentStep() + 1;
3938 distance = std::abs(
centre - currentStep);
3942 double multiplier =
distance / (
centre - 1.0) * m_OpsFocusProcess->focusTimeDilation->value();
3943 multiplier = std::max(multiplier, 1.0);
3944 const double exposure = multiplier * m_donutOrigExposure;
3946 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Donut time dilation for point " << currentStep <<
" from " << m_donutOrigExposure <<
" to "
3951void Focus::updateProperty(INDI::Property
prop)
3953 if (m_Focuser ==
nullptr ||
prop.getType() !=
INDI_NUMBER ||
prop.getDeviceName() != m_Focuser->getDeviceName())
3962 if (
nvp->isNameMatch(
"FOCUS_BACKLASH_STEPS"))
3964 m_OpsFocusMechanics->focusBacklash->setValue(
nvp->np[0].value);
3968 if (
nvp->isNameMatch(
"ABS_FOCUS_POSITION"))
3973 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
3975 if (m_DebugFocuserCounter == 14)
3976 m_DebugFocuserCounter = 0;
3977 appendLogText(
i18n(
"Simulate focuser comms failure..."));
3982 m_FocusMotionTimer.stop();
3996 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Focuser position " << currentPosition <<
" and state:"
3997 <<
pstateStr(currentPositionState) <<
" unchanged";
4007 currentPositionState);
4009 emit absolutePositionChanged(currentPosition);
4013 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Can't access FOCUS_ABSOLUTE_POSITION. Current state:"
4018 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
4023 m_FocusMotionTimer.start();
4029 if (focuserAdditionalMovement == 0)
4034 if (focuserAdditionalMovement == 0)
4036 inAdjustFocus =
false;
4037 emit focusPositionAdjusted();
4042 if (adaptFocus->inAdaptiveFocus())
4044 if (focuserAdditionalMovement == 0)
4046 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4051 if (m_RestartState == RESTART_NOW && status() != Ekos::FOCUS_ABORTED)
4053 if (focuserAdditionalMovement == 0)
4055 m_RestartState = RESTART_NONE;
4056 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4057 adaptFocus->setInAdaptiveFocus(
false);
4058 appendLogText(
i18n(
"Restarting autofocus process..."));
4059 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4063 else if (m_RestartState == RESTART_ABORT && focuserAdditionalMovement == 0)
4069 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4070 m_RestartState = RESTART_NONE;
4071 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4072 adaptFocus->setInAdaptiveFocus(
false);
4078 autoFocusProcessPositionChange(
newState);
4080 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4087 if (
nvp->isNameMatch(
"manualfocusdrive"))
4092 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4094 if (m_DebugFocuserCounter == 14)
4095 m_DebugFocuserCounter = 0;
4096 appendLogText(
i18n(
"Simulate focuser comms failure..."));
4101 m_FocusMotionTimer.stop();
4107 currentPosition += pos->value;
4109 emit absolutePositionChanged(currentPosition);
4114 if (focuserAdditionalMovement == 0)
4116 inAdjustFocus =
false;
4117 emit focusPositionAdjusted();
4124 if (focuserAdditionalMovement == 0)
4126 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4132 if (m_RestartState == RESTART_NOW &&
newState ==
IPS_OK && status() != Ekos::FOCUS_ABORTED)
4134 if (focuserAdditionalMovement == 0)
4136 m_RestartState = RESTART_NONE;
4137 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4138 adaptFocus->setInAdaptiveFocus(
false);
4139 appendLogText(
i18n(
"Restarting autofocus process..."));
4140 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4147 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4148 m_RestartState = RESTART_NONE;
4149 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4150 adaptFocus->setInAdaptiveFocus(
false);
4155 autoFocusProcessPositionChange(
newState);
4157 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4162 if (
nvp->isNameMatch(
"REL_FOCUS_POSITION"))
4164 m_FocusMotionTimer.stop();
4170 currentPosition += pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4172 <<
QString(
"Rel Focuser position moved %1 by %2 to %3")
4173 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").arg(pos->value).
arg(currentPosition);
4175 emit absolutePositionChanged(currentPosition);
4180 if (focuserAdditionalMovement == 0)
4182 inAdjustFocus =
false;
4183 emit focusPositionAdjusted();
4190 if (focuserAdditionalMovement == 0)
4192 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4198 if (m_RestartState == RESTART_NOW &&
newState ==
IPS_OK && status() != Ekos::FOCUS_ABORTED)
4200 if (focuserAdditionalMovement == 0)
4202 m_RestartState = RESTART_NONE;
4203 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4204 adaptFocus->setInAdaptiveFocus(
false);
4205 appendLogText(
i18n(
"Restarting autofocus process..."));
4206 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4213 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4214 m_RestartState = RESTART_NONE;
4215 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4216 adaptFocus->setInAdaptiveFocus(
false);
4221 autoFocusProcessPositionChange(
newState);
4223 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4231 if (
nvp->isNameMatch(
"FOCUS_TIMER"))
4234 m_FocusMotionTimer.stop();
4236 if (m_RestartState == RESTART_NOW &&
newState ==
IPS_OK && status() != Ekos::FOCUS_ABORTED)
4238 if (focuserAdditionalMovement == 0)
4240 m_RestartState = RESTART_NONE;
4241 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4242 adaptFocus->setInAdaptiveFocus(
false);
4243 appendLogText(
i18n(
"Restarting autofocus process..."));
4244 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4251 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4252 m_RestartState = RESTART_NONE;
4253 inAutoFocus = inAdjustFocus = inScanStartPos =
false;
4254 adaptFocus->setInAdaptiveFocus(
false);
4258 if (canAbsMove ==
false && canRelMove ==
false)
4264 currentPosition += pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4266 <<
QString(
"Timer Focuser position moved %1 by %2 to %3")
4267 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").arg(pos->value).
arg(currentPosition);
4272 if (focuserAdditionalMovement == 0)
4274 inAdjustFocus =
false;
4275 emit focusPositionAdjusted();
4282 if (focuserAdditionalMovement == 0)
4284 adaptFocus->adaptiveFocusAdmin(
true,
true,
true);
4289 autoFocusProcessPositionChange(
newState);
4292 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4300 m_LogText.insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
4301 KStarsData::Instance()->lt().toString(
"yyyy-MM-ddThh:mm:ss"), text));
4308void Focus::clearLog()
4314void Focus::appendFocusLogText(
const QString &lines)
4316 if (Options::focusLogging())
4319 if (!m_FocusLogFile.exists())
4323 dir.mkpath(
"focuslogs");
4325 if (m_FocusLogEnabled)
4328 header <<
"date, time, position, temperature, filter, HFR, altitude\n";
4332 qCWarning(
KSTARS_EKOS_FOCUS) <<
"Failed to open focus log file: " << m_FocusLogFileName;
4335 if (m_FocusLogEnabled)
4344void Focus::startFraming()
4346 if (m_Camera ==
nullptr)
4348 appendLogText(
i18n(
"No CCD connected."));
4352 waitStarSelectTimer.stop();
4355 starMeasureFrames.clear();
4360 setState(Ekos::FOCUS_FRAMING);
4364 appendLogText(
i18n(
"Starting continuous exposure..."));
4369void Focus::resetButtons()
4382 trainB->setEnabled(
false);
4396 if (disabledWidgets.empty())
4400 AFDisable(
trainB,
false);
4405 m_FocusGainAFEnabled =
focusGain->isEnabled();
4406 m_FocusISOAFEnabled =
focusISO->isEnabled();
4412 m_FocusSubFrameAFEnabled = m_OpsFocusSettings->focusSubFrame->isEnabled();
4415 AFDisable(m_OpsFocusSettings,
false);
4416 AFDisable(m_OpsFocusProcess,
false);
4417 AFDisable(m_OpsFocusMechanics,
false);
4418 AFDisable(m_AdvisorDialog,
false);
4419 AFDisable(m_CFZDialog,
false);
4428 for(
int i = 0 ; i < disabledWidgets.size() ; i++)
4429 disabledWidgets[i]->setEnabled(
true);
4430 disabledWidgets.clear();
4438 && m_OpsFocusSettings->focusUseFullField->isChecked() ==
false);
4440 if (m_Focuser && m_Focuser->isConnected())
4445 startFocusB->setEnabled(m_FocusType == FOCUS_AUTO);
4468bool Focus::canAbInsStart()
4470 return canAbsMove && m_FocusAlgorithm == FOCUS_LINEAR1PASS && m_currentImageMask == FOCUS_MASK_MOSAIC;
4474void Focus::AFDisable(
QWidget * widget,
const bool children)
4479 for(
auto *
wid : widget->findChildren<
QWidget *>())
4481 if (
wid->isEnabled())
4483 wid->setEnabled(
false);
4484 disabledWidgets.push_back(
wid);
4493 disabledWidgets.push_back(widget);
4497bool Focus::isFocusGainEnabled()
4499 return (inAutoFocus) ? m_FocusGainAFEnabled :
focusGain->isEnabled();
4502bool Focus::isFocusISOEnabled()
4504 return (inAutoFocus) ? m_FocusISOAFEnabled :
focusISO->isEnabled();
4507bool Focus::isFocusSubFrameEnabled()
4509 return (inAutoFocus) ? m_FocusSubFrameAFEnabled : m_OpsFocusSettings->focusSubFrame->isEnabled();
4512void Focus::updateBoxSize(
int value)
4514 if (m_Camera ==
nullptr)
4517 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4519 if (targetChip ==
nullptr)
4522 int subBinX, subBinY;
4523 targetChip->getBinning(&subBinX, &subBinY);
4529 QRect(
center.x() - value / (2 * subBinX),
center.y() - value / (2 * subBinY), value / subBinX, value / subBinY);
4531 m_FocusView->setTrackingBox(
trackBox);
4534void Focus::selectFocusStarFraction(
double x,
double y)
4536 if (m_ImageData.isNull())
4539 focusStarSelected(x * m_ImageData->width(), y * m_ImageData->height());
4543 emit newImage(m_FocusView);
4547void Focus::focusStarSelected(
int x,
int y)
4549 if (state() == Ekos::FOCUS_PROGRESS)
4552 if (subFramed ==
false)
4554 rememberStarCenter.setX(x);
4555 rememberStarCenter.setY(y);
4558 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4560 int subBinX, subBinY;
4561 targetChip->getBinning(&subBinX, &subBinY);
4570 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
4576 if (subFramed ==
false && m_OpsFocusSettings->focusSubFrame->isChecked() && targetChip->canSubframe())
4583 x = (x - offset) * subBinX;
4584 y = (y - offset) * subBinY;
4585 int w = offset * 2 * subBinX;
4586 int h = offset * 2 * subBinY;
4605 QVariantMap settings = frameSettings[targetChip];
4610 settings[
"binx"] = subBinX;
4611 settings[
"biny"] = subBinY;
4613 frameSettings[targetChip] = settings;
4617 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << x <<
"Y:" << y <<
"W:" << w <<
"H:" << h <<
"binX:" << subBinX <<
4620 m_FocusView->setFirstLoad(
true);
4625 starCenter.setX(w / (2 * subBinX));
4626 starCenter.setY(h / (2 * subBinY));
4631 double dist =
sqrt((starCenter.x() - x) * (starCenter.x() - x) + (starCenter.y() - y) * (starCenter.y() - y));
4633 squareMovedOutside = (
dist > (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX));
4637 starRect =
QRect(starCenter.x() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinX),
4638 starCenter.y() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinY),
4639 m_OpsFocusSettings->focusBoxSize->value() / subBinX,
4640 m_OpsFocusSettings->focusBoxSize->value() / subBinY);
4641 m_FocusView->setTrackingBox(
starRect);
4646 starCenter.setZ(subBinX);
4648 if (
squareMovedOutside && inAutoFocus ==
false && m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
4650 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
true);
4651 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
4652 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
false);
4653 appendLogText(
i18n(
"Disabling Auto Star Selection as star selection box was moved manually."));
4654 starSelected =
false;
4656 else if (starSelected ==
false)
4658 appendLogText(
i18n(
"Focus star is selected."));
4659 starSelected =
true;
4663 waitStarSelectTimer.stop();
4664 FocusState
nextState = inAutoFocus ? FOCUS_PROGRESS : FOCUS_IDLE;
4673 if (inAutoFocus || inFocusLoop || inAdjustFocus || adaptFocus->inAdaptiveFocus() || inBuildOffsets)
4675 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Check Focus rejected, focus procedure is already running.";
4682 appendLogText(
"Capturing to check HFR...");
4687void Focus::toggleSubframe(
bool enable)
4689 if (enable ==
false)
4692 starSelected =
false;
4698 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
true);
4700 m_OpsFocusSettings->focusNoMaskRB->setChecked(
true);
4705 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
4706 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
4711 m_OpsFocusSettings->focusRingMaskRB->setEnabled(!enable);
4712 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(!enable);
4721void Focus::setUseWeights()
4723 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC || !m_OpsFocusSettings->focusUseFullField->isChecked()
4724 || m_StarMeasure == FOCUS_STAR_NUM_STARS
4725 || m_StarMeasure == FOCUS_STAR_FOURIER_POWER)
4727 m_OpsFocusProcess->focusUseWeights->setEnabled(
false);
4728 m_OpsFocusProcess->focusUseWeights->setChecked(
false);
4731 m_OpsFocusProcess->focusUseWeights->setEnabled(
true);
4740void Focus::setDonutBuster()
4742 if (m_FocusAlgorithm != FOCUS_LINEAR1PASS)
4744 m_OpsFocusProcess->focusDonut->hide();
4745 m_OpsFocusProcess->focusDonut->setEnabled(
false);
4746 m_OpsFocusProcess->focusDonut->setChecked(
false);
4750 m_OpsFocusProcess->focusDonut->show();
4751 if ((m_StarMeasure == FOCUS_STAR_HFR || m_StarMeasure == FOCUS_STAR_HFR_ADJ || m_StarMeasure == FOCUS_STAR_FWHM) &&
4752 (m_FocusWalk == FOCUS_WALK_FIXED_STEPS || m_FocusWalk == FOCUS_WALK_CFZ_SHUFFLE) &&
4753 (m_CurveFit != CurveFitting::FOCUS_QUADRATIC))
4754 m_OpsFocusProcess->focusDonut->setEnabled(
true);
4757 m_OpsFocusProcess->focusDonut->setEnabled(
false);
4758 m_OpsFocusProcess->focusDonut->setChecked(
false);
4763void Focus::setExposure(
double value)
4768void Focus::setBinning(
int subBinX,
int subBinY)
4774void Focus::setAutoStarEnabled(
bool enable)
4776 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(enable);
4779void Focus::setAutoSubFrameEnabled(
bool enable)
4781 m_OpsFocusSettings->focusSubFrame->setChecked(enable);
4786 m_OpsFocusSettings->focusBoxSize->setValue(
boxSize);
4787 m_OpsFocusMechanics->focusTicks->setValue(stepSize);
4788 m_OpsFocusMechanics->focusMaxTravel->setValue(maxTravel);
4789 m_OpsFocusProcess->focusTolerance->setValue(
tolerance);
4792void Focus::checkAutoStarTimeout()
4795 if (starCenter.isNull() && (inAutoFocus || minimumRequiredHFR > 0))
4799 if (rememberStarCenter.isNull() ==
false)
4801 focusStarSelected(rememberStarCenter.x(), rememberStarCenter.y());
4802 appendLogText(
i18n(
"No star was selected. Using last known position..."));
4807 initialFocuserAbsPosition = -1;
4808 appendLogText(
i18n(
"No star was selected. Aborting..."));
4809 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
4811 else if (state() == FOCUS_WAITING)
4812 setState(FOCUS_IDLE);
4815void Focus::setAbsoluteFocusTicks()
4819 appendLogText(
i18n(
"Focuser already at %1...", currentPosition));
4825 if (!changeFocus(
absTicksSpin->value() - currentPosition))
4829void Focus::syncTrackingBoxPosition()
4831 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4834 int subBinX = 1, subBinY = 1;
4835 targetChip->getBinning(&subBinX, &subBinY);
4837 if (starCenter.isNull() ==
false)
4839 double boxSize = m_OpsFocusSettings->focusBoxSize->value();
4841 targetChip->getFrame(&x, &y, &w, &h);
4845 m_OpsFocusSettings->focusBoxSize->setValue((
boxSize / subBinX >= w) ? w : h);
4850 if (subBinX != starCenter.z())
4852 if (starCenter.z() > 0)
4854 starCenter.setX(starCenter.x() * (starCenter.z() / subBinX));
4855 starCenter.setY(starCenter.y() * (starCenter.z() / subBinY));
4858 starCenter.setZ(subBinX);
4863 m_FocusView->setTrackingBoxEnabled(
true);
4864 m_FocusView->setTrackingBox(
starRect);
4868void Focus::showFITSViewer()
4878 connect(fv.get(), &FITSViewer::terminated,
this, [
this]()
4895 qCDebug(
KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset called whilst inAdjustFocus in progress. Ignoring...";
4899 if (adaptFocus->inAdaptiveFocus())
4901 qCDebug(
KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset called whilst inAdaptiveFocus. Ignoring...";
4905 inAdjustFocus =
true;
4914void Focus::toggleFocusingWidgetFullScreen()
4932void Focus::setMountStatus(ISD::Mount::Status
newState)
4936 case ISD::Mount::MOUNT_PARKING:
4937 case ISD::Mount::MOUNT_SLEWING:
4938 case ISD::Mount::MOUNT_MOVING:
4957void Focus::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
4961 mountAlt = position.
alt().Degrees();
4966 auto name = deviceRemoved->getDeviceName();
4970 if (m_Focuser && m_Focuser->getDeviceName() == name)
4972 m_Focuser->disconnect(
this);
4973 m_Focuser =
nullptr;
4982 for (
auto &
oneSource : m_TemperatureSources)
4987 if (m_LastSourceDeviceAutofocusTemperature && m_LastSourceDeviceAutofocusTemperature->getDeviceName() == name)
4988 m_LastSourceDeviceAutofocusTemperature.reset(
nullptr);
4990 m_TemperatureSources.removeAll(
oneSource);
5000 if (m_Camera && m_Camera->getDeviceName() == name)
5002 m_Camera->disconnect(
this);
5013 if (m_FilterWheel && m_FilterWheel->getDeviceName() == name)
5015 m_FilterWheel->disconnect(
this);
5016 m_FilterWheel =
nullptr;
5026void Focus::setupFilterManager()
5029 if (m_FilterManager)
5030 m_FilterManager->disconnect(
this);
5033 Ekos::Manager::Instance()->createFilterManager(m_FilterWheel);
5036 Ekos::Manager::Instance()->getFilterManager(m_FilterWheel->getDeviceName(), m_FilterManager);
5041 connect(
this, &Focus::absolutePositionChanged, m_FilterManager.get(), &FilterManager::setFocusAbsolutePosition);
5044 connect(
this, &Focus::newStatus,
this, [
this](Ekos::FocusState state)
5046 if (m_FilterManager)
5048 m_FilterManager->setFocusStatus(state);
5049 if (
focusFilter->currentIndex() != -1 && canAbsMove && state == Ekos::FOCUS_COMPLETE)
5051 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
5052 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
5060 connect(m_FilterManager.get(), &FilterManager::newStatus,
this, [
this](Ekos::FilterState
filterState)
5063 if (filterState == FILTER_OFFSET && state() != Ekos::FOCUS_PROGRESS)
5065 if (m_GuidingSuspended == false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
5067 m_GuidingSuspended = true;
5068 emit suspendGuiding();
5074 connect(m_FilterManager.get(), &FilterManager::ready,
this, [
this]()
5077 if (focusFilter->currentIndex() != currentFilterPosition - 1)
5078 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5080 if (filterPositionPending)
5082 filterPositionPending = false;
5085 else if (fallbackFilterPending)
5087 fallbackFilterPending =
false;
5088 emit newStatus(state());
5093 connect(m_FilterManager.get(), &FilterManager::failed,
this, [
this]()
5095 appendLogText(i18n(
"Filter operation failed."));
5096 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FILTER_MANAGER);
5100 connect(m_FilterManager.get(), &FilterManager::runAutoFocus,
this, &Focus::runAutoFocus);
5103 connect(m_FilterManager.get(), &FilterManager::abortAutoFocus,
this, &Focus::abort);
5106 connect(m_FilterManager.get(), &FilterManager::newFocusOffset,
this, &Focus::adjustFocusOffset);
5109 connect(m_FilterManager.get(), &FilterManager::labelsChanged,
this, [
this]()
5111 focusFilter->clear();
5112 focusFilter->addItems(m_FilterManager->getFilterLabels());
5113 currentFilterPosition = m_FilterManager->getFilterPosition();
5114 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5118 connect(m_FilterManager.get(), &FilterManager::positionChanged,
this, [
this]()
5120 currentFilterPosition = m_FilterManager->getFilterPosition();
5121 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5125 connect(m_FilterManager.get(), &FilterManager::exposureChanged,
this, [
this]()
5127 focusExposure->setValue(m_FilterManager->getFilterExposure());
5131 connect(m_FilterManager.get(), &FilterManager::wavelengthChanged,
this, [
this]()
5133 wavelengthChanged();
5137void Focus::connectFilterManager()
5142 if (m_FilterManager)
5144 m_FilterManager->refreshFilterModel();
5145 m_FilterManager->show();
5146 m_FilterManager->raise();
5151 connect(
this, &Focus::focusPositionAdjusted,
this, [
this]()
5153 if (m_FilterManager)
5154 m_FilterManager->setFocusOffsetComplete();
5155 if (m_GuidingSuspended && state() != Ekos::FOCUS_PROGRESS)
5157 QTimer::singleShot(m_OpsFocusMechanics->focusSettleTime->value() * 1000,
this, [
this]()
5159 m_GuidingSuspended = false;
5160 emit resumeGuiding();
5169 if (inAutoFocus && m_OpsFocusProcess->focusDonut->isEnabled())
5172 if (m_FilterManager)
5179 if (m_FilterManager)
5181 focusExposure->setValue(m_FilterManager->getFilterExposure(text));
5189void Focus::toggleVideo(
bool enabled)
5191 if (m_Camera ==
nullptr)
5194 if (m_Camera->isBLOBEnabled() ==
false)
5197 if (Options::guiderType() != Ekos::Guide::GUIDE_INTERNAL)
5198 m_Camera->setBLOBEnabled(
true);
5204 KSMessageBox::Instance()->disconnect(
this);
5205 m_Camera->setVideoStreamEnabled(enabled);
5207 KSMessageBox::Instance()->questionYesNo(
i18n(
"Image transfer is disabled for this camera. Would you like to enable it?"));
5211 m_Camera->setVideoStreamEnabled(enabled);
5227void Focus::setVideoStreamEnabled(
bool enabled)
5241void Focus::processCaptureTimeout()
5243 captureTimeoutCounter++;
5245 if (captureTimeoutCounter >= 3)
5247 captureTimeoutCounter = 0;
5248 captureTimeout.stop();
5249 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5250 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5254 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
5255 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5256 targetChip->abortExposure();
5258 prepareCapture(targetChip);
5264 captureTimeout.start( (
focusExposure->value() + m_OpsFocusMechanics->focusCaptureTimeout->value()) * 1000);
5266 if (inFocusLoop ==
false)
5267 appendLogText(
i18n(
"Capturing image again..."));
5271 else if (inAutoFocus)
5273 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5282 appendLogText(
i18n(
"Failed to save image. Aborting..."));
5283 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5287 captureFailureCounter++;
5289 if (captureFailureCounter >= 3)
5291 captureFailureCounter = 0;
5292 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5293 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5297 appendLogText(
i18n(
"Exposure failure. Restarting exposure..."));
5298 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5299 targetChip->abortExposure();
5303void Focus::syncSettings()
5318 key =
dsb->objectName();
5319 value =
dsb->value();
5325 value = sb->
value();
5334 key =
gb->objectName();
5335 value =
gb->isChecked();
5339 key =
rb->objectName();
5340 value =
rb->isChecked();
5344 key =
cbox->objectName();
5345 value =
cbox->currentText();
5355 Options::self()->setProperty(key.
toLatin1(), value);
5357 m_Settings[key] = value;
5358 m_GlobalSettings[key] = value;
5362 m_DebounceTimer.start();
5368void Focus::settleSettings()
5370 emit settingsUpdated(getAllSettings());
5372 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(
opticalTrainCombo->currentText()));
5373 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
5376void Focus::loadGlobalSettings()
5381 QVariantMap settings;
5385 if (
oneWidget->objectName() ==
"opticalTrainCombo")
5389 value = Options::self()->property(key.
toLatin1());
5393 settings[key] = value;
5403 value = Options::self()->property(key.
toLatin1());
5407 settings[key] = value;
5417 value = Options::self()->property(key.
toLatin1());
5421 settings[key] = value;
5431 value = Options::self()->property(key.
toLatin1());
5435 settings[key] = value;
5447 value = Options::self()->property(key.
toLatin1());
5451 settings[key] = value;
5462 value = Options::self()->property(key.
toLatin1());
5478 value = Options::self()->property(key.
toLatin1());
5482 settings[key] = value;
5487 m_GlobalSettings = m_Settings = settings;
5490void Focus::checkMosaicMaskLimits()
5492 if (m_Camera ==
nullptr || m_Camera->isConnected() ==
false)
5494 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5495 if (targetChip ==
nullptr || frameSettings.contains(targetChip) ==
false)
5497 auto settings = frameSettings[targetChip];
5500 auto width = settings[
"w"].toInt();
5501 auto height = settings[
"h"].toInt();
5502 if (width == 0 || height == 0)
5506 auto min = std::min(width, height);
5508 m_OpsFocusSettings->focusMosaicTileWidth->setMaximum(100 * min / (3 * width));
5511void Focus::connectSyncSettings()
5545void Focus::disconnectSyncSettings()
5577void Focus::initPlots()
5581 profileDialog =
new QDialog(
this);
5584 profileDialog->setWindowTitle(
i18nc(
"@title:window",
"Relative Profile"));
5585 profilePlot =
new FocusProfilePlot(profileDialog);
5589 profileDialog->resize(400, 300);
5592 connect(
this, &Ekos::Focus::newHFR, [
this](
double currentHFR,
int pos)
5594 Q_UNUSED(pos) profilePlot->drawProfilePlot(currentHFR);
5598void Focus::initConnections()
5601 waitStarSelectTimer.setInterval(AUTO_STAR_TIMEOUT);
5606 m_DebounceTimer.setInterval(500);
5607 m_DebounceTimer.setSingleShot(
true);
5622 captureTimer.setSingleShot(
true);
5629 captureTimeout.setSingleShot(
true);
5664 &Ekos::Focus::updateBoxSize);
5670 m_CFZDialog->show();
5671 m_CFZDialog->raise();
5675 m_AdvisorDialog->show();
5676 m_AdvisorDialog->raise();
5681 Options::setFocusForceInSeqAF(enabled);
5687 setFocusDetection(static_cast<StarAlgorithm>(index));
5693 setFocusAlgorithm(static_cast<Algorithm>(index));
5699 this, [&](
int index)
5701 setCurveFit(static_cast<CurveFitting::CurveFit>(index));
5706 this, [&](
int index)
5708 setStarMeasure(static_cast<StarMeasure>(index));
5713 this, [&](
int index)
5715 setStarPSF(static_cast<StarPSF>(index));
5720 this, [&](
int index)
5722 setStarUnits(static_cast<StarUnits>(index));
5727 this, [&](
int index)
5729 setWalk(static_cast<FocusWalk>(index));
5740 starCenter = QVector3D();
5741 starSelected = false;
5742 m_FocusView->setTrackingBox(QRect());
5750 &Ekos::Focus::calcCFZ);
5753 &Ekos::Focus::calcCFZ);
5796 focusAdvisorAction(false);
5802void Focus::setFocusDetection(StarAlgorithm starAlgorithm)
5804 static bool first =
true;
5805 if (!first && m_FocusDetection == starAlgorithm)
5810 m_FocusDetection = starAlgorithm;
5813 setFocusAlgorithm(m_FocusAlgorithm);
5815 if (m_FocusDetection == ALGORITHM_BAHTINOV)
5818 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
5819 m_OpsFocusSettings->focusBoxSize->setMaximum(512);
5824 if (m_OpsFocusSettings->focusBoxSize->value() > 256)
5827 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
5829 m_OpsFocusSettings->focusBoxSize->setMaximum(256);
5831 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(m_FocusDetection != ALGORITHM_BAHTINOV);
5835void Focus::setFocusAlgorithm(Algorithm algorithm)
5837 m_FocusAlgorithm = algorithm;
5840 case FOCUS_ITERATIVE:
5842 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
5843 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
5844 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
5845 m_OpsFocusProcess->focusMultiRowAverage->hide();
5847 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
5848 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
5849 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
5850 m_OpsFocusProcess->focusGaussianSigma->hide();
5852 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
5853 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
5854 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
5855 m_OpsFocusProcess->focusGaussianKernelSize->hide();
5857 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasureLabel);
5858 m_OpsFocusProcess->focusStarMeasureLabel->hide();
5859 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasure);
5860 m_OpsFocusProcess->focusStarMeasure->hide();
5862 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
5863 m_OpsFocusProcess->focusStarPSFLabel->hide();
5864 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
5865 m_OpsFocusProcess->focusStarPSF->hide();
5867 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
5868 m_OpsFocusProcess->focusUseWeights->hide();
5870 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
5871 m_OpsFocusProcess->focusR2LimitLabel->hide();
5872 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
5873 m_OpsFocusProcess->focusR2Limit->hide();
5875 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
5876 m_OpsFocusProcess->focusRefineCurveFit->hide();
5877 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
5879 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
5880 m_OpsFocusProcess->focusToleranceLabel->hide();
5881 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
5882 m_OpsFocusProcess->focusTolerance->hide();
5884 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
5885 m_OpsFocusProcess->focusThresholdLabel->hide();
5886 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
5887 m_OpsFocusProcess->focusThreshold->hide();
5889 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFitLabel);
5890 m_OpsFocusProcess->focusCurveFitLabel->hide();
5891 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFit);
5892 m_OpsFocusProcess->focusCurveFit->hide();
5894 m_OpsFocusProcess->focusDonut->hide();
5895 m_OpsFocusProcess->focusDonut->setChecked(
false);
5898 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
5901 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
5903 m_OpsFocusProcess->focusStarMeasure->clear();
5904 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
5905 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
5909 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
5910 m_OpsFocusProcess->focusToleranceLabel->show();
5911 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
5912 m_OpsFocusProcess->focusTolerance->show();
5914 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
5915 m_OpsFocusProcess->focusFramesCountLabel->show();
5916 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
5917 m_OpsFocusProcess->focusFramesCount->show();
5919 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
5920 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
5921 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
5922 m_OpsFocusProcess->focusHFRFramesCount->show();
5924 if (m_FocusDetection == ALGORITHM_THRESHOLD)
5926 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
5927 m_OpsFocusProcess->focusThresholdLabel->show();
5928 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
5929 m_OpsFocusProcess->focusThreshold->show();
5931 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
5933 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
5934 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
5935 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
5936 m_OpsFocusProcess->focusMultiRowAverage->show();
5938 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
5939 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
5940 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
5941 m_OpsFocusProcess->focusGaussianSigma->show();
5943 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
5944 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
5945 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
5946 m_OpsFocusProcess->focusGaussianKernelSize->show();
5954 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
5955 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
5956 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
5959 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
5960 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
5963 if (m_OpsFocusMechanics->focusWalk->count() != 1)
5965 m_OpsFocusMechanics->focusWalk->clear();
5966 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
5967 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
5971 case FOCUS_POLYNOMIAL:
5973 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
5974 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
5975 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
5976 m_OpsFocusProcess->focusMultiRowAverage->hide();
5978 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
5979 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
5980 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
5981 m_OpsFocusProcess->focusGaussianSigma->hide();
5983 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
5984 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
5985 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
5986 m_OpsFocusProcess->focusGaussianKernelSize->hide();
5988 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
5989 m_OpsFocusProcess->focusStarPSFLabel->hide();
5990 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
5991 m_OpsFocusProcess->focusStarPSF->hide();
5993 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
5994 m_OpsFocusProcess->focusUseWeights->hide();
5996 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
5997 m_OpsFocusProcess->focusR2LimitLabel->hide();
5998 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
5999 m_OpsFocusProcess->focusR2Limit->hide();
6001 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6002 m_OpsFocusProcess->focusRefineCurveFit->hide();
6003 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6005 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6006 m_OpsFocusProcess->focusToleranceLabel->hide();
6007 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6008 m_OpsFocusProcess->focusTolerance->hide();
6010 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6011 m_OpsFocusProcess->focusThresholdLabel->hide();
6012 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6013 m_OpsFocusProcess->focusThreshold->hide();
6016 m_OpsFocusProcess->focusDonut->hide();
6017 m_OpsFocusProcess->focusDonut->setChecked(
false);
6020 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6022 m_OpsFocusProcess->focusStarMeasure->clear();
6023 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6024 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6029 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6030 m_OpsFocusProcess->focusCurveFitLabel->show();
6031 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6032 m_OpsFocusProcess->focusCurveFit->show();
6033 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6035 m_OpsFocusProcess->focusCurveFit->clear();
6036 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6037 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6040 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6041 m_OpsFocusProcess->focusToleranceLabel->show();
6042 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6043 m_OpsFocusProcess->focusTolerance->show();
6045 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6046 m_OpsFocusProcess->focusFramesCountLabel->show();
6047 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6048 m_OpsFocusProcess->focusFramesCount->show();
6050 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6051 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6052 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6053 m_OpsFocusProcess->focusHFRFramesCount->show();
6055 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6057 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6058 m_OpsFocusProcess->focusThresholdLabel->show();
6059 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6060 m_OpsFocusProcess->focusThreshold->show();
6062 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6064 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6065 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6066 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6067 m_OpsFocusProcess->focusMultiRowAverage->show();
6069 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6070 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6071 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6072 m_OpsFocusProcess->focusGaussianSigma->show();
6074 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6075 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6076 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6077 m_OpsFocusProcess->focusGaussianKernelSize->show();
6085 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6086 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6087 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6090 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6091 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6094 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6096 m_OpsFocusMechanics->focusWalk->clear();
6097 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6098 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6104 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6105 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6106 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6107 m_OpsFocusProcess->focusMultiRowAverage->hide();
6109 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6110 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6111 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6112 m_OpsFocusProcess->focusGaussianSigma->hide();
6114 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6115 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6116 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6117 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6119 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6120 m_OpsFocusProcess->focusThresholdLabel->hide();
6121 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6122 m_OpsFocusProcess->focusThreshold->hide();
6124 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6125 m_OpsFocusProcess->focusStarPSFLabel->hide();
6126 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6127 m_OpsFocusProcess->focusStarPSF->hide();
6129 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6130 m_OpsFocusProcess->focusUseWeights->hide();
6132 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6133 m_OpsFocusProcess->focusR2LimitLabel->hide();
6134 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6135 m_OpsFocusProcess->focusR2Limit->hide();
6137 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6138 m_OpsFocusProcess->focusRefineCurveFit->hide();
6139 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6142 m_OpsFocusProcess->focusDonut->hide();
6143 m_OpsFocusProcess->focusDonut->setChecked(
false);
6146 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6148 m_OpsFocusProcess->focusStarMeasure->clear();
6149 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6150 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6155 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6156 m_OpsFocusProcess->focusCurveFitLabel->show();
6157 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6158 m_OpsFocusProcess->focusCurveFit->show();
6159 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6161 m_OpsFocusProcess->focusCurveFit->clear();
6162 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6163 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6166 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6167 m_OpsFocusProcess->focusToleranceLabel->show();
6168 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6169 m_OpsFocusProcess->focusTolerance->show();
6171 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6172 m_OpsFocusProcess->focusFramesCountLabel->show();
6173 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6174 m_OpsFocusProcess->focusFramesCount->show();
6176 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6177 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6178 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6179 m_OpsFocusProcess->focusHFRFramesCount->show();
6181 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6183 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6184 m_OpsFocusProcess->focusThresholdLabel->show();
6185 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6186 m_OpsFocusProcess->focusThreshold->show();
6188 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6190 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6191 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6192 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6193 m_OpsFocusProcess->focusMultiRowAverage->show();
6195 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6196 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6197 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6198 m_OpsFocusProcess->focusGaussianSigma->show();
6200 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6201 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6202 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6203 m_OpsFocusProcess->focusGaussianKernelSize->show();
6211 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6212 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6213 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6216 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6217 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6220 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6222 m_OpsFocusMechanics->focusWalk->clear();
6223 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6224 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6228 case FOCUS_LINEAR1PASS:
6230 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6231 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6232 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6233 m_OpsFocusProcess->focusMultiRowAverage->hide();
6235 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6236 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6237 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6238 m_OpsFocusProcess->focusGaussianSigma->hide();
6240 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6241 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6242 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6243 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6245 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6246 m_OpsFocusProcess->focusThresholdLabel->hide();
6247 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6248 m_OpsFocusProcess->focusThreshold->hide();
6250 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6251 m_OpsFocusProcess->focusToleranceLabel->hide();
6252 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6253 m_OpsFocusProcess->focusTolerance->hide();
6257 if (m_FocusDetection == ALGORITHM_SEP && m_CurveFit != CurveFitting::FOCUS_QUADRATIC)
6259 if (m_OpsFocusProcess->focusStarMeasure->count() != m_StarMeasureText.count())
6261 m_OpsFocusProcess->focusStarMeasure->clear();
6262 m_OpsFocusProcess->focusStarMeasure->addItems(m_StarMeasureText);
6263 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6266 else if (m_FocusDetection != ALGORITHM_SEP || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6268 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6270 m_OpsFocusProcess->focusStarMeasure->clear();
6271 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6272 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6278 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6279 m_OpsFocusProcess->focusCurveFitLabel->show();
6280 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6281 m_OpsFocusProcess->focusCurveFit->show();
6282 if (m_OpsFocusProcess->focusCurveFit->count() != m_CurveFitText.count())
6284 m_OpsFocusProcess->focusCurveFit->clear();
6285 m_OpsFocusProcess->focusCurveFit->addItems(m_CurveFitText);
6286 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_HYPERBOLA);
6289 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusUseWeights, 3, 0, 1, 2);
6290 m_OpsFocusProcess->focusUseWeights->show();
6292 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2LimitLabel, 3, 2);
6293 m_OpsFocusProcess->focusR2LimitLabel->show();
6294 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2Limit, 3, 3);
6295 m_OpsFocusProcess->focusR2Limit->show();
6297 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusRefineCurveFit, 4, 0, 1, 2);
6298 m_OpsFocusProcess->focusRefineCurveFit->show();
6300 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 4, 2);
6301 m_OpsFocusProcess->focusFramesCountLabel->show();
6302 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 4, 3);
6303 m_OpsFocusProcess->focusFramesCount->show();
6305 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 5, 2);
6306 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6307 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 5, 3);
6308 m_OpsFocusProcess->focusHFRFramesCount->show();
6310 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6312 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 6, 0);
6313 m_OpsFocusProcess->focusThresholdLabel->show();
6314 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 6, 1);
6315 m_OpsFocusProcess->focusThreshold->show();
6317 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6319 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 6, 0);
6320 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6321 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 6, 1);
6322 m_OpsFocusProcess->focusMultiRowAverage->show();
6324 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 6, 2);
6325 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6326 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 6, 3);
6327 m_OpsFocusProcess->focusGaussianSigma->show();
6329 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 7, 0);
6330 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6331 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 7, 1);
6332 m_OpsFocusProcess->focusGaussianKernelSize->show();
6336 m_OpsFocusProcess->focusDonut->show();
6337 m_OpsFocusProcess->focusDonut->setEnabled(
true);
6344 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(canAbsMove);
6348 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6349 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6352 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6354 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6356 m_OpsFocusMechanics->focusWalk->clear();
6357 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6358 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6363 if (m_OpsFocusMechanics->focusWalk->count() != m_FocusWalkText.count())
6365 m_OpsFocusMechanics->focusWalk->clear();
6366 m_OpsFocusMechanics->focusWalk->addItems(m_FocusWalkText);
6367 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6374void Focus::setCurveFit(CurveFitting::CurveFit curve)
6376 if (m_OpsFocusProcess->focusCurveFit->currentIndex() == -1)
6379 static bool first =
true;
6380 if (!first && m_CurveFit == curve)
6386 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
6392 case CurveFitting::FOCUS_QUADRATIC:
6393 m_OpsFocusProcess->focusR2Limit->setEnabled(
false);
6394 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6395 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
false);
6398 case CurveFitting::FOCUS_HYPERBOLA:
6399 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6400 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6403 case CurveFitting::FOCUS_PARABOLA:
6404 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6405 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6413void Focus::setStarMeasure(StarMeasure starMeasure)
6415 if (m_OpsFocusProcess->focusStarMeasure->currentIndex() == -1)
6418 static bool first =
true;
6419 if (!first && m_StarMeasure == starMeasure)
6424 m_StarMeasure = starMeasure;
6425 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
6433 switch(m_StarMeasure)
6435 case FOCUS_STAR_HFR:
6436 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6437 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6438 m_FocusView->setStarsHFREnabled(
true);
6441 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6442 m_OpsFocusProcess->focusStarPSFLabel->hide();
6443 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6444 m_OpsFocusProcess->focusStarPSF->hide();
6447 case FOCUS_STAR_HFR_ADJ:
6448 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6449 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6450 m_FocusView->setStarsHFREnabled(
false);
6453 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6454 m_OpsFocusProcess->focusStarPSFLabel->hide();
6455 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6456 m_OpsFocusProcess->focusStarPSF->hide();
6459 case FOCUS_STAR_FWHM:
6460 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6461 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6463 m_FocusView->setStarsHFREnabled(
false);
6466 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSFLabel, 2, 2);
6467 m_OpsFocusProcess->focusStarPSFLabel->show();
6468 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSF, 2, 3);
6469 m_OpsFocusProcess->focusStarPSF->show();
6472 case FOCUS_STAR_NUM_STARS:
6473 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6474 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6475 m_FocusView->setStarsHFREnabled(
true);
6478 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6479 m_OpsFocusProcess->focusStarPSFLabel->hide();
6480 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6481 m_OpsFocusProcess->focusStarPSF->hide();
6484 case FOCUS_STAR_FOURIER_POWER:
6485 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6486 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6487 m_FocusView->setStarsHFREnabled(
true);
6490 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6491 m_OpsFocusProcess->focusStarPSFLabel->hide();
6492 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6493 m_OpsFocusProcess->focusStarPSF->hide();
6501void Focus::setStarPSF(StarPSF starPSF)
6503 m_StarPSF = starPSF;
6506void Focus::setStarUnits(StarUnits starUnits)
6508 m_StarUnits = starUnits;
6511void Focus::setWalk(FocusWalk
walk)
6513 if (m_OpsFocusMechanics->focusWalk->currentIndex() == -1)
6516 static bool first =
true;
6517 if (!first && m_FocusWalk ==
walk)
6526 case FOCUS_WALK_CLASSIC:
6527 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumStepsLabel,
6528 m_OpsFocusMechanics->focusOutStepsLabel);
6529 m_OpsFocusMechanics->focusNumStepsLabel->hide();
6530 m_OpsFocusMechanics->focusOutStepsLabel->show();
6531 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumSteps,
6532 m_OpsFocusMechanics->focusOutSteps);
6533 m_OpsFocusMechanics->focusNumSteps->hide();
6534 m_OpsFocusMechanics->focusOutSteps->show();
6537 case FOCUS_WALK_FIXED_STEPS:
6538 case FOCUS_WALK_CFZ_SHUFFLE:
6539 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
6540 m_OpsFocusMechanics->focusNumStepsLabel);
6541 m_OpsFocusMechanics->focusOutStepsLabel->hide();
6542 m_OpsFocusMechanics->focusNumStepsLabel->show();
6543 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
6544 m_OpsFocusMechanics->focusNumSteps);
6545 m_OpsFocusMechanics->focusOutSteps->hide();
6546 m_OpsFocusMechanics->focusNumSteps->show();
6555double Focus::getStarUnits(
const StarMeasure starMeasure,
const StarUnits starUnits)
6557 if (starUnits == FOCUS_UNITS_PIXEL || starMeasure == FOCUS_STAR_NUM_STARS || starMeasure == FOCUS_STAR_FOURIER_POWER)
6559 if (m_CcdPixelSizeX <= 0.0 || m_FocalLength <= 0.0)
6563 return m_CcdPixelSizeX / m_FocalLength * 206.265;
6566void Focus::calcCFZ()
6569 double cfzCameraSteps = calcCameraCFZ() / m_CFZUI->focusCFZStepSize->value();
6571 switch(
static_cast<Focus::CFZAlgorithm
> (m_CFZUI->focusCFZAlgorithm->currentIndex()))
6573 case Focus::FOCUS_CFZ_CLASSIC:
6575 cfzMicrons = 4.88f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f *
6576 pow(m_CFZUI->focusCFZFNumber->value(), 2.0f);
6577 cfzSteps =
cfzMicrons / m_CFZUI->focusCFZStepSize->value();
6579 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4.88 t λ f²");
6581 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
6583 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
6586 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
6587 m_CFZUI->focusCFZTauLabel->hide();
6588 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
6589 m_CFZUI->focusCFZTau->hide();
6590 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
6591 m_CFZUI->focusCFZSeeingLabel->hide();
6592 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
6593 m_CFZUI->focusCFZSeeing->hide();
6596 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
6597 m_CFZUI->focusCFZToleranceLabel->show();
6598 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
6599 m_CFZUI->focusCFZTolerance->show();
6600 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
6601 m_CFZUI->focusCFZWavelengthLabel->show();
6602 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
6603 m_CFZUI->focusCFZWavelength->show();
6606 case Focus::FOCUS_CFZ_WAVEFRONT:
6608 cfzMicrons = 4.0f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f *
pow(
6609 m_CFZUI->focusCFZFNumber->value(),
6611 cfzSteps =
cfzMicrons / m_CFZUI->focusCFZStepSize->value();
6613 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4 t λ f²");
6615 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
6617 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
6620 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
6621 m_CFZUI->focusCFZTauLabel->hide();
6622 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
6623 m_CFZUI->focusCFZTau->hide();
6624 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
6625 m_CFZUI->focusCFZSeeingLabel->hide();
6626 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
6627 m_CFZUI->focusCFZSeeing->hide();
6630 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
6631 m_CFZUI->focusCFZToleranceLabel->show();
6632 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
6633 m_CFZUI->focusCFZTolerance->show();
6634 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
6635 m_CFZUI->focusCFZWavelengthLabel->show();
6636 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
6637 m_CFZUI->focusCFZWavelength->show();
6640 case Focus::FOCUS_CFZ_GOLD:
6642 cfzMicrons = 0.00225f *
pow(m_CFZUI->focusCFZTau->value(), 0.5f) * m_CFZUI->focusCFZSeeing->value()
6643 *
pow(m_CFZUI->focusCFZFNumber->value(), 2.0f) * m_CFZUI->focusCFZAperture->value();
6644 cfzSteps =
cfzMicrons / m_CFZUI->focusCFZStepSize->value();
6646 m_CFZUI->focusCFZFormula->setText(
"CFZ = 0.00225 √τ θ f² A");
6648 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
6650 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
6653 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZToleranceLabel);
6654 m_CFZUI->focusCFZToleranceLabel->hide();
6655 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTolerance);
6656 m_CFZUI->focusCFZTolerance->hide();
6657 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelengthLabel);
6658 m_CFZUI->focusCFZWavelengthLabel->hide();
6659 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelength);
6660 m_CFZUI->focusCFZWavelength->hide();
6663 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTauLabel, 1, 0);
6664 m_CFZUI->focusCFZTauLabel->show();
6665 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTau, 1, 1);
6666 m_CFZUI->focusCFZTau->show();
6667 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeingLabel, 2, 0);
6668 m_CFZUI->focusCFZSeeingLabel->show();
6669 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeing, 2, 1);
6670 m_CFZUI->focusCFZSeeing->show();
6673 if (linearFocuser !=
nullptr && linearFocuser->isDone())
6674 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
6675 m_CFZUI->focusCFZDisplayVCurve->isChecked());
6681double Focus::calcCameraCFZ()
6683 return m_CcdPixelSizeX *
pow(m_CFZUI->focusCFZFNumber->value(), 2.0) * m_CFZUI->focusCFZAperture->value() / 1000.0;
6686void Focus::wavelengthChanged()
6689 if (m_FilterManager)
6691 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
6696void Focus::resetCFZToOT()
6699 m_CFZUI->focusCFZFNumber->setValue(m_FocalRatio);
6700 m_CFZUI->focusCFZAperture->setValue(m_Aperture);
6703 if (m_FilterManager)
6705 if (m_CFZUI->focusCFZWavelength->value() != m_FilterManager->getFilterWavelength(
filter()))
6706 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
6715 m_AdvisorMap = focusAdvisorOTDefaults(
OTName);
6718 bool longFL = m_FocalLength > 1500;
6719 double imageScale = getStarUnits(FOCUS_STAR_HFR, FOCUS_UNITS_ARCSEC);
6724 m_AdvisorUI->focusAdvLabel->setText(
QString(
"Recommendations: %1 FL=%2 ImageScale=%3")
6725 .arg(m_ScopeType).arg(m_FocalLength).arg(
imageScale, 0,
'f', 2));
6733 if (m_Focuser && m_Focuser->getDeviceName() == FOCUSER_SIMULATOR)
6735 m_AdvisorMap.insert(
"focusTicks", stepSize);
6739 stepSize = m_AdvisorMap.value(
"focusTicks", stepSize).toInt(&ok);
6740 if (!ok || stepSize <= 0)
6743 m_AdvisorUI->focusAdvSteps->setValue(stepSize);
6746 str =
"Camera & Filter Wheel Parameters:\n";
6749 double exposure =
longFL ? 4.0 : 2.0;
6751 m_AdvisorMap.insert(
"focusExposure", exposure);
6754 exposure = m_AdvisorMap.value(
"focusExposure", 2.0).toDouble(&ok);
6755 if (!ok || exposure <= 0)
6774 m_AdvisorMap.insert(
"focusBinning", binning);
6781 binning = m_AdvisorMap.value(
"focusBinning",
"").toString();
6786 str.
append(
"Gain ***Set Manually to Unity Gain***\n");
6790 str.
append(
"Filter ***Set Manually***");
6791 m_AdvisorUI->focusAdvCameraLabel->setToolTip(str);
6794 str =
"Settings Parameters:\n";
6801 autoSelectStar = m_AdvisorMap.value(
"focusAutoStarEnabled",
false).toBool();
6809 m_AdvisorMap.insert(
"useFocusDarkFrame",
darkFrame);
6811 darkFrame = m_AdvisorMap.value(
"useFocusDarkFrame",
false).toBool();
6818 m_AdvisorMap.insert(
"focusUseFullField",
fullFrame);
6819 m_AdvisorMap.insert(
"focusSubFrame", !
fullFrame);
6822 fullFrame = m_AdvisorMap.value(
"focusUseFullField",
false).toBool();
6830 double outer = 80.0;
6834 m_AdvisorMap.insert(
"focusNoMaskRB",
false);
6835 m_AdvisorMap.insert(
"focusRingMaskRB",
true);
6836 m_AdvisorMap.insert(
"focusMosaicMaskRB",
false);
6837 m_AdvisorMap.insert(
"focusFullFieldInnerRadius",
inner);
6838 m_AdvisorMap.insert(
"focusFullFieldOuterRadius",
outer);
6843 bool noMask = m_AdvisorMap.value(
"focusNoMaskRB",
false).toBool();
6844 bool ringMask = m_AdvisorMap.value(
"focusRingMaskRB",
false).toBool();
6845 bool mosaicMask = m_AdvisorMap.value(
"focusMosaicMaskRB",
false).toBool();
6850 inner = m_AdvisorMap.value(
"focusFullFieldInnerRadius",
inner).toDouble(&ok);
6853 outer = m_AdvisorMap.value(
"focusFullFieldOuterRadius",
outer).toDouble(&ok);
6865 bool adaptiveFocus =
false;
6867 m_AdvisorMap.
insert(
"focusAdaptive", adaptiveFocus);
6869 adaptiveFocus = m_AdvisorMap.value(
"focusAdaptive",
false).toBool();
6870 str.
append(
QString(
"Adaptive Focus=%1\n").arg(adaptiveFocus ?
"on" :
"off"));
6880 m_AdvisorUI->focusAdvSettingsLabel->setToolTip(str);
6883 str =
"Process Parameters:\n";
6888 m_AdvisorMap.insert(
"focusDetection",
detection);
6890 detection = m_AdvisorMap.value(
"focusDetection",
false).toString();
6896 QString algorithm =
"Linear 1 Pass";
6898 m_AdvisorMap.insert(
"focusAlgorithm", algorithm);
6900 algorithm = m_AdvisorMap.value(
"focusAlgorithm", algorithm).toString();
6904 QString curveFit =
"Hyperbola";
6906 m_AdvisorMap.
insert(
"focusCurveFit", curveFit);
6908 curveFit = m_AdvisorMap.value(
"focusCurveFit", curveFit).toString();
6914 m_AdvisorMap.insert(
"focusStarMeasure",
measure);
6916 measure = m_AdvisorMap.value(
"focusStarMeasure",
measure).toString();
6920 bool useWeights =
true;
6922 m_AdvisorMap.insert(
"focusUseWeights", useWeights);
6924 useWeights = m_AdvisorMap.value(
"focusUseWeights", useWeights).toBool();
6925 str.
append(
QString(
"Use Weights=%1\n").arg(useWeights ?
"on" :
"off"));
6930 m_AdvisorMap.insert(
"focusR2Limit",
r2);
6933 r2 = m_AdvisorMap.value(
"focusR2Limit",
r2).toDouble(&ok);
6940 bool refineCurveFit =
true;
6942 m_AdvisorMap.
insert(
"focusRefineCurveFit", refineCurveFit);
6944 refineCurveFit = m_AdvisorMap.value(
"focusRefineCurveFit", refineCurveFit).toBool();
6945 str.
append(
QString(
"Refine Curve Fit=%1\n").arg(refineCurveFit ?
"on" :
"off"));
6950 m_AdvisorMap.
insert(
"focusFramesCount", frameCount);
6953 frameCount = m_AdvisorMap.value(
"focusFramesCount", frameCount).toInt(&ok);
6954 if (!ok || frameCount < 1)
6974 double outlierRejection = 0.2;
6978 m_AdvisorMap.insert(
"focusDonut", donutBuster);
6979 m_AdvisorMap.insert(
"focusTimeDilation",
timeDilation);
6980 m_AdvisorMap.insert(
"focusOutlierRejection", outlierRejection);
6984 donutBuster = m_AdvisorMap.value(
"focusDonut", donutBuster).toBool();
6985 str.
append(
QString(
"Donut Buster=%1").arg(donutBuster ?
"on" :
"off"));
6987 m_AdvisorUI->focusAdvProcessLabel->setToolTip(str);
6990 str =
"Mechanics Parameters:\n";
6995 m_AdvisorMap.insert(
"focusWalk",
walk);
6997 walk = m_AdvisorMap.value(
"focusWalk",
measure).toString();
7003 m_AdvisorMap.insert(
"focusSettleTime",
settleTime);
7015 m_AdvisorMap.insert(
"focusNumSteps", numSteps);
7018 numSteps = m_AdvisorMap.value(
"focusNumSteps", numSteps).toInt(&ok);
7019 if (!ok || numSteps < 5)
7025 int maxTravel = m_OpsFocusMechanics->focusMaxTravel->maximum();
7027 m_AdvisorMap.
insert(
"focusMaxTravel", maxTravel);
7030 maxTravel = m_AdvisorMap.value(
"focusMaxTravel", maxTravel).toInt(&ok);
7031 if (!ok || maxTravel < 0)
7032 maxTravel = m_OpsFocusMechanics->focusMaxTravel->maximum();
7037 str.
append(
"Backlash ***Set Manually***\n");
7038 str.
append(
"AF Overscan ***Set Manually***\n");
7053 int captureTimeout = 30;
7055 m_AdvisorMap.
insert(
"focusCaptureTimeout", captureTimeout);
7058 captureTimeout = m_AdvisorMap.value(
"focusCaptureTimeout", captureTimeout).toInt(&ok);
7059 if (!ok || captureTimeout < 0)
7060 captureTimeout = 30;
7062 str.
append(
QString(
"Capture Timeout=%1\n").arg(captureTimeout));
7076 m_AdvisorUI->focusAdvMechanicsLabel->setToolTip(str);
7081 m_AdvisorMap.insert(
"focusSEPProfile", profile);
7083 profile = m_AdvisorMap.value(
"focusSEPProfile", profile).toString();
7084 str =
QString(
"SEP Profile=%1").
arg(profile);
7085 m_AdvisorUI->focusAdvSEPLabel->setToolTip(str);
7089QVariantMap Focus::focusAdvisorOTDefaults(
const QString OTName)
7097 for (
auto tName : OpticalTrainManager::Instance()->getTrainNames())
7101 auto tFocuser = OpticalTrainManager::Instance()->getFocuser(
tName);
7104 auto tScope = OpticalTrainManager::Instance()->getScope(
tName);
7110 auto tID = OpticalTrainManager::Instance()->id(
tName);
7111 OpticalTrainSettings::Instance()->setOpticalTrainID(
tID);
7112 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Focus);
7113 if (settings.isValid())
7116 map = settings.toJsonObject().toVariantMap();
7122 auto tReducer = OpticalTrainManager::Instance()->getReducer(
tName);
7135 if (m_Focuser && m_Focuser->getDeviceName() == FOCUSER_SIMULATOR)
7139 stepSize =
map.value(
"focusTicks", stepSize).toInt() *
pow(m_FocalRatio, 2.0) /
pow(
tFocalRatio, 2.0);
7141 map.insert(
"focusTicks", stepSize);
7146 auto id = OpticalTrainManager::Instance()->id(
OTName);
7147 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
7152void Focus::focusAdvisorHelp()
7154 QString str =
i18n(
"Focus Advisor (FA) is designed to help you with focus parameters.\n"
7155 "It will not necessarily give you the perfect combination of parameters, you will "
7156 "need to experiment yourself, but it will give you a basic set of parameters to "
7157 "achieve focus.\n\n"
7158 "FA will recommend values for the majority of parameters. A few, however, will need "
7159 "extra work from you to setup. These are identified below along with a basic explanation "
7160 "of how to set them.\n\n"
7161 "The first step is to set backlash. Your focuser manual will likely explain how to do "
7162 "this. Once you have a value for backlash for your system, set either the Backlash field "
7163 "to have the driver perform backlash compensation or the AF Overscan field to have Autofocus "
7164 "perform backlash compensation. Set only one field and set the other to 0. If you are "
7165 "unsure which to set, AF Overscan is recommended.\n\n"
7166 "The second step is to set Step Size. If you are aware of an approximate value enter it here "
7167 "otherwise this can be defaulted from the Critical Focus Zone (CFZ) for your equipment - so "
7168 "configure this now in the CFZ tab and restart Focus Advisor.\n\n");
7170 str.
append(
i18n(
"The third step is to set the remaining focus parameters to sensible values. Focus Advisor "
7171 "will suggest values for 5 categories of parameters. Check the associated Update box to "
7172 "accept these recommendations when you press Update Params.\n"
7173 "1. Camera Properties - Note you need to ensure Gain is set appropriately, e.g. unity gain.\n"
7174 "2. Focus Settings (Options Popup): These all have recommendations.\n"
7175 "3. Focus Process (Options Popup): These all have recommendations.\n"
7176 "4. Focus Mechanics (Options Popup): Note Step Size is dealt with above.\n"
7177 "5. SEP Parameters (Options Popup): Set the appropriate profile to its default values.\n\n"
7178 "Now move the focuser to approximate focus and select a broadband filter, e.g. Luminance\n"
7179 "You are now ready to start an Autofocus run."));
7185void Focus::focusAdvisorAction(
bool forceAll)
7189 setAllSettings(m_AdvisorMap);
7195 disconnectSyncSettings();
7197 if (m_AdvisorUI->focusAdvStepSize->isChecked())
7198 m_OpsFocusMechanics->focusTicks->setValue(m_AdvisorUI->focusAdvSteps->value());
7200 if (m_AdvisorUI->focusAdvCamera->isChecked())
7204 if (m_FilterManager)
7209 syncControl(m_AdvisorMap,
"focusBinning",
focusBinning);
7212 if (m_AdvisorUI->focusAdvSettingsTab->isChecked())
7215 syncControl(m_AdvisorMap,
"focusAutoStarEnabled", m_OpsFocusSettings->focusAutoStarEnabled);
7216 syncControl(m_AdvisorMap,
"useFocusDarkFrame", m_OpsFocusSettings->useFocusDarkFrame);
7217 syncControl(m_AdvisorMap,
"focusUseFullField", m_OpsFocusSettings->focusUseFullField);
7218 syncControl(m_AdvisorMap,
"focusSubFrame", m_OpsFocusSettings->focusSubFrame);
7219 syncControl(m_AdvisorMap,
"focusNoMaskRB", m_OpsFocusSettings->focusNoMaskRB);
7220 if (m_AdvisorMap.value(
"focusRingMaskRB",
false).toBool())
7222 syncControl(m_AdvisorMap,
"focusRingMaskRB", m_OpsFocusSettings->focusRingMaskRB);
7223 syncControl(m_AdvisorMap,
"focusFullFieldInnerRadius", m_OpsFocusSettings->focusFullFieldInnerRadius);
7224 syncControl(m_AdvisorMap,
"focusFullFieldOuterRadius", m_OpsFocusSettings->focusFullFieldOuterRadius);
7226 syncControl(m_AdvisorMap,
"focusMosaicMaskRB", m_OpsFocusSettings->focusMosaicMaskRB);
7227 syncControl(m_AdvisorMap,
"focusAdaptive", m_OpsFocusSettings->focusAdaptive);
7228 syncControl(m_AdvisorMap,
"focusAdaptStart", m_OpsFocusSettings->focusAdaptStart);
7231 if (m_AdvisorUI->focusAdvProcessTab->isChecked())
7234 syncControl(m_AdvisorMap,
"focusDetection", m_OpsFocusProcess->focusDetection);
7235 syncControl(m_AdvisorMap,
"focusAlgorithm", m_OpsFocusProcess->focusAlgorithm);
7236 syncControl(m_AdvisorMap,
"focusCurveFit", m_OpsFocusProcess->focusCurveFit);
7237 syncControl(m_AdvisorMap,
"focusStarMeasure", m_OpsFocusProcess->focusStarMeasure);
7238 syncControl(m_AdvisorMap,
"focusUseWeights", m_OpsFocusProcess->focusUseWeights);
7239 syncControl(m_AdvisorMap,
"focusR2Limit", m_OpsFocusProcess->focusR2Limit);
7240 syncControl(m_AdvisorMap,
"focusRefineCurveFit", m_OpsFocusProcess->focusRefineCurveFit);
7241 syncControl(m_AdvisorMap,
"focusFramesCount", m_OpsFocusProcess->focusFramesCount);
7242 syncControl(m_AdvisorMap,
"focusHFRFramesCount", m_OpsFocusProcess->focusHFRFramesCount);
7243 syncControl(m_AdvisorMap,
"focusDonut", m_OpsFocusProcess->focusDonut);
7244 syncControl(m_AdvisorMap,
"focusTimeDilation", m_OpsFocusProcess->focusTimeDilation);
7245 syncControl(m_AdvisorMap,
"focusOutlierRejection", m_OpsFocusProcess->focusOutlierRejection);
7246 syncControl(m_AdvisorMap,
"focusScanStartPos", m_OpsFocusProcess->focusScanStartPos);
7249 if (m_AdvisorUI->focusAdvMechanicsTab->isChecked())
7252 syncControl(m_AdvisorMap,
"focusWalk", m_OpsFocusMechanics->focusWalk);
7253 syncControl(m_AdvisorMap,
"focusSettleTime", m_OpsFocusMechanics->focusSettleTime);
7254 syncControl(m_AdvisorMap,
"focusNumSteps", m_OpsFocusMechanics->focusNumSteps);
7255 syncControl(m_AdvisorMap,
"focusMaxTravel", m_OpsFocusMechanics->focusMaxTravel);
7256 syncControl(m_AdvisorMap,
"focusOverscanDelay", m_OpsFocusMechanics->focusOverscanDelay);
7257 syncControl(m_AdvisorMap,
"focusCaptureTimeout", m_OpsFocusMechanics->focusCaptureTimeout);
7258 syncControl(m_AdvisorMap,
"focusMotionTimeout", m_OpsFocusMechanics->focusMotionTimeout);
7261 if (m_AdvisorUI->focusAdvSEP->isChecked())
7265 syncControl(m_AdvisorMap,
"focusSEPProfile", m_OpsFocusProcess->focusSEPProfile);
7269 for (
auto &key : m_AdvisorMap.keys())
7271 auto value = m_AdvisorMap[key];
7273 Options::self()->setProperty(key.
toLatin1(), value);
7275 m_Settings[key] = value;
7276 m_GlobalSettings[key] = value;
7280 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(
opticalTrainCombo->currentText()));
7281 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
7284 connectSyncSettings();
7287 m_CurveFit =
static_cast<CurveFitting::CurveFit
> (m_OpsFocusProcess->focusCurveFit->currentIndex());
7288 setFocusDetection(
static_cast<StarAlgorithm
> (m_OpsFocusProcess->focusDetection->currentIndex()));
7289 setCurveFit(
static_cast<CurveFitting::CurveFit
>(m_OpsFocusProcess->focusCurveFit->currentIndex()));
7290 setStarMeasure(
static_cast<StarMeasure
>(m_OpsFocusProcess->focusStarMeasure->currentIndex()));
7291 setWalk(
static_cast<FocusWalk
>(m_OpsFocusMechanics->focusWalk->currentIndex()));
7299bool Focus::scopeHasObstruction(
QString scopeType)
7301 if (scopeType ==
"Refractor" || scopeType ==
"Kutter (Schiefspiegler)")
7307void Focus::setState(FocusState
newState)
7309 qCDebug(
KSTARS_EKOS_FOCUS) <<
"Focus State changes from" << getFocusStatusString(m_state) <<
"to" << getFocusStatusString(
7312 emit newStatus(m_state);
7315void Focus::initView()
7320 m_FocusView->createFloatingToolBar();
7322 vlayout->addWidget(m_FocusView.get());
7325 m_FocusView->setStarsEnabled(
true);
7326 m_FocusView->setStarsHFREnabled(
true);
7329QVariantMap Focus::getAllSettings()
const
7331 QVariantMap settings;
7365void Focus::setAllSettings(
const QVariantMap &settings)
7369 disconnectSyncSettings();
7371 for (
auto &name : settings.keys())
7377 syncControl(settings, name, comboBox);
7385 syncControl(settings, name, doubleSpinBox);
7393 syncControl(settings, name,
spinBox);
7401 syncControl(settings, name,
checkbox);
7409 syncControl(settings, name,
groupbox);
7417 syncControl(settings, name, splitter);
7431 for (
auto &key : settings.keys())
7433 auto value = settings[key];
7435 Options::self()->setProperty(key.
toLatin1(), value);
7437 m_Settings[key] = value;
7438 m_GlobalSettings[key] = value;
7441 emit settingsUpdated(getAllSettings());
7444 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(
opticalTrainCombo->currentText()));
7445 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
7448 connectSyncSettings();
7451 m_CurveFit =
static_cast<CurveFitting::CurveFit
> (m_OpsFocusProcess->focusCurveFit->currentIndex());
7452 setFocusDetection(
static_cast<StarAlgorithm
> (m_OpsFocusProcess->focusDetection->currentIndex()));
7453 setCurveFit(
static_cast<CurveFitting::CurveFit
>(m_OpsFocusProcess->focusCurveFit->currentIndex()));
7454 setStarMeasure(
static_cast<StarMeasure
>(m_OpsFocusProcess->focusStarMeasure->currentIndex()));
7455 setWalk(
static_cast<FocusWalk
>(m_OpsFocusMechanics->focusWalk->currentIndex()));
7459bool Focus::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
7472 const int value = settings[key].toInt(&ok);
7475 pSB->setValue(value);
7481 const double value = settings[key].toDouble(&ok);
7484 pDSB->setValue(value);
7490 const bool value = settings[key].toBool();
7491 if (value !=
pCB->isChecked())
7492 pCB->setChecked(value);
7497 const bool value = settings[key].toBool();
7498 if (value !=
pGB->isChecked())
7499 pGB->setChecked(value);
7504 const bool value = settings[key].toBool();
7512 const QString value = settings[key].toString();
7526void Focus::setupOpticalTrainManager()
7528 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Focus::refreshOpticalTrain);
7535 ProfileSettings::Instance()->setOneSetting(ProfileSettings::FocusOpticalTrain,
7537 refreshOpticalTrain();
7538 emit trainChanged();
7542void Focus::refreshOpticalTrain()
7548 trainB->setEnabled(
true);
7550 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::FocusOpticalTrain);
7554 auto id = trainID.
toUInt();
7557 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
7563 auto name = OpticalTrainManager::Instance()->name(
id);
7571 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
7573 auto focuser = OpticalTrainManager::Instance()->getFocuser(name);
7574 setFocuser(focuser);
7576 auto scope = OpticalTrainManager::Instance()->getScope(name);
7577 double reducer = OpticalTrainManager::Instance()->getReducer(name);
7578 setScopeDetails(scope,
reducer);
7580 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Focus);
7581 if (settings.isValid())
7584 auto map = settings.toJsonObject().toVariantMap();
7585 if (map != m_Settings)
7586 setAllSettings(map);
7589 auto camera = OpticalTrainManager::Instance()->getCamera(name);
7595 auto nvp = camera->getNumber(
"CCD_INFO");
7598 m_CcdPixelSizeX = 0.0;
7599 m_CcdWidth = m_CcdHeight = 0;
7603 auto np =
nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
7605 m_CcdPixelSizeX = np->getValue();
7606 np =
nvp->findWidgetByName(
"CCD_MAX_X");
7608 m_CcdWidth = np->getValue();
7609 np =
nvp->findWidgetByName(
"CCD_MAX_Y");
7611 m_CcdHeight = np->getValue();
7616 auto filterWheel = OpticalTrainManager::Instance()->getFilterWheel(name);
7617 setFilterWheel(filterWheel);
7625 focusAdvisorSetup(name);
7626 focusAdvisorAction(
true);
7628 focusAdvisorSetup(
"");
7637 m_Aperture = scope[
"aperture"].toDouble(-1);
7638 m_FocalLength = scope[
"focal_length"].toDouble(-1);
7639 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
7640 m_ScopeType = scope[
"type"].toString();
7644 if (m_Reducer > 0.0)
7645 m_FocalLength *= m_Reducer;
7648 if (m_FocalRatio <= 0.0)
7650 m_FocalRatio = (m_Aperture > 0.001) ? m_FocalLength / m_Aperture : 0.0f;
7651 else if (m_Aperture < 0.0)
7653 m_Aperture = m_FocalLength / m_FocalRatio;
void drawPolynomial(PolynomialFit *poly, bool isVShape, bool activate, bool plot=true)
draw the approximating polynomial into the HFR V-graph
void toggleVideo(bool enabled)
toggleVideo Turn on and off video streaming if supported by the camera.
void checkTemperatureSource(const QString &name=QString())
Check temperature source and make sure information is updated accordingly.
void startFraming()
startFraming Begins continuous capture of the CCD and calculates HFR every frame.
void newHFRPlotPosition(double pos, double hfr, double sigma, bool outlier, int pulseDuration, bool plot=true)
new HFR plot position with sigma
void redrawHFRPlot(PolynomialFit *poly, double solutionPosition, double solutionValue)
redraw the entire HFR plot
void clearDataPoints()
clearDataPoints Remove all data points from HFR plots
void appendLogText(const QString &)
setFocusStatus Upon completion of the focusing process, set its status (fail or pass) and reset focus...
void updateProperty(INDI::Property prop)
updateProperty Read focus number properties of interest as they arrive from the focuser driver and pr...
void focusStarSelected(int x, int y)
focusStarSelected The user selected a focus star, save its coordinates and subframe it if subframing ...
void processData(const QSharedPointer< FITSData > &data)
newFITS A new FITS blob is received by the CCD driver.
void initHFRPlot(QString str, double starUnits, bool minimum, bool useWeights, bool showPosition)
initialize the HFR V plot
Q_SCRIPTABLE Q_NOREPLY void resetFrame()
DBUS interface function.
void processTemperatureSource(INDI::Property prop)
processTemperatureSource Updates focus temperature source.
void drawCFZ(double minPosition, double minValue, int m_cfzSteps, bool plt)
Draw Critical Focus Zone on graph.
void finalUpdates(const QString &title, bool plot=true)
final updates after focus run comopletes on the focus plot
void minimumFound(double solutionPosition, double solutionValue, bool plot=true)
Focus solution with minimal HFR found.
void setTitle(const QString &title, bool plot=true)
draw a title on the focus plot
void drawCurve(CurveFitting *curve, bool isVShape, bool activate, bool plot=true)
draw the curve into the HFR V-graph
CameraChip class controls a particular chip in camera.
Camera class controls an INDI Camera device.
@ ERROR_SAVE
INDI Camera error.
Focuser class handles control of INDI focuser devices.
KPageWidgetItem * addPage(QWidget *page, const QString &itemName, const QString &pixmapName=QString(), const QString &header=QString(), bool manage=true)
void setIcon(const QIcon &icon)
static KStars * Instance()
The sky coordinates of a point in the sky.
An angle, stored as degrees, but expressible in many ways.
Q_SCRIPTABLE Q_NOREPLY void capture(double settleTime=0.0)
DBUS interface function.
Q_SCRIPTABLE bool focusOut(int ms=-1)
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void abort()
DBUS interface function.
Q_SCRIPTABLE bool focusIn(int ms=-1)
DBUS interface function.
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
KIOCORE_EXPORT QString number(KIO::filesize_t size)
QString path(const QString &relativePath)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
KIOCORE_EXPORT QString dir(const QString &fileClass)
QString name(StandardShortcut id)
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
QByteArray fromBase64(const QByteArray &base64, Base64Options options)
QByteArray toBase64(Base64Options options) const const
void stateChanged(int state)
void activated(int index)
void currentIndexChanged(int index)
void currentTextChanged(const QString &text)
QDateTime currentDateTime()
QString toString(QStringView format, QCalendar cal) const const
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
QString filePath(const QString &fileName) const const
void valueChanged(double d)
bool exists() const const
QIcon fromTheme(const QString &name)
QByteArray saveState() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromUtf8(QByteArrayView str)
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
QString number(double n, char format, int precision)
QByteArray toLatin1() const const
QByteArray toUtf8() const const
QTextStream & center(QTextStream &stream)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl fromLocalFile(const QString &localFile)
bool isValid() const const
bool toBool() const const
double toDouble(bool *ok) const const
int toInt(bool *ok) const const
QString toString() const const
uint toUInt(bool *ok) const const