Kstars

solverutils.cpp
1 /*
2  SPDX-FileCopyrightText: 2022 Hy Murveit <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "solverutils.h"
8 
9 #include "fitsviewer/fitsdata.h"
10 #include "Options.h"
11 #include <QRegularExpression>
12 #include <QUuid>
13 
14 SolverUtils::SolverUtils(const SSolver::Parameters &parameters, double timeoutSeconds) : m_Parameters(parameters),
15  m_TimeoutMilliseconds(timeoutSeconds * 1000.0)
16 {
17  connect(&m_Watcher, &QFutureWatcher<bool>::finished, this, &SolverUtils::executeSolver, Qt::UniqueConnection);
18  connect(&m_SolverTimer, &QTimer::timeout, this, &SolverUtils::solverTimeout, Qt::UniqueConnection);
19 
20  m_StellarSolver.reset(new StellarSolver());
21  // connect(m_StellarSolver.get(), &StellarSolver::logOutput, this, &SolverUtils::newLog);
22 }
23 
24 SolverUtils::~SolverUtils()
25 {
26  disconnect(&m_Watcher, &QFutureWatcher<bool>::finished, this, &SolverUtils::executeSolver);
27  disconnect(&m_SolverTimer, &QTimer::timeout, this, &SolverUtils::solverTimeout);
28  if (m_StellarSolver.get())
29  {
30  // disconnect(m_StellarSolver.get(), &StellarSolver::logOutput, this, &SolverUtils::newLog);
31  disconnect(m_StellarSolver.get(), &StellarSolver::finished, this, &SolverUtils::solverDone);
32  }
33 }
34 
35 void SolverUtils::executeSolver()
36 {
37  runSolver(m_ImageData);
38 }
39 
40 void SolverUtils::runSolver(const QString &filename)
41 {
42  m_ImageData.reset(new FITSData(), &QObject::deleteLater);
43  QFuture<bool> response = m_ImageData->loadFromFile(filename);
44  m_Watcher.setFuture(response);
45 }
46 
47 void SolverUtils::setHealpix(int indexToUse, int healpixToUse)
48 {
49  m_IndexToUse = indexToUse;
50  m_HealpixToUse = healpixToUse;
51 }
52 
53 void SolverUtils::abort()
54 {
55  if (m_StellarSolver.get()) m_StellarSolver->abort();
56 }
57 
58 bool SolverUtils::isRunning() const
59 {
60  if (!m_StellarSolver.get()) return false;
61  return m_StellarSolver->isRunning();
62 }
63 
64 void SolverUtils::getSolutionHealpix(int *indexUsed, int *healpixUsed) const
65 {
66  *indexUsed = m_StellarSolver->getSolutionIndexNumber();
67  *healpixUsed = m_StellarSolver->getSolutionHealpix();
68 }
69 
70 
71 void SolverUtils::prepareSolver()
72 {
73  if (m_StellarSolver->isRunning())
74  m_StellarSolver->abort();
75  m_StellarSolver->setProperty("ProcessType", SSolver::SOLVE);
76  m_StellarSolver->loadNewImageBuffer(m_ImageData->getStatistics(), m_ImageData->getImageBuffer());
77  m_StellarSolver->setProperty("ExtractorType", Options::solveSextractorType());
78  m_StellarSolver->setProperty("SolverType", Options::solverType());
79  connect(m_StellarSolver.get(), &StellarSolver::finished, this, &SolverUtils::solverDone, Qt::UniqueConnection);
80 
81  if (m_IndexToUse >= 0)
82  {
83  // The would only have an effect if Options::solverType() == SOLVER_STELLARSOLVER
84  QStringList indexFiles = StellarSolver::getIndexFiles(
85  Options::astrometryIndexFolderList(), m_IndexToUse, m_HealpixToUse);
86  m_StellarSolver->setIndexFilePaths(indexFiles);
87  }
88  else
89  m_StellarSolver->setIndexFolderPaths(Options::astrometryIndexFolderList());
90 
91  // External program paths
92  ExternalProgramPaths externalPaths;
93  externalPaths.sextractorBinaryPath = Options::sextractorBinary();
94  externalPaths.solverPath = Options::astrometrySolverBinary();
95  externalPaths.astapBinaryPath = Options::aSTAPExecutable();
96  externalPaths.watneyBinaryPath = Options::watneyBinary();
97  externalPaths.wcsPath = Options::astrometryWCSInfo();
98  m_StellarSolver->setExternalFilePaths(externalPaths);
99 
100  //No need for a conf file this way.
101  m_StellarSolver->setProperty("AutoGenerateAstroConfig", true);
102 
103  auto params = m_Parameters;
104  params.partition = Options::stellarSolverPartition();
105  m_StellarSolver->setParameters(params);
106 
107  m_TemporaryFilename.clear();
108 
109  const SSolver::SolverType type = static_cast<SSolver::SolverType>(m_StellarSolver->property("SolverType").toInt());
110  if(type == SSolver::SOLVER_LOCALASTROMETRY || type == SSolver::SOLVER_ASTAP || type == SSolver::SOLVER_WATNEYASTROMETRY)
111  {
112  m_TemporaryFilename = QDir::tempPath() + QString("/solver%1.fits").arg(QUuid::createUuid().toString().remove(
113  QRegularExpression("[-{}]")));
114  m_ImageData->saveImage(m_TemporaryFilename);
115  m_StellarSolver->setProperty("FileToProcess", m_TemporaryFilename);
116  }
117  else if (type == SSolver::SOLVER_ONLINEASTROMETRY )
118  {
119  m_TemporaryFilename = QDir::tempPath() + QString("/solver%1.fits").arg(QUuid::createUuid().toString().remove(
120  QRegularExpression("[-{}]")));
121  m_ImageData->saveImage(m_TemporaryFilename);
122  m_StellarSolver->setProperty("FileToProcess", m_TemporaryFilename);
123  m_StellarSolver->setProperty("AstrometryAPIKey", Options::astrometryAPIKey());
124  m_StellarSolver->setProperty("AstrometryAPIURL", Options::astrometryAPIURL());
125  }
126 
127  if (m_UseScale)
128  {
129  SSolver::ScaleUnits units = static_cast<SSolver::ScaleUnits>(Options::astrometryImageScaleUnits());
130  // Extend search scale from 80% to 120%
131  m_StellarSolver->setSearchScale(m_ScaleLowArcsecPerPixel * 0.8,
132  m_ScaleHighArcsecPerPixel * 1.2,
133  units);
134  }
135  else
136  m_StellarSolver->setProperty("UseScale", false);
137 
138  if (m_UsePosition)
139  m_StellarSolver->setSearchPositionInDegrees(m_raDegrees, m_decDegrees);
140  else
141  m_StellarSolver->setProperty("UsePosition", false);
142 
143  // LOG_ALL is crashy now
144  m_StellarSolver->setLogLevel(SSolver::LOG_NONE);
145  m_StellarSolver->setSSLogLevel(SSolver::LOG_OFF);
146 }
147 
148 void SolverUtils::runSolver(const QSharedPointer<FITSData> &data)
149 {
150  // Limit the time the solver can run.
151  m_SolverTimer.setSingleShot(true);
152  m_SolverTimer.setInterval(m_TimeoutMilliseconds);
153  m_SolverTimer.start();
154  // Somehow m_SolverTimer's elapsed time can be greater than the interval,
155  // so using this to get more exact times.
156  m_StartTime = QDateTime::currentMSecsSinceEpoch();
157 
158  m_ImageData = data;
159  prepareSolver();
160  m_StellarSolver->start();
161 }
162 
163 SolverUtils &SolverUtils::useScale(bool useIt, double scaleLowArcsecPerPixel, double scaleHighArcsecPerPixel)
164 {
165  m_UseScale = useIt;
166  m_ScaleLowArcsecPerPixel = scaleLowArcsecPerPixel;
167  m_ScaleHighArcsecPerPixel = scaleHighArcsecPerPixel;
168  return *this;
169 }
170 
171 SolverUtils &SolverUtils::usePosition(bool useIt, double raDegrees, double decDegrees)
172 {
173  m_UsePosition = useIt;
174  m_raDegrees = raDegrees;
175  m_decDegrees = decDegrees;
176  return *this;
177 }
178 
179 void SolverUtils::solverDone()
180 {
181  const double elapsed = (QDateTime::currentMSecsSinceEpoch() - m_StartTime) / 1000.0;
182  m_SolverTimer.stop();
183 
184  FITSImage::Solution solution;
185  bool success = m_StellarSolver->solvingDone() && !m_StellarSolver->failed();
186  if (success)
187  solution = m_StellarSolver->getSolution();
188  emit done(false, success, solution, elapsed);
189 
190  if (!m_TemporaryFilename.isEmpty())
191  QFile::remove(m_TemporaryFilename);
192  m_TemporaryFilename.clear();
193 }
194 
195 void SolverUtils::solverTimeout()
196 {
197  m_SolverTimer.stop();
198  FITSImage::Solution empty;
199  emit done(true, false, empty, m_TimeoutMilliseconds / 1000.0);
200 
201  if (!m_TemporaryFilename.isEmpty())
202  QFile::remove(m_TemporaryFilename);
203  m_TemporaryFilename.clear();
204 }
205 
206 double SolverUtils::rotationToPositionAngle(double value)
207 {
208  double pa = value + 180;
209  while (pa > 180)
210  pa -= 360;
211  while (pa < -180)
212  pa += 360;
213  return pa;
214 }
215 
216 double SolverUtils::positionAngleToRotation(double value)
217 {
218  double rotation = value - 180;
219  while (rotation > 180)
220  rotation -= 360;
221  while (rotation < -180)
222  rotation += 360;
223  return rotation;
224 }
225 
226 double SolverUtils::rangePA(double pa)
227 {
228  while (pa > 180)
229  pa -= 360;
230  while (pa < -180)
231  pa += 360;
232  return pa;
233 }
bool remove()
Type type(const QSqlDatabase &db)
qint64 currentMSecsSinceEpoch()
QString tempPath()
void deleteLater()
char * toString(const T &value)
void timeout()
QUuid createUuid()
UniqueConnection
KGuiItem remove()
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isRunning() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Aug 13 2022 04:02:00 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.