git: afae6c72d90c - main - astro/kstars: fix build against newer stellarsolver

From: Adriaan de Groot <adridg_at_FreeBSD.org>
Date: Fri, 11 Mar 2022 21:23:53 UTC
The branch main has been updated by adridg:

URL: https://cgit.FreeBSD.org/ports/commit/?id=afae6c72d90cf4a923d10973bc8f0a472537d628

commit afae6c72d90cf4a923d10973bc8f0a472537d628
Author:     Adriaan de Groot <adridg@FreeBSD.org>
AuthorDate: 2022-03-11 21:17:13 +0000
Commit:     Adriaan de Groot <adridg@FreeBSD.org>
CommitDate: 2022-03-11 21:23:51 +0000

    astro/kstars: fix build against newer stellarsolver
    
    Patch obtained from upstream KStars 3.5.7 branch.
---
 astro/kstars/Makefile                              |    4 +-
 .../bef3940aaceb1ba574687a4817ef829a04d49dd4.patch | 1237 ++++++++++++++++++++
 2 files changed, 1240 insertions(+), 1 deletion(-)

diff --git a/astro/kstars/Makefile b/astro/kstars/Makefile
index c2911763e2a8..464d2fbfb73c 100644
--- a/astro/kstars/Makefile
+++ b/astro/kstars/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	kstars
 DISTVERSION=	3.5.7
-PORTREVISION=	2
+PORTREVISION=	3
 PORTEPOCH=	1
 CATEGORIES=	astro kde
 MASTER_SITES=	KDE/stable/${PORTNAME}
@@ -10,6 +10,8 @@ COMMENT=	KDE desktop planetarium
 
 LICENSE=	GPLv2
 
+EXTRA_PATCHES=	${PATCHDIR}/bef3940aaceb1ba574687a4817ef829a04d49dd4.patch:-p1
+
 LIB_DEPENDS=	libcfitsio.so:astro/cfitsio \
 		libindidriver.so:devel/indi \
 		libqt5keychain.so:security/qtkeychain \
diff --git a/astro/kstars/files/bef3940aaceb1ba574687a4817ef829a04d49dd4.patch b/astro/kstars/files/bef3940aaceb1ba574687a4817ef829a04d49dd4.patch
new file mode 100644
index 000000000000..5b252c7466dd
--- /dev/null
+++ b/astro/kstars/files/bef3940aaceb1ba574687a4817ef829a04d49dd4.patch
@@ -0,0 +1,1237 @@
+From bef3940aaceb1ba574687a4817ef829a04d49dd4 Mon Sep 17 00:00:00 2001
+From: Jasem Mutlaq <mutlaqja@ikarustech.com>
+Date: Fri, 4 Mar 2022 12:54:11 +0300
+Subject: [PATCH] Make it work with StellarSolver 2.0
+
+---
+ CMakeLists.txt                                |   2 +-
+ Tests/kstars_ui/test_ekos_align.cpp           |  17 +-
+ .../kstars_ui/test_ekos_meridianflip_base.cpp |  63 ++--
+ kstars/auxiliary/ksutils.cpp                  |  11 +
+ kstars/ekos/align/align.cpp                   |  22 +-
+ kstars/ekos/align/opsalign.ui                 |   7 +-
+ kstars/ekos/align/opsprograms.cpp             |  30 +-
+ kstars/ekos/align/opsprograms.ui              |  30 +-
+ .../ekos/auxiliary/stellarsolverprofile.cpp   |  50 +--
+ .../auxiliary/stellarsolverprofileeditor.cpp  |   9 +-
+ .../auxiliary/stellarsolverprofileeditor.ui   | 288 +++++++++++-------
+ kstars/fitsviewer/fitssepdetector.cpp         |   6 +-
+ kstars/fitsviewer/structuredefinitions.h      |  84 +++--
+ kstars/kstars.kcfg                            |   5 +
+ 14 files changed, 387 insertions(+), 237 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 5e83ddb47..aabba563e 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -215,7 +215,7 @@ MACRO_BOOL_TO_01(INDI_FOUND HAVE_INDI)
+ set_package_properties(INDI PROPERTIES DESCRIPTION "Astronomical instrumentation control" URL "https://www.indilib.org" TYPE OPTIONAL PURPOSE "Support for controlling astronomical devices on Linux with KStars.")
+ 
+ if (INDI_FOUND AND NOT ANDROID)
+-    find_package(StellarSolver REQUIRED)
++    find_package(StellarSolver REQUIRED 2.0)
+ endif(INDI_FOUND AND NOT ANDROID)
+ MACRO_BOOL_TO_01(StellarSolver_FOUND HAVE_STELLARSOLVER)
+ 
+diff --git a/Tests/kstars_ui/test_ekos_align.cpp b/Tests/kstars_ui/test_ekos_align.cpp
+index 4e5a9f482..a04aff562 100644
+--- a/Tests/kstars_ui/test_ekos_align.cpp
++++ b/Tests/kstars_ui/test_ekos_align.cpp
+@@ -266,7 +266,7 @@ void TestEkosAlign::prepareTestCase()
+     // select StellarSolver
+     Options::setSolverType(SSolver::SOLVER_LOCALASTROMETRY);
+     // select fast solve profile option
+-    Options::setSolveOptionsProfile(SSolver::Parameters::FAST_SOLVING);
++    Options::setSolveOptionsProfile(SSolver::Parameters::DEFAULT);
+     // select the "Slew to Target" mode
+     KTRY_SET_RADIOBUTTON(ekos->alignModule(), slewR, true);
+     // reduce the accuracy to avoid testing problems
+@@ -305,7 +305,8 @@ void TestEkosAlign::init()
+     image_count  = 0;
+ }
+ 
+-void TestEkosAlign::cleanup() {
++void TestEkosAlign::cleanup()
++{
+     Ekos::Manager *ekos = Ekos::Manager::Instance();
+     Ekos::Scheduler *scheduler = ekos->schedulerModule();
+     // press stop button if running
+@@ -440,10 +441,13 @@ bool TestEkosAlign::executeAlignment(SkyObject *targetObject)
+ bool TestEkosAlign::verifyAlignmentTarget(SkyObject *targetObject)
+ {
+     QList<double> alignmentTarget = Ekos::Manager::Instance()->alignModule()->getTargetCoords();
+-    KVERIFY2_SUB(std::abs(alignmentTarget[0] - targetObject->ra0().Hours()) < 0.005, // difference small enough to capture JNow/J2000 errors
+-            QString("RA target J2000 deviation too big: %1 received, %2 expected.").arg(alignmentTarget[0]).arg(targetObject->ra0().Hours()).toLocal8Bit());
++    KVERIFY2_SUB(std::abs(alignmentTarget[0] - targetObject->ra0().Hours()) <
++                 0.005, // difference small enough to capture JNow/J2000 errors
++                 QString("RA target J2000 deviation too big: %1 received, %2 expected.").arg(alignmentTarget[0]).arg(
++                     targetObject->ra0().Hours()).toLocal8Bit());
+     KVERIFY2_SUB(std::abs(alignmentTarget[1] - targetObject->dec0().Degrees()) < 0.005,
+-            QString("DEC target J2000 deviation too big: %1 received, %2 expected.").arg(alignmentTarget[1]).arg(targetObject->dec0().Degrees()).toLocal8Bit());
++                 QString("DEC target J2000 deviation too big: %1 received, %2 expected.").arg(alignmentTarget[1]).arg(
++                     targetObject->dec0().Degrees()).toLocal8Bit());
+     // success
+     return true;
+ }
+@@ -460,7 +464,8 @@ bool TestEkosAlign::alignWithScheduler(SkyObject *targetObject, QString fitsTarg
+     const QString sequenceFile = TestEkosSchedulerHelper::getDefaultEsqContent();
+     const QString esqFile = testDir->filePath(QString("test.esq"));
+     // create the scheduler file
+-    const QString schedulerFile = TestEkosSchedulerHelper::getSchedulerFile(targetObject, startupCondition, 1, {true, false, true, false}, false, false, 30, fitsTarget);
++    const QString schedulerFile = TestEkosSchedulerHelper::getSchedulerFile(targetObject, startupCondition, 1, {true, false, true, false},
++                                  false, false, 30, fitsTarget);
+     const QString eslFile = testDir->filePath(QString("test.esl"));
+     // write both files to the test directory
+     KVERIFY_SUB(TestEkosSchedulerHelper::writeSimpleSequenceFiles(schedulerFile, eslFile, sequenceFile, esqFile));
+diff --git a/Tests/kstars_ui/test_ekos_meridianflip_base.cpp b/Tests/kstars_ui/test_ekos_meridianflip_base.cpp
+index ea58b07fa..c97486558 100644
+--- a/Tests/kstars_ui/test_ekos_meridianflip_base.cpp
++++ b/Tests/kstars_ui/test_ekos_meridianflip_base.cpp
+@@ -23,7 +23,8 @@
+ #include "ekos/guide/internalguide/gmath.h"
+ #include "Options.h"
+ 
+-TestEkosMeridianFlipBase::TestEkosMeridianFlipBase(QObject *parent) : TestEkosMeridianFlipBase::TestEkosMeridianFlipBase("Internal", parent){}
++TestEkosMeridianFlipBase::TestEkosMeridianFlipBase(QObject *parent) :
++    TestEkosMeridianFlipBase::TestEkosMeridianFlipBase("Internal", parent) {}
+ 
+ TestEkosMeridianFlipBase::TestEkosMeridianFlipBase(QString guider, QObject *parent) : QObject(parent)
+ {
+@@ -88,7 +89,7 @@ bool TestEkosMeridianFlipBase::startEkosProfile()
+     // select StellarSolver
+     Options::setSolverType(SSolver::SOLVER_LOCALASTROMETRY);
+     // select fast solve profile option
+-    Options::setSolveOptionsProfile(SSolver::Parameters::FAST_SOLVING);
++    Options::setSolveOptionsProfile(SSolver::Parameters::DEFAULT);
+     // select the "Slew to Target" mode
+     KTRY_SET_RADIOBUTTON_SUB(ekos->alignModule(), slewR, true);
+ 
+@@ -245,8 +246,9 @@ void TestEkosMeridianFlipBase::cleanup()
+  *
+  * ********************************************************************************* */
+ 
+-void TestEkosMeridianFlipBase::prepareTestData(double exptime, QList<QString> locationList, QList<bool> culminationList, QList<QString> filterList,
+-                                               QList<bool> focusList, QList<bool> autofocusList, QList<bool> guideList, QList<bool> ditherList)
++void TestEkosMeridianFlipBase::prepareTestData(double exptime, QList<QString> locationList, QList<bool> culminationList,
++        QList<QString> filterList,
++        QList<bool> focusList, QList<bool> autofocusList, QList<bool> guideList, QList<bool> ditherList)
+ {
+ #if QT_VERSION < QT_VERSION_CHECK(5,9,0)
+     QSKIP("Bypassing fixture test on old Qt");
+@@ -321,7 +323,7 @@ bool TestEkosMeridianFlipBase::positionMountForMF(int secsToMF, bool fast)
+     // calculate a feasible declination depending to the location's latitude
+     // for the upper culmination, we use an azimuth of 45 deg, for the lower culmination half way between pole and horizont
+     double lat = KStarsData::Instance()->geo()->lat()->Degrees();
+-    target = new SkyPoint(range24(meridianRA + delta), culmination ? (lat-45) : (90-lat/2));
++    target = new SkyPoint(range24(meridianRA + delta), culmination ? (lat - 45) : (90 - lat / 2));
+ 
+     if (fast)
+     {
+@@ -414,7 +416,7 @@ bool TestEkosMeridianFlipBase::prepareCaptureTestcase(int secsToMF, bool initial
+ }
+ 
+ bool TestEkosMeridianFlipBase::prepareSchedulerTestcase(int secsToMF, bool useFocus,
+-                                                        SchedulerJob::CompletionCondition completionCondition, int iterations)
++        SchedulerJob::CompletionCondition completionCondition, int iterations)
+ {
+ #if QT_VERSION < QT_VERSION_CHECK(5,9,0)
+     QSKIP("Bypassing fixture test on old Qt");
+@@ -453,18 +455,19 @@ bool TestEkosMeridianFlipBase::prepareSchedulerTestcase(int secsToMF, bool useFo
+     Options::setStopEkosAfterShutdown(false);
+ 
+     // set the completion condition
+-    switch (completionCondition) {
+-    case SchedulerJob::FINISH_REPEAT:
+-        // repeat the job for a fixed amount
+-        KTRY_SET_RADIOBUTTON_SUB(scheduler, repeatCompletionR, true);
+-        KTRY_SET_SPINBOX_SUB(scheduler, repeatsSpin, iterations);
+-        break;
+-    case SchedulerJob::FINISH_LOOP:
+-        KTRY_SET_RADIOBUTTON_SUB(scheduler, loopCompletionR, true);
+-        break;
+-    default:
+-        QWARN(QString("Unsupported completion condition %1!").arg(completionCondition).toStdString().c_str());
+-        return false;
++    switch (completionCondition)
++    {
++        case SchedulerJob::FINISH_REPEAT:
++            // repeat the job for a fixed amount
++            KTRY_SET_RADIOBUTTON_SUB(scheduler, repeatCompletionR, true);
++            KTRY_SET_SPINBOX_SUB(scheduler, repeatsSpin, iterations);
++            break;
++        case SchedulerJob::FINISH_LOOP:
++            KTRY_SET_RADIOBUTTON_SUB(scheduler, loopCompletionR, true);
++            break;
++        default:
++            QWARN(QString("Unsupported completion condition %1!").arg(completionCondition).toStdString().c_str());
++            return false;
+     }
+     // add scheduler job
+     KTRY_CLICK_SUB(scheduler, addToQueueB);
+@@ -511,7 +514,8 @@ bool TestEkosMeridianFlipBase::checkRefocusing()
+     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT_SUB(m_CaptureHelper->expectedFocusStates, 30000);
+     // check if focus completion is reached (successful or not)
+     if (refocus_checked || autofocus_checked)
+-        KTRY_VERIFY_WITH_TIMEOUT_SUB(m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_COMPLETE || m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_FAILED ||
++        KTRY_VERIFY_WITH_TIMEOUT_SUB(m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_COMPLETE
++                                     || m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_FAILED ||
+                                      m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_ABORTED, 120000);
+     // focusing might have suspended guiding
+     if (m_CaptureHelper->use_guiding)
+@@ -554,7 +558,8 @@ bool TestEkosMeridianFlipBase::stopAligning()
+     // stop alignment
+     KTRY_GADGET_SUB(Ekos::Manager::Instance()->alignModule(), QPushButton, stopB);
+     KTRY_CLICK_SUB(Ekos::Manager::Instance()->alignModule(), stopB);
+-    KTRY_VERIFY_WITH_TIMEOUT_SUB(m_CaptureHelper->getAlignStatus() == Ekos::ALIGN_IDLE || m_CaptureHelper->getAlignStatus() == Ekos::ALIGN_ABORTED ||
++    KTRY_VERIFY_WITH_TIMEOUT_SUB(m_CaptureHelper->getAlignStatus() == Ekos::ALIGN_IDLE
++                                 || m_CaptureHelper->getAlignStatus() == Ekos::ALIGN_ABORTED ||
+                                  m_CaptureHelper->getAlignStatus() == Ekos::ALIGN_FAILED || m_CaptureHelper->getAlignStatus() == Ekos::ALIGN_COMPLETE, 5000);
+     // all checks succeeded
+     return true;
+@@ -581,8 +586,10 @@ bool TestEkosMeridianFlipBase::startCapturing()
+     KWRAP_SUB(KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(Ekos::Manager::Instance()->captureModule(), 1000));
+ 
+     // check if capture is in a stopped state
+-    KWRAP_SUB(QVERIFY(m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_IDLE || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_ABORTED
+-                      || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_SUSPENDED|| m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_COMPLETE));
++    KWRAP_SUB(QVERIFY(m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_IDLE
++                      || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_ABORTED
++                      || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_SUSPENDED
++                      || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_COMPLETE));
+ 
+     // press start
+     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_CAPTURING);
+@@ -599,7 +606,8 @@ bool TestEkosMeridianFlipBase::startCapturing()
+ bool TestEkosMeridianFlipBase::stopCapturing()
+ {
+     // check if capture is in a stopped state
+-    if (m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_IDLE || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_ABORTED ||
++    if (m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_IDLE
++            || m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_ABORTED ||
+             m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_COMPLETE)
+         return true;
+ 
+@@ -629,7 +637,8 @@ bool TestEkosMeridianFlipBase::startScheduler()
+ 
+     // switch to the scheduler module and start
+     KWRAP_SUB(KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(scheduler, 1000));
+-    KVERIFY_SUB(m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_IDLE || m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_ABORTED);
++    KVERIFY_SUB(m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_IDLE
++                || m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_ABORTED);
+     KTRY_CLICK_SUB(scheduler, startB);
+ 
+     // check mount slew and tracking
+@@ -648,7 +657,8 @@ bool TestEkosMeridianFlipBase::stopScheduler()
+     Ekos::Scheduler *scheduler = Ekos::Manager::Instance()->schedulerModule();
+     // switch to the capture module
+     KWRAP_SUB(KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(scheduler, 1000));
+-    if (m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_RUNNING || m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_PAUSED)
++    if (m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_RUNNING
++            || m_CaptureHelper->getSchedulerStatus() == Ekos::SCHEDULER_PAUSED)
+         KTRY_CLICK_SUB(scheduler, startB);
+     // all checks succeeded
+     return true;
+@@ -705,7 +715,8 @@ bool TestEkosMeridianFlipBase::stopFocusing()
+     KTRY_GADGET_SUB(Ekos::Manager::Instance()->focusModule(), QPushButton, stopFocusB);
+     if (stopFocusB->isEnabled())
+         KTRY_CLICK_SUB(Ekos::Manager::Instance()->focusModule(), stopFocusB);
+-    KTRY_VERIFY_WITH_TIMEOUT_SUB(m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_IDLE || m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_COMPLETE ||
++    KTRY_VERIFY_WITH_TIMEOUT_SUB(m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_IDLE
++                                 || m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_COMPLETE ||
+                                  m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_ABORTED || m_CaptureHelper->getFocusStatus() == Ekos::FOCUS_FAILED, 15000);
+ 
+     // all checks succeeded
+diff --git a/kstars/auxiliary/ksutils.cpp b/kstars/auxiliary/ksutils.cpp
+index 1b9b53f6a..81fd06134 100644
+--- a/kstars/auxiliary/ksutils.cpp
++++ b/kstars/auxiliary/ksutils.cpp
+@@ -1165,6 +1165,17 @@ QString getDefaultPath(const QString &option)
+ #endif
+         return prefix + "/bin/solve-field";
+     }
++    else if (option == "WatneyBinary")
++    {
++    #if defined(ASTROMETRY_PREFIX)
++            return QString(ASTROMETRY_PREFIX "/bin/watney-solver");
++    #elif defined(Q_OS_OSX)
++            return "/usr/local/bin/watney-solver";
++    #elif defined(Q_OS_WIN)
++            return "C:/Program Files/watney-solve-win-x64-1/watney-solve.exe";
++    #endif
++            return prefix + "/bin/watney-solver";
++    }
+     else if (option == "SextractorBinary")
+     {
+ #if defined(SEXTRACTOR_PREFIX)
+diff --git a/kstars/ekos/align/align.cpp b/kstars/ekos/align/align.cpp
+index 859ac6b01..2abcbb663 100644
+--- a/kstars/ekos/align/align.cpp
++++ b/kstars/ekos/align/align.cpp
+@@ -1867,7 +1867,7 @@ void Align::startSolving()
+ 
+     if (solverModeButtonGroup->checkedId() == SOLVER_LOCAL)
+     {
+-        if(Options::solverType() != SSolver::SOLVER_ASTAP) //You don't need astrometry index files to use ASTAP
++        if(Options::solverType() != SSolver::SOLVER_ASTAP && Options::solverType() != SSolver::SOLVER_WATNEYASTROMETRY) //You don't need astrometry index files to use ASTAP or Watney
+         {
+             bool foundAnIndex = false;
+             for(QString dataDir : astrometryDataDirs)
+@@ -1916,16 +1916,20 @@ void Align::startSolving()
+         m_StellarSolver->setParameters(m_StellarSolverProfiles.at(Options::solveOptionsProfile()));
+ 
+         const SSolver::SolverType type = static_cast<SSolver::SolverType>(m_StellarSolver->property("SolverType").toInt());
+-        if(type == SSolver::SOLVER_LOCALASTROMETRY || type == SSolver::SOLVER_ASTAP)
++        if(type == SSolver::SOLVER_LOCALASTROMETRY || type == SSolver::SOLVER_ASTAP || type == SSolver::SOLVER_WATNEYASTROMETRY)
+         {
+             QString filename = QDir::tempPath() + QString("/solver%1.fits").arg(QUuid::createUuid().toString().remove(
+                                    QRegularExpression("[-{}]")));
+             alignView->saveImage(filename);
+             m_StellarSolver->setProperty("FileToProcess", filename);
+-            m_StellarSolver->setProperty("SextractorBinaryPath", Options::sextractorBinary());
+-            m_StellarSolver->setProperty("SolverPath", Options::astrometrySolverBinary());
+-            m_StellarSolver->setProperty("ASTAPBinaryPath", Options::aSTAPExecutable());
+-            m_StellarSolver->setProperty("WCSPath", Options::astrometryWCSInfo());
++            ExternalProgramPaths externalPaths;
++            externalPaths.sextractorBinaryPath = Options::sextractorBinary();
++            externalPaths.solverPath = Options::astrometrySolverBinary();
++            externalPaths.astapBinaryPath = Options::aSTAPExecutable();
++            externalPaths.watneyBinaryPath = Options::watneyBinary();
++            externalPaths.wcsPath = Options::astrometryWCSInfo();
++            m_StellarSolver->setExternalFilePaths(externalPaths);
++
+ 
+             //No need for a conf file this way.
+             m_StellarSolver->setProperty("AutoGenerateAstroConfig", true);
+@@ -2011,10 +2015,6 @@ void Align::startSolving()
+             m_StellarSolver->setSSLogLevel(SSolver::LOG_OFF);
+         }
+ 
+-        //Unless we decide to load the WCS Coord, let's turn it off.
+-        //Be sure to set this to true instead if we want WCS from the solve.
+-        m_StellarSolver->setLoadWCS(false);
+-
+         // Start solving process
+         m_StellarSolver->start();
+     }
+@@ -2047,7 +2047,7 @@ void Align::solverComplete()
+     {
+         FITSImage::Solution solution = m_StellarSolver->getSolution();
+         // Would be better if parity was a bool field instead of a QString with "pos" and "neg" as possible values.
+-        const bool eastToTheRight = solution.parity == "pos" ? false : true;
++        const bool eastToTheRight = solution.parity == FITSImage::POSITIVE? false : true;
+         solverFinished(solution.orientation, solution.ra, solution.dec, solution.pixscale, eastToTheRight);
+     }
+ }
+diff --git a/kstars/ekos/align/opsalign.ui b/kstars/ekos/align/opsalign.ui
+index b472917a2..808b05e8c 100644
+--- a/kstars/ekos/align/opsalign.ui
++++ b/kstars/ekos/align/opsalign.ui
+@@ -6,7 +6,7 @@
+    <rect>
+     <x>0</x>
+     <y>0</y>
+-    <width>444</width>
++    <width>470</width>
+     <height>179</height>
+    </rect>
+   </property>
+@@ -108,6 +108,11 @@
+           <string>Local ASTAP</string>
+          </property>
+         </item>
++        <item>
++         <property name="text">
++          <string>Local Watney</string>
++         </property>
++        </item>
+         <item>
+          <property name="text">
+           <string>Online Astrometry</string>
+diff --git a/kstars/ekos/align/opsprograms.cpp b/kstars/ekos/align/opsprograms.cpp
+index ff76214a5..f0e7e467b 100644
+--- a/kstars/ekos/align/opsprograms.cpp
++++ b/kstars/ekos/align/opsprograms.cpp
+@@ -43,37 +43,15 @@ void OpsPrograms::slotApply()
+ 
+ void OpsPrograms::loadDefaultPaths(int option)
+ {
+-    ExternalProgramPaths paths;
+-
+-    switch(option)
+-    {
+-        case 0:
+-            return;
+-            break;
+-        case 1:
+-            paths = StellarSolver::getLinuxDefaultPaths();
+-            break;
+-        case 2:
+-            paths = StellarSolver::getLinuxInternalPaths();
+-            break;
+-        case 3:
+-            paths = StellarSolver::getMacHomebrewPaths();
+-            break;
+-        case 4:
+-            paths = StellarSolver::getWinANSVRPaths();
+-            break;
+-        case 5:
+-            paths = StellarSolver::getWinCygwinPaths();
+-            break;
+-        default:
+-            paths = StellarSolver::getLinuxDefaultPaths();
+-            break;
+-    }
++    if(option == 0)
++        return;
++    ExternalProgramPaths paths = StellarSolver::getDefaultExternalPaths((SSolver::ComputerSystemType) (option - 1));
+ 
+     kcfg_SextractorBinary->setText(paths.sextractorBinaryPath);
+     kcfg_AstrometryConfFile->setText(paths.confPath);
+     kcfg_AstrometrySolverBinary->setText(paths.solverPath);
+     kcfg_ASTAPExecutable->setText(paths.astapBinaryPath);
++    kcfg_WatneyBinary->setText(paths.watneyBinaryPath);
+     kcfg_AstrometryWCSInfo->setText(paths.wcsPath);
+ 
+     defaultPathSelector->setCurrentIndex(0);
+diff --git a/kstars/ekos/align/opsprograms.ui b/kstars/ekos/align/opsprograms.ui
+index fcf59bcea..032d56af8 100644
+--- a/kstars/ekos/align/opsprograms.ui
++++ b/kstars/ekos/align/opsprograms.ui
+@@ -7,7 +7,7 @@
+     <x>0</x>
+     <y>0</y>
+     <width>658</width>
+-    <height>481</height>
++    <height>517</height>
+    </rect>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+@@ -169,6 +169,32 @@
+      </layout>
+     </widget>
+    </item>
++   <item>
++    <widget class="QGroupBox" name="groupBox_6">
++     <property name="title">
++      <string>Watney Solver</string>
++     </property>
++     <layout class="QGridLayout" name="gridLayout_5">
++      <item row="0" column="0">
++       <widget class="QLabel" name="label_21">
++        <property name="text">
++         <string>Watney binary:</string>
++        </property>
++       </widget>
++      </item>
++      <item row="0" column="1">
++       <widget class="QLineEdit" name="kcfg_WatneyBinary">
++        <property name="toolTip">
++         <string>Astrometry.net solve-field binary</string>
++        </property>
++        <property name="text">
++         <string/>
++        </property>
++       </widget>
++      </item>
++     </layout>
++    </widget>
++   </item>
+    <item>
+     <widget class="QGroupBox" name="groupBox_3">
+      <property name="title">
+@@ -262,4 +288,4 @@
+  </widget>
+  <resources/>
+  <connections/>
+-</ui>
++</ui>
+\ No newline at end of file
+diff --git a/kstars/ekos/auxiliary/stellarsolverprofile.cpp b/kstars/ekos/auxiliary/stellarsolverprofile.cpp
+index 909ae58ed..7109df6e4 100644
+--- a/kstars/ekos/auxiliary/stellarsolverprofile.cpp
++++ b/kstars/ekos/auxiliary/stellarsolverprofile.cpp
+@@ -24,8 +24,8 @@ QList<Parameters> getDefaultFocusOptionsProfiles()
+     focusDefault.keepNum = 100;
+     focusDefault.minarea = 20;
+     focusDefault.maxEllipse = 1.5;
+-    // JM 2021.10.03: Seems to be a lot more reliable than 2 FWHM
+-    StellarSolver::createConvFilterFromFWHM(&focusDefault, 1);
++    focusDefault.convFilterType = SSolver::CONV_GAUSSIAN;
++    focusDefault.fwhm = 1;
+     focusDefault.r_min = 5;
+     focusDefault.maxSize = 10;
+     focusDefault.removeBrightest = 10;
+@@ -37,7 +37,8 @@ QList<Parameters> getDefaultFocusOptionsProfiles()
+     stars.listName = "2-AllStars";
+     stars.description = i18n("Profile for the source extraction of all the stars in an image.");
+     stars.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&stars, 1);
++    stars.convFilterType = SSolver::CONV_GAUSSIAN;
++    stars.fwhm = 1;
+     stars.r_min = 2;
+     profileList.append(stars);
+ 
+@@ -45,7 +46,8 @@ QList<Parameters> getDefaultFocusOptionsProfiles()
+     smallStars.listName = "3-SmallSizedStars";
+     smallStars.description = i18n("Profile optimized for source extraction of smaller stars.");
+     smallStars.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&smallStars, 1);
++    smallStars.convFilterType = SSolver::CONV_GAUSSIAN;
++    smallStars.fwhm = 1;
+     smallStars.r_min = 2;
+     smallStars.maxSize = 5;
+     smallStars.initialKeep = 500;
+@@ -57,7 +59,8 @@ QList<Parameters> getDefaultFocusOptionsProfiles()
+     mid.description = i18n("Profile optimized for source extraction of medium sized stars.");
+     mid.maxEllipse = 1.5;
+     mid.minarea = 20;
+-    StellarSolver::createConvFilterFromFWHM(&mid, 4);
++    mid.convFilterType = SSolver::CONV_GAUSSIAN;
++    mid.fwhm = 4;
+     mid.r_min = 5;
+     mid.removeDimmest = 20;
+     mid.minSize = 2;
+@@ -71,7 +74,8 @@ QList<Parameters> getDefaultFocusOptionsProfiles()
+     big.description = i18n("Profile optimized for source extraction of larger stars.");
+     big.maxEllipse = 1.5;
+     big.minarea = 40;
+-    StellarSolver::createConvFilterFromFWHM(&big, 8);
++    big.convFilterType = SSolver::CONV_GAUSSIAN;
++    big.fwhm = 8;
+     big.r_min = 20;
+     big.minSize = 5;
+     big.initialKeep = 500;
+@@ -101,7 +105,8 @@ QList<SSolver::Parameters> getDefaultGuideOptionsProfiles()
+     stars.listName = "2-AllStars";
+     stars.description = i18n("Profile for the source extraction of all the stars in an image.");
+     stars.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&stars, 1);
++    stars.convFilterType = SSolver::CONV_GAUSSIAN;
++    stars.fwhm = 1;
+     stars.r_min = 2;
+     profileList.append(stars);
+ 
+@@ -109,7 +114,8 @@ QList<SSolver::Parameters> getDefaultGuideOptionsProfiles()
+     smallStars.listName = "3-SmallSizedStars";
+     smallStars.description = i18n("Profile optimized for source extraction of smaller stars.");
+     smallStars.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&smallStars, 1);
++    smallStars.convFilterType = SSolver::CONV_GAUSSIAN;
++    smallStars.fwhm = 1;
+     smallStars.r_min = 2;
+     smallStars.maxSize = 5;
+     smallStars.initialKeep = 500;
+@@ -121,7 +127,8 @@ QList<SSolver::Parameters> getDefaultGuideOptionsProfiles()
+     mid.description = i18n("Profile optimized for source extraction of medium sized stars.");
+     mid.maxEllipse = 1.5;
+     mid.minarea = 20;
+-    StellarSolver::createConvFilterFromFWHM(&mid, 4);
++    mid.convFilterType = SSolver::CONV_GAUSSIAN;
++    mid.fwhm = 4;
+     mid.r_min = 5;
+     mid.removeDimmest = 20;
+     mid.minSize = 2;
+@@ -135,7 +142,8 @@ QList<SSolver::Parameters> getDefaultGuideOptionsProfiles()
+     big.description = i18n("Profile optimized for source extraction of larger stars.");
+     big.maxEllipse = 1.5;
+     big.minarea = 40;
+-    StellarSolver::createConvFilterFromFWHM(&big, 8);
++    big.convFilterType = SSolver::CONV_GAUSSIAN;
++    big.fwhm = 8;
+     big.r_min = 20;
+     big.minSize = 5;
+     big.initialKeep = 500;
+@@ -152,8 +160,8 @@ QList<SSolver::Parameters> getDefaultAlignOptionsProfiles()
+     SSolver::Parameters defaultProfile;
+     defaultProfile.listName = "1-Default";
+     defaultProfile.description = i18n("Default profile. Generic and not optimized for any specific purpose.");
+-    // JM 2021.10.03: Seems to help in cases where solver fails to solve any images.
+-    StellarSolver::createConvFilterFromFWHM(&defaultProfile, 1);
++    defaultProfile.convFilterType = SSolver::CONV_GAUSSIAN;
++    defaultProfile.fwhm = 1;
+     profileList.append(defaultProfile);
+ 
+     SSolver::Parameters fastSolving;
+@@ -165,7 +173,8 @@ QList<SSolver::Parameters> getDefaultAlignOptionsProfiles()
+     fastSolving.keepNum = 50;
+     fastSolving.initialKeep = 500;
+     fastSolving.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&fastSolving, 4);
++    fastSolving.convFilterType = SSolver::CONV_GAUSSIAN;
++    fastSolving.fwhm = 4;
+     profileList.append(fastSolving);
+ 
+     SSolver::Parameters parLargeSolving;
+@@ -176,7 +185,8 @@ QList<SSolver::Parameters> getDefaultAlignOptionsProfiles()
+     parLargeSolving.keepNum = 50;
+     parLargeSolving.initialKeep = 500;
+     parLargeSolving.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&parLargeSolving, 4);
++    parLargeSolving.convFilterType = SSolver::CONV_GAUSSIAN;
++    parLargeSolving.fwhm = 4;
+     profileList.append(parLargeSolving);
+ 
+     SSolver::Parameters fastSmallSolving;
+@@ -187,7 +197,8 @@ QList<SSolver::Parameters> getDefaultAlignOptionsProfiles()
+     fastSmallSolving.keepNum = 50;
+     fastSmallSolving.initialKeep = 500;
+     fastSmallSolving.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&fastSmallSolving, 4);
++    fastSmallSolving.convFilterType = SSolver::CONV_GAUSSIAN;
++    fastSmallSolving.fwhm = 4;
+     profileList.append(fastSmallSolving);
+ 
+     return profileList;
+@@ -205,7 +216,8 @@ QList<Parameters> getDefaultHFROptionsProfiles()
+ 
+     hfrDefault.minarea = 20;
+     hfrDefault.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&hfrDefault, 2);
++    hfrDefault.convFilterType = SSolver::CONV_GAUSSIAN;
++    hfrDefault.fwhm = 2;
+     hfrDefault.r_min = 5;
+     hfrDefault.maxSize = 10;
+ 
+@@ -224,7 +236,8 @@ QList<Parameters> getDefaultHFROptionsProfiles()
+ 
+     big.minarea = 40;
+     big.maxEllipse = 1.5;
+-    StellarSolver::createConvFilterFromFWHM(&big, 8);
++    big.convFilterType = SSolver::CONV_GAUSSIAN;
++    big.fwhm = 8;
+     big.r_min = 20;
+     big.maxSize = 0;
+ 
+@@ -242,7 +255,8 @@ QList<Parameters> getDefaultHFROptionsProfiles()
+ 
+     most.minarea = 10;
+     most.maxEllipse = 0;
+-    StellarSolver::createConvFilterFromFWHM(&most, 1);
++    most.convFilterType = SSolver::CONV_GAUSSIAN;
++    most.fwhm = 1;
+     most.r_min = 3.5;
+     most.minSize = 0;
+     most.maxSize = 0;
+diff --git a/kstars/ekos/auxiliary/stellarsolverprofileeditor.cpp b/kstars/ekos/auxiliary/stellarsolverprofileeditor.cpp
+index c80b7725a..e33c1da30 100644
+--- a/kstars/ekos/auxiliary/stellarsolverprofileeditor.cpp
++++ b/kstars/ekos/auxiliary/stellarsolverprofileeditor.cpp
+@@ -241,14 +241,16 @@ SSolver::Parameters StellarSolverProfileEditor::getSettingsFromUI()
+     params.kron_fact = kron_fact->text().toDouble();
+     params.subpix = subpix->text().toInt() ;
+     params.r_min = r_min->text().toFloat();
+-    //params.inflags
+     params.magzero = magzero->text().toFloat();
++    params.threshold_bg_multiple = threshMultiple->text().toFloat();
++    params.threshold_offset = threshOffset->text().toFloat();
+     params.minarea = minarea->text().toFloat();
+     params.deblend_thresh = deblend_thresh->text().toInt();
+     params.deblend_contrast = deblend_contrast->text().toFloat();
+     params.clean = (cleanCheckBox->isChecked()) ? 1 : 0;
+     params.clean_param = clean_param->text().toDouble();
+-    StellarSolver::createConvFilterFromFWHM(&params, fwhm->value());
++    params.convFilterType = (SSolver::ConvFilterType) convFilter->currentIndex();
++    params.fwhm = fwhm->value();
+ 
+     //Star Filter Settings
+     params.resort = resort->isChecked();
+@@ -289,11 +291,14 @@ void StellarSolverProfileEditor::sendSettingsToUI(SSolver::Parameters a)
+     r_min->setText(QString::number(a.r_min));
+ 
+     magzero->setText(QString::number(a.magzero));
++    threshMultiple->setText(QString::number(a.threshold_bg_multiple));
++    threshOffset->setText(QString::number(a.threshold_offset));
+     minarea->setText(QString::number(a.minarea));
+     deblend_thresh->setText(QString::number(a.deblend_thresh));
+     deblend_contrast->setText(QString::number(a.deblend_contrast));
+     cleanCheckBox->setChecked(a.clean == 1);
+     clean_param->setText(QString::number(a.clean_param));
++    convFilter->setCurrentIndex(a.convFilterType);
+     fwhm->setValue(a.fwhm);
+ 
+     //Star Filter Settings
+diff --git a/kstars/ekos/auxiliary/stellarsolverprofileeditor.ui b/kstars/ekos/auxiliary/stellarsolverprofileeditor.ui
+index 54e475cbd..c5d6ea85f 100644
+--- a/kstars/ekos/auxiliary/stellarsolverprofileeditor.ui
++++ b/kstars/ekos/auxiliary/stellarsolverprofileeditor.ui
+@@ -347,7 +347,7 @@
+       <property name="spacing">
+        <number>3</number>
+       </property>
+-      <item row="3" column="6">
++      <item row="4" column="6">
+        <widget class="QLineEdit" name="r_min">
+         <property name="toolTip">
+          <string>The minimum radius for stars for flux calculations.</string>
+@@ -357,43 +357,47 @@
+         </property>
+        </widget>
+       </item>
+-      <item row="0" column="0" colspan="2">
+-       <widget class="QLabel" name="label_38">
+-        <property name="sizePolicy">
+-         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+-          <horstretch>0</horstretch>
+-          <verstretch>0</verstretch>
+-         </sizepolicy>
++      <item row="5" column="3">
++       <widget class="QSpinBox" name="fwhm">
++        <property name="toolTip">
++         <string>A variable to store the fwhm in pixels used to generate the convolution filter for star detection.</string>
+         </property>
+-        <property name="text">
+-         <string>&lt;a href = &quot;https://sep.readthedocs.io/en/v1.0.x/api/sep.extract.html&quot; &gt;Extraction Params&lt;/a&gt;</string>
++        <property name="minimum">
++         <number>1</number>
+         </property>
+-        <property name="openExternalLinks">
+-         <bool>true</bool>
++        <property name="maximum">
++         <number>10</number>
+         </property>
+        </widget>
+       </item>
+-      <item row="0" column="2" colspan="2">
+-       <widget class="QLabel" name="label_20">
+-        <property name="text">
+-         <string>&lt;a href=&quot;https://sep.readthedocs.io/en/v1.0.x/api/sep.extract.html&quot;&gt;Deblending Params&lt;/a&gt;</string>
++      <item row="5" column="6">
++       <widget class="QLineEdit" name="magzero">
++        <property name="toolTip">
++         <string>This is the 'zero' magnitude used for setting the magnitude scale for the stars in the image during sextraction.</string>
+         </property>
+-        <property name="openExternalLinks">
+-         <bool>true</bool>
++        <property name="text">
++         <string>20</string>
+         </property>
+        </widget>
+       </item>
+-      <item row="4" column="6">
+-       <widget class="QLineEdit" name="magzero">
++      <item row="3" column="3">
++       <widget class="QLineEdit" name="deblend_contrast">
+         <property name="toolTip">
+-         <string>This is the 'zero' magnitude used for setting the magnitude scale for the stars in the image during sextraction.</string>
++         <string>The percentage of flux a separate peak must have to be considered a separate object.</string>
+         </property>
+         <property name="text">
+-         <string>20</string>
++         <string>1</string>
++        </property>
++       </widget>
++      </item>
++      <item row="3" column="2">
++       <widget class="QLabel" name="label_19">
++        <property name="text">
++         <string>Min Cont.</string>
+         </property>
+        </widget>
+       </item>
+-      <item row="1" column="6">
++      <item row="2" column="6">
+        <widget class="QLineEdit" name="kron_fact">
+         <property name="toolTip">
+          <string>This sets the Kron Factor for use with the kron radius for flux calculations.</string>
+@@ -403,47 +407,131 @@
+         </property>
+        </widget>
+       </item>
+-      <item row="1" column="0">
+-       <widget class="QLabel" name="label_21">
++      <item row="2" column="5">
++       <widget class="QLabel" name="label_25">
+         <property name="text">
+-         <string>Min Area</string>
++         <string>Kron Factor</string>
+         </property>
+        </widget>
+       </item>
+-      <item row="3" column="0">
+-       <widget class="QCheckBox" name="cleanCheckBox">
+-        <property name="toolTip">
+-         <string>Attempts to 'clean' the image to remove artifacts caused by bright objects</string>
++      <item row="5" column="2">
++       <widget class="QLabel" name="label_23">
++        <property name="text">
++         <string>Conv FWHM</string>
+         </property>
++       </widget>
++      </item>
++      <item row="5" column="5">
++       <widget class="QLabel" name="label_15">
+         <property name="text">
+-         <string>Clean?</string>
++         <string>magzero</string>
+         </property>
+-        <property name="checked">
+-         <bool>true</bool>
++       </widget>
++      </item>
++      <item row="4" column="3">
++       <widget class="QComboBox" name="convFilter">
++        <property name="toolTip">
++         <string>Whether to use the SEP_SUM_ELLIPSE method or the SEP_SUM_CIRCLE method or automatically choose.  NOTE: Circle is usually better at the moment</string>
+         </property>
++        <property name="currentIndex">
++         <number>0</number>
++        </property>
++        <item>
++         <property name="text">
++          <string>Default</string>
++         </property>
++        </item>
++        <item>
++         <property name="text">
++          <string>Custom</string>
++         </property>
++        </item>
++        <item>
++         <property name="text">
++          <string>Gaussian</string>
++         </property>
++        </item>
++        <item>
++         <property name="text">
++          <string>Mexican Hat</string>
++         </property>
++        </item>
++        <item>
++         <property name="text">
++          <string>Top Hat</string>
++         </property>
++        </item>
+        </widget>
+       </item>
+-      <item row="1" column="1">
+-       <widget class="QLineEdit" name="minarea">
++      <item row="2" column="3">
++       <widget class="QLineEdit" name="deblend_thresh">
+         <property name="toolTip">
+-         <string>This is the minimum area in pixels for a star detection, smaller stars are ignored.</string>
++         <string>The number of thresholds the intensity range is divided up into.</string>
+         </property>
+         <property name="text">
+-         <string>5</string>
++         <string>32</string>
+         </property>
+        </widget>
+       </item>
+-      <item row="2" column="1">
+-       <widget class="QLineEdit" name="subpix">
++      <item row="0" column="0" colspan="2">
++       <widget class="QLabel" name="label_38">
++        <property name="sizePolicy">
++         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
++          <horstretch>0</horstretch>
++          <verstretch>0</verstretch>
++         </sizepolicy>
++        </property>
++        <property name="text">
++         <string>&lt;a href = &quot;https://sep.readthedocs.io/en/v1.0.x/api/sep.extract.html&quot; &gt;Extraction Params&lt;/a&gt;</string>
++        </property>
++        <property name="openExternalLinks">
++         <bool>true</bool>
++        </property>
++       </widget>
++      </item>
++      <item row="4" column="5">
++       <widget class="QLabel" name="label_13">
++        <property name="text">
++         <string>r_min</string>
++        </property>
++       </widget>
++      </item>
++      <item row="3" column="6">
++       <widget class="QComboBox" name="apertureShape">
+         <property name="toolTip">
+-         <string>The subpixel sampling factor for star extraction</string>
++         <string>Whether to use the SEP_SUM_ELLIPSE method or the SEP_SUM_CIRCLE method or automatically choose.  NOTE: Circle is usually better at the moment</string>
++        </property>
++        <property name="currentIndex">
++         <number>1</number>
+         </property>
++        <item>
++         <property name="text">
++          <string>Auto</string>
++         </property>
++        </item>
++        <item>
++         <property name="text">
++          <string>Circle</string>
++         </property>
++        </item>
++        <item>
++         <property name="text">
++          <string>Ellipse</string>
++         </property>
++        </item>
++       </widget>
++      </item>
++      <item row="0" column="2" colspan="2">
++       <widget class="QLabel" name="label_20">
+         <property name="text">
+-         <string>5</string>
++         <string>&lt;a href=&quot;https://sep.readthedocs.io/en/v1.0.x/api/sep.extract.html&quot;&gt;Deblending Params&lt;/a&gt;</string>
++        </property>
++        <property name="openExternalLinks">
++         <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+-      <item row="1" column="2">
++      <item row="2" column="2">
+        <widget class="QLabel" name="label_18">
+         <property name="text">
+          <string>Thresh</string>
+@@ -466,38 +554,34 @@
+         </property>
+        </widget>
+       </item>
+-      <item row="2" column="0">
+-       <widget class="QLabel" name="label_24">
++      <item row="4" column="2">
++       <widget class="QLabel" name="label_26">
+         <property name="text">
+-         <string>Sub Pix</string>
++         <string>Conv Filter</string>
+         </property>
+        </widget>
+       </item>
+-      <item row="1" column="3">
+-       <widget class="QLineEdit" name="deblend_thresh">
+-        <property name="toolTip">
+-         <string>The number of thresholds the intensity range is divided up into.</string>
+-        </property>
++      <item row="3" column="5">
++       <widget class="QLabel" name="label_12">
+         <property name="text">
+-         <string>32</string>
++         <string>Shape</string>
+         </property>
+        </widget>
+       </item>
+-      <item row="1" column="5">
+-       <widget class="QLabel" name="label_25">
+-        <property name="text">
+-         <string>Kron Factor</string>
++      <item row="6" column="0">
++       <widget class="QCheckBox" name="cleanCheckBox">
++        <property name="toolTip">
++         <string>Attempts to 'clean' the image to remove artifacts caused by bright objects</string>
+         </property>
+-       </widget>
+-      </item>
+-      <item row="4" column="5">
+-       <widget class="QLabel" name="label_15">
+         <property name="text">
+-         <string>magzero</string>
++         <string>Clean?</string>
++        </property>
++        <property name="checked">
++         <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+-      <item row="3" column="1">
++      <item row="6" column="1">
+        <widget class="QLineEdit" name="clean_param">
+         <property name="toolTip">
+          <string> The cleaning parameter</string>
+@@ -507,79 +591,71 @@
+         </property>
*** 295 LINES SKIPPED ***