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
74Focus::Focus(
int id) : QWidget()
80 m_opsDialogName =
QString(
"focussettings %1").
arg(
id);
101 loadGlobalSettings();
104 connectSyncSettings();
106 connect(focusAdvisor.get(), &FocusAdvisor::newStage,
this, &Focus::newFocusAdvisorStage);
107 connect(focusAdvisor.get(), &FocusAdvisor::newMessage,
this, &Focus::newFocusAdvisorMessage);
114 for (
auto &button : qButtons)
115 button->setAutoDefault(
false);
117 appendLogText(
i18n(
"Idle."));
120 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
121 m_FocusMotionTimer.setSingleShot(
true);
124 m_OpsFocusProcess->editFocusProfile->setIcon(
QIcon::fromTheme(
"document-edit"));
129 KConfigDialog *optionsEditor = new KConfigDialog(this,
"OptionsProfileEditor", Options::self());
130 optionsProfileEditor = new StellarSolverProfileEditor(this, Ekos::FocusProfiles, optionsEditor);
132 optionsEditor->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
134 KPageWidgetItem *mainPage = optionsEditor->addPage(optionsProfileEditor, i18n(
"Focus Options Profile Editor"));
135 mainPage->setIcon(QIcon::fromTheme(
"configure"));
136 connect(optionsProfileEditor, &StellarSolverProfileEditor::optionsProfilesUpdated, this, &Focus::loadStellarSolverProfiles);
137 optionsProfileEditor->loadProfile(m_OpsFocusProcess->focusSEPProfile->currentText());
138 optionsEditor->show();
141 loadStellarSolverProfiles();
155 m_DarkProcessor =
new DarkProcessor(
this);
157 connect(m_DarkProcessor, &DarkProcessor::darkFrameCompleted,
this, [
this](
bool completed)
159 m_OpsFocusSettings->useFocusDarkFrame->setChecked(completed);
160 m_FocusView->setProperty(
"suspended",
false);
163 m_FocusView->rescale(ZOOM_KEEP_LEVEL);
164 m_FocusView->updateFrame();
166 setCaptureComplete();
170 setupOpticalTrainManager();
174 connectFilterManager();
178void Focus::prepareGUI()
188 m_OpsFocusSettings =
new OpsFocusSettings(opsDialogName());
196 m_OpsFocusProcess =
new OpsFocusProcess(opsDialogName());
197 page = dialog->
addPage(m_OpsFocusProcess,
i18n(
"Process"),
nullptr,
i18n(
"Focus Process"),
false);
200 m_OpsFocusMechanics =
new OpsFocusMechanics(opsDialogName());
201 page = dialog->
addPage(m_OpsFocusMechanics,
i18n(
"Mechanics"),
nullptr,
i18n(
"Focus Mechanics"),
false);
205 m_CFZDialog =
new QDialog(
this);
206 m_CFZUI.reset(
new Ui::focusCFZDialog());
207 m_CFZUI->setupUi(m_CFZDialog);
213 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
214 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
215 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
216 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
217 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
218 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusThreshold);
219 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
220 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
221 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
222 m_OpsFocusProcess->gridLayoutProcessBucket->removeWidget(m_OpsFocusProcess->focusTolerance);
223 delete m_OpsFocusProcess->gridLayoutProcessBucket;
226 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
227 m_OpsFocusMechanics->focusNumStepsLabel);
228 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
229 m_OpsFocusMechanics->focusNumSteps);
233 for (
int i = 0; i < m_OpsFocusProcess->focusStarMeasure->count(); i++)
234 m_StarMeasureText.append(m_OpsFocusProcess->focusStarMeasure->itemText(i));
235 for (
int i = 0; i < m_OpsFocusProcess->focusCurveFit->count(); i++)
236 m_CurveFitText.append(m_OpsFocusProcess->focusCurveFit->itemText(i));
237 for (
int i = 0; i < m_OpsFocusMechanics->focusWalk->count(); i++)
238 m_FocusWalkText.append(m_OpsFocusMechanics->focusWalk->itemText(i));
243 QString savedOptionsProfiles =
QDir(KSPaths::writableLocation(
247 m_StellarSolverProfiles = StellarSolver::loadSavedOptionsProfiles(savedOptionsProfiles);
248 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_NAME);
249 addMissingStellarSolverProfile(savedOptionsProfiles, FOCUS_DEFAULT_DONUT_NAME);
252 m_StellarSolverProfiles = getDefaultFocusOptionsProfiles();
253 m_OpsFocusProcess->focusSEPProfile->clear();
254 for(
auto ¶m : m_StellarSolverProfiles)
255 m_OpsFocusProcess->focusSEPProfile->addItem(param.listName);
256 auto profile = m_Settings[
"focusSEPProfile"];
257 if (profile.isValid())
258 m_OpsFocusProcess->focusSEPProfile->setCurrentText(profile.toString());
261void Focus::addMissingStellarSolverProfile(
const QString profilePath,
const QString profile)
263 for(
auto params : m_StellarSolverProfiles)
265 if (params.listName == profile)
271 SSolver::Parameters params;
272 if (profile == FOCUS_DEFAULT_DONUT_NAME)
273 params = getFocusOptionsProfileDefaultDonut();
274 else if (profile == FOCUS_DEFAULT_NAME)
275 params = getFocusOptionsProfileDefault();
279 settings.beginGroup(params.listName);
285 settings.setValue(it.key(), it.value());
289 m_StellarSolverProfiles.append(params);
295 for (
auto param : m_StellarSolverProfiles)
296 profiles << param.listName;
304 if (focusingWidget->parent() ==
nullptr)
305 toggleFocusingWidgetFullScreen();
310 if (m_Camera && m_Camera->isConnected())
312 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
317 targetChip->resetFrame();
320 targetChip->getFrame(&
x, &
y, &w, &h);
322 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is reset. X:" <<
x <<
"Y:" <<
y <<
"W:" << w <<
"H:" << h <<
"binX:" << 1 <<
"binY:" <<
325 QVariantMap settings;
330 settings[
"binx"] = 1;
331 settings[
"biny"] = 1;
332 frameSettings[targetChip] = settings;
334 starSelected =
false;
338 m_FocusView->setTrackingBox(
QRect());
339 checkMosaicMaskLimits();
347 return m_Camera->getDeviceName();
372 case FOCUS_CHANGING_FILTER:
377 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
378 if (targetChip && targetChip->isCapturing())
383 focusBinning->setEnabled(targetChip->canBin());
384 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
385 if (targetChip->canBin())
387 int subBinX = 1, subBinY = 1;
388 focusBinning->clear();
389 targetChip->getMaxBin(&subBinX, &subBinY);
390 for (
int i = 1; i <= subBinX; i++)
391 focusBinning->addItem(
QString(
"%1x%2").arg(i).arg(i));
393 auto binning = m_Settings[
"focusBinning"];
394 if (binning.isValid())
395 focusBinning->setCurrentText(binning.toString());
399 liveVideoB->setEnabled(m_Camera->hasVideoStream());
400 if (m_Camera->hasVideoStream())
401 setVideoStreamEnabled(m_Camera->isStreamingEnabled());
413 if (m_Camera ==
nullptr)
416 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
417 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
420 auto isoList = targetChip->getISOList();
423 if (isoList.isEmpty())
425 focusISO->setEnabled(
false);
426 ISOLabel->setEnabled(
false);
430 focusISO->setEnabled(
true);
431 ISOLabel->setEnabled(
true);
432 focusISO->addItems(isoList);
433 focusISO->setCurrentIndex(targetChip->getISOIndex());
436 bool hasGain = m_Camera->hasGain();
437 gainLabel->setEnabled(hasGain);
438 focusGain->setEnabled(hasGain && m_Camera->getGainPermission() != IP_RO);
441 double gain = 0, min = 0, max = 0, step = 1;
442 m_Camera->getGainMinMaxStep(&min, &max, &step);
443 if (m_Camera->getGain(&gain))
446 GainSpinSpecialValue = min - step;
447 focusGain->setRange(GainSpinSpecialValue, max);
448 focusGain->setSpecialValueText(
i18n(
"--"));
450 focusGain->setSingleStep(step);
452 auto defaultGain = m_Settings[
"focusGain"];
453 if (defaultGain.isValid())
454 focusGain->setValue(defaultGain.toDouble());
456 focusGain->setValue(GainSpinSpecialValue);
465 if (m_Camera ==
nullptr)
468 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
469 if (targetChip ==
nullptr || (targetChip && targetChip->isCapturing()))
472 m_OpsFocusSettings->focusSubFrame->setEnabled(targetChip->canSubframe());
474 if (frameSettings.contains(targetChip) ==
false)
477 if (targetChip->getFrame(&
x, &
y, &w, &h))
479 int binx = 1, biny = 1;
480 targetChip->getBinning(&binx, &biny);
483 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
484 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
486 QVariantMap settings;
488 settings[
"x"] = m_OpsFocusSettings->focusSubFrame->isChecked() ?
x : minX;
489 settings[
"y"] = m_OpsFocusSettings->focusSubFrame->isChecked() ?
y : minY;
490 settings[
"w"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? w : maxW;
491 settings[
"h"] = m_OpsFocusSettings->focusSubFrame->isChecked() ? h : maxH;
492 settings[
"binx"] = binx;
493 settings[
"biny"] = biny;
495 frameSettings[targetChip] = settings;
503 if (m_FilterWheel && m_FilterWheel == device)
510 m_FilterWheel->disconnect(
this);
512 m_FilterWheel = device;
516 connect(m_FilterWheel, &ISD::ConcreteDevice::Connected,
this, [
this]()
518 FilterPosLabel->setEnabled(
true);
519 focusFilter->setEnabled(
true);
520 filterManagerB->setEnabled(
true);
522 connect(m_FilterWheel, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
524 FilterPosLabel->setEnabled(
false);
525 focusFilter->setEnabled(
false);
526 filterManagerB->setEnabled(
false);
530 auto isConnected = m_FilterWheel && m_FilterWheel->isConnected();
531 FilterPosLabel->setEnabled(isConnected);
532 focusFilter->setEnabled(isConnected);
533 filterManagerB->setEnabled(isConnected);
535 FilterPosLabel->setEnabled(
true);
536 focusFilter->setEnabled(
true);
544 defaultFocusTemperatureSource->blockSignals(
true);
545 m_TemperatureSources = temperatureSources;
547 defaultFocusTemperatureSource->clear();
548 for (
auto device : temperatureSources)
552 defaultFocusTemperatureSource->addItem(device->getDeviceName());
554 defaultFocusTemperatureSource->blockSignals(
false);
556 auto targetSource = m_Settings[
"defaultFocusTemperatureSource"];
557 if (targetSource.isValid())
566 source = defaultFocusTemperatureSource->currentText();
567 if (source.isEmpty())
573 for (
auto &oneSource : m_TemperatureSources)
575 if (oneSource->getDeviceName() == source)
577 currentSource = oneSource;
582 m_LastSourceDeviceAutofocusTemperature = currentSource;
589 for (
const auto &oneSource : m_TemperatureSources)
593 if (findTemperatureElement(currentSource))
595 defaultFocusTemperatureSource->setCurrentText(name);
596 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
597 absoluteTemperatureLabel->setText(
QString(
"%1 °C").arg(currentTemperatureSourceElement->value, 0,
'f', 2));
598 deltaTemperatureLabel->setText(
QString(
"%1 °C").arg(0.0, 0,
'f', 2));
602 m_LastSourceAutofocusTemperature = INVALID_VALUE;
615 auto temperatureProperty = device->getProperty(
"FOCUS_TEMPERATURE");
616 if (!temperatureProperty)
617 temperatureProperty = device->getProperty(
"CCD_TEMPERATURE");
618 if (temperatureProperty)
620 currentTemperatureSourceElement = temperatureProperty.getNumber()->at(0);
624 temperatureProperty = device->getProperty(
"WEATHER_PARAMETERS");
625 if (temperatureProperty)
627 for (
int i = 0; i < temperatureProperty.getNumber()->count(); i++)
629 if (strstr(temperatureProperty.getNumber()->at(i)->getName(),
"_TEMPERATURE"))
631 currentTemperatureSourceElement = temperatureProperty.getNumber()->at(i);
643 return m_FilterWheel->getDeviceName();
653 focusFilter->setCurrentText(filter);
662 return focusFilter->currentText();
667 focusFilter->clear();
671 FilterPosLabel->setEnabled(
false);
672 focusFilter->setEnabled(
false);
673 filterManagerB->setEnabled(
false);
677 m_FilterManager->disconnect(
this);
679 m_FilterManager.reset();
684 FilterPosLabel->setEnabled(
true);
685 focusFilter->setEnabled(
true);
686 filterManagerB->setEnabled(
true);
688 setupFilterManager();
690 focusFilter->addItems(m_FilterManager->getFilterLabels());
692 currentFilterPosition = m_FilterManager->getFilterPosition();
694 focusFilter->setCurrentIndex(currentFilterPosition - 1);
696 focusExposure->setValue(m_FilterManager->getFilterExposure());
701 if (m_Focuser && m_Focuser == device)
708 m_Focuser->disconnect(
this);
714 connect(m_Focuser, &ISD::ConcreteDevice::Connected,
this, [
this]()
718 connect(m_Focuser, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
725 emit focuserChanged(m_focuserId, device !=
nullptr);
732 return m_Focuser->getDeviceName();
742 m_FilterManager->setFocusReady(
false);
743 canAbsMove = canRelMove = canTimerMove =
false;
745 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
750 m_FilterManager->setFocusReady(m_Focuser->isConnected());
752 hasDeviation = m_Focuser->hasDeviation();
754 canAbsMove = m_Focuser->canAbsMove();
758 getAbsFocusPosition();
761 m_FilterManager->setFocusAbsolutePosition(currentPosition);
763 absTicksSpin->setEnabled(
true);
764 absTicksLabel->setEnabled(
true);
765 startGotoB->setEnabled(
true);
768 if (absTicksSpin->value() <= 0)
769 absTicksSpin->setValue(currentPosition);
773 absTicksSpin->setEnabled(
false);
774 absTicksLabel->setEnabled(
false);
775 startGotoB->setEnabled(
false);
778 canRelMove = m_Focuser->canRelMove();
783 if (canAbsMove ==
false && canRelMove ==
true)
785 currentPosition = 50000;
786 absMotionMax = 100000;
790 canTimerMove = m_Focuser->canTimerMove();
796 if (!canAbsMove && !canRelMove && canTimerMove)
798 currentPosition = 50000;
799 absMotionMax = 100000;
803 m_FocusType = (canRelMove || canAbsMove || canTimerMove) ? FOCUS_AUTO : FOCUS_MANUAL;
804 profilePlot->setFocusAuto(m_FocusType == FOCUS_AUTO);
806 bool hasBacklash = m_Focuser->hasBacklash();
807 m_OpsFocusMechanics->focusBacklash->setEnabled(hasBacklash);
808 m_OpsFocusMechanics->focusBacklash->disconnect(
this);
811 double min = 0, max = 0, step = 0;
812 m_Focuser->getMinMaxStep(
"FOCUS_BACKLASH_STEPS",
"FOCUS_BACKLASH_VALUE", &min, &max, &step);
813 m_OpsFocusMechanics->focusBacklash->setMinimum(min);
814 m_OpsFocusMechanics->focusBacklash->setMaximum(max);
815 m_OpsFocusMechanics->focusBacklash->setSingleStep(step);
816 m_OpsFocusMechanics->focusBacklash->setValue(m_Focuser->getBacklash());
818 this, [
this](
int value)
822 if (m_Focuser->getBacklash() == value)
828 m_Focuser->setBacklash(value);
837 m_OpsFocusMechanics->focusBacklash->setValue(0);
843 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
848 if (m_Camera && m_Camera == device)
854 m_captureInProgress =
false;
857 m_Camera->disconnect(
this);
863 connect(m_Camera, &ISD::ConcreteDevice::Connected,
this, [
this]()
867 connect(m_Camera, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
873 auto isConnected = m_Camera && m_Camera->isConnected();
874 focuserGroup->setEnabled(isConnected || (m_Focuser && m_Focuser->isConnected()));
875 ccdGroup->setEnabled(isConnected);
876 toolsGroup->setEnabled(isConnected);
884 checkMosaicMaskLimits();
888void Focus::getAbsFocusPosition()
893 auto absMove = m_Focuser->getNumber(
"ABS_FOCUS_POSITION");
897 const auto &it = absMove->at(0);
898 currentPosition =
static_cast<int>(it->getValue());
899 absMotionMax = it->getMax();
900 absMotionMin = it->getMin();
902 absTicksSpin->setMinimum(it->getMin());
903 absTicksSpin->setMaximum(it->getMax());
904 absTicksSpin->setSingleStep(it->getStep());
907 double const travel = std::abs(it->getMax() - it->getMin());
908 m_OpsFocusMechanics->focusMaxTravel->setMaximum(travel);;
912 m_OpsFocusMechanics->focusTicks->setMaximum(it->getMax() / 2);
918 if (m_LastSourceAutofocusTemperature == INVALID_VALUE && m_LastSourceDeviceAutofocusTemperature
919 && !currentTemperatureSourceElement )
921 if( findTemperatureElement( m_LastSourceDeviceAutofocusTemperature ) )
924 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement->value;
929 if (currentTemperatureSourceElement && currentTemperatureSourceElement->nvp->name == prop.getName())
931 if (m_LastSourceAutofocusTemperature != INVALID_VALUE)
933 delta = currentTemperatureSourceElement->value - m_LastSourceAutofocusTemperature;
934 emit newFocusTemperatureDelta(abs(delta), currentTemperatureSourceElement->value, opticalTrain());
938 emit newFocusTemperatureDelta(0, currentTemperatureSourceElement->value, opticalTrain());
941 absoluteTemperatureLabel->setText(
QString(
"%1 °C").arg(currentTemperatureSourceElement->value, 0,
'f', 2));
942 deltaTemperatureLabel->setText(
QString(
"%1%2 °C").arg((delta > 0.0 ?
"+" :
"")).arg(delta, 0,
'f', 2));
944 deltaTemperatureLabel->setStyleSheet(
"color: lightgreen");
946 deltaTemperatureLabel->setStyleSheet(
"color: lightcoral");
948 deltaTemperatureLabel->setStyleSheet(
"color: lightblue");
952void Focus::setLastFocusTemperature()
954 m_LastSourceAutofocusTemperature = currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE;
957 deltaTemperatureLabel->setText(
QString(
"0 °C"));
958 deltaTemperatureLabel->setStyleSheet(
"color: lightgreen");
960 emit newFocusTemperatureDelta(0, -1e6, opticalTrain());
963void Focus::setLastFocusAlt()
965 if (mountAlt < 0.0 || mountAlt > 90.0)
966 m_LastSourceAutofocusAlt = INVALID_VALUE;
968 m_LastSourceAutofocusAlt = mountAlt;
972void Focus::resetAdaptiveFocus(
bool enabled)
975 Options::setFocusAdaptive(enabled);
978 adaptFocus.reset(
new AdaptiveFocus(
this));
979 adaptFocus->resetAdaptiveFocusCounters();
986 adaptFocus->runAdaptiveFocus(currentPosition, filter());
990void Focus::startAbIns()
992 m_abInsOn = canAbInsStart();
993 runAutoFocus(AutofocusReason::FOCUS_ABERRATION_INSPECTOR,
"");
997void Focus::manualStart()
999 runAutoFocus(AutofocusReason::FOCUS_MANUAL,
"");
1011 m_AutofocusReason = autofocusReason;
1012 m_AutofocusReasonInfo = reasonInfo;
1013 if (m_Focuser ==
nullptr)
1016 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_FOCUSER);
1020 if (m_Camera ==
nullptr)
1023 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_CAMERA);
1027 if (!canAbsMove && !canRelMove && m_OpsFocusMechanics->focusTicks->value() <= MINIMUM_PULSE_TIMER)
1029 appendLogText(
i18n(
"Starting pulse step is too low. Increase the step size to %1 or higher...",
1030 MINIMUM_PULSE_TIMER * 5));
1031 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_LOW_PULSE);
1048 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1056 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1060 if (inAdjustFocus || adaptFocus->inAdaptiveFocus())
1062 QString str = inAdjustFocus ?
i18n(
"Adjust Focus") :
i18n(
"Adaptive Focus");
1063 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
1065 appendLogText(
i18n(
"Autofocus start request - Waiting 10sec for %1 to complete.", str));
1068 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
1073 appendLogText(
i18n(
"Discarding Autofocus start request - %1 in progress.", str));
1074 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
1078 inBuildOffsets = (autofocusReason == AutofocusReason::FOCUS_FILTER_OFFSETS);
1079 if (autofocusReason == AutofocusReason::FOCUS_USER_REQUEST)
1081 forceInSeqAF->setChecked(
false);
1082 emit inSequenceAF(
false, opticalTrain());
1091 if ((m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS) && checkAFOptimisation(autofocusReason))
1095 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_OPTIMISED_OUT);
1101 m_LastFocusDirection = FOCUS_NONE;
1103 waitStarSelectTimer.stop();
1106 m_FocusMotionTimerCounter = 0;
1107 m_FocusMotionTimer.stop();
1108 m_FocusMotionTimer.setInterval(m_OpsFocusMechanics->focusMotionTimeout->value() * 1000);
1111 m_FocuserReconnectCounter = 0;
1114 m_FocuserReconnectCounter = 0;
1115 m_DebugFocuserCounter = 0;
1122 m_RestartState = RESTART_NONE;
1130 getAbsFocusPosition();
1131 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1133 else if (canRelMove)
1137 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1139 absMotionMax = 100000;
1144 pulseDuration = m_OpsFocusMechanics->focusTicks->value();
1146 absMotionMax = 100000;
1150 focuserAdditionalMovement = 0;
1151 starMeasureFrames.clear();
1163 profilePlot->clear();
1164 FWHMOut->setText(
"");
1166 qCInfo(KSTARS_EKOS_FOCUS) <<
"Starting Autofocus " << m_AFRun
1167 <<
" on" << opticalTrain()
1168 <<
" Reason: " << AutofocusReasonStr[m_AutofocusReason]
1169 <<
" Reason Info: " << m_AutofocusReasonInfo
1170 <<
" CanAbsMove: " << (canAbsMove ?
"yes" :
"no" )
1171 <<
" CanRelMove: " << (canRelMove ?
"yes" :
"no" )
1172 <<
" CanTimerMove: " << (canTimerMove ?
"yes" :
"no" )
1173 <<
" Position:" << currentPosition
1174 <<
" Filter:" << filter()
1175 <<
" Exp:" << focusExposure->value()
1176 <<
" Bin:" << focusBinning->currentText()
1177 <<
" Gain:" << focusGain->value()
1178 <<
" ISO:" << focusISO->currentText();
1179 qCInfo(KSTARS_EKOS_FOCUS) <<
"Settings Tab."
1180 <<
" Auto Select Star:" << ( m_OpsFocusSettings->focusAutoStarEnabled->isChecked() ?
"yes" :
"no" )
1181 <<
" Dark Frame:" << ( m_OpsFocusSettings->useFocusDarkFrame->isChecked() ?
"yes" :
"no" )
1182 <<
" Sub Frame:" << ( m_OpsFocusSettings->focusSubFrame->isChecked() ?
"yes" :
"no" )
1183 <<
" Box:" << m_OpsFocusSettings->focusBoxSize->value()
1184 <<
" Full frame:" << ( m_OpsFocusSettings->focusUseFullField->isChecked() ?
"yes" :
"no " )
1185 <<
" Focus Mask: " << (m_OpsFocusSettings->focusNoMaskRB->isChecked() ?
"Use all stars" :
1186 (m_OpsFocusSettings->focusRingMaskRB->isChecked() ?
QString(
"Ring Mask: [%1%, %2%]").
1187 arg(m_OpsFocusSettings->focusFullFieldInnerRadius->value()).
arg(m_OpsFocusSettings->focusFullFieldOuterRadius->value()) :
1188 QString(
"Mosaic Mask: [%1%, space=%2px]").
1189 arg(m_OpsFocusSettings->focusMosaicTileWidth->value()).
arg(m_OpsFocusSettings->focusMosaicSpace->value())))
1190 <<
" Suspend Guiding:" << ( m_OpsFocusSettings->focusSuspendGuiding->isChecked() ?
"yes" :
"no " )
1191 <<
" Guide Settle:" << m_OpsFocusSettings->focusGuideSettleTime->value()
1192 <<
" Display Units:" << m_OpsFocusSettings->focusUnits->currentText()
1193 <<
" AF Optimize:" << m_OpsFocusSettings->focusAFOptimize->value()
1194 <<
" Adaptive Focus:" << ( m_OpsFocusSettings->focusAdaptive->isChecked() ?
"yes" :
"no" )
1195 <<
" Min Move:" << m_OpsFocusSettings->focusAdaptiveMinMove->value()
1196 <<
" Adapt Start:" << ( m_OpsFocusSettings->focusAdaptStart->isChecked() ?
"yes" :
"no" )
1197 <<
" Max Total Move:" << m_OpsFocusSettings->focusAdaptiveMaxMove->value();
1198 qCInfo(KSTARS_EKOS_FOCUS) <<
"Process Tab."
1199 <<
" Detection:" << m_OpsFocusProcess->focusDetection->currentText()
1200 <<
" SEP Profile:" << m_OpsFocusProcess->focusSEPProfile->currentText()
1201 <<
" Algorithm:" << m_OpsFocusProcess->focusAlgorithm->currentText()
1202 <<
" Curve Fit:" << m_OpsFocusProcess->focusCurveFit->currentText()
1203 <<
" Measure:" << m_OpsFocusProcess->focusStarMeasure->currentText()
1204 <<
" PSF:" << m_OpsFocusProcess->focusStarPSF->currentText()
1205 <<
" Use Weights:" << ( m_OpsFocusProcess->focusUseWeights->isChecked() ?
"yes" :
"no" )
1206 <<
" R2 Limit:" << m_OpsFocusProcess->focusR2Limit->value()
1207 <<
" Refine Curve Fit:" << ( m_OpsFocusProcess->focusRefineCurveFit->isChecked() ?
"yes" :
"no" )
1208 <<
" Average Over:" << m_OpsFocusProcess->focusFramesCount->value()
1209 <<
" Average HFR Check Over:" << m_OpsFocusProcess->focusHFRFramesCount->value()
1210 <<
" Num.of Rows:" << m_OpsFocusProcess->focusMultiRowAverage->value()
1211 <<
" Sigma:" << m_OpsFocusProcess->focusGaussianSigma->value()
1212 <<
" Threshold:" << m_OpsFocusProcess->focusThreshold->value()
1213 <<
" Kernel size:" << m_OpsFocusProcess->focusGaussianKernelSize->value()
1214 <<
" Tolerance:" << m_OpsFocusProcess->focusTolerance->value()
1215 <<
" Denoise:" << ( m_OpsFocusProcess->focusDenoise->isChecked() ?
"yes" :
"no" )
1216 <<
" Donut Buster:" << ( m_OpsFocusProcess->focusDonut->isChecked() ?
"yes" :
"no" )
1217 <<
" Donut Time Dilation:" << m_OpsFocusProcess->focusTimeDilation->value()
1218 <<
" Outlier Rejection:" << m_OpsFocusProcess->focusOutlierRejection->value()
1219 <<
" Scan Start Pos:" << ( m_OpsFocusProcess->focusScanStartPos->isChecked() ?
"yes" :
"no" )
1220 <<
" Scan Always On:" << ( m_OpsFocusProcess->focusScanAlwaysOn->isChecked() ?
"yes" :
"no" )
1221 <<
" Num Datapoints:" << m_OpsFocusProcess->focusScanDatapoints->value()
1222 <<
" Scan Step Factor:" << m_OpsFocusProcess->focusScanStepSizeFactor->value();
1223 qCInfo(KSTARS_EKOS_FOCUS) <<
"Mechanics Tab."
1224 <<
" Initial Step Size:" << m_OpsFocusMechanics->focusTicks->value()
1225 <<
" Out Step Multiple:" << m_OpsFocusMechanics->focusOutSteps->value()
1226 <<
" Number Steps:" << m_OpsFocusMechanics->focusNumSteps->value()
1227 <<
" Max Travel:" << m_OpsFocusMechanics->focusMaxTravel->value()
1228 <<
" Max Step Size:" << m_OpsFocusMechanics->focusMaxSingleStep->value()
1229 <<
" Driver Backlash:" << m_OpsFocusMechanics->focusBacklash->value()
1230 <<
" AF Overscan:" << m_OpsFocusMechanics->focusAFOverscan->value()
1231 <<
" Overscan Delay:" << m_OpsFocusMechanics->focusOverscanDelay->value()
1232 <<
" Focuser Settle:" << m_OpsFocusMechanics->focusSettleTime->value()
1233 <<
" Walk:" << m_OpsFocusMechanics->focusWalk->currentText()
1234 <<
" Capture Timeout:" << m_OpsFocusMechanics->focusCaptureTimeout->value()
1235 <<
" Motion Timeout:" << m_OpsFocusMechanics->focusMotionTimeout->value();
1236 qCInfo(KSTARS_EKOS_FOCUS) <<
"CFZ Tab."
1237 <<
" Algorithm:" << m_CFZUI->focusCFZAlgorithm->currentText()
1238 <<
" Tolerance:" << m_CFZUI->focusCFZTolerance->value()
1239 <<
" Tolerance (Ï„):" << m_CFZUI->focusCFZTau->value()
1240 <<
" Display:" << ( m_CFZUI->focusCFZDisplayVCurve->isChecked() ?
"yes" :
"no" )
1241 <<
" Wavelength (λ):" << m_CFZUI->focusCFZWavelength->value()
1242 <<
" Aperture (A):" << m_CFZUI->focusCFZAperture->value()
1243 <<
" Focal Ratio (f):" << m_CFZUI->focusCFZFNumber->value()
1244 <<
" Step Size:" << m_CFZUI->focusCFZStepSize->value()
1245 <<
" FWHM (θ):" << m_CFZUI->focusCFZSeeing->value();
1247 const double temperature = (currentTemperatureSourceElement) ? currentTemperatureSourceElement->value : INVALID_VALUE;
1248 emit autofocusStarting(temperature, filter(), m_AutofocusReason, m_AutofocusReasonInfo);
1255 if (m_GuidingSuspended ==
false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
1257 m_GuidingSuspended =
true;
1258 emit suspendGuiding();
1262 setState(Ekos::FOCUS_PROGRESS);
1264 KSNotification::event(
QLatin1String(
"FocusStarted"),
i18n(
"Autofocus operation started"), KSNotification::Focus);
1267 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1269 m_AFfilter = filter();
1270 int position = adaptFocus->adaptStartPosition(currentPosition, m_AFfilter);
1272 curveFitting.reset(
new CurveFitting());
1274 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
1277 starFitting.reset(
new CurveFitting());
1278 focusFWHM.reset(
new FocusFWHM(m_ScaleCalc));
1279 focusFourierPower.reset(
new FocusFourierPower(m_ScaleCalc));
1280#if defined(HAVE_OPENCV)
1281 focusBlurriness.reset(
new FocusBlurriness());
1284 initDonutProcessing();
1286 if (initScanStartPos(
false, currentPosition))
1289 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
1291 focusAdvisor->initControl();
1297 setupLinearFocuser(position);
1298 if (!changeFocus(linearRequestedPosition - currentPosition))
1299 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
1307bool Focus::checkAFOptimisation(
const AutofocusReason autofocusReason)
1309 bool dontRunAF =
false;
1310 inAFOptimise =
false;
1313 if (!m_FilterManager || m_OpsFocusSettings->focusAFOptimize->value() <= 0)
1318 if (autofocusReason != FOCUS_FILTER &&
1319 autofocusReason != FOCUS_TIME &&
1320 autofocusReason != FOCUS_TEMPERATURE &&
1321 autofocusReason != FOCUS_HFR_CHECK &&
1322 autofocusReason != FOCUS_SCHEDULER)
1326 QString filterToUse = filter();
1327 QString lockFilter = m_FilterManager->getFilterLock(filterToUse);
1328 if (lockFilter != NULL_FILTER && lockFilter != filterToUse)
1329 filterToUse = lockFilter;
1333 if (!m_FilterManager->getAFDatetime(filterToUse, lastAFDatetime))
1335 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 unable to get last Autofocus run timestamp on %2")
1336 .
arg(__FUNCTION__).
arg(filterToUse);
1341 QDateTime now = KStarsData::Instance()->lt();
1342 auto lastAFDelta = lastAFDatetime.
secsTo(now);
1343 if (lastAFDelta > m_OpsFocusSettings->focusAFOptimize->value())
1347 int position = currentPosition;
1348 if (m_OpsFocusSettings->focusAdaptStart->isChecked())
1349 position = adaptFocus->adaptStartPosition(currentPosition, filterToUse);
1353 double lastTemp, lastAlt;
1354 if(!m_FilterManager->getFilterAbsoluteFocusDetails(filterToUse, position, lastTemp, lastAlt))
1357 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 unable to get last Autofocus info on %2")
1358 .
arg(__FUNCTION__).
arg(filterToUse);
1362 int minTravelLimit = qMax(0.0, currentPosition - m_OpsFocusMechanics->focusMaxTravel->value());
1363 int maxTravelLimit = qMin(absMotionMax, currentPosition + m_OpsFocusMechanics->focusMaxTravel->value());
1364 if (position < minTravelLimit || position > maxTravelLimit)
1366 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 Bad last Autofocus solution found on %2")
1367 .
arg(__FUNCTION__).
arg(position);
1374 if (filterToUse !=
filter())
1376 int filterOffset = m_FilterManager->getFilterOffset(
filter());
1377 int filterToUseOffset = m_FilterManager->getFilterOffset(filterToUse);
1378 if (filterOffset != INVALID_VALUE && filterToUseOffset != INVALID_VALUE)
1379 position += filterOffset - filterToUseOffset;
1382 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 unable to calculate filter offsets").
arg(__FUNCTION__);
1388 if (abs(position - currentPosition) <= 1)
1392 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Autofocus (%1) on %2 optimised out by Autofocus at %3")
1393 .
arg(AutofocusReasonStr[autofocusReason]).
arg(filterToUse).
arg(lastAFDatetime.
toString());
1398 if (changeFocus(position - currentPosition))
1400 inAFOptimise = dontRunAF =
true;
1401 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Autofocus (%1) on %2 optimised out by Autofocus at %3."
1402 " Current Position %4, Target Position %5")
1403 .
arg(AutofocusReasonStr[autofocusReason]).
arg(filterToUse)
1407 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"%1 unable to move focuser... trying full Autofocus").
arg(__FUNCTION__);
1412void Focus::setupLinearFocuser(
int initialPosition)
1414 FocusAlgorithmInterface::FocusParams params(curveFitting.get(),
1415 m_OpsFocusMechanics->focusMaxTravel->value(), m_OpsFocusMechanics->focusTicks->value(), initialPosition, absMotionMin,
1416 absMotionMax, MAXIMUM_ABS_ITERATIONS, m_OpsFocusProcess->focusTolerance->value() / 100.0, m_AFfilter,
1417 currentTemperatureSourceElement ? currentTemperatureSourceElement->value : INVALID_VALUE,
1418 m_OpsFocusMechanics->focusOutSteps->value(), m_OpsFocusMechanics->focusNumSteps->value(),
1419 m_FocusAlgorithm, m_OpsFocusMechanics->focusBacklash->value(), m_CurveFit, m_OpsFocusProcess->focusUseWeights->isChecked(),
1420 m_StarMeasure, m_StarPSF, m_OpsFocusProcess->focusRefineCurveFit->isChecked(), m_FocusWalk,
1421 m_OpsFocusProcess->focusDonut->isChecked(), m_OpsFocusProcess->focusOutlierRejection->value(), m_OptDir, m_ScaleCalc);
1424 initialFocuserAbsPosition = initialPosition;
1425 linearFocuser.reset(MakeLinearFocuser(params));
1426 linearRequestedPosition = linearFocuser->initialPosition();
1430void Focus::initDonutProcessing()
1432 if (!m_OpsFocusProcess->focusDonut->isChecked())
1435 m_donutOrigExposure = focusExposure->value();
1439void Focus::resetDonutProcessing()
1442 if (m_OpsFocusProcess->focusDonut->isChecked() && inAutoFocus)
1443 focusExposure->setValue(m_donutOrigExposure);
1446int Focus::adjustLinearPosition(
int position,
int newPosition,
int overscan,
bool updateDir)
1448 if (overscan > 0 && newPosition > position)
1451 int adjustment = overscan;
1452 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Linear: extending outward movement by overscan %1").
arg(adjustment);
1454 if (newPosition + adjustment > absMotionMax)
1455 adjustment =
static_cast<int>(absMotionMax) - newPosition;
1457 focuserAdditionalMovement = adjustment;
1458 focuserAdditionalMovementUpdateDir = updateDir;
1460 return newPosition + adjustment;
1470 m_abortInProgress =
true;
1473 resetFocusIteration = MAXIMUM_RESET_ITERATIONS + 1;
1475 if (captureTimer.isActive())
1477 captureTimer.stop();
1479 if (m_captureInProgress)
1481 if (inAutoFocus ==
false && inFocusLoop ==
false)
1483 captureB->setEnabled(
true);
1484 stopFocusB->setEnabled(
false);
1488 else if (inAutoFocus)
1490 stopFocusB->setEnabled(
false);
1500 if (m_starDetectInProgress)
1502 stopFocusB->setEnabled(
false);
1511 completeFocusProcedure(
abort ? Ekos::FOCUS_ABORTED : Ekos::FOCUS_FAILED, Ekos::FOCUS_FAIL_ABORT);
1517 if (state() == FOCUS_IDLE || state() == FOCUS_COMPLETE || state() == FOCUS_FAILED || state() == FOCUS_ABORTED)
1521 int old = resetFocusIteration;
1525 resetFocusIteration = old;
1531 if (state() <= FOCUS_ABORTED)
1535 if (focusAdvisor->inFocusAdvisor())
1537 focusAdvisor->stop();
1543void Focus::processAbort()
1545 bool focusLoop = inFocusLoop;
1546 checkStopFocus(
true);
1547 appendLogText(
i18n(
"Autofocus aborted."));
1554void Focus::stop(Ekos::FocusState completionState)
1556 Q_UNUSED(completionState);
1557 qCDebug(KSTARS_EKOS_FOCUS) <<
"Stopping Focus";
1559 captureTimeout.stop();
1560 m_FocusMotionTimer.stop();
1561 m_FocusMotionTimerCounter = 0;
1562 m_FocuserReconnectCounter = 0;
1564 opticalTrainCombo->setEnabled(
true);
1565 trainB->setEnabled(
true);
1566 resetDonutProcessing();
1567 inAutoFocus =
false;
1568 inAdjustFocus =
false;
1569 adaptFocus->setInAdaptiveFocus(
false);
1570 inBuildOffsets =
false;
1571 inAFOptimise =
false;
1572 inScanStartPos =
false;
1573 focusAdvisor->reset();
1574 m_AutofocusReason = AutofocusReason::FOCUS_NONE;
1575 m_AutofocusReasonInfo =
"";
1576 focuserAdditionalMovement = 0;
1577 focuserAdditionalMovementUpdateDir =
true;
1578 inFocusLoop =
false;
1579 m_captureInProgress =
false;
1580 m_abortInProgress =
false;
1581 m_starDetectInProgress =
false;
1582 isVShapeSolution =
false;
1583 captureFailureCounter = 0;
1584 minimumRequiredHFR = INVALID_STAR_MEASURE;
1586 starMeasureFrames.clear();
1596 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
1598 if (rememberUploadMode != m_Camera->getUploadMode())
1599 m_Camera->setUploadMode(rememberUploadMode);
1602 if (m_RememberCameraFastExposure)
1604 m_RememberCameraFastExposure =
false;
1605 m_Camera->setFastExposureEnabled(
true);
1608 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1609 targetChip->abortExposure();
1618 if (m_GuidingSuspended)
1620 emit resumeGuiding();
1621 m_GuidingSuspended =
false;
1627 if (m_abortInProgress)
1630 m_captureInProgress =
false;
1631 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding capture request.";
1637 if (settleTime > 0 && m_captureInProgress ==
false)
1639 captureTimer.start(
static_cast<int>(settleTime * 1000));
1643 if (m_captureInProgress)
1645 qCWarning(KSTARS_EKOS_FOCUS) <<
"Capture called while already in progress. Capture is ignored.";
1649 if (m_Camera ==
nullptr)
1656 if (m_Camera->isConnected() ==
false)
1664 captureTimeout.stop();
1666 waitStarSelectTimer.stop();
1668 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
1670 if (m_Camera->isBLOBEnabled() ==
false)
1672 m_Camera->setBLOBEnabled(
true);
1675 if (focusFilter->currentIndex() != -1)
1677 if (m_FilterWheel ==
nullptr)
1683 if (m_FilterWheel->isConnected() ==
false)
1693 int targetPosition = focusFilter->currentIndex() + 1;
1694 if (!inBuildOffsets)
1696 QString lockedFilter = m_FilterManager->getFilterLock(filter());
1701 if (lockedFilter !=
"--" && lockedFilter != filter())
1703 int lockedFilterIndex = focusFilter->findText(lockedFilter);
1704 if (lockedFilterIndex >= 0)
1707 fallbackFilterPending =
true;
1708 fallbackFilterPosition = targetPosition;
1709 targetPosition = lockedFilterIndex + 1;
1714 filterPositionPending = (targetPosition != currentFilterPosition);
1715 if (filterPositionPending)
1720 FilterManager::FilterPolicy policy = (inAutoFocus) ?
1721 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY) :
1722 static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY | FilterManager::OFFSET_POLICY);
1723 m_FilterManager->setFilterPosition(targetPosition, policy);
1726 else if (targetPosition != focusFilter->currentIndex() + 1)
1727 focusFilter->setCurrentIndex(targetPosition - 1);
1730 m_FocusView->setProperty(
"suspended", m_OpsFocusSettings->useFocusDarkFrame->isChecked());
1731 prepareCapture(targetChip);
1736 if (frameSettings.contains(targetChip))
1738 QVariantMap settings = frameSettings[targetChip];
1739 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
1740 settings[
"h"].toInt());
1741 settings[
"binx"] = (focusBinning->currentIndex() + 1);
1742 settings[
"biny"] = (focusBinning->currentIndex() + 1);
1743 frameSettings[targetChip] = settings;
1746 m_captureInProgress =
true;
1747 if (state() != FOCUS_PROGRESS)
1748 setState(FOCUS_PROGRESS);
1750 m_FocusView->setBaseSize(focusingWidget->size());
1752 if (targetChip->capture(focusExposure->value()))
1756 captureTimeout.start( (focusExposure->value() + m_OpsFocusMechanics->focusCaptureTimeout->value()) * 1000);
1758 if (inFocusLoop ==
false)
1763 else if (inAutoFocus)
1765 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
1771 if (m_Camera->getUploadMode() == ISD::Camera::UPLOAD_REMOTE)
1773 rememberUploadMode = ISD::Camera::UPLOAD_REMOTE;
1774 m_Camera->setUploadMode(ISD::Camera::UPLOAD_CLIENT);
1778 if (m_Camera->isFastExposureEnabled())
1780 m_RememberCameraFastExposure =
true;
1781 m_Camera->setFastExposureEnabled(
false);
1784 m_Camera->setEncodingFormat(
"FITS");
1785 targetChip->setBatchMode(
false);
1786 targetChip->setBinning((focusBinning->currentIndex() + 1), (focusBinning->currentIndex() + 1));
1787 targetChip->setCaptureMode(FITS_FOCUS);
1788 targetChip->setFrameType(FRAME_LIGHT);
1789 targetChip->setCaptureFilter(FITS_NONE);
1791 if (isFocusISOEnabled() && focusISO->currentIndex() != -1 &&
1792 targetChip->getISOIndex() != focusISO->currentIndex())
1793 targetChip->setISOIndex(focusISO->currentIndex());
1795 if (isFocusGainEnabled() && focusGain->value() != GainSpinSpecialValue)
1796 m_Camera->setGain(focusGain->value());
1801 if (currentPosition == absMotionMin)
1806 focusInB->setEnabled(
false);
1807 focusOutB->setEnabled(
false);
1808 startGotoB->setEnabled(
false);
1810 ms = m_OpsFocusMechanics->focusTicks->value();
1815 if (currentPosition - ms <= absMotionMin)
1817 ms = currentPosition - absMotionMin;
1820 return changeFocus(-ms);
1825 if (currentPosition == absMotionMax)
1830 focusInB->setEnabled(
false);
1831 focusOutB->setEnabled(
false);
1832 startGotoB->setEnabled(
false);
1834 ms = m_OpsFocusMechanics->focusTicks->value();
1835 ms = m_OpsFocusMechanics->focusTicks->value();
1840 if (currentPosition + ms >= absMotionMax)
1842 ms = absMotionMax - currentPosition;
1845 return changeFocus(ms);
1850bool Focus::changeFocus(
int amount,
bool updateDir)
1854 if (inAutoFocus && abs(amount) <= 1)
1856 if (m_RestartState == RESTART_NOW)
1863 capture(m_OpsFocusMechanics->focusSettleTime->value());
1868 if (m_Focuser ==
nullptr)
1870 appendLogText(
i18n(
"Error: No Focuser detected."));
1871 checkStopFocus(
true);
1875 if (m_Focuser->isConnected() ==
false)
1877 appendLogText(
i18n(
"Error: Lost connection to Focuser."));
1878 checkStopFocus(
true);
1882 const int newPosition = adjustLinearPosition(currentPosition, currentPosition + amount,
1883 m_OpsFocusMechanics->focusAFOverscan->value(),
1885 if (newPosition == currentPosition)
1888 const int newAmount = newPosition - currentPosition;
1889 const int absNewAmount = abs(newAmount);
1890 const bool focusingOut = newAmount > 0;
1891 const QString dirStr = focusingOut ?
i18n(
"outward") :
i18n(
"inward");
1894 m_LastFocusDirection = (focusingOut) ? FOCUS_OUT : FOCUS_IN;
1897 m_Focuser->focusOut();
1899 m_Focuser->focusIn();
1902 m_FocusMotionTimer.start();
1906 m_LastFocusSteps = newPosition;
1907 m_Focuser->moveAbs(newPosition);
1908 appendLogText(
i18n(
"Focusing %2 by %1 steps...", abs(absNewAmount), dirStr));
1910 else if (canRelMove)
1912 m_LastFocusSteps = absNewAmount;
1913 m_Focuser->moveRel(absNewAmount);
1914 appendLogText(
i18np(
"Focusing %2 by %1 step...",
"Focusing %2 by %1 steps...", absNewAmount, dirStr));
1918 m_LastFocusSteps = absNewAmount;
1919 m_Focuser->moveByTimer(absNewAmount);
1920 appendLogText(
i18n(
"Focusing %2 by %1 ms...", absNewAmount, dirStr));
1926void Focus::handleFocusMotionTimeout()
1946 qCDebug(KSTARS_EKOS_FOCUS) <<
"handleFocusMotionTimeout() called while not in AutoFocus";
1950 m_FocusMotionTimerCounter++;
1952 if (m_FocusMotionTimerCounter > 4)
1955 appendLogText(
i18n(
"Focuser is still timing out. Aborting..."));
1956 stop(Ekos::FOCUS_ABORTED);
1959 else if (m_FocusMotionTimerCounter > 2)
1961 QString focuser = m_Focuser->getDeviceName();
1962 appendLogText(
i18n(
"Focus motion timed out (%1). Restarting focus driver %2", m_FocusMotionTimerCounter, focuser));
1963 emit focuserTimedout(focuser);
1967 Focus::reconnectFocuser(focuser);
1972 if (!changeFocus(m_LastFocusSteps - currentPosition))
1973 appendLogText(
i18n(
"Focus motion timed out (%1). Focusing to %2 steps...", m_FocusMotionTimerCounter, m_LastFocusSteps));
1978 const bool useFullField = m_OpsFocusSettings->focusUseFullField->isChecked();
1979 ImageMaskType masktype;
1980 if (m_OpsFocusSettings->focusRingMaskRB->isChecked())
1981 masktype = FOCUS_MASK_RING;
1982 else if (m_OpsFocusSettings->focusMosaicMaskRB->isChecked())
1983 masktype = FOCUS_MASK_MOSAIC;
1985 masktype = FOCUS_MASK_NONE;
1988 m_OpsFocusSettings->focusRingMaskRB->setEnabled(
useFullField);
1989 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(
useFullField);
1991 m_OpsFocusSettings->focusFullFieldInnerRadius->setEnabled(
useFullField && masktype == FOCUS_MASK_RING);
1992 m_OpsFocusSettings->focusFullFieldOuterRadius->setEnabled(
useFullField && masktype == FOCUS_MASK_RING);
1994 m_OpsFocusSettings->focusMosaicTileWidth->setEnabled(
useFullField && masktype == FOCUS_MASK_MOSAIC);
1995 m_OpsFocusSettings->focusSpacerLabel->setEnabled(
useFullField && masktype == FOCUS_MASK_MOSAIC);
1996 m_OpsFocusSettings->focusMosaicSpace->setEnabled(
useFullField && masktype == FOCUS_MASK_MOSAIC);
1999 if (masktype == FOCUS_MASK_RING)
2000 m_FocusView->setImageMask(
new ImageRingMask(m_OpsFocusSettings->focusFullFieldInnerRadius->value() / 100.0,
2001 m_OpsFocusSettings->focusFullFieldOuterRadius->value() / 100.0));
2002 else if (masktype == FOCUS_MASK_MOSAIC)
2003 m_FocusView->setImageMask(
new ImageMosaicMask(m_OpsFocusSettings->focusMosaicTileWidth->value(),
2004 m_OpsFocusSettings->focusMosaicSpace->value()));
2006 m_FocusView->setImageMask(
nullptr);
2008 checkMosaicMaskLimits();
2009 m_currentImageMask = masktype;
2010 startAbInsB->setEnabled(canAbInsStart());
2015 m_FocuserReconnectCounter++;
2017 if (m_Focuser && m_Focuser->getDeviceName() ==
focuser)
2021 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
2025 if (m_FocuserReconnectCounter > 12)
2029 stop(Ekos::FOCUS_ABORTED);
2042 if (data->property(
"chip").toInt() == ISD::CameraChip::GUIDE_CCD)
2047 m_FocusView->loadData(data);
2051 m_ImageData.reset();
2053 captureTimeout.stop();
2054 captureTimeoutCounter = 0;
2055 m_MissingCameraCounter = 0;
2057 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
2059 disconnect(m_Camera, &ISD::Camera::error,
this, &Ekos::Focus::processCaptureError);
2061 if (m_ImageData && m_OpsFocusSettings->useFocusDarkFrame->isChecked())
2063 QVariantMap settings = frameSettings[targetChip];
2064 uint16_t offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
2065 uint16_t offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
2067 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()),
2068 targetChip, m_ImageData, focusExposure->value(), offsetX, offsetY);
2072 setCaptureComplete();
2076void Focus::starDetectionFinished()
2078 m_starDetectInProgress =
false;
2079 if (m_abortInProgress)
2082 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding results from " << __FUNCTION__;
2086 appendLogText(
i18n(
"Detection complete."));
2089 double hfr = INVALID_STAR_MEASURE;
2091 if (isStarMeasureStarBased())
2093 appendLogText(
i18n(
"Detection complete."));
2095 if (m_StarFinderWatcher.result() ==
false)
2097 qCWarning(KSTARS_EKOS_FOCUS) <<
"Failed to extract any stars.";
2101 if (m_OpsFocusSettings->focusUseFullField->isChecked())
2103 m_FocusView->filterStars();
2106 hfr = m_ImageData->getHFR(m_StarMeasure == FOCUS_STAR_HFR_ADJ ? HFR_ADJ_AVERAGE : HFR_AVERAGE);
2110 m_FocusView->setTrackingBoxEnabled(
true);
2115 if (starCenter.isNull() ==
false)
2116 hfr = m_ImageData->getHFR(starCenter.x(), starCenter.y());
2120 hfr = m_ImageData->getHFR(m_FocusDetection == ALGORITHM_SEP ? HFR_HIGH : HFR_MAX);
2126 currentNumStars = m_ImageData->getDetectedStars();
2129 if (m_StarMeasure == FOCUS_STAR_NUM_STARS)
2131 currentMeasure = currentNumStars;
2132 currentWeight = 1.0;
2134 else if (m_StarMeasure == FOCUS_STAR_FWHM)
2136 getFWHM(m_ImageData->getStarCenters(), ¤tFWHM, ¤tWeight);
2137 currentMeasure = currentFWHM;
2139 else if (m_StarMeasure == FOCUS_STAR_FOURIER_POWER)
2141 getFourierPower(¤tFourierPower, ¤tWeight);
2142 currentMeasure = currentFourierPower;
2144 else if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
2145 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
2148 if (m_OpsFocusSettings->focusSubFrame->isChecked())
2149 roi = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2150 getBlurriness(m_StarMeasure, m_OpsFocusProcess->focusDenoise->isChecked(), ¤tBlurriness, ¤tWeight, roi);
2151 currentMeasure = currentBlurriness;
2155 currentMeasure = currentHFR;
2157 std::vector<double> hfrs(stars.
size());
2162 currentWeight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), hfrs);
2164 setCurrentMeasure();
2170bool Focus::isStarMeasureStarBased()
2172 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL || m_StarMeasure == FOCUS_STAR_LAPLASSIAN
2173 || m_StarMeasure == FOCUS_STAR_CANNY)
2179void Focus::getFWHM(
const QList<Edge *> &stars,
double *FWHM,
double *weight)
2181 *FWHM = INVALID_STAR_MEASURE;
2184 auto imageBuffer = m_ImageData->getImageBuffer();
2186 switch (m_ImageData->getStatistics().dataType)
2189 focusFWHM->processFWHM(
reinterpret_cast<uint8_t
const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2193 focusFWHM->processFWHM(
reinterpret_cast<short const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2197 focusFWHM->processFWHM(
reinterpret_cast<unsigned short const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM,
2202 focusFWHM->processFWHM(
reinterpret_cast<long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2206 focusFWHM->processFWHM(
reinterpret_cast<unsigned long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2210 focusFWHM->processFWHM(
reinterpret_cast<float const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2214 focusFWHM->processFWHM(
reinterpret_cast<long long const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2218 focusFWHM->processFWHM(
reinterpret_cast<double const *
>(imageBuffer), stars, m_ImageData, starFitting, FWHM, weight);
2222 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2223 " Cannot calc FWHM";
2229void Focus::getFourierPower(
double *fourierPower,
double *weight,
const int mosaicTile)
2231 *fourierPower = INVALID_STAR_MEASURE;
2234 auto imageBuffer = m_ImageData->getImageBuffer();
2236 switch (m_ImageData->getStatistics().dataType)
2239 focusFourierPower->processFourierPower(
reinterpret_cast<uint8_t
const *
>(imageBuffer), m_ImageData,
2240 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2244 focusFourierPower->processFourierPower(
reinterpret_cast<short const *
>(imageBuffer), m_ImageData,
2245 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2249 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned short const *
>(imageBuffer), m_ImageData,
2250 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2254 focusFourierPower->processFourierPower(
reinterpret_cast<long const *
>(imageBuffer), m_ImageData,
2255 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2259 focusFourierPower->processFourierPower(
reinterpret_cast<unsigned long const *
>(imageBuffer), m_ImageData,
2260 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2264 focusFourierPower->processFourierPower(
reinterpret_cast<float const *
>(imageBuffer), m_ImageData,
2265 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2269 focusFourierPower->processFourierPower(
reinterpret_cast<long long const *
>(imageBuffer), m_ImageData,
2270 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2274 focusFourierPower->processFourierPower(
reinterpret_cast<double const *
>(imageBuffer), m_ImageData,
2275 m_FocusView->imageMask(), mosaicTile, fourierPower, weight);
2279 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2280 " Cannot calc Fourier Power";
2286void Focus::getBlurriness(
const StarMeasure starMeasure,
const bool denoise,
double *blurriness,
double *weight,
2287 const QRect &roi,
const int mosaicTile)
2289 *blurriness = INVALID_STAR_MEASURE;
2292#if defined(HAVE_OPENCV)
2294 auto imageBuffer = m_ImageData->getImageBuffer();
2296 switch (m_ImageData->getStatistics().dataType)
2299 focusBlurriness->processBlurriness(
reinterpret_cast<uint8_t
const *
>(imageBuffer), m_ImageData, denoise,
2300 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2304 focusBlurriness->processBlurriness(
reinterpret_cast<short const *
>(imageBuffer), m_ImageData, denoise,
2305 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2309 focusBlurriness->processBlurriness(
reinterpret_cast<unsigned short const *
>(imageBuffer), m_ImageData, denoise,
2310 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2314 focusBlurriness->processBlurriness(
reinterpret_cast<long const *
>(imageBuffer), m_ImageData, denoise,
2315 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2319 focusBlurriness->processBlurriness(
reinterpret_cast<unsigned long const *
>(imageBuffer), m_ImageData, denoise,
2320 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2324 focusBlurriness->processBlurriness(
reinterpret_cast<float const *
>(imageBuffer), m_ImageData, denoise,
2325 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2329 focusBlurriness->processBlurriness(
reinterpret_cast<long long const *
>(imageBuffer), m_ImageData, denoise,
2330 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2334 focusBlurriness->processBlurriness(
reinterpret_cast<double const *
>(imageBuffer), m_ImageData, denoise,
2335 m_FocusView->imageMask(), mosaicTile, roi, starMeasure, blurriness, weight);
2339 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unknown image buffer datatype " << m_ImageData->getStatistics().dataType <<
2340 " Cannot calc Blurriness";
2344 Q_UNUSED(starMeasure);
2347 Q_UNUSED(mosaicTile);
2349 qCDebug(KSTARS_EKOS_FOCUS) <<
"getBlurriness called when openCV not installed";
2353double Focus::calculateStarWeight(
const bool useWeights,
const std::vector<double> values)
2355 if (!useWeights || values.size() <= 0)
2360 return Mathematics::RobustStatistics::ComputeWeight(m_ScaleCalc, values);
2363void Focus::analyzeSources()
2365 appendLogText(
i18n(
"Detecting sources..."));
2366 m_starDetectInProgress =
true;
2368 QVariantMap extractionSettings;
2369 extractionSettings[
"optionsProfileIndex"] = m_OpsFocusProcess->focusSEPProfile->currentIndex();
2370 extractionSettings[
"optionsProfileGroup"] =
static_cast<int>(Ekos::FocusProfiles);
2371 m_ImageData->setSourceExtractorSettings(extractionSettings);
2375 if (m_OpsFocusSettings->focusUseFullField->isChecked())
2377 m_FocusView->setTrackingBoxEnabled(
false);
2379 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2380 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2382 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection));
2386 QRect searchBox = m_FocusView->isTrackingBoxEnabled() ? m_FocusView->getTrackingBox() :
QRect();
2390 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection, searchBox));
2395 m_FocusView->setTrackingBoxEnabled(
false);
2399 if (m_FocusDetection != ALGORITHM_CENTROID && m_FocusDetection != ALGORITHM_SEP)
2400 m_StarFinderWatcher.setFuture(m_ImageData->findStars(ALGORITHM_CENTROID));
2403 m_StarFinderWatcher.setFuture(m_ImageData->findStars(m_FocusDetection, searchBox));
2408bool Focus::appendMeasure(
double newMeasure)
2411 starMeasureFrames.append(newMeasure);
2414 QVector <double> samples(starMeasureFrames);
2415 samples.erase(std::remove_if(samples.begin(), samples.end(), [](
const double measure)
2417 return measure == INVALID_STAR_MEASURE;
2421 if (!samples.isEmpty())
2423 currentMeasure = Mathematics::RobustStatistics::ComputeLocation(
2424 Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, std::vector<double>(samples.begin(), samples.end()));
2426 switch(m_StarMeasure)
2428 case FOCUS_STAR_HFR:
2429 case FOCUS_STAR_HFR_ADJ:
2430 currentHFR = currentMeasure;
2432 case FOCUS_STAR_FWHM:
2433 currentFWHM = currentMeasure;
2435 case FOCUS_STAR_NUM_STARS:
2436 currentNumStars = currentMeasure;
2438 case FOCUS_STAR_FOURIER_POWER:
2439 currentFourierPower = currentMeasure;
2441 case FOCUS_STAR_STDDEV:
2442 case FOCUS_STAR_SOBEL:
2443 case FOCUS_STAR_LAPLASSIAN:
2444 case FOCUS_STAR_CANNY:
2445 currentBlurriness = currentMeasure;
2456 int framesCount = m_OpsFocusProcess->focusFramesCount->value();
2457 if ((minimumRequiredHFR > 0) || (inAutoFocus && !inBuildOffsets && !inScanStartPos && !focusAdvisor->inFocusAdvisor()
2458 && m_FocusAlgorithm == FOCUS_LINEAR1PASS
2459 && linearFocuser && !linearFocuser->isInFirstPass()))
2461 framesCount = m_OpsFocusProcess->focusHFRFramesCount->value();
2463 return starMeasureFrames.count() < framesCount;
2466void Focus::settle(
const FocusState completionState,
const bool autoFocusUsed,
const bool buildOffsetsUsed,
2467 const AutofocusFailReason failCode,
const QString failCodeInfo)
2469 if (autoFocusUsed && failCode != FOCUS_FAIL_OPTIMISED_OUT)
2471 if (completionState == Ekos::FOCUS_COMPLETE)
2473 if (failCode != FOCUS_FAIL_ADVISOR_COMPLETE)
2474 KSNotification::event(
QLatin1String(
"FocusSuccessful"),
i18n(
"Autofocus operation completed successfully"),
2475 KSNotification::Focus);
2477 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && curveFitting !=
nullptr)
2478 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2479 m_OpsFocusProcess->focusUseWeights->isChecked(),
2480 curveFitting->serialize(), linearFocuser->getTextStatus(R2));
2482 emit autofocusComplete(m_LastSourceAutofocusTemperature,
filter(), getAnalyzeData(),
2483 m_OpsFocusProcess->focusUseWeights->isChecked());
2487 if (failCode != FOCUS_FAIL_ADVISOR_COMPLETE)
2488 KSNotification::event(
QLatin1String(
"FocusFailed"),
i18n(
"Autofocus operation failed"),
2489 KSNotification::Focus, KSNotification::Alert);
2490 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2494 if (completionState == Ekos::FOCUS_COMPLETE)
2496 if (autoFocusUsed && fallbackFilterPending)
2501 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
2502 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
2507 if (fallbackFilterPending)
2509 m_pendingState = completionState;
2510 FilterManager::FilterPolicy policy =
static_cast<FilterManager::FilterPolicy
>(FilterManager::CHANGE_POLICY |
2511 FilterManager::OFFSET_POLICY);
2512 m_FilterManager->setFilterPosition(fallbackFilterPosition, policy);
2515 setState(completionState, failCode != FOCUS_FAIL_OPTIMISED_OUT);
2517 if (autoFocusUsed && buildOffsetsUsed)
2519 m_FilterManager->autoFocusComplete(completionState, currentPosition, m_LastSourceAutofocusTemperature,
2520 m_LastSourceAutofocusAlt);
2525QString Focus::getAnalyzeData()
2527 QString analysis_results =
"";
2529 for (
int i = 0; i < plot_position.size(); ++i)
2532 .arg(i == 0 ?
"" :
"|" )
2538 return analysis_results;
2541void Focus::completeFocusProcedure(FocusState completionState, AutofocusFailReason failCode,
QString failCodeInfo,
2545 if (inAutoFocus && failCode != FOCUS_FAIL_ADVISOR_COMPLETE && failCode != FOCUS_FAIL_OPTIMISED_OUT)
2548 updatePlotPosition();
2550 if (completionState == Ekos::FOCUS_COMPLETE)
2554 emit redrawHFRPlot(polynomialFit.get(), currentPosition, currentHFR);
2556 appendLogText(
i18np(
"Focus procedure completed after %1 iteration.",
2557 "Focus procedure completed after %1 iterations.", plot_position.count()));
2559 setLastFocusTemperature();
2561 resetAdaptiveFocus(m_OpsFocusSettings->focusAdaptive->isChecked());
2565 qCInfo(KSTARS_EKOS_FOCUS) <<
"Autofocus values: position," << currentPosition <<
", temperature,"
2566 << m_LastSourceAutofocusTemperature <<
", filter," <<
filter()
2567 <<
", HFR," << currentHFR <<
", altitude," << m_LastSourceAutofocusAlt;
2569 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL)
2572 plot_position.append(currentPosition);
2573 plot_value.append(currentHFR);
2574 plot_weight.append(1.0);
2575 plot_outlier.append(
false);
2578 appendFocusLogText(
QString(
"%1, %2, %3, %4, %5\n")
2585 absTicksSpin->setValue(currentPosition);
2588 else if (canAbsMove && initialFocuserAbsPosition >= 0 && resetFocusIteration <= MAXIMUM_RESET_ITERATIONS &&
2589 m_RestartState != RESTART_ABORT)
2592 bool const retry_focusing = m_RestartState == RESTART_NONE &&
2593 (failCode == Ekos::FOCUS_FAIL_ADVISOR_RERUN || ++resetFocusIteration < MAXIMUM_RESET_ITERATIONS);
2598 m_RestartState = RESTART_NOW;
2607 emit autofocusAborted(
filter(), getAnalyzeData(), m_OpsFocusProcess->focusUseWeights->isChecked(), failCode, failCodeInfo);
2619 m_RestartState = RESTART_ABORT;
2625 resetFocusIteration = 0;
2628 const bool autoFocusUsed = inAutoFocus;
2629 const bool inBuildOffsetsUsed = inBuildOffsets;
2632 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot)
2633 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
2636 int const settleTime = m_GuidingSuspended ? m_OpsFocusSettings->focusGuideSettleTime->value() : 0;
2639 stop(completionState);
2642 appendLogText(
i18n(
"Settling for %1s...", settleTime));
2644 QTimer::singleShot(settleTime * 1000,
this, [ &, settleTime, completionState, autoFocusUsed, inBuildOffsetsUsed, failCode,
2647 settle(completionState, autoFocusUsed, inBuildOffsetsUsed, failCode, failCodeInfo);
2650 appendLogText(
i18n(
"Settling complete."));
2657 if (m_Focuser && m_Focuser->isConnected() && initialFocuserAbsPosition >= 0)
2660 if (currentPosition == initialFocuserAbsPosition)
2663 appendLogText(
i18n(
"Autofocus failed, moving back to initial focus position %1.", initialFocuserAbsPosition));
2664 changeFocus(initialFocuserAbsPosition - currentPosition);
2669void Focus::setCurrentMeasure()
2672 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus newFITS #" << starMeasureFrames.count() + 1 <<
": Current HFR " << currentHFR <<
2674 << (starSelected ? 1 : currentNumStars);
2677 if (appendMeasure(currentMeasure))
2682 else starMeasureFrames.clear();
2687 emit newHFR(currentHFR, currentPosition, inAutoFocus, opticalTrain());
2689 emit newHFR(currentHFR, -1, inAutoFocus, opticalTrain());
2692 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2693 if (m_StarMeasure == FOCUS_STAR_FWHM)
2694 FWHMOut->setText(
QString(
"%1").arg(currentFWHM * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
2695 starsOut->setText(
QString(
"%1").arg(m_ImageData->getDetectedStars()));
2696 iterOut->setText(
QString(
"%1").arg(absIterations + 1));
2699 if (lastHFR == INVALID_STAR_MEASURE)
2700 appendLogText(
i18n(
"FITS received. No stars detected."));
2703 if (!isStarMeasureStarBased() || currentHFR > 0)
2706 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && isVShapeSolution)
2708 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
2712 Edge selectedHFRStarHFR = m_ImageData->getSelectedHFRStar();
2719 if (starCenter.isNull() ==
false && (inAutoFocus || minimumRequiredHFR >= 0))
2722 starSelected =
true;
2723 starCenter.setX(qMax(0,
static_cast<int>(selectedHFRStarHFR.x)));
2724 starCenter.setY(qMax(0,
static_cast<int>(selectedHFRStarHFR.y)));
2726 syncTrackingBoxPosition();
2730 oneStar.
setZ(currentHFR);
2731 starsHFR.append(oneStar);
2736 QVector3D oneStar(starCenter.x(), starCenter.y(), currentHFR);
2737 starsHFR.append(oneStar);
2740 if (currentHFR > maxHFR)
2741 maxHFR = currentHFR;
2749 if (inFocusLoop || (inAutoFocus && ! isPositionBased()))
2751 int pos = plot_position.empty() ? 1 : plot_position.last() + 1;
2752 addPlotPosition(pos, currentMeasure);
2758 QVector3D oneStar(starCenter.x(), starCenter.y(), INVALID_STAR_MEASURE);
2759 starsHFR.append(oneStar);
2764 m_FocusView->updateFrame();
2768 if (m_abInsOn && !inScanStartPos && !focusAdvisor->inFocusAdvisor())
2769 calculateAbInsData();
2773void Focus::saveFocusFrame()
2775 if (inAutoFocus && Options::focusLogging() && Options::saveFocusImages())
2778 QDateTime now = KStarsData::Instance()->lt();
2786 if (focusAdvisor->inFocusAdvisor())
2787 prefix = focusAdvisor->getFocusFramePrefix();
2788 else if (inScanStartPos)
2789 prefix =
QString(
"_ssp_%1_%2").
arg(m_AFRun).
arg(absIterations + 1);
2790 else if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser)
2792 const int currentStep = linearFocuser->currentStep() + 1;
2798 prefix.
append(
QString(
"_%1").arg(starMeasureFrames.count()));
2804 m_ImageData->saveImage(filename);
2808void Focus::calculateAbInsData()
2810 ImageMosaicMask *mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().
get());
2812 auto stars = m_ImageData->getStarCenters();
2815 for (
int star = 0; star < stars.
count(); star++)
2817 const int x = stars[star]->x;
2818 const int y = stars[star]->y;
2819 for (
int tile = 0; tile < NUM_TILES; tile++)
2821 QRect thisTile = tiles[tile];
2824 tileStars[tile].append(stars[star]);
2831 for (
int tile = 0; tile < tileStars.count(); tile++)
2833 double measure, weight;
2834 std::vector<double> HFRs;
2836 switch (m_StarMeasure)
2838 case FOCUS_STAR_HFR:
2839 case FOCUS_STAR_HFR_ADJ:
2840 for (
int star = 0; star < tileStars[tile].count(); star++)
2842 HFRs.push_back(tileStars[tile][star]->HFR);
2844 measure = Mathematics::RobustStatistics::ComputeLocation(Mathematics::RobustStatistics::LOCATION_SIGMACLIPPING, HFRs, 2);
2845 weight = calculateStarWeight(m_OpsFocusProcess->focusUseWeights->isChecked(), HFRs);
2847 case FOCUS_STAR_FWHM:
2848 getFWHM(tileStars[tile], &measure, &weight);
2850 case FOCUS_STAR_NUM_STARS:
2851 measure = tileStars[tile].count();
2854 case FOCUS_STAR_FOURIER_POWER:
2855 getFourierPower(&measure, &weight, tile);
2857 case FOCUS_STAR_STDDEV:
2858 case FOCUS_STAR_SOBEL:
2859 case FOCUS_STAR_LAPLASSIAN:
2860 case FOCUS_STAR_CANNY:
2861 getBlurriness(m_StarMeasure, m_OpsFocusProcess->focusDenoise->isChecked(), &measure, &weight,
QRect(), tile);
2864 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to calculate Aberration Inspector data";
2868 m_abInsMeasure[tile].append(measure);
2869 m_abInsWeight[tile].append(weight);
2870 m_abInsNumStars[tile].append(tileStars[tile].count());
2872 if (!linearFocuser->isInFirstPass())
2877 int xAv = 0, yAv = 0;
2878 if (m_StarMeasure != FOCUS_STAR_FOURIER_POWER)
2880 QPoint tileCenter = tiles[tile].center();
2881 int xSum = 0.0, ySum = 0.0;
2882 for (
int star = 0; star < tileStars[tile].count(); star++)
2884 xSum += tileStars[tile][star]->x - tileCenter.
x();
2885 ySum += tileStars[tile][star]->y - tileCenter.
y();
2888 xAv = (tileStars[tile].count() <= 0) ? 0 : xSum / tileStars[tile].count();
2889 yAv = (tileStars[tile].count() <= 0) ? 0 : ySum / tileStars[tile].count();
2891 m_abInsTileCenterOffset.append(
QPoint(xAv, yAv));
2894 m_abInsPosition.append(currentPosition);
2897void Focus::setCaptureComplete()
2899 DarkLibrary::Instance()->disconnect(
this);
2902 syncTrackingBoxPosition();
2905 if (inFocusLoop ==
false)
2906 appendLogText(
i18n(
"Image received."));
2908 if (m_captureInProgress && inFocusLoop ==
false && inAutoFocus ==
false)
2909 m_Camera->setUploadMode(rememberUploadMode);
2911 if (m_RememberCameraFastExposure && inFocusLoop ==
false && inAutoFocus ==
false)
2913 m_RememberCameraFastExposure =
false;
2914 m_Camera->setFastExposureEnabled(
true);
2917 m_captureInProgress =
false;
2918 if (m_abortInProgress)
2922 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame results in " << __FUNCTION__;
2927 checkMosaicMaskLimits();
2930 emit newImage(m_FocusView);
2932 emit newStarPixmap(m_FocusView->getTrackingBoxPixmap(10));
2940 if (!isStarMeasureStarBased())
2941 starDetectionFinished();
2942 else if (inFocusLoop ==
false || (inFocusLoop && (m_FocusView->isTrackingBoxEnabled()
2943 || m_OpsFocusSettings->focusUseFullField->isChecked())))
2949void Focus::setHFRComplete()
2959 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
2962 int subBinX = 1, subBinY = 1;
2963 if (!targetChip->getBinning(&subBinX, &subBinY))
2964 qCDebug(KSTARS_EKOS_FOCUS) <<
"Warning: target chip is reporting no binning property, using 1x1.";
2966 if (m_OpsFocusSettings->focusSubFrame->isChecked() && !isStarMeasureStarBased() && !starSelected)
2968 appendLogText(
i18n(
"Capture complete. Select a region of interest."));
2970 syncTrackingBoxPosition();
2973 setState(Ekos::FOCUS_WAITING);
2976 waitStarSelectTimer.start();
2979 else if (m_OpsFocusSettings->focusSubFrame->isChecked() && isStarMeasureStarBased() && starCenter.isNull())
2986 int x = 0, y = 0, w = 0, h = 0;
2989 if (frameSettings.contains(targetChip))
2991 QVariantMap settings = frameSettings[targetChip];
2992 x = settings[
"x"].toInt();
2993 y = settings[
"y"].toInt();
2994 w = settings[
"w"].toInt();
2995 h = settings[
"h"].toInt();
2999 targetChip->getFrame(&x, &y, &w, &h);
3002 if (m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
3005 const Edge selectedHFRStar = m_ImageData->getSelectedHFRStar();
3007 if (selectedHFRStar.x == -1)
3009 appendLogText(
i18n(
"Failed to automatically select a star. Please select a star manually."));
3012 m_FocusView->setTrackingBox(
QRect(w - m_OpsFocusSettings->focusBoxSize->value() / (subBinX * 2),
3013 h - m_OpsFocusSettings->focusBoxSize->value() / (subBinY * 2),
3014 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
3015 m_FocusView->setTrackingBoxEnabled(
true);
3018 setState(Ekos::FOCUS_WAITING);
3021 waitStarSelectTimer.start();
3027 starCenter.setX(selectedHFRStar.x);
3028 starCenter.setY(selectedHFRStar.y);
3029 starCenter.setZ(subBinX);
3030 starSelected =
true;
3031 syncTrackingBoxPosition();
3034 if (subFramed ==
false && isFocusSubFrameEnabled() && m_OpsFocusSettings->focusSubFrame->isChecked())
3036 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
3037 int subX = (selectedHFRStar.x - offset) * subBinX;
3038 int subY = (selectedHFRStar.y - offset) * subBinY;
3039 int subW = offset * 2 * subBinX;
3040 int subH = offset * 2 * subBinY;
3042 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
3043 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
3050 if ((subW + subX) > maxW)
3052 if ((subH + subY) > maxH)
3057 QVariantMap settings = frameSettings[targetChip];
3058 settings[
"x"] = subX;
3059 settings[
"y"] = subY;
3060 settings[
"w"] = subW;
3061 settings[
"h"] = subH;
3062 settings[
"binx"] = subBinX;
3063 settings[
"biny"] = subBinY;
3065 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" << subX <<
"Y:" << subY <<
"W:" << subW <<
"H:" << subH <<
"binX:" <<
3066 subBinX <<
"binY:" << subBinY;
3070 frameSettings[targetChip] = settings;
3073 starCenter.setX(subW / (2 * subBinX));
3074 starCenter.setY(subH / (2 * subBinY));
3075 starCenter.setZ(subBinX);
3079 m_FocusView->setFirstLoad(
true);
3088 starCenter.setX(selectedHFRStar.x);
3089 starCenter.setY(selectedHFRStar.y);
3090 starCenter.setZ(subBinX);
3103 appendLogText(
i18n(
"Capture complete. Select a star to focus."));
3105 starSelected =
false;
3109 int subBinX = 1, subBinY = 1;
3110 targetChip->getBinning(&subBinX, &subBinY);
3112 m_FocusView->setTrackingBox(
QRect((w - m_OpsFocusSettings->focusBoxSize->value()) / (subBinX * 2),
3113 (h - m_OpsFocusSettings->focusBoxSize->value()) / (2 * subBinY),
3114 m_OpsFocusSettings->focusBoxSize->value() / subBinX, m_OpsFocusSettings->focusBoxSize->value() / subBinY));
3115 m_FocusView->setTrackingBoxEnabled(
true);
3118 setState(Ekos::FOCUS_WAITING);
3121 waitStarSelectTimer.start();
3127 if (minimumRequiredHFR >= 0)
3130 if (currentHFR == INVALID_STAR_MEASURE)
3132 if (noStarCount++ < MAX_RECAPTURE_RETRIES)
3134 appendLogText(
i18n(
"No stars detected while testing HFR, capturing again..."));
3136 if (noStarCount == MAX_RECAPTURE_RETRIES)
3145 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3150 else if (currentHFR > minimumRequiredHFR)
3152 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is above required minimum HFR:" << minimumRequiredHFR <<
3153 ". Starting AutoFocus...";
3156 minimumRequiredHFR = INVALID_STAR_MEASURE;
3157 runAutoFocus(AutofocusReason::FOCUS_HFR_CHECK, reasonInfo);
3162 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR:" << currentHFR <<
"is below required minimum HFR:" << minimumRequiredHFR <<
3163 ". Autofocus successful.";
3164 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3172 if (inAutoFocus ==
false)
3176 if (state() != Ekos::FOCUS_IDLE)
3177 setState(Ekos::FOCUS_IDLE);
3184 if (state() != Ekos::FOCUS_PROGRESS)
3185 setState(Ekos::FOCUS_PROGRESS);
3190 else if(focusAdvisor->inFocusAdvisor())
3191 focusAdvisor->control();
3192 else if(m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
3194 else if (canAbsMove || canRelMove)
3202QString Focus::getyAxisLabel(StarMeasure starMeasure)
3205 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3207 switch (starMeasure)
3209 case FOCUS_STAR_HFR:
3211 case FOCUS_STAR_HFR_ADJ:
3213 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3215 case FOCUS_STAR_FWHM:
3217 m_StarUnits == FOCUS_UNITS_ARCSEC ? str +=
" (\")" : str +=
" (pix)";
3219 case FOCUS_STAR_NUM_STARS:
3222 case FOCUS_STAR_FOURIER_POWER:
3223 str =
"Fourier Power";
3225 case FOCUS_STAR_STDDEV:
3228 case FOCUS_STAR_SOBEL:
3229 str =
"Sobel Factor";
3231 case FOCUS_STAR_LAPLASSIAN:
3232 str =
"Laplassian Factor";
3234 case FOCUS_STAR_CANNY:
3235 str =
"Canny Factor";
3246 polynomialFit.reset();
3247 plot_position.clear();
3249 plot_weight.clear();
3250 plot_outlier.clear();
3251 isVShapeSolution =
false;
3252 m_abInsPosition.clear();
3253 m_abInsTileCenterOffset.clear();
3254 if (m_abInsMeasure.count() != NUM_TILES)
3256 m_abInsMeasure.resize(NUM_TILES);
3257 m_abInsWeight.resize(NUM_TILES);
3258 m_abInsNumStars.resize(NUM_TILES);
3262 for (
int i = 0; i < m_abInsMeasure.count(); i++)
3264 m_abInsMeasure[i].clear();
3265 m_abInsWeight[i].clear();
3266 m_abInsNumStars[i].clear();
3270 emit
initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3271 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(),
3272 inFocusLoop ==
false && isPositionBased());
3275bool Focus::autoFocusChecks()
3277 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3279 appendLogText(
i18n(
"Autofocus failed: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3280 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3285 if (isStarMeasureStarBased() && currentHFR == INVALID_STAR_MEASURE)
3287 if (noStarCount < MAX_RECAPTURE_RETRIES)
3290 appendLogText(
i18n(
"No stars detected, capturing again..."));
3294 else if (m_FocusAlgorithm == FOCUS_LINEAR)
3296 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
3299 else if(!m_OpsFocusProcess->focusDonut->isChecked())
3302 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
3303 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3313void Focus::plotLinearFocus()
3322 linearFocuser->getMeasurements(&positions, &values, &weights);
3323 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3330 bool incrementalChange =
false;
3331 if (positions.
size() > 1 && positions.
size() == lastPositions.
size() + 1)
3334 for (
int i = 0; i < positions.
size() - 1; ++i)
3335 if (positions[i] != lastPositions[i] || values[i] != lastValues[i])
3340 incrementalChange =
ok;
3342 lastPositions = positions;
3343 lastValues = values;
3345 const bool outlier =
false;
3346 if (incrementalChange)
3347 emit newHFRPlotPosition(
static_cast<double>(positions.
last()), values.
last(), (pow(weights.
last(), -0.5)),
3348 outlier, params.initialStepSize, plt);
3351 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3352 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, params.useWeights, plt);
3353 for (
int i = 0; i < positions.
size(); ++i)
3354 emit newHFRPlotPosition(
static_cast<double>(positions[i]), values[i], (pow(weights.
last(), -0.5)),
3355 outlier, params.initialStepSize, plt);
3359 if (values.
size() > 3)
3365 double minPosition, minValue;
3366 double searchMin = std::max(params.minPositionAllowed, params.startPosition - params.maxTravel);
3367 double searchMax = std::min(params.maxPositionAllowed, params.startPosition + params.maxTravel);
3369 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3370 if (m_FocusAlgorithm == FOCUS_LINEAR || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3374 polynomialFit.reset(
new PolynomialFit(2, pass1Positions, pass1Values));
3376 if (polynomialFit->findMinimum(params.startPosition, searchMin, searchMax, &minPosition, &minValue))
3378 emit drawPolynomial(polynomialFit.get(),
true,
true, plt);
3382 if (linearFocuser->isDone())
3383 emit minimumFound(-1, -1, plt);
3385 emit minimumFound(minPosition, minValue, plt);
3390 emit drawPolynomial(polynomialFit.get(),
false,
false, plt);
3391 emit minimumFound(-1, -1, plt);
3397 if (curveFitting->findMinMax(params.startPosition, searchMin, searchMax, &minPosition, &minValue, params.curveFit,
3398 params.optimisationDirection))
3400 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3401 emit drawCurve(curveFitting.get(),
true,
true, plt);
3404 emit minimumFound(minPosition, minValue, plt);
3409 emit drawCurve(curveFitting.get(),
false,
false, plt);
3410 emit minimumFound(-1, -1, plt);
3416 HFROut->setText(
QString(
"%1").arg(currentHFR * getStarUnits(m_StarMeasure, m_StarUnits), 0,
'f', 2));
3418 emit setTitle(linearFocuser->getTextStatus(R2));
3420 if (!plt) HFRPlot->replot();
3424CurveFitting::FittingGoal Focus::getGoal(
int numSteps)
3427 if (m_FocusWalk == FOCUS_WALK_CLASSIC)
3428 return CurveFitting::FittingGoal::STANDARD;
3431 return (numSteps >= m_OpsFocusMechanics->focusNumSteps->value()) ? CurveFitting::FittingGoal::BEST :
3432 CurveFitting::FittingGoal::STANDARD;
3438void Focus::plotLinearFinalUpdates()
3441 if (!m_OpsFocusProcess->focusRefineCurveFit->isChecked())
3444 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3445 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3447 emit finalUpdates(linearFocuser->getTextStatus(R2), plt);
3457 linearFocuser->getPass1Measurements(&pass1Positions, &pass1Values, &pass1Weights, &pass1Outliers);
3458 const FocusAlgorithmInterface::FocusParams ¶ms = linearFocuser->getParams();
3460 emit initHFRPlot(getyAxisLabel(m_StarMeasure), getStarUnits(m_StarMeasure, m_StarUnits),
3461 m_OptDir == CurveFitting::OPTIMISATION_MINIMISE, m_OpsFocusProcess->focusUseWeights->isChecked(), plt);
3463 for (
int i = 0; i < pass1Positions.
size(); ++i)
3464 emit newHFRPlotPosition(
static_cast<double>(pass1Positions[i]), pass1Values[i], (pow(pass1Weights[i], -0.5)),
3465 pass1Outliers[i], params.initialStepSize, plt);
3467 R2 = curveFitting->calculateR2(
static_cast<CurveFitting::CurveFit
>(params.curveFit));
3468 emit drawCurve(curveFitting.get(),
true,
true,
false);
3471 emit minimumFound(linearFocuser->solution(), linearFocuser->solutionValue(), plt);
3473 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
3474 m_CFZUI->focusCFZDisplayVCurve->isChecked());
3476 emit setTitle(linearFocuser->getTextStatus(R2), plt);
3480void Focus::startAberrationInspector()
3482#ifdef HAVE_DATAVISUALIZATION
3484 AberrationInspector::abInsData data;
3486 ImageMosaicMask *mosaicmask =
dynamic_cast<ImageMosaicMask *
>(m_FocusView->imageMask().
get());
3489 appendLogText(
i18n(
"Unable to launch Aberration Inspector run %1...", m_abInsRun));
3494 data.run = ++m_abInsRun;
3495 data.curveFit = m_CurveFit;
3496 data.useWeights = m_OpsFocusProcess->focusUseWeights->isChecked();
3497 data.optDir = m_OptDir;
3498 data.sensorWidth = m_CcdWidth;
3499 data.sensorHeight = m_CcdHeight;
3500 data.pixelSize = m_CcdPixelSizeX;
3501 data.tileWidth = mosaicmask->tiles()[0].width();
3502 data.focuserStepMicrons = m_CFZUI->focusCFZStepSize->value();
3503 data.yAxisLabel = getyAxisLabel(m_StarMeasure);
3504 data.starUnits = getStarUnits(m_StarMeasure, m_StarUnits);
3505 data.cfzSteps = m_cfzSteps;
3506 data.isPositionBased = isPositionBased();
3509 appendLogText(
i18n(
"Launching Aberration Inspector run %1...", m_abInsRun));
3511 m_abInsNumStars, m_abInsTileCenterOffset));
3518bool Focus::initScanStartPos(
const bool force,
const int initialPosition)
3522 if (!m_OpsFocusProcess->focusScanStartPos->isChecked())
3525 if (!m_OpsFocusProcess->focusScanAlwaysOn->isChecked() && !m_AFRerun)
3530 inScanStartPos =
true;
3531 initialFocuserAbsPosition = initialPosition;
3532 m_scanMeasure.clear();
3533 m_scanPosition.clear();
3535 appendLogText(
i18n(
"Starting scan for initial focuser position."));
3536 emit setTitle(
QString(
i18n(
"Scanning for starting position...")),
true);
3538 if (!changeFocus(initialPosition - currentPosition))
3539 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3544void Focus::scanStartPos()
3547 if (currentHFR == INVALID_STAR_MEASURE)
3549 if (noStarCount < MAX_RECAPTURE_RETRIES)
3552 appendLogText(
i18n(
"No stars detected, capturing again..."));
3558 appendLogText(
i18n(
"Failed to detect any stars. Aborting..."));
3559 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3565 if (++absIterations > MAXIMUM_ABS_ITERATIONS)
3567 appendLogText(
i18n(
"Scan Start Pos: exceeded max iterations %1", MAXIMUM_ABS_ITERATIONS));
3568 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_MAX_ITERS);
3573 m_scanPosition.push_back(currentPosition);
3574 m_scanMeasure.push_back(currentMeasure);
3577 const int step = m_scanPosition.size();
3578 const int maxSteps = m_OpsFocusProcess->focusScanDatapoints->value();
3579 const int stepSize = m_OpsFocusMechanics->focusTicks->value() * m_OpsFocusProcess->focusScanStepSizeFactor->value();
3580 emit newHFRPlotPosition(
static_cast<double>(currentPosition), currentMeasure, pow(currentWeight, -0.5),
false, stepSize,
3582 if (step < maxSteps)
3585 emit setTitle(
QString(
i18n(
"Scanning for starting position %1/%2", step, maxSteps)),
true);
3586 deltaPos = step * stepSize * std::pow(-1, step + 1);
3591 auto it = std::min_element(std::begin(m_scanMeasure), std::end(m_scanMeasure));
3592 auto min = std::distance(std::begin(m_scanMeasure), it);
3593 if (min >= m_OpsFocusProcess->focusScanDatapoints->value() - 2)
3596 deltaPos = m_scanPosition[min] - currentPosition;
3597 m_scanPosition.clear();
3598 m_scanMeasure.clear();
3599 emit setTitle(
QString(
i18n(
"No scan minimum - widening search...")),
true);
3604 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
3605 focusAdvisor->setInFocusAdvisor(
false);
3607 const int initialPosition = m_scanPosition[min];
3608 setupLinearFocuser(initialPosition);
3609 inScanStartPos =
false;
3611 deltaPos = linearRequestedPosition - currentPosition;
3612 emit setTitle(
QString(
i18n(
"Scan Start Position %1 Found", initialPosition)),
true);
3613 appendLogText(
i18n(
"Scan Start Position %1 found", initialPosition));
3616 if (!changeFocus(deltaPos))
3617 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3620void Focus::autoFocusLinear()
3622 if (!autoFocusChecks())
3625 if (!canAbsMove && !canRelMove && canTimerMove)
3628 if (linearRequestedPosition != currentPosition)
3631 qCDebug(KSTARS_EKOS_FOCUS) <<
"Linear: warning, changing position " << currentPosition <<
" to "
3632 << linearRequestedPosition;
3634 currentPosition = linearRequestedPosition;
3639 bool useFocusStarsHFR = m_OpsFocusSettings->focusUseFullField->isChecked()
3640 && m_OpsFocusProcess->focusFramesCount->value() == 1;
3641 auto focusStars = useFocusStarsHFR || (m_FocusAlgorithm == FOCUS_LINEAR1PASS) ? &(m_ImageData->getStarCenters()) :
nullptr;
3643 linearRequestedPosition = linearFocuser->newMeasurement(currentPosition, currentMeasure, currentWeight, focusStars);
3644 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS && linearFocuser->isDone() && linearFocuser->solution() != -1)
3647 plotLinearFinalUpdates();
3649 startAberrationInspector();
3655 if (linearFocuser->isDone())
3657 if (linearFocuser->solution() != -1)
3660 if (m_AutofocusReason == FOCUS_FOCUS_ADVISOR)
3662 if (focusAdvisor->analyseAF())
3663 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_ADVISOR_RERUN,
"",
false);
3665 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3667 else if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
3669 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3670 else if (R2 >= m_OpsFocusProcess->focusR2Limit->value())
3674 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Linear Curve Fit check passed R2=%1 focusR2Limit=%2").
arg(R2).
arg(
3675 m_OpsFocusProcess->focusR2Limit->value());
3676 completeFocusProcedure(Ekos::FOCUS_COMPLETE, FOCUS_FAIL_NONE,
"",
false);
3679 else if (m_R2Retries == 0)
3682 appendLogText(
i18n(
"Curve Fit check failed R2=%1 focusR2Limit=%2 retrying...", R2,
3683 m_OpsFocusProcess->focusR2Limit->value()));
3686 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_R2, failCodeInfo,
false);
3692 appendLogText(
i18n(
"Curve Fit check failed again R2=%1 focusR2Limit=%2 but continuing...", R2,
3693 m_OpsFocusProcess->focusR2Limit->value()));
3694 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE,
"",
false);
3700 qCDebug(KSTARS_EKOS_FOCUS) << linearFocuser->doneReason();
3701 AutofocusFailReason failCode = linearFocuser->getFailCode();
3702 appendLogText(
i18n(
"Linear autofocus algorithm aborted: %1", AutofocusFailReasonStr[failCode]));
3703 completeFocusProcedure(Ekos::FOCUS_ABORTED, failCode,
"",
false);
3709 const int delta = linearRequestedPosition - currentPosition;
3711 if (!changeFocus(delta))
3712 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE,
"",
false);
3718void Focus::autoFocusAbs()
3722 static int minHFRPos = 0, focusOutLimit = 0, focusInLimit = 0, lastHFRPos = 0, fluctuations = 0;
3723 static double minHFR = 0, lastDelta = 0;
3724 double targetPosition = 0;
3725 bool ignoreLimitedDelta =
false;
3727 QString deltaTxt =
QString(
"%1").
arg(fabs(currentHFR - minHFR) * 100.0, 0,
'g', 3);
3730 qCDebug(KSTARS_EKOS_FOCUS) <<
"===============================";
3731 qCDebug(KSTARS_EKOS_FOCUS) <<
"Current HFR: " << currentHFR <<
" Current Position: " << currentPosition;
3732 qCDebug(KSTARS_EKOS_FOCUS) <<
"Last minHFR: " << minHFR <<
" Last MinHFR Pos: " << minHFRPos;
3733 qCDebug(KSTARS_EKOS_FOCUS) <<
"Delta: " << deltaTxt <<
"%";
3734 qCDebug(KSTARS_EKOS_FOCUS) <<
"========================================";
3737 appendLogText(
i18n(
"FITS received. HFR %1 @ %2. Delta (%3%)", HFRText, currentPosition, deltaTxt));
3739 appendLogText(
i18n(
"FITS received. HFR %1 @ %2.", HFRText, currentPosition));
3741 if (!autoFocusChecks())
3744 addPlotPosition(currentPosition, currentHFR);
3746 switch (m_LastFocusDirection)
3749 lastHFR = currentHFR;
3750 initialFocuserAbsPosition = currentPosition;
3751 minHFR = currentHFR;
3752 minHFRPos = currentPosition;
3762 if (absMotionMax < currentPosition + pulseDuration)
3764 if (currentPosition < absMotionMax)
3766 pulseDuration = absMotionMax - currentPosition;
3771 m_LastFocusDirection = FOCUS_IN;
3774 else if (currentPosition + pulseDuration < absMotionMin)
3776 if (absMotionMin < currentPosition)
3778 pulseDuration = currentPosition - absMotionMin;
3783 m_LastFocusDirection = FOCUS_OUT;
3787 m_LastFocusDirection = (pulseDuration > 0) ? FOCUS_OUT : FOCUS_IN;
3788 if (!changeFocus(pulseDuration,
false))
3789 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
3795 if (reverseDir && focusInLimit && focusOutLimit &&
3796 fabs(currentHFR - minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
3798 if (absIterations <= 2)
3800 QString message =
i18n(
"Change in HFR is too small. Try increasing the step size or decreasing the tolerance.");
3801 appendLogText(message);
3802 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3803 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_SMALL_HFR);
3805 else if (noStarCount > 0)
3807 QString message =
i18n(
"Failed to detect focus star in frame. Capture and select a focus star.");
3808 appendLogText(message);
3809 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3810 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
3814 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3818 else if (currentHFR < lastHFR)
3821 if (HFRInc >= 1 && m_LastFocusDirection == FOCUS_OUT && lastHFRPos < focusInLimit && fabs(currentHFR - lastHFR) > 0.1)
3823 focusInLimit = lastHFRPos;
3824 qCDebug(KSTARS_EKOS_FOCUS) <<
"New FocusInLimit " << focusInLimit;
3826 else if (HFRInc >= 1 && m_LastFocusDirection == FOCUS_IN && lastHFRPos > focusOutLimit &&
3827 fabs(currentHFR - lastHFR) > 0.1)
3829 focusOutLimit = lastHFRPos;
3830 qCDebug(KSTARS_EKOS_FOCUS) <<
"New FocusOutLimit " << focusOutLimit;
3833 double factor = std::max(1.0, HFRDec / 2.0);
3834 if (m_LastFocusDirection == FOCUS_IN)
3835 targetPosition = currentPosition - (pulseDuration * factor);
3837 targetPosition = currentPosition + (pulseDuration * factor);
3839 qCDebug(KSTARS_EKOS_FOCUS) <<
"current Position" << currentPosition <<
" targetPosition " << targetPosition;
3841 lastHFR = currentHFR;
3844 if (lastHFR < minHFR)
3847 minHFRPos = currentPosition;
3848 qCDebug(KSTARS_EKOS_FOCUS) <<
"new minHFR " << minHFR <<
" @ position " << minHFRPos;
3851 lastHFRPos = currentPosition;
3858 if (plot_position.count() >= 2)
3860 plot_position.remove(plot_position.count() - 2);
3861 plot_value.remove(plot_value.count() - 2);
3875 lastHFR = currentHFR;
3876 lastHFRPos = currentPosition;
3885 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus is moving away from optimal HFR.";
3888 if (m_LastFocusDirection == FOCUS_IN)
3890 focusInLimit = currentPosition;
3891 qCDebug(KSTARS_EKOS_FOCUS) <<
"Setting focus IN limit to " << focusInLimit;
3895 focusOutLimit = currentPosition;
3896 qCDebug(KSTARS_EKOS_FOCUS) <<
"Setting focus OUT limit to " << focusOutLimit;
3899 if (m_FocusAlgorithm == FOCUS_POLYNOMIAL && plot_position.count() > 4)
3901 polynomialFit.reset(
new PolynomialFit(2, 5, plot_position, plot_value));
3902 double a = *std::min_element(plot_position.constBegin(), plot_position.constEnd());
3903 double b = *std::max_element(plot_position.constBegin(), plot_position.constEnd());
3904 double min_position = 0, min_hfr = 0;
3905 isVShapeSolution = polynomialFit->findMinimum(minHFRPos, a, b, &min_position, &min_hfr);
3906 qCDebug(KSTARS_EKOS_FOCUS) <<
"Found Minimum?" << (isVShapeSolution ?
"Yes" :
"No");
3907 if (isVShapeSolution)
3909 ignoreLimitedDelta =
true;
3910 qCDebug(KSTARS_EKOS_FOCUS) <<
"Minimum Solution:" << min_hfr <<
"@" << min_position;
3911 targetPosition = round(min_position);
3912 appendLogText(
i18n(
"Found polynomial solution @ %1",
QString::number(min_position,
'f', 0)));
3914 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
true);
3915 emit minimumFound(min_position, min_hfr);
3919 emit drawPolynomial(polynomialFit.get(), isVShapeSolution,
false);
3928 if (std::abs(lastDelta) > 0)
3929 targetPosition = currentPosition + lastDelta;
3931 targetPosition = currentPosition + pulseDuration;
3933 else if (isVShapeSolution ==
false)
3935 ignoreLimitedDelta =
true;
3937 if (m_LastFocusDirection == FOCUS_OUT)
3938 targetPosition = minHFRPos - pulseDuration / 2;
3940 targetPosition = minHFRPos + pulseDuration / 2;
3943 qCDebug(KSTARS_EKOS_FOCUS) <<
"new targetPosition " << targetPosition;
3947 if (focusInLimit != 0 && m_LastFocusDirection == FOCUS_IN && targetPosition < focusInLimit)
3949 targetPosition = focusInLimit;
3950 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus in limit " << targetPosition;
3952 else if (focusOutLimit != 0 && m_LastFocusDirection == FOCUS_OUT && targetPosition > focusOutLimit)
3954 targetPosition = focusOutLimit;
3955 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limiting target pulse to focus out limit " << targetPosition;
3959 if (targetPosition < absMotionMin)
3960 targetPosition = absMotionMin;
3961 else if (targetPosition > absMotionMax)
3962 targetPosition = absMotionMax;
3965 if (targetPosition == currentPosition)
3969 if (targetPosition == minHFRPos || isVShapeSolution)
3971 appendLogText(
"Stopping at minimum recorded HFR position.");
3972 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
3976 QString message =
i18n(
"Focuser cannot move further, device limits reached. Autofocus aborted.");
3977 appendLogText(message);
3978 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3979 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
3985 if (fluctuations >= MAXIMUM_FLUCTUATIONS)
3987 QString message =
i18n(
"Unstable fluctuations. Try increasing initial step size or exposure time.");
3988 appendLogText(message);
3989 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
3990 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FLUCTUATIONS);
3995 if (focusOutLimit && focusOutLimit == focusInLimit)
3997 QString message =
i18n(
"Deadlock reached. Please try again with different settings.");
3998 appendLogText(message);
3999 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
4000 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_DEADLOCK);
4005 if (fabs(targetPosition - initialFocuserAbsPosition) > m_OpsFocusMechanics->focusMaxTravel->value())
4007 int minTravelLimit = qMax(0.0, initialFocuserAbsPosition - m_OpsFocusMechanics->focusMaxTravel->value());
4008 int maxTravelLimit = qMin(absMotionMax, initialFocuserAbsPosition + m_OpsFocusMechanics->focusMaxTravel->value());
4012 if (fabs(currentPosition - minTravelLimit) > 10 && targetPosition < minTravelLimit)
4014 targetPosition = minTravelLimit;
4017 else if (fabs(currentPosition - maxTravelLimit) > 10 && targetPosition > maxTravelLimit)
4019 targetPosition = maxTravelLimit;
4023 qCDebug(KSTARS_EKOS_FOCUS) <<
"targetPosition (" << targetPosition <<
") - initHFRAbsPos ("
4024 << initialFocuserAbsPosition <<
") exceeds maxTravel distance of " << m_OpsFocusMechanics->focusMaxTravel->value();
4026 QString message =
i18n(
"Maximum travel limit reached. Autofocus aborted.");
4027 appendLogText(message);
4028 KSNotification::event(
QLatin1String(
"FocusFailed"), message, KSNotification::Focus, KSNotification::Alert);
4029 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_OOB);
4035 lastDelta = (targetPosition - currentPosition);
4037 qCDebug(KSTARS_EKOS_FOCUS) <<
"delta (targetPosition - currentPosition) " << lastDelta;
4040 if (ignoreLimitedDelta ==
false)
4042 double limitedDelta = qMax(-1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(),
4043 qMin(1.0 * m_OpsFocusMechanics->focusMaxSingleStep->value(), lastDelta));
4044 if (std::fabs(limitedDelta - lastDelta) > 0)
4046 qCDebug(KSTARS_EKOS_FOCUS) <<
"Limited delta to maximum permitted single step " <<
4047 m_OpsFocusMechanics->focusMaxSingleStep->value();
4048 lastDelta = limitedDelta;
4052 m_LastFocusDirection = (lastDelta > 0) ? FOCUS_OUT : FOCUS_IN;
4053 if (!changeFocus(lastDelta,
false))
4054 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4060void Focus::addPlotPosition(
int pos,
double value,
bool plot)
4062 plot_position.append(pos);
4063 plot_value.append(value);
4065 emit newHFRPlotPosition(
static_cast<double>(pos), value, 1.0,
false, pulseDuration);
4071void Focus::updatePlotPosition()
4073 if (m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4076 if (inScanStartPos || focusAdvisor->inFocusAdvisor())
4079 plot_position.clear();
4081 plot_weight.clear();
4082 plot_outlier.clear();
4086 linearFocuser->getPass1Measurements(&positions, &plot_value, &plot_weight, &plot_outlier);
4087 plot_position.clear();
4088 for (
int i = 0; i < positions.
count(); i++)
4089 plot_position.append(positions[i]);
4092 if (linearFocuser && linearFocuser->isDone() && linearFocuser->solution() != -1)
4094 plot_position.append(linearFocuser->solution());
4095 plot_value.append(linearFocuser->solutionValue());
4096 plot_weight.append(linearFocuser->solutionWeight());
4097 plot_outlier.append(
false);
4101 else if (m_FocusAlgorithm == FOCUS_LINEAR)
4104 linearFocuser->getMeasurements(&positions, &plot_value, &plot_weight);
4105 plot_position.
clear();
4106 plot_outlier.clear();
4107 for (
int i = 0; i < positions.
count(); i++)
4109 plot_position.append(positions[i]);
4111 plot_outlier.append(
false);
4117 for (
int i = 0; i < plot_position.count(); i++)
4119 plot_weight.append(1.0);
4120 plot_outlier.append(
false);
4125void Focus::autoFocusRel()
4127 static int noStarCount = 0;
4128 static double minHFR = 1e6;
4129 QString deltaTxt =
QString(
"%1").
arg(fabs(currentHFR - minHFR) * 100.0, 0,
'g', 2);
4133 appendLogText(
i18n(
"FITS received. HFR %1. Delta (%2%) Min HFR (%3)", HFRText, deltaTxt, minHFRText));
4135 if (pulseDuration <= MINIMUM_PULSE_TIMER)
4137 appendLogText(
i18n(
"Autofocus failed to reach proper focus. Try adjusting the tolerance value."));
4138 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_TOLERANCE);
4143 if (currentHFR == INVALID_STAR_MEASURE)
4145 if (noStarCount < MAX_RECAPTURE_RETRIES)
4148 appendLogText(
i18n(
"No stars detected, capturing again..."));
4152 else if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4154 appendLogText(
i18n(
"Failed to detect any stars at position %1. Continuing...", currentPosition));
4157 else if(!m_OpsFocusProcess->focusDonut->isChecked())
4160 appendLogText(
i18n(
"Failed to detect any stars. Reset frame and try again."));
4161 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
4168 switch (m_LastFocusDirection)
4171 lastHFR = currentHFR;
4173 m_LastFocusDirection = FOCUS_IN;
4174 changeFocus(-pulseDuration,
false);
4179 if (fabs(currentHFR - minHFR) < (m_OpsFocusProcess->focusTolerance->value() / 100.0) && HFRInc == 0)
4181 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_NONE);
4183 else if (currentHFR < lastHFR)
4185 if (currentHFR < minHFR)
4186 minHFR = currentHFR;
4188 lastHFR = currentHFR;
4189 changeFocus(m_LastFocusDirection == FOCUS_IN ? -pulseDuration : pulseDuration,
false);
4196 lastHFR = currentHFR;
4200 pulseDuration *= 0.75;
4202 if (!changeFocus(m_LastFocusDirection == FOCUS_IN ? pulseDuration : -pulseDuration,
false))
4203 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4206 m_LastFocusDirection = (m_LastFocusDirection == FOCUS_IN) ? FOCUS_OUT : FOCUS_IN;
4212void Focus::handleFocusButtonEvent()
4214 bool inward = (sender() == focusInB);
4218 updateButtonColors(inward ? focusInB : focusOutB, shift, ctrl);
4221 speedup *= m_OpsFocusMechanics->speedupShift->value();
4223 speedup *= m_OpsFocusMechanics->speedupCtrl->value();
4226 focusIn(-1, speedup);
4228 focusOut(-1, speedup);
4231void Focus::autoFocusProcessPositionChange(IPState state)
4233 if (state == IPS_OK)
4239 if (focuserAdditionalMovement > 0)
4241 int temp = focuserAdditionalMovement;
4242 focuserAdditionalMovement = 0;
4244 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Undoing overscan extension. Moving back in by %1 ticks in %2s")
4245 .
arg(temp).
arg(m_OpsFocusMechanics->focusOverscanDelay->value());
4247 QTimer::singleShot(m_OpsFocusMechanics->focusOverscanDelay->value() * 1000,
this, [
this, temp]()
4249 if (!changeFocus(-temp, focuserAdditionalMovementUpdateDir))
4251 appendLogText(i18n(
"Focuser error, check INDI panel."));
4252 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
4256 else if (inAutoFocus && !inAFOptimise)
4259 if (m_FocusAlgorithm == FOCUS_LINEAR || m_FocusAlgorithm == FOCUS_LINEAR1PASS)
4260 if (abs(linearRequestedPosition - currentPosition) > m_OpsFocusMechanics->focusTicks->value())
4261 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Focus positioning error: requested position %1, current position %2")
4262 .
arg(linearRequestedPosition).
arg(currentPosition);
4264 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Focus position reached at %1, starting capture in %2 seconds.").
arg(
4265 currentPosition).
arg(m_OpsFocusMechanics->focusSettleTime->value());
4267 if (m_OpsFocusProcess->focusDonut->isChecked())
4268 donutTimeDilation();
4269 capture(m_OpsFocusMechanics->focusSettleTime->value());
4272 else if (state == IPS_ALERT)
4274 appendLogText(
i18n(
"Focuser error, check INDI panel."));
4275 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_ERROR);
4278 qCDebug(KSTARS_EKOS_FOCUS) <<
4279 QString(
"autoFocusProcessPositionChange called with state %1 (%2), focuserAdditionalMovement=%3, inAutoFocus=%4, m_captureInProgress=%5, currentPosition=%6")
4280 .
arg(state).
arg(pstateStr(state)).
arg(focuserAdditionalMovement).
arg(inAutoFocus).
arg(m_captureInProgress)
4281 .
arg(currentPosition);
4285void Focus::donutTimeDilation()
4287 if (m_OpsFocusProcess->focusTimeDilation->value() == 1.0 || inScanStartPos || focusAdvisor->inFocusAdvisor())
4291 const double centre = (m_OpsFocusMechanics->focusNumSteps->value() + 1.0) / 2.0;
4293 const int currentStep = linearFocuser->currentStep() + 1;
4295 if (currentStep <= m_OpsFocusMechanics->focusNumSteps->value())
4296 distance = std::abs(centre - currentStep);
4300 double multiplier =
distance / (centre - 1.0) * m_OpsFocusProcess->focusTimeDilation->value();
4301 multiplier = std::max(multiplier, 1.0);
4302 const double exposure = multiplier * m_donutOrigExposure;
4303 focusExposure->setValue(exposure);
4304 qCDebug(KSTARS_EKOS_FOCUS) <<
"Donut time dilation for point " << currentStep <<
" from " << m_donutOrigExposure <<
" to "
4311 if (m_Focuser ==
nullptr || prop.getType() != INDI_NUMBER || prop.getDeviceName() != m_Focuser->getDeviceName())
4314 auto nvp = prop.getNumber();
4320 if (nvp->isNameMatch(
"FOCUS_BACKLASH_STEPS"))
4322 m_OpsFocusMechanics->focusBacklash->setValue(nvp->np[0].value);
4326 if (nvp->isNameMatch(
"ABS_FOCUS_POSITION"))
4331 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4333 if (m_DebugFocuserCounter == 14)
4334 m_DebugFocuserCounter = 0;
4340 m_FocusMotionTimer.stop();
4341 INumber *
pos = IUFindNumber(nvp,
"FOCUS_ABSOLUTE_POSITION");
4342 IPState newState = nvp->s;
4347 int newPosition =
static_cast<int>(
pos->value);
4352 if (currentPosition == newPosition && currentPositionState == newState)
4354 if (logPositionAndState)
4356 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focuser position " << currentPosition <<
" and state:"
4357 << pstateStr(currentPositionState) <<
" unchanged";
4358 logPositionAndState =
false;
4364 logPositionAndState =
true;
4367 currentPositionState = newState;
4369 if (currentPosition != newPosition)
4371 currentPosition = newPosition;
4372 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abs Focuser position changed to " << currentPosition <<
"State:" << pstateStr(
4373 currentPositionState);
4375 emit absolutePositionChanged(currentPosition);
4379 qCDebug(KSTARS_EKOS_FOCUS) <<
"Can't access FOCUS_ABSOLUTE_POSITION. Current state:"
4380 << pstateStr(currentPositionState) <<
" New state:" << pstateStr(newState);
4382 if (newState != IPS_OK)
4384 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
4388 qCDebug(KSTARS_EKOS_FOCUS) <<
"Restarting focus motion timer, state " << pstateStr(newState);
4389 m_FocusMotionTimer.start();
4395 if (focuserAdditionalMovement == 0)
4400 if (focuserAdditionalMovement == 0)
4402 inAdjustFocus =
false;
4403 emit focusPositionAdjusted();
4410 if (focuserAdditionalMovement == 0)
4412 inAFOptimise =
false;
4413 emit focusAFOptimise();
4418 if (adaptFocus->inAdaptiveFocus())
4420 if (focuserAdditionalMovement == 0)
4422 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4427 if (m_RestartState == RESTART_NOW &&
status() != Ekos::FOCUS_ABORTED)
4429 if (focuserAdditionalMovement == 0)
4431 m_RestartState = RESTART_NONE;
4433 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4434 adaptFocus->setInAdaptiveFocus(
false);
4435 focusAdvisor->setInFocusAdvisor(
false);
4437 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4441 else if (m_RestartState == RESTART_ABORT && focuserAdditionalMovement == 0)
4447 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4448 m_RestartState = RESTART_NONE;
4449 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4450 adaptFocus->setInAdaptiveFocus(
false);
4451 focusAdvisor->setInFocusAdvisor(
false);
4457 autoFocusProcessPositionChange(newState);
4458 else if (newState == IPS_ALERT)
4466 if (nvp->isNameMatch(
"manualfocusdrive"))
4471 if (m_DebugFocuserCounter++ >= 10 && m_DebugFocuserCounter <= 14)
4473 if (m_DebugFocuserCounter == 14)
4474 m_DebugFocuserCounter = 0;
4480 m_FocusMotionTimer.stop();
4482 INumber *
pos = IUFindNumber(nvp,
"manualfocusdrive");
4483 IPState newState = nvp->s;
4484 if (
pos && newState == IPS_OK)
4486 if (focuserAdditionalMovement == 0)
4489 currentPosition +=
pos->value;
4490 absTicksLabel->setText(
QString::number(
static_cast<int>(currentPosition)));
4491 emit absolutePositionChanged(currentPosition);
4494 if (inAdjustFocus && newState == IPS_OK)
4496 if (focuserAdditionalMovement == 0)
4498 inAdjustFocus =
false;
4499 emit focusPositionAdjusted();
4504 if (inAFOptimise && newState == IPS_OK)
4506 if (focuserAdditionalMovement == 0)
4508 inAFOptimise =
false;
4509 emit focusAFOptimise();
4514 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4516 if (focuserAdditionalMovement == 0)
4518 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4524 if (m_RestartState == RESTART_NOW && newState == IPS_OK &&
status() != Ekos::FOCUS_ABORTED)
4526 if (focuserAdditionalMovement == 0)
4528 m_RestartState = RESTART_NONE;
4530 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4531 adaptFocus->setInAdaptiveFocus(
false);
4532 focusAdvisor->setInFocusAdvisor(
false);
4534 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4538 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4541 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4542 m_RestartState = RESTART_NONE;
4543 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4544 adaptFocus->setInAdaptiveFocus(
false);
4545 focusAdvisor->setInFocusAdvisor(
false);
4550 autoFocusProcessPositionChange(newState);
4551 else if (newState == IPS_ALERT)
4557 if (nvp->isNameMatch(
"REL_FOCUS_POSITION"))
4559 m_FocusMotionTimer.stop();
4561 INumber *
pos = IUFindNumber(nvp,
"FOCUS_RELATIVE_POSITION");
4562 IPState newState = nvp->s;
4563 if (
pos && newState == IPS_OK)
4565 if (focuserAdditionalMovement == 0)
4568 currentPosition +=
pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4569 qCDebug(KSTARS_EKOS_FOCUS)
4570 <<
QString(
"Rel Focuser position moved %1 by %2 to %3")
4571 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").
arg(
pos->value).
arg(currentPosition);
4572 absTicksLabel->setText(
QString::number(
static_cast<int>(currentPosition)));
4573 emit absolutePositionChanged(currentPosition);
4576 if (inAdjustFocus && newState == IPS_OK)
4578 if (focuserAdditionalMovement == 0)
4580 inAdjustFocus =
false;
4581 emit focusPositionAdjusted();
4586 if (inAFOptimise && newState == IPS_OK)
4588 if (focuserAdditionalMovement == 0)
4590 inAFOptimise =
false;
4591 emit focusAFOptimise();
4596 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4598 if (focuserAdditionalMovement == 0)
4600 adaptFocus->adaptiveFocusAdmin(currentPosition,
true,
true);
4606 if (m_RestartState == RESTART_NOW && newState == IPS_OK &&
status() != Ekos::FOCUS_ABORTED)
4608 if (focuserAdditionalMovement == 0)
4610 m_RestartState = RESTART_NONE;
4612 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4613 adaptFocus->setInAdaptiveFocus(
false);
4614 focusAdvisor->setInFocusAdvisor(
false);
4616 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4620 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4623 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4624 m_RestartState = RESTART_NONE;
4625 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4626 adaptFocus->setInAdaptiveFocus(
false);
4627 focusAdvisor->setInFocusAdvisor(
false);
4632 autoFocusProcessPositionChange(newState);
4633 else if (newState == IPS_ALERT)
4642 if (nvp->isNameMatch(
"FOCUS_TIMER"))
4644 IPState newState = nvp->s;
4645 m_FocusMotionTimer.stop();
4647 if (m_RestartState == RESTART_NOW && newState == IPS_OK &&
status() != Ekos::FOCUS_ABORTED)
4649 if (focuserAdditionalMovement == 0)
4651 m_RestartState = RESTART_NONE;
4653 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4654 adaptFocus->setInAdaptiveFocus(
false);
4655 focusAdvisor->setInFocusAdvisor(
false);
4657 runAutoFocus(m_AutofocusReason, m_AutofocusReasonInfo);
4661 else if (m_RestartState == RESTART_ABORT && newState == IPS_OK)
4664 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FORCE_ABORT);
4665 m_RestartState = RESTART_NONE;
4666 inAutoFocus = inBuildOffsets = inAFOptimise = inAdjustFocus = inScanStartPos =
false;
4667 adaptFocus->setInAdaptiveFocus(
false);
4668 focusAdvisor->setInFocusAdvisor(
false);
4672 if (canAbsMove ==
false && canRelMove ==
false)
4675 INumber *
pos = IUFindNumber(nvp,
"FOCUS_TIMER_VALUE");
4678 currentPosition +=
pos->value * (m_LastFocusDirection == FOCUS_IN ? -1 : 1);
4679 qCDebug(KSTARS_EKOS_FOCUS)
4680 <<
QString(
"Timer Focuser position moved %1 by %2 to %3")
4681 .
arg((m_LastFocusDirection == FOCUS_IN) ?
"in" :
"out").
arg(
pos->value).
arg(currentPosition);
4684 if (
pos && newState == IPS_OK && focuserAdditionalMovement == 0)
4687 if (inAdjustFocus && newState == IPS_OK)
4689 if (focuserAdditionalMovement == 0)
4691 inAdjustFocus =
false;
4692 emit focusPositionAdjusted();
4697 if (inAFOptimise && newState == IPS_OK)
4699 if (focuserAdditionalMovement == 0)
4701 inAFOptimise =
false;
4702 emit focusAFOptimise();
4707 if (adaptFocus->inAdaptiveFocus() && newState == IPS_OK)
4709 if (focuserAdditionalMovement == 0)
4711 adaptFocus->adaptiveFocusAdmin(
true,
true,
true);
4716 autoFocusProcessPositionChange(newState);
4718 else if (newState == IPS_ALERT)
4727 const QString logtext(m_Focuser ==
nullptr ? text :
QString(
"[%1] %2").arg(m_Focuser->getDeviceName()).
arg(text));
4728 emit newLog(logtext);
4731void Focus::appendFocusLogText(
const QString &text)
4733 if (Options::focusLogging())
4735 const QString logtext(m_Focuser ==
nullptr ? text :
QString(
"[%1] %2").arg(m_Focuser->getDeviceName()).
arg(text));
4736 emit newFocusLog(logtext);
4742 if (m_Camera ==
nullptr)
4748 waitStarSelectTimer.stop();
4751 starMeasureFrames.clear();
4756 setState(Ekos::FOCUS_FRAMING);
4765void Focus::resetButtons()
4768 updateButtonColors(focusInB,
false,
false);
4769 updateButtonColors(focusOutB,
false,
false);
4773 startFocusB->setEnabled(
false);
4774 startAbInsB->setEnabled(
false);
4775 startLoopB->setEnabled(
false);
4776 focusOutB->setEnabled(
true);
4777 focusInB->setEnabled(
true);
4778 startGotoB->setEnabled(canAbsMove);
4779 stopFocusB->setEnabled(
true);
4780 captureB->setEnabled(
false);
4781 opticalTrainCombo->setEnabled(
false);
4782 trainB->setEnabled(
false);
4796 if (disabledWidgets.empty())
4798 AFDisable(trainLabel,
false);
4799 AFDisable(opticalTrainCombo,
false);
4800 AFDisable(trainB,
false);
4801 AFDisable(focuserGroup,
true);
4802 AFDisable(clearDataB,
false);
4805 m_FocusGainAFEnabled = focusGain->isEnabled();
4806 m_FocusISOAFEnabled = focusISO->isEnabled();
4807 AFDisable(ccdGroup,
false);
4809 AFDisable(toolsGroup,
false);
4812 m_FocusSubFrameAFEnabled = m_OpsFocusSettings->focusSubFrame->isEnabled();
4815 AFDisable(m_OpsFocusSettings,
false);
4816 AFDisable(m_OpsFocusProcess,
false);
4817 AFDisable(m_OpsFocusMechanics,
false);
4818 AFDisable(focusAdvisor->focusAdvGroupBox,
false);
4819 AFDisable(m_CFZDialog,
false);
4822 stopFocusB->setEnabled(
true);
4828 for(
int i = 0 ; i < disabledWidgets.size() ; i++)
4829 disabledWidgets[i]->setEnabled(
true);
4830 disabledWidgets.clear();
4832 bool cameraConnected = m_Camera && m_Camera->isConnected();
4833 bool enableCaptureButtons = cameraConnected && (!m_captureInProgress && !m_starDetectInProgress);
4835 captureB->setEnabled(enableCaptureButtons);
4836 resetFrameB->setEnabled(enableCaptureButtons);
4837 startLoopB->setEnabled(enableCaptureButtons);
4838 startFocusB->setEnabled(enableCaptureButtons);
4841 if (cameraConnected)
4843 ccdGroup->setEnabled(
true);
4844 toolsGroup->setEnabled(
true);
4848 ccdGroup->setEnabled(
false);
4849 toolsGroup->setEnabled(
false);
4852 if (m_Focuser && m_Focuser->isConnected())
4854 focusOutB->setEnabled(
true);
4855 focusInB->setEnabled(
true);
4856 startAbInsB->setEnabled(canAbInsStart());
4857 stopFocusB->setEnabled(!enableCaptureButtons);
4858 startGotoB->setEnabled(canAbsMove);
4859 stopGotoB->setEnabled(
true);
4860 focuserGroup->setEnabled(
true);
4864 focusOutB->setEnabled(
false);
4865 focusInB->setEnabled(
false);
4866 startAbInsB->setEnabled(
false);
4867 stopFocusB->setEnabled(
false);
4868 startGotoB->setEnabled(
false);
4869 stopGotoB->setEnabled(
false);
4870 focuserGroup->setEnabled(cameraConnected);
4874void Focus::updateButtonColors(
QPushButton *button,
bool shift,
bool ctrl)
4879 stylesheet =
"background-color: #D32F2F";
4881 stylesheet =
"background-color: #FFC107";
4883 stylesheet =
"background-color: #FF5722";
4893bool Focus::canAbInsStart()
4895 return canAbsMove && m_FocusAlgorithm == FOCUS_LINEAR1PASS && m_currentImageMask == FOCUS_MASK_MOSAIC
4896 && m_CurveFit != CurveFitting::FOCUS_QUADRATIC;
4900void Focus::AFDisable(
QWidget * widget,
const bool children)
4907 if (wid->isEnabled())
4909 wid->setEnabled(
false);
4910 disabledWidgets.push_back(wid);
4919 disabledWidgets.push_back(widget);
4923bool Focus::isFocusGainEnabled()
4925 return (inAutoFocus) ? m_FocusGainAFEnabled : focusGain->isEnabled();
4928bool Focus::isFocusISOEnabled()
4930 return (inAutoFocus) ? m_FocusISOAFEnabled : focusISO->isEnabled();
4933bool Focus::isFocusSubFrameEnabled()
4935 return (inAutoFocus) ? m_FocusSubFrameAFEnabled : m_OpsFocusSettings->focusSubFrame->isEnabled();
4938void Focus::updateBoxSize(
int value)
4940 if (m_Camera ==
nullptr)
4943 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4945 if (targetChip ==
nullptr)
4948 int subBinX, subBinY;
4949 targetChip->getBinning(&subBinX, &subBinY);
4951 QRect trackBox = m_FocusView->getTrackingBox();
4955 QRect(
center.x() - value / (2 * subBinX),
center.y() - value / (2 * subBinY), value / subBinX, value / subBinY);
4957 m_FocusView->setTrackingBox(trackBox);
4962 if (m_ImageData.isNull())
4969 emit newImage(m_FocusView);
4975 if (state() == Ekos::FOCUS_PROGRESS)
4978 if (subFramed ==
false)
4980 rememberStarCenter.setX(
x);
4981 rememberStarCenter.setY(
y);
4984 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
4986 int subBinX, subBinY;
4987 targetChip->getBinning(&subBinX, &subBinY);
4990 if (subBinX != (focusBinning->currentIndex() + 1))
4996 int offset = (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX) * 1.5;
5000 bool squareMovedOutside =
false;
5002 if (subFramed ==
false && m_OpsFocusSettings->focusSubFrame->isChecked() && targetChip->canSubframe())
5005 if (!isStarMeasureStarBased())
5011 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
5013 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
5016 x = (
x - offset) * subBinX;
5017 y = (
y - offset) * subBinY;
5018 int w = offset * 2 * subBinX;
5019 int h = offset * 2 * subBinY;
5038 QVariantMap settings = frameSettings[targetChip];
5043 settings[
"binx"] = subBinX;
5044 settings[
"biny"] = subBinY;
5046 frameSettings[targetChip] = settings;
5050 qCDebug(KSTARS_EKOS_FOCUS) <<
"Frame is subframed. X:" <<
x <<
"Y:" <<
y <<
"W:" << w <<
"H:" << h <<
"binX:" << subBinX <<
5053 m_FocusView->setFirstLoad(
true);
5057 if (isStarMeasureStarBased())
5059 starCenter.setX(w / (2 * subBinX));
5060 starCenter.setY(h / (2 * subBinY));
5067 double dist = sqrt((starCenter.x() -
x) * (starCenter.x() -
x) + (starCenter.y() -
y) * (starCenter.y() -
y));
5069 squareMovedOutside = (dist > (
static_cast<double>(m_OpsFocusSettings->focusBoxSize->value()) / subBinX));
5073 starRect =
QRect(starCenter.x() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinX),
5074 starCenter.y() - m_OpsFocusSettings->focusBoxSize->value() / (2 * subBinY),
5075 m_OpsFocusSettings->focusBoxSize->value() / subBinX,
5076 m_OpsFocusSettings->focusBoxSize->value() / subBinY);
5077 m_FocusView->setTrackingBox(starRect);
5082 starCenter.setZ(subBinX);
5084 if (squareMovedOutside && inAutoFocus ==
false && m_OpsFocusSettings->focusAutoStarEnabled->isChecked())
5086 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
true);
5087 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
5088 m_OpsFocusSettings->focusAutoStarEnabled->blockSignals(
false);
5089 appendLogText(
i18n(
"Disabling Auto Star Selection as star selection box was moved manually."));
5090 starSelected =
false;
5092 else if (starSelected ==
false)
5094 if (isStarMeasureStarBased())
5099 starSelected =
true;
5103 waitStarSelectTimer.stop();
5104 FocusState nextState = inAutoFocus ? FOCUS_PROGRESS : FOCUS_IDLE;
5105 if (nextState != state())
5107 setState(nextState);
5113 if (inAutoFocus || inAdjustFocus || adaptFocus->inAdaptiveFocus())
5117 str =
i18n(
"Autofocus");
5118 else if (inAdjustFocus)
5119 str =
i18n(
"Adjust Focus");
5121 str =
i18n(
"Adaptive Focus");
5123 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
5125 appendLogText(
i18n(
"Check focus request - Waiting 10sec for %1 to complete.", str));
5134 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_INTERNAL);
5140 if (inFocusLoop || inBuildOffsets)
5142 QString str = inFocusLoop ?
"Focus Looping" :
" Build Offsets";
5143 qCDebug(KSTARS_EKOS_FOCUS) <<
QString(
"Check Focus rejected, %1 is already running.").
arg(str);
5145 else if (!isStarMeasureStarBased())
5149 qCDebug(KSTARS_EKOS_FOCUS) <<
"Check Focus requested with minimum required HFR" << requiredHFR;
5150 minimumRequiredHFR = requiredHFR;
5156void Focus::toggleSubframe(
bool enable)
5158 if (enable ==
false)
5161 m_FocusView->setTrackingBoxEnabled(enable);
5162 starSelected =
false;
5167 m_OpsFocusSettings->focusNoMaskRB->setChecked(
true);
5172 m_OpsFocusSettings->focusRingMaskRB->setEnabled(!enable);
5173 m_OpsFocusSettings->focusMosaicMaskRB->setEnabled(!enable);
5177 setAutoStarAndBox();
5184void Focus::setUseWeights()
5186 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC || !m_OpsFocusSettings->focusUseFullField->isChecked()
5187 || m_StarMeasure == FOCUS_STAR_NUM_STARS || m_StarMeasure == FOCUS_STAR_FOURIER_POWER ||
5188 m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
5189 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
5191 m_OpsFocusProcess->focusUseWeights->setEnabled(
false);
5192 m_OpsFocusProcess->focusUseWeights->setChecked(
false);
5195 m_OpsFocusProcess->focusUseWeights->setEnabled(
true);
5202void Focus::setDenoise()
5204 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
5205 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
5206 m_OpsFocusProcess->focusDenoise->setEnabled(
true);
5209 m_OpsFocusProcess->focusDenoise->setEnabled(
false);
5210 m_OpsFocusProcess->focusDenoise->setChecked(
false);
5219void Focus::setDonutBuster()
5221 if (m_FocusAlgorithm != FOCUS_LINEAR1PASS)
5223 m_OpsFocusProcess->focusDonut->hide();
5224 m_OpsFocusProcess->focusDonut->setEnabled(
false);
5225 m_OpsFocusProcess->focusDonut->setChecked(
false);
5229 m_OpsFocusProcess->focusDonut->show();
5230 if ((m_StarMeasure == FOCUS_STAR_HFR || m_StarMeasure == FOCUS_STAR_HFR_ADJ || m_StarMeasure == FOCUS_STAR_FWHM) &&
5231 (m_FocusWalk == FOCUS_WALK_FIXED_STEPS || m_FocusWalk == FOCUS_WALK_CFZ_SHUFFLE) &&
5232 (m_CurveFit != CurveFitting::FOCUS_QUADRATIC))
5233 m_OpsFocusProcess->focusDonut->setEnabled(
true);
5236 m_OpsFocusProcess->focusDonut->setEnabled(
false);
5237 m_OpsFocusProcess->focusDonut->setChecked(
false);
5244 focusExposure->setValue(value);
5249 INDI_UNUSED(subBinY);
5250 focusBinning->setCurrentIndex(subBinX - 1);
5255 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(enable);
5260 m_OpsFocusSettings->focusSubFrame->setChecked(enable);
5265 m_OpsFocusSettings->focusBoxSize->setValue(boxSize);
5266 m_OpsFocusMechanics->focusTicks->setValue(stepSize);
5267 m_OpsFocusMechanics->focusMaxTravel->setValue(maxTravel);
5268 m_OpsFocusProcess->focusTolerance->setValue(tolerance);
5271void Focus::checkAutoStarTimeout()
5274 if (starCenter.isNull() && (inAutoFocus || minimumRequiredHFR > 0))
5278 if (rememberStarCenter.isNull() ==
false)
5280 focusStarSelected(rememberStarCenter.x(), rememberStarCenter.y());
5281 appendLogText(
i18n(
"No star was selected. Using last known position..."));
5286 initialFocuserAbsPosition = -1;
5287 appendLogText(
i18n(
"No star was selected. Aborting..."));
5288 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_NO_STARS);
5290 else if (state() == FOCUS_WAITING)
5291 setState(FOCUS_IDLE);
5294void Focus::setAbsoluteFocusTicks()
5296 if (absTicksSpin->value() == currentPosition)
5298 appendLogText(
i18n(
"Focuser already at %1...", currentPosition));
5301 focusInB->setEnabled(
false);
5302 focusOutB->setEnabled(
false);
5303 startGotoB->setEnabled(
false);
5304 if (!changeFocus(absTicksSpin->value() - currentPosition))
5305 qCDebug(KSTARS_EKOS_FOCUS) <<
"setAbsoluteFocusTicks unable to move focuser.";
5308void Focus::syncTrackingBoxPosition()
5310 if (m_OpsFocusSettings->focusUseFullField->isChecked() || starCenter.isNull())
5313 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5314 Q_ASSERT(targetChip);
5316 int subBinX = 1, subBinY = 1;
5317 targetChip->getBinning(&subBinX, &subBinY);
5319 double boxSize = m_OpsFocusSettings->focusBoxSize->value();
5321 targetChip->getFrame(&x, &y, &w, &h);
5323 if (boxSize / subBinX >= w || boxSize / subBinY >= h)
5325 m_OpsFocusSettings->focusBoxSize->setValue((boxSize / subBinX >= w) ? w : h);
5330 if (subBinX != starCenter.z())
5332 if (starCenter.z() > 0)
5334 starCenter.setX(starCenter.x() * (starCenter.z() / subBinX));
5335 starCenter.setY(starCenter.y() * (starCenter.z() / subBinY));
5338 starCenter.setZ(subBinX);
5342 if (isStarMeasureStarBased())
5343 starRect =
QRect(starCenter.x() - boxSize / (2 * subBinX), starCenter.y() - boxSize / (2 * subBinY),
5344 boxSize / subBinX, boxSize / subBinY);
5348 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
5349 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
5350 int boxTLX = starCenter.x() - boxSize / (2 * subBinX);
5351 boxTLX = std::max(boxTLX, minX);
5352 int boxTLY = starCenter.y() - boxSize / (2 * subBinY);
5353 boxTLY = std::max(boxTLY, minY);
5354 const int boxBRX = boxTLX + (boxSize / subBinX);
5356 boxTLX -= boxBRX - maxX;
5357 const int boxBRY = boxTLY + (boxSize / subBinY);
5359 boxTLY -= boxBRY - maxY;
5361 starRect =
QRect(boxTLX, boxTLY, boxSize / subBinX, boxSize / subBinY);
5363 m_FocusView->setTrackingBoxEnabled(
true);
5364 m_FocusView->setTrackingBox(starRect);
5367void Focus::showFITSViewer()
5369 static int lastFVTabID = -1;
5376 fv->loadData(m_ImageData, url, &lastFVTabID);
5377 connect(fv.get(), &FITSViewer::terminated,
this, [
this]()
5382 else if (fv->updateData(m_ImageData, url, lastFVTabID, &lastFVTabID) ==
false)
5383 fv->loadData(m_ImageData, url, &lastFVTabID);
5389void Focus::adjustFocusOffset(
int value,
bool useAbsoluteOffset)
5392 if (inAdjustFocus || adaptFocus->inAdaptiveFocus())
5394 QString str = inAdjustFocus ?
i18n(
"Adjust Focus") :
i18n(
"Adaptive Focus");
5395 if (++m_StartRetries < MAXIMUM_RESTART_ITERATIONS)
5397 appendLogText(
i18n(
"Adjust focus request - Waiting 10sec for %1 to complete.", str));
5400 adjustFocusOffset(value, useAbsoluteOffset);
5405 qCDebug(KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset called whilst" << str <<
"in progress. Ignoring...";
5406 emit focusPositionAdjusted();
5411 inAdjustFocus =
true;
5414 int newPosition = (useAbsoluteOffset) ? value : value + currentPosition;
5416 if (!changeFocus(newPosition - currentPosition))
5417 qCDebug(KSTARS_EKOS_FOCUS) <<
"adjustFocusOffset unable to move focuser";
5420void Focus::toggleFocusingWidgetFullScreen()
5422 if (focusingWidget->parent() ==
nullptr)
5424 focusingWidget->setParent(
this);
5425 rightLayout->insertWidget(0, focusingWidget);
5426 focusingWidget->showNormal();
5430 focusingWidget->setParent(
nullptr);
5431 focusingWidget->setWindowTitle(
i18nc(
"@title:window",
"Focus Frame"));
5433 focusingWidget->showMaximized();
5434 focusingWidget->show();
5438void Focus::setMountStatus(ISD::Mount::Status newState)
5442 case ISD::Mount::MOUNT_PARKING:
5443 case ISD::Mount::MOUNT_SLEWING:
5444 case ISD::Mount::MOUNT_MOVING:
5445 captureB->setEnabled(
false);
5446 startFocusB->setEnabled(
false);
5447 startAbInsB->setEnabled(
false);
5448 startLoopB->setEnabled(
false);
5463void Focus::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
5472 auto name = deviceRemoved->getDeviceName();
5476 if (m_Focuser && m_Focuser->getDeviceName() == name)
5478 m_Focuser->disconnect(
this);
5479 m_Focuser =
nullptr;
5488 for (
auto &oneSource : m_TemperatureSources)
5490 if (oneSource->getDeviceName() == name)
5493 if (m_LastSourceDeviceAutofocusTemperature && m_LastSourceDeviceAutofocusTemperature->getDeviceName() == name)
5494 m_LastSourceDeviceAutofocusTemperature.reset(
nullptr);
5496 m_TemperatureSources.removeAll(oneSource);
5499 defaultFocusTemperatureSource->removeItem(defaultFocusTemperatureSource->findText(name));
5506 if (m_Camera && m_Camera->getDeviceName() == name)
5508 m_Camera->disconnect(
this);
5519 if (m_FilterWheel && m_FilterWheel->getDeviceName() == name)
5521 m_FilterWheel->disconnect(
this);
5522 m_FilterWheel =
nullptr;
5532void Focus::setupFilterManager()
5535 if (m_FilterManager)
5536 m_FilterManager->disconnect(
this);
5539 Ekos::Manager::Instance()->createFilterManager(m_FilterWheel);
5542 Ekos::Manager::Instance()->getFilterManager(m_FilterWheel->getDeviceName(), m_FilterManager);
5547 connect(
this, &Focus::absolutePositionChanged, m_FilterManager.get(), &FilterManager::setFocusAbsolutePosition);
5549 if (m_Focuser && m_Focuser->isConnected() && currentPosition >= 0)
5550 m_FilterManager->setFocusAbsolutePosition(currentPosition);
5553 connect(
this, &Focus::newStatus,
this, [
this](Ekos::FocusState state,
const QString trainname,
const bool update)
5555 Q_UNUSED(trainname);
5556 if (m_FilterManager)
5558 m_FilterManager->setFocusStatus(state);
5559 if (update && focusFilter->currentIndex() != -1 && canAbsMove && state == Ekos::FOCUS_COMPLETE)
5561 m_FilterManager->setFilterAbsoluteFocusDetails(focusFilter->currentIndex(), currentPosition,
5562 m_LastSourceAutofocusTemperature, m_LastSourceAutofocusAlt);
5570 connect(m_FilterManager.get(), &FilterManager::newStatus,
this, [
this](Ekos::FilterState filterState)
5573 if (filterState == FILTER_OFFSET && state() != Ekos::FOCUS_PROGRESS)
5575 if (m_GuidingSuspended == false && m_OpsFocusSettings->focusSuspendGuiding->isChecked())
5577 m_GuidingSuspended = true;
5578 emit suspendGuiding();
5584 connect(m_FilterManager.get(), &FilterManager::ready,
this, [
this]()
5587 if (focusFilter->currentIndex() != currentFilterPosition - 1)
5588 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5590 if (filterPositionPending)
5592 filterPositionPending = false;
5595 else if (fallbackFilterPending)
5597 fallbackFilterPending =
false;
5598 setState(m_pendingState);
5599 m_pendingState = FOCUS_IDLE;
5604 connect(m_FilterManager.get(), &FilterManager::failed,
this, [
this]()
5606 if (filterPositionPending)
5608 appendLogText(i18n(
"Filter operation failed."));
5609 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FILTER_MANAGER);
5614 connect(m_FilterManager.get(), &FilterManager::runAutoFocus,
this, &Focus::runAutoFocus);
5617 connect(m_FilterManager.get(), &FilterManager::abortAutoFocus,
this, &Focus::abort);
5620 connect(m_FilterManager.get(), &FilterManager::newFocusOffset,
this, &Focus::adjustFocusOffset);
5623 connect(m_FilterManager.get(), &FilterManager::labelsChanged,
this, [
this]()
5625 focusFilter->clear();
5626 focusFilter->addItems(m_FilterManager->getFilterLabels());
5627 currentFilterPosition = m_FilterManager->getFilterPosition();
5628 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5632 connect(m_FilterManager.get(), &FilterManager::positionChanged,
this, [
this]()
5634 currentFilterPosition = m_FilterManager->getFilterPosition();
5635 focusFilter->setCurrentIndex(currentFilterPosition - 1);
5639 connect(m_FilterManager.get(), &FilterManager::exposureChanged,
this, [
this]()
5641 focusExposure->setValue(m_FilterManager->getFilterExposure());
5645 connect(m_FilterManager.get(), &FilterManager::wavelengthChanged,
this, [
this]()
5647 wavelengthChanged();
5651void Focus::connectFilterManager()
5656 if (m_FilterManager)
5658 m_FilterManager->refreshFilterModel();
5659 m_FilterManager->show();
5660 m_FilterManager->raise();
5665 connect(
this, &Focus::focusPositionAdjusted,
this, [
this]()
5667 if (m_FilterManager)
5668 m_FilterManager->setFocusOffsetComplete();
5669 if (m_GuidingSuspended && state() != Ekos::FOCUS_PROGRESS)
5671 QTimer::singleShot(m_OpsFocusMechanics->focusSettleTime->value() * 1000,
this, [
this]()
5673 m_GuidingSuspended = false;
5674 emit resumeGuiding();
5680 connect(
this, &Focus::focusAFOptimise,
this, [
this]()
5682 completeFocusProcedure(Ekos::FOCUS_COMPLETE, Ekos::FOCUS_FAIL_OPTIMISED_OUT);
5689 if (inAutoFocus && m_OpsFocusProcess->focusDonut->isEnabled())
5692 if (m_FilterManager)
5693 m_FilterManager->setFilterExposure(focusFilter->currentIndex(), focusExposure->value());
5699 if (m_FilterManager)
5701 focusExposure->setValue(m_FilterManager->getFilterExposure(text));
5711 if (m_Camera ==
nullptr)
5714 if (m_Camera->isBLOBEnabled() ==
false)
5717 if (Options::guiderType() != Ekos::Guide::GUIDE_INTERNAL)
5718 m_Camera->setBLOBEnabled(
true);
5724 KSMessageBox::Instance()->disconnect(
this);
5725 m_Camera->setVideoStreamEnabled(
enabled);
5727 KSMessageBox::Instance()->questionYesNo(
i18n(
"Image transfer is disabled for this camera. Would you like to enable it?"));
5731 m_Camera->setVideoStreamEnabled(
enabled);
5747void Focus::setVideoStreamEnabled(
bool enabled)
5751 liveVideoB->setChecked(
true);
5756 liveVideoB->setChecked(
false);
5761void Focus::processCaptureTimeout()
5763 m_captureInProgress =
false;
5765 if (m_abortInProgress)
5768 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame in " << __FUNCTION__;
5772 captureTimeoutCounter++;
5774 if (captureTimeoutCounter >= 3)
5776 captureTimeoutCounter = 0;
5777 m_MissingCameraCounter = 0;
5778 captureTimeout.stop();
5779 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5780 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5784 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
5785 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5786 targetChip->abortExposure();
5788 capture(focusExposure->value());
5792 else if (m_MissingCameraCounter < 40)
5794 m_MissingCameraCounter++;
5795 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to restart focus exposure as camera is missing, trying again in 5 seconds...";
5800 m_MissingCameraCounter = 0;
5801 captureTimeoutCounter = 0;
5802 captureTimeout.stop();
5803 appendLogText(
i18n(
"Exposure timeout. Aborting..."));
5804 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_TIMEOUT);
5809void Focus::processCaptureErrorDefault()
5811 processCaptureError(ISD::Camera::ERROR_CAPTURE);
5816 m_captureInProgress =
false;
5817 captureTimeout.stop();
5819 if (m_abortInProgress)
5821 qCDebug(KSTARS_EKOS_FOCUS) <<
"Abort AF: discarding frame in " << __FUNCTION__;
5827 appendLogText(
i18n(
"Failed to save image. Aborting..."));
5828 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5835 captureFailureCounter++;
5837 if (captureFailureCounter >= 3)
5839 captureFailureCounter = 0;
5840 captureTimeoutCounter = 0;
5841 m_MissingCameraCounter = 0;
5842 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5843 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5847 ISD::CameraChip *targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
5848 targetChip->abortExposure();
5849 capture(focusExposure->value());
5853 else if (m_MissingCameraCounter < 40)
5855 m_MissingCameraCounter++;
5856 qCDebug(KSTARS_EKOS_FOCUS) <<
"Unable to restart focus exposure as camera is missing, trying again in 5 seconds...";
5863 m_MissingCameraCounter = 0;
5864 captureFailureCounter = 0;
5865 captureTimeoutCounter = 0;
5866 captureTimeout.stop();
5867 appendLogText(
i18n(
"Exposure failure. Aborting..."));
5868 completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_CAPTURE_FAILED);
5872void Focus::syncSettings()
5885 if ( (dsb = qobject_cast<QDoubleSpinBox*>(sender())))
5888 value = dsb->
value();
5891 else if ( (sb = qobject_cast<QSpinBox*>(sender())))
5894 value = sb->
value();
5896 else if ( (cb = qobject_cast<QCheckBox*>(sender())))
5901 else if ( (gb = qobject_cast<QGroupBox*>(sender())))
5906 else if ( (rb = qobject_cast<QRadioButton*>(sender())))
5912 m_Settings.remove(key);
5917 else if ( (cbox = qobject_cast<QComboBox*>(sender())))
5922 else if ( (s = qobject_cast<QSplitter*>(sender())))
5930 Options::self()->setProperty(key.
toLatin1(), value);
5932 m_Settings[key] = value;
5933 m_GlobalSettings[key] = value;
5937 m_DebounceTimer.start();
5943void Focus::settleSettings()
5945 emit settingsUpdated(getAllSettings());
5947 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
5948 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
5951void Focus::loadGlobalSettings()
5956 QVariantMap settings;
5958 for (
auto &oneWidget : findChildren<QComboBox*>())
5960 if (oneWidget->objectName() ==
"opticalTrainCombo")
5963 key = oneWidget->objectName();
5964 value = Options::self()->property(key.
toLatin1());
5965 if (value.
isValid() && oneWidget->count() > 0)
5967 oneWidget->setCurrentText(value.
toString());
5968 settings[key] = value;
5971 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5975 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
5977 key = oneWidget->objectName();
5978 value = Options::self()->property(key.
toLatin1());
5981 oneWidget->setValue(value.
toDouble());
5982 settings[key] = value;
5985 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
5989 for (
auto &oneWidget : findChildren<QSpinBox*>())
5991 key = oneWidget->objectName();
5992 value = Options::self()->property(key.
toLatin1());
5995 oneWidget->setValue(value.
toInt());
5996 settings[key] = value;
5999 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
6003 for (
auto &oneWidget : findChildren<QCheckBox*>())
6005 key = oneWidget->objectName();
6006 value = Options::self()->property(key.
toLatin1());
6009 oneWidget->setChecked(value.
toBool());
6010 settings[key] = value;
6012 else if (key != forceInSeqAF->objectName())
6013 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
6017 for (
auto &oneWidget : findChildren<QGroupBox*>())
6019 if (oneWidget->isCheckable())
6021 key = oneWidget->objectName();
6022 value = Options::self()->property(key.
toLatin1());
6025 oneWidget->setChecked(value.
toBool());
6026 settings[key] = value;
6029 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
6034 for (
auto &oneWidget : findChildren<QSplitter*>())
6036 key = oneWidget->objectName();
6037 value = Options::self()->property(key.
toLatin1());
6042 oneWidget->restoreState(valueBA);
6043 settings[key] = valueBA;
6046 qCDebug(KSTARS_EKOS_FOCUS) <<
"Option" << key <<
"not found!";
6050 for (
auto &oneWidget : findChildren<QRadioButton*>())
6052 key = oneWidget->objectName();
6053 value = Options::self()->property(key.
toLatin1());
6056 oneWidget->setChecked(value.
toBool());
6057 settings[key] = value;
6062 m_GlobalSettings = m_Settings = settings;
6065void Focus::checkMosaicMaskLimits()
6067 if (m_Camera ==
nullptr || m_Camera->isConnected() ==
false)
6069 auto targetChip = m_Camera->getChip(ISD::CameraChip::PRIMARY_CCD);
6070 if (targetChip ==
nullptr || frameSettings.contains(targetChip) ==
false)
6072 auto settings = frameSettings[targetChip];
6075 auto width = settings[
"w"].toInt();
6076 auto height = settings[
"h"].toInt();
6077 if (width == 0 || height == 0)
6081 auto min = std::min(width, height);
6083 m_OpsFocusSettings->focusMosaicTileWidth->setMaximum(100 * min / (3 * width));
6086void Focus::connectSyncSettings()
6089 for (
auto &oneWidget : findChildren<QComboBox*>())
6091 if (oneWidget != opticalTrainCombo)
6095 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
6099 for (
auto &oneWidget : findChildren<QSpinBox*>())
6103 for (
auto &oneWidget : findChildren<QCheckBox*>())
6107 for (
auto &oneWidget : findChildren<QGroupBox*>())
6108 if (oneWidget->isCheckable())
6112 for (
auto &oneWidget : findChildren<QSplitter*>())
6116 for (
auto &oneWidget : findChildren<QRadioButton*>())
6120void Focus::disconnectSyncSettings()
6123 for (
auto &oneWidget : findChildren<QComboBox*>())
6124 disconnect(oneWidget, QOverload<int>::of(&
QComboBox::activated),
this, &Ekos::Focus::syncSettings);
6127 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
6131 for (
auto &oneWidget : findChildren<QSpinBox*>())
6135 for (
auto &oneWidget : findChildren<QCheckBox*>())
6139 for (
auto &oneWidget : findChildren<QGroupBox*>())
6140 if (oneWidget->isCheckable())
6144 for (
auto &oneWidget : findChildren<QSplitter*>())
6148 for (
auto &oneWidget : findChildren<QRadioButton*>())
6152void Focus::initPlots()
6156 profileDialog =
new QDialog(
this);
6159 profileDialog->setWindowTitle(
i18nc(
"@title:window",
"Relative Profile"));
6160 profilePlot =
new FocusProfilePlot(profileDialog);
6163 profileDialog->setLayout(profileLayout);
6164 profileDialog->resize(400, 300);
6167 connect(
this, &Ekos::Focus::newHFR, [
this](
double currentHFR,
int pos)
6169 Q_UNUSED(pos) profilePlot->drawProfilePlot(currentHFR);
6173void Focus::initConnections()
6176 waitStarSelectTimer.setInterval(AUTO_STAR_TIMEOUT);
6181 m_DebounceTimer.setInterval(500);
6182 m_DebounceTimer.setSingleShot(
true);
6197 captureTimer.setSingleShot(
true);
6204 captureTimeout.setSingleShot(
true);
6239 &Ekos::Focus::updateBoxSize);
6245 m_CFZDialog->show();
6246 m_CFZDialog->raise();
6252 focusAdvisor->setButtons(
false);
6253 focusAdvisor->show();
6254 focusAdvisor->raise();
6260 emit inSequenceAF(enabled, opticalTrain());
6266 setFocusDetection(static_cast<StarAlgorithm>(index));
6272 setFocusAlgorithm(static_cast<Algorithm>(index));
6278 this, [&](
int index)
6280 setCurveFit(static_cast<CurveFitting::CurveFit>(index));
6285 this, [&](
int index)
6287 setStarMeasure(static_cast<StarMeasure>(index));
6292 this, [&](
int index)
6294 setStarPSF(static_cast<StarPSF>(index));
6299 this, [&](
int index)
6301 setStarUnits(static_cast<StarUnits>(index));
6306 this, [&](
int index)
6308 setWalk(static_cast<FocusWalk>(index));
6319 starCenter = QVector3D();
6320 starSelected = false;
6321 m_FocusView->setTrackingBox(QRect());
6329 &Ekos::Focus::calcCFZ);
6332 &Ekos::Focus::calcCFZ);
6373void Focus::setFocusDetection(StarAlgorithm starAlgorithm)
6375 static bool first =
true;
6376 if (!first && m_FocusDetection == starAlgorithm)
6381 m_FocusDetection = starAlgorithm;
6384 setFocusAlgorithm(m_FocusAlgorithm);
6385 setAutoStarAndBox();
6393void Focus::setAutoStarAndBox()
6395 if (m_FocusDetection == ALGORITHM_BAHTINOV)
6397 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6398 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6399 m_OpsFocusSettings->focusBoxSize->setEnabled(m_OpsFocusSettings->focusSubFrame->isChecked());
6400 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(m_OpsFocusSettings->focusSubFrame->isChecked());
6401 m_OpsFocusSettings->focusBoxSize->setMaximum(512);
6402 if (m_OpsFocusSettings->focusBoxSize->value() > 512)
6403 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
6405 else if(m_OpsFocusSettings->focusSubFrame->isChecked())
6407 if(isStarMeasureStarBased())
6409 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
true);
6411 m_OpsFocusSettings->focusBoxSize->setEnabled(
true);
6412 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
true);
6413 if (m_OpsFocusSettings->focusBoxSize->value() > 256)
6414 m_OpsFocusSettings->focusBoxSize->setValue(m_OpsFocusSettings->focusBoxSize->value());
6415 m_OpsFocusSettings->focusBoxSize->setMaximum(256);
6419 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6420 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6423 m_OpsFocusSettings->focusBoxSize->setEnabled(
true);
6424 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
true);
6425 int maxSize = std::min(m_CcdWidth, m_CcdHeight);
6426 int step = m_OpsFocusSettings->focusBoxSize->singleStep();
6427 maxSize = std::max(256, (maxSize / step) * step);
6428 m_OpsFocusSettings->focusBoxSize->setMaximum(maxSize);
6434 m_OpsFocusSettings->focusAutoStarEnabled->setEnabled(
false);
6435 m_OpsFocusSettings->focusAutoStarEnabled->setChecked(
false);
6436 m_OpsFocusSettings->focusBoxSize->setEnabled(
false);
6437 m_OpsFocusSettings->focusBoxSizeLabel->setEnabled(
false);
6442void Focus::setFocusAlgorithm(Algorithm algorithm)
6444 m_FocusAlgorithm = algorithm;
6447 case FOCUS_ITERATIVE:
6449 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6450 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6451 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6452 m_OpsFocusProcess->focusMultiRowAverage->hide();
6454 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6455 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6456 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6457 m_OpsFocusProcess->focusGaussianSigma->hide();
6459 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6460 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6461 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6462 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6464 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasureLabel);
6465 m_OpsFocusProcess->focusStarMeasureLabel->hide();
6466 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarMeasure);
6467 m_OpsFocusProcess->focusStarMeasure->hide();
6469 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6470 m_OpsFocusProcess->focusStarPSFLabel->hide();
6471 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6472 m_OpsFocusProcess->focusStarPSF->hide();
6474 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6475 m_OpsFocusProcess->focusUseWeights->hide();
6477 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6478 m_OpsFocusProcess->focusR2LimitLabel->hide();
6479 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6480 m_OpsFocusProcess->focusR2Limit->hide();
6482 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6483 m_OpsFocusProcess->focusRefineCurveFit->hide();
6484 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6486 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6487 m_OpsFocusProcess->focusToleranceLabel->hide();
6488 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6489 m_OpsFocusProcess->focusTolerance->hide();
6491 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6492 m_OpsFocusProcess->focusThresholdLabel->hide();
6493 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6494 m_OpsFocusProcess->focusThreshold->hide();
6496 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFitLabel);
6497 m_OpsFocusProcess->focusCurveFitLabel->hide();
6498 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusCurveFit);
6499 m_OpsFocusProcess->focusCurveFit->hide();
6501 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6502 m_OpsFocusProcess->focusDenoise->hide();
6505 m_OpsFocusProcess->focusDonut->hide();
6506 m_OpsFocusProcess->focusDonut->setChecked(
false);
6509 m_OpsFocusProcess->focusScanStartPos->hide();
6510 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6513 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6516 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6518 m_OpsFocusProcess->focusStarMeasure->clear();
6519 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6520 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6524 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6525 m_OpsFocusProcess->focusToleranceLabel->show();
6526 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6527 m_OpsFocusProcess->focusTolerance->show();
6529 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6530 m_OpsFocusProcess->focusFramesCountLabel->show();
6531 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6532 m_OpsFocusProcess->focusFramesCount->show();
6534 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6535 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6536 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6537 m_OpsFocusProcess->focusHFRFramesCount->show();
6539 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6541 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6542 m_OpsFocusProcess->focusThresholdLabel->show();
6543 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6544 m_OpsFocusProcess->focusThreshold->show();
6546 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6548 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6549 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6550 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6551 m_OpsFocusProcess->focusMultiRowAverage->show();
6553 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6554 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6555 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6556 m_OpsFocusProcess->focusGaussianSigma->show();
6558 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6559 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6560 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6561 m_OpsFocusProcess->focusGaussianKernelSize->show();
6565 startAbInsB->setEnabled(canAbInsStart());
6569 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6570 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6571 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6573 m_OpsFocusSettings->focusAFOptimize->setValue(0);
6574 m_OpsFocusSettings->focusAFOptimize->setEnabled(
false);
6577 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6578 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6581 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6583 m_OpsFocusMechanics->focusWalk->clear();
6584 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6585 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6589 case FOCUS_POLYNOMIAL:
6591 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6592 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6593 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6594 m_OpsFocusProcess->focusMultiRowAverage->hide();
6596 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6597 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6598 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6599 m_OpsFocusProcess->focusGaussianSigma->hide();
6601 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6602 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6603 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6604 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6606 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6607 m_OpsFocusProcess->focusStarPSFLabel->hide();
6608 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6609 m_OpsFocusProcess->focusStarPSF->hide();
6611 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6612 m_OpsFocusProcess->focusUseWeights->hide();
6614 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6615 m_OpsFocusProcess->focusR2LimitLabel->hide();
6616 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6617 m_OpsFocusProcess->focusR2Limit->hide();
6619 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6620 m_OpsFocusProcess->focusRefineCurveFit->hide();
6621 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6623 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6624 m_OpsFocusProcess->focusToleranceLabel->hide();
6625 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6626 m_OpsFocusProcess->focusTolerance->hide();
6628 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6629 m_OpsFocusProcess->focusThresholdLabel->hide();
6630 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6631 m_OpsFocusProcess->focusThreshold->hide();
6633 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6634 m_OpsFocusProcess->focusDenoise->hide();
6637 m_OpsFocusProcess->focusDonut->hide();
6638 m_OpsFocusProcess->focusDonut->setChecked(
false);
6641 m_OpsFocusProcess->focusScanStartPos->hide();
6642 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6645 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6647 m_OpsFocusProcess->focusStarMeasure->clear();
6648 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6649 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6654 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6655 m_OpsFocusProcess->focusCurveFitLabel->show();
6656 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6657 m_OpsFocusProcess->focusCurveFit->show();
6658 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6660 m_OpsFocusProcess->focusCurveFit->clear();
6661 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6662 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6665 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6666 m_OpsFocusProcess->focusToleranceLabel->show();
6667 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6668 m_OpsFocusProcess->focusTolerance->show();
6670 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6671 m_OpsFocusProcess->focusFramesCountLabel->show();
6672 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6673 m_OpsFocusProcess->focusFramesCount->show();
6675 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6676 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6677 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6678 m_OpsFocusProcess->focusHFRFramesCount->show();
6680 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6682 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6683 m_OpsFocusProcess->focusThresholdLabel->show();
6684 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6685 m_OpsFocusProcess->focusThreshold->show();
6687 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6689 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6690 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6691 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6692 m_OpsFocusProcess->focusMultiRowAverage->show();
6694 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6695 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6696 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6697 m_OpsFocusProcess->focusGaussianSigma->show();
6699 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6700 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6701 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6702 m_OpsFocusProcess->focusGaussianKernelSize->show();
6706 startAbInsB->setEnabled(canAbInsStart());
6710 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6711 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6712 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6714 m_OpsFocusSettings->focusAFOptimize->setValue(0);
6715 m_OpsFocusSettings->focusAFOptimize->setEnabled(
false);
6718 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
true);
6719 m_OpsFocusMechanics->focusOutSteps->setEnabled(
false);
6722 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6724 m_OpsFocusMechanics->focusWalk->clear();
6725 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6726 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6732 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6733 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6734 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6735 m_OpsFocusProcess->focusMultiRowAverage->hide();
6737 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6738 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6739 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6740 m_OpsFocusProcess->focusGaussianSigma->hide();
6742 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6743 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6744 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6745 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6747 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6748 m_OpsFocusProcess->focusThresholdLabel->hide();
6749 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6750 m_OpsFocusProcess->focusThreshold->hide();
6752 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
6753 m_OpsFocusProcess->focusStarPSFLabel->hide();
6754 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
6755 m_OpsFocusProcess->focusStarPSF->hide();
6757 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6758 m_OpsFocusProcess->focusUseWeights->hide();
6760 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2LimitLabel);
6761 m_OpsFocusProcess->focusR2LimitLabel->hide();
6762 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusR2Limit);
6763 m_OpsFocusProcess->focusR2Limit->hide();
6765 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusRefineCurveFit);
6766 m_OpsFocusProcess->focusRefineCurveFit->hide();
6767 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
6769 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6770 m_OpsFocusProcess->focusDenoise->hide();
6773 m_OpsFocusProcess->focusDonut->hide();
6774 m_OpsFocusProcess->focusDonut->setChecked(
false);
6777 m_OpsFocusProcess->focusScanStartPos->hide();
6778 m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
6781 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6783 m_OpsFocusProcess->focusStarMeasure->clear();
6784 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6785 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6790 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6791 m_OpsFocusProcess->focusCurveFitLabel->show();
6792 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6793 m_OpsFocusProcess->focusCurveFit->show();
6794 if (m_OpsFocusProcess->focusCurveFit->count() != 1)
6796 m_OpsFocusProcess->focusCurveFit->clear();
6797 m_OpsFocusProcess->focusCurveFit->addItem(m_CurveFitText.at(CurveFitting::FOCUS_QUADRATIC));
6798 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_QUADRATIC);
6801 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusToleranceLabel, 3, 0);
6802 m_OpsFocusProcess->focusToleranceLabel->show();
6803 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusTolerance, 3, 1);
6804 m_OpsFocusProcess->focusTolerance->show();
6806 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 3, 2);
6807 m_OpsFocusProcess->focusFramesCountLabel->show();
6808 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 3, 3);
6809 m_OpsFocusProcess->focusFramesCount->show();
6811 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 4, 2);
6812 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6813 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 4, 3);
6814 m_OpsFocusProcess->focusHFRFramesCount->show();
6816 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6818 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 5, 0);
6819 m_OpsFocusProcess->focusThresholdLabel->show();
6820 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 5, 1);
6821 m_OpsFocusProcess->focusThreshold->show();
6823 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6825 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 5, 0);
6826 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6827 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 5, 1);
6828 m_OpsFocusProcess->focusMultiRowAverage->show();
6830 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 5, 2);
6831 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6832 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 5, 3);
6833 m_OpsFocusProcess->focusGaussianSigma->show();
6835 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 6, 0);
6836 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6837 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 6, 1);
6838 m_OpsFocusProcess->focusGaussianKernelSize->show();
6842 startAbInsB->setEnabled(canAbInsStart());
6846 m_OpsFocusSettings->focusAdaptive->setChecked(
false);
6847 m_OpsFocusSettings->focusAdaptStart->setChecked(
false);
6848 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(
false);
6850 if (m_FilterManager)
6851 m_OpsFocusSettings->focusAFOptimize->setEnabled(
true);
6854 m_OpsFocusSettings->focusAFOptimize->setValue(0);
6855 m_OpsFocusSettings->focusAFOptimize->setEnabled(
false);
6859 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
6860 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
6863 if (m_OpsFocusMechanics->focusWalk->count() != 1)
6865 m_OpsFocusMechanics->focusWalk->clear();
6866 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
6867 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
6871 case FOCUS_LINEAR1PASS:
6873 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverageLabel);
6874 m_OpsFocusProcess->focusMultiRowAverageLabel->hide();
6875 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusMultiRowAverage);
6876 m_OpsFocusProcess->focusMultiRowAverage->hide();
6878 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigmaLabel);
6879 m_OpsFocusProcess->focusGaussianSigmaLabel->hide();
6880 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianSigma);
6881 m_OpsFocusProcess->focusGaussianSigma->hide();
6883 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel);
6884 m_OpsFocusProcess->focusGaussianKernelSizeLabel->hide();
6885 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusGaussianKernelSize);
6886 m_OpsFocusProcess->focusGaussianKernelSize->hide();
6888 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThresholdLabel);
6889 m_OpsFocusProcess->focusThresholdLabel->hide();
6890 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusThreshold);
6891 m_OpsFocusProcess->focusThreshold->hide();
6893 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusToleranceLabel);
6894 m_OpsFocusProcess->focusToleranceLabel->hide();
6895 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusTolerance);
6896 m_OpsFocusProcess->focusTolerance->hide();
6900 if (m_FocusDetection == ALGORITHM_SEP && m_CurveFit != CurveFitting::FOCUS_QUADRATIC)
6902 if (m_OpsFocusProcess->focusStarMeasure->count() != m_StarMeasureText.count())
6904 m_OpsFocusProcess->focusStarMeasure->clear();
6905 m_OpsFocusProcess->focusStarMeasure->addItems(m_StarMeasureText);
6906 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6910#if !defined(HAVE_OPENCV)
6918 else if (m_FocusDetection != ALGORITHM_SEP || m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
6920 if (m_OpsFocusProcess->focusStarMeasure->count() != 1)
6922 m_OpsFocusProcess->focusStarMeasure->clear();
6923 m_OpsFocusProcess->focusStarMeasure->addItem(m_StarMeasureText.at(FOCUS_STAR_HFR));
6924 m_OpsFocusProcess->focusStarMeasure->setCurrentIndex(FOCUS_STAR_HFR);
6930 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFitLabel, 1, 2);
6931 m_OpsFocusProcess->focusCurveFitLabel->show();
6932 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusCurveFit, 1, 3);
6933 m_OpsFocusProcess->focusCurveFit->show();
6934 if (m_OpsFocusProcess->focusCurveFit->count() != m_CurveFitText.count())
6936 m_OpsFocusProcess->focusCurveFit->clear();
6937 m_OpsFocusProcess->focusCurveFit->addItems(m_CurveFitText);
6938 m_OpsFocusProcess->focusCurveFit->setCurrentIndex(CurveFitting::FOCUS_HYPERBOLA);
6941 if (m_StarMeasure == FOCUS_STAR_STDDEV || m_StarMeasure == FOCUS_STAR_SOBEL ||
6942 m_StarMeasure == FOCUS_STAR_LAPLASSIAN || m_StarMeasure == FOCUS_STAR_CANNY)
6944 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusUseWeights);
6945 m_OpsFocusProcess->focusUseWeights->hide();
6946 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusDenoise, 3, 0, 1, 2);
6947 m_OpsFocusProcess->focusDenoise->show();
6951 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusDenoise);
6952 m_OpsFocusProcess->focusDenoise->hide();
6953 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusUseWeights, 3, 0, 1, 2);
6954 m_OpsFocusProcess->focusUseWeights->show();
6957 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2LimitLabel, 3, 2);
6958 m_OpsFocusProcess->focusR2LimitLabel->show();
6959 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusR2Limit, 3, 3);
6960 m_OpsFocusProcess->focusR2Limit->show();
6962 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusRefineCurveFit, 4, 0, 1, 2);
6963 m_OpsFocusProcess->focusRefineCurveFit->show();
6965 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCountLabel, 4, 2);
6966 m_OpsFocusProcess->focusFramesCountLabel->show();
6967 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusFramesCount, 4, 3);
6968 m_OpsFocusProcess->focusFramesCount->show();
6970 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCountLabel, 5, 2);
6971 m_OpsFocusProcess->focusHFRFramesCountLabel->show();
6972 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusHFRFramesCount, 5, 3);
6973 m_OpsFocusProcess->focusHFRFramesCount->show();
6975 if (m_FocusDetection == ALGORITHM_THRESHOLD)
6977 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThresholdLabel, 6, 0);
6978 m_OpsFocusProcess->focusThresholdLabel->show();
6979 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusThreshold, 6, 1);
6980 m_OpsFocusProcess->focusThreshold->show();
6982 else if (m_FocusDetection == ALGORITHM_BAHTINOV)
6984 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverageLabel, 6, 0);
6985 m_OpsFocusProcess->focusMultiRowAverageLabel->show();
6986 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusMultiRowAverage, 6, 1);
6987 m_OpsFocusProcess->focusMultiRowAverage->show();
6989 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigmaLabel, 6, 2);
6990 m_OpsFocusProcess->focusGaussianSigmaLabel->show();
6991 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianSigma, 6, 3);
6992 m_OpsFocusProcess->focusGaussianSigma->show();
6994 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSizeLabel, 7, 0);
6995 m_OpsFocusProcess->focusGaussianKernelSizeLabel->show();
6996 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusGaussianKernelSize, 7, 1);
6997 m_OpsFocusProcess->focusGaussianKernelSize->show();
7001 m_OpsFocusProcess->focusDonut->show();
7002 m_OpsFocusProcess->focusDonut->setEnabled(
true);
7005 m_OpsFocusProcess->focusScanStartPos->show();
7006 m_OpsFocusProcess->focusScanStartPos->setEnabled(
true);
7009 startAbInsB->setEnabled(canAbInsStart());
7013 m_OpsFocusSettings->adaptiveFocusGroup->setEnabled(canAbsMove);
7015 if (m_FilterManager)
7016 m_OpsFocusSettings->focusAFOptimize->setEnabled(
true);
7019 m_OpsFocusSettings->focusAFOptimize->setValue(0);
7020 m_OpsFocusSettings->focusAFOptimize->setEnabled(
false);
7025 m_OpsFocusMechanics->focusMaxSingleStep->setEnabled(
false);
7026 m_OpsFocusMechanics->focusOutSteps->setEnabled(
true);
7029 if (m_CurveFit == CurveFitting::FOCUS_QUADRATIC)
7031 if (m_OpsFocusMechanics->focusWalk->count() != 1)
7033 m_OpsFocusMechanics->focusWalk->clear();
7034 m_OpsFocusMechanics->focusWalk->addItem(m_FocusWalkText.at(FOCUS_WALK_CLASSIC));
7035 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
7040 if (m_OpsFocusMechanics->focusWalk->count() != m_FocusWalkText.count())
7042 m_OpsFocusMechanics->focusWalk->clear();
7043 m_OpsFocusMechanics->focusWalk->addItems(m_FocusWalkText);
7044 m_OpsFocusMechanics->focusWalk->setCurrentIndex(FOCUS_WALK_CLASSIC);
7051void Focus::setCurveFit(CurveFitting::CurveFit curve)
7053 if (m_OpsFocusProcess->focusCurveFit->currentIndex() == -1)
7056 static bool first =
true;
7057 if (!first && m_CurveFit == curve)
7063 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
7070 case CurveFitting::FOCUS_QUADRATIC:
7071 m_OpsFocusProcess->focusR2Limit->setEnabled(
false);
7072 m_OpsFocusProcess->focusRefineCurveFit->setChecked(
false);
7073 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
false);
7076 case CurveFitting::FOCUS_HYPERBOLA:
7077 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
7078 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
7081 case CurveFitting::FOCUS_PARABOLA:
7082 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
7083 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
7086 case CurveFitting::FOCUS_2DGAUSSIAN:
7087 m_OpsFocusProcess->focusR2Limit->setEnabled(
true);
7088 m_OpsFocusProcess->focusRefineCurveFit->setEnabled(
true);
7096void Focus::setStarMeasure(StarMeasure starMeasure)
7098 if (m_OpsFocusProcess->focusStarMeasure->currentIndex() == -1)
7101 static bool first =
true;
7102 if (!first && m_StarMeasure == starMeasure)
7107 m_StarMeasure = starMeasure;
7108 setFocusAlgorithm(
static_cast<Algorithm
> (m_OpsFocusProcess->focusAlgorithm->currentIndex()));
7112 setAutoStarAndBox();
7118 switch(m_StarMeasure)
7120 case FOCUS_STAR_HFR:
7121 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
7122 m_FocusView->setStarsHFREnabled(
true);
7125 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
7126 m_OpsFocusProcess->focusStarPSFLabel->hide();
7127 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
7128 m_OpsFocusProcess->focusStarPSF->hide();
7131 case FOCUS_STAR_HFR_ADJ:
7132 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
7133 m_FocusView->setStarsHFREnabled(
false);
7136 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
7137 m_OpsFocusProcess->focusStarPSFLabel->hide();
7138 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
7139 m_OpsFocusProcess->focusStarPSF->hide();
7142 case FOCUS_STAR_FWHM:
7143 m_OptDir = CurveFitting::OPTIMISATION_MINIMISE;
7145 m_FocusView->setStarsHFREnabled(
false);
7148 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSFLabel, 2, 2);
7149 m_OpsFocusProcess->focusStarPSFLabel->show();
7150 m_OpsFocusProcess->gridLayoutProcess->addWidget(m_OpsFocusProcess->focusStarPSF, 2, 3);
7151 m_OpsFocusProcess->focusStarPSF->show();
7154 case FOCUS_STAR_NUM_STARS:
7155 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
7156 m_FocusView->setStarsHFREnabled(
true);
7159 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
7160 m_OpsFocusProcess->focusStarPSFLabel->hide();
7161 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
7162 m_OpsFocusProcess->focusStarPSF->hide();
7165 case FOCUS_STAR_FOURIER_POWER:
7166 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
7167 m_FocusView->setStarsHFREnabled(
true);
7170 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
7171 m_OpsFocusProcess->focusStarPSFLabel->hide();
7172 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
7173 m_OpsFocusProcess->focusStarPSF->hide();
7176 case FOCUS_STAR_STDDEV:
7177 case FOCUS_STAR_SOBEL:
7178 case FOCUS_STAR_LAPLASSIAN:
7179 case FOCUS_STAR_CANNY:
7180 m_OptDir = CurveFitting::OPTIMISATION_MAXIMISE;
7181 m_FocusView->setStarsHFREnabled(
true);
7184 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSFLabel);
7185 m_OpsFocusProcess->focusStarPSFLabel->hide();
7186 m_OpsFocusProcess->gridLayoutProcess->removeWidget(m_OpsFocusProcess->focusStarPSF);
7187 m_OpsFocusProcess->focusStarPSF->hide();
7195void Focus::setStarPSF(StarPSF starPSF)
7197 m_StarPSF = starPSF;
7200void Focus::setStarUnits(StarUnits starUnits)
7202 m_StarUnits = starUnits;
7205void Focus::setWalk(FocusWalk walk)
7207 if (m_OpsFocusMechanics->focusWalk->currentIndex() == -1)
7210 static bool first =
true;
7211 if (!first && m_FocusWalk == walk)
7220 case FOCUS_WALK_CLASSIC:
7221 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumStepsLabel,
7222 m_OpsFocusMechanics->focusOutStepsLabel);
7223 m_OpsFocusMechanics->focusNumStepsLabel->hide();
7224 m_OpsFocusMechanics->focusOutStepsLabel->show();
7225 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusNumSteps,
7226 m_OpsFocusMechanics->focusOutSteps);
7227 m_OpsFocusMechanics->focusNumSteps->hide();
7228 m_OpsFocusMechanics->focusOutSteps->show();
7231 case FOCUS_WALK_FIXED_STEPS:
7232 case FOCUS_WALK_CFZ_SHUFFLE:
7233 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutStepsLabel,
7234 m_OpsFocusMechanics->focusNumStepsLabel);
7235 m_OpsFocusMechanics->focusOutStepsLabel->hide();
7236 m_OpsFocusMechanics->focusNumStepsLabel->show();
7237 m_OpsFocusMechanics->gridLayoutMechanics->replaceWidget(m_OpsFocusMechanics->focusOutSteps,
7238 m_OpsFocusMechanics->focusNumSteps);
7239 m_OpsFocusMechanics->focusOutSteps->hide();
7240 m_OpsFocusMechanics->focusNumSteps->show();
7249double Focus::getStarUnits(
const StarMeasure starMeasure,
const StarUnits starUnits)
7251 if (starUnits == FOCUS_UNITS_PIXEL || starMeasure == FOCUS_STAR_NUM_STARS || starMeasure == FOCUS_STAR_FOURIER_POWER
7252 || starMeasure == FOCUS_STAR_STDDEV || starMeasure == FOCUS_STAR_SOBEL || starMeasure == FOCUS_STAR_LAPLASSIAN
7253 || starMeasure == FOCUS_STAR_CANNY)
7255 if (m_CcdPixelSizeX <= 0.0 || m_FocalLength <= 0.0)
7259 return m_CcdPixelSizeX / m_FocalLength * 206.265;
7262void Focus::calcCFZ()
7264 double cfzMicrons, cfzSteps;
7265 double cfzCameraSteps = calcCameraCFZ() / m_CFZUI->focusCFZStepSize->value();
7267 switch(
static_cast<Focus::CFZAlgorithm
> (m_CFZUI->focusCFZAlgorithm->currentIndex()))
7269 case Focus::FOCUS_CFZ_CLASSIC:
7271 cfzMicrons = 4.88f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f *
7272 pow(m_CFZUI->focusCFZFNumber->value(), 2.0f);
7273 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7274 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7275 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4.88 t λ f²");
7276 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7277 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7278 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7279 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7282 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
7283 m_CFZUI->focusCFZTauLabel->hide();
7284 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
7285 m_CFZUI->focusCFZTau->hide();
7286 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
7287 m_CFZUI->focusCFZSeeingLabel->hide();
7288 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
7289 m_CFZUI->focusCFZSeeing->hide();
7292 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
7293 m_CFZUI->focusCFZToleranceLabel->show();
7294 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
7295 m_CFZUI->focusCFZTolerance->show();
7296 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
7297 m_CFZUI->focusCFZWavelengthLabel->show();
7298 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
7299 m_CFZUI->focusCFZWavelength->show();
7302 case Focus::FOCUS_CFZ_WAVEFRONT:
7304 cfzMicrons = 4.0f * m_CFZUI->focusCFZTolerance->value() * m_CFZUI->focusCFZWavelength->value() / 1000.0f * pow(
7305 m_CFZUI->focusCFZFNumber->value(),
7307 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7308 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7309 m_CFZUI->focusCFZFormula->setText(
"CFZ = 4 t λ f²");
7310 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7311 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7312 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7313 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7316 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTauLabel);
7317 m_CFZUI->focusCFZTauLabel->hide();
7318 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTau);
7319 m_CFZUI->focusCFZTau->hide();
7320 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeingLabel);
7321 m_CFZUI->focusCFZSeeingLabel->hide();
7322 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZSeeing);
7323 m_CFZUI->focusCFZSeeing->hide();
7326 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZToleranceLabel, 1, 0);
7327 m_CFZUI->focusCFZToleranceLabel->show();
7328 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTolerance, 1, 1);
7329 m_CFZUI->focusCFZTolerance->show();
7330 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelengthLabel, 2, 0);
7331 m_CFZUI->focusCFZWavelengthLabel->show();
7332 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZWavelength, 2, 1);
7333 m_CFZUI->focusCFZWavelength->show();
7336 case Focus::FOCUS_CFZ_GOLD:
7338 cfzMicrons = 0.00225f * pow(m_CFZUI->focusCFZTau->value(), 0.5f) * m_CFZUI->focusCFZSeeing->value()
7339 * pow(m_CFZUI->focusCFZFNumber->value(), 2.0f) * m_CFZUI->focusCFZAperture->value();
7340 cfzSteps = cfzMicrons / m_CFZUI->focusCFZStepSize->value();
7341 m_cfzSteps = std::round(std::max(cfzSteps, cfzCameraSteps));
7342 m_CFZUI->focusCFZFormula->setText(
"CFZ = 0.00225 √τ θ f² A");
7343 m_CFZUI->focusCFZ->setText(
QString(
"%1 μm").arg(cfzMicrons, 0,
'f', 0));
7344 m_CFZUI->focusCFZSteps->setText(
QString(
"%1 steps").arg(cfzSteps, 0,
'f', 0));
7345 m_CFZUI->focusCFZCameraSteps->setText(
QString(
"%1 steps").arg(cfzCameraSteps, 0,
'f', 0));
7346 m_CFZUI->focusCFZFinal->setText(
QString(
"%1 steps").arg(m_cfzSteps, 0,
'f', 0));
7349 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZToleranceLabel);
7350 m_CFZUI->focusCFZToleranceLabel->hide();
7351 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZTolerance);
7352 m_CFZUI->focusCFZTolerance->hide();
7353 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelengthLabel);
7354 m_CFZUI->focusCFZWavelengthLabel->hide();
7355 m_CFZUI->gridLayoutCFZ->removeWidget(m_CFZUI->focusCFZWavelength);
7356 m_CFZUI->focusCFZWavelength->hide();
7359 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTauLabel, 1, 0);
7360 m_CFZUI->focusCFZTauLabel->show();
7361 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZTau, 1, 1);
7362 m_CFZUI->focusCFZTau->show();
7363 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeingLabel, 2, 0);
7364 m_CFZUI->focusCFZSeeingLabel->show();
7365 m_CFZUI->gridLayoutCFZ->addWidget(m_CFZUI->focusCFZSeeing, 2, 1);
7366 m_CFZUI->focusCFZSeeing->show();
7369 if (linearFocuser !=
nullptr && linearFocuser->isDone())
7370 emit drawCFZ(linearFocuser->solution(), linearFocuser->solutionValue(), m_cfzSteps,
7371 m_CFZUI->focusCFZDisplayVCurve->isChecked());
7377double Focus::calcCameraCFZ()
7379 return m_CcdPixelSizeX * pow(m_CFZUI->focusCFZFNumber->value(), 2.0) * m_CFZUI->focusCFZAperture->value() / 1000.0;
7382void Focus::wavelengthChanged()
7385 if (m_FilterManager)
7387 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
7392void Focus::resetCFZToOT()
7395 m_CFZUI->focusCFZFNumber->setValue(m_FocalRatio);
7396 m_CFZUI->focusCFZAperture->setValue(m_Aperture);
7399 if (m_FilterManager)
7401 if (m_CFZUI->focusCFZWavelength->value() != m_FilterManager->getFilterWavelength(
filter()))
7402 m_CFZUI->focusCFZWavelength->setValue(m_FilterManager->getFilterWavelength(
filter()));
7407void Focus::setState(FocusState newState,
const bool update)
7409 qCDebug(KSTARS_EKOS_FOCUS) <<
"Focus State changes from" << getFocusStatusString(m_state) <<
"to" << getFocusStatusString(
7412 emit newStatus(m_state, opticalTrain(), update);
7415void Focus::initView()
7417 m_FocusView.reset(
new FITSView(focusingWidget, FITS_FOCUS));
7419 m_FocusView->setBaseSize(focusingWidget->size());
7420 m_FocusView->createFloatingToolBar();
7423 focusingWidget->setLayout(vlayout);
7425 m_FocusView->setStarsEnabled(
true);
7426 m_FocusView->setStarsHFREnabled(
true);
7429void Focus::initHelperObjects()
7432 starFitting.reset(
new CurveFitting());
7433 focusFWHM.reset(
new FocusFWHM(m_ScaleCalc));
7434 focusFourierPower.reset(
new FocusFourierPower(m_ScaleCalc));
7435#if defined(HAVE_OPENCV)
7436 focusBlurriness.reset(
new FocusBlurriness());
7440 adaptFocus.reset(
new AdaptiveFocus(
this));
7443 focusAdvisor.reset(
new FocusAdvisor(
this));
7446QVariantMap Focus::getAllSettings()
const
7448 QVariantMap settings;
7451 for (
auto &oneWidget : findChildren<QComboBox*>())
7452 settings.insert(oneWidget->objectName(), oneWidget->currentText());
7455 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
7456 settings.insert(oneWidget->objectName(), oneWidget->value());
7459 for (
auto &oneWidget : findChildren<QSpinBox*>())
7460 settings.insert(oneWidget->objectName(), oneWidget->value());
7463 for (
auto &oneWidget : findChildren<QCheckBox*>())
7464 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7467 for (
auto &oneWidget : findChildren<QGroupBox*>())
7468 if (oneWidget->isCheckable())
7469 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7472 for (
auto &oneWidget : findChildren<QSplitter*>())
7473 settings.insert(oneWidget->objectName(),
QString::fromUtf8(oneWidget->saveState().toBase64()));
7476 for (
auto &oneWidget : findChildren<QRadioButton*>())
7477 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
7482void Focus::setAllSettings(
const QVariantMap &settings)
7486 disconnectSyncSettings();
7488 for (
auto &name : settings.keys())
7491 auto comboBox = findChild<QComboBox*>(name);
7494 syncControl(settings, name, comboBox);
7499 auto doubleSpinBox = findChild<QDoubleSpinBox*>(name);
7502 syncControl(settings, name, doubleSpinBox);
7507 auto spinBox = findChild<QSpinBox*>(name);
7510 syncControl(settings, name, spinBox);
7515 auto checkbox = findChild<QCheckBox*>(name);
7518 syncControl(settings, name, checkbox);
7523 auto groupbox = findChild<QGroupBox*>(name);
7524 if (groupbox && groupbox->isCheckable())
7526 syncControl(settings, name, groupbox);
7531 auto splitter = findChild<QSplitter*>(name);
7534 syncControl(settings, name, splitter);
7539 auto radioButton = findChild<QRadioButton*>(name);
7542 syncControl(settings, name, radioButton);
7548 for (
auto &key : settings.keys())
7550 auto value = settings[key];
7552 Options::self()->setProperty(key.
toLatin1(), value);
7554 m_Settings[key] = value;
7555 m_GlobalSettings[key] = value;
7558 emit settingsUpdated(getAllSettings());
7561 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
7562 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Focus, m_Settings);
7565 connectSyncSettings();
7568 m_CurveFit =
static_cast<CurveFitting::CurveFit
> (m_OpsFocusProcess->focusCurveFit->currentIndex());
7569 setFocusDetection(
static_cast<StarAlgorithm
> (m_OpsFocusProcess->focusDetection->currentIndex()));
7570 setCurveFit(
static_cast<CurveFitting::CurveFit
>(m_OpsFocusProcess->focusCurveFit->currentIndex()));
7571 setStarMeasure(
static_cast<StarMeasure
>(m_OpsFocusProcess->focusStarMeasure->currentIndex()));
7572 setWalk(
static_cast<FocusWalk
>(m_OpsFocusMechanics->focusWalk->currentIndex()));
7576bool Focus::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
7587 if ((pSB = qobject_cast<QSpinBox *>(widget)))
7589 const int value = settings[key].
toInt(&ok);
7596 else if ((pDSB = qobject_cast<QDoubleSpinBox *>(widget)))
7598 const double value = settings[key].toDouble(&ok);
7605 else if ((pCB = qobject_cast<QCheckBox *>(widget)))
7607 const bool value = settings[key].toBool();
7612 else if ((pGB = qobject_cast<QGroupBox *>(widget)))
7614 const bool value = settings[key].toBool();
7619 else if ((pRadioButton = qobject_cast<QRadioButton *>(widget)))
7621 const bool value = settings[key].toBool();
7627 else if ((pComboBox = qobject_cast<QComboBox *>(widget)))
7629 const QString value = settings[key].toString();
7633 else if ((pSplitter = qobject_cast<QSplitter *>(widget)))
7643void Focus::setupOpticalTrainManager()
7645 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, [
this]()
7648 const int current = opticalTrainCombo->currentIndex();
7651 if (current >= 0 & current < opticalTrainCombo->count())
7652 opticalTrainCombo->setCurrentIndex(current);
7656 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
7660 const int id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(index));
7662 if (m_focuserId == 0)
7664 ProfileSettings::Instance()->setOneSetting(ProfileSettings::FocusOpticalTrain,
id);
7666 refreshOpticalTrain(
id);
7667 emit trainChanged();
7671void Focus::initOpticalTrain()
7673 opticalTrainCombo->blockSignals(
true);
7674 opticalTrainCombo->clear();
7675 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
7676 trainB->setEnabled(
true);
7678 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::FocusOpticalTrain);
7682 auto id = trainID.
toUInt();
7685 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
7687 qCWarning(KSTARS_EKOS_FOCUS) <<
"Optical train doesn't exist for id" << id;
7688 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
7690 refreshOpticalTrain(
id);
7693 opticalTrainCombo->blockSignals(
false);
7696void Focus::refreshOpticalTrain(
const int id)
7698 bool validSettings =
false;
7699 auto name = OpticalTrainManager::Instance()->name(
id);
7701 opticalTrainCombo->setCurrentText(name);
7707 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
7709 auto focuser = OpticalTrainManager::Instance()->getFocuser(name);
7710 setFocuser(focuser);
7712 auto scope = OpticalTrainManager::Instance()->getScope(name);
7713 double reducer = OpticalTrainManager::Instance()->getReducer(name);
7714 setScopeDetails(scope, reducer);
7716 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Focus);
7717 if (settings.isValid())
7719 validSettings =
true;
7720 auto map = settings.toJsonObject().toVariantMap();
7721 if (map != m_Settings)
7724 setAllSettings(map);
7728 auto camera = OpticalTrainManager::Instance()->getCamera(name);
7731 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(camera->getDeviceName(), scope[
"name"].toString()));
7734 auto nvp = camera->getNumber(
"CCD_INFO");
7737 m_CcdPixelSizeX = 0.0;
7738 m_CcdWidth = m_CcdHeight = 0;
7742 auto np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
7744 m_CcdPixelSizeX = np->getValue();
7745 np = nvp->findWidgetByName(
"CCD_MAX_X");
7747 m_CcdWidth = np->getValue();
7748 np = nvp->findWidgetByName(
"CCD_MAX_Y");
7750 m_CcdHeight = np->getValue();
7755 auto filterWheel = OpticalTrainManager::Instance()->getFilterWheel(name);
7756 setFilterWheel(filterWheel);
7764 focusAdvisor->setupParams(name);
7765 focusAdvisor->updateParams();
7772void Focus::setScopeDetails(
const QJsonObject &scope,
const double reducer)
7774 m_Aperture = scope[
"aperture"].toDouble(-1);
7775 m_FocalLength = scope[
"focal_length"].toDouble(-1);
7776 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
7777 m_ScopeType = scope[
"type"].toString();
7778 m_Reducer = reducer;
7781 if (m_Reducer > 0.0)
7782 m_FocalLength *= m_Reducer;
7785 if (m_FocalRatio <= 0.0)
7787 m_FocalRatio = (m_Aperture > 0.001) ? m_FocalLength / m_Aperture : 0.0f;
7788 else if (m_Aperture < 0.0)
7790 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.
Q_SCRIPTABLE bool setFilter(const QString &filter)
DBUS interface function.
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 loadStellarSolverProfiles()
setWeatherData Updates weather data that could be used to extract focus temperature from observatory ...
Q_SCRIPTABLE Q_NOREPLY void setBinning(int binX, int binY)
DBUS interface function.
void clearDataPoints()
clearDataPoints Remove all data points from HFR plots
Q_SCRIPTABLE QString camera()
DBUS interface function.
Q_SCRIPTABLE QString focuser()
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void setAutoStarEnabled(bool enable)
DBUS interface function.
void runAutoFocus(const AutofocusReason autofocusReason, const QString &reasonInfo)
Run the autofocus process for the currently selected filter.
Q_SCRIPTABLE QString filterWheel()
DBUS interface function.
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 reconnectFocuser(const QString &focuser)
reconnectFocuser Add focuser to the list of available focusers.
bool setFocuser(ISD::Focuser *device)
addFocuser Add focuser to the list of available focusers.
void resetFocuser()
Move the focuser to the initial focus position.
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 selectFocusStarFraction(double x, double y)
selectFocusStarFraction Select the focus star based by fraction of the overall size.
void appendLogText(const QString &logtext)
setFocusStatus Upon completion of the focusing process, set its status (fail or pass) and reset focus...
Q_SCRIPTABLE bool useFullField()
DBUS interface function.
void adaptiveFocus()
adaptiveFocus moves the focuser between subframes to stay at focus
Q_SCRIPTABLE Q_NOREPLY void resetFrame()
DBUS interface function.
void meridianFlipStarted()
React when a meridian flip has been started.
void processTemperatureSource(INDI::Property prop)
processTemperatureSource Updates focus temperature source.
void removeDevice(const QSharedPointer< ISD::GenericDevice > &deviceRemoved)
removeDevice Remove device from Focus module
void syncCameraInfo()
syncCameraInfo Read current CCD information and update settings accordingly.
void checkFilter()
Check Filter and make sure information is updated accordingly.
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 checkStopFocus(bool abort)
checkStopFocus Perform checks before stopping the autofocus operation.
void checkFocuser()
Check Focuser and make sure information is updated accordingly.
Q_SCRIPTABLE Q_NOREPLY void setExposure(double value)
DBUS interface function.
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
QStringList getStellarSolverProfiles()
getStellarSolverProfiles
Q_SCRIPTABLE Q_NOREPLY void setAutoFocusParameters(int boxSize, int stepSize, int maxTravel, double tolerance)
DBUS interface function.
Q_SCRIPTABLE Ekos::FocusState status()
DBUS interface function.
bool setFilterWheel(ISD::FilterWheel *device)
addFilter Add filter to the list of available filters.
void updateTemperatureSources(const QList< QSharedPointer< ISD::GenericDevice > > &temperatureSources)
updateTemperatureSources Update list of available temperature sources.
Q_SCRIPTABLE Q_NOREPLY void setAutoSubFrameEnabled(bool enable)
DBUS interface function.
bool setCamera(ISD::Camera *device)
Add CCD to the list of available CCD.
void syncCCDControls()
Update camera controls like Gain, ISO, Offset...etc.
void checkCamera()
Check CCD and make sure information is updated accordingly.
void selectImageMask()
setImageMask Select the currently active image mask filtering the stars relevant for focusing
CameraChip class controls a particular chip in camera.
Camera class controls an INDI Camera device.
@ ERROR_SAVE
INDI Camera error.
Focuser class handles control of INDI focuser devices.
KPageWidgetItem * addPage(QWidget *page, const QString &itemName, const QString &pixmapName=QString(), const QString &header=QString(), bool manage=true)
void setIcon(const QIcon &icon)
static KStars * Instance()
The sky coordinates of a point in the sky.
An angle, stored as degrees, but expressible in many ways.
const double & Degrees() const
Q_SCRIPTABLE Q_NOREPLY void checkFocus(double requiredHFR)
checkFocus Given the minimum required HFR, check focus and calculate HFR.
Q_SCRIPTABLE bool focusOut(int ms=-1, int speedFactor=1)
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void capture(double settleTime=0.0)
DBUS interface function.
Q_SCRIPTABLE bool focusIn(int ms=-1, int speedFactor=1)
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void start()
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void abort()
DBUS interface function.
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
QString name(const QVariant &location)
int distance(const GeoCoordinates &coord1, const GeoCoordinates &coord2)
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
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)
qint64 secsTo(const QDateTime &other) const const
QString toString(QStringView format, QCalendar cal) const const
QString filePath(const QString &fileName) const const
void valueChanged(double d)
bool exists(const QString &path)
bool isChecked() const const
Qt::KeyboardModifiers keyboardModifiers()
QIcon fromTheme(const QString &name)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
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