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
84 qRegisterMetaType<Ekos::FocusState>(
"Ekos::FocusState");
85 qDBusRegisterMetaType<Ekos::FocusState>();
86 new FocusAdaptor(
this);
102 loadGlobalSettings();
105 connectSyncSettings();
108 adaptFocus.reset(
new AdaptiveFocus(
this));
111 focusAdvisor.reset(
new FocusAdvisor(
this));
113 connect(focusAdvisor.get(), &FocusAdvisor::newStage,
this, &Focus::newFocusAdvisorStage);
114 connect(focusAdvisor.get(), &FocusAdvisor::newMessage,
this, &Focus::newFocusAdvisorMessage);
121 for (
auto &button : qButtons)
122 button->setAutoDefault(
false);
124 appendLogText(
i18n(
"Idle."));
127 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
128 m_FocusMotionTimer.setSingleShot(
true);
131 m_OpsFocusProcess->editFocusProfile->setIcon(
QIcon::fromTheme(
"document-edit"));
136 KConfigDialog *optionsEditor = new KConfigDialog(this,
"OptionsProfileEditor", Options::self());
137 optionsProfileEditor = new StellarSolverProfileEditor(this, Ekos::FocusProfiles, optionsEditor);
139 optionsEditor->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
141 KPageWidgetItem *mainPage = optionsEditor->addPage(optionsProfileEditor, i18n(
"Focus Options Profile Editor"));
142 mainPage->setIcon(QIcon::fromTheme(
"configure"));
143 connect(optionsProfileEditor, &StellarSolverProfileEditor::optionsProfilesUpdated, this, &Focus::loadStellarSolverProfiles);
144 optionsProfileEditor->loadProfile(m_OpsFocusProcess->focusSEPProfile->currentText());
145 optionsEditor->show();
148 loadStellarSolverProfiles();
162 m_DarkProcessor =
new DarkProcessor(
this);
164 connect(m_DarkProcessor, &DarkProcessor::darkFrameCompleted,
this, [
this](
bool completed)
166 m_OpsFocusSettings->useFocusDarkFrame->setChecked(completed);
167 m_FocusView->setProperty(
"suspended",
false);
170 m_FocusView->rescale(ZOOM_KEEP_LEVEL);
171 m_FocusView->updateFrame();
173 setCaptureComplete();
177 setupOpticalTrainManager();
178 refreshOpticalTrain();
181 connectFilterManager();
185void Focus::prepareGUI()
195 m_OpsFocusSettings =
new OpsFocusSettings();
203 m_OpsFocusProcess =
new OpsFocusProcess();
204 page = dialog->
addPage(m_OpsFocusProcess,
i18n(
"Process"),
nullptr,
i18n(
"Focus Process"),
false);
207 m_OpsFocusMechanics =
new OpsFocusMechanics();
208 page = dialog->
addPage(m_OpsFocusMechanics,
i18n(
"Mechanics"),
nullptr,
i18n(
"Focus Mechanics"),
false);
212 m_CFZDialog =
new QDialog(
this);
213 m_CFZUI.reset(
new Ui::focusCFZDialog());
214 m_CFZUI->setupUi(m_CFZDialog);
220 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
221 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
222 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
223 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
224 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
225 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThreshold);
226 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
227 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
228 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
229 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusTolerance);
230 delete m_OpsFocusProcess->gridLayoutProcessBucket;
233 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
234 m_OpsFocusMechanics->focusNumStepsLabel);
235 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
236 m_OpsFocusMechanics->focusNumSteps);
240 for (
int i = 0; i < m_OpsFocusProcess->focusStarMeasure->count(); i++)
241 m_StarMeasureText.append(m_OpsFocusProcess->focusStarMeasure->itemText(i));
242 for (
int i = 0; i < m_OpsFocusProcess->focusCurveFit->count(); i++)
243 m_CurveFitText.append(m_OpsFocusProcess->focusCurveFit->itemText(i));
244 for (
int i = 0; i < m_OpsFocusMechanics->focusWalk->count(); i++)
245 m_FocusWalkText.append(m_OpsFocusMechanics->focusWalk->itemText(i));
248void Focus::loadStellarSolverProfiles()
250 QString savedOptionsProfiles =
QDir(KSPaths::writableLocation(
254 m_StellarSolverProfiles = StellarSolver::loadSavedOptionsProfiles(savedOptionsProfiles);
255 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_NAME);
256 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_DONUT_NAME);
259 m_StellarSolverProfiles = getDefaultFocusOptionsProfiles();
260 m_OpsFocusProcess->focusSEPProfile->clear();
261 for(
auto ¶m : m_StellarSolverProfiles)
262 m_OpsFocusProcess->focusSEPProfile->addItem(param.listName);
263 auto profile = m_Settings[
"focusSEPProfile"];
264 if (profile.isValid())
265 m_OpsFocusProcess->focusSEPProfile->setCurrentText(profile.toString());
268void Focus::addMissingStellarSolverProfile(
const QString profilePath,
const QString profile)
270 for(
auto params : m_StellarSolverProfiles)
272 if (params.listName == profile)
278 SSolver::Parameters params;
279 if (profile == FOCUS_DEFAULT_DONUT_NAME)
280 params = getFocusOptionsProfileDefaultDonut();
281 else if (profile == FOCUS_DEFAULT_NAME)
282 params = getFocusOptionsProfileDefault();
286 settings.beginGroup(params.listName);
292 settings.setValue(it.key(), it.value());
296 m_StellarSolverProfiles.append(params);
302 for (
auto param : m_StellarSolverProfiles)
303 profiles << param.listName;
311 if (focusingWidget->parent() ==
nullptr)
312 toggleFocusingWidgetFullScreen();
315void Focus::resetFrame()
317 if (m_Camera && m_Camera->isConnected())
319 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
324 targetChip->resetFrame();
327 targetChip->getFrame(&x, &y, &w, &h);
329 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is reset. X:" << x <<
"Y:" << y <<
"W:" << w <<
"H:" << h <<
"binX:" << 1 <<
"binY:" <<
332 QVariantMap settings;
337 settings[
"binx"] = 1;
338 settings[
"biny"] = 1;
339 frameSettings[targetChip] = settings;
341 starSelected =
false;
345 m_FocusView->setTrackingBox(
QRect());
346 checkMosaicMaskLimits();
354 return m_Camera->getDeviceName();
359void Focus::checkCamera()
379 case FOCUS_CHANGING_FILTER:
384 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
385 if (targetChip && targetChip->isCapturing())
390 focusBinning->setEnabled(targetChip->canBin());
391 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
392 if (targetChip->canBin())
394 int subBinX = 1, subBinY = 1;
395 focusBinning->clear();
396 targetChip->getMaxBin(&subBinX, &subBinY);
397 for (
int i = 1; i <= subBinX; i++)
398 focusBinning->addItem(
QString(
"%1x%2").arg(i).arg(i));
400 auto binning = m_Settings[
"focusBinning"];
401 if (binning.isValid())
402 focusBinning->setCurrentText(binning.toString());
405 connect(m_Camera, &ISD::Camera::videoStreamToggled,
this, &Ekos::Focus::setVideoStreamEnabled,
Qt::UniqueConnection);
406 liveVideoB->setEnabled(m_Camera->hasVideoStream());
407 if (m_Camera->hasVideoStream())
408 setVideoStreamEnabled(m_Camera->isStreamingEnabled());
418void Focus::syncCCDControls()
420 if (m_Camera ==
nullptr)
423 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
424 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
427 auto isoList = targetChip->getISOList();
430 if (isoList.isEmpty())
432 focusISO->setEnabled(
false);
433 ISOLabel->setEnabled(
false);
437 focusISO->setEnabled(
true);
438 ISOLabel->setEnabled(
true);
439 focusISO->addItems(isoList);
440 focusISO->setCurrentIndex(targetChip->getISOIndex());
443 bool hasGain = m_Camera->hasGain();
444 gainLabel->setEnabled(hasGain);
445 focusGain->setEnabled(hasGain && m_Camera->getGainPermission() != IP_RO);
448 double gain = 0, min = 0, max = 0, step = 1;
449 m_Camera->getGainMinMaxStep(&min, &max, &step);
450 if (m_Camera->getGain(&gain))
453 GainSpinSpecialValue = min - step;
454 focusGain->setRange(GainSpinSpecialValue, max);
455 focusGain->setSpecialValueText(
i18n(
"--"));
457 focusGain->setSingleStep(step);
459 auto defaultGain = m_Settings[
"focusGain"];
460 if (defaultGain.isValid())
461 focusGain->setValue(defaultGain.toDouble());
463 focusGain->setValue(GainSpinSpecialValue);
470void Focus::syncCameraInfo()
472 if (m_Camera ==
nullptr)
475 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
476 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
479 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
481 if (frameSettings.contains(targetChip) ==
false)
484 if (targetChip->getFrame(&x, &y, &w, &h))
486 int binx = 1, biny = 1;
487 targetChip->getBinning(&binx, &biny);
490 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
491 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
493 QVariantMap settings;
495 settings[
"x"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? x : minX;
496 settings[
"y"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? y : minY;
497 settings[
"w"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? w : maxW;
498 settings[
"h"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? h : maxH;
499 settings[
"binx"] = binx;
500 settings[
"biny"] = biny;
502 frameSettings[targetChip] = settings;
508bool Focus::setFilterWheel(ISD::FilterWheel *device)
510 if (m_FilterWheel && m_FilterWheel == device)
517 m_FilterWheel->disconnect(
this);
519 m_FilterWheel = device;
523 connect(m_FilterWheel, &ISD::ConcreteDevice::Connected,
this, [
this]()
525 FilterPosLabel->setEnabled(
true);
526 focusFilter->setEnabled(
true);
527 filterManagerB->setEnabled(
true);
529 connect(m_FilterWheel, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
531 FilterPosLabel->setEnabled(
false);
532 focusFilter->setEnabled(
false);
533 filterManagerB->setEnabled(
false);
537 auto isConnected = m_FilterWheel && m_FilterWheel->isConnected();
538 FilterPosLabel->setEnabled(isConnected);
539 focusFilter->setEnabled(isConnected);
540 filterManagerB->setEnabled(isConnected);
542 FilterPosLabel->setEnabled(
true);
543 focusFilter->setEnabled(
true);
551 defaultFocusTemperatureSource->blockSignals(
true);
552 m_TemperatureSources = temperatureSources;
554 defaultFocusTemperatureSource->clear();
555 for (
auto device : temperatureSources)
559 defaultFocusTemperatureSource->addItem(device->getDeviceName());
561 defaultFocusTemperatureSource->blockSignals(
false);
563 auto targetSource = m_Settings[
"defaultFocusTemperatureSource"];
564 if (targetSource.isValid())
565 checkTemperatureSource(targetSource.toString());
568void Focus::checkTemperatureSource(
const QString &name )
573 source = defaultFocusTemperatureSource->currentText();
574 if (source.isEmpty())
580 for (
auto &oneSource : m_TemperatureSources)
582 if (oneSource->getDeviceName() == source)
584 currentSource = oneSource;
589 m_LastSourceDeviceAutofocusTemperature = currentSource;
596 for (
const auto &oneSource : m_TemperatureSources)
600 if (findTemperatureElement(currentSource))
602 defaultFocusTemperatureSource->setCurrentText(name);
603 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
604 absoluteTemperatureLabel->setText(
QString(
"%1 °C").arg(currentTemperatureSourceElement->value, 0,
'f', 2));
605 deltaTemperatureLabel->setText(
QString(
"%1 °C").arg(0.0, 0,
'f', 2));
609 m_LastSourceAutofocusTemperature = INVALID_VALUE;
622 auto temperatureProperty = device->getProperty(
"FOCUS_TEMPERATURE");
623 if (!temperatureProperty)
624 temperatureProperty = device->getProperty(
"CCD_TEMPERATURE");
625 if (temperatureProperty)
627 currentTemperatureSourceElement = temperatureProperty.getNumber()->at(0);
631 temperatureProperty = device->getProperty(
"WEATHER_PARAMETERS");
632 if (temperatureProperty)
634 for (
int i = 0; i < temperatureProperty.getNumber()->count(); i++)
636 if (strstr(temperatureProperty.getNumber()->at(i)->getName(),
"_TEMPERATURE"))
638 currentTemperatureSourceElement = temperatureProperty.getNumber()->at(i);
650 return m_FilterWheel->getDeviceName();
660 focusFilter->setCurrentText(filter);
669 return focusFilter->currentText();
672void Focus::checkFilter()
674 focusFilter->
clear();
678 FilterPosLabel->setEnabled(
false);
679 focusFilter->setEnabled(
false);
680 filterManagerB->setEnabled(
false);
684 m_FilterManager->disconnect(
this);
685 disconnect(m_FilterManager.get());
686 m_FilterManager.reset();
691 FilterPosLabel->setEnabled(
true);
692 focusFilter->setEnabled(
true);
693 filterManagerB->setEnabled(
true);
695 setupFilterManager();
697 focusFilter->addItems(m_FilterManager->getFilterLabels());
699 currentFilterPosition = m_FilterManager->getFilterPosition();
701 focusFilter->setCurrentIndex(currentFilterPosition - 1);
703 focusExposure->setValue(m_FilterManager->getFilterExposure());
708 if (m_Focuser && m_Focuser == device)
715 m_Focuser->disconnect(
this);
721 connect(m_Focuser, &ISD::ConcreteDevice::Connected,
this, [
this]()
725 connect(m_Focuser, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
732 emit focuserChanged(m_focuserId, device !=
nullptr);
739 return m_Focuser->getDeviceName();
744void Focus::checkFocuser()
749 m_FilterManager->setFocusReady(
false);
750 canAbsMove = canRelMove = canTimerMove =
false;
752 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
757 m_FilterManager->setFocusReady(m_Focuser->isConnected());
759 hasDeviation = m_Focuser->hasDeviation();
761 canAbsMove = m_Focuser->canAbsMove();
765 getAbsFocusPosition();
767 absTicksSpin->setEnabled(
true);
768 absTicksLabel->setEnabled(
true);
769 startGotoB->setEnabled(
true);
772 if (absTicksSpin->value() <= 0)
773 absTicksSpin->setValue(currentPosition);
777 absTicksSpin->setEnabled(
false);
778 absTicksLabel->setEnabled(
false);
779 startGotoB->setEnabled(
false);
782 canRelMove = m_Focuser->canRelMove();
787 if (canAbsMove ==
false && canRelMove ==
true)
789 currentPosition = 50000;
790 absMotionMax = 100000;
794 canTimerMove = m_Focuser->canTimerMove();
800 if (!canAbsMove && !canRelMove && canTimerMove)
802 currentPosition = 50000;
803 absMotionMax = 100000;
807 m_FocusType = (canRelMove || canAbsMove || canTimerMove) ? FOCUS_AUTO : FOCUS_MANUAL;
808 profilePlot->setFocusAuto(m_FocusType == FOCUS_AUTO);
810 bool hasBacklash = m_Focuser->hasBacklash();
811 m_OpsFocusMechanics->focusBacklash->setEnabled(hasBacklash);
812 m_OpsFocusMechanics->focusBacklash->disconnect(
this);
815 double min = 0, max = 0, step = 0;
816 m_Focuser->getMinMaxStep(
"FOCUS_BACKLASH_STEPS",
"FOCUS_BACKLASH_VALUE", &min, &max, &step);
817 m_OpsFocusMechanics->focusBacklash->setMinimum(min);
818 m_OpsFocusMechanics->focusBacklash->setMaximum(max);
819 m_OpsFocusMechanics->focusBacklash->setSingleStep(step);
820 m_OpsFocusMechanics->focusBacklash->setValue(m_Focuser->getBacklash());
822 this, [
this](
int value)
826 if (m_Focuser->getBacklash() == value)
832 m_Focuser->setBacklash(value);
837 connect(m_OpsFocusMechanics->focusBacklash, QOverload<int>::of(&
QSpinBox::valueChanged),
this, &Ekos::Focus::syncSettings);
841 m_OpsFocusMechanics->focusBacklash->setValue(0);
847 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
852 if (m_Camera && m_Camera == device)
858 m_captureInProgress =
false;
861 m_Camera->disconnect(
this);
867 connect(m_Camera, &ISD::ConcreteDevice::Connected,
this, [
this]()
869 focuserGroup->setEnabled(
true);
870 ccdGroup->setEnabled(
true);
871 toolsGroup->setEnabled(
true);
873 connect(m_Camera, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
875 focuserGroup->setEnabled(
false);
876 ccdGroup->setEnabled(
false);
877 toolsGroup->setEnabled(
false);
881 auto isConnected = m_Camera && m_Camera->isConnected();
882 focuserGroup->setEnabled(isConnected);
883 ccdGroup->setEnabled(isConnected);
884 toolsGroup->setEnabled(isConnected);
892 checkMosaicMaskLimits();
896void Focus::getAbsFocusPosition()
901 auto absMove = m_Focuser->getNumber(
"ABS_FOCUS_POSITION");
905 const auto &it = absMove->at(0);
906 currentPosition =
static_cast<int>(it->getValue());
907 absMotionMax = it->getMax();
908 absMotionMin = it->getMin();
910 absTicksSpin->setMinimum(it->getMin());
911 absTicksSpin->setMaximum(it->getMax());
912 absTicksSpin->setSingleStep(it->getStep());
915 double const travel = std::abs(it->getMax() - it->getMin());
916 m_OpsFocusMechanics->focusMaxTravel->setMaximum(travel);;
920 m_OpsFocusMechanics->focusTicks->setMaximum(it->getMax() / 2);
924void Focus::processTemperatureSource(INDI::Property prop)
926 if (m_LastSourceAutofocusTemperature == INVALID_VALUE && m_LastSourceDeviceAutofocusTemperature
927 && !currentTemperatureSourceElement )
929 if( findTemperatureElement( m_LastSourceDeviceAutofocusTemperature ) )
931 appendLogText(
i18n(
"Finally found temperature source %1",
QString(currentTemperatureSourceElement->nvp->name)));
932 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
937 if (currentTemperatureSourceElement && currentTemperatureSourceElement->nvp->name == prop.getName())
939 if (m_LastSourceAutofocusTemperature != INVALID_VALUE)
941 delta = currentTemperatureSourceElement->value - m_LastSourceAutofocusTemperature;
942 emit newFocusTemperatureDelta(abs(delta), currentTemperatureSourceElement->value, opticalTrain());
946 emit newFocusTemperatureDelta(0, currentTemperatureSourceElement->value, opticalTrain());
949 absoluteTemperatureLabel->setText(
QString(
"%1 °C").arg(currentTemperatureSourceElement->value, 0,
'f', 2));
950 deltaTemperatureLabel->setText(
QString(
"%1%2 °C").arg((delta > 0.0 ?
"+" :
"")).arg(delta, 0,
'f', 2));
952 deltaTemperatureLabel->setStyleSheet(
"color: lightgreen");
954 deltaTemperatureLabel->setStyleSheet(
"color: lightcoral");
956 deltaTemperatureLabel->setStyleSheet(
"color: lightblue");
960void Focus::setLastFocusTemperature()
962 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE;
965 deltaTemperatureLabel->setText(
QString(
"0 °C"));
966 deltaTemperatureLabel->setStyleSheet(
"color: lightgreen");
968 emit newFocusTemperatureDelta(0, -1e6, opticalTrain());
971void Focus::setLastFocusAlt()
973 if (mountAlt < 0.0 || mountAlt > 90.0)
974 m_LastSourceAutofocusAlt = INVALID_VALUE;
976 m_LastSourceAutofocusAlt = mountAlt;
980void Focus::resetAdaptiveFocus(
bool enabled)
983 Options::setFocusAdaptive(enabled);
986 adaptFocus.reset(
new AdaptiveFocus(
this));
987 adaptFocus->resetAdaptiveFocusCounters();
991void Focus::adaptiveFocus()
994 adaptFocus->runAdaptiveFocus(currentPosition, filter());
998void Focus::startAbIns()
1000 m_abInsOn = canAbInsStart();
1001 runAutoFocus(AutofocusReason::FOCUS_ABERRATION_INSPECTOR,
"");
1005void Focus::manualStart()
1007 runAutoFocus(AutofocusReason::FOCUS_MANUAL,
"");
1013 runAutoFocus(AutofocusReason::FOCUS_SCHEDULER,
"");
1017void Focus::runAutoFocus(AutofocusReason autofocusReason,
const QString &reasonInfo)
1019 m_AutofocusReason = autofocusReason;
1020 m_AutofocusReasonInfo = reasonInfo;
1021 if (m_Focuser ==
nullptr)
1023 appendLogText(
i18n(
"No Focuser connected."));
1024 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_FOCUSER);
1028 if (m_Camera ==
nullptr)
1030 appendLogText(
i18n(
"No CCD connected."));
1031 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_CAMERA);
1035 if (!canAbsMove && !canRelMove && m_OpsFocusMechanics->focusTicks->value() <= MINIMUM_PULSE_TIMER)
1037 appendLogText(
i18n(
"Starting pulse step is too low. Increase the step size to %1 or higher...",
1038 MINIMUM_PULSE_TIMER * 5));
1039 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_LOW_PULSE);
1048 appendLogText(
i18n(
"Autofocus is already running, discarding start request."));
1055 appendLogText(
i18n(
"Build Offset is already running, Autofocus rejected."));
1056 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1063 appendLogText(
i18n(
"In Focus Loop, Autofocus rejected."));
1064 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1068 if (inAdjustFocus || adaptFocus->inAdaptiveFocus())
1070 QString str = inAdjustFocus ?
i18n(
"Adjust Focus") :
i18n(
"Adaptive Focus");
1071 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
1073 appendLogText(
i18n(
"Autofocus start request - Waiting 10sec for %1 to complete.", str));
1076 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
1081 appendLogText(
i18n(
"Discarding Autofocus start request - %1 in progress.", str));
1082 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1086 inBuildOffsets = (autofocusReason == AutofocusReason::FOCUS_FILTER_OFFSETS);
1087 if (autofocusReason == AutofocusReason::FOCUS_USER_REQUEST)
1089 forceInSeqAF->setChecked(
false);
1090 emit inSequenceAF(
false, opticalTrain());
1095 m_LastFocusDirection = FOCUS_NONE;
1097 waitStarSelectTimer.stop();
1100 m_FocusMotionTimerCounter = 0;
1101 m_FocusMotionTimer.stop();
1102 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
1105 m_FocuserReconnectCounter = 0;
1108 m_FocuserReconnectCounter = 0;
1109 m_DebugFocuserCounter = 0;
1116 m_RestartState = RESTART_NONE;
1124 getAbsFocusPosition();
1125 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1127 else if (canRelMove)
1131 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1133 absMotionMax = 100000;
1138 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1140 absMotionMax = 100000;
1144 focuserAdditionalMovement = 0;
1145 starMeasureFrames.clear();
1157 profilePlot->clear();
1158 FWHMOut->setText(
"");
1160 qCInfo(KSTARS_EKOS_FOCUS) <<
"Starting Autofocus " << m_AFRun
1161 <<
" on" << opticalTrain()
1162 <<
" Reason: " << AutofocusReasonStr[m_AutofocusReason]
1163 <<
" Reason Info: " << m_AutofocusReasonInfo
1164 <<
" CanAbsMove: " << (canAbsMove ?
"yes" :
"no" )
1165 <<
" CanRelMove: " << (canRelMove ?
"yes" :
"no" )
1166 <<
" CanTimerMove: " << (canTimerMove ?
"yes" :
"no" )
1167 <<
" Position:" << currentPosition
1168 <<
" Filter:" << filter()
1169 <<
" Exp:" << focusExposure->value()
1170 <<
" Bin:" << focusBinning->currentText()
1171 <<
" Gain:" << focusGain->value()
1172 <<
" ISO:" << focusISO->currentText();
1173 qCInfo(KSTARS_EKOS_FOCUS) <<
"Settings Tab."
1174 <<
" Auto Select Star:" << ( m_OpsFocusSettings->focusAutoStarEnabled->isChecked() ?
"yes" :
"no" )
1175 <<
" Dark Frame:" << ( m_OpsFocusSettings->useFocusDarkFrame->isChecked() ?
"yes" :
"no" )
1176 <<
" Sub Frame:" << ( m_OpsFocusSettings->focusSubFrame->isChecked() ?
"yes" :
"no" )
1177 <<
" Box:" << m_OpsFocusSettings->focusBoxSize->value()
1178 <<
" Full frame:" << ( m_OpsFocusSettings->focusUseFullField->isChecked() ?
"yes" :
"no " )
1179 <<
" Focus Mask: " << (m_OpsFocusSettings->focusNoMaskRB->isChecked() ?
"Use all stars" :
1180 (m_OpsFocusSettings->focusRingMaskRB->isChecked() ?
QString(
"Ring Mask: [%1%, %2%]").
1181 arg(m_OpsFocusSettings->focusFullFieldInnerRadius->value()).
arg(m_OpsFocusSettings->focusFullFieldOuterRadius->value()) :
1182 QString(
"Mosaic Mask: [%1%, space=%2px]").
1183 arg(m_OpsFocusSettings->focusMosaicTileWidth->value()).
arg(m_OpsFocusSettings->focusMosaicSpace->value())))
1184 <<
" Suspend Guiding:" << ( m_OpsFocusSettings->focusSuspendGuiding->isChecked() ?
"yes" :
"no " )
1185 <<
" Guide Settle:" << m_OpsFocusSettings->focusGuideSettleTime->value()
1186 <<
" Display Units:" << m_OpsFocusSettings->focusUnits->currentText()
1187 <<
" Adaptive Focus:" << ( m_OpsFocusSettings->focusAdaptive->isChecked() ?
"yes" :
"no" )
1188 <<
" Min Move:" << m_OpsFocusSettings->focusAdaptiveMinMove->value()
1189 <<
" Adapt Start:" << ( m_OpsFocusSettings->focusAdaptStart->isChecked() ?
"yes" :
"no" )
1190 <<
" Max Total Move:" << m_OpsFocusSettings->focusAdaptiveMaxMove->value();
1191 qCInfo(KSTARS_EKOS_FOCUS) <<
"Process Tab."
1192 <<
" Detection:" << m_OpsFocusProcess->focusDetection->currentText()
1193 <<
" SEP Profile:" << m_OpsFocusProcess->focusSEPProfile->currentText()
1194 <<
" Algorithm:" << m_OpsFocusProcess->focusAlgorithm->currentText()
1195 <<
" Curve Fit:" << m_OpsFocusProcess->focusCurveFit->currentText()
1196 <<
" Measure:" << m_OpsFocusProcess->focusStarMeasure->currentText()
1197 <<
" PSF:" << m_OpsFocusProcess->focusStarPSF->currentText()
1198 <<
" Use Weights:" << ( m_OpsFocusProcess->focusUseWeights->isChecked() ?
"yes" :
"no" )
1199 <<
" R2 Limit:" << m_OpsFocusProcess->focusR2Limit->value()
1200 <<
" Refine Curve Fit:" << ( m_OpsFocusProcess->focusRefineCurveFit->isChecked() ?
"yes" :
"no" )
1201 <<
" Average Over:" << m_OpsFocusProcess->focusFramesCount->value()
1202 <<
" Average HFR Check Over:" << m_OpsFocusProcess->focusHFRFramesCount->value()
1203 <<
" Num.of Rows:" << m_OpsFocusProcess->focusMultiRowAverage->value()
1204 <<
" Sigma:" << m_OpsFocusProcess->focusGaussianSigma->value()
1205 <<
" Threshold:" << m_OpsFocusProcess->focusThreshold->value()
1206 <<
" Kernel size:" << m_OpsFocusProcess->focusGaussianKernelSize->value()
1207 <<
" Tolerance:" << m_OpsFocusProcess->focusTolerance->value()
1208 <<
" Denoise:" << ( m_OpsFocusProcess->focusDenoise->isChecked() ?
"yes" :
"no" )
1209 <<
" Donut Buster:" << ( m_OpsFocusProcess->focusDonut->isChecked() ?
"yes" :
"no" )
1210 <<
" Donut Time Dilation:" << m_OpsFocusProcess->focusTimeDilation->value()
1211 <<
" Outlier Rejection:" << m_OpsFocusProcess->focusOutlierRejection->value()
1212 <<
" Scan Start Pos:" << ( m_OpsFocusProcess->focusScanStartPos->isChecked() ?
"yes" :
"no" )
1213 <<
" Scan Always On:" << ( m_OpsFocusProcess->focusScanAlwaysOn->isChecked() ?
"yes" :
"no" )
1214 <<
" Num Datapoints:" << m_OpsFocusProcess->focusScanDatapoints->value()
1215 <<
" Scan Step Factor:" << m_OpsFocusProcess->focusScanStepSizeFactor->value();
1216 qCInfo(KSTARS_EKOS_FOCUS) <<
"Mechanics Tab."
1217 <<
" Initial Step Size:" << m_OpsFocusMechanics->focusTicks->value()
1218 <<
" Out Step Multiple:" << m_OpsFocusMechanics->focusOutSteps->value()
1219 <<
" Number Steps:" << m_OpsFocusMechanics->focusNumSteps->value()
1220 <<
" Max Travel:" << m_OpsFocusMechanics->focusMaxTravel->value()
1221 <<
" Max Step Size:" << m_OpsFocusMechanics->focusMaxSingleStep->value()
1222 <<
" Driver Backlash:" << m_OpsFocusMechanics->focusBacklash->value()
1223 <<
" AF Overscan:" << m_OpsFocusMechanics->focusAFOverscan->value()
1224 <<
" Overscan Delay:" << m_OpsFocusMechanics->focusOverscanDelay->value()
1225 <<
" Focuser Settle:" << m_OpsFocusMechanics->focusSettleTime->value()
1226 <<
" Walk:" << m_OpsFocusMechanics->focusWalk->currentText()
1227 <<
" Capture Timeout:" << m_OpsFocusMechanics->focusCaptureTimeout->value()
1228 <<
" Motion Timeout:" << m_OpsFocusMechanics->focusMotionTimeout->value();
1229 qCInfo(KSTARS_EKOS_FOCUS) <<
"CFZ Tab."
1230 <<
" Algorithm:" << m_CFZUI->focusCFZAlgorithm->currentText()
1231 <<
" Tolerance:" << m_CFZUI->focusCFZTolerance->value()
1232 <<
" Tolerance (Ï„):" << m_CFZUI->focusCFZTau->value()
1233 <<
" Display:" << ( m_CFZUI->focusCFZDisplayVCurve->isChecked() ?
"yes" :
"no" )
1234 <<
" Wavelength (λ):" << m_CFZUI->focusCFZWavelength->value()
1235 <<
" Aperture (A):" << m_CFZUI->focusCFZAperture->value()
1236 <<
" Focal Ratio (f):" << m_CFZUI->focusCFZFNumber->value()
1237 <<
" Step Size:" << m_CFZUI->focusCFZStepSize->value()
1238 <<
" FWHM (θ):" << m_CFZUI->focusCFZSeeing->value();
1240 const double temperature = (currentTemperatureSourceElement) ? currentTemperatureSourceElement->value : INVALID_VALUE;
1241 emit autofocusStarting(temperature, filter(), m_AutofocusReason, m_AutofocusReasonInfo);
1243 appendLogText(
i18n(
"Autofocus starting..."));
1248 if (m_GuidingSuspended ==
false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
1250 m_GuidingSuspended =
true;
1251 emit suspendGuiding();
1255 setState(Ekos::FOCUS_PROGRESS);
1257 KSNotification::event(
QLatin1String(
"FocusStarted"),
i18n(
"Autofocus operation started"), KSNotification::Focus);
1260 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1262 m_AFfilter = filter();
1263 int position = adaptFocus->adaptStartPosition(currentPosition, m_AFfilter);
1265 curveFitting.reset(
new CurveFitting());
1267 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1270 starFitting.reset(
new CurveFitting());
1271 focusFWHM.reset(
new FocusFWHM(m_ScaleCalc));
1272 focusFourierPower.reset(
new FocusFourierPower(m_ScaleCalc));
1273#if defined(HAVE_OPENCV)
1274 focusBlurriness.reset(
new FocusBlurriness(m_ScaleCalc));
1277 initDonutProcessing();
1279 if (initScanStartPos(
false, currentPosition))
1282 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
1284 focusAdvisor->initControl();
1290 setupLinearFocuser(position);
1291 if (!changeFocus(linearRequestedPosition - currentPosition))
1292 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
1300void Focus::setupLinearFocuser(
int initialPosition)
1302 FocusAlgorithmInterface::FocusParams params(curveFitting.get(),
1303 m_OpsFocusMechanics->focusMaxTravel->value(), m_OpsFocusMechanics->focusTicks->value(), initialPosition, absMotionMin,
1304 absMotionMax, MAXIMUM_ABS_ITERATIONS, m_OpsFocusProcess->focusTolerance->value() / 100.0, m_AFfilter,
1305 currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE,
1306 m_OpsFocusMechanics->focusOutSteps->value(), m_OpsFocusMechanics->focusNumSteps->value(),
1307 m_FocusAlgorithm, m_OpsFocusMechanics->focusBacklash->value(), m_CurveFit, m_OpsFocusProcess->focusUseWeights->isChecked(),
1308 m_StarMeasure, m_StarPSF, m_OpsFocusProcess->focusRefineCurveFit->isChecked(), m_FocusWalk,
1309 m_OpsFocusProcess->focusDonut->isChecked(), m_OpsFocusProcess->focusOutlierRejection->value(), m_OptDir, m_ScaleCalc);
1312 initialFocuserAbsPosition = initialPosition;
1313 linearFocuser.reset(MakeLinearFocuser(params));
1314 linearRequestedPosition = linearFocuser->initialPosition();
1318void Focus::initDonutProcessing()
1320 if (!m_OpsFocusProcess->focusDonut->isChecked())
1323 m_donutOrigExposure = focusExposure->value();
1327void Focus::resetDonutProcessing()
1330 if (m_OpsFocusProcess->focusDonut->isChecked() && inAutoFocus)
1331 focusExposure->setValue(m_donutOrigExposure);
1334int Focus::adjustLinearPosition(
int position,
int newPosition,
int overscan,
bool updateDir)
1336 if (overscan > 0 && newPosition > position)
1339 int adjustment = overscan;
1340 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Linear: extending outward movement by overscan %1").
arg(adjustment);
1342 if (newPosition + adjustment > absMotionMax)
1343 adjustment =
static_cast<int>(absMotionMax) - newPosition;
1345 focuserAdditionalMovement = adjustment;
1346 focuserAdditionalMovementUpdateDir = updateDir;
1348 return newPosition + adjustment;
1356void Focus::checkStopFocus(
bool abort)
1358 m_abortInProgress =
true;
1361 resetFocusIteration = MAXIMUM_RESET_ITERATIONS + 1;
1363 if (captureTimer.isActive())
1365 captureTimer.stop();
1367 if (m_captureInProgress)
1369 if (inAutoFocus ==
false && inFocusLoop ==
false)
1371 captureB->setEnabled(
true);
1372 stopFocusB->setEnabled(
false);
1374 appendLogText(
i18n(
"Capture aborted."));
1376 else if (inAutoFocus)
1378 stopFocusB->setEnabled(
false);
1379 appendLogText(
i18n(
"Capture in progress, retrying in 1s..."));
1382 checkStopFocus(abort);
1388 if (m_starDetectInProgress)
1390 stopFocusB->setEnabled(
false);
1391 appendLogText(
i18n(
"Star detection in progress, retrying in 1s..."));
1394 checkStopFocus(abort);
1399 completeFocusProcedure(abort ? Ekos::FOCUS_ABORTED : Ekos::FOCUS_FAILED, Ekos::FOCUS_FAIL_ABORT);
1402void Focus::meridianFlipStarted()
1405 if (state() == FOCUS_IDLE || state() == FOCUS_COMPLETE || state() == FOCUS_FAILED || state() == FOCUS_ABORTED)
1409 int old = resetFocusIteration;
1413 resetFocusIteration = old;
1419 if (state() <= FOCUS_ABORTED)
1423 if (focusAdvisor->inFocusAdvisor())
1425 focusAdvisor->stop();
1431void Focus::processAbort()
1433 bool focusLoop = inFocusLoop;
1434 checkStopFocus(
true);
1435 appendLogText(
i18n(
"Autofocus aborted."));
1442void Focus::stop(Ekos::FocusState completionState)
1444 Q_UNUSED(completionState);
1445 qCDebug(KSTARS_EKOS_FOCUS) <<
"Stopping Focus";
1447 captureTimeout.stop();
1448 m_FocusMotionTimer.stop();
1449 m_FocusMotionTimerCounter = 0;
1450 m_FocuserReconnectCounter = 0;
1452 opticalTrainCombo->setEnabled(
true);
1453 resetDonutProcessing();
1454 inAutoFocus =
false;
1455 inAdjustFocus =
false;
1456 adaptFocus->setInAdaptiveFocus(
false);
1457 inBuildOffsets =
false;
1458 inScanStartPos =
false;
1459 focusAdvisor->reset();
1460 m_AutofocusReason = AutofocusReason::FOCUS_NONE;
1461 m_AutofocusReasonInfo =
"";
1462 focuserAdditionalMovement = 0;
1463 focuserAdditionalMovementUpdateDir =
true;
1464 inFocusLoop =
false;
1465 m_captureInProgress =
false;
1466 m_abortInProgress =
false;
1467 m_starDetectInProgress =
false;
1468 isVShapeSolution =
false;
1469 captureFailureCounter = 0;
1470 minimumRequiredHFR = INVALID_STAR_MEASURE;
1472 starMeasureFrames.clear();
1481 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1483 if (rememberUploadMode != m_Camera->getUploadMode())
1484 m_Camera->setUploadMode(rememberUploadMode);
1487 if (m_RememberCameraFastExposure)
1489 m_RememberCameraFastExposure =
false;
1490 m_Camera->setFastExposureEnabled(
true);
1493 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1494 targetChip->abortExposure();
1503 if (m_GuidingSuspended)
1505 emit resumeGuiding();
1506 m_GuidingSuspended =
false;
1510void Focus::capture(
double settleTime)
1512 if (m_abortInProgress)
1515 m_captureInProgress =
false;
1516 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding capture request.";
1522 if (settleTime > 0 && m_captureInProgress ==
false)
1524 captureTimer.start(
static_cast<int>(settleTime * 1000));
1528 if (m_captureInProgress)
1530 qCWarning(KSTARS_EKOS_FOCUS) <<
"Capture called while already in progress. Capture is ignored.";
1534 if (m_Camera ==
nullptr)
1536 appendLogText(
i18n(
"Error: No Camera detected."));
1537 checkStopFocus(
true);
1541 if (m_Camera->isConnected() ==
false)
1543 appendLogText(
i18n(
"Error: Lost connection to Camera."));
1544 checkStopFocus(
true);
1549 captureTimeout.stop();
1551 waitStarSelectTimer.stop();
1553 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1555 if (m_Camera->isBLOBEnabled() ==
false)
1557 m_Camera->setBLOBEnabled(
true);
1560 if (focusFilter->currentIndex() != -1)
1562 if (m_FilterWheel ==
nullptr)
1564 appendLogText(
i18n(
"Error: No Filter Wheel detected."));
1565 checkStopFocus(
true);
1568 if (m_FilterWheel->isConnected() ==
false)
1570 appendLogText(
i18n(
"Error: Lost connection to Filter Wheel."));
1571 checkStopFocus(
true);
1578 int targetPosition = focusFilter->currentIndex() + 1;
1579 if (!inBuildOffsets)
1581 QString lockedFilter = m_FilterManager->getFilterLock(filter());
1586 if (lockedFilter !=
"--" && lockedFilter != filter())
1588 int lockedFilterIndex = focusFilter->findText(lockedFilter);
1589 if (lockedFilterIndex >= 0)
1592 fallbackFilterPending =
true;
1593 fallbackFilterPosition = targetPosition;
1594 targetPosition = lockedFilterIndex + 1;
1599 filterPositionPending = (targetPosition != currentFilterPosition);
1600 if (filterPositionPending)
1605 FilterManager::FilterPolicy policy = (inAutoFocus) ?
1606 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY) :
1607 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY | FilterManager::OFFSET_POLICY);
1608 m_FilterManager->setFilterPosition(targetPosition, policy);
1611 else if (targetPosition != focusFilter->currentIndex() + 1)
1612 focusFilter->setCurrentIndex(targetPosition - 1);
1615 m_FocusView->setProperty(
"suspended", m_OpsFocusSettings->useFocusDarkFrame->isChecked());
1616 prepareCapture(targetChip);
1619 connect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError,
Qt::UniqueConnection);
1621 if (frameSettings.contains(targetChip))
1623 QVariantMap settings = frameSettings[targetChip];
1624 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
1625 settings[
"h"].toInt());
1626 settings[
"binx"] = (focusBinning->currentIndex() + 1);
1627 settings[
"biny"] = (focusBinning->currentIndex() + 1);
1628 frameSettings[targetChip] = settings;
1631 m_captureInProgress =
true;
1632 if (state() != FOCUS_PROGRESS)
1633 setState(FOCUS_PROGRESS);
1635 m_FocusView->setBaseSize(focusingWidget->size());
1637 if (targetChip->capture(focusExposure->value()))
1641 captureTimeout.start( (focusExposure->value() + m_OpsFocusMechanics->focusCaptureTimeout->value()) * 1000);
1643 if (inFocusLoop ==
false)
1644 appendLogText(
i18n(
"Capturing image..."));
1648 else if (inAutoFocus)
1650 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
1656 if (m_Camera->getUploadMode() == ISD::Camera::UPLOAD_LOCAL)
1658 rememberUploadMode = ISD::Camera::UPLOAD_LOCAL;
1659 m_Camera->setUploadMode(ISD::Camera::UPLOAD_CLIENT);
1663 if (m_Camera->isFastExposureEnabled())
1665 m_RememberCameraFastExposure =
true;
1666 m_Camera->setFastExposureEnabled(
false);
1669 m_Camera->setEncodingFormat(
"FITS");
1670 targetChip->setBatchMode(
false);
1671 targetChip->setBinning((focusBinning->currentIndex() + 1), (focusBinning->currentIndex() + 1));
1672 targetChip->setCaptureMode(FITS_FOCUS);
1673 targetChip->setFrameType(FRAME_LIGHT);
1674 targetChip->setCaptureFilter(FITS_NONE);
1676 if (isFocusISOEnabled() && focusISO->currentIndex() != -1 &&
1677 targetChip->getISOIndex() != focusISO->currentIndex())
1678 targetChip->setISOIndex(focusISO->currentIndex());
1680 if (isFocusGainEnabled() && focusGain->value() != GainSpinSpecialValue)
1681 m_Camera->setGain(focusGain->value());
1684bool Focus::focusIn(
int ms)
1686 if (currentPosition == absMotionMin)
1688 appendLogText(
i18n(
"At minimum focus position %1...", absMotionMin));
1691 focusInB->setEnabled(
false);
1692 focusOutB->setEnabled(
false);
1693 startGotoB->setEnabled(
false);
1695 ms = m_OpsFocusMechanics->focusTicks->value();
1696 if (currentPosition - ms <= absMotionMin)
1698 ms = currentPosition - absMotionMin;
1699 appendLogText(
i18n(
"Moving to minimum focus position %1...", absMotionMin));
1701 return changeFocus(-ms);
1704bool Focus::focusOut(
int ms)
1706 if (currentPosition == absMotionMax)
1708 appendLogText(
i18n(
"At maximum focus position %1...", absMotionMax));
1711 focusInB->setEnabled(
false);
1712 focusOutB->setEnabled(
false);
1713 startGotoB->setEnabled(
false);
1715 ms = m_OpsFocusMechanics->focusTicks->value();
1716 if (currentPosition + ms >= absMotionMax)
1718 ms = absMotionMax - currentPosition;
1719 appendLogText(
i18n(
"Moving to maximum focus position %1...", absMotionMax));
1721 return changeFocus(ms);
1726bool Focus::changeFocus(
int amount,
bool updateDir)
1730 if (inAutoFocus && abs(amount) <= 1)
1732 if (m_RestartState == RESTART_NOW)
1739 capture(m_OpsFocusMechanics->focusSettleTime->value());
1744 if (m_Focuser ==
nullptr)
1746 appendLogText(
i18n(
"Error: No Focuser detected."));
1747 checkStopFocus(
true);
1751 if (m_Focuser->isConnected() ==
false)
1753 appendLogText(
i18n(
"Error: Lost connection to Focuser."));
1754 checkStopFocus(
true);
1758 const int newPosition = adjustLinearPosition(currentPosition, currentPosition + amount,
1759 m_OpsFocusMechanics->focusAFOverscan->value(),
1761 if (newPosition == currentPosition)
1764 const int newAmount = newPosition - currentPosition;
1765 const int absNewAmount = abs(newAmount);
1766 const bool focusingOut = newAmount > 0;
1767 const QString dirStr = focusingOut ?
i18n(
"outward") :
i18n(
"inward");
1770 m_LastFocusDirection = (focusingOut) ? FOCUS_OUT : FOCUS_IN;
1773 m_Focuser->focusOut();
1775 m_Focuser->focusIn();
1778 m_FocusMotionTimer.start();
1782 m_LastFocusSteps = newPosition;
1783 m_Focuser->moveAbs(newPosition);
1784 appendLogText(
i18n(
"Focusing %2 by %1 steps...", abs(absNewAmount), dirStr));
1786 else if (canRelMove)
1788 m_LastFocusSteps = absNewAmount;
1789 m_Focuser->moveRel(absNewAmount);
1790 appendLogText(
i18np(
"Focusing %2 by %1 step...",
"Focusing %2 by %1 steps...", absNewAmount, dirStr));
1794 m_LastFocusSteps = absNewAmount;
1795 m_Focuser->moveByTimer(absNewAmount);
1796 appendLogText(
i18n(
"Focusing %2 by %1 ms...", absNewAmount, dirStr));
1802void Focus::handleFocusMotionTimeout()
1822 qCDebug(KSTARS_EKOS_FOCUS) <<
"handleFocusMotionTimeout() called while not in AutoFocus";
1826 m_FocusMotionTimerCounter++;
1828 if (m_FocusMotionTimerCounter > 4)
1831 appendLogText(
i18n(
"Focuser is still timing out. Aborting..."));
1832 stop(Ekos::FOCUS_ABORTED);
1835 else if (m_FocusMotionTimerCounter > 2)
1837 QString focuser = m_Focuser->getDeviceName();
1838 appendLogText(
i18n(
"Focus motion timed out (%1). Restarting focus driver %2", m_FocusMotionTimerCounter, focuser));
1839 emit focuserTimedout(focuser);
1843 Focus::reconnectFocuser(focuser);
1848 if (!changeFocus(m_LastFocusSteps - currentPosition))
1849 appendLogText(
i18n(
"Focus motion timed out (%1). Focusing to %2 steps...", m_FocusMotionTimerCounter, m_LastFocusSteps));
1852void Focus::selectImageMask()
1854 const bool useFullField = m_OpsFocusSettings->focusUseFullField->isChecked();
1855 ImageMaskType masktype;
1856 if (m_OpsFocusSettings->focusRingMaskRB->isChecked())
1857 masktype = FOCUS_MASK_RING;
1858 else if (m_OpsFocusSettings->focusMosaicMaskRB->isChecked())
1859 masktype = FOCUS_MASK_MOSAIC;
1861 masktype = FOCUS_MASK_NONE;
1864 m_OpsFocusSettings->focusRingMaskRB->setEnabled(useFullField);
1865 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(useFullField);
1867 m_OpsFocusSettings->focusFullFieldInnerRadius->setEnabled(useFullField && masktype == FOCUS_MASK_RING);
1868 m_OpsFocusSettings->focusFullFieldOuterRadius->setEnabled(useFullField && masktype == FOCUS_MASK_RING);
1870 m_OpsFocusSettings->focusMosaicTileWidth->setEnabled(useFullField && masktype == FOCUS_MASK_MOSAIC);
1871 m_OpsFocusSettings->focusSpacerLabel->setEnabled(useFullField && masktype == FOCUS_MASK_MOSAIC);
1872 m_OpsFocusSettings->focusMosaicSpace->setEnabled(useFullField && masktype == FOCUS_MASK_MOSAIC);
1875 if (masktype == FOCUS_MASK_RING)
1876 m_FocusView->setImageMask(
new ImageRingMask(m_OpsFocusSettings->focusFullFieldInnerRadius->value() / 100.0,
1877 m_OpsFocusSettings->focusFullFieldOuterRadius->value() / 100.0));
1878 else if (masktype == FOCUS_MASK_MOSAIC)
1879 m_FocusView->setImageMask(
new ImageMosaicMask(m_OpsFocusSettings->focusMosaicTileWidth->value(),
1880 m_OpsFocusSettings->focusMosaicSpace->value()));
1882 m_FocusView->setImageMask(
nullptr);
1884 checkMosaicMaskLimits();
1885 m_currentImageMask = masktype;
1886 startAbInsB->setEnabled(canAbInsStart());
1889void Focus::reconnectFocuser(
const QString &focuser)
1891 m_FocuserReconnectCounter++;
1893 if (m_Focuser && m_Focuser->getDeviceName() == focuser)
1895 appendLogText(
i18n(
"Attempting to reconnect focuser: %1", focuser));
1896 refreshOpticalTrain();
1897 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
1901 if (m_FocuserReconnectCounter > 12)
1904 appendLogText(
i18n(
"Cannot reconnect focuser: %1. Aborting...", focuser));
1905 stop(Ekos::FOCUS_ABORTED);
1911 reconnectFocuser(focuser);
1918 if (data->property(
"chip").toInt() == ISD::CameraChip::GUIDE_CCD)
1923 m_FocusView->loadData(data);
1927 m_ImageData.reset();
1929 captureTimeout.stop();
1930 captureTimeoutCounter = 0;
1931 m_MissingCameraCounter = 0;
1933 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1935 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1937 if (m_ImageData && m_OpsFocusSettings->useFocusDarkFrame->isChecked())
1939 QVariantMap settings = frameSettings[targetChip];
1940 uint16_t offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
1941 uint16_t offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
1943 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()),
1944 targetChip, m_ImageData, focusExposure->value(), offsetX, offsetY);
1948 setCaptureComplete();
1952void Focus::starDetectionFinished()
1954 m_starDetectInProgress =
false;
1955 if (m_abortInProgress)
1958 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding results from " << __FUNCTION__;
1962 appendLogText(
i18n(
"Detection complete."));
1965 double hfr = INVALID_STAR_MEASURE;
1967 if (isStarMeasureStarBased())
1969 appendLogText(
i18n(
"Detection complete."));
1971 if (m_StarFinderWatcher.result() ==
false)
1973 qCWarning(KSTARS_EKOS_FOCUS) <<
"Failed to extract any stars.";
1977 if (m_OpsFocusSettings->focusUseFullField->isChecked())
1979 m_FocusView->filterStars();
1982 hfr = m_ImageData->getHFR(m_StarMeasure == FOCUS_STAR_HFR_ADJ ? HFR_ADJ_AVERAGE : HFR_AVERAGE);
1986 m_FocusView->setTrackingBoxEnabled(
true);
1991 if (starCenter.isNull() ==
false)
1992 hfr = m_ImageData->getHFR(starCenter.x(), starCenter.y());
1996 hfr = m_ImageData->getHFR(m_FocusDetection == ALGORITHM_SEP ? HFR_HIGH : HFR_MAX);
2002 currentNumStars = m_ImageData->getDetectedStars();
2006 currentMeasure = currentHFR;
2009 if (m_StarMeasure == FOCUS_STAR_NUM_STARS)
2011 currentMeasure = currentNumStars;
2012 currentWeight = 1.0;
2014 else if (m_StarMeasure == FOCUS_STAR_FWHM)
2016 getFWHM(m_ImageData->getStarCenters(), ¤tFWHM, ¤tWeight);
2017 currentMeasure = currentFWHM;
2019 else if (m_StarMeasure == FOCUS_STAR_FOURIER_POWER)
2021 getFourierPower(¤tFourierPower, ¤tWeight);
2022 currentMeasure = currentFourierPower;
2024 else if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
2025 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
2028 if (m_OpsFocusSettings->focusSubFrame->isChecked())
2029 roi = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2030 getBlurriness(m_StarMeasure, m_OpsFocusProcess->focusDenoise->isChecked(), ¤tBlurriness, ¤tWeight, roi);
2031 currentMeasure = currentBlurriness;
2035 currentMeasure = currentHFR;
2037 std::vector<double> hfrs(stars.
size());
2042 currentWeight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), hfrs);
2045 setCurrentMeasure();
2051bool Focus::isStarMeasureStarBased()
2053 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL || m_StarMeasure == FOCUS_STAR_LAPLASSIAN
2054 || m_StarMeasure == FOCUS_STAR_CANNY)
2060void Focus::getFWHM(
const QList<Edge *> &stars,
double *FWHM,
double *weight)
2062 *FWHM = INVALID_STAR_MEASURE;
2065 auto imageBuffer = m_ImageData->getImageBuffer();
2067 switch (m_ImageData->getStatistics().dataType)
2070 focusFWHM->processFWHM(
reinterpret_cast<uint8_t
const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2074 focusFWHM->processFWHM(
reinterpret_cast<short const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2078 focusFWHM->processFWHM(
reinterpret_cast<unsigned short const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM,
2083 focusFWHM->processFWHM(
reinterpret_cast<long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2087 focusFWHM->processFWHM(
reinterpret_cast<unsigned long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2091 focusFWHM->processFWHM(
reinterpret_cast<float const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2095 focusFWHM->processFWHM(
reinterpret_cast<long long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2099 focusFWHM->processFWHM(
reinterpret_cast<double const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2103 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2104 " Cannot calc FWHM";
2110void Focus::getFourierPower(
double *fourierPower,
double *weight,
const int mosaicTile)
2112 *fourierPower = INVALID_STAR_MEASURE;
2115 auto imageBuffer = m_ImageData->getImageBuffer();
2117 switch (m_ImageData->getStatistics().dataType)
2120 focusFourierPower->processFourierPower(
reinterpret_cast<uint8_t
const *
>(imageBuffer), m_ImageData,
2121 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2125 focusFourierPower->processFourierPower(
reinterpret_cast<short const *
>(imageBuffer), m_ImageData,
2126 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2130 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned short const *
>(imageBuffer), m_ImageData,
2131 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2135 focusFourierPower->processFourierPower(
reinterpret_cast<long const *
>(imageBuffer), m_ImageData,
2136 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2140 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned long const *
>(imageBuffer), m_ImageData,
2141 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2145 focusFourierPower->processFourierPower(
reinterpret_cast<float const *
>(imageBuffer), m_ImageData,
2146 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2150 focusFourierPower->processFourierPower(
reinterpret_cast<long long const *
>(imageBuffer), m_ImageData,
2151 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2155 focusFourierPower->processFourierPower(
reinterpret_cast<double const *
>(imageBuffer), m_ImageData,
2156 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2160 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2161 " Cannot calc Fourier Power";
2167void Focus::getBlurriness(
const StarMeasure starMeasure,
const bool denoise,
double *blurriness,
double *weight,
2168 const QRect &roi,
const int mosaicTile)
2170 *blurriness = INVALID_STAR_MEASURE;
2173#if defined(HAVE_OPENCV)
2175 auto imageBuffer = m_ImageData->getImageBuffer();
2177 switch (m_ImageData->getStatistics().dataType)
2180 focusBlurriness->processBlurriness(
reinterpret_cast<uint8_t
const *
>(imageBuffer), m_ImageData, denoise,
2181 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2185 focusBlurriness->processBlurriness(
reinterpret_cast<short const *
>(imageBuffer), m_ImageData, denoise,
2186 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2190 focusBlurriness->processBlurriness(
reinterpret_cast<unsigned short const *
>(imageBuffer), m_ImageData, denoise,
2191 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2195 focusBlurriness->processBlurriness(
reinterpret_cast<long const *
>(imageBuffer), m_ImageData, denoise,
2196 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2200 focusBlurriness->processBlurriness(
reinterpret_cast<unsigned long const *
>(imageBuffer), m_ImageData, denoise,
2201 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2205 focusBlurriness->processBlurriness(
reinterpret_cast<float const *
>(imageBuffer), m_ImageData, denoise,
2206 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2210 focusBlurriness->processBlurriness(
reinterpret_cast<long long const *
>(imageBuffer), m_ImageData, denoise,
2211 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2215 focusBlurriness->processBlurriness(
reinterpret_cast<double const *
>(imageBuffer), m_ImageData, denoise,
2216 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2220 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2221 " Cannot calc Blurriness";
2225 Q_UNUSED(starMeasure);
2228 Q_UNUSED(mosaicTile);
2230 qCDebug(KSTARS_EKOS_FOCUS) <<
"getBlurriness called when openCV not installed";
2234double Focus::calculateStarWeight(
const bool useWeights,
const std::vector<double> values)
2236 if (!useWeights || values.size() <= 0)
2241 return Mathematics::RobustStatistics::ComputeWeight(m_ScaleCalc, values);
2244void Focus::analyzeSources()
2246 appendLogText(
i18n(
"Detecting sources..."));
2247 m_starDetectInProgress =
true;
2249 QVariantMap extractionSettings;
2250 extractionSettings[
"optionsProfileIndex"] = m_OpsFocusProcess->focusSEPProfile->currentIndex();
2251 extractionSettings[
"optionsProfileGroup"] =
static_cast<int>(Ekos::FocusProfiles);
2252 m_ImageData->setSourceExtractorSettings(extractionSettings);
2256 if (m_OpsFocusSettings->focusUseFullField->isChecked())
2258 m_FocusView->setTrackingBoxEnabled(
false);
2260 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2261 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2263 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection));
2267 QRect searchBox = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2271 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection, searchBox));
2276 m_FocusView->setTrackingBoxEnabled(
false);
2280 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2281 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2284 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection, searchBox));
2289bool Focus::appendMeasure(
double newMeasure)
2292 starMeasureFrames.append(newMeasure);
2295 QVector <double> samples(starMeasureFrames);
2296 samples.erase(std::remove_if(samples.begin(), samples.end(), [](
const double measure)
2298 return measure == INVALID_STAR_MEASURE;
2302 if (!samples.isEmpty())
2304 currentMeasure = Mathematics::RobustStatistics::ComputeLocation(
2305 Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, std::vector<double>(samples.begin(), samples.end()));
2307 switch(m_StarMeasure)
2309 case FOCUS_STAR_HFR:
2310 case FOCUS_STAR_HFR_ADJ:
2311 currentHFR = currentMeasure;
2313 case FOCUS_STAR_FWHM:
2314 currentFWHM = currentMeasure;
2316 case FOCUS_STAR_NUM_STARS:
2317 currentNumStars = currentMeasure;
2319 case FOCUS_STAR_FOURIER_POWER:
2320 currentFourierPower = currentMeasure;
2322 case FOCUS_STAR_STDDEV:
2323 case FOCUS_STAR_SOBEL:
2324 case FOCUS_STAR_LAPLASSIAN:
2325 case FOCUS_STAR_CANNY:
2326 currentBlurriness = currentMeasure;
2337 int framesCount = m_OpsFocusProcess->focusFramesCount->value();
2338 if ((minimumRequiredHFR > 0) || (inAutoFocus && !inBuildOffsets && !inScanStartPos && !focusAdvisor->inFocusAdvisor()
2339 && m_FocusAlgorithm == FOCUS_LINEAR1PASS
2340 && linearFocuser && !linearFocuser->isInFirstPass()))
2342 framesCount = m_OpsFocusProcess->focusHFRFramesCount->value();
2344 return starMeasureFrames.count() < framesCount;
2347void Focus::settle(
const FocusState completionState,
const bool autoFocusUsed,
const bool buildOffsetsUsed,
2348 const AutofocusFailReason failCode,
const QString failCodeInfo)
2352 if (completionState == Ekos::FOCUS_COMPLETE)
2354 if (failCode != FOCUS_FAIL_ADVISOR_COMPLETE)
2355 KSNotification::event(
QLatin1String(
"FocusSuccessful"),
i18n(
"Autofocus operation completed successfully"),
2356 KSNotification::Focus);
2358 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && curveFitting !=
nullptr)
2359 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2360 m_OpsFocusProcess->focusUseWeights->isChecked(),
2361 curveFitting->serialize(), linearFocuser->getTextStatus(R2));
2363 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2364 m_OpsFocusProcess->focusUseWeights->isChecked());
2368 if (failCode != FOCUS_FAIL_ADVISOR_COMPLETE)
2369 KSNotification::event(
QLatin1String(
"FocusFailed"),
i18n(
"Autofocus operation failed"),
2370 KSNotification::Focus, KSNotification::Alert);
2371 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2375 if (completionState == Ekos::FOCUS_COMPLETE)
2377 if (autoFocusUsed && fallbackFilterPending)
2382 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
2383 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
2388 if (fallbackFilterPending)
2390 m_pendingState = completionState;
2391 FilterManager::FilterPolicy policy =
static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY |
2392 FilterManager::OFFSET_POLICY);
2393 m_FilterManager->setFilterPosition(fallbackFilterPosition, policy);
2396 setState(completionState);
2398 if (autoFocusUsed && buildOffsetsUsed)
2400 m_FilterManager->autoFocusComplete(completionState, currentPosition, m_LastSourceAutofocusTemperature,
2401 m_LastSourceAutofocusAlt);
2406QString Focus::getAnalyzeData()
2408 QString analysis_results =
"";
2410 for (
int i = 0; i < plot_position.size(); ++i)
2413 .arg(i == 0 ?
"" :
"|" )
2419 return analysis_results;
2422void Focus::completeFocusProcedure(FocusState completionState, AutofocusFailReason failCode,
QString failCodeInfo,
2426 if (inAutoFocus && failCode != Ekos::FOCUS_FAIL_ADVISOR_COMPLETE)
2429 updatePlotPosition();
2431 if (completionState == Ekos::FOCUS_COMPLETE)
2435 emit redrawHFRPlot(polynomialFit.get(), currentPosition, currentHFR);
2437 appendLogText(
i18np(
"Focus procedure completed after %1 iteration.",
2438 "Focus procedure completed after %1 iterations.", plot_position.count()));
2440 setLastFocusTemperature();
2442 resetAdaptiveFocus(m_OpsFocusSettings->focusAdaptive->isChecked());
2446 qCInfo(KSTARS_EKOS_FOCUS) <<
"Autofocus values: position," << currentPosition <<
", temperature,"
2447 << m_LastSourceAutofocusTemperature <<
", filter," <<
filter()
2448 <<
", HFR," << currentHFR <<
", altitude," << m_LastSourceAutofocusAlt;
2450 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL)
2453 plot_position.append(currentPosition);
2454 plot_value.append(currentHFR);
2455 plot_weight.append(1.0);
2456 plot_outlier.append(
false);
2459 appendFocusLogText(
QString(
"%1, %2, %3, %4, %5\n")
2466 absTicksSpin->setValue(currentPosition);
2469 else if (canAbsMove && initialFocuserAbsPosition >= 0 && resetFocusIteration <= MAXIMUM_RESET_ITERATIONS &&
2470 m_RestartState != RESTART_ABORT)
2473 bool const retry_focusing = m_RestartState == RESTART_NONE &&
2474 (failCode == Ekos::FOCUS_FAIL_ADVISOR_RERUN || ++resetFocusIteration < MAXIMUM_RESET_ITERATIONS);
2479 m_RestartState = RESTART_NOW;
2488 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2500 m_RestartState = RESTART_ABORT;
2506 resetFocusIteration = 0;
2509 const bool autoFocusUsed = inAutoFocus;
2510 const bool inBuildOffsetsUsed = inBuildOffsets;
2513 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot)
2514 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
2517 int const settleTime = m_GuidingSuspended ? m_OpsFocusSettings->focusGuideSettleTime->value() : 0;
2520 stop(completionState);
2523 appendLogText(
i18n(
"Settling for %1s...", settleTime));
2525 QTimer::singleShot(settleTime * 1000,
this, [ &, settleTime, completionState, autoFocusUsed, inBuildOffsetsUsed, failCode,
2528 settle(completionState, autoFocusUsed, inBuildOffsetsUsed, failCode, failCodeInfo);
2531 appendLogText(
i18n(
"Settling complete."));
2535void Focus::resetFocuser()
2538 if (m_Focuser && m_Focuser->isConnected() && initialFocuserAbsPosition >= 0)
2541 if (currentPosition == initialFocuserAbsPosition)
2544 appendLogText(
i18n(
"Autofocus failed, moving back to initial focus position %1.", initialFocuserAbsPosition));
2545 changeFocus(initialFocuserAbsPosition - currentPosition);
2550void Focus::setCurrentMeasure()
2553 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus newFITS #" << starMeasureFrames.count() + 1 <<
": Current HFR " << currentHFR <<
2555 << (starSelected ? 1 : currentNumStars);
2558 if (appendMeasure(currentMeasure))
2563 else starMeasureFrames.clear();
2568 emit newHFR(currentHFR, currentPosition, inAutoFocus, opticalTrain());
2570 emit newHFR(currentHFR, -1, inAutoFocus, opticalTrain());
2573 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2574 if (m_StarMeasure == FOCUS_STAR_FWHM)
2575 FWHMOut->setText(
QString(
"%1").arg(currentFWHM * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2576 starsOut->setText(
QString(
"%1").arg(m_ImageData->getDetectedStars()));
2577 iterOut->setText(
QString(
"%1").arg(absIterations + 1));
2580 if (lastHFR == INVALID_STAR_MEASURE)
2581 appendLogText(
i18n(
"FITS received. No stars detected."));
2587 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && isVShapeSolution)
2589 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
2593 Edge selectedHFRStarHFR = m_ImageData->getSelectedHFRStar();
2600 if (starCenter.isNull() ==
false && (inAutoFocus || minimumRequiredHFR >= 0))
2603 starSelected =
true;
2604 starCenter.setX(qMax(0,
static_cast<int>(selectedHFRStarHFR.x)));
2605 starCenter.setY(qMax(0,
static_cast<int>(selectedHFRStarHFR.y)));
2607 syncTrackingBoxPosition();
2611 oneStar.
setZ(currentHFR);
2612 starsHFR.append(oneStar);
2617 QVector3D oneStar(starCenter.x(), starCenter.y(), currentHFR);
2618 starsHFR.append(oneStar);
2621 if (currentHFR > maxHFR)
2622 maxHFR = currentHFR;
2630 if (inFocusLoop || (inAutoFocus && ! isPositionBased()))
2632 int pos = plot_position.empty() ? 1 : plot_position.last() + 1;
2633 addPlotPosition(pos, currentHFR);
2639 QVector3D oneStar(starCenter.x(), starCenter.y(), INVALID_STAR_MEASURE);
2640 starsHFR.append(oneStar);
2645 m_FocusView->updateFrame();
2649 if (m_abInsOn && !inScanStartPos && !focusAdvisor->inFocusAdvisor())
2650 calculateAbInsData();
2654void Focus::saveFocusFrame()
2656 if (inAutoFocus && Options::focusLogging() && Options::saveFocusImages())
2667 if (focusAdvisor->inFocusAdvisor())
2668 prefix = focusAdvisor->getFocusFramePrefix();
2669 else if (inScanStartPos)
2670 prefix =
QString(
"_ssp_%1_%2").
arg(m_AFRun).
arg(absIterations + 1);
2671 else if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser)
2673 const int currentStep = linearFocuser->currentStep() + 1;
2679 prefix.
append(
QString(
"_%1").arg(starMeasureFrames.count()));
2685 m_ImageData->saveImage(filename);
2689void Focus::calculateAbInsData()
2691 ImageMosaicMask *mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().
get());
2693 auto stars = m_ImageData->getStarCenters();
2696 for (
int star = 0; star < stars.
count(); star++)
2698 const int x = stars[star]->x;
2699 const int y = stars[star]->y;
2700 for (
int tile = 0; tile < NUM_TILES; tile++)
2702 QRect thisTile = tiles[tile];
2705 tileStars[tile].append(stars[star]);
2712 for (
int tile = 0; tile < tileStars.count(); tile++)
2714 double measure, weight;
2715 std::vector<double> HFRs;
2717 switch (m_StarMeasure)
2719 case FOCUS_STAR_HFR:
2720 case FOCUS_STAR_HFR_ADJ:
2721 for (
int star = 0; star < tileStars[tile].count(); star++)
2723 HFRs.push_back(tileStars[tile][star]->HFR);
2725 measure = Mathematics::RobustStatistics::ComputeLocation(Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, HFRs, 2);
2726 weight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), HFRs);
2728 case FOCUS_STAR_FWHM:
2729 getFWHM(tileStars[tile], &measure, &weight);
2731 case FOCUS_STAR_NUM_STARS:
2732 measure = tileStars[tile].count();
2735 case FOCUS_STAR_FOURIER_POWER:
2736 getFourierPower(&measure, &weight, tile);
2738 case FOCUS_STAR_STDDEV:
2739 case FOCUS_STAR_SOBEL:
2740 case FOCUS_STAR_LAPLASSIAN:
2741 case FOCUS_STAR_CANNY:
2742 getBlurriness(m_StarMeasure, m_OpsFocusProcess->focusDenoise->isChecked(), &measure, &weight,
QRect(), tile);
2745 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to calculate Aberration Inspector data";
2749 m_abInsMeasure[tile].append(measure);
2750 m_abInsWeight[tile].append(weight);
2751 m_abInsNumStars[tile].append(tileStars[tile].count());
2753 if (!linearFocuser->isInFirstPass())
2758 int xAv = 0, yAv = 0;
2759 if (m_StarMeasure != FOCUS_STAR_FOURIER_POWER)
2761 QPoint tileCenter = tiles[tile].center();
2762 int xSum = 0.0, ySum = 0.0;
2763 for (
int star = 0; star < tileStars[tile].count(); star++)
2765 xSum += tileStars[tile][star]->x - tileCenter.
x();
2766 ySum += tileStars[tile][star]->y - tileCenter.
y();
2769 xAv = (tileStars[tile].count() <= 0) ? 0 : xSum / tileStars[tile].count();
2770 yAv = (tileStars[tile].count() <= 0) ? 0 : ySum / tileStars[tile].count();
2772 m_abInsTileCenterOffset.append(
QPoint(xAv, yAv));
2775 m_abInsPosition.append(currentPosition);
2778void Focus::setCaptureComplete()
2780 DarkLibrary::Instance()->disconnect(
this);
2783 syncTrackingBoxPosition();
2786 if (inFocusLoop ==
false)
2787 appendLogText(
i18n(
"Image received."));
2789 if (m_captureInProgress && inFocusLoop ==
false && inAutoFocus ==
false)
2790 m_Camera->setUploadMode(rememberUploadMode);
2792 if (m_RememberCameraFastExposure && inFocusLoop ==
false && inAutoFocus ==
false)
2794 m_RememberCameraFastExposure =
false;
2795 m_Camera->setFastExposureEnabled(
true);
2798 m_captureInProgress =
false;
2799 if (m_abortInProgress)
2803 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame results in " << __FUNCTION__;
2808 checkMosaicMaskLimits();
2811 emit newImage(m_FocusView);
2813 emit newStarPixmap(m_FocusView->getTrackingBoxPixmap(10));
2821 if (!isStarMeasureStarBased())
2822 starDetectionFinished();
2823 else if (inFocusLoop ==
false || (inFocusLoop && (m_FocusView->isTrackingBoxEnabled()
2824 || m_OpsFocusSettings->focusUseFullField->isChecked())))
2830void Focus::setHFRComplete()
2840 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
2843 int subBinX = 1, subBinY = 1;
2844 if (!targetChip->getBinning(&subBinX, &subBinY))
2845 qCDebug(KSTARS_EKOS_FOCUS) <<
"Warning: target chip is reporting no binning property, using 1x1.";
2848 if (m_OpsFocusSettings->focusSubFrame->isChecked() && !isStarMeasureStarBased() && !starSelected)
2850 appendLogText(
i18n(
"Capture complete. Select a region of interest."));
2852 syncTrackingBoxPosition();
2855 setState(Ekos::FOCUS_WAITING);
2858 waitStarSelectTimer.start();
2861 else if (m_OpsFocusSettings->focusSubFrame->isChecked() && isStarMeasureStarBased() && starCenter.isNull())
2868 int x = 0, y = 0, w = 0, h = 0;
2871 if (frameSettings.contains(targetChip))
2873 QVariantMap settings = frameSettings[targetChip];
2874 x = settings[
"x"].toInt();
2875 y = settings[
"y"].toInt();
2876 w = settings[
"w"].toInt();
2877 h = settings[
"h"].toInt();
2881 targetChip->getFrame(&x, &y, &w, &h);
2884 if (m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
2887 const Edge selectedHFRStar = m_ImageData->getSelectedHFRStar();
2889 if (selectedHFRStar.x == -1)
2891 appendLogText(
i18n(
"Failed to automatically select a star. Please select a star manually."));
2894 m_FocusView->setTrackingBox(
QRect(w - m_OpsFocusSettings->focusBoxSize->value() / (subBinX * 2),
2895 h - m_OpsFocusSettings->focusBoxSize->value() / (subBinY * 2),
2896 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
2897 m_FocusView->setTrackingBoxEnabled(
true);
2900 setState(Ekos::FOCUS_WAITING);
2903 waitStarSelectTimer.start();
2909 starCenter.setX(selectedHFRStar.x);
2910 starCenter.setY(selectedHFRStar.y);
2911 starCenter.setZ(subBinX);
2912 starSelected =
true;
2913 syncTrackingBoxPosition();
2916 if (subFramed ==
false && isFocusSubFrameEnabled() && m_OpsFocusSettings->focusSubFrame->isChecked())
2918 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
2919 int subX = (selectedHFRStar.x - offset) * subBinX;
2920 int subY = (selectedHFRStar.y - offset) * subBinY;
2921 int subW = offset * 2 * subBinX;
2922 int subH = offset * 2 * subBinY;
2924 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2925 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2932 if ((subW + subX) > maxW)
2934 if ((subH + subY) > maxH)
2939 QVariantMap settings = frameSettings[targetChip];
2940 settings[
"x"] = subX;
2941 settings[
"y"] = subY;
2942 settings[
"w"] = subW;
2943 settings[
"h"] = subH;
2944 settings[
"binx"] = subBinX;
2945 settings[
"biny"] = subBinY;
2947 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << subX <<
"Y:" << subY <<
"W:" << subW <<
"H:" << subH <<
"binX:" <<
2948 subBinX <<
"binY:" << subBinY;
2952 frameSettings[targetChip] = settings;
2955 starCenter.setX(subW / (2 * subBinX));
2956 starCenter.setY(subH / (2 * subBinY));
2957 starCenter.setZ(subBinX);
2961 m_FocusView->setFirstLoad(
true);
2970 starCenter.setX(selectedHFRStar.x);
2971 starCenter.setY(selectedHFRStar.y);
2972 starCenter.setZ(subBinX);
2985 appendLogText(
i18n(
"Capture complete. Select a star to focus."));
2987 starSelected =
false;
2991 int subBinX = 1, subBinY = 1;
2992 targetChip->getBinning(&subBinX, &subBinY);
2994 m_FocusView->setTrackingBox(
QRect((w - m_OpsFocusSettings->focusBoxSize->value()) / (subBinX * 2),
2995 (h - m_OpsFocusSettings->focusBoxSize->value()) / (2 * subBinY),
2996 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
2997 m_FocusView->setTrackingBoxEnabled(
true);
3000 setState(Ekos::FOCUS_WAITING);
3003 waitStarSelectTimer.start();
3009 if (minimumRequiredHFR >= 0)
3012 if (currentHFR == INVALID_STAR_MEASURE)
3014 if (noStarCount++ < MAX_RECAPTURE_RETRIES)
3016 appendLogText(
i18n(
"No stars detected while testing HFR, capturing again..."));
3018 if (noStarCount == MAX_RECAPTURE_RETRIES)
3027 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3032 else if (currentHFR > minimumRequiredHFR)
3034 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is above required minimum HFR:" << minimumRequiredHFR <<
3035 ". Starting AutoFocus...";
3038 minimumRequiredHFR = INVALID_STAR_MEASURE;
3039 runAutoFocus(AutofocusReason::FOCUS_HFR_CHECK, reasonInfo);
3044 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is below required minimum HFR:" << minimumRequiredHFR <<
3045 ". Autofocus successful.";
3046 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3054 if (inAutoFocus ==
false)
3058 if (state() != Ekos::FOCUS_IDLE)
3059 setState(Ekos::FOCUS_IDLE);
3066 if (state() != Ekos::FOCUS_PROGRESS)
3067 setState(Ekos::FOCUS_PROGRESS);
3072 else if(focusAdvisor->inFocusAdvisor())
3073 focusAdvisor->control();
3074 else if(m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3076 else if (canAbsMove || canRelMove)
3084QString Focus::getyAxisLabel(StarMeasure starMeasure)
3087 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3091 switch (starMeasure)
3093 case FOCUS_STAR_HFR:
3095 case FOCUS_STAR_HFR_ADJ:
3097 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3099 case FOCUS_STAR_FWHM:
3101 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3103 case FOCUS_STAR_NUM_STARS:
3106 case FOCUS_STAR_FOURIER_POWER:
3107 str =
"Fourier Power";
3109 case FOCUS_STAR_STDDEV:
3112 case FOCUS_STAR_SOBEL:
3113 str =
"Sobel Factor";
3115 case FOCUS_STAR_LAPLASSIAN:
3116 str =
"Laplassian Factor";
3118 case FOCUS_STAR_CANNY:
3119 str =
"Canny Factor";
3128void Focus::clearDataPoints()
3131 polynomialFit.reset();
3132 plot_position.
clear();
3134 plot_weight.clear();
3135 plot_outlier.clear();
3136 isVShapeSolution =
false;
3137 m_abInsPosition.clear();
3138 m_abInsTileCenterOffset.clear();
3139 if (m_abInsMeasure.count() != NUM_TILES)
3141 m_abInsMeasure.resize(NUM_TILES);
3142 m_abInsWeight.resize(NUM_TILES);
3143 m_abInsNumStars.resize(NUM_TILES);
3147 for (
int i = 0; i < m_abInsMeasure.count(); i++)
3149 m_abInsMeasure[i].clear();
3150 m_abInsWeight[i].clear();
3151 m_abInsNumStars[i].clear();
3155 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3156 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(),
3157 inFocusLoop ==
false && isPositionBased());
3160bool Focus::autoFocusChecks()
3162 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3164 appendLogText(
i18n(
"Autofocus failed: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3165 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3170 if (isStarMeasureStarBased() && currentHFR == INVALID_STAR_MEASURE)
3172 if (noStarCount < MAX_RECAPTURE_RETRIES)
3175 appendLogText(
i18n(
"No stars detected, capturing again..."));
3179 else if (m_FocusAlgorithm == FOCUS_LINEAR)
3181 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
3184 else if(!m_OpsFocusProcess->focusDonut->isChecked())
3187 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
3188 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3198void Focus::plotLinearFocus()
3207 linearFocuser->getMeasurements(&positions, &values, &weights);
3208 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3215 bool incrementalChange =
false;
3216 if (positions.
size() > 1 && positions.
size() == lastPositions.
size() + 1)
3219 for (
int i = 0; i < positions.
size() - 1; ++i)
3220 if (positions[i] != lastPositions[i] || values[i] != lastValues[i])
3225 incrementalChange =
ok;
3227 lastPositions = positions;
3228 lastValues = values;
3230 const bool outlier =
false;
3231 if (incrementalChange)
3232 emit newHFRPlotPosition(
static_cast<double>(positions.
last()), values.
last(), (pow(weights.
last(), -0.5)),
3233 outlier, params.initialStepSize, plt);
3236 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3237 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, params.useWeights, plt);
3238 for (
int i = 0; i < positions.
size(); ++i)
3239 emit newHFRPlotPosition(
static_cast<double>(positions[i]), values[i], (pow(weights.
last(), -0.5)),
3240 outlier, params.initialStepSize, plt);
3244 if (values.
size() > 3)
3250 double minPosition, minValue;
3251 double searchMin = std::max(params.minPositionAllowed, params.startPosition - params.maxTravel);
3252 double searchMax = std::min(params.maxPositionAllowed, params.startPosition + params.maxTravel);
3254 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3255 if (m_FocusAlgorithm == FOCUS_LINEAR || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3259 polynomialFit.reset(
new PolynomialFit(2, pass1Positions, pass1Values));
3261 if (polynomialFit->findMinimum(params.startPosition, searchMin, searchMax, &minPosition, &minValue))
3263 emit drawPolynomial(polynomialFit.get(),
true,
true, plt);
3267 if (linearFocuser->isDone())
3268 emit minimumFound(-1, -1, plt);
3270 emit minimumFound(minPosition, minValue, plt);
3275 emit drawPolynomial(polynomialFit.get(),
false,
false, plt);
3276 emit minimumFound(-1, -1, plt);
3282 if (curveFitting->findMinMax(params.startPosition, searchMin, searchMax, &minPosition, &minValue, params.curveFit,
3283 params.optimisationDirection))
3285 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3286 emit drawCurve(curveFitting.get(),
true,
true, plt);
3289 emit minimumFound(minPosition, minValue, plt);
3294 emit drawCurve(curveFitting.get(),
false,
false, plt);
3295 emit minimumFound(-1, -1, plt);
3301 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
3303 emit setTitle(linearFocuser->getTextStatus(R2));
3305 if (!plt) HFRPlot->replot();
3309CurveFitting::FittingGoal Focus::getGoal(
int numSteps)
3312 if (m_FocusWalk == FOCUS_WALK_CLASSIC)
3313 return CurveFitting::FittingGoal::STANDARD;
3316 return (numSteps >= m_OpsFocusMechanics->focusNumSteps->value()) ? CurveFitting::FittingGoal::BEST :
3317 CurveFitting::FittingGoal::STANDARD;
3323void Focus::plotLinearFinalUpdates()
3326 if (!m_OpsFocusProcess->focusRefineCurveFit->isChecked())
3329 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3330 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3332 emit finalUpdates(linearFocuser->getTextStatus(R2), plt);
3342 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3343 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3345 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3346 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(), plt);
3348 for (
int i = 0; i < pass1Positions.
size(); ++i)
3349 emit newHFRPlotPosition(
static_cast<double>(pass1Positions[i]), pass1Values[i], (pow(pass1Weights[i], -0.5)),
3350 pass1Outliers[i], params.initialStepSize, plt);
3352 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3353 emit drawCurve(curveFitting.get(),
true,
true,
false);
3356 emit minimumFound(linearFocuser->solution(), linearFocuser->solutionValue(), plt);
3358 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3359 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3361 emit setTitle(linearFocuser->getTextStatus(R2), plt);
3365void Focus::startAberrationInspector()
3367#ifdef HAVE_DATAVISUALIZATION
3369 AberrationInspector::abInsData data;
3371 ImageMosaicMask *mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().
get());
3374 appendLogText(
i18n(
"Unable to launch Aberration Inspector run %1...", m_abInsRun));
3379 data.run = ++m_abInsRun;
3380 data.curveFit = m_CurveFit;
3381 data.useWeights = m_OpsFocusProcess->focusUseWeights->isChecked();
3382 data.optDir = m_OptDir;
3383 data.sensorWidth = m_CcdWidth;
3384 data.sensorHeight = m_CcdHeight;
3385 data.pixelSize = m_CcdPixelSizeX;
3386 data.tileWidth = mosaicmask->tiles()[0].width();
3387 data.focuserStepMicrons = m_CFZUI->focusCFZStepSize->value();
3388 data.yAxisLabel = getyAxisLabel(m_StarMeasure);
3389 data.starUnits = getStarUnits(m_StarMeasure, m_StarUnits);
3390 data.cfzSteps = m_cfzSteps;
3391 data.isPositionBased = isPositionBased();
3394 appendLogText(
i18n(
"Launching Aberration Inspector run %1...", m_abInsRun));
3396 m_abInsNumStars, m_abInsTileCenterOffset));
3403bool Focus::initScanStartPos(
const bool force,
const int initialPosition)
3407 if (!m_OpsFocusProcess->focusScanStartPos->isChecked())
3410 if (!m_OpsFocusProcess->focusScanAlwaysOn->isChecked() && !m_AFRerun)
3415 inScanStartPos =
true;
3416 initialFocuserAbsPosition = initialPosition;
3417 m_scanMeasure.clear();
3418 m_scanPosition.clear();
3420 appendLogText(
i18n(
"Starting scan for initial focuser position."));
3421 emit setTitle(
QString(
i18n(
"Scanning for starting position...")),
true);
3423 if (!changeFocus(initialPosition - currentPosition))
3424 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3429void Focus::scanStartPos()
3432 if (currentHFR == INVALID_STAR_MEASURE)
3434 if (noStarCount < MAX_RECAPTURE_RETRIES)
3437 appendLogText(
i18n(
"No stars detected, capturing again..."));
3443 appendLogText(
i18n(
"Failed to detect any stars. Aborting..."));
3444 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3450 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3452 appendLogText(
i18n(
"Scan Start Pos: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3453 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3458 m_scanPosition.push_back(currentPosition);
3459 m_scanMeasure.push_back(currentMeasure);
3462 const int step = m_scanPosition.size();
3463 const int maxSteps = m_OpsFocusProcess->focusScanDatapoints->value();
3464 const int stepSize = m_OpsFocusMechanics->focusTicks->value() * m_OpsFocusProcess->focusScanStepSizeFactor->value();
3465 emit newHFRPlotPosition(
static_cast<double>(currentPosition), currentMeasure, pow(currentWeight, -0.5),
false, stepSize,
3467 if (step < maxSteps)
3470 emit setTitle(
QString(
i18n(
"Scanning for starting position %1/%2", step, maxSteps)),
true);
3471 deltaPos = step * stepSize * std::pow(-1, step + 1);
3476 auto it = std::min_element(std::begin(m_scanMeasure), std::end(m_scanMeasure));
3477 auto min = std::distance(std::begin(m_scanMeasure), it);
3478 if (min >= m_OpsFocusProcess->focusScanDatapoints->value() - 2)
3481 deltaPos = m_scanPosition[min] - currentPosition;
3482 m_scanPosition.clear();
3483 m_scanMeasure.clear();
3484 emit setTitle(
QString(
i18n(
"No scan minimum - widening search...")),
true);
3489 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
3490 focusAdvisor->setInFocusAdvisor(
false);
3492 const int initialPosition = m_scanPosition[min];
3493 setupLinearFocuser(initialPosition);
3494 inScanStartPos =
false;
3496 deltaPos = linearRequestedPosition - currentPosition;
3497 emit setTitle(
QString(
i18n(
"Scan Start Position %1 Found", initialPosition)),
true);
3498 appendLogText(
i18n(
"Scan Start Position %1 found", initialPosition));
3501 if (!changeFocus(deltaPos))
3502 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3505void Focus::autoFocusLinear()
3507 if (!autoFocusChecks())
3510 if (!canAbsMove && !canRelMove && canTimerMove)
3513 if (linearRequestedPosition != currentPosition)
3516 qCDebug(KSTARS_EKOS_FOCUS) <<
"Linear: warning, changing position " << currentPosition <<
" to "
3517 << linearRequestedPosition;
3519 currentPosition = linearRequestedPosition;
3524 bool useFocusStarsHFR = m_OpsFocusSettings->focusUseFullField->isChecked()
3525 && m_OpsFocusProcess->focusFramesCount->value() == 1;
3526 auto focusStars = useFocusStarsHFR || (m_FocusAlgorithm == FOCUS_LINEAR1PASS) ? &(m_ImageData->getStarCenters()) :
nullptr;
3528 linearRequestedPosition = linearFocuser->newMeasurement(currentPosition, currentMeasure, currentWeight, focusStars);
3529 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser->isDone() && linearFocuser->solution() != -1)
3532 plotLinearFinalUpdates();
3534 startAberrationInspector();
3540 if (linearFocuser->isDone())
3542 if (linearFocuser->solution() != -1)
3545 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
3547 if (focusAdvisor->analyseAF())
3548 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_ADVISOR_RERUN,
"",
false);
3550 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3552 else if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3554 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3555 else if (R2 >= m_OpsFocusProcess->focusR2Limit->value())
3559 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Linear Curve Fit check passed R2=%1 focusR2Limit=%2").
arg(R2).
arg(
3560 m_OpsFocusProcess->focusR2Limit->value());
3561 completeFocusProcedure(Ekos::FOCUS_COMPLETE, FOCUS_FAIL_NONE,
"",
false);
3564 else if (R2Retries == 0)
3567 appendLogText(
i18n(
"Curve Fit check failed R2=%1 focusR2Limit=%2 retrying...", R2,
3568 m_OpsFocusProcess->focusR2Limit->value()));
3571 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_R2, failCodeInfo,
false);
3577 appendLogText(
i18n(
"Curve Fit check failed again R2=%1 focusR2Limit=%2 but continuing...", R2,
3578 m_OpsFocusProcess->focusR2Limit->value()));
3579 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3585 qCDebug(KSTARS_EKOS_FOCUS) << linearFocuser->doneReason();
3586 AutofocusFailReason failCode = linearFocuser->getFailCode();
3587 appendLogText(
i18n(
"Linear autofocus algorithm aborted: %1", AutofocusFailReasonStr[failCode]));
3588 completeFocusProcedure(Ekos::FOCUS_ABORTED, failCode,
"",
false);
3594 const int delta = linearRequestedPosition - currentPosition;
3596 if (!changeFocus(delta))
3597 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE,
"",
false);
3603void Focus::autoFocusAbs()
3607 static int minHFRPos = 0, focusOutLimit = 0, focusInLimit = 0, lastHFRPos = 0, fluctuations = 0;
3608 static double minHFR = 0, lastDelta = 0;
3609 double targetPosition = 0;
3610 bool ignoreLimitedDelta =
false;
3612 QString deltaTxt =
QString(
"%1").
arg(fabs(currentHFR - minHFR) * 100.0, 0,
'g', 3);
3615 qCDebug(KSTARS_EKOS_FOCUS) <<
"===============================";
3616 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR: " << currentHFR <<
" Current Position: " << currentPosition;
3617 qCDebug(KSTARS_EKOS_FOCUS) <<
"Last minHFR: " << minHFR <<
" Last MinHFR Pos: " << minHFRPos;
3618 qCDebug(KSTARS_EKOS_FOCUS) <<
"Delta: " << deltaTxt <<
"%";
3619 qCDebug(KSTARS_EKOS_FOCUS) <<
"========================================";
3622 appendLogText(
i18n(
"FITS received. HFR %1 @ %2. Delta (%3%)", HFRText, currentPosition, deltaTxt));
3624 appendLogText(
i18n(
"FITS received. HFR %1 @ %2.", HFRText, currentPosition));
3626 if (!autoFocusChecks())
3629 addPlotPosition(currentPosition, currentHFR);
3631 switch (m_LastFocusDirection)
3634 lastHFR = currentHFR;
3635 initialFocuserAbsPosition = currentPosition;
3636 minHFR = currentHFR;
3637 minHFRPos = currentPosition;
3647 if (absMotionMax < currentPosition + pulseDuration)
3649 if (currentPosition < absMotionMax)
3651 pulseDuration = absMotionMax - currentPosition;
3656 m_LastFocusDirection = FOCUS_IN;
3659 else if (currentPosition + pulseDuration < absMotionMin)
3661 if (absMotionMin < currentPosition)
3663 pulseDuration = currentPosition - absMotionMin;
3668 m_LastFocusDirection = FOCUS_OUT;
3672 m_LastFocusDirection = (pulseDuration > 0) ? FOCUS_OUT : FOCUS_IN;
3673 if (!changeFocus(pulseDuration,
false))
3674 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3680 if (reverseDir && focusInLimit && focusOutLimit &&
3681 fabs(currentHFR - minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
3683 if (absIterations <= 2)
3685 QString message =
i18n(
"Change in HFR is too small. Try increasing the step size or decreasing the tolerance.");
3686 appendLogText(message);
3687 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3688 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_SMALL_HFR);
3690 else if (noStarCount > 0)
3692 QString message =
i18n(
"Failed to detect focus star in frame. Capture and select a focus star.");
3693 appendLogText(message);
3694 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3695 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3699 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3703 else if (currentHFR < lastHFR)
3706 if (HFRInc >= 1 && m_LastFocusDirection == FOCUS_OUT && lastHFRPos < focusInLimit && fabs(currentHFR - lastHFR) > 0.1)
3708 focusInLimit = lastHFRPos;
3709 qCDebug(KSTARS_EKOS_FOCUS) <<
"New FocusInLimit " << focusInLimit;
3711 else if (HFRInc >= 1 && m_LastFocusDirection == FOCUS_IN && lastHFRPos > focusOutLimit &&
3712 fabs(currentHFR - lastHFR) > 0.1)
3714 focusOutLimit = lastHFRPos;
3715 qCDebug(KSTARS_EKOS_FOCUS) <<
"New FocusOutLimit " << focusOutLimit;
3718 double factor = std::max(1.0, HFRDec / 2.0);
3719 if (m_LastFocusDirection == FOCUS_IN)
3720 targetPosition = currentPosition - (pulseDuration * factor);
3722 targetPosition = currentPosition + (pulseDuration * factor);
3724 qCDebug(KSTARS_EKOS_FOCUS) <<
"current Position" << currentPosition <<
" targetPosition " << targetPosition;
3726 lastHFR = currentHFR;
3729 if (lastHFR < minHFR)
3732 minHFRPos = currentPosition;
3733 qCDebug(KSTARS_EKOS_FOCUS) <<
"new minHFR " << minHFR <<
" @ position " << minHFRPos;
3736 lastHFRPos = currentPosition;
3743 if (plot_position.count() >= 2)
3745 plot_position.remove(plot_position.count() - 2);
3746 plot_value.remove(plot_value.count() - 2);
3760 lastHFR = currentHFR;
3761 lastHFRPos = currentPosition;
3770 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus is moving away from optimal HFR.";
3773 if (m_LastFocusDirection == FOCUS_IN)
3775 focusInLimit = currentPosition;
3776 qCDebug(KSTARS_EKOS_FOCUS) <<
"Setting focus IN limit to " << focusInLimit;
3780 focusOutLimit = currentPosition;
3781 qCDebug(KSTARS_EKOS_FOCUS) <<
"Setting focus OUT limit to " << focusOutLimit;
3784 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot_position.count() > 4)
3786 polynomialFit.reset(
new PolynomialFit(2, 5, plot_position, plot_value));
3787 double a = *std::min_element(plot_position.constBegin(), plot_position.constEnd());
3788 double b = *std::max_element(plot_position.constBegin(), plot_position.constEnd());
3789 double min_position = 0, min_hfr = 0;
3790 isVShapeSolution = polynomialFit->findMinimum(minHFRPos, a, b, &min_position, &min_hfr);
3791 qCDebug(KSTARS_EKOS_FOCUS) <<
"Found Minimum?" << (isVShapeSolution ?
"Yes" :
"No");
3792 if (isVShapeSolution)
3794 ignoreLimitedDelta =
true;
3795 qCDebug(KSTARS_EKOS_FOCUS) <<
"Minimum Solution:" << min_hfr <<
"@" << min_position;
3796 targetPosition = round(min_position);
3797 appendLogText(
i18n(
"Found polynomial solution @ %1",
QString::number(min_position,
'f', 0)));
3799 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
3800 emit minimumFound(min_position, min_hfr);
3804 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
false);
3813 if (std::abs(lastDelta) > 0)
3814 targetPosition = currentPosition + lastDelta;
3816 targetPosition = currentPosition + pulseDuration;
3818 else if (isVShapeSolution ==
false)
3820 ignoreLimitedDelta =
true;
3822 if (m_LastFocusDirection == FOCUS_OUT)
3823 targetPosition = minHFRPos - pulseDuration / 2;
3825 targetPosition = minHFRPos + pulseDuration / 2;
3828 qCDebug(KSTARS_EKOS_FOCUS) <<
"new targetPosition " << targetPosition;
3832 if (focusInLimit != 0 && m_LastFocusDirection == FOCUS_IN && targetPosition < focusInLimit)
3834 targetPosition = focusInLimit;
3835 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus in limit " << targetPosition;
3837 else if (focusOutLimit != 0 && m_LastFocusDirection == FOCUS_OUT && targetPosition > focusOutLimit)
3839 targetPosition = focusOutLimit;
3840 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus out limit " << targetPosition;
3844 if (targetPosition < absMotionMin)
3845 targetPosition = absMotionMin;
3846 else if (targetPosition > absMotionMax)
3847 targetPosition = absMotionMax;
3850 if (targetPosition == currentPosition)
3854 if (targetPosition == minHFRPos || isVShapeSolution)
3856 appendLogText(
"Stopping at minimum recorded HFR position.");
3857 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3861 QString message =
i18n(
"Focuser cannot move further, device limits reached. Autofocus aborted.");
3862 appendLogText(message);
3863 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3864 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3870 if (fluctuations >= MAXIMUM_FLUCTUATIONS)
3872 QString message =
i18n(
"Unstable fluctuations. Try increasing initial step size or exposure time.");
3873 appendLogText(message);
3874 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3875 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FLUCTUATIONS);
3880 if (focusOutLimit && focusOutLimit == focusInLimit)
3882 QString message =
i18n(
"Deadlock reached. Please try again with different settings.");
3883 appendLogText(message);
3884 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3885 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_DEADLOCK);
3890 if (fabs(targetPosition - initialFocuserAbsPosition) > m_OpsFocusMechanics->focusMaxTravel->value())
3892 int minTravelLimit = qMax(0.0, initialFocuserAbsPosition - m_OpsFocusMechanics->focusMaxTravel->value());
3893 int maxTravelLimit = qMin(absMotionMax, initialFocuserAbsPosition + m_OpsFocusMechanics->focusMaxTravel->value());
3897 if (fabs(currentPosition - minTravelLimit) > 10 && targetPosition < minTravelLimit)
3899 targetPosition = minTravelLimit;
3902 else if (fabs(currentPosition - maxTravelLimit) > 10 && targetPosition > maxTravelLimit)
3904 targetPosition = maxTravelLimit;
3908 qCDebug(KSTARS_EKOS_FOCUS) <<
"targetPosition (" << targetPosition <<
") - initHFRAbsPos ("
3909 << initialFocuserAbsPosition <<
") exceeds maxTravel distance of " << m_OpsFocusMechanics->focusMaxTravel->value();
3911 QString message =
i18n(
"Maximum travel limit reached. Autofocus aborted.");
3912 appendLogText(message);
3913 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3914 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3920 lastDelta = (targetPosition - currentPosition);
3922 qCDebug(KSTARS_EKOS_FOCUS) <<
"delta (targetPosition - currentPosition) " << lastDelta;
3925 if (ignoreLimitedDelta ==
false)
3927 double limitedDelta = qMax(-1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(),
3928 qMin(1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(), lastDelta));
3929 if (std::fabs(limitedDelta - lastDelta) > 0)
3931 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limited delta to maximum permitted single step " <<
3932 m_OpsFocusMechanics->focusMaxSingleStep->value();
3933 lastDelta = limitedDelta;
3937 m_LastFocusDirection = (lastDelta > 0) ? FOCUS_OUT : FOCUS_IN;
3938 if (!changeFocus(lastDelta,
false))
3939 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3945void Focus::addPlotPosition(
int pos,
double value,
bool plot)
3947 plot_position.append(pos);
3948 plot_value.append(value);
3950 emit newHFRPlotPosition(
static_cast<double>(pos), value, 1.0,
false, pulseDuration);
3956void Focus::updatePlotPosition()
3958 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3961 if (inScanStartPos || focusAdvisor->inFocusAdvisor())
3964 plot_position.clear();
3966 plot_weight.clear();
3967 plot_outlier.clear();
3971 linearFocuser->getPass1Measurements(&positions, &plot_value, &plot_weight, &plot_outlier);
3972 plot_position.clear();
3973 for (
int i = 0; i < positions.
count(); i++)
3974 plot_position.append(positions[i]);
3977 if (linearFocuser && linearFocuser->isDone() && linearFocuser->solution() != -1)
3979 plot_position.append(linearFocuser->solution());
3980 plot_value.append(linearFocuser->solutionValue());
3981 plot_weight.append(linearFocuser->solutionWeight());
3982 plot_outlier.append(
false);
3986 else if (m_FocusAlgorithm == FOCUS_LINEAR)
3989 linearFocuser->getMeasurements(&positions, &plot_value, &plot_weight);
3990 plot_position.
clear();
3991 plot_outlier.clear();
3992 for (
int i = 0; i < positions.
count(); i++)
3994 plot_position.append(positions[i]);
3996 plot_outlier.append(
false);
4002 for (
int i = 0; i < plot_position.count(); i++)
4004 plot_weight.append(1.0);
4005 plot_outlier.append(
false);
4010void Focus::autoFocusRel()
4012 static int noStarCount = 0;
4013 static double minHFR = 1e6;
4014 QString deltaTxt =
QString(
"%1").
arg(fabs(currentHFR - minHFR) * 100.0, 0,
'g', 2);
4018 appendLogText(
i18n(
"FITS received. HFR %1. Delta (%2%) Min HFR (%3)", HFRText, deltaTxt, minHFRText));
4020 if (pulseDuration <= MINIMUM_PULSE_TIMER)
4022 appendLogText(
i18n(
"Autofocus failed to reach proper focus. Try adjusting the tolerance value."));
4023 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_TOLERANCE);
4028 if (currentHFR == INVALID_STAR_MEASURE)
4030 if (noStarCount < MAX_RECAPTURE_RETRIES)
4033 appendLogText(
i18n(
"No stars detected, capturing again..."));
4037 else if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4039 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
4042 else if(!m_OpsFocusProcess->focusDonut->isChecked())
4045 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
4046 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
4053 switch (m_LastFocusDirection)
4056 lastHFR = currentHFR;
4058 m_LastFocusDirection = FOCUS_IN;
4059 changeFocus(-pulseDuration,
false);
4064 if (fabs(currentHFR - minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
4066 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
4068 else if (currentHFR < lastHFR)
4070 if (currentHFR < minHFR)
4071 minHFR = currentHFR;
4073 lastHFR = currentHFR;
4074 changeFocus(m_LastFocusDirection == FOCUS_IN ? -pulseDuration : pulseDuration,
false);
4081 lastHFR = currentHFR;
4085 pulseDuration *= 0.75;
4087 if (!changeFocus(m_LastFocusDirection == FOCUS_IN ? pulseDuration : -pulseDuration,
false))
4088 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4091 m_LastFocusDirection = (m_LastFocusDirection == FOCUS_IN) ? FOCUS_OUT : FOCUS_IN;
4097void Focus::autoFocusProcessPositionChange(IPState state)
4099 if (state == IPS_OK)
4105 if (focuserAdditionalMovement > 0)
4107 int temp = focuserAdditionalMovement;
4108 focuserAdditionalMovement = 0;
4110 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Undoing overscan extension. Moving back in by %1 ticks in %2s")
4111 .
arg(temp).
arg(m_OpsFocusMechanics->focusOverscanDelay->value());
4113 QTimer::singleShot(m_OpsFocusMechanics->focusOverscanDelay->value() * 1000,
this, [
this, temp]()
4115 if (!changeFocus(-temp, focuserAdditionalMovementUpdateDir))
4117 appendLogText(i18n(
"Focuser error, check INDI panel."));
4118 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4122 else if (inAutoFocus)
4125 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4126 if (abs(linearRequestedPosition - currentPosition) > m_OpsFocusMechanics->focusTicks->value())
4127 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Focus positioning error: requested position %1, current position %2")
4128 .
arg(linearRequestedPosition).
arg(currentPosition);
4130 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Focus position reached at %1, starting capture in %2 seconds.").
arg(
4131 currentPosition).
arg(m_OpsFocusMechanics->focusSettleTime->value());
4133 if (m_OpsFocusProcess->focusDonut->isChecked())
4134 donutTimeDilation();
4135 capture(m_OpsFocusMechanics->focusSettleTime->value());
4138 else if (state == IPS_ALERT)
4140 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4141 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
4144 qCDebug(KSTARS_EKOS_FOCUS) <<
4145 QString(
"autoFocusProcessPositionChange called with state %1 (%2), focuserAdditionalMovement=%3, inAutoFocus=%4, m_captureInProgress=%5, currentPosition=%6")
4146 .
arg(state).
arg(pstateStr(state)).
arg(focuserAdditionalMovement).
arg(inAutoFocus).
arg(m_captureInProgress)
4147 .
arg(currentPosition);
4151void Focus::donutTimeDilation()
4153 if (m_OpsFocusProcess->focusTimeDilation->value() == 1.0 || inScanStartPos || focusAdvisor->inFocusAdvisor())
4157 const double centre = (m_OpsFocusMechanics->focusNumSteps->value() + 1.0) / 2.0;
4159 const int currentStep = linearFocuser->currentStep() + 1;
4161 if (currentStep <= m_OpsFocusMechanics->focusNumSteps->value())
4162 distance = std::abs(centre - currentStep);
4166 double multiplier =
distance / (centre - 1.0) * m_OpsFocusProcess->focusTimeDilation->value();
4167 multiplier = std::max(multiplier, 1.0);
4168 const double exposure = multiplier * m_donutOrigExposure;
4169 focusExposure->setValue(exposure);
4170 qCDebug(KSTARS_EKOS_FOCUS) <<
"Donut time dilation for point " << currentStep <<
" from " << m_donutOrigExposure <<
" to "
4175void Focus::updateProperty(INDI::Property prop)
4177 if (m_Focuser ==
nullptr || prop.getType() != INDI_NUMBER || prop.getDeviceName() != m_Focuser->getDeviceName())
4180 auto nvp = prop.getNumber();
4186 if (nvp->isNameMatch(
"FOCUS_BACKLASH_STEPS"))
4188 m_OpsFocusMechanics->focusBacklash->setValue(nvp->np[0].value);
4192 if (nvp->isNameMatch(
"ABS_FOCUS_POSITION"))
4197 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4199 if (m_DebugFocuserCounter == 14)
4200 m_DebugFocuserCounter = 0;
4201 appendLogText(
i18n(
"Simulate focuser comms failure..."));
4206 m_FocusMotionTimer.stop();
4207 INumber *pos = IUFindNumber(nvp,
"FOCUS_ABSOLUTE_POSITION");
4208 IPState newState = nvp->s;
4213 int newPosition =
static_cast<int>(pos->value);
4218 if (currentPosition == newPosition && currentPositionState == newState)
4220 if (logPositionAndState)
4222 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focuser position " << currentPosition <<
" and state:"
4223 << pstateStr(currentPositionState) <<
" unchanged";
4224 logPositionAndState =
false;
4230 logPositionAndState =
true;
4233 currentPositionState = newState;
4235 if (currentPosition != newPosition)
4237 currentPosition = newPosition;
4238 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abs Focuser position changed to " << currentPosition <<
"State:" << pstateStr(
4239 currentPositionState);
4241 emit absolutePositionChanged(currentPosition);
4245 qCDebug(KSTARS_EKOS_FOCUS) <<
"Can't access FOCUS_ABSOLUTE_POSITION. Current state:"
4246 << pstateStr(currentPositionState) <<
" New state:" << pstateStr(newState);
4248 if (newState != IPS_OK)
4250 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
4254 qCDebug(KSTARS_EKOS_FOCUS) <<
"Restarting focus motion timer, state " << pstateStr(newState);
4255 m_FocusMotionTimer.start();
4261 if (focuserAdditionalMovement == 0)
4266 if (focuserAdditionalMovement == 0)
4268 inAdjustFocus =
false;
4269 emit focusPositionAdjusted();
4274 if (adaptFocus->inAdaptiveFocus())
4276 if (focuserAdditionalMovement == 0)
4278 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4283 if (m_RestartState == RESTART_NOW && status() != Ekos::FOCUS_ABORTED)
4285 if (focuserAdditionalMovement == 0)
4287 m_RestartState = RESTART_NONE;
4289 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4290 adaptFocus->setInAdaptiveFocus(
false);
4291 focusAdvisor->setInFocusAdvisor(
false);
4292 appendLogText(
i18n(
"Restarting autofocus process..."));
4293 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4297 else if (m_RestartState == RESTART_ABORT && focuserAdditionalMovement == 0)
4303 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4304 m_RestartState = RESTART_NONE;
4305 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4306 adaptFocus->setInAdaptiveFocus(
false);
4307 focusAdvisor->setInFocusAdvisor(
false);
4313 autoFocusProcessPositionChange(newState);
4314 else if (newState == IPS_ALERT)
4315 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4322 if (nvp->isNameMatch(
"manualfocusdrive"))
4327 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4329 if (m_DebugFocuserCounter == 14)
4330 m_DebugFocuserCounter = 0;
4331 appendLogText(
i18n(
"Simulate focuser comms failure..."));
4336 m_FocusMotionTimer.stop();
4338 INumber *pos = IUFindNumber(nvp,
"manualfocusdrive");
4339 IPState newState = nvp->s;
4340 if (pos && newState == IPS_OK)
4342 if (focuserAdditionalMovement == 0)
4345 currentPosition += pos->value;
4346 absTicksLabel->setText(
QString::number(
static_cast<int>(currentPosition)));
4347 emit absolutePositionChanged(currentPosition);
4350 if (inAdjustFocus && newState == IPS_OK)
4352 if (focuserAdditionalMovement == 0)
4354 inAdjustFocus =
false;
4355 emit focusPositionAdjusted();
4360 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4362 if (focuserAdditionalMovement == 0)
4364 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4370 if (m_RestartState == RESTART_NOW && newState == IPS_OK && status() != Ekos::FOCUS_ABORTED)
4372 if (focuserAdditionalMovement == 0)
4374 m_RestartState = RESTART_NONE;
4376 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4377 adaptFocus->setInAdaptiveFocus(
false);
4378 focusAdvisor->setInFocusAdvisor(
false);
4379 appendLogText(
i18n(
"Restarting autofocus process..."));
4380 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4384 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4387 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4388 m_RestartState = RESTART_NONE;
4389 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4390 adaptFocus->setInAdaptiveFocus(
false);
4391 focusAdvisor->setInFocusAdvisor(
false);
4396 autoFocusProcessPositionChange(newState);
4397 else if (newState == IPS_ALERT)
4398 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4403 if (nvp->isNameMatch(
"REL_FOCUS_POSITION"))
4405 m_FocusMotionTimer.stop();
4407 INumber *pos = IUFindNumber(nvp,
"FOCUS_RELATIVE_POSITION");
4408 IPState newState = nvp->s;
4409 if (pos && newState == IPS_OK)
4411 if (focuserAdditionalMovement == 0)
4414 currentPosition += pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4415 qCDebug(KSTARS_EKOS_FOCUS)
4416 <<
QString(
"Rel Focuser position moved %1 by %2 to %3")
4417 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").
arg(pos->value).
arg(currentPosition);
4418 absTicksLabel->setText(
QString::number(
static_cast<int>(currentPosition)));
4419 emit absolutePositionChanged(currentPosition);
4422 if (inAdjustFocus && newState == IPS_OK)
4424 if (focuserAdditionalMovement == 0)
4426 inAdjustFocus =
false;
4427 emit focusPositionAdjusted();
4432 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4434 if (focuserAdditionalMovement == 0)
4436 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4442 if (m_RestartState == RESTART_NOW && newState == IPS_OK && status() != Ekos::FOCUS_ABORTED)
4444 if (focuserAdditionalMovement == 0)
4446 m_RestartState = RESTART_NONE;
4448 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4449 adaptFocus->setInAdaptiveFocus(
false);
4450 focusAdvisor->setInFocusAdvisor(
false);
4451 appendLogText(
i18n(
"Restarting autofocus process..."));
4452 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4456 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4459 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4460 m_RestartState = RESTART_NONE;
4461 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4462 adaptFocus->setInAdaptiveFocus(
false);
4463 focusAdvisor->setInFocusAdvisor(
false);
4468 autoFocusProcessPositionChange(newState);
4469 else if (newState == IPS_ALERT)
4470 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4478 if (nvp->isNameMatch(
"FOCUS_TIMER"))
4480 IPState newState = nvp->s;
4481 m_FocusMotionTimer.stop();
4483 if (m_RestartState == RESTART_NOW && newState == IPS_OK && status() != Ekos::FOCUS_ABORTED)
4485 if (focuserAdditionalMovement == 0)
4487 m_RestartState = RESTART_NONE;
4489 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4490 adaptFocus->setInAdaptiveFocus(
false);
4491 focusAdvisor->setInFocusAdvisor(
false);
4492 appendLogText(
i18n(
"Restarting autofocus process..."));
4493 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4497 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4500 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4501 m_RestartState = RESTART_NONE;
4502 inAutoFocus = inBuildOffsets = inAdjustFocus = inScanStartPos =
false;
4503 adaptFocus->setInAdaptiveFocus(
false);
4504 focusAdvisor->setInFocusAdvisor(
false);
4508 if (canAbsMove ==
false && canRelMove ==
false)
4511 INumber *pos = IUFindNumber(nvp,
"FOCUS_TIMER_VALUE");
4514 currentPosition += pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4515 qCDebug(KSTARS_EKOS_FOCUS)
4516 <<
QString(
"Timer Focuser position moved %1 by %2 to %3")
4517 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").
arg(pos->value).
arg(currentPosition);
4520 if (pos && newState == IPS_OK && focuserAdditionalMovement == 0)
4523 if (inAdjustFocus && newState == IPS_OK)
4525 if (focuserAdditionalMovement == 0)
4527 inAdjustFocus =
false;
4528 emit focusPositionAdjusted();
4533 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4535 if (focuserAdditionalMovement == 0)
4537 adaptFocus->adaptiveFocusAdmin(
true,
true,
true);
4542 autoFocusProcessPositionChange(newState);
4544 else if (newState == IPS_ALERT)
4545 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4553 const QString logtext(m_Focuser ==
nullptr ? text :
QString(
"[%1] %2").arg(m_Focuser->getDeviceName()).
arg(text));
4554 emit newLog(logtext);
4557void Focus::appendFocusLogText(
const QString &text)
4559 if (Options::focusLogging())
4561 const QString logtext(m_Focuser ==
nullptr ? text :
QString(
"[%1] %2").arg(m_Focuser->getDeviceName()).
arg(text));
4562 emit newFocusLog(logtext);
4566void Focus::startFraming()
4568 if (m_Camera ==
nullptr)
4570 appendLogText(
i18n(
"No CCD connected."));
4574 waitStarSelectTimer.stop();
4577 starMeasureFrames.clear();
4582 setState(Ekos::FOCUS_FRAMING);
4586 appendLogText(
i18n(
"Starting continuous exposure..."));
4591void Focus::resetButtons()
4595 startFocusB->setEnabled(
false);
4596 startAbInsB->setEnabled(
false);
4597 startLoopB->setEnabled(
false);
4598 focusOutB->setEnabled(
true);
4599 focusInB->setEnabled(
true);
4600 startGotoB->setEnabled(canAbsMove);
4601 stopFocusB->setEnabled(
true);
4602 captureB->setEnabled(
false);
4603 opticalTrainCombo->setEnabled(
false);
4604 trainB->setEnabled(
false);
4618 if (disabledWidgets.empty())
4620 AFDisable(trainLabel,
false);
4621 AFDisable(opticalTrainCombo,
false);
4622 AFDisable(trainB,
false);
4623 AFDisable(focuserGroup,
true);
4624 AFDisable(clearDataB,
false);
4627 m_FocusGainAFEnabled = focusGain->isEnabled();
4628 m_FocusISOAFEnabled = focusISO->isEnabled();
4629 AFDisable(ccdGroup,
false);
4631 AFDisable(toolsGroup,
false);
4634 m_FocusSubFrameAFEnabled = m_OpsFocusSettings->focusSubFrame->isEnabled();
4637 AFDisable(m_OpsFocusSettings,
false);
4638 AFDisable(m_OpsFocusProcess,
false);
4639 AFDisable(m_OpsFocusMechanics,
false);
4640 AFDisable(focusAdvisor->focusAdvGroupBox,
false);
4641 AFDisable(m_CFZDialog,
false);
4644 stopFocusB->setEnabled(
true);
4650 for(
int i = 0 ; i < disabledWidgets.size() ; i++)
4651 disabledWidgets[i]->setEnabled(
true);
4652 disabledWidgets.clear();
4654 auto enableCaptureButtons = (m_captureInProgress ==
false && m_starDetectInProgress ==
false);
4656 captureB->setEnabled(enableCaptureButtons);
4657 resetFrameB->setEnabled(enableCaptureButtons);
4658 startLoopB->setEnabled(enableCaptureButtons);
4660 if (m_Focuser && m_Focuser->isConnected())
4662 focusOutB->setEnabled(
true);
4663 focusInB->setEnabled(
true);
4665 startFocusB->setEnabled(m_FocusType == FOCUS_AUTO);
4666 startAbInsB->setEnabled(canAbInsStart());
4667 stopFocusB->setEnabled(!enableCaptureButtons);
4668 startGotoB->setEnabled(canAbsMove);
4669 stopGotoB->setEnabled(
true);
4673 focusOutB->setEnabled(
false);
4674 focusInB->setEnabled(
false);
4676 startFocusB->setEnabled(
false);
4677 startAbInsB->setEnabled(
false);
4678 stopFocusB->setEnabled(
false);
4679 startGotoB->setEnabled(
false);
4680 stopGotoB->setEnabled(
false);
4688bool Focus::canAbInsStart()
4690 return canAbsMove && m_FocusAlgorithm == FOCUS_LINEAR1PASS && m_currentImageMask == FOCUS_MASK_MOSAIC;
4694void Focus::AFDisable(
QWidget * widget,
const bool children)
4701 if (wid->isEnabled())
4703 wid->setEnabled(
false);
4704 disabledWidgets.push_back(wid);
4713 disabledWidgets.push_back(widget);
4717bool Focus::isFocusGainEnabled()
4719 return (inAutoFocus) ? m_FocusGainAFEnabled : focusGain->isEnabled();
4722bool Focus::isFocusISOEnabled()
4724 return (inAutoFocus) ? m_FocusISOAFEnabled : focusISO->isEnabled();
4727bool Focus::isFocusSubFrameEnabled()
4729 return (inAutoFocus) ? m_FocusSubFrameAFEnabled : m_OpsFocusSettings->focusSubFrame->isEnabled();
4732void Focus::updateBoxSize(
int value)
4734 if (m_Camera ==
nullptr)
4737 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4739 if (targetChip ==
nullptr)
4742 int subBinX, subBinY;
4743 targetChip->getBinning(&subBinX, &subBinY);
4745 QRect trackBox = m_FocusView->getTrackingBox();
4749 QRect(
center.x() - value / (2 * subBinX),
center.y() - value / (2 * subBinY), value / subBinX, value / subBinY);
4751 m_FocusView->setTrackingBox(trackBox);
4754void Focus::selectFocusStarFraction(
double x,
double y)
4756 if (m_ImageData.isNull())
4759 focusStarSelected(x * m_ImageData->width(), y * m_ImageData->height());
4763 emit newImage(m_FocusView);
4767void Focus::focusStarSelected(
int x,
int y)
4769 if (state() == Ekos::FOCUS_PROGRESS)
4772 if (subFramed ==
false)
4774 rememberStarCenter.setX(x);
4775 rememberStarCenter.setY(y);
4778 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4780 int subBinX, subBinY;
4781 targetChip->getBinning(&subBinX, &subBinY);
4784 if (subBinX != (focusBinning->currentIndex() + 1))
4790 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
4794 bool squareMovedOutside =
false;
4796 if (subFramed ==
false && m_OpsFocusSettings->focusSubFrame->isChecked() && targetChip->canSubframe())
4799 if (!isStarMeasureStarBased())
4805 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
4807 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
4810 x = (x - offset) * subBinX;
4811 y = (y - offset) * subBinY;
4812 int w = offset * 2 * subBinX;
4813 int h = offset * 2 * subBinY;
4832 QVariantMap settings = frameSettings[targetChip];
4837 settings[
"binx"] = subBinX;
4838 settings[
"biny"] = subBinY;
4840 frameSettings[targetChip] = settings;
4844 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << x <<
"Y:" << y <<
"W:" << w <<
"H:" << h <<
"binX:" << subBinX <<
4847 m_FocusView->setFirstLoad(
true);
4851 if (isStarMeasureStarBased())
4853 starCenter.setX(w / (2 * subBinX));
4854 starCenter.setY(h / (2 * subBinY));
4861 double dist = sqrt((starCenter.x() - x) * (starCenter.x() - x) + (starCenter.y() - y) * (starCenter.y() - y));
4863 squareMovedOutside = (dist > (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX));
4867 starRect =
QRect(starCenter.x() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinX),
4868 starCenter.y() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinY),
4869 m_OpsFocusSettings->focusBoxSize->value() / subBinX,
4870 m_OpsFocusSettings->focusBoxSize->value() / subBinY);
4871 m_FocusView->setTrackingBox(starRect);
4876 starCenter.setZ(subBinX);
4878 if (squareMovedOutside && inAutoFocus ==
false && m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
4880 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
true);
4881 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
4882 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
false);
4883 appendLogText(
i18n(
"Disabling Auto Star Selection as star selection box was moved manually."));
4884 starSelected =
false;
4886 else if (starSelected ==
false)
4888 if (isStarMeasureStarBased())
4889 appendLogText(
i18n(
"Focus star is selected."));
4891 appendLogText(
i18n(
"Region of interest is selected."));
4893 starSelected =
true;
4897 waitStarSelectTimer.stop();
4898 FocusState nextState = inAutoFocus ? FOCUS_PROGRESS : FOCUS_IDLE;
4899 if (nextState != state())
4901 setState(nextState);
4905void Focus::checkFocus(
double requiredHFR)
4907 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
4911 str =
i18n(
"Autofocus");
4912 else if (inAdjustFocus)
4913 str =
i18n(
"Adjust Focus");
4915 str =
i18n(
"Adaptive Focus");
4917 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
4919 appendLogText(
i18n(
"Check focus request - Waiting 10sec for %1 to complete.", str));
4922 checkFocus(requiredHFR);
4927 appendLogText(
i18n(
"Discarding Check Focus request - %1 in progress.", str));
4928 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
4934 if (inFocusLoop || inBuildOffsets)
4936 QString str = inFocusLoop ?
"Focus Looping" :
" Build Offsets";
4937 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Check Focus rejected, %1 is already running.").
arg(str);
4939 else if (!isStarMeasureStarBased())
4940 appendLogText(
i18n(
"Check Focus ignored - Star Measure must be star based"));
4943 qCDebug(KSTARS_EKOS_FOCUS) <<
"Check Focus requested with minimum required HFR" << requiredHFR;
4944 minimumRequiredHFR = requiredHFR;
4945 appendLogText(
i18n(
"Capturing to check HFR..."));
4950void Focus::toggleSubframe(
bool enable)
4952 if (enable ==
false)
4956 m_FocusView->setTrackingBoxEnabled(enable);
4957 starSelected =
false;
4962 m_OpsFocusSettings->focusNoMaskRB->setChecked(
true);
4967 m_OpsFocusSettings->focusRingMaskRB->setEnabled(!enable);
4968 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(!enable);
4972 setAutoStarAndBox();
4979void Focus::setUseWeights()
4981 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC || !m_OpsFocusSettings->focusUseFullField->isChecked()
4982 || m_StarMeasure == FOCUS_STAR_NUM_STARS || m_StarMeasure == FOCUS_STAR_FOURIER_POWER ||
4983 m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
4984 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
4986 m_OpsFocusProcess->focusUseWeights->setEnabled(
false);
4987 m_OpsFocusProcess->focusUseWeights->setChecked(
false);
4990 m_OpsFocusProcess->focusUseWeights->setEnabled(
true);
4997void Focus::setDenoise()
4999 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
5000 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
5001 m_OpsFocusProcess->focusDenoise->setEnabled(
true);
5004 m_OpsFocusProcess->focusDenoise->setEnabled(
false);
5005 m_OpsFocusProcess->focusDenoise->setChecked(
false);
5014void Focus::setDonutBuster()
5016 if (m_FocusAlgorithm != FOCUS_LINEAR1PASS)
5018 m_OpsFocusProcess->focusDonut->hide();
5019 m_OpsFocusProcess->focusDonut->setEnabled(
false);
5020 m_OpsFocusProcess->focusDonut->setChecked(
false);
5024 m_OpsFocusProcess->focusDonut->show();
5025 if ((m_StarMeasure == FOCUS_STAR_HFR || m_StarMeasure == FOCUS_STAR_HFR_ADJ || m_StarMeasure == FOCUS_STAR_FWHM) &&
5026 (m_FocusWalk == FOCUS_WALK_FIXED_STEPS || m_FocusWalk == FOCUS_WALK_CFZ_SHUFFLE) &&
5027 (m_CurveFit != CurveFitting::FOCUS_QUADRATIC))
5028 m_OpsFocusProcess->focusDonut->setEnabled(
true);
5031 m_OpsFocusProcess->focusDonut->setEnabled(
false);
5032 m_OpsFocusProcess->focusDonut->setChecked(
false);
5037void Focus::setExposure(
double value)
5039 focusExposure->setValue(value);
5042void Focus::setBinning(
int subBinX,
int subBinY)
5044 INDI_UNUSED(subBinY);
5045 focusBinning->setCurrentIndex(subBinX - 1);
5048void Focus::setAutoStarEnabled(
bool enable)
5050 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(enable);
5053void Focus::setAutoSubFrameEnabled(
bool enable)
5055 m_OpsFocusSettings->focusSubFrame->setChecked(enable);
5058void Focus::setAutoFocusParameters(
int boxSize,
int stepSize,
int maxTravel,
double tolerance)
5060 m_OpsFocusSettings->focusBoxSize->setValue(boxSize);
5061 m_OpsFocusMechanics->focusTicks->setValue(stepSize);
5062 m_OpsFocusMechanics->focusMaxTravel->setValue(maxTravel);
5063 m_OpsFocusProcess->focusTolerance->setValue(tolerance);
5066void Focus::checkAutoStarTimeout()
5069 if (starCenter.isNull() && (inAutoFocus || minimumRequiredHFR > 0))
5073 if (rememberStarCenter.isNull() ==
false)
5075 focusStarSelected(rememberStarCenter.x(), rememberStarCenter.y());
5076 appendLogText(
i18n(
"No star was selected. Using last known position..."));
5081 initialFocuserAbsPosition = -1;
5082 appendLogText(
i18n(
"No star was selected. Aborting..."));
5083 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
5085 else if (state() == FOCUS_WAITING)
5086 setState(FOCUS_IDLE);
5089void Focus::setAbsoluteFocusTicks()
5091 if (absTicksSpin->value() == currentPosition)
5093 appendLogText(
i18n(
"Focuser already at %1...", currentPosition));
5096 focusInB->setEnabled(
false);
5097 focusOutB->setEnabled(
false);
5098 startGotoB->setEnabled(
false);
5099 if (!changeFocus(absTicksSpin->value() - currentPosition))
5100 qCDebug(KSTARS_EKOS_FOCUS) <<
"setAbsoluteFocusTicks unable to move focuser.";
5103void Focus::syncTrackingBoxPosition()
5106 if (m_OpsFocusSettings->focusUseFullField->isChecked() || starCenter.isNull())
5109 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5110 Q_ASSERT(targetChip);
5112 int subBinX = 1, subBinY = 1;
5113 targetChip->getBinning(&subBinX, &subBinY);
5115 double boxSize = m_OpsFocusSettings->focusBoxSize->value();
5117 targetChip->getFrame(&x, &y, &w, &h);
5119 if (boxSize / subBinX >= w || boxSize / subBinY >= h)
5121 m_OpsFocusSettings->focusBoxSize->setValue((boxSize / subBinX >= w) ? w : h);
5126 if (subBinX != starCenter.z())
5128 if (starCenter.z() > 0)
5130 starCenter.setX(starCenter.x() * (starCenter.z() / subBinX));
5131 starCenter.setY(starCenter.y() * (starCenter.z() / subBinY));
5134 starCenter.setZ(subBinX);
5139 if (isStarMeasureStarBased())
5140 starRect =
QRect(starCenter.x() - boxSize / (2 * subBinX), starCenter.y() - boxSize / (2 * subBinY),
5141 boxSize / subBinX, boxSize / subBinY);
5145 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
5146 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
5147 int boxTLX = starCenter.x() - boxSize / (2 * subBinX);
5148 boxTLX = std::max(boxTLX, minX);
5149 int boxTLY = starCenter.y() - boxSize / (2 * subBinY);
5150 boxTLY = std::max(boxTLY, minY);
5151 const int boxBRX = boxTLX + (boxSize / subBinX);
5153 boxTLX -= boxBRX - maxX;
5154 const int boxBRY = boxTLY + (boxSize / subBinY);
5156 boxTLY -= boxBRY - maxY;
5158 starRect =
QRect(boxTLX, boxTLY, boxSize / subBinX, boxSize / subBinY);
5160 m_FocusView->setTrackingBoxEnabled(
true);
5161 m_FocusView->setTrackingBox(starRect);
5164void Focus::showFITSViewer()
5166 static int lastFVTabID = -1;
5173 fv->loadData(m_ImageData, url, &lastFVTabID);
5174 connect(fv.get(), &FITSViewer::terminated,
this, [
this]()
5179 else if (fv->updateData(m_ImageData, url, lastFVTabID, &lastFVTabID) ==
false)
5180 fv->loadData(m_ImageData, url, &lastFVTabID);
5186void Focus::adjustFocusOffset(
int value,
bool useAbsoluteOffset)
5189 if (inAdjustFocus || adaptFocus->inAdaptiveFocus())
5191 QString str = inAdjustFocus ?
i18n(
"Adjust Focus") :
i18n(
"Adaptive Focus");
5192 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
5194 appendLogText(
i18n(
"Adjust focus request - Waiting 10sec for %1 to complete.", str));
5197 adjustFocusOffset(value, useAbsoluteOffset);
5202 qCDebug(KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset called whilst" << str <<
"in progress. Ignoring...";
5203 emit focusPositionAdjusted();
5208 inAdjustFocus =
true;
5211 int newPosition = (useAbsoluteOffset) ? value : value + currentPosition;
5213 if (!changeFocus(newPosition - currentPosition))
5214 qCDebug(KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset unable to move focuser";
5217void Focus::toggleFocusingWidgetFullScreen()
5219 if (focusingWidget->parent() ==
nullptr)
5221 focusingWidget->setParent(
this);
5222 rightLayout->insertWidget(0, focusingWidget);
5223 focusingWidget->showNormal();
5227 focusingWidget->setParent(
nullptr);
5228 focusingWidget->setWindowTitle(
i18nc(
"@title:window",
"Focus Frame"));
5230 focusingWidget->showMaximized();
5231 focusingWidget->show();
5235void Focus::setMountStatus(ISD::Mount::Status newState)
5239 case ISD::Mount::MOUNT_PARKING:
5240 case ISD::Mount::MOUNT_SLEWING:
5241 case ISD::Mount::MOUNT_MOVING:
5242 captureB->setEnabled(
false);
5243 startFocusB->setEnabled(
false);
5244 startAbInsB->setEnabled(
false);
5245 startLoopB->setEnabled(
false);
5260void Focus::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
5269 auto name = deviceRemoved->getDeviceName();
5273 if (m_Focuser && m_Focuser->getDeviceName() == name)
5275 m_Focuser->disconnect(
this);
5276 m_Focuser =
nullptr;
5285 for (
auto &oneSource : m_TemperatureSources)
5287 if (oneSource->getDeviceName() == name)
5290 if (m_LastSourceDeviceAutofocusTemperature && m_LastSourceDeviceAutofocusTemperature->getDeviceName() == name)
5291 m_LastSourceDeviceAutofocusTemperature.reset(
nullptr);
5293 m_TemperatureSources.removeAll(oneSource);
5296 defaultFocusTemperatureSource->removeItem(defaultFocusTemperatureSource->findText(name));
5303 if (m_Camera && m_Camera->getDeviceName() == name)
5305 m_Camera->disconnect(
this);
5316 if (m_FilterWheel && m_FilterWheel->getDeviceName() == name)
5318 m_FilterWheel->disconnect(
this);
5319 m_FilterWheel =
nullptr;
5329void Focus::setupFilterManager()
5332 if (m_FilterManager)
5333 m_FilterManager->disconnect(
this);
5336 Ekos::Manager::Instance()->createFilterManager(m_FilterWheel);
5339 Ekos::Manager::Instance()->getFilterManager(m_FilterWheel->getDeviceName(), m_FilterManager);
5344 connect(
this, &Focus::absolutePositionChanged, m_FilterManager.get(), &FilterManager::setFocusAbsolutePosition);
5347 connect(
this, &Focus::newStatus,
this, [
this](Ekos::FocusState state)
5349 if (m_FilterManager)
5351 m_FilterManager->setFocusStatus(state);
5352 if (focusFilter->currentIndex() != -1 && canAbsMove && state == Ekos::FOCUS_COMPLETE)
5354 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
5355 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
5363 connect(m_FilterManager.get(), &FilterManager::newStatus,
this, [
this](Ekos::FilterState filterState)
5366 if (filterState == FILTER_OFFSET && state() != Ekos::FOCUS_PROGRESS)
5368 if (m_GuidingSuspended == false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
5370 m_GuidingSuspended = true;
5371 emit suspendGuiding();
5377 connect(m_FilterManager.get(), &FilterManager::ready,
this, [
this]()
5380 if (focusFilter->currentIndex() != currentFilterPosition - 1)
5381 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5383 if (filterPositionPending)
5385 filterPositionPending = false;
5388 else if (fallbackFilterPending)
5390 fallbackFilterPending =
false;
5391 setState(m_pendingState);
5392 m_pendingState = FOCUS_IDLE;
5397 connect(m_FilterManager.get(), &FilterManager::failed,
this, [
this]()
5399 appendLogText(i18n(
"Filter operation failed."));
5400 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FILTER_MANAGER);
5404 connect(m_FilterManager.get(), &FilterManager::runAutoFocus,
this, &Focus::runAutoFocus);
5407 connect(m_FilterManager.get(), &FilterManager::abortAutoFocus,
this, &Focus::abort);
5410 connect(m_FilterManager.get(), &FilterManager::newFocusOffset,
this, &Focus::adjustFocusOffset);
5413 connect(m_FilterManager.get(), &FilterManager::labelsChanged,
this, [
this]()
5415 focusFilter->clear();
5416 focusFilter->addItems(m_FilterManager->getFilterLabels());
5417 currentFilterPosition = m_FilterManager->getFilterPosition();
5418 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5422 connect(m_FilterManager.get(), &FilterManager::positionChanged,
this, [
this]()
5424 currentFilterPosition = m_FilterManager->getFilterPosition();
5425 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5429 connect(m_FilterManager.get(), &FilterManager::exposureChanged,
this, [
this]()
5431 focusExposure->setValue(m_FilterManager->getFilterExposure());
5435 connect(m_FilterManager.get(), &FilterManager::wavelengthChanged,
this, [
this]()
5437 wavelengthChanged();
5441void Focus::connectFilterManager()
5446 if (m_FilterManager)
5448 m_FilterManager->refreshFilterModel();
5449 m_FilterManager->show();
5450 m_FilterManager->raise();
5455 connect(
this, &Focus::focusPositionAdjusted,
this, [
this]()
5457 if (m_FilterManager)
5458 m_FilterManager->setFocusOffsetComplete();
5459 if (m_GuidingSuspended && state() != Ekos::FOCUS_PROGRESS)
5461 QTimer::singleShot(m_OpsFocusMechanics->focusSettleTime->value() * 1000,
this, [
this]()
5463 m_GuidingSuspended = false;
5464 emit resumeGuiding();
5473 if (inAutoFocus && m_OpsFocusProcess->focusDonut->isEnabled())
5476 if (m_FilterManager)
5477 m_FilterManager->setFilterExposure(focusFilter->currentIndex(), focusExposure->value());
5483 if (m_FilterManager)
5485 focusExposure->setValue(m_FilterManager->getFilterExposure(text));
5493void Focus::toggleVideo(
bool enabled)
5495 if (m_Camera ==
nullptr)
5498 if (m_Camera->isBLOBEnabled() ==
false)
5501 if (Options::guiderType() != Ekos::Guide::GUIDE_INTERNAL)
5502 m_Camera->setBLOBEnabled(
true);
5509 m_Camera->setVideoStreamEnabled(enabled);
5511 KSMessageBox::Instance()->questionYesNo(
i18n(
"Image transfer is disabled for this camera. Would you like to enable it?"));
5515 m_Camera->setVideoStreamEnabled(enabled);
5531void Focus::setVideoStreamEnabled(
bool enabled)
5535 liveVideoB->setChecked(
true);
5540 liveVideoB->setChecked(
false);
5545void Focus::processCaptureTimeout()
5547 m_captureInProgress =
false;
5549 if (m_abortInProgress)
5552 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame in " << __FUNCTION__;
5556 captureTimeoutCounter++;
5558 if (captureTimeoutCounter >= 3)
5560 captureTimeoutCounter = 0;
5561 m_MissingCameraCounter = 0;
5562 captureTimeout.stop();
5563 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5564 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5568 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
5569 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5570 targetChip->abortExposure();
5572 capture(focusExposure->value());
5576 else if (m_MissingCameraCounter < 40)
5578 m_MissingCameraCounter++;
5579 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to restart focus exposure as camera is missing, trying again in 5 seconds...";
5584 m_MissingCameraCounter = 0;
5585 captureTimeoutCounter = 0;
5586 captureTimeout.stop();
5587 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5588 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5593void Focus::processCaptureErrorDefault()
5595 processCaptureError(ISD::Camera::ERROR_CAPTURE);
5600 m_captureInProgress =
false;
5601 captureTimeout.stop();
5603 if (m_abortInProgress)
5605 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame in " << __FUNCTION__;
5611 appendLogText(
i18n(
"Failed to save image. Aborting..."));
5612 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5619 captureFailureCounter++;
5621 if (captureFailureCounter >= 3)
5623 captureFailureCounter = 0;
5624 captureTimeoutCounter = 0;
5625 m_MissingCameraCounter = 0;
5626 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5627 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5631 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5632 targetChip->abortExposure();
5633 capture(focusExposure->value());
5637 else if (m_MissingCameraCounter < 40)
5639 m_MissingCameraCounter++;
5640 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to restart focus exposure as camera is missing, trying again in 5 seconds...";
5647 m_MissingCameraCounter = 0;
5648 captureFailureCounter = 0;
5649 captureTimeoutCounter = 0;
5650 captureTimeout.stop();
5651 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5652 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5656void Focus::syncSettings()
5669 if ( (dsb = qobject_cast<QDoubleSpinBox*>(sender())))
5672 value = dsb->
value();
5675 else if ( (sb = qobject_cast<QSpinBox*>(sender())))
5678 value = sb->
value();
5680 else if ( (cb = qobject_cast<QCheckBox*>(sender())))
5685 else if ( (gb = qobject_cast<QGroupBox*>(sender())))
5690 else if ( (rb = qobject_cast<QRadioButton*>(sender())))
5696 m_Settings.remove(key);
5701 else if ( (cbox = qobject_cast<QComboBox*>(sender())))
5706 else if ( (s = qobject_cast<QSplitter*>(sender())))
5714 Options::self()->setProperty(key.
toLatin1(), value);
5716 m_Settings[key] = value;
5717 m_GlobalSettings[key] = value;
5721 m_DebounceTimer.start();
5727void Focus::settleSettings()
5729 emit settingsUpdated(getAllSettings());
5731 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
5732 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
5735void Focus::loadGlobalSettings()
5740 QVariantMap settings;
5742 for (
auto &oneWidget : findChildren<QComboBox*>())
5744 if (oneWidget->objectName() ==
"opticalTrainCombo")
5747 key = oneWidget->objectName();
5748 value = Options::self()->property(key.
toLatin1());
5749 if (value.
isValid() && oneWidget->count() > 0)
5751 oneWidget->setCurrentText(value.
toString());
5752 settings[key] = value;
5755 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5759 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5761 key = oneWidget->objectName();
5762 value = Options::self()->property(key.
toLatin1());
5765 oneWidget->setValue(value.
toDouble());
5766 settings[key] = value;
5769 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5773 for (
auto &oneWidget : findChildren<QSpinBox*>())
5775 key = oneWidget->objectName();
5776 value = Options::self()->property(key.
toLatin1());
5779 oneWidget->setValue(value.
toInt());
5780 settings[key] = value;
5783 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5787 for (
auto &oneWidget : findChildren<QCheckBox*>())
5789 key = oneWidget->objectName();
5790 value = Options::self()->property(key.
toLatin1());
5793 oneWidget->setChecked(value.
toBool());
5794 settings[key] = value;
5796 else if (key != forceInSeqAF->objectName())
5797 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5801 for (
auto &oneWidget : findChildren<QGroupBox*>())
5803 if (oneWidget->isCheckable())
5805 key = oneWidget->objectName();
5806 value = Options::self()->property(key.
toLatin1());
5809 oneWidget->setChecked(value.
toBool());
5810 settings[key] = value;
5813 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5818 for (
auto &oneWidget : findChildren<QSplitter*>())
5820 key = oneWidget->objectName();
5821 value = Options::self()->property(key.
toLatin1());
5826 oneWidget->restoreState(valueBA);
5827 settings[key] = valueBA;
5830 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5834 for (
auto &oneWidget : findChildren<QRadioButton*>())
5836 key = oneWidget->objectName();
5837 value = Options::self()->property(key.
toLatin1());
5840 oneWidget->setChecked(value.
toBool());
5841 settings[key] = value;
5846 m_GlobalSettings = m_Settings = settings;
5849void Focus::checkMosaicMaskLimits()
5851 if (m_Camera ==
nullptr || m_Camera->isConnected() ==
false)
5853 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5854 if (targetChip ==
nullptr || frameSettings.contains(targetChip) ==
false)
5856 auto settings = frameSettings[targetChip];
5859 auto width = settings[
"w"].toInt();
5860 auto height = settings[
"h"].toInt();
5861 if (width == 0 || height == 0)
5865 auto min = std::min(width, height);
5867 m_OpsFocusSettings->focusMosaicTileWidth->setMaximum(100 * min / (3 * width));
5870void Focus::connectSyncSettings()
5873 for (
auto &oneWidget : findChildren<QComboBox*>())
5875 if (oneWidget != opticalTrainCombo)
5879 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5883 for (
auto &oneWidget : findChildren<QSpinBox*>())
5887 for (
auto &oneWidget : findChildren<QCheckBox*>())
5891 for (
auto &oneWidget : findChildren<QGroupBox*>())
5892 if (oneWidget->isCheckable())
5896 for (
auto &oneWidget : findChildren<QSplitter*>())
5900 for (
auto &oneWidget : findChildren<QRadioButton*>())
5904void Focus::disconnectSyncSettings()
5907 for (
auto &oneWidget : findChildren<QComboBox*>())
5908 disconnect(oneWidget, QOverload<int>::of(&
QComboBox::activated),
this, &Ekos::Focus::syncSettings);
5911 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5915 for (
auto &oneWidget : findChildren<QSpinBox*>())
5919 for (
auto &oneWidget : findChildren<QCheckBox*>())
5923 for (
auto &oneWidget : findChildren<QGroupBox*>())
5924 if (oneWidget->isCheckable())
5928 for (
auto &oneWidget : findChildren<QSplitter*>())
5932 for (
auto &oneWidget : findChildren<QRadioButton*>())
5936void Focus::initPlots()
5940 profileDialog =
new QDialog(
this);
5943 profileDialog->setWindowTitle(
i18nc(
"@title:window",
"Relative Profile"));
5944 profilePlot =
new FocusProfilePlot(profileDialog);
5947 profileDialog->setLayout(profileLayout);
5948 profileDialog->resize(400, 300);
5951 connect(
this, &Ekos::Focus::newHFR, [
this](
double currentHFR,
int pos)
5953 Q_UNUSED(pos) profilePlot->drawProfilePlot(currentHFR);
5957void Focus::initConnections()
5960 waitStarSelectTimer.setInterval(AUTO_STAR_TIMEOUT);
5965 m_DebounceTimer.setInterval(500);
5966 m_DebounceTimer.setSingleShot(
true);
5981 captureTimer.setSingleShot(
true);
5988 captureTimeout.setSingleShot(
true);
6023 &Ekos::Focus::updateBoxSize);
6029 m_CFZDialog->show();
6030 m_CFZDialog->raise();
6036 focusAdvisor->setButtons(
false);
6037 focusAdvisor->show();
6038 focusAdvisor->raise();
6044 emit inSequenceAF(enabled, opticalTrain());
6050 setFocusDetection(static_cast<StarAlgorithm>(index));
6056 setFocusAlgorithm(static_cast<Algorithm>(index));
6062 this, [&](
int index)
6064 setCurveFit(static_cast<CurveFitting::CurveFit>(index));
6069 this, [&](
int index)
6071 setStarMeasure(static_cast<StarMeasure>(index));
6076 this, [&](
int index)
6078 setStarPSF(static_cast<StarPSF>(index));
6083 this, [&](
int index)
6085 setStarUnits(static_cast<StarUnits>(index));
6090 this, [&](
int index)
6092 setWalk(static_cast<FocusWalk>(index));
6103 starCenter = QVector3D();
6104 starSelected = false;
6105 m_FocusView->setTrackingBox(QRect());
6113 &Ekos::Focus::calcCFZ);
6116 &Ekos::Focus::calcCFZ);
6157void Focus::setFocusDetection(StarAlgorithm starAlgorithm)
6159 static bool first =
true;
6160 if (!first && m_FocusDetection == starAlgorithm)
6165 m_FocusDetection = starAlgorithm;
6168 setFocusAlgorithm(m_FocusAlgorithm);
6169 setAutoStarAndBox();
6177void Focus::setAutoStarAndBox()
6179 if (m_FocusDetection == ALGORITHM_BAHTINOV)
6181 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6182 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6183 m_OpsFocusSettings->focusBoxSize->setEnabled(m_OpsFocusSettings->focusSubFrame->isChecked());
6184 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(m_OpsFocusSettings->focusSubFrame->isChecked());
6185 m_OpsFocusSettings->focusBoxSize->setMaximum(512);
6186 if (m_OpsFocusSettings->focusBoxSize->value() > 512)
6187 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
6189 else if(m_OpsFocusSettings->focusSubFrame->isChecked())
6191 if(isStarMeasureStarBased())
6193 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
true);
6195 m_OpsFocusSettings->focusBoxSize->setEnabled(
true);
6196 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
true);
6197 if (m_OpsFocusSettings->focusBoxSize->value() > 256)
6198 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
6199 m_OpsFocusSettings->focusBoxSize->setMaximum(256);
6203 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6204 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6207 m_OpsFocusSettings->focusBoxSize->setEnabled(
true);
6208 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
true);
6209 int maxSize = std::min(m_CcdWidth, m_CcdHeight);
6210 int step = m_OpsFocusSettings->focusBoxSize->singleStep();
6211 maxSize = std::max(256, (maxSize / step) * step);
6212 m_OpsFocusSettings->focusBoxSize->setMaximum(maxSize);
6218 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6219 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6220 m_OpsFocusSettings->focusBoxSize->setEnabled(
false);
6221 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
false);
6226void Focus::setFocusAlgorithm(Algorithm algorithm)
6228 m_FocusAlgorithm = algorithm;
6231 case FOCUS_ITERATIVE:
6233 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6234 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6235 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6236 m_OpsFocusProcess->focusMultiRowAverage->hide();
6238 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6239 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6240 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6241 m_OpsFocusProcess->focusGaussianSigma->hide();
6243 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6244 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6245 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6246 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6248 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasureLabel);
6249 m_OpsFocusProcess->focusStarMeasureLabel->hide();
6250 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasure);
6251 m_OpsFocusProcess->focusStarMeasure->hide();
6253 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6254 m_OpsFocusProcess->focusStarPSFLabel->hide();
6255 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6256 m_OpsFocusProcess->focusStarPSF->hide();
6258 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6259 m_OpsFocusProcess->focusUseWeights->hide();
6261 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6262 m_OpsFocusProcess->focusR2LimitLabel->hide();
6263 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6264 m_OpsFocusProcess->focusR2Limit->hide();
6266 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6267 m_OpsFocusProcess->focusRefineCurveFit->hide();
6268 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6270 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6271 m_OpsFocusProcess->focusToleranceLabel->hide();
6272 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6273 m_OpsFocusProcess->focusTolerance->hide();
6275 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6276 m_OpsFocusProcess->focusThresholdLabel->hide();
6277 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6278 m_OpsFocusProcess->focusThreshold->hide();
6280 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFitLabel);
6281 m_OpsFocusProcess->focusCurveFitLabel->hide();
6282 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFit);
6283 m_OpsFocusProcess->focusCurveFit->hide();
6285 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6286 m_OpsFocusProcess->focusDenoise->hide();
6289 m_OpsFocusProcess->focusDonut->hide();
6290 m_OpsFocusProcess->focusDonut->setChecked(
false);
6293 m_OpsFocusProcess->focusScanStartPos->hide();
6294 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6297 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6300 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6302 m_OpsFocusProcess->focusStarMeasure->clear();
6303 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6304 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6308 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6309 m_OpsFocusProcess->focusToleranceLabel->show();
6310 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6311 m_OpsFocusProcess->focusTolerance->show();
6313 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6314 m_OpsFocusProcess->focusFramesCountLabel->show();
6315 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6316 m_OpsFocusProcess->focusFramesCount->show();
6318 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6319 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6320 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6321 m_OpsFocusProcess->focusHFRFramesCount->show();
6323 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6325 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6326 m_OpsFocusProcess->focusThresholdLabel->show();
6327 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6328 m_OpsFocusProcess->focusThreshold->show();
6330 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6332 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6333 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6334 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6335 m_OpsFocusProcess->focusMultiRowAverage->show();
6337 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6338 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6339 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6340 m_OpsFocusProcess->focusGaussianSigma->show();
6342 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6343 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6344 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6345 m_OpsFocusProcess->focusGaussianKernelSize->show();
6349 startAbInsB->setEnabled(canAbInsStart());
6353 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6354 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6355 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6358 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6359 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6362 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6364 m_OpsFocusMechanics->focusWalk->clear();
6365 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6366 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6370 case FOCUS_POLYNOMIAL:
6372 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6373 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6374 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6375 m_OpsFocusProcess->focusMultiRowAverage->hide();
6377 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6378 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6379 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6380 m_OpsFocusProcess->focusGaussianSigma->hide();
6382 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6383 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6384 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6385 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6387 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6388 m_OpsFocusProcess->focusStarPSFLabel->hide();
6389 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6390 m_OpsFocusProcess->focusStarPSF->hide();
6392 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6393 m_OpsFocusProcess->focusUseWeights->hide();
6395 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6396 m_OpsFocusProcess->focusR2LimitLabel->hide();
6397 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6398 m_OpsFocusProcess->focusR2Limit->hide();
6400 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6401 m_OpsFocusProcess->focusRefineCurveFit->hide();
6402 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6404 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6405 m_OpsFocusProcess->focusToleranceLabel->hide();
6406 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6407 m_OpsFocusProcess->focusTolerance->hide();
6409 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6410 m_OpsFocusProcess->focusThresholdLabel->hide();
6411 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6412 m_OpsFocusProcess->focusThreshold->hide();
6414 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6415 m_OpsFocusProcess->focusDenoise->hide();
6418 m_OpsFocusProcess->focusDonut->hide();
6419 m_OpsFocusProcess->focusDonut->setChecked(
false);
6422 m_OpsFocusProcess->focusScanStartPos->hide();
6423 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6426 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6428 m_OpsFocusProcess->focusStarMeasure->clear();
6429 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6430 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6435 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6436 m_OpsFocusProcess->focusCurveFitLabel->show();
6437 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6438 m_OpsFocusProcess->focusCurveFit->show();
6439 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6441 m_OpsFocusProcess->focusCurveFit->clear();
6442 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6443 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6446 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6447 m_OpsFocusProcess->focusToleranceLabel->show();
6448 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6449 m_OpsFocusProcess->focusTolerance->show();
6451 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6452 m_OpsFocusProcess->focusFramesCountLabel->show();
6453 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6454 m_OpsFocusProcess->focusFramesCount->show();
6456 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6457 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6458 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6459 m_OpsFocusProcess->focusHFRFramesCount->show();
6461 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6463 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6464 m_OpsFocusProcess->focusThresholdLabel->show();
6465 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6466 m_OpsFocusProcess->focusThreshold->show();
6468 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6470 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6471 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6472 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6473 m_OpsFocusProcess->focusMultiRowAverage->show();
6475 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6476 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6477 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6478 m_OpsFocusProcess->focusGaussianSigma->show();
6480 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6481 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6482 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6483 m_OpsFocusProcess->focusGaussianKernelSize->show();
6487 startAbInsB->setEnabled(canAbInsStart());
6491 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6492 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6493 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6496 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6497 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6500 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6502 m_OpsFocusMechanics->focusWalk->clear();
6503 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6504 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6510 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6511 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6512 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6513 m_OpsFocusProcess->focusMultiRowAverage->hide();
6515 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6516 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6517 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6518 m_OpsFocusProcess->focusGaussianSigma->hide();
6520 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6521 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6522 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6523 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6525 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6526 m_OpsFocusProcess->focusThresholdLabel->hide();
6527 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6528 m_OpsFocusProcess->focusThreshold->hide();
6530 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6531 m_OpsFocusProcess->focusStarPSFLabel->hide();
6532 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6533 m_OpsFocusProcess->focusStarPSF->hide();
6535 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6536 m_OpsFocusProcess->focusUseWeights->hide();
6538 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6539 m_OpsFocusProcess->focusR2LimitLabel->hide();
6540 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6541 m_OpsFocusProcess->focusR2Limit->hide();
6543 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6544 m_OpsFocusProcess->focusRefineCurveFit->hide();
6545 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6547 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6548 m_OpsFocusProcess->focusDenoise->hide();
6551 m_OpsFocusProcess->focusDonut->hide();
6552 m_OpsFocusProcess->focusDonut->setChecked(
false);
6555 m_OpsFocusProcess->focusScanStartPos->hide();
6556 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6559 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6561 m_OpsFocusProcess->focusStarMeasure->clear();
6562 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6563 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6568 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6569 m_OpsFocusProcess->focusCurveFitLabel->show();
6570 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6571 m_OpsFocusProcess->focusCurveFit->show();
6572 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6574 m_OpsFocusProcess->focusCurveFit->clear();
6575 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6576 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6579 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6580 m_OpsFocusProcess->focusToleranceLabel->show();
6581 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6582 m_OpsFocusProcess->focusTolerance->show();
6584 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6585 m_OpsFocusProcess->focusFramesCountLabel->show();
6586 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6587 m_OpsFocusProcess->focusFramesCount->show();
6589 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6590 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6591 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6592 m_OpsFocusProcess->focusHFRFramesCount->show();
6594 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6596 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6597 m_OpsFocusProcess->focusThresholdLabel->show();
6598 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6599 m_OpsFocusProcess->focusThreshold->show();
6601 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6603 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6604 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6605 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6606 m_OpsFocusProcess->focusMultiRowAverage->show();
6608 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6609 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6610 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6611 m_OpsFocusProcess->focusGaussianSigma->show();
6613 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6614 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6615 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6616 m_OpsFocusProcess->focusGaussianKernelSize->show();
6620 startAbInsB->setEnabled(canAbInsStart());
6624 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6625 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6626 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6629 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6630 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6633 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6635 m_OpsFocusMechanics->focusWalk->clear();
6636 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6637 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6641 case FOCUS_LINEAR1PASS:
6643 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6644 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6645 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6646 m_OpsFocusProcess->focusMultiRowAverage->hide();
6648 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6649 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6650 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6651 m_OpsFocusProcess->focusGaussianSigma->hide();
6653 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6654 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6655 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6656 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6658 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6659 m_OpsFocusProcess->focusThresholdLabel->hide();
6660 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6661 m_OpsFocusProcess->focusThreshold->hide();
6663 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6664 m_OpsFocusProcess->focusToleranceLabel->hide();
6665 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6666 m_OpsFocusProcess->focusTolerance->hide();
6670 if (m_FocusDetection == ALGORITHM_SEP && m_CurveFit != CurveFitting::FOCUS_QUADRATIC)
6672 if (m_OpsFocusProcess->focusStarMeasure->count() != m_StarMeasureText.count())
6674 m_OpsFocusProcess->focusStarMeasure->clear();
6675 m_OpsFocusProcess->focusStarMeasure->addItems(m_StarMeasureText);
6676 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6680#if !defined(HAVE_OPENCV)
6688 else if (m_FocusDetection != ALGORITHM_SEP || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6690 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6692 m_OpsFocusProcess->focusStarMeasure->clear();
6693 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6694 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6700 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6701 m_OpsFocusProcess->focusCurveFitLabel->show();
6702 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6703 m_OpsFocusProcess->focusCurveFit->show();
6704 if (m_OpsFocusProcess->focusCurveFit->count() != m_CurveFitText.count())
6706 m_OpsFocusProcess->focusCurveFit->clear();
6707 m_OpsFocusProcess->focusCurveFit->addItems(m_CurveFitText);
6708 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_HYPERBOLA);
6711 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
6712 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
6714 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6715 m_OpsFocusProcess->focusUseWeights->hide();
6716 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusDenoise, 3, 0, 1, 2);
6717 m_OpsFocusProcess->focusDenoise->show();
6721 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6722 m_OpsFocusProcess->focusDenoise->hide();
6723 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusUseWeights, 3, 0, 1, 2);
6724 m_OpsFocusProcess->focusUseWeights->show();
6727 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2LimitLabel, 3, 2);
6728 m_OpsFocusProcess->focusR2LimitLabel->show();
6729 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2Limit, 3, 3);
6730 m_OpsFocusProcess->focusR2Limit->show();
6732 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusRefineCurveFit, 4, 0, 1, 2);
6733 m_OpsFocusProcess->focusRefineCurveFit->show();
6735 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 4, 2);
6736 m_OpsFocusProcess->focusFramesCountLabel->show();
6737 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 4, 3);
6738 m_OpsFocusProcess->focusFramesCount->show();
6740 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 5, 2);
6741 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6742 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 5, 3);
6743 m_OpsFocusProcess->focusHFRFramesCount->show();
6745 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6747 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 6, 0);
6748 m_OpsFocusProcess->focusThresholdLabel->show();
6749 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 6, 1);
6750 m_OpsFocusProcess->focusThreshold->show();
6752 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6754 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 6, 0);
6755 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6756 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 6, 1);
6757 m_OpsFocusProcess->focusMultiRowAverage->show();
6759 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 6, 2);
6760 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6761 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 6, 3);
6762 m_OpsFocusProcess->focusGaussianSigma->show();
6764 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 7, 0);
6765 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6766 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 7, 1);
6767 m_OpsFocusProcess->focusGaussianKernelSize->show();
6771 m_OpsFocusProcess->focusDonut->show();
6772 m_OpsFocusProcess->focusDonut->setEnabled(
true);
6775 m_OpsFocusProcess->focusScanStartPos->show();
6776 m_OpsFocusProcess->focusScanStartPos->setEnabled(
true);
6779 startAbInsB->setEnabled(canAbInsStart());
6783 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(canAbsMove);
6787 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6788 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6791 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6793 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6795 m_OpsFocusMechanics->focusWalk->clear();
6796 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6797 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6802 if (m_OpsFocusMechanics->focusWalk->count() != m_FocusWalkText.count())
6804 m_OpsFocusMechanics->focusWalk->clear();
6805 m_OpsFocusMechanics->focusWalk->addItems(m_FocusWalkText);
6806 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6813void Focus::setCurveFit(CurveFitting::CurveFit curve)
6815 if (m_OpsFocusProcess->focusCurveFit->currentIndex() == -1)
6818 static bool first =
true;
6819 if (!first && m_CurveFit == curve)
6825 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
6832 case CurveFitting::FOCUS_QUADRATIC:
6833 m_OpsFocusProcess->focusR2Limit->setEnabled(
false);
6834 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6835 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
false);
6838 case CurveFitting::FOCUS_HYPERBOLA:
6839 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6840 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6843 case CurveFitting::FOCUS_PARABOLA:
6844 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6845 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6848 case CurveFitting::FOCUS_2DGAUSSIAN:
6849 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
6850 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
6858void Focus::setStarMeasure(StarMeasure starMeasure)
6860 if (m_OpsFocusProcess->focusStarMeasure->currentIndex() == -1)
6863 static bool first =
true;
6864 if (!first && m_StarMeasure == starMeasure)
6869 m_StarMeasure = starMeasure;
6870 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
6874 setAutoStarAndBox();
6880 switch(m_StarMeasure)
6882 case FOCUS_STAR_HFR:
6883 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6884 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6885 m_FocusView->setStarsHFREnabled(
true);
6888 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6889 m_OpsFocusProcess->focusStarPSFLabel->hide();
6890 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6891 m_OpsFocusProcess->focusStarPSF->hide();
6894 case FOCUS_STAR_HFR_ADJ:
6895 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6896 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6897 m_FocusView->setStarsHFREnabled(
false);
6900 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6901 m_OpsFocusProcess->focusStarPSFLabel->hide();
6902 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6903 m_OpsFocusProcess->focusStarPSF->hide();
6906 case FOCUS_STAR_FWHM:
6907 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
6908 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6910 m_FocusView->setStarsHFREnabled(
false);
6913 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSFLabel, 2, 2);
6914 m_OpsFocusProcess->focusStarPSFLabel->show();
6915 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSF, 2, 3);
6916 m_OpsFocusProcess->focusStarPSF->show();
6919 case FOCUS_STAR_NUM_STARS:
6920 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6921 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6922 m_FocusView->setStarsHFREnabled(
true);
6925 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6926 m_OpsFocusProcess->focusStarPSFLabel->hide();
6927 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6928 m_OpsFocusProcess->focusStarPSF->hide();
6931 case FOCUS_STAR_FOURIER_POWER:
6932 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6933 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6934 m_FocusView->setStarsHFREnabled(
true);
6937 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6938 m_OpsFocusProcess->focusStarPSFLabel->hide();
6939 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6940 m_OpsFocusProcess->focusStarPSF->hide();
6943 case FOCUS_STAR_STDDEV:
6944 case FOCUS_STAR_SOBEL:
6945 case FOCUS_STAR_LAPLASSIAN:
6946 case FOCUS_STAR_CANNY:
6947 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
6948 m_ScaleCalc = Mathematics::RobustStatistics::ScaleCalculation::SCALE_SESTIMATOR;
6949 m_FocusView->setStarsHFREnabled(
true);
6952 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6953 m_OpsFocusProcess->focusStarPSFLabel->hide();
6954 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6955 m_OpsFocusProcess->focusStarPSF->hide();
6963void Focus::setStarPSF(StarPSF starPSF)
6965 m_StarPSF = starPSF;
6968void Focus::setStarUnits(StarUnits starUnits)
6970 m_StarUnits = starUnits;
6973void Focus::setWalk(FocusWalk walk)
6975 if (m_OpsFocusMechanics->focusWalk->currentIndex() == -1)
6978 static bool first =
true;
6979 if (!first && m_FocusWalk == walk)
6988 case FOCUS_WALK_CLASSIC:
6989 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumStepsLabel,
6990 m_OpsFocusMechanics->focusOutStepsLabel);
6991 m_OpsFocusMechanics->focusNumStepsLabel->hide();
6992 m_OpsFocusMechanics->focusOutStepsLabel->show();
6993 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumSteps,
6994 m_OpsFocusMechanics->focusOutSteps);
6995 m_OpsFocusMechanics->focusNumSteps->hide();
6996 m_OpsFocusMechanics->focusOutSteps->show();
6999 case FOCUS_WALK_FIXED_STEPS:
7000 case FOCUS_WALK_CFZ_SHUFFLE:
7001 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
7002 m_OpsFocusMechanics->focusNumStepsLabel);
7003 m_OpsFocusMechanics->focusOutStepsLabel->hide();
7004 m_OpsFocusMechanics->focusNumStepsLabel->show();
7005 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
7006 m_OpsFocusMechanics->focusNumSteps);
7007 m_OpsFocusMechanics->focusOutSteps->hide();
7008 m_OpsFocusMechanics->focusNumSteps->show();
7017double Focus::getStarUnits(
const StarMeasure starMeasure,
const StarUnits starUnits)
7019 if (starUnits == FOCUS_UNITS_PIXEL || starMeasure == FOCUS_STAR_NUM_STARS || starMeasure == FOCUS_STAR_FOURIER_POWER
7020 || starMeasure == FOCUS_STAR_STDDEV || starMeasure == FOCUS_STAR_SOBEL || starMeasure == FOCUS_STAR_LAPLASSIAN
7021 || starMeasure == FOCUS_STAR_CANNY)
7023 if (m_CcdPixelSizeX <= 0.0 || m_FocalLength <= 0.0)
7027 return m_CcdPixelSizeX / m_FocalLength * 206.265;
7030void Focus::calcCFZ()
7032 double cfzMicrons, cfzSteps;
7033 double cfzCameraSteps = calcCameraCFZ() / m_CFZUI->focusCFZStepSize->value();
7035 switch(
static_cast<Focus::CFZAlgorithm
> (m_CFZUI->focusCFZAlgorithm->currentIndex()))
7037 case Focus::FOCUS_CFZ_CLASSIC:
7039 cfzMicrons = 4.88f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f *
7040 pow(m_CFZUI->focusCFZFNumber->value(), 2.0f);
7041 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7042 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7043 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4.88 t λ f²");
7044 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7045 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7046 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7047 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7050 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
7051 m_CFZUI->focusCFZTauLabel->hide();
7052 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
7053 m_CFZUI->focusCFZTau->hide();
7054 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
7055 m_CFZUI->focusCFZSeeingLabel->hide();
7056 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
7057 m_CFZUI->focusCFZSeeing->hide();
7060 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
7061 m_CFZUI->focusCFZToleranceLabel->show();
7062 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
7063 m_CFZUI->focusCFZTolerance->show();
7064 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
7065 m_CFZUI->focusCFZWavelengthLabel->show();
7066 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
7067 m_CFZUI->focusCFZWavelength->show();
7070 case Focus::FOCUS_CFZ_WAVEFRONT:
7072 cfzMicrons = 4.0f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f * pow(
7073 m_CFZUI->focusCFZFNumber->value(),
7075 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7076 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7077 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4 t λ f²");
7078 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7079 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7080 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7081 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7084 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
7085 m_CFZUI->focusCFZTauLabel->hide();
7086 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
7087 m_CFZUI->focusCFZTau->hide();
7088 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
7089 m_CFZUI->focusCFZSeeingLabel->hide();
7090 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
7091 m_CFZUI->focusCFZSeeing->hide();
7094 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
7095 m_CFZUI->focusCFZToleranceLabel->show();
7096 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
7097 m_CFZUI->focusCFZTolerance->show();
7098 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
7099 m_CFZUI->focusCFZWavelengthLabel->show();
7100 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
7101 m_CFZUI->focusCFZWavelength->show();
7104 case Focus::FOCUS_CFZ_GOLD:
7106 cfzMicrons = 0.00225f * pow(m_CFZUI->focusCFZTau->value(), 0.5f) * m_CFZUI->focusCFZSeeing->value()
7107 * pow(m_CFZUI->focusCFZFNumber->value(), 2.0f) * m_CFZUI->focusCFZAperture->value();
7108 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7109 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7110 m_CFZUI->focusCFZFormula->setText(
"CFZ = 0.00225 √τ θ f² A");
7111 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7112 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7113 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7114 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7117 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZToleranceLabel);
7118 m_CFZUI->focusCFZToleranceLabel->hide();
7119 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTolerance);
7120 m_CFZUI->focusCFZTolerance->hide();
7121 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelengthLabel);
7122 m_CFZUI->focusCFZWavelengthLabel->hide();
7123 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelength);
7124 m_CFZUI->focusCFZWavelength->hide();
7127 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTauLabel, 1, 0);
7128 m_CFZUI->focusCFZTauLabel->show();
7129 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTau, 1, 1);
7130 m_CFZUI->focusCFZTau->show();
7131 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeingLabel, 2, 0);
7132 m_CFZUI->focusCFZSeeingLabel->show();
7133 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeing, 2, 1);
7134 m_CFZUI->focusCFZSeeing->show();
7137 if (linearFocuser !=
nullptr && linearFocuser->isDone())
7138 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
7139 m_CFZUI->focusCFZDisplayVCurve->isChecked());
7145double Focus::calcCameraCFZ()
7147 return m_CcdPixelSizeX * pow(m_CFZUI->focusCFZFNumber->value(), 2.0) * m_CFZUI->focusCFZAperture->value() / 1000.0;
7150void Focus::wavelengthChanged()
7153 if (m_FilterManager)
7155 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
7160void Focus::resetCFZToOT()
7163 m_CFZUI->focusCFZFNumber->setValue(m_FocalRatio);
7164 m_CFZUI->focusCFZAperture->setValue(m_Aperture);
7167 if (m_FilterManager)
7169 if (m_CFZUI->focusCFZWavelength->value() != m_FilterManager->getFilterWavelength(
filter()))
7170 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
7175void Focus::setState(FocusState newState)
7177 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus State changes from" << getFocusStatusString(m_state) <<
"to" << getFocusStatusString(
7180 emit newStatus(m_state, opticalTrain());
7183void Focus::initView()
7185 m_FocusView.reset(
new FITSView(focusingWidget, FITS_FOCUS));
7187 m_FocusView->setBaseSize(focusingWidget->size());
7188 m_FocusView->createFloatingToolBar();
7191 focusingWidget->setLayout(vlayout);
7193 m_FocusView->setStarsEnabled(
true);
7194 m_FocusView->setStarsHFREnabled(
true);
7197QVariantMap Focus::getAllSettings()
const
7199 QVariantMap settings;
7202 for (
auto &oneWidget : findChildren<QComboBox*>())
7203 settings.insert(oneWidget->objectName(), oneWidget->currentText());
7206 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
7207 settings.insert(oneWidget->objectName(), oneWidget->value());
7210 for (
auto &oneWidget : findChildren<QSpinBox*>())
7211 settings.insert(oneWidget->objectName(), oneWidget->value());
7214 for (
auto &oneWidget : findChildren<QCheckBox*>())
7215 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7218 for (
auto &oneWidget : findChildren<QGroupBox*>())
7219 if (oneWidget->isCheckable())
7220 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7223 for (
auto &oneWidget : findChildren<QSplitter*>())
7224 settings.insert(oneWidget->objectName(),
QString::fromUtf8(oneWidget->saveState().toBase64()));
7227 for (
auto &oneWidget : findChildren<QRadioButton*>())
7228 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7233void Focus::setAllSettings(
const QVariantMap &settings)
7237 disconnectSyncSettings();
7239 for (
auto &name : settings.keys())
7242 auto comboBox = findChild<QComboBox*>(name);
7245 syncControl(settings, name, comboBox);
7250 auto doubleSpinBox = findChild<QDoubleSpinBox*>(name);
7253 syncControl(settings, name, doubleSpinBox);
7258 auto spinBox = findChild<QSpinBox*>(name);
7261 syncControl(settings, name, spinBox);
7266 auto checkbox = findChild<QCheckBox*>(name);
7269 syncControl(settings, name, checkbox);
7274 auto groupbox = findChild<QGroupBox*>(name);
7275 if (groupbox && groupbox->isCheckable())
7277 syncControl(settings, name, groupbox);
7282 auto splitter = findChild<QSplitter*>(name);
7285 syncControl(settings, name, splitter);
7290 auto radioButton = findChild<QRadioButton*>(name);
7293 syncControl(settings, name, radioButton);
7299 for (
auto &key : settings.keys())
7301 auto value = settings[key];
7303 Options::self()->setProperty(key.
toLatin1(), value);
7305 m_Settings[key] = value;
7306 m_GlobalSettings[key] = value;
7309 emit settingsUpdated(getAllSettings());
7312 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
7313 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
7316 connectSyncSettings();
7319 m_CurveFit =
static_cast<CurveFitting::CurveFit
> (m_OpsFocusProcess->focusCurveFit->currentIndex());
7320 setFocusDetection(
static_cast<StarAlgorithm
> (m_OpsFocusProcess->focusDetection->currentIndex()));
7321 setCurveFit(
static_cast<CurveFitting::CurveFit
>(m_OpsFocusProcess->focusCurveFit->currentIndex()));
7322 setStarMeasure(
static_cast<StarMeasure
>(m_OpsFocusProcess->focusStarMeasure->currentIndex()));
7323 setWalk(
static_cast<FocusWalk
>(m_OpsFocusMechanics->focusWalk->currentIndex()));
7327bool Focus::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
7338 if ((pSB = qobject_cast<QSpinBox *>(widget)))
7340 const int value = settings[key].toInt(&ok);
7347 else if ((pDSB = qobject_cast<QDoubleSpinBox *>(widget)))
7349 const double value = settings[key].toDouble(&ok);
7356 else if ((pCB = qobject_cast<QCheckBox *>(widget)))
7358 const bool value = settings[key].toBool();
7363 else if ((pGB = qobject_cast<QGroupBox *>(widget)))
7365 const bool value = settings[key].toBool();
7370 else if ((pRadioButton = qobject_cast<QRadioButton *>(widget)))
7372 const bool value = settings[key].toBool();
7374 pRadioButton->
click();
7378 else if ((pComboBox = qobject_cast<QComboBox *>(widget)))
7380 const QString value = settings[key].toString();
7384 else if ((pSplitter = qobject_cast<QSplitter *>(widget)))
7394void Focus::setupOpticalTrainManager()
7396 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Focus::refreshOpticalTrain);
7399 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
7403 ProfileSettings::Instance()->setOneSetting(ProfileSettings::FocusOpticalTrain,
7404 OpticalTrainManager::Instance()->
id(opticalTrainCombo->itemText(index)));
7405 refreshOpticalTrain();
7406 emit trainChanged();
7410void Focus::refreshOpticalTrain()
7412 bool validSettings =
false;
7413 opticalTrainCombo->blockSignals(
true);
7414 opticalTrainCombo->clear();
7415 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
7416 trainB->setEnabled(
true);
7418 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::FocusOpticalTrain);
7422 auto id = trainID.
toUInt();
7425 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
7427 qCWarning(KSTARS_EKOS_FOCUS) <<
"Optical train doesn't exist for id" << id;
7428 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
7431 auto name = OpticalTrainManager::Instance()->name(
id);
7433 opticalTrainCombo->setCurrentText(name);
7439 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
7441 auto focuser = OpticalTrainManager::Instance()->getFocuser(name);
7442 setFocuser(focuser);
7444 auto scope = OpticalTrainManager::Instance()->getScope(name);
7445 double reducer = OpticalTrainManager::Instance()->getReducer(name);
7446 setScopeDetails(scope, reducer);
7448 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Focus);
7449 if (settings.isValid())
7451 validSettings =
true;
7452 auto map = settings.toJsonObject().toVariantMap();
7453 if (map != m_Settings)
7456 setAllSettings(map);
7460 auto camera = OpticalTrainManager::Instance()->getCamera(name);
7463 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(camera->getDeviceName(), scope[
"name"].toString()));
7466 auto nvp = camera->getNumber(
"CCD_INFO");
7469 m_CcdPixelSizeX = 0.0;
7470 m_CcdWidth = m_CcdHeight = 0;
7474 auto np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
7476 m_CcdPixelSizeX = np->getValue();
7477 np = nvp->findWidgetByName(
"CCD_MAX_X");
7479 m_CcdWidth = np->getValue();
7480 np = nvp->findWidgetByName(
"CCD_MAX_Y");
7482 m_CcdHeight = np->getValue();
7487 auto filterWheel = OpticalTrainManager::Instance()->getFilterWheel(name);
7488 setFilterWheel(filterWheel);
7496 focusAdvisor->setupParams(name);
7497 focusAdvisor->updateParams();
7501 opticalTrainCombo->blockSignals(
false);
7505void Focus::setScopeDetails(
const QJsonObject &scope,
const double reducer)
7507 m_Aperture = scope[
"aperture"].toDouble(-1);
7508 m_FocalLength = scope[
"focal_length"].toDouble(-1);
7509 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
7510 m_ScopeType = scope[
"type"].toString();
7511 m_Reducer = reducer;
7514 if (m_Reducer > 0.0)
7515 m_FocalLength *= m_Reducer;
7518 if (m_FocalRatio <= 0.0)
7520 m_FocalRatio = (m_Aperture > 0.001) ? m_FocalLength / m_Aperture : 0.0f;
7521 else if (m_Aperture < 0.0)
7523 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.
QString name(GameStandardAction id)
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)
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