[kstars] kstars/ekos/focus: Use sigmal clipping when focus frames count > 3 and simple averaging for the rest. Please note that invalid values for currentHFR (-1) must be counted and passed to the focusing algorithm since it is responsible for making decisions on how to correct this.

Jasem Mutlaq null at kde.org
Sat Feb 4 07:57:04 UTC 2017


Git commit 989cae1a874efa4be31ba3b0acbbcb3b388581b6 by Jasem Mutlaq.
Committed on 04/02/2017 at 07:54.
Pushed by mutlaqja into branch 'master'.

Use sigmal clipping when focus frames count > 3 and simple averaging for the rest. Please note that invalid values for currentHFR (-1) must be counted and passed to the focusing algorithm since it is responsible for making decisions on how to correct this.
Also using read-only QLineEdit instead of QLabel because it looks better and users can copy the current absolute position from it.

CCMAIL:kstars-devel at kde.org

M  +44   -14   kstars/ekos/focus/focus.cpp
M  +13   -7    kstars/ekos/focus/focus.ui

https://commits.kde.org/kstars/989cae1a874efa4be31ba3b0acbbcb3b388581b6

diff --git a/kstars/ekos/focus/focus.cpp b/kstars/ekos/focus/focus.cpp
index 63dfbec4c..dab573dcd 100644
--- a/kstars/ekos/focus/focus.cpp
+++ b/kstars/ekos/focus/focus.cpp
@@ -1117,27 +1117,57 @@ void Focus::setCaptureComplete()
         if (Options::focusLogging())
             qDebug() << "Focus newFITS #" << HFRFrames.count()+1 << ": Current HFR " << currentHFR;
 
-
-        if (currentHFR != -1)
-            HFRFrames.append(currentHFR);
+        HFRFrames.append(currentHFR);
 
         // Check if we need to average more than a single frame
         if (HFRFrames.count() >= focusFramesSpin->value())
         {
             currentHFR=0;
-            // Sort all HFRs
-            qSort(HFRFrames.begin(), HFRFrames.end(), [](double a, double b){return a < b;});
-            // Reject 10% outliers for frames > 3
-            int cutOff=0;
-            if (HFRFrames.count() > 3)
-                cutOff = ceil(HFRFrames.count() * 0.1);
 
-            for (int i=cutOff; i < HFRFrames.count()-cutOff; i++)
-                currentHFR+= HFRFrames[i];
+            // Remove all -1
+            QMutableVectorIterator<double> i(HFRFrames);
+            while (i.hasNext())
+            {
+                if (i.next() == -1)
+                    i.remove();
+            }
+
+            if (HFRFrames.isEmpty())
+                currentHFR = -1;
+            else
+            {
+                // Perform simple sigma clipping if frames count > 3
+                if (HFRFrames.count() > 3)
+                {
+                    // Sort all HFRs
+                    std::sort(HFRFrames.begin(), HFRFrames.end());
+                    const auto median = HFRFrames.size()%2   ? HFRFrames[HFRFrames.size() / 2]
+                                                             : ((double)HFRFrames[HFRFrames.size() / 2 - 1] + HFRFrames[HFRFrames.size() / 2]) * .5;
+                    const auto mean = std::accumulate(HFRFrames.begin(), HFRFrames.end(), .0) / HFRFrames.size();
+                    double variance =0;
+                    foreach(auto val, HFRFrames)
+                        variance += (val-mean)*(val-mean);
+                    const double stddev = sqrt(variance/HFRFrames.size());
+
+                    // Reject those 2 sigma away from median
+                    const double sigmaHigh = median + stddev*2;
+                    const double sigmaLow  = median - stddev*2;
+
+                    QMutableVectorIterator<double> i(HFRFrames);
+                    while (i.hasNext())
+                    {
+                        auto val = i.next();
+                        if (val > sigmaHigh || val < sigmaLow)
+                            i.remove();
+                    }
+                }
+
+                // Find average HFR
+                currentHFR = std::accumulate(HFRFrames.begin(), HFRFrames.end(), .0) / HFRFrames.size();
 
-            currentHFR /= (HFRFrames.count() - (2 * cutOff));
+                HFRFrames.clear();
+            }
 
-            HFRFrames.clear();
         }
         else
         {
@@ -1147,7 +1177,7 @@ void Focus::setCaptureComplete()
 
         emit newHFR(currentHFR);
 
-        QString HFRText = QString("%1").arg(currentHFR, 0,'g', 3);
+        QString HFRText = QString("%1").arg(currentHFR, 0,'f', 2);
 
         if (/*focusType == FOCUS_MANUAL && */ lastHFR == -1)
                 appendLogText(i18n("FITS received. No stars detected."));
diff --git a/kstars/ekos/focus/focus.ui b/kstars/ekos/focus/focus.ui
index 21a36ebc6..419995e87 100644
--- a/kstars/ekos/focus/focus.ui
+++ b/kstars/ekos/focus/focus.ui
@@ -146,6 +146,9 @@
             <property name="enabled">
              <bool>false</bool>
             </property>
+            <property name="toolTip">
+             <string>Set desired absolute focus position</string>
+            </property>
             <property name="text">
              <string>Set</string>
             </property>
@@ -162,18 +165,21 @@
               <verstretch>0</verstretch>
              </sizepolicy>
             </property>
+            <property name="toolTip">
+             <string>Desired absolute focus position</string>
+            </property>
            </widget>
           </item>
           <item row="1" column="1">
-           <widget class="QLabel" name="absTicksLabel">
-            <property name="frameShape">
-             <enum>QFrame::Box</enum>
+           <widget class="QLineEdit" name="absTicksLabel">
+            <property name="enabled">
+             <bool>false</bool>
             </property>
-            <property name="frameShadow">
-             <enum>QFrame::Sunken</enum>
+            <property name="toolTip">
+             <string>Current absolute focuser position</string>
             </property>
-            <property name="text">
-             <string/>
+            <property name="readOnly">
+             <bool>true</bool>
             </property>
            </widget>
           </item>


More information about the Kstars-devel mailing list