9#include "ekos_guide_debug.h"
10#include "../guideview.h"
11#include "fitsviewer/fitsdata.h"
12#include "fitsviewer/fitssepdetector.h"
16#include <stellarsolver.h>
17#include "ekos/auxiliary/stellarsolverprofileeditor.h"
20#define DLOG if (false) qCDebug
23#define STARS_TO_SEARCH 250
26#define MIN_DRIFT_SNR 8
30#define MIN_STAR_CORRESPONDENCE_SIZE 5
35constexpr double HFR_MARGIN = 2.0;
51 return QString(
"%1 %2 %3 %4 %5 %6 %7")
53 .
arg(
"HFR", 6).
arg(
"SNR ", 5);
58 double snr = bg.SNR(star.sum, star.numPixels);
59 return QString(
"%1 %2 %3 %4 %5 %6 %7")
62 .
arg(star.x, 6,
'f', 1)
63 .
arg(star.y, 6,
'f', 1)
64 .
arg(star.sum, 6,
'f', 0)
65 .
arg(star.HFR, 6,
'f', 2)
71 std::function<
const Edge & (
int index)> stars,
79 for (
int i = 0; i < size; ++i)
81 const auto &star = stars(i);
90GuideStars::GuideStars()
95int GuideStars::getStarMap(
int index)
97 if (index >= starMap.size() || (index < 0))
99 return starMap[index];
102void GuideStars::setupStarCorrespondence(
const QList<Edge> &neighbors,
int guideIndex)
104 qCDebug(
KSTARS_EKOS_GUIDE) <<
"setupStarCorrespondence: neighbors " << neighbors.size() <<
"guide index" << guideIndex;
105 if (neighbors.size() >= MIN_STAR_CORRESPONDENCE_SIZE)
108 for (
int i = 0; i < neighbors.size(); ++i)
110 qCDebug(
KSTARS_EKOS_GUIDE) <<
" adding ref: " << neighbors[i].x << neighbors[i].y;
114 starMap.push_back(i);
116 starCorrespondence.initialize(neighbors, guideIndex);
119 starCorrespondence.reset();
126 if (imageData ==
nullptr)
131 const double maxHFR = Options::guideMaxHFR();
132 findTopStars(imageData, Options::maxMultistarReferenceStars(), &detectedStars, maxHFR,
135 int maxX = imageData->width();
136 int maxY = imageData->height();
150 if ((uint) stars.size() < Options::minDetectionsSEPMultistar())
156 int maxIndex = Options::maxMultistarReferenceStars() < stars.count() ? Options::maxMultistarReferenceStars() :
163 hfrs.push_back(stars[i].HFR);
164 std::sort(hfrs.begin(), hfrs.end());
173 const Edge &
center = stars.at(i);
191 auto bg = skybackground();
193 if (snr >= 40 && snr <= 100)
211 logStars(
"Select",
"Star", skyBackground,
213 [&](
int i) ->
const Edge&
251 if (starCorrespondence.size() == 0)
return;
253 const Edge
gStar = starCorrespondence.reference(starCorrespondence.guideStar());
264 for (
int i = 0; i < detectedStars.
size(); ++i)
274 for (
int i = 0; i < starCorrespondence.size(); ++i)
276 bool isGuideStar = i == starCorrespondence.guideStar();
277 const QVector2D offset = starCorrespondence.offset(i);
297 unreliableDectionCounter = 0;
302 if (imageData ==
nullptr)
303 return GuiderUtils::Vector(-1, -1, -1);
309 if (
firstFrame && starCorrespondence.size() == 0)
311 QVector3D v = selectGuideStar(imageData);
312 qCDebug(
KSTARS_EKOS_GUIDE) <<
QString(
"findGuideStar: Called without starCorrespondence. Refound guide star at %1 %2")
314 return GuiderUtils::Vector(v.
x(), v.
y(), v.
z());
318 const double maxHFR = Options::guideMaxHFR() + HFR_MARGIN;
319 if (starCorrespondence.size() > 0)
322 findTopStars(imageData, STARS_TO_SEARCH, &detectedStars, maxHFR);
323 if (detectedStars.
empty())
324 return GuiderUtils::Vector(-1, -1, -1);
327 starCorrespondence.setAllowMissingGuideStar(allowMissingGuideStar);
330 starCorrespondence.setImageSize(imageData->width(), imageData->height());
335 if (starCorrespondence.size() > 25)
minFraction = 0.33;
336 else if (starCorrespondence.size() > 15)
minFraction = 0.4;
342 for (
int i = 0; i < detectedStars.
size(); ++i)
344 if (getStarMap(i) == starCorrespondence.guideStar())
346 auto &star = detectedStars[i];
347 double SNR = skyBackground.SNR(star.sum, star.numPixels);
349 guideStarMass = star.sum;
350 unreliableDectionCounter = 0;
352 .
arg(i).
arg(star.x, 0,
'f', 1).
arg(star.y, 0,
'f', 1).
arg(SNR, 0,
'f', 1);
356 return GuiderUtils::Vector(star.x, star.y, 0);
365 unreliableDectionCounter = 0;
373 qCDebug(
KSTARS_EKOS_GUIDE) <<
"StarCorrespondence not used. It failed to find the guide star.";
376 return GuiderUtils::Vector(-1, -1, -1);
378 logStars(
"findGuide",
"Star", skyBackground,
379 detectedStars.
size(),
380 [&](
int i) ->
const Edge&
382 return detectedStars[i];
386 return QString(
"%1").arg(getStarMap(i));
389 if (trackingBox.
isValid() ==
false)
390 return GuiderUtils::Vector(-1, -1, -1);
393 findTopStars(imageData, 100, &detectedStars, maxHFR, &trackingBox);
394 if (detectedStars.
size() > 0)
400 double refX = trackingBox.
x() + trackingBox.
width() / 2;
401 double refY = trackingBox.
y() + trackingBox.
height() / 2;
402 if (starCorrespondence.size() > 0 && starCorrespondence.guideStar() >= 0)
404 const auto gStar = starCorrespondence.reference(starCorrespondence.guideStar());
410 for (
int i = 0; i < detectedStars.
size(); ++i)
412 const auto &
dStar = detectedStars[i];
421 auto &star = detectedStars[
best];
422 double SNR = skyBackground.SNR(star.sum, star.numPixels);
424 guideStarMass = star.sum;
425 qCDebug(
KSTARS_EKOS_GUIDE) <<
"StarCorrespondence. Standard method found at " << star.x << star.y <<
"SNR" << SNR;
426 return GuiderUtils::Vector(star.x, star.y, 0);
428 return GuiderUtils::Vector(-1, -1, -1);
431SSolver::Parameters GuideStars::getStarExtractionParameters(
int num)
433 SSolver::Parameters params;
434 params.listName =
"Guider";
435 params.apertureShape = SSolver::SHAPE_CIRCLE;
437 params.deblend_thresh = 32;
438 params.deblend_contrast = 0.005;
439 params.initialKeep = num * 2;
440 params.keepNum = num;
441 params.removeBrightest = 0;
442 params.removeDimmest = 0;
443 params.saturationLimit = 0;
450 if (imageData ==
nullptr)
453 QVariantMap settings;
454 settings[
"optionsProfileIndex"] = Options::guideOptionsProfile();
455 settings[
"optionsProfileGroup"] =
static_cast<int>(Ekos::GuideProfiles);
456 imageData->setSourceExtractorSettings(settings);
457 imageData->findStars(ALGORITHM_SEP).waitForFinished();
458 skyBackground = imageData->getSkyBackground();
462 std::sort(
edges.begin(),
edges.end(), [](
const Edge *
edge1,
const Edge *
edge2) ->
bool { return edge1->HFR > edge2->HFR;});
464 m_NumStarsDetected =
edges.count();
477double GuideStars::findMinDistance(
int index,
const QList<Edge*> &stars)
480 const Edge &star = *stars[index];
481 for (
int i = 0; i < stars.size(); ++i)
483 if (i == index)
continue;
497 const double maxHFR,
const QRect *
roi,
507 if (imageData ==
nullptr)
513 int count = findAllSEPStars(imageData, &
sepStars, num * 2);
524 for (
int i = 0; i <
scores.size(); ++i)
525 sc.push_back(std::pair<int, double>(i,
scores[i]));
526 std::sort(
sc.begin(),
sc.end(), [](
const std::pair<int, double> &a,
const std::pair<int, double> &b)
528 return a.second > b.second;
531 for (
int i = 0; i < std::min(num,
scores.size()); ++i)
545 <<
QString(
"Multistar: findTopStars returning: %1 stars, %2s")
546 .
arg(stars->size()).
arg(timer.elapsed() / 1000.0, 4,
'f', 2);
551 const QRect *
roi,
const double maxHFR)
const
563 auto bg = skybackground();
567 std::sort(
centers.begin(),
centers.end(), [&bg](
const Edge * a,
const Edge * b)
569 double snrA = bg.SNR(a->sum, a->numPixels);
570 double snrB = bg.SNR(b->sum, b->numPixels);
578 if (
centers.at(i)->HFR > maxHFR)
592 if (starCenters.at(
j) ==
centers.at(i))
608 for (
int j = 0;
j < starCenters.size(); ++
j)
610 const auto &star = starCenters.at(
j);
611 if (star->x <
roi->x() || star->x >=
roi->x() +
roi->width() ||
612 star->y <
roi->y() || star->y >=
roi->y() +
roi->height())
619void GuideStars::computeStarDrift(
const Edge &star,
const Edge &reference,
double *
driftRA,
double *
driftDEC)
const
621 if (!calibrationInitialized)
return;
623 GuiderUtils::Vector position(star.x, star.y, 0);
626 arc_position = calibration.convertToArcseconds(position);
648 if (starCorrespondence.size() == 0)
650 const Edge
gStar = starCorrespondence.reference(starCorrespondence.guideStar());
658 if (!calibrationInitialized)
667 if (starCorrespondence.size() < 2)
685 for (
int i = 0; i < detectedStars.
size(); ++i)
687 const auto &star = detectedStars[i];
688 auto bg = skybackground();
689 double snr = bg.SNR(detectedStars[i].sum, detectedStars[i].numPixels);
691 if (getStarMap(i) >= 0 && snr >= MIN_DRIFT_SNR)
693 auto ref = starCorrespondence.reference(getStarMap(i));
698 if (getStarMap(i) == starCorrespondence.guideStar())
711 .
arg(
logStar(
" Ref:", getStarMap(i), bg, ref))
721 for (
int i = 0; i <
raDrifts.size(); ++i)
763 detectedStars.
size() <<
"#guide" << starCorrespondence.size();
770 detectedStars.
size() <<
"#guide" << starCorrespondence.size();
775void GuideStars::setCalibration(
const Calibration &
cal)
778 calibrationInitialized =
true;
qsizetype size() const const
bool isValid() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QTextStream & center(QTextStream &stream)