7#include "adaptivefocus.h"
8#include "focusadvisor.h"
9#include "focusadaptor.h"
10#include "focusalgorithms.h"
12#if defined(HAVE_OPENCV)
13#include "focusblurriness.h"
15#include "aberrationinspector.h"
16#include "aberrationinspectorutils.h"
18#include "kstarsdata.h"
20#include "stellarsolver.h"
23#include "ekos/guide/guide.h"
24#include "ekos/manager.h"
27#include "auxiliary/kspaths.h"
28#include "auxiliary/ksmessagebox.h"
31#include "ekos/auxiliary/darklibrary.h"
32#include "ekos/auxiliary/darkprocessor.h"
33#include "ekos/auxiliary/profilesettings.h"
34#include "ekos/auxiliary/opticaltrainmanager.h"
35#include "ekos/auxiliary/opticaltrainsettings.h"
36#include "ekos/auxiliary/filtermanager.h"
37#include "ekos/auxiliary/stellarsolverprofileeditor.h"
40#include "fitsviewer/fitsdata.h"
41#include "fitsviewer/fitsview.h"
42#include "fitsviewer/fitsviewer.h"
45#include "indi/indifilterwheel.h"
46#include "ksnotification.h"
47#include "kconfigdialog.h"
49#include <basedevice.h>
50#include <gsl/gsl_fit.h>
51#include <gsl/gsl_vector.h>
52#include <gsl/gsl_min.h>
54#include <ekos_focus_debug.h>
55#include <config-kstars.h>
59#ifdef HAVE_DATAVISUALIZATION
60#include "aberrationinspector.h"
61#include "aberrationinspectorutils.h"
64#define MAXIMUM_ABS_ITERATIONS 51
65#define MAXIMUM_RESET_ITERATIONS 3
66#define MAXIMUM_RESTART_ITERATIONS 3
67#define AUTO_STAR_TIMEOUT 45000
68#define MINIMUM_PULSE_TIMER 32
69#define MAX_RECAPTURE_RETRIES 3
70#define MINIMUM_POLY_SOLUTIONS 2
80 m_opsDialogName =
QString(
"focussettings %1").
arg(
id);
86 qRegisterMetaType<Ekos::FocusState>(
"Ekos::FocusState");
87 qDBusRegisterMetaType<Ekos::FocusState>();
88 new FocusAdaptor(
this);
107 loadGlobalSettings();
110 connectSyncSettings();
112 connect(focusAdvisor.get(), &FocusAdvisor::newStage,
this, &Focus::newFocusAdvisorStage);
113 connect(focusAdvisor.get(), &FocusAdvisor::newMessage,
this, &Focus::newFocusAdvisorMessage);
120 for (
auto &button : qButtons)
121 button->setAutoDefault(
false);
123 appendLogText(
i18n(
"Idle."));
126 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
127 m_FocusMotionTimer.setSingleShot(
true);
130 m_OpsFocusProcess->editFocusProfile->setIcon(
QIcon::fromTheme(
"document-edit"));
135 KConfigDialog *optionsEditor = new KConfigDialog(this,
"OptionsProfileEditor", Options::self());
136 optionsProfileEditor = new StellarSolverProfileEditor(this, Ekos::FocusProfiles, optionsEditor);
138 optionsEditor->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
140 KPageWidgetItem *mainPage = optionsEditor->addPage(optionsProfileEditor, i18n(
"Focus Options Profile Editor"));
141 mainPage->setIcon(QIcon::fromTheme(
"configure"));
142 connect(optionsProfileEditor, &StellarSolverProfileEditor::optionsProfilesUpdated, this, &Focus::loadStellarSolverProfiles);
143 optionsProfileEditor->loadProfile(m_OpsFocusProcess->focusSEPProfile->currentText());
144 optionsEditor->show();
147 loadStellarSolverProfiles();
161 m_DarkProcessor =
new DarkProcessor(
this);
163 connect(m_DarkProcessor, &DarkProcessor::darkFrameCompleted,
this, [
this](
bool completed)
165 m_OpsFocusSettings->useFocusDarkFrame->setChecked(completed);
166 m_FocusView->setProperty(
"suspended",
false);
169 m_FocusView->rescale(ZOOM_KEEP_LEVEL);
170 m_FocusView->updateFrame();
172 setCaptureComplete();
176 setupOpticalTrainManager();
177 refreshOpticalTrain();
180 connectFilterManager();
184void Focus::prepareGUI()
194 m_OpsFocusSettings =
new OpsFocusSettings(opsDialogName());
202 m_OpsFocusProcess =
new OpsFocusProcess(opsDialogName());
203 page = dialog->
addPage(m_OpsFocusProcess,
i18n(
"Process"),
nullptr,
i18n(
"Focus Process"),
false);
206 m_OpsFocusMechanics =
new OpsFocusMechanics(opsDialogName());
207 page = dialog->
addPage(m_OpsFocusMechanics,
i18n(
"Mechanics"),
nullptr,
i18n(
"Focus Mechanics"),
false);
211 m_CFZDialog =
new QDialog(
this);
212 m_CFZUI.reset(
new Ui::focusCFZDialog());
213 m_CFZUI->setupUi(m_CFZDialog);
219 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
220 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
221 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
222 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
223 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
224 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThreshold);
225 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
226 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
227 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
228 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusTolerance);
229 delete m_OpsFocusProcess->gridLayoutProcessBucket;
232 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
233 m_OpsFocusMechanics->focusNumStepsLabel);
234 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
235 m_OpsFocusMechanics->focusNumSteps);
239 for (
int i = 0; i < m_OpsFocusProcess->focusStarMeasure->count(); i++)
240 m_StarMeasureText.append(m_OpsFocusProcess->focusStarMeasure->itemText(i));
241 for (
int i = 0; i < m_OpsFocusProcess->focusCurveFit->count(); i++)
242 m_CurveFitText.append(m_OpsFocusProcess->focusCurveFit->itemText(i));
243 for (
int i = 0; i < m_OpsFocusMechanics->focusWalk->count(); i++)
244 m_FocusWalkText.append(m_OpsFocusMechanics->focusWalk->itemText(i));
247void Focus::loadStellarSolverProfiles()
249 QString savedOptionsProfiles =
QDir(KSPaths::writableLocation(
253 m_StellarSolverProfiles = StellarSolver::loadSavedOptionsProfiles(savedOptionsProfiles);
254 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_NAME);
255 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_DONUT_NAME);
258 m_StellarSolverProfiles = getDefaultFocusOptionsProfiles();
259 m_OpsFocusProcess->focusSEPProfile->clear();
260 for(
auto ¶m : m_StellarSolverProfiles)
261 m_OpsFocusProcess->focusSEPProfile->addItem(param.listName);
262 auto profile = m_Settings[
"focusSEPProfile"];
263 if (profile.isValid())
264 m_OpsFocusProcess->focusSEPProfile->setCurrentText(profile.toString());
267void Focus::addMissingStellarSolverProfile(
const QString profilePath,
const QString profile)
269 for(
auto params : m_StellarSolverProfiles)
271 if (params.listName == profile)
277 SSolver::Parameters params;
278 if (profile == FOCUS_DEFAULT_DONUT_NAME)
279 params = getFocusOptionsProfileDefaultDonut();
280 else if (profile == FOCUS_DEFAULT_NAME)
281 params = getFocusOptionsProfileDefault();
285 settings.beginGroup(params.listName);
291 settings.setValue(it.key(), it.value());
295 m_StellarSolverProfiles.append(params);
301 for (
auto param : m_StellarSolverProfiles)
302 profiles << param.listName;
310 if (focusingWidget->parent() ==
nullptr)
311 toggleFocusingWidgetFullScreen();
314void Focus::resetFrame()
316 if (m_Camera && m_Camera->isConnected())
318 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
323 targetChip->resetFrame();
326 targetChip->getFrame(&x, &y, &w, &h);
328 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is reset. X:" << x <<
"Y:" << y <<
"W:" << w <<
"H:" << h <<
"binX:" << 1 <<
"binY:" <<
331 QVariantMap settings;
336 settings[
"binx"] = 1;
337 settings[
"biny"] = 1;
338 frameSettings[targetChip] = settings;
340 starSelected =
false;
344 m_FocusView->setTrackingBox(
QRect());
345 checkMosaicMaskLimits();
353 return m_Camera->getDeviceName();
358void Focus::checkCamera()
378 case FOCUS_CHANGING_FILTER:
383 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
384 if (targetChip && targetChip->isCapturing())
389 focusBinning->setEnabled(targetChip->canBin());
390 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
391 if (targetChip->canBin())
393 int subBinX = 1, subBinY = 1;
394 focusBinning->clear();
395 targetChip->getMaxBin(&subBinX, &subBinY);
396 for (
int i = 1; i <= subBinX; i++)
397 focusBinning->addItem(
QString(
"%1x%2").arg(i).arg(i));
399 auto binning = m_Settings[
"focusBinning"];
400 if (binning.isValid())
401 focusBinning->setCurrentText(binning.toString());
404 connect(m_Camera, &ISD::Camera::videoStreamToggled,
this, &Ekos::Focus::setVideoStreamEnabled,
Qt::UniqueConnection);
405 liveVideoB->setEnabled(m_Camera->hasVideoStream());
406 if (m_Camera->hasVideoStream())
407 setVideoStreamEnabled(m_Camera->isStreamingEnabled());
417void Focus::syncCCDControls()
419 if (m_Camera ==
nullptr)
422 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
423 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
426 auto isoList = targetChip->getISOList();
429 if (isoList.isEmpty())
431 focusISO->setEnabled(
false);
432 ISOLabel->setEnabled(
false);
436 focusISO->setEnabled(
true);
437 ISOLabel->setEnabled(
true);
438 focusISO->addItems(isoList);
439 focusISO->setCurrentIndex(targetChip->getISOIndex());
442 bool hasGain = m_Camera->hasGain();
443 gainLabel->setEnabled(hasGain);
444 focusGain->setEnabled(hasGain && m_Camera->getGainPermission() != IP_RO);
447 double gain = 0, min = 0, max = 0, step = 1;
448 m_Camera->getGainMinMaxStep(&min, &max, &step);
449 if (m_Camera->getGain(&gain))
452 GainSpinSpecialValue = min - step;
453 focusGain->setRange(GainSpinSpecialValue, max);
454 focusGain->setSpecialValueText(
i18n(
"--"));
456 focusGain->setSingleStep(step);
458 auto defaultGain = m_Settings[
"focusGain"];
459 if (defaultGain.isValid())
460 focusGain->setValue(defaultGain.toDouble());
462 focusGain->setValue(GainSpinSpecialValue);
469void Focus::syncCameraInfo()
471 if (m_Camera ==
nullptr)
474 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
475 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
478 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
480 if (frameSettings.contains(targetChip) ==
false)
483 if (targetChip->getFrame(&x, &y, &w, &h))
485 int binx = 1, biny = 1;
486 targetChip->getBinning(&binx, &biny);
489 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
490 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
492 QVariantMap settings;
494 settings[
"x"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? x : minX;
495 settings[
"y"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? y : minY;
496 settings[
"w"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? w : maxW;
497 settings[
"h"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? h : maxH;
498 settings[
"binx"] = binx;
499 settings[
"biny"] = biny;
501 frameSettings[targetChip] = settings;
507bool Focus::setFilterWheel(ISD::FilterWheel *device)
509 if (m_FilterWheel && m_FilterWheel == device)
516 m_FilterWheel->disconnect(
this);
518 m_FilterWheel = device;
522 connect(m_FilterWheel, &ISD::ConcreteDevice::Connected,
this, [
this]()
524 FilterPosLabel->setEnabled(
true);
525 focusFilter->setEnabled(
true);
526 filterManagerB->setEnabled(
true);
528 connect(m_FilterWheel, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
530 FilterPosLabel->setEnabled(
false);
531 focusFilter->setEnabled(
false);
532 filterManagerB->setEnabled(
false);
536 auto isConnected = m_FilterWheel && m_FilterWheel->isConnected();
537 FilterPosLabel->setEnabled(isConnected);
538 focusFilter->setEnabled(isConnected);
539 filterManagerB->setEnabled(isConnected);
541 FilterPosLabel->setEnabled(
true);
542 focusFilter->setEnabled(
true);
550 defaultFocusTemperatureSource->blockSignals(
true);
551 m_TemperatureSources = temperatureSources;
553 defaultFocusTemperatureSource->clear();
554 for (
auto device : temperatureSources)
558 defaultFocusTemperatureSource->addItem(device->getDeviceName());
560 defaultFocusTemperatureSource->blockSignals(
false);
562 auto targetSource = m_Settings[
"defaultFocusTemperatureSource"];
563 if (targetSource.isValid())
564 checkTemperatureSource(targetSource.toString());
567void Focus::checkTemperatureSource(
const QString &name )
572 source = defaultFocusTemperatureSource->currentText();
573 if (source.isEmpty())
579 for (
auto &oneSource : m_TemperatureSources)
581 if (oneSource->getDeviceName() == source)
583 currentSource = oneSource;
588 m_LastSourceDeviceAutofocusTemperature = currentSource;
595 for (
const auto &oneSource : m_TemperatureSources)
599 if (findTemperatureElement(currentSource))
601 defaultFocusTemperatureSource->setCurrentText(name);
602 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
603 absoluteTemperatureLabel->setText(
QString(
"%1 °C").arg(currentTemperatureSourceElement->value, 0,
'f', 2));
604 deltaTemperatureLabel->setText(
QString(
"%1 °C").arg(0.0, 0,
'f', 2));
608 m_LastSourceAutofocusTemperature = INVALID_VALUE;
621 auto temperatureProperty = device->getProperty(
"FOCUS_TEMPERATURE");
622 if (!temperatureProperty)
623 temperatureProperty = device->getProperty(
"CCD_TEMPERATURE");
624 if (temperatureProperty)
626 currentTemperatureSourceElement = temperatureProperty.getNumber()->at(0);
630 temperatureProperty = device->getProperty(
"WEATHER_PARAMETERS");
631 if (temperatureProperty)
633 for (
int i = 0; i < temperatureProperty.getNumber()->count(); i++)
635 if (strstr(temperatureProperty.getNumber()->at(i)->getName(),
"_TEMPERATURE"))
637 currentTemperatureSourceElement = temperatureProperty.getNumber()->at(i);
649 return m_FilterWheel->getDeviceName();
659 focusFilter->setCurrentText(filter);
668 return focusFilter->currentText();
671void Focus::checkFilter()
673 focusFilter->
clear();
677 FilterPosLabel->setEnabled(
false);
678 focusFilter->setEnabled(
false);
679 filterManagerB->setEnabled(
false);
683 m_FilterManager->disconnect(
this);
684 disconnect(m_FilterManager.get());
685 m_FilterManager.reset();
690 FilterPosLabel->setEnabled(
true);
691 focusFilter->setEnabled(
true);
692 filterManagerB->setEnabled(
true);
694 setupFilterManager();
696 focusFilter->addItems(m_FilterManager->getFilterLabels());
698 currentFilterPosition = m_FilterManager->getFilterPosition();
700 focusFilter->setCurrentIndex(currentFilterPosition - 1);
702 focusExposure->setValue(m_FilterManager->getFilterExposure());
707 if (m_Focuser && m_Focuser == device)
714 m_Focuser->disconnect(
this);
720 connect(m_Focuser, &ISD::ConcreteDevice::Connected,
this, [
this]()
724 connect(m_Focuser, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
731 emit focuserChanged(m_focuserId, device !=
nullptr);
738 return m_Focuser->getDeviceName();
743void Focus::checkFocuser()
748 m_FilterManager->setFocusReady(
false);
749 canAbsMove = canRelMove = canTimerMove =
false;
751 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
756 m_FilterManager->setFocusReady(m_Focuser->isConnected());
758 hasDeviation = m_Focuser->hasDeviation();
760 canAbsMove = m_Focuser->canAbsMove();
764 getAbsFocusPosition();
766 absTicksSpin->setEnabled(
true);
767 absTicksLabel->setEnabled(
true);
768 startGotoB->setEnabled(
true);
771 if (absTicksSpin->value() <= 0)
772 absTicksSpin->setValue(currentPosition);
776 absTicksSpin->setEnabled(
false);
777 absTicksLabel->setEnabled(
false);
778 startGotoB->setEnabled(
false);
781 canRelMove = m_Focuser->canRelMove();
786 if (canAbsMove ==
false && canRelMove ==
true)
788 currentPosition = 50000;
789 absMotionMax = 100000;
793 canTimerMove = m_Focuser->canTimerMove();
799 if (!canAbsMove && !canRelMove && canTimerMove)
801 currentPosition = 50000;
802 absMotionMax = 100000;
806 m_FocusType = (canRelMove || canAbsMove || canTimerMove) ? FOCUS_AUTO : FOCUS_MANUAL;
807 profilePlot->setFocusAuto(m_FocusType == FOCUS_AUTO);
809 bool hasBacklash = m_Focuser->hasBacklash();
810 m_OpsFocusMechanics->focusBacklash->setEnabled(hasBacklash);
811 m_OpsFocusMechanics->focusBacklash->disconnect(
this);
814 double min = 0, max = 0, step = 0;
815 m_Focuser->getMinMaxStep(
"FOCUS_BACKLASH_STEPS",
"FOCUS_BACKLASH_VALUE", &min, &max, &step);
816 m_OpsFocusMechanics->focusBacklash->setMinimum(min);
817 m_OpsFocusMechanics->focusBacklash->setMaximum(max);
818 m_OpsFocusMechanics->focusBacklash->setSingleStep(step);
819 m_OpsFocusMechanics->focusBacklash->setValue(m_Focuser->getBacklash());
821 this, [
this](
int value)
825 if (m_Focuser->getBacklash() == value)
831 m_Focuser->setBacklash(value);
836 connect(m_OpsFocusMechanics->focusBacklash, QOverload<int>::of(&
QSpinBox::valueChanged),
this, &Ekos::Focus::syncSettings);
840 m_OpsFocusMechanics->focusBacklash->setValue(0);
846 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
851 if (m_Camera && m_Camera == device)
857 m_captureInProgress =
false;
860 m_Camera->disconnect(
this);
866 connect(m_Camera, &ISD::ConcreteDevice::Connected,
this, [
this]()
870 connect(m_Camera, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
876 auto isConnected = m_Camera && m_Camera->isConnected();
877 focuserGroup->setEnabled(isConnected);
878 ccdGroup->setEnabled(isConnected);
879 toolsGroup->setEnabled(isConnected);
887 checkMosaicMaskLimits();
891void Focus::getAbsFocusPosition()
896 auto absMove = m_Focuser->getNumber(
"ABS_FOCUS_POSITION");
900 const auto &it = absMove->at(0);
901 currentPosition =
static_cast<int>(it->getValue());
902 absMotionMax = it->getMax();
903 absMotionMin = it->getMin();
905 absTicksSpin->setMinimum(it->getMin());
906 absTicksSpin->setMaximum(it->getMax());
907 absTicksSpin->setSingleStep(it->getStep());
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, opticalTrain());
941 emit newFocusTemperatureDelta(0, currentTemperatureSourceElement->value, opticalTrain());
944 absoluteTemperatureLabel->setText(
QString(
"%1 °C").arg(currentTemperatureSourceElement->value, 0,
'f', 2));
945 deltaTemperatureLabel->setText(
QString(
"%1%2 °C").arg((delta > 0.0 ?
"+" :
"")).arg(delta, 0,
'f', 2));
947 deltaTemperatureLabel->setStyleSheet(
"color: lightgreen");
949 deltaTemperatureLabel->setStyleSheet(
"color: lightcoral");
951 deltaTemperatureLabel->setStyleSheet(
"color: lightblue");
955void Focus::setLastFocusTemperature()
957 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE;
960 deltaTemperatureLabel->setText(
QString(
"0 °C"));
961 deltaTemperatureLabel->setStyleSheet(
"color: lightgreen");
963 emit newFocusTemperatureDelta(0, -1e6, opticalTrain());
966void Focus::setLastFocusAlt()
968 if (mountAlt < 0.0 || mountAlt > 90.0)
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,
"");
1012void Focus::runAutoFocus(AutofocusReason autofocusReason,
const QString &reasonInfo)
1014 m_AutofocusReason = autofocusReason;
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);
1063 if (inAdjustFocus || adaptFocus->inAdaptiveFocus())
1065 QString str = inAdjustFocus ?
i18n(
"Adjust Focus") :
i18n(
"Adaptive Focus");
1066 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
1068 appendLogText(
i18n(
"Autofocus start request - Waiting 10sec for %1 to complete.", str));
1071 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
1076 appendLogText(
i18n(
"Discarding Autofocus start request - %1 in progress.", str));
1077 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1081 inBuildOffsets = (autofocusReason == AutofocusReason::FOCUS_FILTER_OFFSETS);
1082 if (autofocusReason == AutofocusReason::FOCUS_USER_REQUEST)
1084 forceInSeqAF->setChecked(
false);
1085 emit inSequenceAF(
false, opticalTrain());
1090 m_LastFocusDirection = FOCUS_NONE;
1092 waitStarSelectTimer.stop();
1095 m_FocusMotionTimerCounter = 0;
1096 m_FocusMotionTimer.stop();
1097 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
1100 m_FocuserReconnectCounter = 0;
1103 m_FocuserReconnectCounter = 0;
1104 m_DebugFocuserCounter = 0;
1111 m_RestartState = RESTART_NONE;
1119 getAbsFocusPosition();
1120 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1122 else if (canRelMove)
1126 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1128 absMotionMax = 100000;
1133 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1135 absMotionMax = 100000;
1139 focuserAdditionalMovement = 0;
1140 starMeasureFrames.clear();
1152 profilePlot->clear();
1153 FWHMOut->setText(
"");
1155 qCInfo(KSTARS_EKOS_FOCUS) <<
"Starting Autofocus " << m_AFRun
1156 <<
" on" << opticalTrain()
1157 <<
" Reason: " << AutofocusReasonStr[m_AutofocusReason]
1158 <<
" Reason Info: " << m_AutofocusReasonInfo
1159 <<
" CanAbsMove: " << (canAbsMove ?
"yes" :
"no" )
1160 <<
" CanRelMove: " << (canRelMove ?
"yes" :
"no" )
1161 <<
" CanTimerMove: " << (canTimerMove ?
"yes" :
"no" )
1162 <<
" Position:" << currentPosition
1163 <<
" Filter:" << filter()
1164 <<
" Exp:" << focusExposure->value()
1165 <<
" Bin:" << focusBinning->currentText()
1166 <<
" Gain:" << focusGain->value()
1167 <<
" ISO:" << focusISO->currentText();
1168 qCInfo(KSTARS_EKOS_FOCUS) <<
"Settings Tab."
1169 <<
" Auto Select Star:" << ( m_OpsFocusSettings->focusAutoStarEnabled->isChecked() ?
"yes" :
"no" )
1170 <<
" Dark Frame:" << ( m_OpsFocusSettings->useFocusDarkFrame->isChecked() ?
"yes" :
"no" )
1171 <<
" Sub Frame:" << ( m_OpsFocusSettings->focusSubFrame->isChecked() ?
"yes" :
"no" )
1172 <<
" Box:" << m_OpsFocusSettings->focusBoxSize->value()
1173 <<
" Full frame:" << ( m_OpsFocusSettings->focusUseFullField->isChecked() ?
"yes" :
"no " )
1174 <<
" Focus Mask: " << (m_OpsFocusSettings->focusNoMaskRB->isChecked() ?
"Use all stars" :
1175 (m_OpsFocusSettings->focusRingMaskRB->isChecked() ?
QString(
"Ring Mask: [%1%, %2%]").
1176 arg(m_OpsFocusSettings->focusFullFieldInnerRadius->value()).
arg(m_OpsFocusSettings->focusFullFieldOuterRadius->value()) :
1177 QString(
"Mosaic Mask: [%1%, space=%2px]").
1178 arg(m_OpsFocusSettings->focusMosaicTileWidth->value()).
arg(m_OpsFocusSettings->focusMosaicSpace->value())))
1179 <<
" Suspend Guiding:" << ( m_OpsFocusSettings->focusSuspendGuiding->isChecked() ?
"yes" :
"no " )
1180 <<
" Guide Settle:" << m_OpsFocusSettings->focusGuideSettleTime->value()
1181 <<
" Display Units:" << m_OpsFocusSettings->focusUnits->currentText()
1182 <<
" Adaptive Focus:" << ( m_OpsFocusSettings->focusAdaptive->isChecked() ?
"yes" :
"no" )
1183 <<
" Min Move:" << m_OpsFocusSettings->focusAdaptiveMinMove->value()
1184 <<
" Adapt Start:" << ( m_OpsFocusSettings->focusAdaptStart->isChecked() ?
"yes" :
"no" )
1185 <<
" Max Total Move:" << m_OpsFocusSettings->focusAdaptiveMaxMove->value();
1186 qCInfo(KSTARS_EKOS_FOCUS) <<
"Process Tab."
1187 <<
" Detection:" << m_OpsFocusProcess->focusDetection->currentText()
1188 <<
" SEP Profile:" << m_OpsFocusProcess->focusSEPProfile->currentText()
1189 <<
" Algorithm:" << m_OpsFocusProcess->focusAlgorithm->currentText()
1190 <<
" Curve Fit:" << m_OpsFocusProcess->focusCurveFit->currentText()
1191 <<
" Measure:" << m_OpsFocusProcess->focusStarMeasure->currentText()
1192 <<
" PSF:" << m_OpsFocusProcess->focusStarPSF->currentText()
1193 <<
" Use Weights:" << ( m_OpsFocusProcess->focusUseWeights->isChecked() ?
"yes" :
"no" )
1194 <<
" R2 Limit:" << m_OpsFocusProcess->focusR2Limit->value()
1195 <<
" Refine Curve Fit:" << ( m_OpsFocusProcess->focusRefineCurveFit->isChecked() ?
"yes" :
"no" )
1196 <<
" Average Over:" << m_OpsFocusProcess->focusFramesCount->value()
1197 <<
" Average HFR Check Over:" << m_OpsFocusProcess->focusHFRFramesCount->value()
1198 <<
" Num.of Rows:" << m_OpsFocusProcess->focusMultiRowAverage->value()
1199 <<
" Sigma:" << m_OpsFocusProcess->focusGaussianSigma->value()
1200 <<
" Threshold:" << m_OpsFocusProcess->focusThreshold->value()
1201 <<
" Kernel size:" << m_OpsFocusProcess->focusGaussianKernelSize->value()
1202 <<
" Tolerance:" << m_OpsFocusProcess->focusTolerance->value()
1203 <<
" Denoise:" << ( m_OpsFocusProcess->focusDenoise->isChecked() ?
"yes" :
"no" )
1204 <<
" Donut Buster:" << ( m_OpsFocusProcess->focusDonut->isChecked() ?
"yes" :
"no" )
1205 <<
" Donut Time Dilation:" << m_OpsFocusProcess->focusTimeDilation->value()
1206 <<
" Outlier Rejection:" << m_OpsFocusProcess->focusOutlierRejection->value()
1207 <<
" Scan Start Pos:" << ( m_OpsFocusProcess->focusScanStartPos->isChecked() ?
"yes" :
"no" )
1208 <<
" Scan Always On:" << ( m_OpsFocusProcess->focusScanAlwaysOn->isChecked() ?
"yes" :
"no" )
1209 <<
" Num Datapoints:" << m_OpsFocusProcess->focusScanDatapoints->value()
1210 <<
" Scan Step Factor:" << m_OpsFocusProcess->focusScanStepSizeFactor->value();
1211 qCInfo(KSTARS_EKOS_FOCUS) <<
"Mechanics Tab."
1212 <<
" Initial Step Size:" << m_OpsFocusMechanics->focusTicks->value()
1213 <<
" Out Step Multiple:" << m_OpsFocusMechanics->focusOutSteps->value()
1214 <<
" Number Steps:" << m_OpsFocusMechanics->focusNumSteps->value()
1215 <<
" Max Travel:" << m_OpsFocusMechanics->focusMaxTravel->value()
1216 <<
" Max Step Size:" << m_OpsFocusMechanics->focusMaxSingleStep->value()
1217 <<
" Driver Backlash:" << m_OpsFocusMechanics->focusBacklash->value()
1218 <<
" AF Overscan:" << m_OpsFocusMechanics->focusAFOverscan->value()
1219 <<
" Overscan Delay:" << m_OpsFocusMechanics->focusOverscanDelay->value()
1220 <<
" Focuser Settle:" << m_OpsFocusMechanics->focusSettleTime->value()
1221 <<
" Walk:" << m_OpsFocusMechanics->focusWalk->currentText()
1222 <<
" Capture Timeout:" << m_OpsFocusMechanics->focusCaptureTimeout->value()
1223 <<
" Motion Timeout:" << m_OpsFocusMechanics->focusMotionTimeout->value();
1224 qCInfo(KSTARS_EKOS_FOCUS) <<
"CFZ Tab."
1225 <<
" Algorithm:" << m_CFZUI->focusCFZAlgorithm->currentText()
1226 <<
" Tolerance:" << m_CFZUI->focusCFZTolerance->value()
1227 <<
" Tolerance (Ï„):" << m_CFZUI->focusCFZTau->value()
1228 <<
" Display:" << ( m_CFZUI->focusCFZDisplayVCurve->isChecked() ?
"yes" :
"no" )
1229 <<
" Wavelength (λ):" << m_CFZUI->focusCFZWavelength->value()
1230 <<
" Aperture (A):" << m_CFZUI->focusCFZAperture->value()
1231 <<
" Focal Ratio (f):" << m_CFZUI->focusCFZFNumber->value()
1232 <<
" Step Size:" << m_CFZUI->focusCFZStepSize->value()
1233 <<
" FWHM (θ):" << m_CFZUI->focusCFZSeeing->value();
1235 const double temperature = (currentTemperatureSourceElement) ? currentTemperatureSourceElement->value : INVALID_VALUE;
1236 emit autofocusStarting(temperature, filter(), m_AutofocusReason, m_AutofocusReasonInfo);
1238 appendLogText(
i18n(
"Autofocus starting..."));
1243 if (m_GuidingSuspended ==
false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
1245 m_GuidingSuspended =
true;
1246 emit suspendGuiding();
1250 setState(Ekos::FOCUS_PROGRESS);
1252 KSNotification::event(
QLatin1String(
"FocusStarted"),
i18n(
"Autofocus operation started"), KSNotification::Focus);
1255 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1257 m_AFfilter = filter();
1258 int position = adaptFocus->adaptStartPosition(currentPosition, m_AFfilter);
1260 curveFitting.reset(
new CurveFitting());
1262 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1265 starFitting.reset(
new CurveFitting());
1266 focusFWHM.reset(
new FocusFWHM(m_ScaleCalc));
1267 focusFourierPower.reset(
new FocusFourierPower(m_ScaleCalc));
1268#if defined(HAVE_OPENCV)
1269 focusBlurriness.reset(
new FocusBlurriness());
1272 initDonutProcessing();
1274 if (initScanStartPos(
false, currentPosition))
1277 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
1279 focusAdvisor->initControl();
1285 setupLinearFocuser(position);
1286 if (!changeFocus(linearRequestedPosition - currentPosition))
1287 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
1295void Focus::setupLinearFocuser(
int initialPosition)
1297 FocusAlgorithmInterface::FocusParams params(curveFitting.get(),
1298 m_OpsFocusMechanics->focusMaxTravel->value(), m_OpsFocusMechanics->focusTicks->value(), initialPosition, absMotionMin,
1299 absMotionMax, MAXIMUM_ABS_ITERATIONS, m_OpsFocusProcess->focusTolerance->value() / 100.0, m_AFfilter,
1300 currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE,
1301 m_OpsFocusMechanics->focusOutSteps->value(), m_OpsFocusMechanics->focusNumSteps->value(),
1302 m_FocusAlgorithm, m_OpsFocusMechanics->focusBacklash->value(), m_CurveFit, m_OpsFocusProcess->focusUseWeights->isChecked(),
1303 m_StarMeasure, m_StarPSF, m_OpsFocusProcess->focusRefineCurveFit->isChecked(), m_FocusWalk,
1304 m_OpsFocusProcess->focusDonut->isChecked(), m_OpsFocusProcess->focusOutlierRejection->value(), m_OptDir, m_ScaleCalc);
1307 initialFocuserAbsPosition = initialPosition;
1308 linearFocuser.reset(MakeLinearFocuser(params));
1309 linearRequestedPosition = linearFocuser->initialPosition();
1313void Focus::initDonutProcessing()
1315 if (!m_OpsFocusProcess->focusDonut->isChecked())
1318 m_donutOrigExposure = focusExposure->value();
1322void Focus::resetDonutProcessing()
1325 if (m_OpsFocusProcess->focusDonut->isChecked() && inAutoFocus)
1326 focusExposure->setValue(m_donutOrigExposure);
1329int Focus::adjustLinearPosition(
int position,
int newPosition,
int overscan,
bool updateDir)
1331 if (overscan > 0 && newPosition > position)
1334 int adjustment = overscan;
1335 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Linear: extending outward movement by overscan %1").
arg(adjustment);
1337 if (newPosition + adjustment > absMotionMax)
1338 adjustment =
static_cast<int>(absMotionMax) - newPosition;
1340 focuserAdditionalMovement = adjustment;
1341 focuserAdditionalMovementUpdateDir = updateDir;
1343 return newPosition + adjustment;
1351void Focus::checkStopFocus(
bool abort)
1353 m_abortInProgress =
true;
1356 resetFocusIteration = MAXIMUM_RESET_ITERATIONS + 1;
1358 if (captureTimer.isActive())
1360 captureTimer.stop();
1362 if (m_captureInProgress)
1364 if (inAutoFocus ==
false && inFocusLoop ==
false)
1366 captureB->setEnabled(
true);
1367 stopFocusB->setEnabled(
false);
1369 appendLogText(
i18n(
"Capture aborted."));
1371 else if (inAutoFocus)
1373 stopFocusB->setEnabled(
false);
1374 appendLogText(
i18n(
"Capture in progress, retrying in 1s..."));
1377 checkStopFocus(abort);
1383 if (m_starDetectInProgress)
1385 stopFocusB->setEnabled(
false);
1386 appendLogText(
i18n(
"Star detection in progress, retrying in 1s..."));
1389 checkStopFocus(abort);
1394 completeFocusProcedure(abort ? Ekos::FOCUS_ABORTED : Ekos::FOCUS_FAILED, Ekos::FOCUS_FAIL_ABORT);
1397void Focus::meridianFlipStarted()
1400 if (state() == FOCUS_IDLE || state() == FOCUS_COMPLETE || state() == FOCUS_FAILED || state() == FOCUS_ABORTED)
1404 int old = resetFocusIteration;
1408 resetFocusIteration = old;
1414 if (state() <= FOCUS_ABORTED)
1418 if (focusAdvisor->inFocusAdvisor())
1420 focusAdvisor->stop();
1426void Focus::processAbort()
1428 bool focusLoop = inFocusLoop;
1429 checkStopFocus(
true);
1430 appendLogText(
i18n(
"Autofocus aborted."));
1437void Focus::stop(Ekos::FocusState completionState)
1439 Q_UNUSED(completionState);
1440 qCDebug(KSTARS_EKOS_FOCUS) <<
"Stopping Focus";
1442 captureTimeout.stop();
1443 m_FocusMotionTimer.stop();
1444 m_FocusMotionTimerCounter = 0;
1445 m_FocuserReconnectCounter = 0;
1447 opticalTrainCombo->setEnabled(
true);
1448 resetDonutProcessing();
1449 inAutoFocus =
false;
1450 inAdjustFocus =
false;
1451 adaptFocus->setInAdaptiveFocus(
false);
1452 inBuildOffsets =
false;
1453 inScanStartPos =
false;
1454 focusAdvisor->reset();
1455 m_AutofocusReason = AutofocusReason::FOCUS_NONE;
1456 m_AutofocusReasonInfo =
"";
1457 focuserAdditionalMovement = 0;
1458 focuserAdditionalMovementUpdateDir =
true;
1459 inFocusLoop =
false;
1460 m_captureInProgress =
false;
1461 m_abortInProgress =
false;
1462 m_starDetectInProgress =
false;
1463 isVShapeSolution =
false;
1464 captureFailureCounter = 0;
1465 minimumRequiredHFR = INVALID_STAR_MEASURE;
1467 starMeasureFrames.clear();
1476 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1478 if (rememberUploadMode != m_Camera->getUploadMode())
1479 m_Camera->setUploadMode(rememberUploadMode);
1482 if (m_RememberCameraFastExposure)
1484 m_RememberCameraFastExposure =
false;
1485 m_Camera->setFastExposureEnabled(
true);
1488 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1489 targetChip->abortExposure();
1498 if (m_GuidingSuspended)
1500 emit resumeGuiding();
1501 m_GuidingSuspended =
false;
1505void Focus::capture(
double settleTime)
1507 if (m_abortInProgress)
1510 m_captureInProgress =
false;
1511 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding capture request.";
1517 if (settleTime > 0 && m_captureInProgress ==
false)
1519 captureTimer.start(
static_cast<int>(settleTime * 1000));
1523 if (m_captureInProgress)
1525 qCWarning(KSTARS_EKOS_FOCUS) <<
"Capture called while already in progress. Capture is ignored.";
1529 if (m_Camera ==
nullptr)
1531 appendLogText(
i18n(
"Error: No Camera detected."));
1532 checkStopFocus(
true);
1536 if (m_Camera->isConnected() ==
false)
1538 appendLogText(
i18n(
"Error: Lost connection to Camera."));
1539 checkStopFocus(
true);
1544 captureTimeout.stop();
1546 waitStarSelectTimer.stop();
1548 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1550 if (m_Camera->isBLOBEnabled() ==
false)
1552 m_Camera->setBLOBEnabled(
true);
1555 if (focusFilter->currentIndex() != -1)
1557 if (m_FilterWheel ==
nullptr)
1559 appendLogText(
i18n(
"Error: No Filter Wheel detected."));
1560 checkStopFocus(
true);
1563 if (m_FilterWheel->isConnected() ==
false)
1565 appendLogText(
i18n(
"Error: Lost connection to Filter Wheel."));
1566 checkStopFocus(
true);
1573 int targetPosition = focusFilter->currentIndex() + 1;
1574 if (!inBuildOffsets)
1576 QString lockedFilter = m_FilterManager->getFilterLock(filter());
1581 if (lockedFilter !=
"--" && lockedFilter != filter())
1583 int lockedFilterIndex = focusFilter->findText(lockedFilter);
1584 if (lockedFilterIndex >= 0)
1587 fallbackFilterPending =
true;
1588 fallbackFilterPosition = targetPosition;
1589 targetPosition = lockedFilterIndex + 1;
1594 filterPositionPending = (targetPosition != currentFilterPosition);
1595 if (filterPositionPending)
1600 FilterManager::FilterPolicy policy = (inAutoFocus) ?
1601 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY) :
1602 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY | FilterManager::OFFSET_POLICY);
1603 m_FilterManager->setFilterPosition(targetPosition, policy);
1606 else if (targetPosition != focusFilter->currentIndex() + 1)
1607 focusFilter->setCurrentIndex(targetPosition - 1);
1610 m_FocusView->setProperty(
"suspended", m_OpsFocusSettings->useFocusDarkFrame->isChecked());
1611 prepareCapture(targetChip);
1614 connect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError,
Qt::UniqueConnection);
1616 if (frameSettings.contains(targetChip))
1618 QVariantMap settings = frameSettings[targetChip];
1619 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
1620 settings[
"h"].toInt());
1621 settings[
"binx"] = (focusBinning->currentIndex() + 1);
1622 settings[
"biny"] = (focusBinning->currentIndex() + 1);
1623 frameSettings[targetChip] = settings;
1626 m_captureInProgress =
true;
1627 if (state() != FOCUS_PROGRESS)
1628 setState(FOCUS_PROGRESS);
1630 m_FocusView->setBaseSize(focusingWidget->size());
1632 if (targetChip->capture(focusExposure->value()))
1636 captureTimeout.start( (focusExposure->value() + m_OpsFocusMechanics->focusCaptureTimeout->value()) * 1000);
1638 if (inFocusLoop ==
false)
1639 appendLogText(
i18n(
"Capturing image..."));
1643 else if (inAutoFocus)
1645 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
1651 if (m_Camera->getUploadMode() == ISD::Camera::UPLOAD_REMOTE)
1653 rememberUploadMode = ISD::Camera::UPLOAD_REMOTE;
1654 m_Camera->setUploadMode(ISD::Camera::UPLOAD_CLIENT);
1658 if (m_Camera->isFastExposureEnabled())
1660 m_RememberCameraFastExposure =
true;
1661 m_Camera->setFastExposureEnabled(
false);
1664 m_Camera->setEncodingFormat(
"FITS");
1665 targetChip->setBatchMode(
false);
1666 targetChip->setBinning((focusBinning->currentIndex() + 1), (focusBinning->currentIndex() + 1));
1667 targetChip->setCaptureMode(FITS_FOCUS);
1668 targetChip->setFrameType(FRAME_LIGHT);
1669 targetChip->setCaptureFilter(FITS_NONE);
1671 if (isFocusISOEnabled() && focusISO->currentIndex() != -1 &&
1672 targetChip->getISOIndex() != focusISO->currentIndex())
1673 targetChip->setISOIndex(focusISO->currentIndex());
1675 if (isFocusGainEnabled() && focusGain->value() != GainSpinSpecialValue)
1676 m_Camera->setGain(focusGain->value());
1679bool Focus::focusIn(
int ms)
1681 if (currentPosition == absMotionMin)
1683 appendLogText(
i18n(
"At minimum focus position %1...", absMotionMin));
1686 focusInB->setEnabled(
false);
1687 focusOutB->setEnabled(
false);
1688 startGotoB->setEnabled(
false);
1690 ms = m_OpsFocusMechanics->focusTicks->value();
1691 if (currentPosition - ms <= absMotionMin)
1693 ms = currentPosition - absMotionMin;
1694 appendLogText(
i18n(
"Moving to minimum focus position %1...", absMotionMin));
1696 return changeFocus(-ms);
1699bool Focus::focusOut(
int ms)
1701 if (currentPosition == absMotionMax)
1703 appendLogText(
i18n(
"At maximum focus position %1...", absMotionMax));
1706 focusInB->setEnabled(
false);
1707 focusOutB->setEnabled(
false);
1708 startGotoB->setEnabled(
false);
1710 ms = m_OpsFocusMechanics->focusTicks->value();
1711 if (currentPosition + ms >= absMotionMax)
1713 ms = absMotionMax - currentPosition;
1714 appendLogText(
i18n(
"Moving to maximum focus position %1...", absMotionMax));
1716 return changeFocus(ms);
1721bool Focus::changeFocus(
int amount,
bool updateDir)
1725 if (inAutoFocus && abs(amount) <= 1)
1727 if (m_RestartState == RESTART_NOW)
1734 capture(m_OpsFocusMechanics->focusSettleTime->value());
1739 if (m_Focuser ==
nullptr)
1741 appendLogText(
i18n(
"Error: No Focuser detected."));
1742 checkStopFocus(
true);
1746 if (m_Focuser->isConnected() ==
false)
1748 appendLogText(
i18n(
"Error: Lost connection to Focuser."));
1749 checkStopFocus(
true);
1753 const int newPosition = adjustLinearPosition(currentPosition, currentPosition + amount,
1754 m_OpsFocusMechanics->focusAFOverscan->value(),
1756 if (newPosition == currentPosition)
1759 const int newAmount = newPosition - currentPosition;
1760 const int absNewAmount = abs(newAmount);
1761 const bool focusingOut = newAmount > 0;
1762 const QString dirStr = focusingOut ?
i18n(
"outward") :
i18n(
"inward");
1765 m_LastFocusDirection = (focusingOut) ? FOCUS_OUT : FOCUS_IN;
1768 m_Focuser->focusOut();
1770 m_Focuser->focusIn();
1773 m_FocusMotionTimer.start();
1777 m_LastFocusSteps = newPosition;
1778 m_Focuser->moveAbs(newPosition);
1779 appendLogText(
i18n(
"Focusing %2 by %1 steps...", abs(absNewAmount), dirStr));
1781 else if (canRelMove)
1783 m_LastFocusSteps = absNewAmount;
1784 m_Focuser->moveRel(absNewAmount);
1785 appendLogText(
i18np(
"Focusing %2 by %1 step...",
"Focusing %2 by %1 steps...", absNewAmount, dirStr));
1789 m_LastFocusSteps = absNewAmount;
1790 m_Focuser->moveByTimer(absNewAmount);
1791 appendLogText(
i18n(
"Focusing %2 by %1 ms...", absNewAmount, dirStr));
1797void Focus::handleFocusMotionTimeout()
1817 qCDebug(KSTARS_EKOS_FOCUS) <<
"handleFocusMotionTimeout() called while not in AutoFocus";
1821 m_FocusMotionTimerCounter++;
1823 if (m_FocusMotionTimerCounter > 4)
1826 appendLogText(
i18n(
"Focuser is still timing out. Aborting..."));
1827 stop(Ekos::FOCUS_ABORTED);
1830 else if (m_FocusMotionTimerCounter > 2)
1832 QString focuser = m_Focuser->getDeviceName();
1833 appendLogText(
i18n(
"Focus motion timed out (%1). Restarting focus driver %2", m_FocusMotionTimerCounter, focuser));
1834 emit focuserTimedout(focuser);
1838 Focus::reconnectFocuser(focuser);
1843 if (!changeFocus(m_LastFocusSteps - currentPosition))
1844 appendLogText(
i18n(
"Focus motion timed out (%1). Focusing to %2 steps...", m_FocusMotionTimerCounter, m_LastFocusSteps));
1847void Focus::selectImageMask()
1849 const bool useFullField = m_OpsFocusSettings->focusUseFullField->isChecked();
1850 ImageMaskType masktype;
1851 if (m_OpsFocusSettings->focusRingMaskRB->isChecked())
1852 masktype = FOCUS_MASK_RING;
1853 else if (m_OpsFocusSettings->focusMosaicMaskRB->isChecked())
1854 masktype = FOCUS_MASK_MOSAIC;
1856 masktype = FOCUS_MASK_NONE;
1859 m_OpsFocusSettings->focusRingMaskRB->setEnabled(useFullField);
1860 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(useFullField);
1862 m_OpsFocusSettings->focusFullFieldInnerRadius->setEnabled(useFullField && masktype == FOCUS_MASK_RING);
1863 m_OpsFocusSettings->focusFullFieldOuterRadius->setEnabled(useFullField && masktype == FOCUS_MASK_RING);
1865 m_OpsFocusSettings->focusMosaicTileWidth->setEnabled(useFullField && masktype == FOCUS_MASK_MOSAIC);
1866 m_OpsFocusSettings->focusSpacerLabel->setEnabled(useFullField && masktype == FOCUS_MASK_MOSAIC);
1867 m_OpsFocusSettings->focusMosaicSpace->setEnabled(useFullField && masktype == FOCUS_MASK_MOSAIC);
1870 if (masktype == FOCUS_MASK_RING)
1871 m_FocusView->setImageMask(
new ImageRingMask(m_OpsFocusSettings->focusFullFieldInnerRadius->value() / 100.0,
1872 m_OpsFocusSettings->focusFullFieldOuterRadius->value() / 100.0));
1873 else if (masktype == FOCUS_MASK_MOSAIC)
1874 m_FocusView->setImageMask(
new ImageMosaicMask(m_OpsFocusSettings->focusMosaicTileWidth->value(),
1875 m_OpsFocusSettings->focusMosaicSpace->value()));
1877 m_FocusView->setImageMask(
nullptr);
1879 checkMosaicMaskLimits();
1880 m_currentImageMask = masktype;
1881 startAbInsB->setEnabled(canAbInsStart());
1884void Focus::reconnectFocuser(
const QString &focuser)
1886 m_FocuserReconnectCounter++;
1888 if (m_Focuser && m_Focuser->getDeviceName() == focuser)
1890 appendLogText(
i18n(
"Attempting to reconnect focuser: %1", focuser));
1891 refreshOpticalTrain();
1892 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
1896 if (m_FocuserReconnectCounter > 12)
1899 appendLogText(
i18n(
"Cannot reconnect focuser: %1. Aborting...", focuser));
1900 stop(Ekos::FOCUS_ABORTED);
1906 reconnectFocuser(focuser);
1913 if (data->property(
"chip").toInt() == ISD::CameraChip::GUIDE_CCD)
1918 m_FocusView->loadData(data);
1922 m_ImageData.reset();
1924 captureTimeout.stop();
1925 captureTimeoutCounter = 0;
1926 m_MissingCameraCounter = 0;
1928 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1930 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1932 if (m_ImageData && m_OpsFocusSettings->useFocusDarkFrame->isChecked())
1934 QVariantMap settings = frameSettings[targetChip];
1935 uint16_t offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
1936 uint16_t offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
1938 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()),
1939 targetChip, m_ImageData, focusExposure->value(), offsetX, offsetY);
1943 setCaptureComplete();
1947void Focus::starDetectionFinished()
1949 m_starDetectInProgress =
false;
1950 if (m_abortInProgress)
1953 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding results from " << __FUNCTION__;
1957 appendLogText(
i18n(
"Detection complete."));
1960 double hfr = INVALID_STAR_MEASURE;
1962 if (isStarMeasureStarBased())
1964 appendLogText(
i18n(
"Detection complete."));
1966 if (m_StarFinderWatcher.result() ==
false)
1968 qCWarning(KSTARS_EKOS_FOCUS) <<
"Failed to extract any stars.";
1972 if (m_OpsFocusSettings->focusUseFullField->isChecked())
1974 m_FocusView->filterStars();
1977 hfr = m_ImageData->getHFR(m_StarMeasure == FOCUS_STAR_HFR_ADJ ? HFR_ADJ_AVERAGE : HFR_AVERAGE);
1981 m_FocusView->setTrackingBoxEnabled(
true);
1986 if (starCenter.isNull() ==
false)
1987 hfr = m_ImageData->getHFR(starCenter.x(), starCenter.y());
1991 hfr = m_ImageData->getHFR(m_FocusDetection == ALGORITHM_SEP ? HFR_HIGH : HFR_MAX);
1997 currentNumStars = m_ImageData->getDetectedStars();
2000 if (m_StarMeasure == FOCUS_STAR_NUM_STARS)
2002 currentMeasure = currentNumStars;
2003 currentWeight = 1.0;
2005 else if (m_StarMeasure == FOCUS_STAR_FWHM)
2007 getFWHM(m_ImageData->getStarCenters(), ¤tFWHM, ¤tWeight);
2008 currentMeasure = currentFWHM;
2010 else if (m_StarMeasure == FOCUS_STAR_FOURIER_POWER)
2012 getFourierPower(¤tFourierPower, ¤tWeight);
2013 currentMeasure = currentFourierPower;
2015 else if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
2016 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
2019 if (m_OpsFocusSettings->focusSubFrame->isChecked())
2020 roi = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2021 getBlurriness(m_StarMeasure, m_OpsFocusProcess->focusDenoise->isChecked(), ¤tBlurriness, ¤tWeight, roi);
2022 currentMeasure = currentBlurriness;
2026 currentMeasure = currentHFR;
2028 std::vector<double> hfrs(stars.
size());
2033 currentWeight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), hfrs);
2035 setCurrentMeasure();
2041bool Focus::isStarMeasureStarBased()
2043 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL || m_StarMeasure == FOCUS_STAR_LAPLASSIAN
2044 || m_StarMeasure == FOCUS_STAR_CANNY)
2050void Focus::getFWHM(
const QList<Edge *> &stars,
double *FWHM,
double *weight)
2052 *FWHM = INVALID_STAR_MEASURE;
2055 auto imageBuffer = m_ImageData->getImageBuffer();
2057 switch (m_ImageData->getStatistics().dataType)
2060 focusFWHM->processFWHM(
reinterpret_cast<uint8_t
const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2064 focusFWHM->processFWHM(
reinterpret_cast<short const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2068 focusFWHM->processFWHM(
reinterpret_cast<unsigned short const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM,
2073 focusFWHM->processFWHM(
reinterpret_cast<long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2077 focusFWHM->processFWHM(
reinterpret_cast<unsigned long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2081 focusFWHM->processFWHM(
reinterpret_cast<float const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2085 focusFWHM->processFWHM(
reinterpret_cast<long long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2089 focusFWHM->processFWHM(
reinterpret_cast<double const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2093 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2094 " Cannot calc FWHM";
2100void Focus::getFourierPower(
double *fourierPower,
double *weight,
const int mosaicTile)
2102 *fourierPower = INVALID_STAR_MEASURE;
2105 auto imageBuffer = m_ImageData->getImageBuffer();
2107 switch (m_ImageData->getStatistics().dataType)
2110 focusFourierPower->processFourierPower(
reinterpret_cast<uint8_t
const *
>(imageBuffer), m_ImageData,
2111 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2115 focusFourierPower->processFourierPower(
reinterpret_cast<short const *
>(imageBuffer), m_ImageData,
2116 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2120 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned short const *
>(imageBuffer), m_ImageData,
2121 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2125 focusFourierPower->processFourierPower(
reinterpret_cast<long const *
>(imageBuffer), m_ImageData,
2126 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2130 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned long const *
>(imageBuffer), m_ImageData,
2131 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2135 focusFourierPower->processFourierPower(
reinterpret_cast<float const *
>(imageBuffer), m_ImageData,
2136 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2140 focusFourierPower->processFourierPower(
reinterpret_cast<long long const *
>(imageBuffer), m_ImageData,
2141 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2145 focusFourierPower->processFourierPower(
reinterpret_cast<double const *
>(imageBuffer), m_ImageData,
2146 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2150 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2151 " Cannot calc Fourier Power";
2157void Focus::getBlurriness(
const StarMeasure starMeasure,
const bool denoise,
double *blurriness,
double *weight,
2158 const QRect &roi,
const int mosaicTile)
2160 *blurriness = INVALID_STAR_MEASURE;
2163#if defined(HAVE_OPENCV)
2165 auto imageBuffer = m_ImageData->getImageBuffer();
2167 switch (m_ImageData->getStatistics().dataType)
2170 focusBlurriness->processBlurriness(
reinterpret_cast<uint8_t
const *
>(imageBuffer), m_ImageData, denoise,
2171 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2175 focusBlurriness->processBlurriness(
reinterpret_cast<short const *
>(imageBuffer), m_ImageData, denoise,
2176 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2180 focusBlurriness->processBlurriness(
reinterpret_cast<unsigned short const *
>(imageBuffer), m_ImageData, denoise,
2181 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2185 focusBlurriness->processBlurriness(
reinterpret_cast<long const *
>(imageBuffer), m_ImageData, denoise,
2186 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2190 focusBlurriness->processBlurriness(
reinterpret_cast<unsigned long const *
>(imageBuffer), m_ImageData, denoise,
2191 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2195 focusBlurriness->processBlurriness(
reinterpret_cast<float const *
>(imageBuffer), m_ImageData, denoise,
2196 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2200 focusBlurriness->processBlurriness(
reinterpret_cast<long long const *
>(imageBuffer), m_ImageData, denoise,
2201 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2205 focusBlurriness->processBlurriness(
reinterpret_cast<double const *
>(imageBuffer), m_ImageData, denoise,
2206 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2210 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2211 " Cannot calc Blurriness";
2215 Q_UNUSED(starMeasure);
2218 Q_UNUSED(mosaicTile);
2220 qCDebug(KSTARS_EKOS_FOCUS) <<
"getBlurriness called when openCV not installed";
2224double Focus::calculateStarWeight(
const bool useWeights,
const std::vector<double> values)
2226 if (!useWeights || values.size() <= 0)
2231 return Mathematics::RobustStatistics::ComputeWeight(m_ScaleCalc, values);
2234void Focus::analyzeSources()
2236 appendLogText(
i18n(
"Detecting sources..."));
2237 m_starDetectInProgress =
true;
2239 QVariantMap extractionSettings;
2240 extractionSettings[
"optionsProfileIndex"] = m_OpsFocusProcess->focusSEPProfile->currentIndex();
2241 extractionSettings[
"optionsProfileGroup"] =
static_cast<int>(Ekos::FocusProfiles);
2242 m_ImageData->setSourceExtractorSettings(extractionSettings);
2246 if (m_OpsFocusSettings->focusUseFullField->isChecked())
2248 m_FocusView->setTrackingBoxEnabled(
false);
2250 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2251 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2253 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection));
2257 QRect searchBox = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2261 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection, searchBox));
2266 m_FocusView->setTrackingBoxEnabled(
false);
2270 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2271 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2274 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection, searchBox));
2279bool Focus::appendMeasure(
double newMeasure)
2282 starMeasureFrames.append(newMeasure);
2285 QVector <double> samples(starMeasureFrames);
2286 samples.erase(std::remove_if(samples.begin(), samples.end(), [](
const double measure)
2288 return measure == INVALID_STAR_MEASURE;
2292 if (!samples.isEmpty())
2294 currentMeasure = Mathematics::RobustStatistics::ComputeLocation(
2295 Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, std::vector<double>(samples.begin(), samples.end()));
2297 switch(m_StarMeasure)
2299 case FOCUS_STAR_HFR:
2300 case FOCUS_STAR_HFR_ADJ:
2301 currentHFR = currentMeasure;
2303 case FOCUS_STAR_FWHM:
2304 currentFWHM = currentMeasure;
2306 case FOCUS_STAR_NUM_STARS:
2307 currentNumStars = currentMeasure;
2309 case FOCUS_STAR_FOURIER_POWER:
2310 currentFourierPower = currentMeasure;
2312 case FOCUS_STAR_STDDEV:
2313 case FOCUS_STAR_SOBEL:
2314 case FOCUS_STAR_LAPLASSIAN:
2315 case FOCUS_STAR_CANNY:
2316 currentBlurriness = currentMeasure;
2327 int framesCount = m_OpsFocusProcess->focusFramesCount->value();
2328 if ((minimumRequiredHFR > 0) || (inAutoFocus && !inBuildOffsets && !inScanStartPos && !focusAdvisor->inFocusAdvisor()
2329 && m_FocusAlgorithm == FOCUS_LINEAR1PASS
2330 && linearFocuser && !linearFocuser->isInFirstPass()))
2332 framesCount = m_OpsFocusProcess->focusHFRFramesCount->value();
2334 return starMeasureFrames.count() < framesCount;
2337void Focus::settle(
const FocusState completionState,
const bool autoFocusUsed,
const bool buildOffsetsUsed,
2338 const AutofocusFailReason failCode,
const QString failCodeInfo)
2342 if (completionState == Ekos::FOCUS_COMPLETE)
2344 if (failCode != FOCUS_FAIL_ADVISOR_COMPLETE)
2345 KSNotification::event(
QLatin1String(
"FocusSuccessful"),
i18n(
"Autofocus operation completed successfully"),
2346 KSNotification::Focus);
2348 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && curveFitting !=
nullptr)
2349 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2350 m_OpsFocusProcess->focusUseWeights->isChecked(),
2351 curveFitting->serialize(), linearFocuser->getTextStatus(R2));
2353 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2354 m_OpsFocusProcess->focusUseWeights->isChecked());
2358 if (failCode != FOCUS_FAIL_ADVISOR_COMPLETE)
2359 KSNotification::event(
QLatin1String(
"FocusFailed"),
i18n(
"Autofocus operation failed"),
2360 KSNotification::Focus, KSNotification::Alert);
2361 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2365 if (completionState == Ekos::FOCUS_COMPLETE)
2367 if (autoFocusUsed && fallbackFilterPending)
2372 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
2373 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
2378 if (fallbackFilterPending)
2380 m_pendingState = completionState;
2381 FilterManager::FilterPolicy policy =
static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY |
2382 FilterManager::OFFSET_POLICY);
2383 m_FilterManager->setFilterPosition(fallbackFilterPosition, policy);
2386 setState(completionState);
2388 if (autoFocusUsed && buildOffsetsUsed)
2390 m_FilterManager->autoFocusComplete(completionState, currentPosition, m_LastSourceAutofocusTemperature,
2391 m_LastSourceAutofocusAlt);
2396QString Focus::getAnalyzeData()
2398 QString analysis_results =
"";
2400 for (
int i = 0; i < plot_position.size(); ++i)
2403 .arg(i == 0 ?
"" :
"|" )
2409 return analysis_results;
2412void Focus::completeFocusProcedure(FocusState completionState, AutofocusFailReason failCode,
QString failCodeInfo,
2416 if (inAutoFocus && failCode != Ekos::FOCUS_FAIL_ADVISOR_COMPLETE)
2419 updatePlotPosition();
2421 if (completionState == Ekos::FOCUS_COMPLETE)
2425 emit redrawHFRPlot(polynomialFit.get(), currentPosition, currentHFR);
2427 appendLogText(
i18np(
"Focus procedure completed after %1 iteration.",
2428 "Focus procedure completed after %1 iterations.", plot_position.count()));
2430 setLastFocusTemperature();
2432 resetAdaptiveFocus(m_OpsFocusSettings->focusAdaptive->isChecked());
2436 qCInfo(KSTARS_EKOS_FOCUS) <<
"Autofocus values: position," << currentPosition <<
", temperature,"
2437 << m_LastSourceAutofocusTemperature <<
", filter," <<
filter()
2438 <<
", HFR," << currentHFR <<
", altitude," << m_LastSourceAutofocusAlt;
2440 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL)
2443 plot_position.append(currentPosition);
2444 plot_value.append(currentHFR);
2445 plot_weight.append(1.0);
2446 plot_outlier.append(
false);
2449 appendFocusLogText(
QString(
"%1, %2, %3, %4, %5\n")
2456 absTicksSpin->setValue(currentPosition);
2459 else if (canAbsMove && initialFocuserAbsPosition >= 0 && resetFocusIteration <= MAXIMUM_RESET_ITERATIONS &&
2460 m_RestartState != RESTART_ABORT)
2463 bool const retry_focusing = m_RestartState == RESTART_NONE &&
2464 (failCode == Ekos::FOCUS_FAIL_ADVISOR_RERUN || ++resetFocusIteration < MAXIMUM_RESET_ITERATIONS);
2469 m_RestartState = RESTART_NOW;
2478 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2490 m_RestartState = RESTART_ABORT;
2496 resetFocusIteration = 0;
2499 const bool autoFocusUsed = inAutoFocus;
2500 const bool inBuildOffsetsUsed = inBuildOffsets;
2503 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot)
2504 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
2507 int const settleTime = m_GuidingSuspended ? m_OpsFocusSettings->focusGuideSettleTime->value() : 0;
2510 stop(completionState);
2513 appendLogText(
i18n(
"Settling for %1s...", settleTime));
2515 QTimer::singleShot(settleTime * 1000,
this, [ &, settleTime, completionState, autoFocusUsed, inBuildOffsetsUsed, failCode,
2518 settle(completionState, autoFocusUsed, inBuildOffsetsUsed, failCode, failCodeInfo);
2521 appendLogText(
i18n(
"Settling complete."));
2525void Focus::resetFocuser()
2528 if (m_Focuser && m_Focuser->isConnected() && initialFocuserAbsPosition >= 0)
2531 if (currentPosition == initialFocuserAbsPosition)
2534 appendLogText(
i18n(
"Autofocus failed, moving back to initial focus position %1.", initialFocuserAbsPosition));
2535 changeFocus(initialFocuserAbsPosition - currentPosition);
2540void Focus::setCurrentMeasure()
2543 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus newFITS #" << starMeasureFrames.count() + 1 <<
": Current HFR " << currentHFR <<
2545 << (starSelected ? 1 : currentNumStars);
2548 if (appendMeasure(currentMeasure))
2553 else starMeasureFrames.clear();
2558 emit newHFR(currentHFR, currentPosition, inAutoFocus, opticalTrain());
2560 emit newHFR(currentHFR, -1, inAutoFocus, opticalTrain());
2563 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2564 if (m_StarMeasure == FOCUS_STAR_FWHM)
2565 FWHMOut->setText(
QString(
"%1").arg(currentFWHM * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2566 starsOut->setText(
QString(
"%1").arg(m_ImageData->getDetectedStars()));
2567 iterOut->setText(
QString(
"%1").arg(absIterations + 1));
2570 if (lastHFR == INVALID_STAR_MEASURE)
2571 appendLogText(
i18n(
"FITS received. No stars detected."));
2574 if (!isStarMeasureStarBased() || currentHFR > 0)
2577 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && isVShapeSolution)
2579 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
2583 Edge selectedHFRStarHFR = m_ImageData->getSelectedHFRStar();
2590 if (starCenter.isNull() ==
false && (inAutoFocus || minimumRequiredHFR >= 0))
2593 starSelected =
true;
2594 starCenter.setX(qMax(0,
static_cast<int>(selectedHFRStarHFR.x)));
2595 starCenter.setY(qMax(0,
static_cast<int>(selectedHFRStarHFR.y)));
2597 syncTrackingBoxPosition();
2601 oneStar.
setZ(currentHFR);
2602 starsHFR.append(oneStar);
2607 QVector3D oneStar(starCenter.x(), starCenter.y(), currentHFR);
2608 starsHFR.append(oneStar);
2611 if (currentHFR > maxHFR)
2612 maxHFR = currentHFR;
2620 if (inFocusLoop || (inAutoFocus && ! isPositionBased()))
2622 int pos = plot_position.empty() ? 1 : plot_position.last() + 1;
2623 addPlotPosition(pos, currentMeasure);
2629 QVector3D oneStar(starCenter.x(), starCenter.y(), INVALID_STAR_MEASURE);
2630 starsHFR.append(oneStar);
2635 m_FocusView->updateFrame();
2639 if (m_abInsOn && !inScanStartPos && !focusAdvisor->inFocusAdvisor())
2640 calculateAbInsData();
2644void Focus::saveFocusFrame()
2646 if (inAutoFocus && Options::focusLogging() && Options::saveFocusImages())
2657 if (focusAdvisor->inFocusAdvisor())
2658 prefix = focusAdvisor->getFocusFramePrefix();
2659 else if (inScanStartPos)
2660 prefix =
QString(
"_ssp_%1_%2").
arg(m_AFRun).
arg(absIterations + 1);
2661 else if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser)
2663 const int currentStep = linearFocuser->currentStep() + 1;
2669 prefix.
append(
QString(
"_%1").arg(starMeasureFrames.count()));
2675 m_ImageData->saveImage(filename);
2679void Focus::calculateAbInsData()
2681 ImageMosaicMask *mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().
get());
2683 auto stars = m_ImageData->getStarCenters();
2686 for (
int star = 0; star < stars.
count(); star++)
2688 const int x = stars[star]->x;
2689 const int y = stars[star]->y;
2690 for (
int tile = 0; tile < NUM_TILES; tile++)
2692 QRect thisTile = tiles[tile];
2695 tileStars[tile].append(stars[star]);
2702 for (
int tile = 0; tile < tileStars.count(); tile++)
2704 double measure, weight;
2705 std::vector<double> HFRs;
2707 switch (m_StarMeasure)
2709 case FOCUS_STAR_HFR:
2710 case FOCUS_STAR_HFR_ADJ:
2711 for (
int star = 0; star < tileStars[tile].count(); star++)
2713 HFRs.push_back(tileStars[tile][star]->HFR);
2715 measure = Mathematics::RobustStatistics::ComputeLocation(Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, HFRs, 2);
2716 weight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), HFRs);
2718 case FOCUS_STAR_FWHM:
2719 getFWHM(tileStars[tile], &measure, &weight);
2721 case FOCUS_STAR_NUM_STARS:
2722 measure = tileStars[tile].count();
2725 case FOCUS_STAR_FOURIER_POWER:
2726 getFourierPower(&measure, &weight, tile);
2728 case FOCUS_STAR_STDDEV:
2729 case FOCUS_STAR_SOBEL:
2730 case FOCUS_STAR_LAPLASSIAN:
2731 case FOCUS_STAR_CANNY:
2732 getBlurriness(m_StarMeasure, m_OpsFocusProcess->focusDenoise->isChecked(), &measure, &weight,
QRect(), tile);
2735 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to calculate Aberration Inspector data";
2739 m_abInsMeasure[tile].append(measure);
2740 m_abInsWeight[tile].append(weight);
2741 m_abInsNumStars[tile].append(tileStars[tile].count());
2743 if (!linearFocuser->isInFirstPass())
2748 int xAv = 0, yAv = 0;
2749 if (m_StarMeasure != FOCUS_STAR_FOURIER_POWER)
2751 QPoint tileCenter = tiles[tile].center();
2752 int xSum = 0.0, ySum = 0.0;
2753 for (
int star = 0; star < tileStars[tile].count(); star++)
2755 xSum += tileStars[tile][star]->x - tileCenter.
x();
2756 ySum += tileStars[tile][star]->y - tileCenter.
y();
2759 xAv = (tileStars[tile].count() <= 0) ? 0 : xSum / tileStars[tile].count();
2760 yAv = (tileStars[tile].count() <= 0) ? 0 : ySum / tileStars[tile].count();
2762 m_abInsTileCenterOffset.append(
QPoint(xAv, yAv));
2765 m_abInsPosition.append(currentPosition);
2768void Focus::setCaptureComplete()
2770 DarkLibrary::Instance()->disconnect(
this);
2773 syncTrackingBoxPosition();
2776 if (inFocusLoop ==
false)
2777 appendLogText(
i18n(
"Image received."));
2779 if (m_captureInProgress && inFocusLoop ==
false && inAutoFocus ==
false)
2780 m_Camera->setUploadMode(rememberUploadMode);
2782 if (m_RememberCameraFastExposure && inFocusLoop ==
false && inAutoFocus ==
false)
2784 m_RememberCameraFastExposure =
false;
2785 m_Camera->setFastExposureEnabled(
true);
2788 m_captureInProgress =
false;
2789 if (m_abortInProgress)
2793 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame results in " << __FUNCTION__;
2798 checkMosaicMaskLimits();
2801 emit newImage(m_FocusView);
2803 emit newStarPixmap(m_FocusView->getTrackingBoxPixmap(10));
2811 if (!isStarMeasureStarBased())
2812 starDetectionFinished();
2813 else if (inFocusLoop ==
false || (inFocusLoop && (m_FocusView->isTrackingBoxEnabled()
2814 || m_OpsFocusSettings->focusUseFullField->isChecked())))
2820void Focus::setHFRComplete()
2830 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
2833 int subBinX = 1, subBinY = 1;
2834 if (!targetChip->getBinning(&subBinX, &subBinY))
2835 qCDebug(KSTARS_EKOS_FOCUS) <<
"Warning: target chip is reporting no binning property, using 1x1.";
2837 if (m_OpsFocusSettings->focusSubFrame->isChecked() && !isStarMeasureStarBased() && !starSelected)
2839 appendLogText(
i18n(
"Capture complete. Select a region of interest."));
2841 syncTrackingBoxPosition();
2844 setState(Ekos::FOCUS_WAITING);
2847 waitStarSelectTimer.start();
2850 else if (m_OpsFocusSettings->focusSubFrame->isChecked() && isStarMeasureStarBased() && starCenter.isNull())
2857 int x = 0, y = 0, w = 0, h = 0;
2860 if (frameSettings.contains(targetChip))
2862 QVariantMap settings = frameSettings[targetChip];
2863 x = settings[
"x"].toInt();
2864 y = settings[
"y"].toInt();
2865 w = settings[
"w"].toInt();
2866 h = settings[
"h"].toInt();
2870 targetChip->getFrame(&x, &y, &w, &h);
2873 if (m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
2876 const Edge selectedHFRStar = m_ImageData->getSelectedHFRStar();
2878 if (selectedHFRStar.x == -1)
2880 appendLogText(
i18n(
"Failed to automatically select a star. Please select a star manually."));
2883 m_FocusView->setTrackingBox(
QRect(w - m_OpsFocusSettings->focusBoxSize->value() / (subBinX * 2),
2884 h - m_OpsFocusSettings->focusBoxSize->value() / (subBinY * 2),
2885 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
2886 m_FocusView->setTrackingBoxEnabled(
true);
2889 setState(Ekos::FOCUS_WAITING);
2892 waitStarSelectTimer.start();
2898 starCenter.setX(selectedHFRStar.x);
2899 starCenter.setY(selectedHFRStar.y);
2900 starCenter.setZ(subBinX);
2901 starSelected =
true;
2902 syncTrackingBoxPosition();
2905 if (subFramed ==
false && isFocusSubFrameEnabled() && m_OpsFocusSettings->focusSubFrame->isChecked())
2907 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
2908 int subX = (selectedHFRStar.x - offset) * subBinX;
2909 int subY = (selectedHFRStar.y - offset) * subBinY;
2910 int subW = offset * 2 * subBinX;
2911 int subH = offset * 2 * subBinY;
2913 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2914 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2921 if ((subW + subX) > maxW)
2923 if ((subH + subY) > maxH)
2928 QVariantMap settings = frameSettings[targetChip];
2929 settings[
"x"] = subX;
2930 settings[
"y"] = subY;
2931 settings[
"w"] = subW;
2932 settings[
"h"] = subH;
2933 settings[
"binx"] = subBinX;
2934 settings[
"biny"] = subBinY;
2936 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << subX <<
"Y:" << subY <<
"W:" << subW <<
"H:" << subH <<
"binX:" <<
2937 subBinX <<
"binY:" << subBinY;
2941 frameSettings[targetChip] = settings;
2944 starCenter.setX(subW / (2 * subBinX));
2945 starCenter.setY(subH / (2 * subBinY));
2946 starCenter.setZ(subBinX);
2950 m_FocusView->setFirstLoad(
true);
2959 starCenter.setX(selectedHFRStar.x);
2960 starCenter.setY(selectedHFRStar.y);
2961 starCenter.setZ(subBinX);
2974 appendLogText(
i18n(
"Capture complete. Select a star to focus."));
2976 starSelected =
false;
2980 int subBinX = 1, subBinY = 1;
2981 targetChip->getBinning(&subBinX, &subBinY);
2983 m_FocusView->setTrackingBox(
QRect((w - m_OpsFocusSettings->focusBoxSize->value()) / (subBinX * 2),
2984 (h - m_OpsFocusSettings->focusBoxSize->value()) / (2 * subBinY),
2985 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
2986 m_FocusView->setTrackingBoxEnabled(
true);
2989 setState(Ekos::FOCUS_WAITING);
2992 waitStarSelectTimer.start();
2998 if (minimumRequiredHFR >= 0)
3001 if (currentHFR == INVALID_STAR_MEASURE)
3003 if (noStarCount++ < MAX_RECAPTURE_RETRIES)
3005 appendLogText(
i18n(
"No stars detected while testing HFR, capturing again..."));
3007 if (noStarCount == MAX_RECAPTURE_RETRIES)
3016 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3021 else if (currentHFR > minimumRequiredHFR)
3023 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is above required minimum HFR:" << minimumRequiredHFR <<
3024 ". Starting AutoFocus...";
3027 minimumRequiredHFR = INVALID_STAR_MEASURE;
3028 runAutoFocus(AutofocusReason::FOCUS_HFR_CHECK, reasonInfo);
3033 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is below required minimum HFR:" << minimumRequiredHFR <<
3034 ". Autofocus successful.";
3035 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3043 if (inAutoFocus ==
false)
3047 if (state() != Ekos::FOCUS_IDLE)
3048 setState(Ekos::FOCUS_IDLE);
3055 if (state() != Ekos::FOCUS_PROGRESS)
3056 setState(Ekos::FOCUS_PROGRESS);
3061 else if(focusAdvisor->inFocusAdvisor())
3062 focusAdvisor->control();
3063 else if(m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3065 else if (canAbsMove || canRelMove)
3073QString Focus::getyAxisLabel(StarMeasure starMeasure)
3076 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3078 switch (starMeasure)
3080 case FOCUS_STAR_HFR:
3082 case FOCUS_STAR_HFR_ADJ:
3084 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3086 case FOCUS_STAR_FWHM:
3088 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3090 case FOCUS_STAR_NUM_STARS:
3093 case FOCUS_STAR_FOURIER_POWER:
3094 str =
"Fourier Power";
3096 case FOCUS_STAR_STDDEV:
3099 case FOCUS_STAR_SOBEL:
3100 str =
"Sobel Factor";
3102 case FOCUS_STAR_LAPLASSIAN:
3103 str =
"Laplassian Factor";
3105 case FOCUS_STAR_CANNY:
3106 str =
"Canny Factor";
3114void Focus::clearDataPoints()
3117 polynomialFit.reset();
3118 plot_position.
clear();
3120 plot_weight.clear();
3121 plot_outlier.clear();
3122 isVShapeSolution =
false;
3123 m_abInsPosition.clear();
3124 m_abInsTileCenterOffset.clear();
3125 if (m_abInsMeasure.count() != NUM_TILES)
3127 m_abInsMeasure.resize(NUM_TILES);
3128 m_abInsWeight.resize(NUM_TILES);
3129 m_abInsNumStars.resize(NUM_TILES);
3133 for (
int i = 0; i < m_abInsMeasure.count(); i++)
3135 m_abInsMeasure[i].clear();
3136 m_abInsWeight[i].clear();
3137 m_abInsNumStars[i].clear();
3141 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3142 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(),
3143 inFocusLoop ==
false && isPositionBased());
3146bool Focus::autoFocusChecks()
3148 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3150 appendLogText(
i18n(
"Autofocus failed: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3151 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3156 if (isStarMeasureStarBased() && currentHFR == INVALID_STAR_MEASURE)
3158 if (noStarCount < MAX_RECAPTURE_RETRIES)
3161 appendLogText(
i18n(
"No stars detected, capturing again..."));
3165 else if (m_FocusAlgorithm == FOCUS_LINEAR)
3167 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
3170 else if(!m_OpsFocusProcess->focusDonut->isChecked())
3173 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
3174 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3184void Focus::plotLinearFocus()
3193 linearFocuser->getMeasurements(&positions, &values, &weights);
3194 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3201 bool incrementalChange =
false;
3202 if (positions.
size() > 1 && positions.
size() == lastPositions.
size() + 1)
3205 for (
int i = 0; i < positions.
size() - 1; ++i)
3206 if (positions[i] != lastPositions[i] || values[i] != lastValues[i])
3211 incrementalChange =
ok;
3213 lastPositions = positions;
3214 lastValues = values;
3216 const bool outlier =
false;
3217 if (incrementalChange)
3218 emit newHFRPlotPosition(
static_cast<double>(positions.
last()), values.
last(), (pow(weights.
last(), -0.5)),
3219 outlier, params.initialStepSize, plt);
3222 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3223 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, params.useWeights, plt);
3224 for (
int i = 0; i < positions.
size(); ++i)
3225 emit newHFRPlotPosition(
static_cast<double>(positions[i]), values[i], (pow(weights.
last(), -0.5)),
3226 outlier, params.initialStepSize, plt);
3230 if (values.
size() > 3)
3236 double minPosition, minValue;
3237 double searchMin = std::max(params.minPositionAllowed, params.startPosition - params.maxTravel);
3238 double searchMax = std::min(params.maxPositionAllowed, params.startPosition + params.maxTravel);
3240 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3241 if (m_FocusAlgorithm == FOCUS_LINEAR || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3245 polynomialFit.reset(
new PolynomialFit(2, pass1Positions, pass1Values));
3247 if (polynomialFit->findMinimum(params.startPosition, searchMin, searchMax, &minPosition, &minValue))
3249 emit drawPolynomial(polynomialFit.get(),
true,
true, plt);
3253 if (linearFocuser->isDone())
3254 emit minimumFound(-1, -1, plt);
3256 emit minimumFound(minPosition, minValue, plt);
3261 emit drawPolynomial(polynomialFit.get(),
false,
false, plt);
3262 emit minimumFound(-1, -1, plt);
3268 if (curveFitting->findMinMax(params.startPosition, searchMin, searchMax, &minPosition, &minValue, params.curveFit,
3269 params.optimisationDirection))
3271 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3272 emit drawCurve(curveFitting.get(),
true,
true, plt);
3275 emit minimumFound(minPosition, minValue, plt);
3280 emit drawCurve(curveFitting.get(),
false,
false, plt);
3281 emit minimumFound(-1, -1, plt);
3287 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
3289 emit setTitle(linearFocuser->getTextStatus(R2));
3291 if (!plt) HFRPlot->replot();
3295CurveFitting::FittingGoal Focus::getGoal(
int numSteps)
3298 if (m_FocusWalk == FOCUS_WALK_CLASSIC)
3299 return CurveFitting::FittingGoal::STANDARD;
3302 return (numSteps >= m_OpsFocusMechanics->focusNumSteps->value()) ? CurveFitting::FittingGoal::BEST :
3303 CurveFitting::FittingGoal::STANDARD;
3309void Focus::plotLinearFinalUpdates()
3312 if (!m_OpsFocusProcess->focusRefineCurveFit->isChecked())
3315 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3316 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3318 emit finalUpdates(linearFocuser->getTextStatus(R2), plt);
3328 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3329 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3331 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3332 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(), plt);
3334 for (
int i = 0; i < pass1Positions.
size(); ++i)
3335 emit newHFRPlotPosition(
static_cast<double>(pass1Positions[i]), pass1Values[i], (pow(pass1Weights[i], -0.5)),
3336 pass1Outliers[i], params.initialStepSize, plt);
3338 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3339 emit drawCurve(curveFitting.get(),
true,
true,
false);
3342 emit minimumFound(linearFocuser->solution(), linearFocuser->solutionValue(), plt);
3344 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3345 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3347 emit setTitle(linearFocuser->getTextStatus(R2), plt);
3351void Focus::startAberrationInspector()
3353#ifdef HAVE_DATAVISUALIZATION
3355 AberrationInspector::abInsData data;
3357 ImageMosaicMask *mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().
get());
3360 appendLogText(
i18n(
"Unable to launch Aberration Inspector run %1...", m_abInsRun));
3365 data.run = ++m_abInsRun;
3366 data.curveFit = m_CurveFit;
3367 data.useWeights = m_OpsFocusProcess->focusUseWeights->isChecked();
3368 data.optDir = m_OptDir;
3369 data.sensorWidth = m_CcdWidth;
3370 data.sensorHeight = m_CcdHeight;
3371 data.pixelSize = m_CcdPixelSizeX;
3372 data.tileWidth = mosaicmask->tiles()[0].width();
3373 data.focuserStepMicrons = m_CFZUI->focusCFZStepSize->value();
3374 data.yAxisLabel = getyAxisLabel(m_StarMeasure);
3375 data.starUnits = getStarUnits(m_StarMeasure, m_StarUnits);
3376 data.cfzSteps = m_cfzSteps;
3377 data.isPositionBased = isPositionBased();
3380 appendLogText(
i18n(
"Launching Aberration Inspector run %1...", m_abInsRun));
3382 m_abInsNumStars, m_abInsTileCenterOffset));
3389bool Focus::initScanStartPos(
const bool force,
const int initialPosition)
3393 if (!m_OpsFocusProcess->focusScanStartPos->isChecked())
3396 if (!m_OpsFocusProcess->focusScanAlwaysOn->isChecked() && !m_AFRerun)
3401 inScanStartPos =
true;
3402 initialFocuserAbsPosition = initialPosition;
3403 m_scanMeasure.clear();
3404 m_scanPosition.clear();
3406 appendLogText(
i18n(
"Starting scan for initial focuser position."));
3407 emit setTitle(
QString(
i18n(
"Scanning for starting position...")),
true);
3409 if (!changeFocus(initialPosition - currentPosition))
3410 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3415void Focus::scanStartPos()
3418 if (currentHFR == INVALID_STAR_MEASURE)
3420 if (noStarCount < MAX_RECAPTURE_RETRIES)
3423 appendLogText(
i18n(
"No stars detected, capturing again..."));
3429 appendLogText(
i18n(
"Failed to detect any stars. Aborting..."));
3430 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3436 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3438 appendLogText(
i18n(
"Scan Start Pos: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3439 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3444 m_scanPosition.push_back(currentPosition);
3445 m_scanMeasure.push_back(currentMeasure);
3448 const int step = m_scanPosition.size();
3449 const int maxSteps = m_OpsFocusProcess->focusScanDatapoints->value();
3450 const int stepSize = m_OpsFocusMechanics->focusTicks->value() * m_OpsFocusProcess->focusScanStepSizeFactor->value();
3451 emit newHFRPlotPosition(
static_cast<double>(currentPosition), currentMeasure, pow(currentWeight, -0.5),
false, stepSize,
3453 if (step < maxSteps)
3456 emit setTitle(
QString(
i18n(
"Scanning for starting position %1/%2", step, maxSteps)),
true);
3457 deltaPos = step * stepSize * std::pow(-1, step + 1);
3462 auto it = std::min_element(std::begin(m_scanMeasure), std::end(m_scanMeasure));
3463 auto min = std::distance(std::begin(m_scanMeasure), it);
3464 if (min >= m_OpsFocusProcess->focusScanDatapoints->value() - 2)
3467 deltaPos = m_scanPosition[min] - currentPosition;
3468 m_scanPosition.clear();
3469 m_scanMeasure.clear();
3470 emit setTitle(
QString(
i18n(
"No scan minimum - widening search...")),
true);
3475 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
3476 focusAdvisor->setInFocusAdvisor(
false);
3478 const int initialPosition = m_scanPosition[min];
3479 setupLinearFocuser(initialPosition);
3480 inScanStartPos =
false;
3482 deltaPos = linearRequestedPosition - currentPosition;
3483 emit setTitle(
QString(
i18n(
"Scan Start Position %1 Found", initialPosition)),
true);
3484 appendLogText(
i18n(
"Scan Start Position %1 found", initialPosition));
3487 if (!changeFocus(deltaPos))
3488 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3491void Focus::autoFocusLinear()
3493 if (!autoFocusChecks())
3496 if (!canAbsMove && !canRelMove && canTimerMove)
3499 if (linearRequestedPosition != currentPosition)
3502 qCDebug(KSTARS_EKOS_FOCUS) <<
"Linear: warning, changing position " << currentPosition <<
" to "
3503 << linearRequestedPosition;
3505 currentPosition = linearRequestedPosition;
3510 bool useFocusStarsHFR = m_OpsFocusSettings->focusUseFullField->isChecked()
3511 && m_OpsFocusProcess->focusFramesCount->value() == 1;
3512 auto focusStars = useFocusStarsHFR || (m_FocusAlgorithm == FOCUS_LINEAR1PASS) ? &(m_ImageData->getStarCenters()) :
nullptr;
3514 linearRequestedPosition = linearFocuser->newMeasurement(currentPosition, currentMeasure, currentWeight, focusStars);
3515 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser->isDone() && linearFocuser->solution() != -1)
3518 plotLinearFinalUpdates();
3520 startAberrationInspector();
3526 if (linearFocuser->isDone())
3528 if (linearFocuser->solution() != -1)
3531 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
3533 if (focusAdvisor->analyseAF())
3534 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_ADVISOR_RERUN,
"",
false);
3536 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3538 else if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3540 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3541 else if (R2 >= m_OpsFocusProcess->focusR2Limit->value())
3545 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Linear Curve Fit check passed R2=%1 focusR2Limit=%2").
arg(R2).
arg(
3546 m_OpsFocusProcess->focusR2Limit->value());
3547 completeFocusProcedure(Ekos::FOCUS_COMPLETE, FOCUS_FAIL_NONE,
"",
false);
3550 else if (R2Retries == 0)
3553 appendLogText(
i18n(
"Curve Fit check failed R2=%1 focusR2Limit=%2 retrying...", R2,
3554 m_OpsFocusProcess->focusR2Limit->value()));
3557 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_R2, failCodeInfo,
false);
3563 appendLogText(
i18n(
"Curve Fit check failed again R2=%1 focusR2Limit=%2 but continuing...", R2,
3564 m_OpsFocusProcess->focusR2Limit->value()));
3565 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3571 qCDebug(KSTARS_EKOS_FOCUS) << linearFocuser->doneReason();
3572 AutofocusFailReason failCode = linearFocuser->getFailCode();
3573 appendLogText(
i18n(
"Linear autofocus algorithm aborted: %1", AutofocusFailReasonStr[failCode]));
3574 completeFocusProcedure(Ekos::FOCUS_ABORTED, failCode,
"",
false);
3580 const int delta = linearRequestedPosition - currentPosition;
3582 if (!changeFocus(delta))
3583 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE,
"",
false);
3589void Focus::autoFocusAbs()
3593 static int minHFRPos = 0, focusOutLimit = 0, focusInLimit = 0, lastHFRPos = 0, fluctuations = 0;
3594 static double minHFR = 0, lastDelta = 0;
3595 double targetPosition = 0;
3596 bool ignoreLimitedDelta =
false;
3598 QString deltaTxt =
QString(
"%1").
arg(fabs(currentHFR - minHFR) * 100.0, 0,
'g', 3);
3601 qCDebug(KSTARS_EKOS_FOCUS) <<
"===============================";
3602 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR: " << currentHFR <<
" Current Position: " << currentPosition;
3603 qCDebug(KSTARS_EKOS_FOCUS) <<
"Last minHFR: " << minHFR <<
" Last MinHFR Pos: " << minHFRPos;
3604 qCDebug(KSTARS_EKOS_FOCUS) <<
"Delta: " << deltaTxt <<
"%";
3605 qCDebug(KSTARS_EKOS_FOCUS) <<
"========================================";
3608 appendLogText(
i18n(
"FITS received. HFR %1 @ %2. Delta (%3%)", HFRText, currentPosition, deltaTxt));
3610 appendLogText(
i18n(
"FITS received. HFR %1 @ %2.", HFRText, currentPosition));
3612 if (!autoFocusChecks())
3615 addPlotPosition(currentPosition, currentHFR);
3617 switch (m_LastFocusDirection)
3620 lastHFR = currentHFR;
3621 initialFocuserAbsPosition = currentPosition;
3622 minHFR = currentHFR;
3623 minHFRPos = currentPosition;
3633 if (absMotionMax < currentPosition + pulseDuration)
3635 if (currentPosition < absMotionMax)
3637 pulseDuration = absMotionMax - currentPosition;
3642 m_LastFocusDirection = FOCUS_IN;
3645 else if (currentPosition + pulseDuration < absMotionMin)
3647 if (absMotionMin < currentPosition)
3649 pulseDuration = currentPosition - absMotionMin;
3654 m_LastFocusDirection = FOCUS_OUT;
3658 m_LastFocusDirection = (pulseDuration > 0) ? FOCUS_OUT : FOCUS_IN;
3659 if (!changeFocus(pulseDuration,
false))
3660 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3666 if (reverseDir && focusInLimit && focusOutLimit &&
3667 fabs(currentHFR - minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
3669 if (absIterations <= 2)
3671 QString message =
i18n(
"Change in HFR is too small. Try increasing the step size or decreasing the tolerance.");
3672 appendLogText(message);
3673 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3674 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_SMALL_HFR);
3676 else if (noStarCount > 0)
3678 QString message =
i18n(
"Failed to detect focus star in frame. Capture and select a focus star.");
3679 appendLogText(message);
3680 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3681 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3685 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3689 else if (currentHFR < lastHFR)
3692 if (HFRInc >= 1 && m_LastFocusDirection == FOCUS_OUT && lastHFRPos < focusInLimit && fabs(currentHFR - lastHFR) > 0.1)
3694 focusInLimit = lastHFRPos;
3695 qCDebug(KSTARS_EKOS_FOCUS) <<
"New FocusInLimit " << focusInLimit;
3697 else if (HFRInc >= 1 && m_LastFocusDirection == FOCUS_IN && lastHFRPos > focusOutLimit &&
3698 fabs(currentHFR - lastHFR) > 0.1)
3700 focusOutLimit = lastHFRPos;
3701 qCDebug(KSTARS_EKOS_FOCUS) <<
"New FocusOutLimit " << focusOutLimit;
3704 double factor = std::max(1.0, HFRDec / 2.0);
3705 if (m_LastFocusDirection == FOCUS_IN)
3706 targetPosition = currentPosition - (pulseDuration * factor);
3708 targetPosition = currentPosition + (pulseDuration * factor);
3710 qCDebug(KSTARS_EKOS_FOCUS) <<
"current Position" << currentPosition <<
" targetPosition " << targetPosition;
3712 lastHFR = currentHFR;
3715 if (lastHFR < minHFR)
3718 minHFRPos = currentPosition;
3719 qCDebug(KSTARS_EKOS_FOCUS) <<
"new minHFR " << minHFR <<
" @ position " << minHFRPos;
3722 lastHFRPos = currentPosition;
3729 if (plot_position.count() >= 2)
3731 plot_position.remove(plot_position.count() - 2);
3732 plot_value.remove(plot_value.count() - 2);
3746 lastHFR = currentHFR;
3747 lastHFRPos = currentPosition;
3756 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus is moving away from optimal HFR.";
3759 if (m_LastFocusDirection == FOCUS_IN)
3761 focusInLimit = currentPosition;
3762 qCDebug(KSTARS_EKOS_FOCUS) <<
"Setting focus IN limit to " << focusInLimit;
3766 focusOutLimit = currentPosition;
3767 qCDebug(KSTARS_EKOS_FOCUS) <<
"Setting focus OUT limit to " << focusOutLimit;
3770 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot_position.count() > 4)
3772 polynomialFit.reset(
new PolynomialFit(2, 5, plot_position, plot_value));
3773 double a = *std::min_element(plot_position.constBegin(), plot_position.constEnd());
3774 double b = *std::max_element(plot_position.constBegin(), plot_position.constEnd());
3775 double min_position = 0, min_hfr = 0;
3776 isVShapeSolution = polynomialFit->findMinimum(minHFRPos, a, b, &min_position, &min_hfr);
3777 qCDebug(KSTARS_EKOS_FOCUS) <<
"Found Minimum?" << (isVShapeSolution ?
"Yes" :
"No");
3778 if (isVShapeSolution)
3780 ignoreLimitedDelta =
true;
3781 qCDebug(KSTARS_EKOS_FOCUS) <<
"Minimum Solution:" << min_hfr <<
"@" << min_position;
3782 targetPosition = round(min_position);
3783 appendLogText(
i18n(
"Found polynomial solution @ %1",
QString::number(min_position,
'f', 0)));
3785 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
3786 emit minimumFound(min_position, min_hfr);
3790 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
false);
3799 if (std::abs(lastDelta) > 0)
3800 targetPosition = currentPosition + lastDelta;
3802 targetPosition = currentPosition + pulseDuration;
3804 else if (isVShapeSolution ==
false)
3806 ignoreLimitedDelta =
true;
3808 if (m_LastFocusDirection == FOCUS_OUT)
3809 targetPosition = minHFRPos - pulseDuration / 2;
3811 targetPosition = minHFRPos + pulseDuration / 2;
3814 qCDebug(KSTARS_EKOS_FOCUS) <<
"new targetPosition " << targetPosition;
3818 if (focusInLimit != 0 && m_LastFocusDirection == FOCUS_IN && targetPosition < focusInLimit)
3820 targetPosition = focusInLimit;
3821 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus in limit " << targetPosition;
3823 else if (focusOutLimit != 0 && m_LastFocusDirection == FOCUS_OUT && targetPosition > focusOutLimit)
3825 targetPosition = focusOutLimit;
3826 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus out limit " << targetPosition;
3830 if (targetPosition < absMotionMin)
3831 targetPosition = absMotionMin;
3832 else if (targetPosition > absMotionMax)
3833 targetPosition = absMotionMax;
3836 if (targetPosition == currentPosition)
3840 if (targetPosition == minHFRPos || isVShapeSolution)
3842 appendLogText(
"Stopping at minimum recorded HFR position.");
3843 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3847 QString message =
i18n(
"Focuser cannot move further, device limits reached. Autofocus aborted.");
3848 appendLogText(message);
3849 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3850 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3856 if (fluctuations >= MAXIMUM_FLUCTUATIONS)
3858 QString message =
i18n(
"Unstable fluctuations. Try increasing initial step size or exposure time.");
3859 appendLogText(message);
3860 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3861 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FLUCTUATIONS);
3866 if (focusOutLimit && focusOutLimit == focusInLimit)
3868 QString message =
i18n(
"Deadlock reached. Please try again with different settings.");
3869 appendLogText(message);
3870 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3871 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_DEADLOCK);
3876 if (fabs(targetPosition - initialFocuserAbsPosition) > m_OpsFocusMechanics->focusMaxTravel->value())
3878 int minTravelLimit = qMax(0.0, initialFocuserAbsPosition - m_OpsFocusMechanics->focusMaxTravel->value());
3879 int maxTravelLimit = qMin(absMotionMax, initialFocuserAbsPosition + m_OpsFocusMechanics->focusMaxTravel->value());
3883 if (fabs(currentPosition - minTravelLimit) > 10 && targetPosition < minTravelLimit)
3885 targetPosition = minTravelLimit;
3888 else if (fabs(currentPosition - maxTravelLimit) > 10 && targetPosition > maxTravelLimit)
3890 targetPosition = maxTravelLimit;
3894 qCDebug(KSTARS_EKOS_FOCUS) <<
"targetPosition (" << targetPosition <<
") - initHFRAbsPos ("
3895 << initialFocuserAbsPosition <<
") exceeds maxTravel distance of " << m_OpsFocusMechanics->focusMaxTravel->value();
3897 QString message =
i18n(
"Maximum travel limit reached. Autofocus aborted.");
3898 appendLogText(message);
3899 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3900 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3906 lastDelta = (targetPosition - currentPosition);
3908 qCDebug(KSTARS_EKOS_FOCUS) <<
"delta (targetPosition - currentPosition) " << lastDelta;
3911 if (ignoreLimitedDelta ==
false)
3913 double limitedDelta = qMax(-1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(),
3914 qMin(1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(), lastDelta));
3915 if (std::fabs(limitedDelta - lastDelta) > 0)
3917 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limited delta to maximum permitted single step " <<
3918 m_OpsFocusMechanics->focusMaxSingleStep->value();
3919 lastDelta = limitedDelta;
3923 m_LastFocusDirection = (lastDelta > 0) ? FOCUS_OUT : FOCUS_IN;
3924 if (!changeFocus(lastDelta,
false))
3925 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3931void Focus::addPlotPosition(
int pos,
double value,
bool plot)
3933 plot_position.append(pos);
3934 plot_value.append(value);
3936 emit newHFRPlotPosition(
static_cast<double>(pos), value, 1.0,
false, pulseDuration);
3942void Focus::updatePlotPosition()
3944 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3947 if (inScanStartPos || focusAdvisor->inFocusAdvisor())
3950 plot_position.clear();
3952 plot_weight.clear();
3953 plot_outlier.clear();
3957 linearFocuser->getPass1Measurements(&positions, &plot_value, &plot_weight, &plot_outlier);
3958 plot_position.clear();
3959 for (
int i = 0; i < positions.
count(); i++)
3960 plot_position.append(positions[i]);
3963 if (linearFocuser && linearFocuser->isDone() && linearFocuser->solution() != -1)
3965 plot_position.append(linearFocuser->solution());
3966 plot_value.append(linearFocuser->solutionValue());
3967 plot_weight.append(linearFocuser->solutionWeight());
3968 plot_outlier.append(
false);
3972 else if (m_FocusAlgorithm == FOCUS_LINEAR)
3975 linearFocuser->getMeasurements(&positions, &plot_value, &plot_weight);
3976 plot_position.
clear();
3977 plot_outlier.clear();
3978 for (
int i = 0; i < positions.
count(); i++)
3980 plot_position.append(positions[i]);
3982 plot_outlier.append(
false);
3988 for (
int i = 0; i < plot_position.count(); i++)
3990 plot_weight.append(1.0);
3991 plot_outlier.append(
false);
3996void Focus::autoFocusRel()
3998 static int noStarCount = 0;
3999 static double minHFR = 1e6;
4000 QString deltaTxt =
QString(
"%1").
arg(fabs(currentHFR - minHFR) * 100.0, 0,
'g', 2);
4004 appendLogText(
i18n(
"FITS received. HFR %1. Delta (%2%) Min HFR (%3)", HFRText, deltaTxt, minHFRText));
4006 if (pulseDuration <= MINIMUM_PULSE_TIMER)
4008 appendLogText(
i18n(
"Autofocus failed to reach proper focus. Try adjusting the tolerance value."));
4009 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_TOLERANCE);
4014 if (currentHFR == INVALID_STAR_MEASURE)
4016 if (noStarCount < MAX_RECAPTURE_RETRIES)
4019 appendLogText(
i18n(
"No stars detected, capturing again..."));
4023 else if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4025 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
4028 else if(!m_OpsFocusProcess->focusDonut->isChecked())
4031 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
4032 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
4039 switch (m_LastFocusDirection)
4042 lastHFR = currentHFR;
4044 m_LastFocusDirection = FOCUS_IN;
4045 changeFocus(-pulseDuration,
false);
4050 if (fabs(currentHFR - minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
4052 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
4054 else if (currentHFR < lastHFR)
4056 if (currentHFR < minHFR)
4057 minHFR = currentHFR;
4059 lastHFR = currentHFR;
4060 changeFocus(m_LastFocusDirection == FOCUS_IN ? -pulseDuration : pulseDuration,
false);
4067 lastHFR = currentHFR;
4071 pulseDuration *= 0.75;
4073 if (!changeFocus(m_LastFocusDirection == FOCUS_IN ? pulseDuration : -pulseDuration,
false))
4074 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4077 m_LastFocusDirection = (m_LastFocusDirection == FOCUS_IN) ? FOCUS_OUT : FOCUS_IN;
4083void Focus::autoFocusProcessPositionChange(IPState state)
4085 if (state == IPS_OK)
4091 if (focuserAdditionalMovement > 0)
4093 int temp = focuserAdditionalMovement;
4094 focuserAdditionalMovement = 0;
4096 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Undoing overscan extension. Moving back in by %1 ticks in %2s")
4097 .
arg(temp).
arg(m_OpsFocusMechanics->focusOverscanDelay->value());
4099 QTimer::singleShot(m_OpsFocusMechanics->focusOverscanDelay->value() * 1000,
this, [
this, temp]()
4101 if (!changeFocus(-temp, focuserAdditionalMovementUpdateDir))
4103 appendLogText(i18n(
"Focuser error, check INDI panel."));
4104 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4108 else if (inAutoFocus)
4111 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4112 if (abs(linearRequestedPosition - currentPosition) > m_OpsFocusMechanics->focusTicks->value())
4113 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Focus positioning error: requested position %1, current position %2")
4114 .
arg(linearRequestedPosition).
arg(currentPosition);
4116 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Focus position reached at %1, starting capture in %2 seconds.").
arg(
4117 currentPosition).
arg(m_OpsFocusMechanics->focusSettleTime->value());
4119 if (m_OpsFocusProcess->focusDonut->isChecked())
4120 donutTimeDilation();
4121 capture(m_OpsFocusMechanics->focusSettleTime->value());
4124 else if (state == IPS_ALERT)
4126 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4127 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
4130 qCDebug(KSTARS_EKOS_FOCUS) <<
4131 QString(
"autoFocusProcessPositionChange called with state %1 (%2), focuserAdditionalMovement=%3, inAutoFocus=%4, m_captureInProgress=%5, currentPosition=%6")
4132 .
arg(state).
arg(pstateStr(state)).
arg(focuserAdditionalMovement).
arg(inAutoFocus).
arg(m_captureInProgress)
4133 .
arg(currentPosition);
4137void Focus::donutTimeDilation()
4139 if (m_OpsFocusProcess->focusTimeDilation->value() == 1.0 || inScanStartPos || focusAdvisor->inFocusAdvisor())
4143 const double centre = (m_OpsFocusMechanics->focusNumSteps->value() + 1.0) / 2.0;
4145 const int currentStep = linearFocuser->currentStep() + 1;
4147 if (currentStep <= m_OpsFocusMechanics->focusNumSteps->value())
4148 distance = std::abs(centre - currentStep);
4152 double multiplier =
distance / (centre - 1.0) * m_OpsFocusProcess->focusTimeDilation->value();
4153 multiplier = std::max(multiplier, 1.0);
4154 const double exposure = multiplier * m_donutOrigExposure;
4155 focusExposure->setValue(exposure);
4156 qCDebug(KSTARS_EKOS_FOCUS) <<
"Donut time dilation for point " << currentStep <<
" from " << m_donutOrigExposure <<
" to "
4161void Focus::updateProperty(INDI::Property prop)
4163 if (m_Focuser ==
nullptr || prop.getType() != INDI_NUMBER || prop.getDeviceName() != m_Focuser->getDeviceName())
4166 auto nvp = prop.getNumber();
4172 if (nvp->isNameMatch(
"FOCUS_BACKLASH_STEPS"))
4174 m_OpsFocusMechanics->focusBacklash->setValue(nvp->np[0].value);
4178 if (nvp->isNameMatch(
"ABS_FOCUS_POSITION"))
4183 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4185 if (m_DebugFocuserCounter == 14)
4186 m_DebugFocuserCounter = 0;
4187 appendLogText(
i18n(
"Simulate focuser comms failure..."));
4192 m_FocusMotionTimer.stop();
4193 INumber *pos = IUFindNumber(nvp,
"FOCUS_ABSOLUTE_POSITION");
4194 IPState newState = nvp->s;
4199 int newPosition =
static_cast<int>(pos->value);
4204 if (currentPosition == newPosition && currentPositionState == newState)
4206 if (logPositionAndState)
4208 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focuser position " << currentPosition <<
" and state:"
4209 << pstateStr(currentPositionState) <<
" unchanged";
4210 logPositionAndState =
false;
4216 logPositionAndState =
true;
4219 currentPositionState = newState;
4221 if (currentPosition != newPosition)
4223 currentPosition = newPosition;
4224 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abs Focuser position changed to " << currentPosition <<
"State:" << pstateStr(
4225 currentPositionState);
4227 emit absolutePositionChanged(currentPosition);
4231 qCDebug(KSTARS_EKOS_FOCUS) <<
"Can't access FOCUS_ABSOLUTE_POSITION. Current state:"
4232 << pstateStr(currentPositionState) <<
" New state:" << pstateStr(newState);
4234 if (newState != IPS_OK)
4236 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
4240 qCDebug(KSTARS_EKOS_FOCUS) <<
"Restarting focus motion timer, state " << pstateStr(newState);
4241 m_FocusMotionTimer.start();
4247 if (focuserAdditionalMovement == 0)
4252 if (focuserAdditionalMovement == 0)
4254 inAdjustFocus =
false;
4255 emit focusPositionAdjusted();
4260 if (adaptFocus->inAdaptiveFocus())
4262 if (focuserAdditionalMovement == 0)
4264 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4269 if (m_RestartState == RESTART_NOW && status() != Ekos::FOCUS_ABORTED)
4271 if (focuserAdditionalMovement == 0)
4273 m_RestartState = RESTART_NONE;
4275 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4276 adaptFocus->setInAdaptiveFocus(
false);
4277 focusAdvisor->setInFocusAdvisor(
false);
4278 appendLogText(
i18n(
"Restarting autofocus process..."));
4279 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4283 else if (m_RestartState == RESTART_ABORT && focuserAdditionalMovement == 0)
4289 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4290 m_RestartState = RESTART_NONE;
4291 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4292 adaptFocus->setInAdaptiveFocus(
false);
4293 focusAdvisor->setInFocusAdvisor(
false);
4299 autoFocusProcessPositionChange(newState);
4300 else if (newState == IPS_ALERT)
4301 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4308 if (nvp->isNameMatch(
"manualfocusdrive"))
4313 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4315 if (m_DebugFocuserCounter == 14)
4316 m_DebugFocuserCounter = 0;
4317 appendLogText(
i18n(
"Simulate focuser comms failure..."));
4322 m_FocusMotionTimer.stop();
4324 INumber *pos = IUFindNumber(nvp,
"manualfocusdrive");
4325 IPState newState = nvp->s;
4326 if (pos && newState == IPS_OK)
4328 if (focuserAdditionalMovement == 0)
4331 currentPosition += pos->value;
4332 absTicksLabel->setText(
QString::number(
static_cast<int>(currentPosition)));
4333 emit absolutePositionChanged(currentPosition);
4336 if (inAdjustFocus && newState == IPS_OK)
4338 if (focuserAdditionalMovement == 0)
4340 inAdjustFocus =
false;
4341 emit focusPositionAdjusted();
4346 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4348 if (focuserAdditionalMovement == 0)
4350 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4356 if (m_RestartState == RESTART_NOW && newState == IPS_OK && status() != Ekos::FOCUS_ABORTED)
4358 if (focuserAdditionalMovement == 0)
4360 m_RestartState = RESTART_NONE;
4362 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4363 adaptFocus->setInAdaptiveFocus(
false);
4364 focusAdvisor->setInFocusAdvisor(
false);
4365 appendLogText(
i18n(
"Restarting autofocus process..."));
4366 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4370 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4373 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4374 m_RestartState = RESTART_NONE;
4375 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4376 adaptFocus->setInAdaptiveFocus(
false);
4377 focusAdvisor->setInFocusAdvisor(
false);
4382 autoFocusProcessPositionChange(newState);
4383 else if (newState == IPS_ALERT)
4384 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4389 if (nvp->isNameMatch(
"REL_FOCUS_POSITION"))
4391 m_FocusMotionTimer.stop();
4393 INumber *pos = IUFindNumber(nvp,
"FOCUS_RELATIVE_POSITION");
4394 IPState newState = nvp->s;
4395 if (pos && newState == IPS_OK)
4397 if (focuserAdditionalMovement == 0)
4400 currentPosition += pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4401 qCDebug(KSTARS_EKOS_FOCUS)
4402 <<
QString(
"Rel Focuser position moved %1 by %2 to %3")
4403 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").
arg(pos->value).
arg(currentPosition);
4404 absTicksLabel->setText(
QString::number(
static_cast<int>(currentPosition)));
4405 emit absolutePositionChanged(currentPosition);
4408 if (inAdjustFocus && newState == IPS_OK)
4410 if (focuserAdditionalMovement == 0)
4412 inAdjustFocus =
false;
4413 emit focusPositionAdjusted();
4418 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4420 if (focuserAdditionalMovement == 0)
4422 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4428 if (m_RestartState == RESTART_NOW && newState == IPS_OK && status() != Ekos::FOCUS_ABORTED)
4430 if (focuserAdditionalMovement == 0)
4432 m_RestartState = RESTART_NONE;
4434 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4435 adaptFocus->setInAdaptiveFocus(
false);
4436 focusAdvisor->setInFocusAdvisor(
false);
4437 appendLogText(
i18n(
"Restarting autofocus process..."));
4438 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4442 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4445 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4446 m_RestartState = RESTART_NONE;
4447 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4448 adaptFocus->setInAdaptiveFocus(
false);
4449 focusAdvisor->setInFocusAdvisor(
false);
4454 autoFocusProcessPositionChange(newState);
4455 else if (newState == IPS_ALERT)
4456 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4464 if (nvp->isNameMatch(
"FOCUS_TIMER"))
4466 IPState newState = nvp->s;
4467 m_FocusMotionTimer.stop();
4469 if (m_RestartState == RESTART_NOW && newState == IPS_OK && status() != Ekos::FOCUS_ABORTED)
4471 if (focuserAdditionalMovement == 0)
4473 m_RestartState = RESTART_NONE;
4475 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4476 adaptFocus->setInAdaptiveFocus(
false);
4477 focusAdvisor->setInFocusAdvisor(
false);
4478 appendLogText(
i18n(
"Restarting autofocus process..."));
4479 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4483 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4486 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4487 m_RestartState = RESTART_NONE;
4488 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4489 adaptFocus->setInAdaptiveFocus(
false);
4490 focusAdvisor->setInFocusAdvisor(
false);
4494 if (canAbsMove ==
false && canRelMove ==
false)
4497 INumber *pos = IUFindNumber(nvp,
"FOCUS_TIMER_VALUE");
4500 currentPosition += pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4501 qCDebug(KSTARS_EKOS_FOCUS)
4502 <<
QString(
"Timer Focuser position moved %1 by %2 to %3")
4503 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").
arg(pos->value).
arg(currentPosition);
4506 if (pos && newState == IPS_OK && focuserAdditionalMovement == 0)
4509 if (inAdjustFocus && newState == IPS_OK)
4511 if (focuserAdditionalMovement == 0)
4513 inAdjustFocus =
false;
4514 emit focusPositionAdjusted();
4519 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4521 if (focuserAdditionalMovement == 0)
4523 adaptFocus->adaptiveFocusAdmin(
true,
true,
true);
4528 autoFocusProcessPositionChange(newState);
4530 else if (newState == IPS_ALERT)
4531 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4539 const QString logtext(m_Focuser ==
nullptr ? text :
QString(
"[%1] %2").arg(m_Focuser->getDeviceName()).
arg(text));
4540 emit newLog(logtext);
4543void Focus::appendFocusLogText(
const QString &text)
4545 if (Options::focusLogging())
4547 const QString logtext(m_Focuser ==
nullptr ? text :
QString(
"[%1] %2").arg(m_Focuser->getDeviceName()).
arg(text));
4548 emit newFocusLog(logtext);
4552void Focus::startFraming()
4554 if (m_Camera ==
nullptr)
4556 appendLogText(
i18n(
"No CCD connected."));
4560 waitStarSelectTimer.stop();
4563 starMeasureFrames.clear();
4568 setState(Ekos::FOCUS_FRAMING);
4572 appendLogText(
i18n(
"Starting continuous exposure..."));
4577void Focus::resetButtons()
4581 startFocusB->setEnabled(
false);
4582 startAbInsB->setEnabled(
false);
4583 startLoopB->setEnabled(
false);
4584 focusOutB->setEnabled(
true);
4585 focusInB->setEnabled(
true);
4586 startGotoB->setEnabled(canAbsMove);
4587 stopFocusB->setEnabled(
true);
4588 captureB->setEnabled(
false);
4589 opticalTrainCombo->setEnabled(
false);
4590 trainB->setEnabled(
false);
4604 if (disabledWidgets.empty())
4606 AFDisable(trainLabel,
false);
4607 AFDisable(opticalTrainCombo,
false);
4608 AFDisable(trainB,
false);
4609 AFDisable(focuserGroup,
true);
4610 AFDisable(clearDataB,
false);
4613 m_FocusGainAFEnabled = focusGain->isEnabled();
4614 m_FocusISOAFEnabled = focusISO->isEnabled();
4615 AFDisable(ccdGroup,
false);
4617 AFDisable(toolsGroup,
false);
4620 m_FocusSubFrameAFEnabled = m_OpsFocusSettings->focusSubFrame->isEnabled();
4623 AFDisable(m_OpsFocusSettings,
false);
4624 AFDisable(m_OpsFocusProcess,
false);
4625 AFDisable(m_OpsFocusMechanics,
false);
4626 AFDisable(focusAdvisor->focusAdvGroupBox,
false);
4627 AFDisable(m_CFZDialog,
false);
4630 stopFocusB->setEnabled(
true);
4636 for(
int i = 0 ; i < disabledWidgets.size() ; i++)
4637 disabledWidgets[i]->setEnabled(
true);
4638 disabledWidgets.clear();
4640 bool cameraConnected = m_Camera && m_Camera->isConnected();
4641 bool enableCaptureButtons = cameraConnected && (!m_captureInProgress && !m_starDetectInProgress);
4643 captureB->setEnabled(enableCaptureButtons);
4644 resetFrameB->setEnabled(enableCaptureButtons);
4645 startLoopB->setEnabled(enableCaptureButtons);
4647 if (cameraConnected)
4649 ccdGroup->setEnabled(
true);
4650 toolsGroup->setEnabled(
true);
4654 ccdGroup->setEnabled(
false);
4655 toolsGroup->setEnabled(
false);
4658 if (m_Focuser && m_Focuser->isConnected())
4660 focusOutB->setEnabled(
true);
4661 focusInB->setEnabled(
true);
4662 startFocusB->setEnabled(cameraConnected && m_FocusType == FOCUS_AUTO);
4663 startAbInsB->setEnabled(canAbInsStart());
4664 stopFocusB->setEnabled(!enableCaptureButtons);
4665 startGotoB->setEnabled(canAbsMove);
4666 stopGotoB->setEnabled(
true);
4667 focuserGroup->setEnabled(
true);
4671 focusOutB->setEnabled(
false);
4672 focusInB->setEnabled(
false);
4673 startFocusB->setEnabled(
false);
4674 startAbInsB->setEnabled(
false);
4675 stopFocusB->setEnabled(
false);
4676 startGotoB->setEnabled(
false);
4677 stopGotoB->setEnabled(
false);
4678 focuserGroup->setEnabled(
false);
4687bool Focus::canAbInsStart()
4689 return canAbsMove && m_FocusAlgorithm == FOCUS_LINEAR1PASS && m_currentImageMask == FOCUS_MASK_MOSAIC && m_CurveFit != CurveFitting::FOCUS_QUADRATIC;
4693void Focus::AFDisable(
QWidget * widget,
const bool children)
4700 if (wid->isEnabled())
4702 wid->setEnabled(
false);
4703 disabledWidgets.push_back(wid);
4712 disabledWidgets.push_back(widget);
4716bool Focus::isFocusGainEnabled()
4718 return (inAutoFocus) ? m_FocusGainAFEnabled : focusGain->isEnabled();
4721bool Focus::isFocusISOEnabled()
4723 return (inAutoFocus) ? m_FocusISOAFEnabled : focusISO->isEnabled();
4726bool Focus::isFocusSubFrameEnabled()
4728 return (inAutoFocus) ? m_FocusSubFrameAFEnabled : m_OpsFocusSettings->focusSubFrame->isEnabled();
4731void Focus::updateBoxSize(
int value)
4733 if (m_Camera ==
nullptr)
4736 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4738 if (targetChip ==
nullptr)
4741 int subBinX, subBinY;
4742 targetChip->getBinning(&subBinX, &subBinY);
4744 QRect trackBox = m_FocusView->getTrackingBox();
4748 QRect(
center.x() - value / (2 * subBinX),
center.y() - value / (2 * subBinY), value / subBinX, value / subBinY);
4750 m_FocusView->setTrackingBox(trackBox);
4753void Focus::selectFocusStarFraction(
double x,
double y)
4755 if (m_ImageData.isNull())
4758 focusStarSelected(x * m_ImageData->width(), y * m_ImageData->height());
4762 emit newImage(m_FocusView);
4766void Focus::focusStarSelected(
int x,
int y)
4768 if (state() == Ekos::FOCUS_PROGRESS)
4771 if (subFramed ==
false)
4773 rememberStarCenter.setX(x);
4774 rememberStarCenter.setY(y);
4777 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4779 int subBinX, subBinY;
4780 targetChip->getBinning(&subBinX, &subBinY);
4783 if (subBinX != (focusBinning->currentIndex() + 1))
4789 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
4793 bool squareMovedOutside =
false;
4795 if (subFramed ==
false && m_OpsFocusSettings->focusSubFrame->isChecked() && targetChip->canSubframe())
4798 if (!isStarMeasureStarBased())
4804 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
4806 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
4809 x = (x - offset) * subBinX;
4810 y = (y - offset) * subBinY;
4811 int w = offset * 2 * subBinX;
4812 int h = offset * 2 * subBinY;
4831 QVariantMap settings = frameSettings[targetChip];
4836 settings[
"binx"] = subBinX;
4837 settings[
"biny"] = subBinY;
4839 frameSettings[targetChip] = settings;
4843 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << x <<
"Y:" << y <<
"W:" << w <<
"H:" << h <<
"binX:" << subBinX <<
4846 m_FocusView->setFirstLoad(
true);
4850 if (isStarMeasureStarBased())
4852 starCenter.setX(w / (2 * subBinX));
4853 starCenter.setY(h / (2 * subBinY));
4860 double dist = sqrt((starCenter.x() - x) * (starCenter.x() - x) + (starCenter.y() - y) * (starCenter.y() - y));
4862 squareMovedOutside = (dist > (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX));
4866 starRect =
QRect(starCenter.x() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinX),
4867 starCenter.y() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinY),
4868 m_OpsFocusSettings->focusBoxSize->value() / subBinX,
4869 m_OpsFocusSettings->focusBoxSize->value() / subBinY);
4870 m_FocusView->setTrackingBox(starRect);
4875 starCenter.setZ(subBinX);
4877 if (squareMovedOutside && inAutoFocus ==
false && m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
4879 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
true);
4880 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
4881 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
false);
4882 appendLogText(
i18n(
"Disabling Auto Star Selection as star selection box was moved manually."));
4883 starSelected =
false;
4885 else if (starSelected ==
false)
4887 if (isStarMeasureStarBased())
4888 appendLogText(
i18n(
"Focus star is selected."));
4890 appendLogText(
i18n(
"Region of interest is selected."));
4892 starSelected =
true;
4896 waitStarSelectTimer.stop();
4897 FocusState nextState = inAutoFocus ? FOCUS_PROGRESS : FOCUS_IDLE;
4898 if (nextState != state())
4900 setState(nextState);
4904void Focus::checkFocus(
double requiredHFR)
4906 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
4910 str =
i18n(
"Autofocus");
4911 else if (inAdjustFocus)
4912 str =
i18n(
"Adjust Focus");
4914 str =
i18n(
"Adaptive Focus");
4916 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
4918 appendLogText(
i18n(
"Check focus request - Waiting 10sec for %1 to complete.", str));
4921 checkFocus(requiredHFR);
4926 appendLogText(
i18n(
"Discarding Check Focus request - %1 in progress.", str));
4927 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
4933 if (inFocusLoop || inBuildOffsets)
4935 QString str = inFocusLoop ?
"Focus Looping" :
" Build Offsets";
4936 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Check Focus rejected, %1 is already running.").
arg(str);
4938 else if (!isStarMeasureStarBased())
4939 appendLogText(
i18n(
"Check Focus ignored - Star Measure must be star based"));
4942 qCDebug(KSTARS_EKOS_FOCUS) <<
"Check Focus requested with minimum required HFR" << requiredHFR;
4943 minimumRequiredHFR = requiredHFR;
4944 appendLogText(
i18n(
"Capturing to check HFR..."));
4949void Focus::toggleSubframe(
bool enable)
4951 if (enable ==
false)
4954 m_FocusView->setTrackingBoxEnabled(enable);
4955 starSelected =
false;
4960 m_OpsFocusSettings->focusNoMaskRB->setChecked(
true);
4965 m_OpsFocusSettings->focusRingMaskRB->setEnabled(!enable);
4966 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(!enable);
4970 setAutoStarAndBox();
4977void Focus::setUseWeights()
4979 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC || !m_OpsFocusSettings->focusUseFullField->isChecked()
4980 || m_StarMeasure == FOCUS_STAR_NUM_STARS || m_StarMeasure == FOCUS_STAR_FOURIER_POWER ||
4981 m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
4982 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
4984 m_OpsFocusProcess->focusUseWeights->setEnabled(
false);
4985 m_OpsFocusProcess->focusUseWeights->setChecked(
false);
4988 m_OpsFocusProcess->focusUseWeights->setEnabled(
true);
4995void Focus::setDenoise()
4997 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
4998 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
4999 m_OpsFocusProcess->focusDenoise->setEnabled(
true);
5002 m_OpsFocusProcess->focusDenoise->setEnabled(
false);
5003 m_OpsFocusProcess->focusDenoise->setChecked(
false);
5012void Focus::setDonutBuster()
5014 if (m_FocusAlgorithm != FOCUS_LINEAR1PASS)
5016 m_OpsFocusProcess->focusDonut->hide();
5017 m_OpsFocusProcess->focusDonut->setEnabled(
false);
5018 m_OpsFocusProcess->focusDonut->setChecked(
false);
5022 m_OpsFocusProcess->focusDonut->show();
5023 if ((m_StarMeasure == FOCUS_STAR_HFR || m_StarMeasure == FOCUS_STAR_HFR_ADJ || m_StarMeasure == FOCUS_STAR_FWHM) &&
5024 (m_FocusWalk == FOCUS_WALK_FIXED_STEPS || m_FocusWalk == FOCUS_WALK_CFZ_SHUFFLE) &&
5025 (m_CurveFit != CurveFitting::FOCUS_QUADRATIC))
5026 m_OpsFocusProcess->focusDonut->setEnabled(
true);
5029 m_OpsFocusProcess->focusDonut->setEnabled(
false);
5030 m_OpsFocusProcess->focusDonut->setChecked(
false);
5035void Focus::setExposure(
double value)
5037 focusExposure->setValue(value);
5040void Focus::setBinning(
int subBinX,
int subBinY)
5042 INDI_UNUSED(subBinY);
5043 focusBinning->setCurrentIndex(subBinX - 1);
5046void Focus::setAutoStarEnabled(
bool enable)
5048 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(enable);
5051void Focus::setAutoSubFrameEnabled(
bool enable)
5053 m_OpsFocusSettings->focusSubFrame->setChecked(enable);
5056void Focus::setAutoFocusParameters(
int boxSize,
int stepSize,
int maxTravel,
double tolerance)
5058 m_OpsFocusSettings->focusBoxSize->setValue(boxSize);
5059 m_OpsFocusMechanics->focusTicks->setValue(stepSize);
5060 m_OpsFocusMechanics->focusMaxTravel->setValue(maxTravel);
5061 m_OpsFocusProcess->focusTolerance->setValue(tolerance);
5064void Focus::checkAutoStarTimeout()
5067 if (starCenter.isNull() && (inAutoFocus || minimumRequiredHFR > 0))
5071 if (rememberStarCenter.isNull() ==
false)
5073 focusStarSelected(rememberStarCenter.x(), rememberStarCenter.y());
5074 appendLogText(
i18n(
"No star was selected. Using last known position..."));
5079 initialFocuserAbsPosition = -1;
5080 appendLogText(
i18n(
"No star was selected. Aborting..."));
5081 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
5083 else if (state() == FOCUS_WAITING)
5084 setState(FOCUS_IDLE);
5087void Focus::setAbsoluteFocusTicks()
5089 if (absTicksSpin->value() == currentPosition)
5091 appendLogText(
i18n(
"Focuser already at %1...", currentPosition));
5094 focusInB->setEnabled(
false);
5095 focusOutB->setEnabled(
false);
5096 startGotoB->setEnabled(
false);
5097 if (!changeFocus(absTicksSpin->value() - currentPosition))
5098 qCDebug(KSTARS_EKOS_FOCUS) <<
"setAbsoluteFocusTicks unable to move focuser.";
5101void Focus::syncTrackingBoxPosition()
5103 if (m_OpsFocusSettings->focusUseFullField->isChecked() || starCenter.isNull())
5106 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5107 Q_ASSERT(targetChip);
5109 int subBinX = 1, subBinY = 1;
5110 targetChip->getBinning(&subBinX, &subBinY);
5112 double boxSize = m_OpsFocusSettings->focusBoxSize->value();
5114 targetChip->getFrame(&x, &y, &w, &h);
5116 if (boxSize / subBinX >= w || boxSize / subBinY >= h)
5118 m_OpsFocusSettings->focusBoxSize->setValue((boxSize / subBinX >= w) ? w : h);
5123 if (subBinX != starCenter.z())
5125 if (starCenter.z() > 0)
5127 starCenter.setX(starCenter.x() * (starCenter.z() / subBinX));
5128 starCenter.setY(starCenter.y() * (starCenter.z() / subBinY));
5131 starCenter.setZ(subBinX);
5135 if (isStarMeasureStarBased())
5136 starRect =
QRect(starCenter.x() - boxSize / (2 * subBinX), starCenter.y() - boxSize / (2 * subBinY),
5137 boxSize / subBinX, boxSize / subBinY);
5141 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
5142 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
5143 int boxTLX = starCenter.x() - boxSize / (2 * subBinX);
5144 boxTLX = std::max(boxTLX, minX);
5145 int boxTLY = starCenter.y() - boxSize / (2 * subBinY);
5146 boxTLY = std::max(boxTLY, minY);
5147 const int boxBRX = boxTLX + (boxSize / subBinX);
5149 boxTLX -= boxBRX - maxX;
5150 const int boxBRY = boxTLY + (boxSize / subBinY);
5152 boxTLY -= boxBRY - maxY;
5154 starRect =
QRect(boxTLX, boxTLY, boxSize / subBinX, boxSize / subBinY);
5156 m_FocusView->setTrackingBoxEnabled(
true);
5157 m_FocusView->setTrackingBox(starRect);
5160void Focus::showFITSViewer()
5162 static int lastFVTabID = -1;
5169 fv->loadData(m_ImageData, url, &lastFVTabID);
5170 connect(fv.get(), &FITSViewer::terminated,
this, [
this]()
5175 else if (fv->updateData(m_ImageData, url, lastFVTabID, &lastFVTabID) ==
false)
5176 fv->loadData(m_ImageData, url, &lastFVTabID);
5182void Focus::adjustFocusOffset(
int value,
bool useAbsoluteOffset)
5185 if (inAdjustFocus || adaptFocus->inAdaptiveFocus())
5187 QString str = inAdjustFocus ?
i18n(
"Adjust Focus") :
i18n(
"Adaptive Focus");
5188 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
5190 appendLogText(
i18n(
"Adjust focus request - Waiting 10sec for %1 to complete.", str));
5193 adjustFocusOffset(value, useAbsoluteOffset);
5198 qCDebug(KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset called whilst" << str <<
"in progress. Ignoring...";
5199 emit focusPositionAdjusted();
5204 inAdjustFocus =
true;
5207 int newPosition = (useAbsoluteOffset) ? value : value + currentPosition;
5209 if (!changeFocus(newPosition - currentPosition))
5210 qCDebug(KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset unable to move focuser";
5213void Focus::toggleFocusingWidgetFullScreen()
5215 if (focusingWidget->parent() ==
nullptr)
5217 focusingWidget->setParent(
this);
5218 rightLayout->insertWidget(0, focusingWidget);
5219 focusingWidget->showNormal();
5223 focusingWidget->setParent(
nullptr);
5224 focusingWidget->setWindowTitle(
i18nc(
"@title:window",
"Focus Frame"));
5226 focusingWidget->showMaximized();
5227 focusingWidget->show();
5231void Focus::setMountStatus(ISD::Mount::Status newState)
5235 case ISD::Mount::MOUNT_PARKING:
5236 case ISD::Mount::MOUNT_SLEWING:
5237 case ISD::Mount::MOUNT_MOVING:
5238 captureB->setEnabled(
false);
5239 startFocusB->setEnabled(
false);
5240 startAbInsB->setEnabled(
false);
5241 startLoopB->setEnabled(
false);
5256void Focus::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
5265 auto name = deviceRemoved->getDeviceName();
5269 if (m_Focuser && m_Focuser->getDeviceName() == name)
5271 m_Focuser->disconnect(
this);
5272 m_Focuser =
nullptr;
5281 for (
auto &oneSource : m_TemperatureSources)
5283 if (oneSource->getDeviceName() == name)
5286 if (m_LastSourceDeviceAutofocusTemperature && m_LastSourceDeviceAutofocusTemperature->getDeviceName() == name)
5287 m_LastSourceDeviceAutofocusTemperature.reset(
nullptr);
5289 m_TemperatureSources.removeAll(oneSource);
5292 defaultFocusTemperatureSource->removeItem(defaultFocusTemperatureSource->findText(name));
5299 if (m_Camera && m_Camera->getDeviceName() == name)
5301 m_Camera->disconnect(
this);
5312 if (m_FilterWheel && m_FilterWheel->getDeviceName() == name)
5314 m_FilterWheel->disconnect(
this);
5315 m_FilterWheel =
nullptr;
5325void Focus::setupFilterManager()
5328 if (m_FilterManager)
5329 m_FilterManager->disconnect(
this);
5332 Ekos::Manager::Instance()->createFilterManager(m_FilterWheel);
5335 Ekos::Manager::Instance()->getFilterManager(m_FilterWheel->getDeviceName(), m_FilterManager);
5340 connect(
this, &Focus::absolutePositionChanged, m_FilterManager.get(), &FilterManager::setFocusAbsolutePosition);
5343 connect(
this, &Focus::newStatus,
this, [
this](Ekos::FocusState state)
5345 if (m_FilterManager)
5347 m_FilterManager->setFocusStatus(state);
5348 if (focusFilter->currentIndex() != -1 && canAbsMove && state == Ekos::FOCUS_COMPLETE)
5350 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
5351 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
5359 connect(m_FilterManager.get(), &FilterManager::newStatus,
this, [
this](Ekos::FilterState filterState)
5362 if (filterState == FILTER_OFFSET && state() != Ekos::FOCUS_PROGRESS)
5364 if (m_GuidingSuspended == false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
5366 m_GuidingSuspended = true;
5367 emit suspendGuiding();
5373 connect(m_FilterManager.get(), &FilterManager::ready,
this, [
this]()
5376 if (focusFilter->currentIndex() != currentFilterPosition - 1)
5377 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5379 if (filterPositionPending)
5381 filterPositionPending = false;
5384 else if (fallbackFilterPending)
5386 fallbackFilterPending =
false;
5387 setState(m_pendingState);
5388 m_pendingState = FOCUS_IDLE;
5393 connect(m_FilterManager.get(), &FilterManager::failed,
this, [
this]()
5395 if (filterPositionPending)
5397 appendLogText(i18n(
"Filter operation failed."));
5398 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FILTER_MANAGER);
5403 connect(m_FilterManager.get(), &FilterManager::runAutoFocus,
this, &Focus::runAutoFocus);
5406 connect(m_FilterManager.get(), &FilterManager::abortAutoFocus,
this, &Focus::abort);
5409 connect(m_FilterManager.get(), &FilterManager::newFocusOffset,
this, &Focus::adjustFocusOffset);
5412 connect(m_FilterManager.get(), &FilterManager::labelsChanged,
this, [
this]()
5414 focusFilter->clear();
5415 focusFilter->addItems(m_FilterManager->getFilterLabels());
5416 currentFilterPosition = m_FilterManager->getFilterPosition();
5417 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5421 connect(m_FilterManager.get(), &FilterManager::positionChanged,
this, [
this]()
5423 currentFilterPosition = m_FilterManager->getFilterPosition();
5424 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5428 connect(m_FilterManager.get(), &FilterManager::exposureChanged,
this, [
this]()
5430 focusExposure->setValue(m_FilterManager->getFilterExposure());
5434 connect(m_FilterManager.get(), &FilterManager::wavelengthChanged,
this, [
this]()
5436 wavelengthChanged();
5440void Focus::connectFilterManager()
5445 if (m_FilterManager)
5447 m_FilterManager->refreshFilterModel();
5448 m_FilterManager->show();
5449 m_FilterManager->raise();
5454 connect(
this, &Focus::focusPositionAdjusted,
this, [
this]()
5456 if (m_FilterManager)
5457 m_FilterManager->setFocusOffsetComplete();
5458 if (m_GuidingSuspended && state() != Ekos::FOCUS_PROGRESS)
5460 QTimer::singleShot(m_OpsFocusMechanics->focusSettleTime->value() * 1000,
this, [
this]()
5462 m_GuidingSuspended = false;
5463 emit resumeGuiding();
5472 if (inAutoFocus && m_OpsFocusProcess->focusDonut->isEnabled())
5475 if (m_FilterManager)
5476 m_FilterManager->setFilterExposure(focusFilter->currentIndex(), focusExposure->value());
5482 if (m_FilterManager)
5484 focusExposure->setValue(m_FilterManager->getFilterExposure(text));
5492void Focus::toggleVideo(
bool enabled)
5494 if (m_Camera ==
nullptr)
5497 if (m_Camera->isBLOBEnabled() ==
false)
5500 if (Options::guiderType() != Ekos::Guide::GUIDE_INTERNAL)
5501 m_Camera->setBLOBEnabled(
true);
5508 m_Camera->setVideoStreamEnabled(enabled);
5510 KSMessageBox::Instance()->questionYesNo(
i18n(
"Image transfer is disabled for this camera. Would you like to enable it?"));
5514 m_Camera->setVideoStreamEnabled(enabled);
5530void Focus::setVideoStreamEnabled(
bool enabled)
5534 liveVideoB->setChecked(
true);
5539 liveVideoB->setChecked(
false);
5544void Focus::processCaptureTimeout()
5546 m_captureInProgress =
false;
5548 if (m_abortInProgress)
5551 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame in " << __FUNCTION__;
5555 captureTimeoutCounter++;
5557 if (captureTimeoutCounter >= 3)
5559 captureTimeoutCounter = 0;
5560 m_MissingCameraCounter = 0;
5561 captureTimeout.stop();
5562 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5563 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5567 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
5568 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5569 targetChip->abortExposure();
5571 capture(focusExposure->value());
5575 else if (m_MissingCameraCounter < 40)
5577 m_MissingCameraCounter++;
5578 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to restart focus exposure as camera is missing, trying again in 5 seconds...";
5583 m_MissingCameraCounter = 0;
5584 captureTimeoutCounter = 0;
5585 captureTimeout.stop();
5586 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5587 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5592void Focus::processCaptureErrorDefault()
5594 processCaptureError(ISD::Camera::ERROR_CAPTURE);
5599 m_captureInProgress =
false;
5600 captureTimeout.stop();
5602 if (m_abortInProgress)
5604 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame in " << __FUNCTION__;
5610 appendLogText(
i18n(
"Failed to save image. Aborting..."));
5611 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5618 captureFailureCounter++;
5620 if (captureFailureCounter >= 3)
5622 captureFailureCounter = 0;
5623 captureTimeoutCounter = 0;
5624 m_MissingCameraCounter = 0;
5625 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5626 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5630 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5631 targetChip->abortExposure();
5632 capture(focusExposure->value());
5636 else if (m_MissingCameraCounter < 40)
5638 m_MissingCameraCounter++;
5639 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to restart focus exposure as camera is missing, trying again in 5 seconds...";
5646 m_MissingCameraCounter = 0;
5647 captureFailureCounter = 0;
5648 captureTimeoutCounter = 0;
5649 captureTimeout.stop();
5650 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5651 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5655void Focus::syncSettings()
5668 if ( (dsb = qobject_cast<QDoubleSpinBox*>(sender())))
5671 value = dsb->
value();
5674 else if ( (sb = qobject_cast<QSpinBox*>(sender())))
5677 value = sb->
value();
5679 else if ( (cb = qobject_cast<QCheckBox*>(sender())))
5684 else if ( (gb = qobject_cast<QGroupBox*>(sender())))
5689 else if ( (rb = qobject_cast<QRadioButton*>(sender())))
5695 m_Settings.remove(key);
5700 else if ( (cbox = qobject_cast<QComboBox*>(sender())))
5705 else if ( (s = qobject_cast<QSplitter*>(sender())))
5713 Options::self()->setProperty(key.
toLatin1(), value);
5715 m_Settings[key] = value;
5716 m_GlobalSettings[key] = value;
5720 m_DebounceTimer.start();
5726void Focus::settleSettings()
5728 emit settingsUpdated(getAllSettings());
5730 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
5731 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
5734void Focus::loadGlobalSettings()
5739 QVariantMap settings;
5741 for (
auto &oneWidget : findChildren<QComboBox*>())
5743 if (oneWidget->objectName() ==
"opticalTrainCombo")
5746 key = oneWidget->objectName();
5747 value = Options::self()->property(key.
toLatin1());
5748 if (value.
isValid() && oneWidget->count() > 0)
5750 oneWidget->setCurrentText(value.
toString());
5751 settings[key] = value;
5754 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5758 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5760 key = oneWidget->objectName();
5761 value = Options::self()->property(key.
toLatin1());
5764 oneWidget->setValue(value.
toDouble());
5765 settings[key] = value;
5768 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5772 for (
auto &oneWidget : findChildren<QSpinBox*>())
5774 key = oneWidget->objectName();
5775 value = Options::self()->property(key.
toLatin1());
5778 oneWidget->setValue(value.
toInt());
5779 settings[key] = value;
5782 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5786 for (
auto &oneWidget : findChildren<QCheckBox*>())
5788 key = oneWidget->objectName();
5789 value = Options::self()->property(key.
toLatin1());
5792 oneWidget->setChecked(value.
toBool());
5793 settings[key] = value;
5795 else if (key != forceInSeqAF->objectName())
5796 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5800 for (
auto &oneWidget : findChildren<QGroupBox*>())
5802 if (oneWidget->isCheckable())
5804 key = oneWidget->objectName();
5805 value = Options::self()->property(key.
toLatin1());
5808 oneWidget->setChecked(value.
toBool());
5809 settings[key] = value;
5812 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5817 for (
auto &oneWidget : findChildren<QSplitter*>())
5819 key = oneWidget->objectName();
5820 value = Options::self()->property(key.
toLatin1());
5825 oneWidget->restoreState(valueBA);
5826 settings[key] = valueBA;
5829 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5833 for (
auto &oneWidget : findChildren<QRadioButton*>())
5835 key = oneWidget->objectName();
5836 value = Options::self()->property(key.
toLatin1());
5839 oneWidget->setChecked(value.
toBool());
5840 settings[key] = value;
5845 m_GlobalSettings = m_Settings = settings;
5848void Focus::checkMosaicMaskLimits()
5850 if (m_Camera ==
nullptr || m_Camera->isConnected() ==
false)
5852 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5853 if (targetChip ==
nullptr || frameSettings.contains(targetChip) ==
false)
5855 auto settings = frameSettings[targetChip];
5858 auto width = settings[
"w"].toInt();
5859 auto height = settings[
"h"].toInt();
5860 if (width == 0 || height == 0)
5864 auto min = std::min(width, height);
5866 m_OpsFocusSettings->focusMosaicTileWidth->setMaximum(100 * min / (3 * width));
5869void Focus::connectSyncSettings()
5872 for (
auto &oneWidget : findChildren<QComboBox*>())
5874 if (oneWidget != opticalTrainCombo)
5878 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5882 for (
auto &oneWidget : findChildren<QSpinBox*>())
5886 for (
auto &oneWidget : findChildren<QCheckBox*>())
5890 for (
auto &oneWidget : findChildren<QGroupBox*>())
5891 if (oneWidget->isCheckable())
5895 for (
auto &oneWidget : findChildren<QSplitter*>())
5899 for (
auto &oneWidget : findChildren<QRadioButton*>())
5903void Focus::disconnectSyncSettings()
5906 for (
auto &oneWidget : findChildren<QComboBox*>())
5907 disconnect(oneWidget, QOverload<int>::of(&
QComboBox::activated),
this, &Ekos::Focus::syncSettings);
5910 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5914 for (
auto &oneWidget : findChildren<QSpinBox*>())
5918 for (
auto &oneWidget : findChildren<QCheckBox*>())
5922 for (
auto &oneWidget : findChildren<QGroupBox*>())
5923 if (oneWidget->isCheckable())
5927 for (
auto &oneWidget : findChildren<QSplitter*>())
5931 for (
auto &oneWidget : findChildren<QRadioButton*>())
5935void Focus::initPlots()
5939 profileDialog =
new QDialog(
this);
5942 profileDialog->setWindowTitle(
i18nc(
"@title:window",
"Relative Profile"));
5943 profilePlot =
new FocusProfilePlot(profileDialog);
5946 profileDialog->setLayout(profileLayout);
5947 profileDialog->resize(400, 300);
5950 connect(
this, &Ekos::Focus::newHFR, [
this](
double currentHFR,
int pos)
5952 Q_UNUSED(pos) profilePlot->drawProfilePlot(currentHFR);
5956void Focus::initConnections()
5959 waitStarSelectTimer.setInterval(AUTO_STAR_TIMEOUT);
5964 m_DebounceTimer.setInterval(500);
5965 m_DebounceTimer.setSingleShot(
true);
5980 captureTimer.setSingleShot(
true);
5987 captureTimeout.setSingleShot(
true);
6022 &Ekos::Focus::updateBoxSize);
6028 m_CFZDialog->show();
6029 m_CFZDialog->raise();
6035 focusAdvisor->setButtons(
false);
6036 focusAdvisor->show();
6037 focusAdvisor->raise();
6043 emit inSequenceAF(enabled, opticalTrain());
6049 setFocusDetection(static_cast<StarAlgorithm>(index));
6055 setFocusAlgorithm(static_cast<Algorithm>(index));
6061 this, [&](
int index)
6063 setCurveFit(static_cast<CurveFitting::CurveFit>(index));
6068 this, [&](
int index)
6070 setStarMeasure(static_cast<StarMeasure>(index));
6075 this, [&](
int index)
6077 setStarPSF(static_cast<StarPSF>(index));
6082 this, [&](
int index)
6084 setStarUnits(static_cast<StarUnits>(index));
6089 this, [&](
int index)
6091 setWalk(static_cast<FocusWalk>(index));
6102 starCenter = QVector3D();
6103 starSelected = false;
6104 m_FocusView->setTrackingBox(QRect());
6112 &Ekos::Focus::calcCFZ);
6115 &Ekos::Focus::calcCFZ);
6156void Focus::setFocusDetection(StarAlgorithm starAlgorithm)
6158 static bool first =
true;
6159 if (!first && m_FocusDetection == starAlgorithm)
6164 m_FocusDetection = starAlgorithm;
6167 setFocusAlgorithm(m_FocusAlgorithm);
6168 setAutoStarAndBox();
6176void Focus::setAutoStarAndBox()
6178 if (m_FocusDetection == ALGORITHM_BAHTINOV)
6180 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6181 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6182 m_OpsFocusSettings->focusBoxSize->setEnabled(m_OpsFocusSettings->focusSubFrame->isChecked());
6183 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(m_OpsFocusSettings->focusSubFrame->isChecked());
6184 m_OpsFocusSettings->focusBoxSize->setMaximum(512);
6185 if (m_OpsFocusSettings->focusBoxSize->value() > 512)
6186 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
6188 else if(m_OpsFocusSettings->focusSubFrame->isChecked())
6190 if(isStarMeasureStarBased())
6192 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
true);
6194 m_OpsFocusSettings->focusBoxSize->setEnabled(
true);
6195 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
true);
6196 if (m_OpsFocusSettings->focusBoxSize->value() > 256)
6197 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
6198 m_OpsFocusSettings->focusBoxSize->setMaximum(256);
6202 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6203 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6206 m_OpsFocusSettings->focusBoxSize->setEnabled(
true);
6207 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
true);
6208 int maxSize = std::min(m_CcdWidth, m_CcdHeight);
6209 int step = m_OpsFocusSettings->focusBoxSize->singleStep();
6210 maxSize = std::max(256, (maxSize / step) * step);
6211 m_OpsFocusSettings->focusBoxSize->setMaximum(maxSize);
6217 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6218 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6219 m_OpsFocusSettings->focusBoxSize->setEnabled(
false);
6220 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
false);
6225void Focus::setFocusAlgorithm(Algorithm algorithm)
6227 m_FocusAlgorithm = algorithm;
6230 case FOCUS_ITERATIVE:
6232 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6233 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6234 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6235 m_OpsFocusProcess->focusMultiRowAverage->hide();
6237 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6238 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6239 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6240 m_OpsFocusProcess->focusGaussianSigma->hide();
6242 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6243 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6244 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6245 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6247 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasureLabel);
6248 m_OpsFocusProcess->focusStarMeasureLabel->hide();
6249 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasure);
6250 m_OpsFocusProcess->focusStarMeasure->hide();
6252 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6253 m_OpsFocusProcess->focusStarPSFLabel->hide();
6254 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6255 m_OpsFocusProcess->focusStarPSF->hide();
6257 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6258 m_OpsFocusProcess->focusUseWeights->hide();
6260 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6261 m_OpsFocusProcess->focusR2LimitLabel->hide();
6262 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6263 m_OpsFocusProcess->focusR2Limit->hide();
6265 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6266 m_OpsFocusProcess->focusRefineCurveFit->hide();
6267 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6269 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6270 m_OpsFocusProcess->focusToleranceLabel->hide();
6271 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6272 m_OpsFocusProcess->focusTolerance->hide();
6274 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6275 m_OpsFocusProcess->focusThresholdLabel->hide();
6276 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6277 m_OpsFocusProcess->focusThreshold->hide();
6279 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFitLabel);
6280 m_OpsFocusProcess->focusCurveFitLabel->hide();
6281 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFit);
6282 m_OpsFocusProcess->focusCurveFit->hide();
6284 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6285 m_OpsFocusProcess->focusDenoise->hide();
6288 m_OpsFocusProcess->focusDonut->hide();
6289 m_OpsFocusProcess->focusDonut->setChecked(
false);
6292 m_OpsFocusProcess->focusScanStartPos->hide();
6293 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6296 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6299 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6301 m_OpsFocusProcess->focusStarMeasure->clear();
6302 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6303 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6307 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6308 m_OpsFocusProcess->focusToleranceLabel->show();
6309 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6310 m_OpsFocusProcess->focusTolerance->show();
6312 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6313 m_OpsFocusProcess->focusFramesCountLabel->show();
6314 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6315 m_OpsFocusProcess->focusFramesCount->show();
6317 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6318 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6319 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6320 m_OpsFocusProcess->focusHFRFramesCount->show();
6322 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6324 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6325 m_OpsFocusProcess->focusThresholdLabel->show();
6326 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6327 m_OpsFocusProcess->focusThreshold->show();
6329 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6331 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6332 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6333 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6334 m_OpsFocusProcess->focusMultiRowAverage->show();
6336 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6337 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6338 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6339 m_OpsFocusProcess->focusGaussianSigma->show();
6341 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6342 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6343 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6344 m_OpsFocusProcess->focusGaussianKernelSize->show();
6348 startAbInsB->setEnabled(canAbInsStart());
6352 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6353 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6354 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6357 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6358 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6361 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6363 m_OpsFocusMechanics->focusWalk->clear();
6364 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6365 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6369 case FOCUS_POLYNOMIAL:
6371 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6372 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6373 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6374 m_OpsFocusProcess->focusMultiRowAverage->hide();
6376 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6377 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6378 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6379 m_OpsFocusProcess->focusGaussianSigma->hide();
6381 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6382 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6383 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6384 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6386 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6387 m_OpsFocusProcess->focusStarPSFLabel->hide();
6388 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6389 m_OpsFocusProcess->focusStarPSF->hide();
6391 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6392 m_OpsFocusProcess->focusUseWeights->hide();
6394 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6395 m_OpsFocusProcess->focusR2LimitLabel->hide();
6396 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6397 m_OpsFocusProcess->focusR2Limit->hide();
6399 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6400 m_OpsFocusProcess->focusRefineCurveFit->hide();
6401 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6403 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6404 m_OpsFocusProcess->focusToleranceLabel->hide();
6405 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6406 m_OpsFocusProcess->focusTolerance->hide();
6408 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6409 m_OpsFocusProcess->focusThresholdLabel->hide();
6410 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6411 m_OpsFocusProcess->focusThreshold->hide();
6413 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6414 m_OpsFocusProcess->focusDenoise->hide();
6417 m_OpsFocusProcess->focusDonut->hide();
6418 m_OpsFocusProcess->focusDonut->setChecked(
false);
6421 m_OpsFocusProcess->focusScanStartPos->hide();
6422 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6425 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6427 m_OpsFocusProcess->focusStarMeasure->clear();
6428 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6429 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6434 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6435 m_OpsFocusProcess->focusCurveFitLabel->show();
6436 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6437 m_OpsFocusProcess->focusCurveFit->show();
6438 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6440 m_OpsFocusProcess->focusCurveFit->clear();
6441 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6442 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6445 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6446 m_OpsFocusProcess->focusToleranceLabel->show();
6447 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6448 m_OpsFocusProcess->focusTolerance->show();
6450 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6451 m_OpsFocusProcess->focusFramesCountLabel->show();
6452 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6453 m_OpsFocusProcess->focusFramesCount->show();
6455 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6456 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6457 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6458 m_OpsFocusProcess->focusHFRFramesCount->show();
6460 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6462 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6463 m_OpsFocusProcess->focusThresholdLabel->show();
6464 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6465 m_OpsFocusProcess->focusThreshold->show();
6467 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6469 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6470 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6471 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6472 m_OpsFocusProcess->focusMultiRowAverage->show();
6474 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6475 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6476 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6477 m_OpsFocusProcess->focusGaussianSigma->show();
6479 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6480 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6481 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6482 m_OpsFocusProcess->focusGaussianKernelSize->show();
6486 startAbInsB->setEnabled(canAbInsStart());
6490 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6491 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6492 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6495 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6496 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6499 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6501 m_OpsFocusMechanics->focusWalk->clear();
6502 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6503 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6509 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6510 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6511 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6512 m_OpsFocusProcess->focusMultiRowAverage->hide();
6514 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6515 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6516 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6517 m_OpsFocusProcess->focusGaussianSigma->hide();
6519 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6520 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6521 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6522 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6524 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6525 m_OpsFocusProcess->focusThresholdLabel->hide();
6526 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6527 m_OpsFocusProcess->focusThreshold->hide();
6529 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6530 m_OpsFocusProcess->focusStarPSFLabel->hide();
6531 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6532 m_OpsFocusProcess->focusStarPSF->hide();
6534 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6535 m_OpsFocusProcess->focusUseWeights->hide();
6537 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6538 m_OpsFocusProcess->focusR2LimitLabel->hide();
6539 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6540 m_OpsFocusProcess->focusR2Limit->hide();
6542 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6543 m_OpsFocusProcess->focusRefineCurveFit->hide();
6544 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6546 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6547 m_OpsFocusProcess->focusDenoise->hide();
6550 m_OpsFocusProcess->focusDonut->hide();
6551 m_OpsFocusProcess->focusDonut->setChecked(
false);
6554 m_OpsFocusProcess->focusScanStartPos->hide();
6555 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6558 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6560 m_OpsFocusProcess->focusStarMeasure->clear();
6561 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6562 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6567 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6568 m_OpsFocusProcess->focusCurveFitLabel->show();
6569 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6570 m_OpsFocusProcess->focusCurveFit->show();
6571 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6573 m_OpsFocusProcess->focusCurveFit->clear();
6574 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6575 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6578 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6579 m_OpsFocusProcess->focusToleranceLabel->show();
6580 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6581 m_OpsFocusProcess->focusTolerance->show();
6583 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6584 m_OpsFocusProcess->focusFramesCountLabel->show();
6585 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6586 m_OpsFocusProcess->focusFramesCount->show();
6588 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6589 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6590 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6591 m_OpsFocusProcess->focusHFRFramesCount->show();
6593 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6595 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6596 m_OpsFocusProcess->focusThresholdLabel->show();
6597 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6598 m_OpsFocusProcess->focusThreshold->show();
6600 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6602 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6603 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6604 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6605 m_OpsFocusProcess->focusMultiRowAverage->show();
6607 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6608 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6609 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6610 m_OpsFocusProcess->focusGaussianSigma->show();
6612 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6613 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6614 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6615 m_OpsFocusProcess->focusGaussianKernelSize->show();
6619 startAbInsB->setEnabled(canAbInsStart());
6623 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6624 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6625 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6628 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6629 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6632 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6634 m_OpsFocusMechanics->focusWalk->clear();
6635 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6636 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6640 case FOCUS_LINEAR1PASS:
6642 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6643 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6644 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6645 m_OpsFocusProcess->focusMultiRowAverage->hide();
6647 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6648 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6649 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6650 m_OpsFocusProcess->focusGaussianSigma->hide();
6652 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6653 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6654 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6655 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6657 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6658 m_OpsFocusProcess->focusThresholdLabel->hide();
6659 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6660 m_OpsFocusProcess->focusThreshold->hide();
6662 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6663 m_OpsFocusProcess->focusToleranceLabel->hide();
6664 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6665 m_OpsFocusProcess->focusTolerance->hide();
6669 if (m_FocusDetection == ALGORITHM_SEP && m_CurveFit != CurveFitting::FOCUS_QUADRATIC)
6671 if (m_OpsFocusProcess->focusStarMeasure->count() != m_StarMeasureText.count())
6673 m_OpsFocusProcess->focusStarMeasure->clear();
6674 m_OpsFocusProcess->focusStarMeasure->addItems(m_StarMeasureText);
6675 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6679#if !defined(HAVE_OPENCV)
6687 else if (m_FocusDetection != ALGORITHM_SEP || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6689 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6691 m_OpsFocusProcess->focusStarMeasure->clear();
6692 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6693 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6699 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6700 m_OpsFocusProcess->focusCurveFitLabel->show();
6701 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6702 m_OpsFocusProcess->focusCurveFit->show();
6703 if (m_OpsFocusProcess->focusCurveFit->count() != m_CurveFitText.count())
6705 m_OpsFocusProcess->focusCurveFit->clear();
6706 m_OpsFocusProcess->focusCurveFit->addItems(m_CurveFitText);
6707 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_HYPERBOLA);
6710 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
6711 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
6713 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6714 m_OpsFocusProcess->focusUseWeights->hide();
6715 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusDenoise, 3, 0, 1, 2);
6716 m_OpsFocusProcess->focusDenoise->show();
6720 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6721 m_OpsFocusProcess->focusDenoise->hide();
6722 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusUseWeights, 3, 0, 1, 2);
6723 m_OpsFocusProcess->focusUseWeights->show();
6726 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2LimitLabel, 3, 2);
6727 m_OpsFocusProcess->focusR2LimitLabel->show();
6728 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2Limit, 3, 3);
6729 m_OpsFocusProcess->focusR2Limit->show();
6731 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusRefineCurveFit, 4, 0, 1, 2);
6732 m_OpsFocusProcess->focusRefineCurveFit->show();
6734 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 4, 2);
6735 m_OpsFocusProcess->focusFramesCountLabel->show();
6736 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 4, 3);
6737 m_OpsFocusProcess->focusFramesCount->show();
6739 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 5, 2);
6740 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6741 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 5, 3);
6742 m_OpsFocusProcess->focusHFRFramesCount->show();
6744 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6746 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 6, 0);
6747 m_OpsFocusProcess->focusThresholdLabel->show();
6748 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 6, 1);
6749 m_OpsFocusProcess->focusThreshold->show();
6751 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6753 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 6, 0);
6754 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6755 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 6, 1);
6756 m_OpsFocusProcess->focusMultiRowAverage->show();
6758 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 6, 2);
6759 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6760 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 6, 3);
6761 m_OpsFocusProcess->focusGaussianSigma->show();
6763 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 7, 0);
6764 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6765 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 7, 1);
6766 m_OpsFocusProcess->focusGaussianKernelSize->show();
6770 m_OpsFocusProcess->focusDonut->show();
6771 m_OpsFocusProcess->focusDonut->setEnabled(
true);
6774 m_OpsFocusProcess->focusScanStartPos->show();
6775 m_OpsFocusProcess->focusScanStartPos->setEnabled(
true);
6778 startAbInsB->setEnabled(canAbInsStart());
6782 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(canAbsMove);
6786 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6787 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6790 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6792 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6794 m_OpsFocusMechanics->focusWalk->clear();
6795 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6796 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6801 if (m_OpsFocusMechanics->focusWalk->count() != m_FocusWalkText.count())
6803 m_OpsFocusMechanics->focusWalk->clear();
6804 m_OpsFocusMechanics->focusWalk->addItems(m_FocusWalkText);
6805 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6812void Focus::setCurveFit(CurveFitting::CurveFit curve)
6814 if (m_OpsFocusProcess->focusCurveFit->currentIndex() == -1)
6817 static bool first =
true;
6818 if (!first && m_CurveFit == curve)
6824 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
6831 case CurveFitting::FOCUS_QUADRATIC:
6832 m_OpsFocusProcess->focusR2Limit->setEnabled(
false);
6833 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6834 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
false);
6837 case CurveFitting::FOCUS_HYPERBOLA:
6838 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6839 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6842 case CurveFitting::FOCUS_PARABOLA:
6843 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6844 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6847 case CurveFitting::FOCUS_2DGAUSSIAN:
6848 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6849 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6857void Focus::setStarMeasure(StarMeasure starMeasure)
6859 if (m_OpsFocusProcess->focusStarMeasure->currentIndex() == -1)
6862 static bool first =
true;
6863 if (!first && m_StarMeasure == starMeasure)
6868 m_StarMeasure = starMeasure;
6869 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
6873 setAutoStarAndBox();
6879 switch(m_StarMeasure)
6881 case FOCUS_STAR_HFR:
6882 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6883 m_FocusView->setStarsHFREnabled(
true);
6886 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6887 m_OpsFocusProcess->focusStarPSFLabel->hide();
6888 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6889 m_OpsFocusProcess->focusStarPSF->hide();
6892 case FOCUS_STAR_HFR_ADJ:
6893 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6894 m_FocusView->setStarsHFREnabled(
false);
6897 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6898 m_OpsFocusProcess->focusStarPSFLabel->hide();
6899 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6900 m_OpsFocusProcess->focusStarPSF->hide();
6903 case FOCUS_STAR_FWHM:
6904 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6906 m_FocusView->setStarsHFREnabled(
false);
6909 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSFLabel, 2, 2);
6910 m_OpsFocusProcess->focusStarPSFLabel->show();
6911 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSF, 2, 3);
6912 m_OpsFocusProcess->focusStarPSF->show();
6915 case FOCUS_STAR_NUM_STARS:
6916 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6917 m_FocusView->setStarsHFREnabled(
true);
6920 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6921 m_OpsFocusProcess->focusStarPSFLabel->hide();
6922 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6923 m_OpsFocusProcess->focusStarPSF->hide();
6926 case FOCUS_STAR_FOURIER_POWER:
6927 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6928 m_FocusView->setStarsHFREnabled(
true);
6931 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6932 m_OpsFocusProcess->focusStarPSFLabel->hide();
6933 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6934 m_OpsFocusProcess->focusStarPSF->hide();
6937 case FOCUS_STAR_STDDEV:
6938 case FOCUS_STAR_SOBEL:
6939 case FOCUS_STAR_LAPLASSIAN:
6940 case FOCUS_STAR_CANNY:
6941 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6942 m_FocusView->setStarsHFREnabled(
true);
6945 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6946 m_OpsFocusProcess->focusStarPSFLabel->hide();
6947 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6948 m_OpsFocusProcess->focusStarPSF->hide();
6956void Focus::setStarPSF(StarPSF starPSF)
6958 m_StarPSF = starPSF;
6961void Focus::setStarUnits(StarUnits starUnits)
6963 m_StarUnits = starUnits;
6966void Focus::setWalk(FocusWalk walk)
6968 if (m_OpsFocusMechanics->focusWalk->currentIndex() == -1)
6971 static bool first =
true;
6972 if (!first && m_FocusWalk == walk)
6981 case FOCUS_WALK_CLASSIC:
6982 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumStepsLabel,
6983 m_OpsFocusMechanics->focusOutStepsLabel);
6984 m_OpsFocusMechanics->focusNumStepsLabel->hide();
6985 m_OpsFocusMechanics->focusOutStepsLabel->show();
6986 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumSteps,
6987 m_OpsFocusMechanics->focusOutSteps);
6988 m_OpsFocusMechanics->focusNumSteps->hide();
6989 m_OpsFocusMechanics->focusOutSteps->show();
6992 case FOCUS_WALK_FIXED_STEPS:
6993 case FOCUS_WALK_CFZ_SHUFFLE:
6994 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
6995 m_OpsFocusMechanics->focusNumStepsLabel);
6996 m_OpsFocusMechanics->focusOutStepsLabel->hide();
6997 m_OpsFocusMechanics->focusNumStepsLabel->show();
6998 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
6999 m_OpsFocusMechanics->focusNumSteps);
7000 m_OpsFocusMechanics->focusOutSteps->hide();
7001 m_OpsFocusMechanics->focusNumSteps->show();
7010double Focus::getStarUnits(
const StarMeasure starMeasure,
const StarUnits starUnits)
7012 if (starUnits == FOCUS_UNITS_PIXEL || starMeasure == FOCUS_STAR_NUM_STARS || starMeasure == FOCUS_STAR_FOURIER_POWER
7013 || starMeasure == FOCUS_STAR_STDDEV || starMeasure == FOCUS_STAR_SOBEL || starMeasure == FOCUS_STAR_LAPLASSIAN
7014 || starMeasure == FOCUS_STAR_CANNY)
7016 if (m_CcdPixelSizeX <= 0.0 || m_FocalLength <= 0.0)
7020 return m_CcdPixelSizeX / m_FocalLength * 206.265;
7023void Focus::calcCFZ()
7025 double cfzMicrons, cfzSteps;
7026 double cfzCameraSteps = calcCameraCFZ() / m_CFZUI->focusCFZStepSize->value();
7028 switch(
static_cast<Focus::CFZAlgorithm
> (m_CFZUI->focusCFZAlgorithm->currentIndex()))
7030 case Focus::FOCUS_CFZ_CLASSIC:
7032 cfzMicrons = 4.88f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f *
7033 pow(m_CFZUI->focusCFZFNumber->value(), 2.0f);
7034 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7035 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7036 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4.88 t λ f²");
7037 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7038 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7039 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7040 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7043 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
7044 m_CFZUI->focusCFZTauLabel->hide();
7045 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
7046 m_CFZUI->focusCFZTau->hide();
7047 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
7048 m_CFZUI->focusCFZSeeingLabel->hide();
7049 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
7050 m_CFZUI->focusCFZSeeing->hide();
7053 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
7054 m_CFZUI->focusCFZToleranceLabel->show();
7055 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
7056 m_CFZUI->focusCFZTolerance->show();
7057 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
7058 m_CFZUI->focusCFZWavelengthLabel->show();
7059 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
7060 m_CFZUI->focusCFZWavelength->show();
7063 case Focus::FOCUS_CFZ_WAVEFRONT:
7065 cfzMicrons = 4.0f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f * pow(
7066 m_CFZUI->focusCFZFNumber->value(),
7068 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7069 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7070 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4 t λ f²");
7071 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7072 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7073 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7074 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7077 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
7078 m_CFZUI->focusCFZTauLabel->hide();
7079 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
7080 m_CFZUI->focusCFZTau->hide();
7081 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
7082 m_CFZUI->focusCFZSeeingLabel->hide();
7083 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
7084 m_CFZUI->focusCFZSeeing->hide();
7087 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
7088 m_CFZUI->focusCFZToleranceLabel->show();
7089 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
7090 m_CFZUI->focusCFZTolerance->show();
7091 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
7092 m_CFZUI->focusCFZWavelengthLabel->show();
7093 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
7094 m_CFZUI->focusCFZWavelength->show();
7097 case Focus::FOCUS_CFZ_GOLD:
7099 cfzMicrons = 0.00225f * pow(m_CFZUI->focusCFZTau->value(), 0.5f) * m_CFZUI->focusCFZSeeing->value()
7100 * pow(m_CFZUI->focusCFZFNumber->value(), 2.0f) * m_CFZUI->focusCFZAperture->value();
7101 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7102 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7103 m_CFZUI->focusCFZFormula->setText(
"CFZ = 0.00225 √τ θ f² A");
7104 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7105 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7106 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7107 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7110 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZToleranceLabel);
7111 m_CFZUI->focusCFZToleranceLabel->hide();
7112 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTolerance);
7113 m_CFZUI->focusCFZTolerance->hide();
7114 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelengthLabel);
7115 m_CFZUI->focusCFZWavelengthLabel->hide();
7116 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelength);
7117 m_CFZUI->focusCFZWavelength->hide();
7120 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTauLabel, 1, 0);
7121 m_CFZUI->focusCFZTauLabel->show();
7122 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTau, 1, 1);
7123 m_CFZUI->focusCFZTau->show();
7124 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeingLabel, 2, 0);
7125 m_CFZUI->focusCFZSeeingLabel->show();
7126 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeing, 2, 1);
7127 m_CFZUI->focusCFZSeeing->show();
7130 if (linearFocuser !=
nullptr && linearFocuser->isDone())
7131 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
7132 m_CFZUI->focusCFZDisplayVCurve->isChecked());
7138double Focus::calcCameraCFZ()
7140 return m_CcdPixelSizeX * pow(m_CFZUI->focusCFZFNumber->value(), 2.0) * m_CFZUI->focusCFZAperture->value() / 1000.0;
7143void Focus::wavelengthChanged()
7146 if (m_FilterManager)
7148 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
7153void Focus::resetCFZToOT()
7156 m_CFZUI->focusCFZFNumber->setValue(m_FocalRatio);
7157 m_CFZUI->focusCFZAperture->setValue(m_Aperture);
7160 if (m_FilterManager)
7162 if (m_CFZUI->focusCFZWavelength->value() != m_FilterManager->getFilterWavelength(
filter()))
7163 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
7168void Focus::setState(FocusState newState)
7170 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus State changes from" << getFocusStatusString(m_state) <<
"to" << getFocusStatusString(
7173 emit newStatus(m_state, opticalTrain());
7176void Focus::initView()
7178 m_FocusView.reset(
new FITSView(focusingWidget, FITS_FOCUS));
7180 m_FocusView->setBaseSize(focusingWidget->size());
7181 m_FocusView->createFloatingToolBar();
7184 focusingWidget->setLayout(vlayout);
7186 m_FocusView->setStarsEnabled(
true);
7187 m_FocusView->setStarsHFREnabled(
true);
7190void Focus::initHelperObjects()
7193 starFitting.reset(
new CurveFitting());
7194 focusFWHM.reset(
new FocusFWHM(m_ScaleCalc));
7195 focusFourierPower.reset(
new FocusFourierPower(m_ScaleCalc));
7196#if defined(HAVE_OPENCV)
7197 focusBlurriness.reset(
new FocusBlurriness());
7201 adaptFocus.reset(
new AdaptiveFocus(
this));
7204 focusAdvisor.reset(
new FocusAdvisor(
this));
7207QVariantMap Focus::getAllSettings()
const
7209 QVariantMap settings;
7212 for (
auto &oneWidget : findChildren<QComboBox*>())
7213 settings.insert(oneWidget->objectName(), oneWidget->currentText());
7216 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
7217 settings.insert(oneWidget->objectName(), oneWidget->value());
7220 for (
auto &oneWidget : findChildren<QSpinBox*>())
7221 settings.insert(oneWidget->objectName(), oneWidget->value());
7224 for (
auto &oneWidget : findChildren<QCheckBox*>())
7225 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7228 for (
auto &oneWidget : findChildren<QGroupBox*>())
7229 if (oneWidget->isCheckable())
7230 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7233 for (
auto &oneWidget : findChildren<QSplitter*>())
7234 settings.insert(oneWidget->objectName(),
QString::fromUtf8(oneWidget->saveState().toBase64()));
7237 for (
auto &oneWidget : findChildren<QRadioButton*>())
7238 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7243void Focus::setAllSettings(
const QVariantMap &settings)
7247 disconnectSyncSettings();
7249 for (
auto &name : settings.keys())
7252 auto comboBox = findChild<QComboBox*>(name);
7255 syncControl(settings, name, comboBox);
7260 auto doubleSpinBox = findChild<QDoubleSpinBox*>(name);
7263 syncControl(settings, name, doubleSpinBox);
7268 auto spinBox = findChild<QSpinBox*>(name);
7271 syncControl(settings, name, spinBox);
7276 auto checkbox = findChild<QCheckBox*>(name);
7279 syncControl(settings, name, checkbox);
7284 auto groupbox = findChild<QGroupBox*>(name);
7285 if (groupbox && groupbox->isCheckable())
7287 syncControl(settings, name, groupbox);
7292 auto splitter = findChild<QSplitter*>(name);
7295 syncControl(settings, name, splitter);
7300 auto radioButton = findChild<QRadioButton*>(name);
7303 syncControl(settings, name, radioButton);
7309 for (
auto &key : settings.keys())
7311 auto value = settings[key];
7313 Options::self()->setProperty(key.
toLatin1(), value);
7315 m_Settings[key] = value;
7316 m_GlobalSettings[key] = value;
7319 emit settingsUpdated(getAllSettings());
7322 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
7323 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
7326 connectSyncSettings();
7329 m_CurveFit =
static_cast<CurveFitting::CurveFit
> (m_OpsFocusProcess->focusCurveFit->currentIndex());
7330 setFocusDetection(
static_cast<StarAlgorithm
> (m_OpsFocusProcess->focusDetection->currentIndex()));
7331 setCurveFit(
static_cast<CurveFitting::CurveFit
>(m_OpsFocusProcess->focusCurveFit->currentIndex()));
7332 setStarMeasure(
static_cast<StarMeasure
>(m_OpsFocusProcess->focusStarMeasure->currentIndex()));
7333 setWalk(
static_cast<FocusWalk
>(m_OpsFocusMechanics->focusWalk->currentIndex()));
7337bool Focus::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
7348 if ((pSB = qobject_cast<QSpinBox *>(widget)))
7350 const int value = settings[key].toInt(&ok);
7357 else if ((pDSB = qobject_cast<QDoubleSpinBox *>(widget)))
7359 const double value = settings[key].toDouble(&ok);
7366 else if ((pCB = qobject_cast<QCheckBox *>(widget)))
7368 const bool value = settings[key].toBool();
7373 else if ((pGB = qobject_cast<QGroupBox *>(widget)))
7375 const bool value = settings[key].toBool();
7380 else if ((pRadioButton = qobject_cast<QRadioButton *>(widget)))
7382 const bool value = settings[key].toBool();
7388 else if ((pComboBox = qobject_cast<QComboBox *>(widget)))
7390 const QString value = settings[key].toString();
7394 else if ((pSplitter = qobject_cast<QSplitter *>(widget)))
7404void Focus::setupOpticalTrainManager()
7406 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Focus::refreshOpticalTrain);
7409 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
7413 ProfileSettings::Instance()->setOneSetting(ProfileSettings::FocusOpticalTrain,
7414 OpticalTrainManager::Instance()->
id(opticalTrainCombo->itemText(index)));
7415 refreshOpticalTrain();
7416 emit trainChanged();
7420void Focus::refreshOpticalTrain()
7422 bool validSettings =
false;
7423 opticalTrainCombo->blockSignals(
true);
7424 opticalTrainCombo->clear();
7425 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
7426 trainB->setEnabled(
true);
7428 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::FocusOpticalTrain);
7432 auto id = trainID.
toUInt();
7435 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
7437 qCWarning(KSTARS_EKOS_FOCUS) <<
"Optical train doesn't exist for id" << id;
7438 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
7441 auto name = OpticalTrainManager::Instance()->name(
id);
7443 opticalTrainCombo->setCurrentText(name);
7449 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
7451 auto focuser = OpticalTrainManager::Instance()->getFocuser(name);
7452 setFocuser(focuser);
7454 auto scope = OpticalTrainManager::Instance()->getScope(name);
7455 double reducer = OpticalTrainManager::Instance()->getReducer(name);
7456 setScopeDetails(scope, reducer);
7458 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Focus);
7459 if (settings.isValid())
7461 validSettings =
true;
7462 auto map = settings.toJsonObject().toVariantMap();
7463 if (map != m_Settings)
7466 setAllSettings(map);
7470 auto camera = OpticalTrainManager::Instance()->getCamera(name);
7473 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(camera->getDeviceName(), scope[
"name"].toString()));
7476 auto nvp = camera->getNumber(
"CCD_INFO");
7479 m_CcdPixelSizeX = 0.0;
7480 m_CcdWidth = m_CcdHeight = 0;
7484 auto np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
7486 m_CcdPixelSizeX = np->getValue();
7487 np = nvp->findWidgetByName(
"CCD_MAX_X");
7489 m_CcdWidth = np->getValue();
7490 np = nvp->findWidgetByName(
"CCD_MAX_Y");
7492 m_CcdHeight = np->getValue();
7497 auto filterWheel = OpticalTrainManager::Instance()->getFilterWheel(name);
7498 setFilterWheel(filterWheel);
7506 focusAdvisor->setupParams(name);
7507 focusAdvisor->updateParams();
7511 opticalTrainCombo->blockSignals(
false);
7515void Focus::setScopeDetails(
const QJsonObject &scope,
const double reducer)
7517 m_Aperture = scope[
"aperture"].toDouble(-1);
7518 m_FocalLength = scope[
"focal_length"].toDouble(-1);
7519 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
7520 m_ScopeType = scope[
"type"].toString();
7521 m_Reducer = reducer;
7524 if (m_Reducer > 0.0)
7525 m_FocalLength *= m_Reducer;
7528 if (m_FocalRatio <= 0.0)
7530 m_FocalRatio = (m_Aperture > 0.001) ? m_FocalLength / m_Aperture : 0.0f;
7531 else if (m_Aperture < 0.0)
7533 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 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
void appendLogText(const QString &logtext)
setFocusStatus Upon completion of the focusing process, set its status (fail or pass) and reset focus...
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)
const KStarsDateTime & lt() const
static KStars * Instance()
The sky coordinates of a point in the sky.
An angle, stored as degrees, but expressible in many ways.
const double & Degrees() const
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 TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
QString name(StandardAction 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)
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
bool isChecked() const const
QIcon fromTheme(const QString &name)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
qsizetype size() const const
bool disconnect(const QMetaObject::Connection &connection)
QList< T > findChildren(Qt::FindChildOptions options) const const
bool contains(const QPoint &point, bool proper) const const
bool isNull() const const
bool restoreState(const QByteArray &state)
QByteArray saveState() const const
void splitterMoved(int pos, int index)
void setEnabled(bool enabled)
QStandardItem * item(int row, int column) 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)
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