Refining platesolving

This commit is contained in:
2024-10-01 17:37:34 +02:00
parent da1aa4c6fc
commit 9f4c4c8bdc
6 changed files with 158 additions and 17 deletions
+3 -2
View File
@@ -72,7 +72,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
infoDock->setWidget(m_info);
infoDock->setObjectName("infoDock");
addDockWidget(Qt::LeftDockWidgetArea, infoDock);
resize(800, 600);
resize(1024, 600);
setStatusBar(new QStatusBar(this));
m_database = new Database(this);
@@ -111,6 +111,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
#ifdef PLATESOLVER
_plateSolving = new PlateSolving(this);
addDockWidget(Qt::RightDockWidgetArea, _plateSolving);
_plateSolving->hide();
#endif
addToolBar(Qt::TopToolBarArea, m_stretchPanel);
@@ -268,7 +269,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
helpMenu->addAction(tr("Help"), QKeySequence::HelpContents, [this]{ HelpDialog help(this); help.exec(); });
helpMenu->addAction(tr("About Tenmon"), [this]{ About about(this); about.exec(); });
helpMenu->addAction(tr("About Qt"), [this](){ QMessageBox::aboutQt(this); });
helpMenu->addAction(tr("Check update"), this, &MainWindow::checkNewVersion);
helpMenu->addAction(tr("Check for update"), this, &MainWindow::checkNewVersion);
setupSigterm();
QSettings settings;
+2 -2
View File
@@ -81,7 +81,7 @@ void PlateSolving::extractionDone()
}
_ui->stars->setText(QString::number(stars.size()));
_ui->hfr->setText(QString("%1 %2x%3").arg(hfr).arg(a).arg(b));
_ui->hfr->setText(QString("%1 Ecc:%2").arg(hfr).arg(std::sqrt(1 - (b*b)/(a*a))));
_ui->log->appendPlainText(QString("Extraction finished in %1 ms").arg(_solvingTime.elapsed()));
_ui->solveButton->setDisabled(false);
@@ -180,7 +180,7 @@ void PlateSolving::imageLoaded(Image *image)
_ui->scaleUnit->setCurrentIndex(2);
_ui->fovLow->setValue(pointScale.scaleLow);
_ui->fovHigh->setValue(pointScale.scaleHigh);
_ui->usePosition->setChecked(true);
_ui->useScale->setChecked(true);
}
else
{
+119
View File
@@ -9,6 +9,7 @@
#include "batchprocessing.h"
#include <fitsio2.h>
#include "libXISF/libxisf.h"
#include "solver.h"
namespace Script
{
@@ -25,6 +26,8 @@ ScriptEngine::ScriptEngine(BatchProcessing *parent)
_jsEngine->globalObject().setProperty("FITSRecordModify", fitsRecordObject);
_database->init(QLatin1String("scriptengine"));
_semaphore.release(_pool->maxThreadCount());
_solver = new Solver(this);
}
void ScriptEngine::setParams(const QString &scriptPath, const QList<QPair<QString, QString>> &paths, const QString &outputDir)
@@ -46,6 +49,7 @@ const QString &ScriptEngine::outputDir() const
void ScriptEngine::interrupt()
{
_solver->abort();
_jsEngine->setInterrupted(true);
}
@@ -118,6 +122,25 @@ QJSValue ScriptEngine::getItem(const QStringList &items, const QString &label, i
return ret;
}
void ScriptEngine::setStartingSolution(const QJSValue &solution)
{
if(solution.isObject())
{
if(solution.hasProperty("ra") && solution.hasProperty("dec") && solution.property("ra").isNumber() && solution.property("dec").isNumber())
_solver->setSearchPosition(solution.property("ra").toNumber(), solution.property("dec").toNumber());
if(solution.hasProperty("pixscale") && solution.property("pixscale").isNumber())
{
double scale = solution.property("pixscale").toNumber();
_solver->setSearchScale(scale * 0.8, scale * 1.2, SSolver::ScaleUnits::ARCSEC_PER_PIX);
}
}
else
{
_solver->clearStartingPositionAndScale();
}
}
bool ScriptEngine::convert(File *file, QString &outpath, const QString &format, const QVariantMap &params, bool async)
{
QString path;
@@ -151,6 +174,86 @@ bool ScriptEngine::convert(File *file, QString &outpath, const QString &format,
return true;
}
QJSValue ScriptEngine::solveImage(File *file, bool updateHeader)
{
QString path = file->absoluteFilePath();
QJSValue ret = newObject();
if(_solver->loadImage(path))
{
if(_solver->solveImage(true))
{
auto solution = _solver->getSolution();
ret.setProperty("fieldWidth", solution.fieldWidth);
ret.setProperty("fieldHeight", solution.fieldHeight);
ret.setProperty("ra", solution.ra);
ret.setProperty("dec", solution.dec);
ret.setProperty("orientation", solution.orientation);
ret.setProperty("pixscale", solution.pixscale);
ret.setProperty("parity", solution.parity == FITSImage::Parity::POSITIVE);
ret.setProperty("raError", solution.raError);
ret.setProperty("decError", solution.decError);
if(updateHeader)
{
QString error;
if(!_solver->updateHeader(error))
logError(error);
}
}
else
{
logError("Failed to plate solve image " + path);
}
}
else
{
logError("Failed to load image " + path);
}
return ret;
}
QJSValue ScriptEngine::extractStars(File *file, bool hfr)
{
QJSValue ret;
QString path = file->absoluteFilePath();
if(_solver->loadImage(path))
{
if(_solver->extractSources(hfr, true))
{
auto stars = _solver->getStars();
ret = newArray(stars.size());
int i = 0;
for(auto &star : stars)
{
QJSValue starj = newObject();
starj.setProperty("x", star.x);
starj.setProperty("y", star.y);
starj.setProperty("mag", star.mag);
starj.setProperty("flux", star.flux);
starj.setProperty("peak", star.peak);
starj.setProperty("HFR", star.HFR);
starj.setProperty("a", star.a);
starj.setProperty("b", star.b);
starj.setProperty("theta", star.theta);
starj.setProperty("ra", star.ra);
starj.setProperty("dec", star.dec);
starj.setProperty("numPixels", star.numPixels);
ret.setProperty(i++, starj);
}
}
else
{
logError("Failed to extract sources from " + path);
}
}
else
{
logError("Failed to load image " + path);
}
return ret;
}
QJSValue ScriptEngine::newObject()
{
return _jsEngine->newObject();
@@ -579,6 +682,22 @@ QJSValue File::stats()
return _stats;
}
QJSValue File::solve(bool updateHeader)
{
if(_solution.isUndefined() || updateHeader)
_solution = _engine->solveImage(this, updateHeader);
return _solution;
}
QJSValue File::extractStars(bool hfr)
{
if(_stars.isUndefined())
_stars = _engine->extractStars(this, hfr);
return _stars;
}
ScriptEngineThread::ScriptEngineThread(BatchProcessing *parent) : QObject(parent)
{
_thread = new QThread();
+9
View File
@@ -11,6 +11,7 @@
#include "imageinfo.h"
class BatchProcessing;
class Solver;
namespace Script
{
@@ -28,6 +29,7 @@ class ScriptEngine : public QObject
QString _scriptPath;
QString _outputDir;
QList<QPair<QString, QString>> _paths;
Solver *_solver;
public:
explicit ScriptEngine(BatchProcessing *parent = nullptr);
void setParams(const QString &scriptPath, const QList<QPair<QString, QString>> &paths, const QString &outputDir);
@@ -45,7 +47,10 @@ public:
Q_INVOKABLE QJSValue getInt(const QString &label = QString(), int value = 0);
Q_INVOKABLE QJSValue getFloat(const QString &label = QString(), double value = 0, int decimals = 3) const;
Q_INVOKABLE QJSValue getItem(const QStringList &items, const QString &label = "", int current = 0) const;
Q_INVOKABLE void setStartingSolution(const QJSValue &solution = QJSValue());
bool convert(File *file, QString &outpath, const QString &format, const QVariantMap &params, bool async);
QJSValue solveImage(File *file, bool updateHeader);
QJSValue extractStars(File *file, bool hfr);
QJSValue newObject();
QJSValue newArray(uint size);
public slots:
@@ -86,6 +91,8 @@ class File : public QObject
void loadFitsKeywords();
bool mkpath(const QString &path) const;
QJSValue _stats;
QJSValue _solution;
QJSValue _stars;
public:
explicit File(const QString &path, ScriptEngine *engine);
explicit File(const QString &path, const QString &root, ScriptEngine *engine);
@@ -109,6 +116,8 @@ public:
Q_INVOKABLE File* convert(const QString &outpath, const QString &format, const QVariantMap &params = QVariantMap());
Q_INVOKABLE File* convertAsync(const QString &outpath, const QString &format, const QVariantMap &params = QVariantMap());
Q_INVOKABLE QJSValue stats();
Q_INVOKABLE QJSValue solve(bool updateHeader = false);
Q_INVOKABLE QJSValue extractStars(bool hfr);
};
class FITSRecordModify : public QObject
+22 -11
View File
@@ -3,6 +3,7 @@
#include <QJsonDocument>
#include <fitsio.h>
#include <QStandardPaths>
#include <QSettings>
#include <wcslib/wcshdr.h>
#include <wcslib/wcsutil.h>
#include "rawimage.h"
@@ -15,8 +16,11 @@ Solver::Solver(QObject *parent) : QObject(parent)
connect(_solver, &StellarSolver::logOutput, this, &Solver::logOutput);
_solver->setProperty("ProcessType", SSolver::SOLVE);
_solver->setIndexFolderPaths(QStringList(getTenmonIndexPath()));
_solver->setParameterProfile(SSolver::Parameters::ALL_STARS);
QSettings settings;
setIndexFolder(settings.value("platesolving/indexPath", Solver::getTenmonIndexPath()).toString());
int profileIdx = settings.value("platesolving/profile", 0).toInt();
auto profiles = _solver->getBuiltInProfiles();
_solver->setParameters(profiles[profileIdx]);
connect(_solver, &StellarSolver::finished, this, &Solver::finished);
}
@@ -32,12 +36,14 @@ void Solver::setIndexFolder(const QString &indexPath)
bool Solver::loadImage(const QString &path)
{
if(path == _path)return true;
_loaded = false;
std::shared_ptr<RawImage> image;
ImageInfoData info;
if(::loadImage(path, info, image, true))
{
loadImage(image, path);
return loadImage(image, path);
}
return false;
}
@@ -85,25 +91,27 @@ bool Solver::loadImage(std::shared_ptr<RawImage> &image, const QString &path)
return _loaded;
}
bool Solver::solveImage()
bool Solver::solveImage(bool sync)
{
if(_loaded && !_solver->isRunning())
{
_process = SSolver::ProcessType::SOLVE;
_solver->setProperty("ProcessType", _process);
_solver->start();
if(sync)return _solver->solve();
else _solver->start();
return true;
}
return false;
}
bool Solver::extractSources(bool hfr)
bool Solver::extractSources(bool hfr, bool sync)
{
if(_loaded && !_solver->isRunning())
{
_process = hfr ? SSolver::ProcessType::EXTRACT_WITH_HFR : SSolver::ProcessType::EXTRACT;
_solver->setProperty("ProcessType", _process);
_solver->start();
if(sync)return _solver->extract(hfr);
else _solver->start();
return true;
}
return false;
@@ -161,6 +169,7 @@ bool Solver::updateHeader(QString &error)
Script::File file(_path, nullptr);
Script::FITSRecordModify modify;
modify.removeKeyword("RADECSYS");
modify.updateKeyword("CRPIX1", _stats.width / 2.0, QByteArray("x pixel coordinate of the reference point"));
modify.updateKeyword("CRPIX2", _stats.height / 2.0, QByteArray("y pixel coordinate of the reference point"));
modify.updateKeyword("CDELT1", cdeltx, QByteArray("X pixel size (deg)"));
@@ -185,18 +194,14 @@ bool Solver::updateHeader(QString &error)
void Solver::setParameters(Parameters::ParametersProfile profile)
{
auto profileParam = _solver->getBuiltInProfiles().at(profile);
// TODO seems like any paralel is crashing with Qt6
profileParam.partition = false;
//profileParam.inParallel = false;
_solver->setParameters(profileParam);
}
void Solver::setParameters(const Parameters &parameters)
{
auto profile = parameters;
// TODO seems like any paralel is crashing with Qt6
profile.partition = false;
//profile.inParallel = false;
_solver->setParameters(profile);
}
@@ -210,6 +215,12 @@ void Solver::setSearchPosition(double ra, double dec)
_solver->setSearchPositionRaDec(ra, dec);
}
void Solver::clearStartingPositionAndScale()
{
_solver->clearSearchPosition();
_solver->clearSearchScale();
}
QStringList Solver::getIndexPaths()
{
QStringList paths = StellarSolver::getDefaultIndexFolderPaths();
+3 -2
View File
@@ -23,8 +23,8 @@ public:
bool loadImage(const QString &path);
bool loadImage(std::shared_ptr<RawImage> &image, const QString &path);
bool solveImage();
bool extractSources(bool hfr);
bool solveImage(bool sync = false);
bool extractSources(bool hfr, bool sync = false);
void abort();
const FITSImage::Solution& getSolution() const;
const QList<FITSImage::Star>& getStars() const;
@@ -36,6 +36,7 @@ public:
void setParameters(const SSolver::Parameters &parameters);
void setSearchScale(double fovLow, double fowHigh, ScaleUnits units);
void setSearchPosition(double ra, double dec);
void clearStartingPositionAndScale();
static QStringList getIndexPaths();
static QString getTenmonIndexPath();