7#include "focusadvisor.h" 
    9#include "focusalgorithms.h" 
   11#include "ekos/auxiliary/opticaltrainmanager.h" 
   12#include "ekos/auxiliary/opticaltrainsettings.h" 
   13#include "ekos/auxiliary/stellarsolverprofile.h" 
   20const char * FOCUSER_SIMULATOR = 
"Focuser Simulator";
 
   21const int MAXIMUM_FOCUS_ADVISOR_ITERATIONS = 1001;
 
   22const int NUM_JUMPS_PER_SECTOR = 10;
 
   23const int FIND_STARS_MIN_STARS = 2;
 
   24const double TARGET_MAXMIN_HFR_RATIO = 3.0;
 
   25const double INITIAL_MAXMIN_HFR_RATIO = 2.0;
 
   26const int NUM_STEPS_PRE_AF = 11;
 
   28FocusAdvisor::FocusAdvisor(QWidget *parent) : QDialog(parent)
 
   35    m_focus = 
static_cast<Focus *
>(parent);
 
   41FocusAdvisor::~FocusAdvisor()
 
   45void FocusAdvisor::processUI()
 
   48    m_helpDialog = 
new QDialog(
this);
 
   49    m_helpUI.reset(
new Ui::focusAdvisorHelpDialog());
 
   50    m_helpUI->setupUi(m_helpDialog);
 
   60    m_runButton->setToolTip(
"Run Focus Advisor");
 
   61    m_stopButton->setToolTip(
"Stop Focus Advisor");
 
   62    m_helpButton->setToolTip(
"List parameter settings");
 
   76void FocusAdvisor::setupResultsTable()
 
   78    focusAdvTable->setColumnCount(RESULTS_MAX_COLS);
 
   79    focusAdvTable->setRowCount(0);
 
   83    focusAdvTable->setHorizontalHeaderItem(RESULTS_SECTION, itemSection);
 
   87    focusAdvTable->setHorizontalHeaderItem(RESULTS_RUN_NUMBER, itemRunNumber);
 
   91    focusAdvTable->setHorizontalHeaderItem(RESULTS_START_POSITION, itemStartPosition);
 
   95    focusAdvTable->setHorizontalHeaderItem(RESULTS_STEP_SIZE, itemStepSize);
 
   99    focusAdvTable->setHorizontalHeaderItem(RESULTS_AFOVERSCAN, itemAFOverscan);
 
  103    focusAdvTable->setHorizontalHeaderItem(RESULTS_TEXT, itemText);
 
  106    focusAdvTable->hide();
 
  111void FocusAdvisor::setupHelpTable()
 
  115    m_helpUI->table->setHorizontalHeaderItem(HELP_PARAMETER, itemParameter);
 
  118    itemCurrentValue->
setToolTip(
i18n(
"Current value of the parameter"));
 
  119    m_helpUI->table->setHorizontalHeaderItem(HELP_CURRENT_VALUE, itemCurrentValue);
 
  122    itemProposedValue->
setToolTip(
i18n(
"Focus Advisor proposed value for the parameter"));
 
  123    m_helpUI->table->setHorizontalHeaderItem(HELP_NEW_VALUE, itemProposedValue);
 
  131void FocusAdvisor::setButtons(
const bool running)
 
  133    bool canRun = m_focus->m_Focuser && m_focus->m_Focuser->isConnected() && m_focus->m_Focuser->canAbsMove();
 
  134    m_runButton->setEnabled(!running && canRun);
 
  135    m_stopButton->setEnabled(running);
 
  136    m_helpButton->setEnabled(!running);
 
  140bool FocusAdvisor::canFocusAdvisorRun()
 
  143    return m_focus->m_Focuser && m_focus->m_Focuser->isConnected() && m_focus->m_Focuser->canAbsMove() &&
 
  144           m_focus->m_FocusAlgorithm == Focus::FOCUS_LINEAR1PASS &&
 
  145           (m_focus->m_StarMeasure == Focus::FOCUS_STAR_HFR || m_focus->m_StarMeasure == Focus::FOCUS_STAR_HFR_ADJ
 
  146            || m_focus->m_StarMeasure == Focus::FOCUS_STAR_FWHM) &&
 
  147           (m_focus->m_CurveFit == CurveFitting::FOCUS_HYPERBOLA || m_focus->m_CurveFit == CurveFitting::FOCUS_PARABOLA);
 
  150bool FocusAdvisor::start()
 
  153    focusAdvTable->setRowCount(0);
 
  154    focusAdvTable->sizePolicy();
 
  159    if (m_focus->inFocusLoop || m_focus->inAdjustFocus || m_focus->inAutoFocus || m_focus->inBuildOffsets || m_focus->inAFOptimise ||
 
  160        m_focus->inScanStartPos || inFocusAdvisor())
 
  162        m_focus->appendLogText(
i18n(
"Focus Advisor: another focus action in progress. Please try again."));
 
  166    if (focusAdvUpdateParams->isChecked())
 
  169        focusAdvUpdateParamsLabel->setText(
i18n(
"Done"));
 
  170        emit newStage(UpdatingParameters);
 
  173    m_inFindStars = focusAdvFindStars->isChecked();
 
  174    m_inPreAFAdj = focusAdvCoarseAdj->isChecked();
 
  175    m_inAFAdj = focusAdvFineAdj->isChecked();
 
  176    if (m_inFindStars || m_inPreAFAdj || m_inAFAdj)
 
  178        if (canFocusAdvisorRun())
 
  181            m_initialScanStartPos = m_focus->m_OpsFocusProcess->focusScanStartPos->isChecked();
 
  182            m_focus->m_OpsFocusProcess->focusScanStartPos->setChecked(
false);
 
  183            m_focus->runAutoFocus(FOCUS_FOCUS_ADVISOR, 
"");
 
  187            m_focus->appendLogText(
i18n(
"Focus Advisor cannot run with current params."));
 
  195void FocusAdvisor::stop()
 
  197    abort(
i18n(
"Focus Advisor stopped"));
 
  202void FocusAdvisor::help()
 
  205    m_helpDialog->show();
 
  206    m_helpDialog->raise();
 
  209void FocusAdvisor::addSectionToHelpTable(
int &row, 
const QString §ion)
 
  211    if (++row >= m_helpUI->table->rowCount())
 
  212        m_helpUI->table->setRowCount(row + 1);
 
  219    m_helpUI->table->setItem(row, HELP_PARAMETER, item);
 
  222void FocusAdvisor::addParamToHelpTable(
int &row, 
const QString ¶meter, 
const QString ¤tValue,
 
  225    if (m_helpUI->focusAdvHelpOnlyChanges->isChecked() && newValue == currentValue)
 
  228    if (++row >= m_helpUI->table->rowCount())
 
  229        m_helpUI->table->setRowCount(row + 1);
 
  231    m_helpUI->table->setItem(row, HELP_PARAMETER, itemParameter);
 
  233    m_helpUI->table->setItem(row, HELP_CURRENT_VALUE, itemCurrentValue);
 
  235    if (newValue != currentValue)
 
  242    m_helpUI->table->setItem(row, HELP_NEW_VALUE, itemNewValue);
 
  246void FocusAdvisor::resizeHelpDialog()
 
  253    m_helpUI->verticalLayout->layout()->getContentsMargins(&left, &top, &right, &bottom);
 
  255    const int width = m_helpUI->table->horizontalHeader()->length() +
 
  256                      m_helpUI->table->verticalHeader()->width() +
 
  257                      m_helpUI->table->verticalScrollBar()->width() +
 
  258                      m_helpUI->table->frameWidth() * 2 +
 
  260                      m_helpDialog->contentsMargins().left() + m_helpDialog->contentsMargins().right() + 8;
 
  262    m_helpDialog->resize(width, m_helpDialog->height());
 
  266void FocusAdvisor::updateParams()
 
  268    m_focus->setAllSettings(m_map);
 
  269    addResultsTable(
i18n(
"Update Parameters"), -1, -1, -1, -1, 
"Done");
 
  273void FocusAdvisor::setupParams(
const QString &OTName)
 
  276    m_map = getOTDefaults(OTName);
 
  277    bool noDefaults = m_map.isEmpty();
 
  279    if (!m_map.isEmpty())
 
  283    bool longFL = m_focus->m_FocalLength > 1500;
 
  284    double imageScale = m_focus->getStarUnits(Focus::FOCUS_STAR_HFR, Focus::FOCUS_UNITS_ARCSEC);
 
  285    bool centralObstruction = scopeHasObstruction(m_focus->m_ScopeType);
 
  288    m_helpUI->helpLabel->setText(
QString(
"Recommendations: %1 FL=%2 ImageScale=%3")
 
  289                                 .arg(m_focus->m_ScopeType).
arg(m_focus->m_FocalLength).
arg(imageScale, 0, 
'f', 2));
 
  293    m_helpUI->table->setRowCount(0);
 
  297    addSectionToHelpTable(row, 
i18n(
"Camera & Filter Wheel Parameters"));
 
  300    double exposure = longFL ? 4.0 : 2.0;
 
  301    processParam(exposure, row, m_map, m_focus->focusExposure, 
"Exposure");
 
  305    if (m_focus->focusBinning->isEnabled())
 
  308        QString binTarget = (imageScale < 1.0) ? 
"2x2" : 
"1x1";
 
  310        for (
int i = 0; i < m_focus->focusBinning->count(); i++)
 
  312            if (m_focus->focusBinning->itemText(i) == binTarget)
 
  319    processParam(binning, row, m_map, m_focus->focusBinning, 
"Binning");
 
  322    processParam(m_focus->focusGain->value(), row, m_map, m_focus->focusGain, 
"Gain");
 
  325    processParam(m_focus->focusISO->currentText(), row, m_map, m_focus->focusISO, 
"ISO");
 
  328    processParam(m_focus->focusFilter->currentText(), row, m_map, m_focus->focusFilter, 
"Filter");
 
  331    addSectionToHelpTable(row, 
i18n(
"Settings Parameters"));
 
  334    processParam(
false, row, m_map, m_focus->m_OpsFocusSettings->focusAutoStarEnabled, 
"Auto Select Star");
 
  337    processParam(m_focus->m_OpsFocusSettings->focusSuspendGuiding->isChecked(), row, m_map,
 
  338                 m_focus->m_OpsFocusSettings->focusSuspendGuiding, 
"Auto Select Star");
 
  341    processParam(
false, row, m_map, m_focus->m_OpsFocusSettings->useFocusDarkFrame, 
"Dark Frame");
 
  344    processParam(
true, row, m_map, m_focus->m_OpsFocusSettings->focusUseFullField, 
"Full Field");
 
  345    processParam(
false, row, m_map, m_focus->m_OpsFocusSettings->focusSubFrame, 
"Sub Frame");
 
  348    processParam(32, row, m_map, m_focus->m_OpsFocusSettings->focusBoxSize, 
"Box");
 
  351    processParam(m_focus->m_OpsFocusSettings->focusUnits->currentText(), row, m_map, m_focus->m_OpsFocusSettings->focusUnits,
 
  355    processParam(m_focus->m_OpsFocusSettings->focusGuideSettleTime->value(), row, m_map,
 
  356                 m_focus->m_OpsFocusSettings->focusGuideSettleTime, 
"Guide Settle");
 
  359    processParam(0, row, m_map,
 
  360                 m_focus->m_OpsFocusSettings->focusAFOptimize, 
"AF Optimize");
 
  364    if (m_focus->m_OpsFocusSettings->focusNoMaskRB->isChecked())
 
  365        maskCurrent = 
"Use all stars";
 
  366    else if (m_focus->m_OpsFocusSettings->focusRingMaskRB->isChecked())
 
  368        double inner = m_focus->m_OpsFocusSettings->focusFullFieldInnerRadius->value();
 
  369        double outer = m_focus->m_OpsFocusSettings->focusFullFieldOuterRadius->value();
 
  370        maskCurrent = 
QString(
"Ring Mask %1%-%2%").
arg(inner, 0, 
'f', 1).
arg(outer, 0, 
'f', 1);
 
  374        int width = m_focus->m_OpsFocusSettings->focusMosaicTileWidth->value();
 
  375        int spacer = m_focus->m_OpsFocusSettings->focusMosaicSpace->value();
 
  376        maskCurrent = 
QString(
"Mosaic Mask %1% (%2 px)").
arg(width).
arg(spacer);
 
  382        m_map.insert(
"focusNoMaskRB", 
false);
 
  383        m_map.insert(
"focusRingMaskRB", 
true);
 
  384        m_map.insert(
"focusMosaicMaskRB", 
false);
 
  385        m_map.insert(
"focusFullFieldInnerRadius", 0.0);
 
  386        m_map.insert(
"focusFullFieldOuterRadius", 80.0);
 
  387        maskNew = 
QString(
"Ring Mask %1%-%2%").
arg(0.0, 0, 
'f', 1).
arg(80.0, 0, 
'f', 1);
 
  391        bool noMask = m_map.value(
"focusNoMaskRB", 
false).toBool();
 
  392        bool ringMask = m_map.value(
"focusRingMaskRB", 
false).toBool();
 
  393        bool mosaicMask = m_map.value(
"focusMosaicMaskRB", 
false).toBool();
 
  395            maskNew = 
"Use all stars";
 
  398            double inner = m_map.value(
"focusFullFieldInnerRadius", 0.0).toDouble(&ok);
 
  399            if (!ok || inner < 0.0 || inner > 100.0)
 
  401            double outer = m_map.value(
"focusFullFieldOuterRadius", 80.0).toDouble(&ok);
 
  402            if (!ok || outer < 0.0 || outer > 100.0)
 
  404            maskNew = 
QString(
"Ring Mask %1%-%2%").
arg(inner, 0, 
'f', 1).
arg(outer, 0, 
'f', 1);
 
  408            int width = m_map.value(
"focusMosaicTileWidth", 0.0).toInt(&ok);
 
  409            if (!ok || width < 0 || width > 100)
 
  411            int spacer = m_map.value(
"focusMosaicSpace", 0.0).toInt(&ok);
 
  412            if (!ok || spacer < 0 || spacer > 100)
 
  414            maskNew = 
QString(
"Mosaic Mask %1% (%2 px)").
arg(width).
arg(spacer);
 
  417    addParamToHelpTable(row, 
i18n(
"Mask"), maskCurrent, maskNew);
 
  420    processParam(
false, row, m_map, m_focus->m_OpsFocusSettings->focusAdaptive, 
"Adaptive Focus");
 
  423    processParam(m_focus->m_OpsFocusSettings->focusAdaptiveMinMove->value(), row, m_map,
 
  424                 m_focus->m_OpsFocusSettings->focusAdaptiveMinMove, 
"Min Move");
 
  427    processParam(
false, row, m_map, m_focus->m_OpsFocusSettings->focusAdaptStart, 
"Adapt Start Pos");
 
  430    processParam(m_focus->m_OpsFocusSettings->focusAdaptiveMaxMove->value(), row, m_map,
 
  431                 m_focus->m_OpsFocusSettings->focusAdaptiveMaxMove, 
"Max Total Move");
 
  434    addSectionToHelpTable(row, 
i18n(
"Process Parameters"));
 
  437    processParam(
QString(
"SEP"), row, m_map, m_focus->m_OpsFocusProcess->focusDetection, 
"Detection");
 
  440    QString profile = centralObstruction ? FOCUS_DEFAULT_DONUT_NAME : FOCUS_DEFAULT_NAME;
 
  441    processParam(profile, row, m_map, m_focus->m_OpsFocusProcess->focusSEPProfile, 
"SEP Profile");
 
  444    processParam(
QString(
"Linear 1 Pass"), row, m_map, m_focus->m_OpsFocusProcess->focusAlgorithm, 
"Algorithm");
 
  447    processParam(
QString(
"Hyperbola"), row, m_map, m_focus->m_OpsFocusProcess->focusCurveFit, 
"Curve Fit");
 
  450    processParam(
QString(
"HFR"), row, m_map, m_focus->m_OpsFocusProcess->focusStarMeasure, 
"Measure");
 
  453    processParam(
true, row, m_map, m_focus->m_OpsFocusProcess->focusUseWeights, 
"Use Weights");
 
  456    processParam(0.8, row, m_map, m_focus->m_OpsFocusProcess->focusR2Limit, 
"R² Limit");
 
  459    processParam(
true, row, m_map, m_focus->m_OpsFocusProcess->focusRefineCurveFit, 
"Refine Curve Fit");
 
  462    processParam(1, row, m_map, m_focus->m_OpsFocusProcess->focusFramesCount, 
"Average Over");
 
  465    processParam(1, row, m_map, m_focus->m_OpsFocusProcess->focusHFRFramesCount, 
"Average HFR Check");
 
  468    processParam(centralObstruction, row, m_map, m_focus->m_OpsFocusProcess->focusDonut, 
"Donut Buster");
 
  469    processParam(1.0, row, m_map, m_focus->m_OpsFocusProcess->focusTimeDilation, 
"Time Dilation x");
 
  470    processParam(0.2, row, m_map, m_focus->m_OpsFocusProcess->focusOutlierRejection, 
"Outlier Rejection");
 
  473    processParam(
true, row, m_map, m_focus->m_OpsFocusProcess->focusScanStartPos, 
"Scan for Start Position");
 
  474    processParam(
false, row, m_map, m_focus->m_OpsFocusProcess->focusScanAlwaysOn, 
"Always On");
 
  475    processParam(5, row, m_map, m_focus->m_OpsFocusProcess->focusScanDatapoints, 
"Num Datapoints");
 
  476    processParam(1.0, row, m_map, m_focus->m_OpsFocusProcess->focusScanStepSizeFactor, 
"Initial Step Sixe x");
 
  479    addSectionToHelpTable(row, 
i18n(
"Mechanics Parameters"));
 
  482    processParam(
QString(
"Fixed Steps"), row, m_map, m_focus->m_OpsFocusMechanics->focusWalk, 
"Walk");
 
  485    processParam(1.0, row, m_map, m_focus->m_OpsFocusMechanics->focusSettleTime, 
"Focuser Settle");
 
  488    int stepSize = m_focus->m_Focuser && m_focus->m_Focuser->getDeviceName() == FOCUSER_SIMULATOR ? 5000 : 20;
 
  489    processParam(stepSize, row, m_map, m_focus->m_OpsFocusMechanics->focusTicks, 
"Initial Step Size");
 
  492    processParam(11, row, m_map, m_focus->m_OpsFocusMechanics->focusNumSteps, 
"Number Steps");
 
  495    processParam(m_focus->m_OpsFocusMechanics->focusMaxTravel->maximum(), row, m_map,
 
  496                 m_focus->m_OpsFocusMechanics->focusMaxTravel, 
"Max Travel");
 
  499    processParam(m_focus->m_OpsFocusMechanics->focusBacklash->value(), row, m_map, m_focus->m_OpsFocusMechanics->focusBacklash,
 
  503    processParam(m_focus->m_OpsFocusMechanics->focusAFOverscan->value(), row, m_map,
 
  504                 m_focus->m_OpsFocusMechanics->focusAFOverscan, 
"AF Overscan");
 
  507    processParam(0.0, row, m_map, m_focus->m_OpsFocusMechanics->focusOverscanDelay, 
"AF Overscan Delay");
 
  510    processParam(30, row, m_map, m_focus->m_OpsFocusMechanics->focusCaptureTimeout, 
"Capture Timeout");
 
  513    processParam(30, row, m_map, m_focus->m_OpsFocusMechanics->focusMotionTimeout, 
"Motion Timeout");
 
  519QString FocusAdvisor::boolText(
const bool flag)
 
  521    return flag ? 
"On" : 
"Off";
 
  525void FocusAdvisor::setInFocusAdvisor(
bool value)
 
  527    m_inFocusAdvisor = value;
 
  531QString FocusAdvisor::getFocusFramePrefix()
 
  534    if (inFocusAdvisor() && m_inFindStars)
 
  535        prefix = 
"_fs_" + 
QString(
"%1_%2").
arg(m_findStarsRunNum).
arg(m_focus->absIterations + 1);
 
  536    else if (inFocusAdvisor() && m_inPreAFAdj)
 
  537        prefix = 
"_ca_" + 
QString(
"%1_%2").
arg(m_preAFRunNum).
arg(m_focus->absIterations + 1);
 
  538    else if (inFocusAdvisor() && m_focus->inScanStartPos)
 
  539        prefix = 
"_ssp_" + 
QString(
"%1_%2").
arg(m_focus->m_AFRun).
arg(m_focus->absIterations + 1);
 
  544QVariantMap FocusAdvisor::getOTDefaults(
const QString &OTName)
 
  552    for (
auto &tName : OpticalTrainManager::Instance()->getTrainNames())
 
  556        auto tFocuser = OpticalTrainManager::Instance()->getFocuser(tName);
 
  557        if (tFocuser != m_focus->m_Focuser)
 
  559        auto tScope = OpticalTrainManager::Instance()->getScope(tName);
 
  560        auto tScopeType = tScope[
"type"].toString();
 
  561        if (tScopeType != m_focus->m_ScopeType)
 
  565        auto tID = OpticalTrainManager::Instance()->id(tName);
 
  566        OpticalTrainSettings::Instance()->setOpticalTrainID(tID);
 
  567        auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Focus);
 
  568        if (settings.isValid())
 
  571            map = settings.toJsonObject().toVariantMap();
 
  574            auto tAperture = tScope[
"aperture"].toDouble(-1);
 
  575            auto tFocalLength = tScope[
"focal_length"].toDouble(-1);
 
  576            auto tFocalRatio = tScope[
"focal_ratio"].toDouble(-1);
 
  577            auto tReducer = OpticalTrainManager::Instance()->getReducer(tName);
 
  578            if (tFocalLength > 0.0)
 
  579                tFocalLength *= tReducer;
 
  582            if (tFocalRatio <= 0.0)
 
  584                tFocalRatio = (tAperture > 0.001) ? tFocalLength / tAperture : 0.0f;
 
  590            if (m_focus->m_Focuser && m_focus->m_Focuser->getDeviceName() == FOCUSER_SIMULATOR)
 
  594                stepSize = 
map.value(
"focusTicks", stepSize).toInt() * pow(m_focus->m_FocalRatio, 2.0) / pow(tFocalRatio, 2.0);
 
  596            map.insert(
"focusTicks", stepSize);
 
  601    auto id = OpticalTrainManager::Instance()->id(OTName);
 
  602    OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
 
  610bool FocusAdvisor::scopeHasObstruction(
const QString &scopeType)
 
  612    return (scopeType != 
"Refractor" && scopeType != 
"Kutter (Schiefspiegler)");
 
  616void FocusAdvisor::initControl()
 
  618    setInFocusAdvisor(
true);
 
  620    m_initialStepSize = m_focus->m_OpsFocusMechanics->focusTicks->value();
 
  621    m_initialBacklash = m_focus->m_OpsFocusMechanics->focusBacklash->value();
 
  622    m_initialAFOverscan = m_focus->m_OpsFocusMechanics->focusAFOverscan->value();
 
  623    m_initialUseWeights = m_focus->m_OpsFocusProcess->focusUseWeights->isChecked();
 
  626        initFindStars(m_focus->currentPosition);
 
  627    else if (m_inPreAFAdj)
 
  628        initPreAFAdj(m_focus->currentPosition);
 
  630        initAFAdj(m_focus->currentPosition, 
false);
 
  634void FocusAdvisor::control()
 
  636    if (!inFocusAdvisor())
 
  641    else if (m_inPreAFAdj)
 
  644        abort(
i18n(
"Focus Advisor aborted due to internal error"));
 
  648void FocusAdvisor::initFindStars(
const int startPos)
 
  651    if (!canFocusAdvisorRun())
 
  653        abort(
i18n(
"Focus Advisor cannot run with current params"));
 
  657    focusAdvFindStarsLabel->setText(
i18n(
"In progress..."));
 
  658    emit newStage(FindingStars);
 
  661    m_focus->initialFocuserAbsPosition = startPos;
 
  662    m_focus->linearRequestedPosition = startPos;
 
  665    m_focus->m_OpsFocusProcess->focusUseWeights->setChecked(
false);
 
  667    m_focus->absIterations = 0;
 
  670    m_focus->clearDataPoints();
 
  671    m_jumpsToGo = NUM_JUMPS_PER_SECTOR;
 
  672    m_jumpSize = m_focus->m_OpsFocusMechanics->focusTicks->value() * NUM_JUMPS_PER_SECTOR;
 
  673    m_findStarsIn = 
false;
 
  674    m_findStarsMaxBound = m_findStarsMinBound = 
false;
 
  675    m_findStarsSector = 0;
 
  676    m_findStarsRange = 
false;
 
  677    m_findStarsRangeIn = 
false;
 
  678    m_findStarsFindInEdge = 
false;
 
  679    m_findStarsInRange = -1;
 
  680    m_findStarsOutRange = -1;
 
  684    m_focus->m_OpsFocusMechanics->focusBacklash->setValue(0);
 
  685    m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(0);
 
  687    addResultsTable(
i18n(
"Find Stars"), m_findStarsRunNum, startPos, m_jumpSize,
 
  688                    m_focus->m_OpsFocusMechanics->focusAFOverscan->value(), 
"");
 
  689    emit m_focus->setTitle(
QString(
i18n(
"Find Stars: Scanning for stars...")), 
true);
 
  690    if (!m_focus->changeFocus(startPos - m_focus->currentPosition))
 
  691        abort(
i18n(
"Find Stars: Failed"));
 
  698void FocusAdvisor::findStars()
 
  701    emit m_focus->newHFRPlotPosition(
static_cast<double>(m_focus->currentPosition), m_focus->currentMeasure,
 
  702                                     std::pow(m_focus->currentWeight, -0.5), 
false, m_jumpSize, 
true);
 
  705    bool starsExist = starsFound();
 
  706    if (m_findStarsRange)
 
  708        bool outOfRange = 
false;
 
  712            if (m_findStarsRangeIn)
 
  713                outOfRange = (m_focus->currentPosition - m_jumpSize) < 
static_cast<int>(m_focus->absMotionMin);
 
  715                outOfRange = (m_focus->currentPosition + m_jumpSize) > 
static_cast<int>(m_focus->absMotionMax);
 
  718        if (m_findStarsFindInEdge)
 
  723                m_findStarsFindInEdge = 
false;
 
  724                m_findStarsInRange = m_focus->currentPosition - m_jumpSize;
 
  727        else if (!starsExist && m_findStarsInRange < 0 && m_findStarsOutRange < 0)
 
  731            if (m_findStarsRangeIn)
 
  733                m_findStarsInRange = m_focus->currentPosition;
 
  734                auto max = std::max_element(std::begin(m_position), std::end(m_position));
 
  735                offset = *max - m_focus->currentPosition;
 
  739                m_findStarsOutRange = m_focus->currentPosition;
 
  740                auto min = std::min_element(std::begin(m_position), std::end(m_position));
 
  741                offset = *min - m_focus->currentPosition;
 
  743            m_findStarsRangeIn = !m_findStarsRangeIn;
 
  745        else if (!starsExist || outOfRange)
 
  749            m_inFindStars = 
false;
 
  750            if (m_findStarsRangeIn)
 
  752                m_findStarsInRange = m_focus->currentPosition;
 
  755                m_findStarsOutRange = m_focus->currentPosition;
 
  756            const int zoneCentre = (m_findStarsInRange + m_findStarsOutRange) / 2;
 
  757            focusAdvFindStarsLabel->setText(
i18n(
"Done"));
 
  761                initPreAFAdj(zoneCentre);
 
  763                initAFAdj(zoneCentre, 
true);
 
  766                m_focus->absTicksSpin->setValue(zoneCentre);
 
  767                emit m_focus->setTitle(
QString(
i18n(
"Stars detected, range centre %1", zoneCentre)), 
true);
 
  768                complete(
false, 
i18n(
"Focus Advisor Find Stars completed"));
 
  775    m_position.push_back(m_focus->currentPosition);
 
  776    m_measure.push_back(m_focus->currentMeasure);
 
  783        if (!m_findStarsRange)
 
  785            m_findStarsRange = 
true;
 
  789            if (m_position.size() > 1)
 
  791                if (m_position.last() < m_position[m_position.size() - 2])
 
  795                    std::sort(positionsCopy.
begin(), positionsCopy.
end(), std::greater<int>());
 
  796                    m_findStarsOutRange = positionsCopy[1];
 
  797                    m_findStarsOutRange = m_position[m_position.size() - 2];
 
  798                    m_findStarsRangeIn = 
true;
 
  804                    m_findStarsFindInEdge = 
true;
 
  806                    std::sort(positionsCopy.
begin(), positionsCopy.
end(), std::greater<int>());
 
  807                    offset = positionsCopy[1] - m_focus->currentPosition;
 
  814    if (++m_focus->absIterations > MAXIMUM_FOCUS_ADVISOR_ITERATIONS)
 
  816        abort(
i18n(
"Find Stars: exceeded max iterations %1", MAXIMUM_FOCUS_ADVISOR_ITERATIONS));
 
  821    if (m_findStarsRange)
 
  824        emit m_focus->setTitle(
QString(
i18n(
"Stars detected, centering range")), 
true);
 
  825        updateResultsTable(
i18n(
"Stars detected, centering range"));
 
  827        if (m_findStarsRangeIn)
 
  828            nextPos = std::max(m_focus->currentPosition + offset - m_jumpSize, 
static_cast<int>(m_focus->absMotionMin));
 
  830            nextPos = std::min(m_focus->currentPosition + offset + m_jumpSize, 
static_cast<int>(m_focus->absMotionMax));
 
  831        deltaPos = nextPos - m_focus->currentPosition;
 
  833    else if (m_position.size() == 1)
 
  836        deltaPos = m_jumpSize * m_jumpsToGo;
 
  838        if (m_focus->currentPosition + deltaPos >= m_focus->absMotionMax)
 
  840            deltaPos = m_focus->absMotionMax - m_focus->currentPosition;
 
  841            m_jumpsToGo = deltaPos / m_jumpSize + (deltaPos % m_jumpSize != 0);
 
  842            m_findStarsMaxBound = 
true;
 
  844        m_findStarsJumpsInSector = m_jumpsToGo;
 
  845        m_findStarsSector = 1;
 
  846        emit m_focus->setTitle(
QString(
i18n(
"Find Stars Run %1: No stars at start %2, scanning...", m_findStarsRunNum,
 
  847                                            m_focus->currentPosition)), 
true);
 
  849    else if (m_jumpsToGo > 0)
 
  852        emit m_focus->setTitle(
QString(
i18n(
"Find Stars Run %1 Sector %2: Scanning %3/%4", m_findStarsRunNum, m_findStarsSector,
 
  853                                            m_jumpsToGo, m_findStarsJumpsInSector)), 
true);
 
  854        updateResultsTable(
i18n(
"Find Stars Run %1: Scanning Sector %2", m_findStarsRunNum, m_findStarsSector));
 
  855        int nextPos = std::max(m_focus->currentPosition - m_jumpSize, 
static_cast<int>(m_focus->absMotionMin));
 
  856        deltaPos = nextPos - m_focus->currentPosition;
 
  861        if(m_findStarsMaxBound && m_findStarsMinBound)
 
  865            updateResultsTable(
i18n(
"No stars detected"));
 
  866            int newStepSize = m_focus->m_OpsFocusMechanics->focusTicks->value() / 2;
 
  869                m_focus->m_OpsFocusMechanics->focusTicks->setValue(newStepSize);
 
  870                initFindStars(m_focus->initialFocuserAbsPosition);
 
  873                abort(
i18n(
"Find Stars Run %1: failed to find any stars", m_findStarsRunNum));
 
  878        m_jumpsToGo = NUM_JUMPS_PER_SECTOR;
 
  882            if (m_findStarsMaxBound)
 
  885                if (m_focus->currentPosition - m_jumpSize < 
static_cast<int>(m_focus->absMotionMin))
 
  886                    deltaPos = 
static_cast<int>(m_focus->absMotionMin) - m_focus->currentPosition;
 
  888                    deltaPos = -m_jumpSize;
 
  892                auto max = std::max_element(std::begin(m_position), std::end(m_position));
 
  893                int sweepMax = *max + (m_jumpSize * m_jumpsToGo);
 
  894                if (sweepMax >= 
static_cast<int>(m_focus->absMotionMax))
 
  896                    sweepMax = 
static_cast<int>(m_focus->absMotionMax);
 
  897                    m_jumpsToGo = (sweepMax - *max) / m_jumpSize + ((sweepMax - *max) % m_jumpSize != 0);
 
  898                    m_findStarsMaxBound = 
true;
 
  900                m_findStarsIn = 
false;
 
  901                deltaPos = sweepMax - m_focus->currentPosition;
 
  907            if (m_findStarsMinBound)
 
  909                auto max = std::max_element(std::begin(m_position), std::end(m_position));
 
  910                int sweepMax = *max + (m_jumpSize * m_jumpsToGo);
 
  911                if (sweepMax >= 
static_cast<int>(m_focus->absMotionMax))
 
  913                    sweepMax = 
static_cast<int>(m_focus->absMotionMax);
 
  914                    m_jumpsToGo = (sweepMax - *max) / m_jumpSize + ((sweepMax - *max) % m_jumpSize != 0);
 
  915                    m_findStarsMaxBound = 
true;
 
  917                deltaPos = sweepMax - m_focus->currentPosition;
 
  921                auto min = std::min_element(std::begin(m_position), std::end(m_position));
 
  922                int sweepMin = *min - (m_jumpSize * m_jumpsToGo);
 
  923                if (sweepMin <= 
static_cast<int>(m_focus->absMotionMin))
 
  926                    m_findStarsMinBound = 
true;
 
  927                    sweepMin = 
static_cast<int>(m_focus->absMotionMin);
 
  928                    m_jumpsToGo = (*min - sweepMin) / m_jumpSize + ((*min - sweepMin) % m_jumpSize != 0);
 
  931                m_findStarsIn = 
true;
 
  932                int nextJumpPos = std::max(*min - m_jumpSize, 
static_cast<int>(m_focus->absMotionMin));
 
  933                deltaPos = nextJumpPos - m_focus->currentPosition;
 
  937        m_findStarsJumpsInSector = m_jumpsToGo;
 
  938        emit m_focus->setTitle(
QString(
i18n(
"Find Stars Run %1 Sector %2: scanning %3/%4", m_findStarsRunNum, m_findStarsSector,
 
  939                                            m_jumpsToGo, m_findStarsJumpsInSector)), 
true);
 
  941    if (!m_findStarsRange)
 
  943    m_focus->linearRequestedPosition = m_focus->currentPosition + deltaPos;
 
  944    if (!m_focus->changeFocus(deltaPos))
 
  945        abort(
i18n(
"Focus Advisor Find Stars run %1: failed to move focuser", m_findStarsRunNum));
 
  948bool FocusAdvisor::starsFound()
 
  950    return (m_focus->currentMeasure != INVALID_STAR_MEASURE && m_focus->currentNumStars > FIND_STARS_MIN_STARS);
 
  955void FocusAdvisor::initPreAFAdj(
const int startPos)
 
  958    if (!canFocusAdvisorRun())
 
  960        abort(
i18n(
"Focus Advisor cannot run with current params"));
 
  965    if (m_preAFRunNum > 50)
 
  967        abort(
i18n(
"Focus Advisor Coarse Adjustment aborted after %1 runs", m_preAFRunNum));
 
  971    focusAdvCoarseAdjLabel->setText(
i18n(
"In progress..."));
 
  972    emit newStage(CoarseAdjustments);
 
  974    m_focus->initialFocuserAbsPosition = startPos;
 
  975    m_focus->absIterations = 0;
 
  979    m_preAFNoStarsOut = m_preAFNoStarsIn = 
false;
 
  983    m_focus->clearDataPoints();
 
  984    emit m_focus->setTitle(
QString(
i18n(
"Coarse Adjustment Scan...")), 
true);
 
  987    m_jumpSize = m_focus->m_OpsFocusMechanics->focusTicks->value() * NUM_STEPS_PRE_AF;
 
  990    if (m_jumpSize > m_focus->absMotionMax - m_focus->absMotionMin)
 
  992        m_jumpSize = m_focus->absMotionMax - m_focus->absMotionMin;
 
  993        m_focus->m_OpsFocusMechanics->focusTicks->setValue(m_jumpSize / NUM_STEPS_PRE_AF);
 
  996    int deltaPos = (startPos - m_focus->currentPosition) + m_jumpSize / 2;
 
  997    if (m_focus->currentPosition + deltaPos > maxStarsLimit())
 
  998        deltaPos = maxStarsLimit() - m_focus->currentPosition;
 
 1000    m_preAFInner = startPos - m_jumpSize / 2;
 
 1001    if (m_preAFInner < minStarsLimit())
 
 1002        m_preAFInner = minStarsLimit();
 
 1005    if (m_preAFRunNum == 1)
 
 1007        m_focus->m_OpsFocusMechanics->focusBacklash->setValue(0);
 
 1008        m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(0);
 
 1009        m_focus->m_OpsFocusProcess->focusUseWeights->setChecked(m_initialUseWeights);
 
 1012    addResultsTable(
i18n(
"Coarse Adjustment"), m_preAFRunNum, startPos,
 
 1013                    m_focus->m_OpsFocusMechanics->focusTicks->value(),
 
 1014                    m_focus->m_OpsFocusMechanics->focusAFOverscan->value(), 
"");
 
 1016    m_focus->linearRequestedPosition = m_focus->currentPosition + deltaPos;
 
 1017    if (!m_focus->changeFocus(deltaPos))
 
 1018        abort(
i18n(
"Focus Advisor Coarse Adjustment failed to move focuser"));
 
 1023void FocusAdvisor::preAFAdj()
 
 1026    if (++m_focus->absIterations > MAXIMUM_FOCUS_ADVISOR_ITERATIONS)
 
 1028        abort(
i18n(
"Focus Advisor Coarse Adjustment: exceeded max iterations %1", MAXIMUM_FOCUS_ADVISOR_ITERATIONS));
 
 1033    const int step = m_focus->m_OpsFocusMechanics->focusTicks->value();
 
 1035    bool starsExist = starsFound();
 
 1039        m_position.push_back(m_focus->currentPosition);
 
 1040        m_measure.push_back(m_focus->currentMeasure);
 
 1042        if (m_preAFNoStarsOut && (m_position.size() == 0))
 
 1044            if (m_findStarsOutRange < 0)
 
 1045                m_findStarsOutRange = m_focus->currentPosition;
 
 1047                m_findStarsOutRange = std::max(m_findStarsOutRange, m_focus->currentPosition);
 
 1053        if (m_position.size() < 2)
 
 1054            m_preAFNoStarsOut = 
true;
 
 1055        else if (m_focus->currentPosition - (2 * step) <= m_preAFInner)
 
 1057            m_preAFNoStarsIn = 
true;
 
 1058            if (m_findStarsInRange < 0)
 
 1059                m_findStarsInRange = m_position.last();
 
 1061                m_findStarsInRange = std::min(m_findStarsInRange, m_position.last());
 
 1065    emit m_focus->newHFRPlotPosition(
static_cast<double>(m_focus->currentPosition), m_focus->currentMeasure,
 
 1066                                     std::pow(m_focus->currentWeight, -0.5), 
false, step, 
true);
 
 1069    if (m_focus->currentPosition - step < m_preAFInner && starsExist)
 
 1072        auto it = std::min_element(std::begin(m_measure), std::end(m_measure));
 
 1073        auto min = std::distance(std::begin(m_measure), it);
 
 1074        if (m_position.size() < 5 || (m_position.size() < 2 * NUM_STEPS_PRE_AF && m_position.size() - min < 3))
 
 1077            if (m_preAFInner - step >= minStarsLimit())
 
 1078                m_preAFInner -= step;
 
 1082    if (m_focus->currentPosition - step >= m_preAFInner)
 
 1085        emit m_focus->setTitle(
QString(
i18n(
"Coarse Adjustment Run %1 scan...", m_preAFRunNum)), 
true);
 
 1091        if (m_position.size() < 5)
 
 1093            abort(
i18n(
"Focus Advisor Coarse Adjustment Run %1: insufficient data to proceed", m_preAFRunNum));
 
 1098            auto it = std::min_element(std::begin(m_measure), std::end(m_measure));
 
 1099            auto min = std::distance(std::begin(m_measure), it);
 
 1100            const double minMeasure = *it;
 
 1101            int minPos = m_position[min];
 
 1103            auto it2 = std::max_element(std::begin(m_measure), std::end(m_measure));
 
 1104            const double maxMeasure = *it2;
 
 1106            const double scaling = 
static_cast<double>(NUM_STEPS_PRE_AF) / 
static_cast<double>(m_measure.count());
 
 1107            const double measureRatio = maxMeasure / minMeasure * scaling;
 
 1110            double whereInRange = 
static_cast<double>(minPos - m_position.last()) / 
static_cast<double> 
 1111                                  (m_position.first() - m_position.last());
 
 1112            bool nearCenter = whereInRange > 0.3 && whereInRange < 0.7;
 
 1115            for (
int i = 0; i < m_position.size() - 1; i++)
 
 1117                double gradient = (m_measure[i] - m_measure[i + 1]) / (m_position[i] - m_position[i + 1]);
 
 1118                gradients.
push_back(std::abs(gradient));
 
 1124            std::sort(gradientsCopy.
begin(), gradientsCopy.
end(), std::greater<double>());
 
 1125            std::vector<double> gradientsMax;
 
 1126            for (
int i = 0; i < 3; i++)
 
 1127                gradientsMax.push_back(gradientsCopy[i]);
 
 1129            double gradientsMean = Mathematics::RobustStatistics::ComputeLocation(Mathematics::RobustStatistics::LOCATION_MEAN,
 
 1132            const double threshold = gradientsMean * 0.5;
 
 1133            int overscan = m_focus->m_OpsFocusMechanics->focusAFOverscan->value();
 
 1134            for (
int i = 0; i < gradients.
size(); i++)
 
 1136                if (gradients[i] <= threshold)
 
 1137                    overscan += m_position[i] - m_position[i + 1];
 
 1141            overscan = std::max(overscan, step);
 
 1142            m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(overscan);
 
 1144            const bool hitNoStarsRegion = m_preAFNoStarsIn || m_preAFNoStarsOut;
 
 1147            if (nearCenter && maxMinRatioOK(INITIAL_MAXMIN_HFR_RATIO, measureRatio) && !hitNoStarsRegion)
 
 1151                m_inPreAFAdj = 
false;
 
 1152                focusAdvCoarseAdjLabel->setText(
i18n(
"Done"));
 
 1153                m_focus->absIterations = 0;
 
 1159                    m_focus->clearDataPoints();
 
 1162                    initAFAdj(minPos, 
true);
 
 1166                    m_focus->absTicksSpin->setValue(minPos);
 
 1167                    complete(
false, 
i18n(
"Focus Advisor Coarse Adjustment completed."));
 
 1175                const double expansion = TARGET_MAXMIN_HFR_RATIO / measureRatio;
 
 1176                int newStepSize = m_focus->m_OpsFocusMechanics->focusTicks->value() * expansion;
 
 1178                if (m_preAFNoStarsIn && m_preAFNoStarsOut)
 
 1181                    const int range = m_position.first() - m_position.last();
 
 1182                    newStepSize = range / NUM_STEPS_PRE_AF;
 
 1183                    startPosition = (m_position.first() + m_position.last()) / 2;
 
 1184                    m_preAFMaxRange = 
true;
 
 1185                    if (newStepSize < 1)
 
 1188                        abort(
i18n(
"Focus Advisor Coarse Adjustment: data quality too poor to continue"));
 
 1192                else if (m_preAFNoStarsIn)
 
 1195                    int range = NUM_STEPS_PRE_AF * newStepSize;
 
 1196                    int jumpPosition = m_position.last() + range;
 
 1197                    if (jumpPosition > maxStarsLimit())
 
 1199                        range = maxStarsLimit() - m_position.last();
 
 1200                        newStepSize = range / NUM_STEPS_PRE_AF;
 
 1201                        m_preAFMaxRange = 
true;
 
 1203                    startPosition = m_position.last() + (range / 2);
 
 1205                else if (m_preAFNoStarsOut)
 
 1208                    int range = NUM_STEPS_PRE_AF * newStepSize;
 
 1209                    int endPosition = m_position.first() - range;
 
 1210                    if (endPosition < minStarsLimit())
 
 1212                        range = m_position.first() - minStarsLimit();
 
 1213                        newStepSize = range / NUM_STEPS_PRE_AF;
 
 1214                        m_preAFMaxRange = 
true;
 
 1216                    startPosition = m_position.first() - (range / 2);
 
 1220                    startPosition = minPos;
 
 1222                updateResultsTable(
i18n(
"Max/Min Ratio: %1, Next Step Size: %2, Next Overscan: %3", 
QString::number(measureRatio, 
'f', 1),
 
 1224                m_focus->m_OpsFocusMechanics->focusTicks->setValue(newStepSize);
 
 1225                initPreAFAdj(startPosition);
 
 1230    m_focus->linearRequestedPosition = m_focus->currentPosition + deltaPos;
 
 1231    if (!m_focus->changeFocus(deltaPos))
 
 1232        abort(
i18n(
"Focus Advisor Coarse Adjustment failed to move focuser"));
 
 1236bool FocusAdvisor::maxMinRatioOK(
const double limit, 
const double maxMinRatio)
 
 1238    if (m_preAFMaxRange)
 
 1241    return maxMinRatio >= limit;
 
 1245int FocusAdvisor::minStarsLimit()
 
 1247    return std::max(
static_cast<int>(m_focus->absMotionMin), m_findStarsInRange);
 
 1251int FocusAdvisor::maxStarsLimit()
 
 1253    if (m_findStarsOutRange < 0)
 
 1254        return m_focus->absMotionMax;
 
 1256        return std::min(
static_cast<int>(m_focus->absMotionMax), m_findStarsOutRange);
 
 1259void FocusAdvisor::initAFAdj(
const int startPos, 
const bool retryOverscan)
 
 1262    if (!canFocusAdvisorRun())
 
 1264        abort(
i18n(
"Focus Advisor cannot run with current params"));
 
 1268    focusAdvFineAdjLabel->setText(
i18n(
"In progress..."));
 
 1269    emit newStage(FineAdjustments);
 
 1275        const int newOverscan = m_focus->m_OpsFocusMechanics->focusAFOverscan->value() / 2;
 
 1276        m_focus->m_OpsFocusMechanics->focusBacklash->setValue(0);
 
 1277        m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(newOverscan);
 
 1281    m_focus->m_OpsFocusProcess->focusUseWeights->setChecked(m_initialUseWeights);
 
 1283    addResultsTable(
i18n(
"Fine Adjustment"), ++m_AFRunCount, startPos,
 
 1284                    m_focus->m_OpsFocusMechanics->focusTicks->value(),
 
 1285                    m_focus->m_OpsFocusMechanics->focusAFOverscan->value(), 
"");
 
 1290void FocusAdvisor::startAF(
const int startPos)
 
 1294        setInFocusAdvisor(
false);
 
 1295        m_focus->absIterations = 0;
 
 1296        m_focus->setupLinearFocuser(startPos);
 
 1297        if (!m_focus->changeFocus(m_focus->linearRequestedPosition - m_focus->currentPosition))
 
 1298            m_focus->completeFocusProcedure(Ekos::FOCUS_ABORTED, Ekos::FOCUS_FAIL_FOCUSER_NO_MOVE);
 
 1303        m_focus->initScanStartPos(
true, startPos);
 
 1307bool FocusAdvisor::analyseAF()
 
 1309    if (m_focus->m_FocusAlgorithm != Focus::FOCUS_LINEAR1PASS || !m_focus->linearFocuser || !m_focus->linearFocuser->isDone()
 
 1310            || m_focus->linearFocuser->solution() == -1)
 
 1313    bool runAgainRatio = 
false;
 
 1317    m_focus->linearFocuser->getPass1Measurements(&positions, &measures, &weights, &outliers);
 
 1319    int minPosition = m_focus->linearFocuser->solution();
 
 1320    double minMeasure = m_focus->linearFocuser->solutionValue();
 
 1322    int maxPositon = positions[0];
 
 1323    double maxMeasure = m_focus->curveFitting->f(maxPositon);
 
 1325    const int stepSize = m_focus->m_OpsFocusMechanics->focusTicks->value();
 
 1326    int newStepSize = stepSize;
 
 1328    double measureRatio = maxMeasure / minMeasure;
 
 1329    if (measureRatio > 2.5 && measureRatio < 3.5)
 
 1331        runAgainRatio = 
false;
 
 1334        runAgainRatio = 
true;
 
 1336        int pos = m_focus->curveFitting->fy(minMeasure * TARGET_MAXMIN_HFR_RATIO);
 
 1337        newStepSize = (pos - minPosition) / ((positions.
size() - 1.0) / 2.0);
 
 1341        double ratio = 
static_cast<double>(newStepSize) / 
static_cast<double>(stepSize);
 
 1342        ratio = std::max(std::min(ratio, 2.0), 0.5);
 
 1343        newStepSize = stepSize * ratio;
 
 1344        m_focus->m_OpsFocusMechanics->focusTicks->setValue(newStepSize);
 
 1349    if (!m_overscanFound)
 
 1351        double backlashPoints = 0.0;
 
 1352        for (
int i = 0; i < positions.
size() / 2; i++)
 
 1354            double deltaAct = measures[i] - measures[i + 1];
 
 1355            double deltaExp = m_focus->curveFitting->f(positions[i]) - m_focus->curveFitting->f(positions[i + 1]);
 
 1356            double delta = std::abs(deltaAct / deltaExp);
 
 1361                backlashPoints += 0.5;
 
 1366        const int overscan = m_focus->m_OpsFocusMechanics->focusAFOverscan->value();
 
 1367        int newOverscan = overscan;
 
 1369        if (backlashPoints > 0.0)
 
 1372            newOverscan = overscan + (stepSize * backlashPoints);
 
 1373            m_overscanFound = 
true;
 
 1375        else if (overscan == 0)
 
 1376            m_overscanFound = 
true;
 
 1377        else if (!m_overscanFound)
 
 1379            newOverscan = overscan <= 2 * stepSize ? 0 : overscan / 2;
 
 1381        m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(newOverscan);
 
 1386        m_runAgainR2 = 
false;
 
 1388        m_runAgainR2 = m_focus->R2 < m_focus->m_OpsFocusProcess->focusR2Limit->value();
 
 1389    bool runAgain = runAgainRatio || m_runAgainR2 || !m_overscanFound;
 
 1391    updateResultsTable(
i18n(
"Max/Min Ratio: %1, R2: %2, Step Size: %3, Overscan: %4", 
QString::number(measureRatio, 
'f', 1),
 
 1393                            QString::number(m_focus->m_OpsFocusMechanics->focusAFOverscan->value())));
 
 1397        focusAdvFineAdjLabel->setText(
i18n(
"Done"));
 
 1398        complete(
true, 
i18n(
"Focus Advisor Fine Adjustment completed"));
 
 1399        emit newStage(Idle);
 
 1405void FocusAdvisor::reset()
 
 1407    m_inFocusAdvisor = 
false;
 
 1408    m_initialStepSize = -1;
 
 1409    m_initialBacklash = -1;
 
 1410    m_initialAFOverscan = -1;
 
 1411    m_initialUseWeights = 
false;
 
 1412    m_initialScanStartPos = 
false;
 
 1415    m_inFindStars = 
false;
 
 1416    m_inPreAFAdj = 
false;
 
 1420    m_findStarsIn = 
false;
 
 1421    m_findStarsMaxBound = 
false;
 
 1422    m_findStarsMinBound = 
false;
 
 1423    m_findStarsSector = 0;
 
 1424    m_findStarsRunNum = 0;
 
 1425    m_findStarsRange = 
false;
 
 1426    m_findStarsRangeIn = 
false;
 
 1427    m_findStarsFindInEdge = 
false;
 
 1428    m_findStarsInRange = -1;
 
 1429    m_findStarsOutRange = -1;
 
 1431    m_preAFNoStarsOut = 
false;
 
 1432    m_preAFNoStarsIn = 
false;
 
 1433    m_preAFMaxRange = 
false;
 
 1435    m_overscanFound = 
false;
 
 1436    m_runAgainR2 = 
false;
 
 1437    m_nearFocus = 
false;
 
 1440    focusAdvUpdateParamsLabel->setText(
"");
 
 1441    focusAdvFindStarsLabel->setText(
"");
 
 1442    focusAdvCoarseAdjLabel->setText(
"");
 
 1443    focusAdvFineAdjLabel->setText(
"");
 
 1447void FocusAdvisor::abort(
const QString &msg)
 
 1449    m_focus->appendLogText(msg);
 
 1452    resetSavedSettings(
false);
 
 1453    m_focus->processAbort();
 
 1458void FocusAdvisor::complete(
const bool autofocus, 
const QString &msg)
 
 1460    m_focus->appendLogText(msg);
 
 1462    resetSavedSettings(
true);
 
 1466        if (m_initialBacklash > -1) m_focus->m_OpsFocusMechanics->focusBacklash->setValue(m_initialBacklash);
 
 1467        if (m_initialAFOverscan > -1) m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(m_initialAFOverscan);
 
 1468        m_focus->completeFocusProcedure(Ekos::FOCUS_IDLE, Ekos::FOCUS_FAIL_ADVISOR_COMPLETE);
 
 1472void FocusAdvisor::resetSavedSettings(
const bool success)
 
 1474    m_focus->m_OpsFocusProcess->focusUseWeights->setChecked(m_initialUseWeights);
 
 1475    m_focus->m_OpsFocusProcess->focusScanStartPos->setChecked(m_initialScanStartPos);
 
 1480        if (m_initialStepSize > -1) m_focus->m_OpsFocusMechanics->focusTicks->setValue(m_initialStepSize);
 
 1481        if (m_initialBacklash > -1) m_focus->m_OpsFocusMechanics->focusBacklash->setValue(m_initialBacklash);
 
 1482        if (m_initialAFOverscan > -1) m_focus->m_OpsFocusMechanics->focusAFOverscan->setValue(m_initialAFOverscan);
 
 1487void FocusAdvisor::addResultsTable(
QString section, 
int run, 
int startPos, 
int stepSize, 
int overscan, 
QString text)
 
 1489    m_focus->appendLogText(
i18n(
"Focus Advisor Result (%1): Run: %2 startPos: %3 stepSize: %4 overscan: %5",
 
 1490                                section, run, startPos, stepSize, overscan));
 
 1492    focusAdvTable->insertRow(0);
 
 1494    focusAdvTable->setItem(0, RESULTS_SECTION, itemSection);
 
 1498    focusAdvTable->setItem(0, RESULTS_RUN_NUMBER, itemRunNumber);
 
 1502    focusAdvTable->setItem(0, RESULTS_START_POSITION, itemStartPos);
 
 1506    focusAdvTable->setItem(0, RESULTS_STEP_SIZE, itemStepSize);
 
 1510    focusAdvTable->setItem(0, RESULTS_AFOVERSCAN, itemAFOverscan);
 
 1512    focusAdvTable->setItem(0, RESULTS_TEXT, itemText);
 
 1514    emit newMessage(text);
 
 1516    if (focusAdvTable->rowCount() == 1)
 
 1518        focusAdvTable->show();
 
 1524void FocusAdvisor::updateResultsTable(
QString text)
 
 1526    m_focus->appendLogText(
i18n(
"Focus Advisor Result Update: %1", text));
 
 1529    focusAdvTable->setItem(0, RESULTS_TEXT, itemText);
 
 1533void FocusAdvisor::resizeDialog()
 
 1537    this->verticalLayout->layout()->getContentsMargins(&left, &top, &right, &bottom);
 
 1540    for (
int i = 0; i < focusAdvTable->horizontalHeader()->count(); i++)
 
 1541        width += focusAdvTable->columnWidth(i);
 
 1542    const int height = focusAdvGroupBox->height() + focusAdvTable->height() + focusAdvButtonBox->height();
 
 1543    this->resize(width, height);
 
QString i18n(const char *text, const TYPE &arg...)
 
Ekos is an advanced Astrophotography tool for Linux.
 
void stateChanged(int state)
 
int pointSize() const const
 
void setBold(bool enable)
 
void setPointSize(int pointSize)
 
void setUnderline(bool enable)
 
void push_back(parameter_type value)
 
qsizetype size() const const
 
QString arg(Args &&... args) const const
 
bool isEmpty() const const
 
QString number(double n, char format, int precision)
 
QTextStream & left(QTextStream &stream)
 
QTextStream & right(QTextStream &stream)
 
void setText(const QString &text)
 
void setTextAlignment(Qt::Alignment alignment)
 
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
 
QFuture< T > run(Function function,...)
 
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)