Adding platesolving

This commit is contained in:
2024-09-30 18:39:35 +02:00
parent dccb2e88da
commit 32973c54ce
16 changed files with 1075 additions and 210 deletions
+1
View File
@@ -101,6 +101,7 @@ if(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB)
target_sources(tenmon PRIVATE target_sources(tenmon PRIVATE
solver.cpp solver.h solver.cpp solver.h
platesolving.cpp platesolving.h platesolving.ui platesolving.cpp platesolving.h platesolving.ui
platesolvingsettings.cpp platesolvingsettings.h platesolvingsettings.ui
) )
endif(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB) endif(STELLARSOLVER_INCLUDE AND STELLARSOLVER_LIB)
+56 -22
View File
@@ -2,7 +2,11 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QDebug> #include <QDebug>
#include <QRegularExpression> #include <QRegularExpression>
#include <QFileInfo>
#ifdef PLATESOLVER
#include "solver.h" #include "solver.h"
#endif
// filename arcseconds range // filename arcseconds range
// index-4119.fits 14002000 // index-4119.fits 14002000
@@ -135,7 +139,7 @@ static const QMap<QString, QByteArray> md5 = {
{"index-5202-45.fits.zst", "83fe2cff3cf65317f5c1bf7b953519e9"}, {"index-5202-45.fits.zst", "83fe2cff3cf65317f5c1bf7b953519e9"},
{"index-5202-46.fits.zst", "f12f308a3b53d95ffd7bc420700e4f44"}, {"index-5202-46.fits.zst", "f12f308a3b53d95ffd7bc420700e4f44"},
{"index-5202-47.fits.zst", "608a14303810c9762b25fc68896d2a26"}, {"index-5202-47.fits.zst", "608a14303810c9762b25fc68896d2a26"},
{"index-5203-00.fits.zst", "155217faa535550c1d7e499145750bb0"}, {"index-5203-00.fits.zst", "2862efb33765b7bbefb635dcad970298"},
{"index-5203-01.fits.zst", "2cd34cef4b44ad1e770396baccb2a46c"}, {"index-5203-01.fits.zst", "2cd34cef4b44ad1e770396baccb2a46c"},
{"index-5203-02.fits.zst", "40c9f67282210cc374281cde023c4e71"}, {"index-5203-02.fits.zst", "40c9f67282210cc374281cde023c4e71"},
{"index-5203-03.fits.zst", "c8f40e164ec3ce1df92e3a121a127716"}, {"index-5203-03.fits.zst", "c8f40e164ec3ce1df92e3a121a127716"},
@@ -368,20 +372,32 @@ void Download::readData()
void Download::finished() void Download::finished()
{ {
QByteArray data = _reply->readAll(); if(_reply->error() == QNetworkReply::NoError)
qDebug() << "finished" << data.size();
decompress(data);
if(md5.contains(_reply->url().fileName()))
{ {
if(_hash.result().toHex() == md5[_reply->url().fileName()]) QByteArray data = _reply->readAll();
qDebug() << "DOWNLOAD OK"; qDebug() << "finished" << data.size();
else decompress(data);
qDebug() << "DOWNLOAD BAD";
}
_fw.flush(); if(md5.contains(_reply->url().fileName()))
_fw.close(); {
if(_hash.result().toHex() == md5[_reply->url().fileName()])
qDebug() << "DOWNLOAD OK";
else
{
qDebug() << "DOWNLOAD BAD";
_fw.remove();
return;
}
}
_fw.flush();
_fw.close();
}
else
{
qDebug() << "Failed to perform http request" << _reply->url();
_fw.remove();
}
} }
void Download::decompress(QByteArray &data) void Download::decompress(QByteArray &data)
@@ -413,7 +429,9 @@ void Download::decompress(QByteArray &data)
HttpDownloader::HttpDownloader(QObject *parent) : QObject(parent) HttpDownloader::HttpDownloader(QObject *parent) : QObject(parent)
,_manager(new QNetworkAccessManager(this)) ,_manager(new QNetworkAccessManager(this))
{ {
_manager->setAutoDeleteReplies(true);
connect(_manager, &QNetworkAccessManager::finished, this, &HttpDownloader::finished); connect(_manager, &QNetworkAccessManager::finished, this, &HttpDownloader::finished);
#ifdef PLATESOLVER
QDir dir(Solver::getTenmonIndexPath()); QDir dir(Solver::getTenmonIndexPath());
if(!dir.exists()) if(!dir.exists())
{ {
@@ -422,6 +440,7 @@ HttpDownloader::HttpDownloader(QObject *parent) : QObject(parent)
} }
_indexPath = dir.absolutePath(); _indexPath = dir.absolutePath();
#endif
} }
void HttpDownloader::download(const QUrl &url) void HttpDownloader::download(const QUrl &url)
@@ -437,17 +456,17 @@ bool HttpDownloader::downloadIndex(int scale)
return false; return false;
QUrl url("https://nouspiro.space/"); QUrl url("https://nouspiro.space/");
QStringList files = indexFileNames(scale);
if(scale >= 7) for(auto &file : files)
{ {
url.setPath(QString("/astrometry/index-%1.fits.zst").arg(4100 + scale)); if(QFile::exists(_indexPath + "/" + file))
download(url);
}
else
{
for(int i=0; i<48; i++)
{ {
url.setPath(QString("/astrometry/index-%1-%2.fits.zst").arg(5200 + scale).arg(i, 2, 10, QChar('0'))); qDebug() << "File already exists, skipping" << file;
}
else
{
url.setPath("/astrometry/" + file + ".zst");
download(url); download(url);
} }
} }
@@ -460,6 +479,22 @@ void HttpDownloader::abort()
_download->abort(); _download->abort();
} }
QStringList HttpDownloader::indexFileNames(int scale)
{
QStringList ret;
if(scale >= 7)
{
ret.append(QString("index-%1.fits").arg(4100 + scale));
}
else
{
for(int i=0; i<48; i++)
ret.append(QString("index-%1-%2.fits").arg(5200 + scale).arg(i, 2, 10, QChar('0')));
}
return ret;
}
void HttpDownloader::finished() void HttpDownloader::finished()
{ {
if(_queue.isEmpty()) if(_queue.isEmpty())
@@ -478,7 +513,6 @@ void HttpDownloader::finished()
return; return;
} }
QNetworkRequest request(url); QNetworkRequest request(url);
_download->deleteLater();
_download = new Download(_manager->get(request), _indexPath, this); _download = new Download(_manager->get(request), _indexPath, this);
connect(_download, &Download::progress, this, &HttpDownloader::updateProgress); connect(_download, &Download::progress, this, &HttpDownloader::updateProgress);
} }
+1
View File
@@ -41,6 +41,7 @@ public:
// scale in range 19-1 // scale in range 19-1
bool downloadIndex(int scale); bool downloadIndex(int scale);
void abort(); void abort();
static QStringList indexFileNames(int scale);
signals: signals:
void progress(int percent, int files); void progress(int percent, int files);
protected slots: protected slots:
+142
View File
@@ -257,6 +257,33 @@ void WCSDataT::calculateBounds(double &minRa, double &maxRa, double &minDec, dou
} }
} }
double hav(double x)
{
return (1.0 - std::cos(x)) * 0.5;
}
double haverSine(const SkyPoint &a, SkyPoint &b)
{
const double ToRAD = M_PI / 180.0;
double d = hav((a.DEC() - b.DEC()) * ToRAD) + std::cos(a.DEC() * ToRAD) * std::cos(b.DEC() * ToRAD) * hav((a.RA() - b.RA()) * ToRAD);
return std::acos(1.0 - 2.0 * d) * (180.0 / M_PI);
}
SkyPointScale WCSDataT::getRaDecScale() const
{
SkyPointScale ret;
pixelToWorld(QPointF(width/2.0, height/2.0), ret.point);
SkyPoint pointX;
SkyPoint pointY;
pixelToWorld(QPointF(width/2.0+1, height/2.0), pointX);
pixelToWorld(QPointF(width/2.0, height/2.0+1), pointY);
double scaleX = haverSine(ret.point, pointX) * 3600.0;
double scaleY = haverSine(ret.point, pointY) * 3600.0;
ret.scaleLow = std::min(scaleX, scaleY);
ret.scaleHigh = std::max(scaleX, scaleY);
return ret;
}
SkyPoint::SkyPoint() : ra(NAN), dec(NAN) SkyPoint::SkyPoint() : ra(NAN), dec(NAN)
{ {
} }
@@ -284,3 +311,118 @@ QString SkyPoint::toString() const
sec = std::modf(min, &min) * 60; sec = std::modf(min, &min) * 60;
return QString("RA: %1 DEC: %2° %3' %4\"").arg(t.toString("HH'h' mm'm' ss's'")).arg(deg, 2, 'f', 0, '0').arg(min, 2, 'f', 0, '0').arg(sec, 2, 'f', 0, '0'); return QString("RA: %1 DEC: %2° %3' %4\"").arg(t.toString("HH'h' mm'm' ss's'")).arg(deg, 2, 'f', 0, '0').arg(min, 2, 'f', 0, '0').arg(sec, 2, 'f', 0, '0');
} }
double SkyPoint::fromHMS(const QString &hms)
{
double deg = fromDMS(hms);
if(std::isnan(deg))return deg;
return deg * 15.0;
}
double SkyPoint::fromDMS(const QString &dms)
{
double deg = 0.0;
QString str = dms.trimmed();
str.remove(QRegularExpression("[hdms°'\"]"));
str.replace(':', ' ');
str.replace(QRegularExpression("\\s+"), " ");
QStringList fields = str.split(' ');
double sign = 1.0;
bool ok = false;
if(fields.size() >= 1)
deg = fields.at(0).toDouble(&ok);
if(!ok)return NAN;
if(deg < 0.0)
sign = -1.0;
if(fields.size() >= 2)
deg += sign * fields.at(1).toDouble() / 60.0;
if(fields.size() >= 3)
deg += sign * fields.at(2).toDouble() / 3600.0;
return deg;
}
SkyPointScale ImageInfoData::getCenterRaDec() const
{
SkyPointScale ret;
if(wcs && wcs->valid())
{
ret = wcs->getRaDecScale();
}
else
{
double ra,dec,focalLen,scale,pixSizeX,pixSizeY;
int binX = 1;
int binY = 1;
ra = dec = focalLen = scale = pixSizeX = pixSizeY = NAN;
bool ok;
for(const FITSRecord &header : fitsHeader)
{
if(header.key == "OBJCTRA")
{
double tmp = SkyPoint::fromHMS(header.value.toString());
if(!std::isnan(tmp))ra = tmp;
}
else if(header.key == "RA" && std::isnan(ra))
{
double tmp = header.value.toDouble(&ok);
if(ok)ra = tmp;
}
else if(header.key == "OBJCTDEC")
{
double tmp = SkyPoint::fromDMS(header.value.toString());
if(!std::isnan(tmp))dec = tmp;
}
else if(header.key == "DEC" && std::isnan(dec))
{
double tmp = SkyPoint::fromDMS(header.value.toString());
if(!std::isnan(tmp))dec = tmp;
}
else if(header.key == "SCALE")
{
double tmp = header.value.toDouble(&ok);
if(ok)scale = tmp;
}
else if(header.key == "FOCALLEN")
{
double tmp = header.value.toDouble(&ok);
if(ok)focalLen = tmp;
}
else if(header.key == "PIXSIZE1" || header.key == "XPIXSZ")
{
pixSizeX = header.value.toDouble();
}
else if(header.key == "PIXSIZE2" || header.key == "YPIXSZ")
{
pixSizeY = header.value.toDouble();
}
else if(header.key == "XBINNING")
{
int tmp = header.value.toInt(&ok);
if(ok)binX = tmp;
}
else if(header.key == "YBINNING")
{
int tmp = header.value.toInt(&ok);
if(ok)binY = tmp;
}
}
ret.point.set(ra, dec);
if(!std::isnan(scale))
{
ret.scaleLow = ret.scaleHigh = scale;
}
else if(!(std::isnan(focalLen) || std::isnan(pixSizeX) || std::isnan(pixSizeY)))
{
const double r = 206.2648097656; // (180 * 3600) / (1000 * pi) magic number to convert pixel size to focal length ratio to arcsec.
ret.scaleLow = std::min(pixSizeX * binX / focalLen * r, pixSizeY * binY / focalLen * r);
ret.scaleHigh = std::max(pixSizeX * binX / focalLen * r, pixSizeY * binY / focalLen * r);
}
}
ret.scaleLow *= 0.8;
ret.scaleHigh *= 1.2;
return ret;
}
+13
View File
@@ -31,8 +31,19 @@ public:
SkyPoint(double ra, double dec); SkyPoint(double ra, double dec);
void set(double ra, double dec); void set(double ra, double dec);
double RA() const { return ra; } double RA() const { return ra; }
double RAHour() const { return ra / 15.0; }
double DEC() const { return dec; } double DEC() const { return dec; }
QString toString() const; QString toString() const;
static double fromHMS(const QString &hms);
static double fromDMS(const QString &dms);
};
struct SkyPointScale
{
SkyPoint point;
//arcsec per pixel
double scaleLow = 0.0;
double scaleHigh = 10000.0;
}; };
class WCSDataT class WCSDataT
@@ -51,6 +62,7 @@ public:
bool worldToPixel(const SkyPoint &point, QPointF &pixel) const; bool worldToPixel(const SkyPoint &point, QPointF &pixel) const;
void calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const; void calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const;
bool valid() const { return wcs; }; bool valid() const { return wcs; };
SkyPointScale getRaDecScale() const;
}; };
struct ImageInfoData struct ImageInfoData
@@ -58,6 +70,7 @@ struct ImageInfoData
QVector<FITSRecord> fitsHeader; QVector<FITSRecord> fitsHeader;
QVector<QPair<QString, QString>> info; QVector<QPair<QString, QString>> info;
std::shared_ptr<WCSDataT> wcs; std::shared_ptr<WCSDataT> wcs;
SkyPointScale getCenterRaDec() const;
}; };
Q_DECLARE_METATYPE(ImageInfoData); Q_DECLARE_METATYPE(ImageInfoData);
+6
View File
@@ -108,8 +108,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
m_databaseView = new DataBaseView(m_database, this); m_databaseView = new DataBaseView(m_database, this);
connect(m_databaseView, SIGNAL(loadFile(QString)), this, SLOT(loadFile(QString))); connect(m_databaseView, SIGNAL(loadFile(QString)), this, SLOT(loadFile(QString)));
#ifdef PLATESOLVER
_plateSolving = new PlateSolving(this); _plateSolving = new PlateSolving(this);
addDockWidget(Qt::RightDockWidgetArea, _plateSolving); addDockWidget(Qt::RightDockWidgetArea, _plateSolving);
#endif
addToolBar(Qt::TopToolBarArea, m_stretchPanel); addToolBar(Qt::TopToolBarArea, m_stretchPanel);
@@ -146,7 +148,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
connect(m_ringList, &ImageRingList::thumbnailLoaded, m_image, &ImageScrollArea::thumbnailLoaded); connect(m_ringList, &ImageRingList::thumbnailLoaded, m_image, &ImageScrollArea::thumbnailLoaded);
connect(m_ringList, &ImageRingList::pixmapLoaded, m_stretchPanel, &StretchToolbar::imageLoaded); connect(m_ringList, &ImageRingList::pixmapLoaded, m_stretchPanel, &StretchToolbar::imageLoaded);
connect(m_ringList, &ImageRingList::pixmapLoaded, histogram, &Histogram::imageLoaded); connect(m_ringList, &ImageRingList::pixmapLoaded, histogram, &Histogram::imageLoaded);
#ifdef PLATESOLVER
connect(m_ringList, &ImageRingList::pixmapLoaded, _plateSolving, &PlateSolving::imageLoaded); connect(m_ringList, &ImageRingList::pixmapLoaded, _plateSolving, &PlateSolving::imageLoaded);
#endif
connect(m_image, &ImageScrollArea::fileDropped, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile)); connect(m_image, &ImageScrollArea::fileDropped, this, static_cast<void (MainWindow::*)(const QString &)>(&MainWindow::loadFile));
QMenu *fileMenu = new QMenu(tr("File"), this); QMenu *fileMenu = new QMenu(tr("File"), this);
@@ -255,7 +259,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
dockMenu->addAction(databaseViewDock->toggleViewAction()); dockMenu->addAction(databaseViewDock->toggleViewAction());
dockMenu->addAction(filetreeDock->toggleViewAction()); dockMenu->addAction(filetreeDock->toggleViewAction());
dockMenu->addAction(histogramDock->toggleViewAction()); dockMenu->addAction(histogramDock->toggleViewAction());
#ifdef PLATESOLVER
dockMenu->addAction(_plateSolving->toggleViewAction()); dockMenu->addAction(_plateSolving->toggleViewAction());
#endif
menuBar()->addMenu(dockMenu); menuBar()->addMenu(dockMenu);
QMenu *helpMenu = menuBar()->addMenu(tr("Help")); QMenu *helpMenu = menuBar()->addMenu(tr("Help"));
+93 -34
View File
@@ -1,45 +1,61 @@
#include "platesolving.h" #include "platesolving.h"
#include <QSettings>
#include "ui_platesolving.h" #include "ui_platesolving.h"
#include "solver.h" #include "solver.h"
#include "imageringlist.h" #include "imageringlist.h"
#include "platesolvingsettings.h"
PlateSolving::PlateSolving(QWidget *parent) PlateSolving::PlateSolving(QWidget *parent)
: QDockWidget(parent) : QDockWidget(parent)
, ui(new Ui::PlateSolving) , _ui(new Ui::PlateSolving)
{ {
ui->setupUi(this); _ui->setupUi(this);
_solver = new Solver(this); _solver = new Solver(this);
QSettings settings;
_solver->setIndexFolder(settings.value("platesolving/indexPath", Solver::getTenmonIndexPath()).toString());
auto profiles = StellarSolver::getBuiltInProfiles(); auto profiles = StellarSolver::getBuiltInProfiles();
int profileIdx = settings.value("platesolving/profile", 0).toInt();
_solver->setParameters(profiles[profileIdx]);
for(auto &profile : profiles) for(auto &profile : profiles)
{ {
ui->profileComboBox->addItem(profile.listName); _ui->profileComboBox->addItem(profile.listName);
} }
_ui->profileComboBox->setCurrentIndex(profileIdx);
_ui->scaleUnit->setCurrentIndex(settings.value("platesolving/scaleUnit", 1).toInt());
connect(ui->profileComboBox, &QComboBox::currentIndexChanged, [this](int index){ connect(_ui->profileComboBox, &QComboBox::currentIndexChanged, [this](int index){
auto profiles = StellarSolver::getBuiltInProfiles(); auto profiles = StellarSolver::getBuiltInProfiles();
_solver->setParameters(profiles[index]); _solver->setParameters(profiles[index]);
}); });
connect(ui->extractButton, &QPushButton::clicked, this, &PlateSolving::extract); connect(_ui->extractButton, &QPushButton::clicked, this, &PlateSolving::extract);
connect(ui->solveButton, &QPushButton::clicked, this, &PlateSolving::solve); connect(_ui->solveButton, &QPushButton::clicked, this, &PlateSolving::solve);
connect(_ui->settingsButton, &QPushButton::clicked, this, &PlateSolving::settings);
connect(_solver, &Solver::solvingDone, this, &PlateSolving::solvingDone); connect(_solver, &Solver::solvingDone, this, &PlateSolving::solvingDone);
connect(_solver, &Solver::extractionDone, this, &PlateSolving::extractionDone); connect(_solver, &Solver::extractionDone, this, &PlateSolving::extractionDone);
connect(_solver, &Solver::logOutput, [this](const QString &log){ _ui->log->appendPlainText(log); });
} }
PlateSolving::~PlateSolving() PlateSolving::~PlateSolving()
{ {
delete ui; QSettings settings;
settings.setValue("platesolving/profile", _ui->profileComboBox->currentIndex());
settings.setValue("platesolving/scaleUnit", _ui->scaleUnit->currentIndex());
delete _ui;
} }
void PlateSolving::extract() void PlateSolving::extract()
{ {
ui->solveButton->setDisabled(true); if(!_rawImage)return;
ui->extractButton->setDisabled(true); _ui->solveButton->setDisabled(true);
_ui->extractButton->setDisabled(true);
_ui->log->clear();
_solver->loadImage(_rawImage, _path); _solver->loadImage(_rawImage, _path);
_solver->extractSources(ui->withHFR->isChecked()); _solvingTime.start();
_solver->extractSources(_ui->withHFR->isChecked());
} }
void PlateSolving::extractionDone() void PlateSolving::extractionDone()
@@ -61,49 +77,92 @@ void PlateSolving::extractionDone()
hfr /= size; hfr /= size;
} }
ui->stars->setText(QString::number(stars.size())); _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 %2x%3").arg(hfr).arg(a).arg(b));
_ui->log->appendPlainText(QString("Extraction finished in %1 ms").arg(_solvingTime.elapsed()));
ui->solveButton->setDisabled(false); _ui->solveButton->setDisabled(false);
ui->extractButton->setDisabled(false); _ui->extractButton->setDisabled(false);
} }
void PlateSolving::solve() void PlateSolving::solve()
{ {
ui->solveButton->setDisabled(true); if(!_rawImage)return;
ui->extractButton->setDisabled(true); _ui->solveButton->setDisabled(true);
_ui->extractButton->setDisabled(true);
_ui->log->clear();
_solver->loadImage(_rawImage, _path); _solver->loadImage(_rawImage, _path);
if(_ui->usePosition->isChecked())
_solver->setSearchPosition(_ui->raStart->value(), _ui->decStart->value());
if(_ui->useScale->isChecked())
{
SSolver::ScaleUnits scaleUnit;
switch(_ui->scaleUnit->currentIndex())
{
default:
case 0:
scaleUnit = SSolver::ScaleUnits::DEG_WIDTH; break;
case 1:
scaleUnit = SSolver::ScaleUnits::ARCMIN_WIDTH; break;
case 2:
scaleUnit = SSolver::ScaleUnits::ARCSEC_PER_PIX; break;
case 3:
scaleUnit = SSolver::ScaleUnits::FOCAL_MM; break;
}
_solver->setSearchScale(_ui->fovLow->value(), _ui->fovHigh->value(), scaleUnit);
}
_solvingTime.start();
_solver->solveImage(); _solver->solveImage();
} }
void PlateSolving::solvingDone() void PlateSolving::solvingDone()
{ {
ui->solveButton->setDisabled(false); _ui->solveButton->setDisabled(false);
ui->extractButton->setDisabled(false); _ui->extractButton->setDisabled(false);
auto solution = _solver->getSolution(); auto solution = _solver->getSolution();
ui->ra->setText(QString::number(solution.ra)); _ui->ra->setText(QString::number(solution.ra));
ui->dec->setText(QString::number(solution.dec)); _ui->dec->setText(QString::number(solution.dec));
ui->orientation->setText(QString::number(solution.orientation)); _ui->orientation->setText(QString::number(solution.orientation));
ui->fieldWidth->setText(QString::number(solution.fieldWidth)); _ui->fieldWidth->setText(QString::number(solution.fieldWidth));
ui->fieldHeight->setText(QString::number(solution.fieldHeight)); _ui->fieldHeight->setText(QString::number(solution.fieldHeight));
ui->pixelScale->setText(QString::number(solution.pixscale)); _ui->pixelScale->setText(QString::number(solution.pixscale));
_ui->log->appendPlainText(QString("Solving finished in %1 ms").arg(_solvingTime.elapsed()));
} }
void PlateSolving::imageLoaded(Image *image) void PlateSolving::imageLoaded(Image *image)
{ {
if(image) if(image && image->rawImage())
{ {
_rawImage = image->rawImage(); _rawImage = image->rawImage();
_path = image->name(); _path = image->name();
ui->ra->clear(); _ui->ra->clear();
ui->dec->clear(); _ui->dec->clear();
ui->orientation->clear(); _ui->orientation->clear();
ui->fieldWidth->clear(); _ui->fieldWidth->clear();
ui->fieldHeight->clear(); _ui->fieldHeight->clear();
ui->pixelScale->clear(); _ui->pixelScale->clear();
ui->hfr->clear(); _ui->hfr->clear();
ui->stars->clear(); _ui->stars->clear();
const ImageInfoData &info = image->info();
SkyPointScale pointScale = info.getCenterRaDec();
if(!std::isnan(pointScale.point.RA()) && !std::isnan(pointScale.point.DEC()))
{
_ui->raStart->setValue(pointScale.point.RAHour());
_ui->decStart->setValue(pointScale.point.DEC());
}
_ui->scaleUnit->setCurrentIndex(2);
_ui->fovLow->setValue(pointScale.scaleLow);
_ui->fovHigh->setValue(pointScale.scaleHigh);
} }
} }
void PlateSolving::settings()
{
PlateSolvingSettings settings(this);
settings.exec();
}
+4 -1
View File
@@ -1,6 +1,7 @@
#ifndef PLATESOLVING_H #ifndef PLATESOLVING_H
#define PLATESOLVING_H #define PLATESOLVING_H
#include "qelapsedtimer.h"
#include <QDockWidget> #include <QDockWidget>
class Solver; class Solver;
@@ -17,6 +18,7 @@ class PlateSolving : public QDockWidget
Solver *_solver; Solver *_solver;
std::shared_ptr<RawImage> _rawImage; std::shared_ptr<RawImage> _rawImage;
QString _path; QString _path;
QElapsedTimer _solvingTime;
public: public:
explicit PlateSolving(QWidget *parent = nullptr); explicit PlateSolving(QWidget *parent = nullptr);
~PlateSolving(); ~PlateSolving();
@@ -27,8 +29,9 @@ public slots:
void solve(); void solve();
void solvingDone(); void solvingDone();
void imageLoaded(Image *image); void imageLoaded(Image *image);
void settings();
private: private:
Ui::PlateSolving *ui; Ui::PlateSolving *_ui;
}; };
#endif // PLATESOLVING_H #endif // PLATESOLVING_H
+299 -137
View File
@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>571</width> <width>860</width>
<height>472</height> <height>700</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -30,153 +30,315 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <widget class="QGroupBox" name="groupBox_2">
<item row="1" column="2"> <property name="title">
<widget class="QLabel" name="label_3"> <string>Start point</string>
<property name="text"> </property>
<string>Field height</string> <layout class="QGridLayout" name="gridLayout_3">
</property> <item row="3" column="3">
</widget> <widget class="QComboBox" name="scaleUnit">
</item> <item>
<item row="2" column="2"> <property name="text">
<widget class="QLabel" name="label_7"> <string>Degree width</string>
<property name="text"> </property>
<string>Pixel scale</string> </item>
</property> <item>
</widget> <property name="text">
</item> <string>Arcmin width</string>
<item row="0" column="0"> </property>
<widget class="QLabel" name="label_4"> </item>
<property name="text"> <item>
<string>RA</string> <property name="text">
</property> <string>Arcsec per pixel</string>
</widget> </property>
</item> </item>
<item row="2" column="1"> <item>
<widget class="QLineEdit" name="orientation"> <property name="text">
<property name="readOnly"> <string>35 mm equivalent focal length</string>
<bool>true</bool> </property>
</property> </item>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_6"> <widget class="QCheckBox" name="usePosition">
<property name="text"> <property name="text">
<string>Orientation</string> <string>Use position</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="4" column="3">
<widget class="QLabel" name="label_5"> <widget class="QDoubleSpinBox" name="fovHigh">
<property name="text"> <property name="decimals">
<string>DEC</string> <number>3</number>
</property> </property>
</widget> <property name="maximum">
</item> <double>100000.000000000000000</double>
<item row="2" column="3"> </property>
<widget class="QLineEdit" name="pixelScale"> <property name="stepType">
<property name="readOnly"> <enum>QAbstractSpinBox::AdaptiveDecimalStepType</enum>
<bool>true</bool> </property>
</property> <property name="value">
</widget> <double>10000.000000000000000</double>
</item> </property>
<item row="0" column="1"> </widget>
<widget class="QLineEdit" name="ra"> </item>
<property name="readOnly"> <item row="1" column="2">
<bool>true</bool> <widget class="QLabel" name="label_11">
</property> <property name="text">
</widget> <string>DEC</string>
</item> </property>
<item row="1" column="0"> </widget>
<widget class="QLabel" name="label_2"> </item>
<property name="text"> <item row="1" column="1">
<string>Field width</string> <widget class="QDoubleSpinBox" name="raStart">
</property> <property name="suffix">
</widget> <string> h</string>
</item> </property>
<item row="0" column="3"> <property name="decimals">
<widget class="QLineEdit" name="dec"> <number>3</number>
<property name="readOnly"> </property>
<bool>true</bool> <property name="maximum">
</property> <double>24.000000000000000</double>
</widget> </property>
</item> </widget>
<item row="1" column="1"> </item>
<widget class="QLineEdit" name="fieldWidth"> <item row="4" column="2">
<property name="readOnly"> <widget class="QLabel" name="label_13">
<bool>true</bool> <property name="text">
</property> <string>High</string>
</widget> </property>
</item> </widget>
<item row="1" column="3"> </item>
<widget class="QLineEdit" name="fieldHeight"> <item row="4" column="1">
<property name="readOnly"> <widget class="QDoubleSpinBox" name="fovLow">
<bool>true</bool> <property name="decimals">
</property> <number>3</number>
</widget> </property>
</item> <property name="maximum">
<item row="3" column="0"> <double>10000.000000000000000</double>
<widget class="QLabel" name="label_8"> </property>
<property name="text"> <property name="stepType">
<string>Stars</string> <enum>QAbstractSpinBox::AdaptiveDecimalStepType</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="0">
<widget class="QLineEdit" name="stars"> <widget class="QCheckBox" name="useScale">
<property name="readOnly"> <property name="sizePolicy">
<bool>true</bool> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
</property> <horstretch>0</horstretch>
</widget> <verstretch>0</verstretch>
</item> </sizepolicy>
<item row="3" column="2"> </property>
<widget class="QLabel" name="label_9"> <property name="text">
<property name="text"> <string>Use scale</string>
<string>HFR</string> </property>
</property> </widget>
</widget> </item>
</item> <item row="2" column="0" colspan="4">
<item row="3" column="3"> <widget class="Line" name="line">
<widget class="QLineEdit" name="hfr"> <property name="orientation">
<property name="readOnly"> <enum>Qt::Horizontal</enum>
<bool>true</bool> </property>
</property> </widget>
</widget> </item>
</item> <item row="1" column="3">
</layout> <widget class="QDoubleSpinBox" name="decStart">
<property name="suffix">
<string> deg</string>
</property>
<property name="minimum">
<double>-90.000000000000000</double>
</property>
<property name="maximum">
<double>90.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Low </string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>RA</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Unit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Solution</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>RA</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="ra">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>DEC</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="dec">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Field width</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="fieldWidth">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Field height</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="fieldHeight">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Orientation</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="orientation">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Pixel scale</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLineEdit" name="pixelScale">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Stars</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="stars">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>HFR</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLineEdit" name="hfr">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="log">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="extractButton">
<property name="text">
<string>Extract</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="solveButton">
<property name="text">
<string>Solve</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="withHFR"> <widget class="QCheckBox" name="withHFR">
<property name="text"> <property name="text">
<string>Extract with HFR</string> <string>Extract with HFR</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QPushButton" name="extractButton">
<property name="text">
<string>Extract</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="solveButton">
<property name="text">
<string>Solve</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="settingsButton">
<property name="text">
<string>Settings</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item>
<widget class="QPushButton" name="settingsButton">
<property name="text">
<string>Settings</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
+130
View File
@@ -0,0 +1,130 @@
#include "platesolvingsettings.h"
#include "ui_platesolvingsettings.h"
#include <QSettings>
#include <QFileDialog>
#include "solver.h"
PlateSolvingSettings::PlateSolvingSettings(QWidget *parent) : QDialog(parent)
, _ui(new Ui::PlateSolvingSettings)
{
_ui->setupUi(this);
_download = new HttpDownloader(this);
connect(_download, &HttpDownloader::progress, this, &PlateSolvingSettings::progress);
connect(_ui->stopDownloadButton, &QPushButton::clicked, _download, &HttpDownloader::abort);
connect(_ui->scale01, &QCheckBox::clicked, [this](){ if(_ui->scale01->isChecked())_download->downloadIndex(1); });
connect(_ui->scale02, &QCheckBox::clicked, [this](){ if(_ui->scale02->isChecked())_download->downloadIndex(2); });
connect(_ui->scale03, &QCheckBox::clicked, [this](){ if(_ui->scale03->isChecked())_download->downloadIndex(3); });
connect(_ui->scale04, &QCheckBox::clicked, [this](){ if(_ui->scale04->isChecked())_download->downloadIndex(4); });
connect(_ui->scale05, &QCheckBox::clicked, [this](){ if(_ui->scale05->isChecked())_download->downloadIndex(5); });
connect(_ui->scale06, &QCheckBox::clicked, [this](){ if(_ui->scale06->isChecked())_download->downloadIndex(6); });
connect(_ui->scale07, &QCheckBox::clicked, [this](){ if(_ui->scale07->isChecked())_download->downloadIndex(7); });
connect(_ui->scale08, &QCheckBox::clicked, [this](){ if(_ui->scale08->isChecked())_download->downloadIndex(8); });
connect(_ui->scale09, &QCheckBox::clicked, [this](){ if(_ui->scale09->isChecked())_download->downloadIndex(9); });
connect(_ui->scale10, &QCheckBox::clicked, [this](){ if(_ui->scale10->isChecked())_download->downloadIndex(10); });
connect(_ui->scale11, &QCheckBox::clicked, [this](){ if(_ui->scale11->isChecked())_download->downloadIndex(11); });
connect(_ui->scale12, &QCheckBox::clicked, [this](){ if(_ui->scale12->isChecked())_download->downloadIndex(12); });
connect(_ui->scale13, &QCheckBox::clicked, [this](){ if(_ui->scale13->isChecked())_download->downloadIndex(13); });
connect(_ui->scale14, &QCheckBox::clicked, [this](){ if(_ui->scale14->isChecked())_download->downloadIndex(14); });
connect(_ui->scale15, &QCheckBox::clicked, [this](){ if(_ui->scale15->isChecked())_download->downloadIndex(15); });
connect(_ui->scale16, &QCheckBox::clicked, [this](){ if(_ui->scale16->isChecked())_download->downloadIndex(16); });
connect(_ui->scale17, &QCheckBox::clicked, [this](){ if(_ui->scale17->isChecked())_download->downloadIndex(17); });
connect(_ui->scale18, &QCheckBox::clicked, [this](){ if(_ui->scale18->isChecked())_download->downloadIndex(18); });
connect(_ui->scale19, &QCheckBox::clicked, [this](){ if(_ui->scale19->isChecked())_download->downloadIndex(19); });
QSettings settings;
_ui->indexPaths->addItems(settings.value("platesolving/indexPaths", Solver::getIndexPaths()).toStringList());
_ui->indexPaths->setCurrentText(settings.value("platesolving/indexPath", Solver::getTenmonIndexPath()).toString());
connect(_ui->addButton, &QPushButton::clicked, [this](){
QString path = QFileDialog::getExistingDirectory(this, tr("Index files directory"), Solver::getTenmonIndexPath());
if(!path.isEmpty())
{
bool contain = false;
for(int i=0; i<_ui->indexPaths->count(); i++)
{
if(path == _ui->indexPaths->itemText(i))
{
contain = true;
break;
}
}
if(!contain)_ui->indexPaths->addItem(path);
}
});
connect(_ui->removeButton, &QPushButton::clicked, [this](){
int current = _ui->indexPaths->currentIndex();
if(current > 0)_ui->indexPaths->removeItem(current);
});
_watcher = new QFileSystemWatcher(this);
_watcher->addPath(Solver::getTenmonIndexPath());
connect(_watcher, &QFileSystemWatcher::directoryChanged, this, &PlateSolvingSettings::checkIndexFiles);
connect(_ui->indexPaths, &QComboBox::currentTextChanged, [this](const QString &text){
_watcher->removePaths(_watcher->directories());
_watcher->addPath(text);
});
connect(_ui->indexPaths, &QComboBox::currentIndexChanged, [this](int index){
_ui->indexFilesGroup->setEnabled(index == 0);
});
checkIndexFiles();
}
PlateSolvingSettings::~PlateSolvingSettings()
{
QSettings settings;
settings.setValue("platesolving/indexPath", _ui->indexPaths->currentText());
QStringList paths;
for(int i=0; i<_ui->indexPaths->count(); i++)
paths.append(_ui->indexPaths->itemText(i));
settings.setValue("platesolving/indexPaths", paths);
delete _ui;
}
void PlateSolvingSettings::checkIndexFiles()
{
QString indexDir = Solver::getTenmonIndexPath() + "/";
auto checkScale = [indexDir](QCheckBox *box, int scale)
{
bool all = true;
QStringList files = HttpDownloader::indexFileNames(scale);
for(auto &file : files)
if(!QFile::exists(indexDir + file))
{
all = false;
break;
}
box->setChecked(all);
if(all)box->setStyleSheet("color: green; font: bold;");
else box->setStyleSheet("");
};
checkScale(_ui->scale01, 1);
checkScale(_ui->scale02, 2);
checkScale(_ui->scale03, 3);
checkScale(_ui->scale04, 4);
checkScale(_ui->scale05, 5);
checkScale(_ui->scale06, 6);
checkScale(_ui->scale07, 7);
checkScale(_ui->scale08, 8);
checkScale(_ui->scale09, 9);
checkScale(_ui->scale10, 10);
checkScale(_ui->scale11, 11);
checkScale(_ui->scale12, 12);
checkScale(_ui->scale13, 13);
checkScale(_ui->scale14, 14);
checkScale(_ui->scale15, 15);
checkScale(_ui->scale16, 16);
checkScale(_ui->scale17, 17);
checkScale(_ui->scale18, 18);
checkScale(_ui->scale19, 19);
}
void PlateSolvingSettings::progress(int percent, int files)
{
_ui->filesRemaining->setText(tr("%1 files").arg(files));
_ui->downloadProgressbar->setValue(percent);
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef PLATESOLVINGSETTINGS_H
#define PLATESOLVINGSETTINGS_H
#include <QDialog>
#include <QFileSystemWatcher>
#include "httpdownloader.h"
namespace Ui {
class PlateSolvingSettings;
}
class PlateSolvingSettings : public QDialog
{
Q_OBJECT
HttpDownloader *_download;
QFileSystemWatcher *_watcher;
public:
explicit PlateSolvingSettings(QWidget *parent = nullptr);
~PlateSolvingSettings();
void checkIndexFiles();
protected slots:
void progress(int percent, int files);
private:
Ui::PlateSolvingSettings *_ui;
};
#endif // PLATESOLVINGSETTINGS_H
+226
View File
@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PlateSolvingSettings</class>
<widget class="QDialog" name="PlateSolvingSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>787</width>
<height>479</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="indexPaths">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Plate solving need index files in order to solve an image. You can download them here by checking. This is possible only to default location.&lt;/p&gt;&lt;p&gt;It is required to download index files that cover 100%-50% field of view and recomended 100%-10%. So for images with 70' field of view it is required to download index files in 30'-85' and recomended 4'-85'.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="indexFilesGroup">
<property name="title">
<string>Index files</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="0">
<widget class="QCheckBox" name="scale14">
<property name="text">
<string>240' - 340'index-4114.fits (1.4 MiB)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="scale17">
<property name="text">
<string>680' - 1000' index-4117.fits (242 kiB)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="scale16">
<property name="text">
<string>480' - 680' index-4116.fits (400 kiB)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="scale18">
<property name="text">
<string>1000' - 1400' index-4118.fits (183 kiB)</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="scale15">
<property name="text">
<string>340' - 480' index-4115.fits (723 kiB)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="scale19">
<property name="text">
<string>1400' - 2000' index-4119.fits (141 kiB)</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="scale12">
<property name="text">
<string>120' - 170' index-4112.fits (5.1MiB)</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="scale13">
<property name="text">
<string>170' - 240' index-4113.fits (2.7MiB)</string>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QCheckBox" name="scale11">
<property name="text">
<string>85' - 120' index-4111.fits (9.8 MiB)</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QCheckBox" name="scale10">
<property name="text">
<string>60' - 85' index-4110.fits (24 MiB)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="scale09">
<property name="text">
<string>42' - 60' index-4109.fits (48 MiB)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="scale08">
<property name="text">
<string>30' - 42' index-4108.fits (91 MiB)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="scale07">
<property name="text">
<string>22' - 30' index-4107.fits (158 MiB)</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="scale06">
<property name="text">
<string>16' - 22' index-5206-*.fits (294 MiB)</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="scale05">
<property name="text">
<string>11' - 16' index-5205-*.fits (587 MiB)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="scale04">
<property name="text">
<string>8' - 11' index-5204-*.fits (1.2 GiB)</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="scale03">
<property name="text">
<string>4.0' - 5.6' index-5203-*.fits (2.3 GiB)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="scale02">
<property name="text">
<string>5.6' - 8.0' index-5202-*.fits (4.6 GiB)</string>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QCheckBox" name="scale01">
<property name="text">
<string>2.0' - 2.8' index-5201-*.fits (8.9 GiB)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="filesRemaining">
<property name="text">
<string>0 files</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="downloadProgressbar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopDownloadButton">
<property name="text">
<string>Stop download</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+34 -1
View File
@@ -3,8 +3,8 @@
#include <cstring> #include <cstring>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QFloat16> #include <QFloat16>
#include <QColorSpace>
#include <lcms2.h> #include <lcms2.h>
//#include <libstellarsolver/stellarsolver.h>
using F16 = qfloat16; using F16 = qfloat16;
@@ -804,6 +804,39 @@ std::shared_ptr<RawImage> RawImage::fromPlanar(const void *pixels, uint32_t w, u
return image; return image;
} }
std::shared_ptr<RawImage> RawImage::toPlanar()
{
std::shared_ptr<RawImage> ret = std::make_shared<RawImage>(m_width, m_height, 1, m_type);
size_t size = m_width * m_height;
size_t ch = m_ch;
auto convert = [&](auto *in, auto *out)
{
for(size_t i=0; i<size; i++)
out[i] = in[i * ch];
};
switch(m_type)
{
case UINT8:
convert(static_cast<uint8_t*>(data()), static_cast<uint8_t*>(ret->data()));
break;
case UINT16:
case FLOAT16:
convert(static_cast<uint16_t*>(data()), static_cast<uint16_t*>(ret->data()));
break;
case UINT32:
case FLOAT32:
convert(static_cast<uint32_t*>(data()), static_cast<uint32_t*>(ret->data()));
break;
case FLOAT64:
convert(static_cast<double*>(data()), static_cast<double*>(ret->data()));
break;
}
return ret;
}
std::vector<RawImage> RawImage::split() const std::vector<RawImage> RawImage::split() const
{ {
std::vector<RawImage> planes; std::vector<RawImage> planes;
+1 -1
View File
@@ -8,7 +8,6 @@
#include <math.h> #include <math.h>
#include <memory.h> #include <memory.h>
#include <QImage> #include <QImage>
#include <QColorSpace>
extern int THUMB_SIZE; extern int THUMB_SIZE;
extern int THUMB_SIZE_BORDER; extern int THUMB_SIZE_BORDER;
@@ -114,6 +113,7 @@ public:
static std::shared_ptr<RawImage> fromPlanar(const RawImage &img); static std::shared_ptr<RawImage> fromPlanar(const RawImage &img);
static std::shared_ptr<RawImage> fromPlanar(const void *pixels, uint32_t w, uint32_t h, uint32_t ch, DataType type); static std::shared_ptr<RawImage> fromPlanar(const void *pixels, uint32_t w, uint32_t h, uint32_t ch, DataType type);
std::shared_ptr<RawImage> toPlanar();
static size_t typeSize(DataType type); static size_t typeSize(DataType type);
std::vector<RawImage> split() const; std::vector<RawImage> split() const;
bool valid() const; bool valid() const;
+37 -13
View File
@@ -12,11 +12,10 @@
Solver::Solver(QObject *parent) : QObject(parent) Solver::Solver(QObject *parent) : QObject(parent)
{ {
_solver = new StellarSolver(this); _solver = new StellarSolver(this);
connect(_solver, &StellarSolver::logOutput, this, &Solver::logOutput);
QStringList indexFolder = getIndexPaths();
_solver->setProperty("ProcessType", SSolver::SOLVE); _solver->setProperty("ProcessType", SSolver::SOLVE);
_solver->setIndexFolderPaths(indexFolder); _solver->setIndexFolderPaths(QStringList(getTenmonIndexPath()));
_solver->setParameterProfile(SSolver::Parameters::ALL_STARS); _solver->setParameterProfile(SSolver::Parameters::ALL_STARS);
connect(_solver, &StellarSolver::finished, this, &Solver::finished); connect(_solver, &StellarSolver::finished, this, &Solver::finished);
@@ -26,9 +25,9 @@ Solver::~Solver()
{ {
} }
void Solver::setIndexFolders(const QStringList &indexPaths) void Solver::setIndexFolder(const QString &indexPath)
{ {
_solver->setIndexFolderPaths(indexPaths); _solver->setIndexFolderPaths(QStringList(indexPath));
} }
bool Solver::loadImage(const QString &path) bool Solver::loadImage(const QString &path)
@@ -46,6 +45,11 @@ bool Solver::loadImage(const QString &path)
bool Solver::loadImage(std::shared_ptr<RawImage> &image, const QString &path) bool Solver::loadImage(std::shared_ptr<RawImage> &image, const QString &path)
{ {
_rawImage = image; _rawImage = image;
if(_rawImage->channels() > 1)
_rawImagePlanar = _rawImage->toPlanar();
else
_rawImagePlanar = _rawImage;
switch(_rawImage->type()) switch(_rawImage->type())
{ {
case RawImage::UINT8: case RawImage::UINT8:
@@ -68,13 +72,15 @@ bool Solver::loadImage(std::shared_ptr<RawImage> &image, const QString &path)
return false; return false;
break; break;
} }
_stats.bytesPerPixel = _rawImage->typeSize(_rawImage->type()); _stats.bytesPerPixel = _rawImage->typeSize(_rawImagePlanar->type());
_stats.channels = _rawImage->channels(); _stats.channels = _rawImagePlanar->channels();
_stats.width = _rawImage->width(); _stats.width = _rawImagePlanar->width();
_stats.height = _rawImage->height(); _stats.height = _rawImagePlanar->height();
_stats.samples_per_channel = _stats.width * _stats.height; _stats.samples_per_channel = _stats.width * _stats.height;
_loaded = _solver->loadNewImageBuffer(_stats, (const uint8_t*)_rawImage->data()); _solver->clearSearchPosition();
_solver->clearSearchScale();
_loaded = _solver->loadNewImageBuffer(_stats, (const uint8_t*)_rawImagePlanar->data());
_path = path; _path = path;
return _loaded; return _loaded;
} }
@@ -169,17 +175,35 @@ void Solver::updateHeader()
void Solver::setParameters(Parameters::ParametersProfile profile) void Solver::setParameters(Parameters::ParametersProfile profile)
{ {
_solver->setParameterProfile(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) void Solver::setParameters(const Parameters &parameters)
{ {
_solver->setParameters(parameters); auto profile = parameters;
// TODO seems like any paralel is crashing with Qt6
profile.partition = false;
//profile.inParallel = false;
_solver->setParameters(profile);
}
void Solver::setSearchScale(double fovLow, double fowHigh, SSolver::ScaleUnits units)
{
_solver->setSearchScale(fovLow, fowHigh, units);
}
void Solver::setSearchPosition(double ra, double dec)
{
_solver->setSearchPositionRaDec(ra, dec);
} }
QStringList Solver::getIndexPaths() QStringList Solver::getIndexPaths()
{ {
QStringList paths;// = StellarSolver::getDefaultIndexFolderPaths(); QStringList paths = StellarSolver::getDefaultIndexFolderPaths();
paths.prepend(getTenmonIndexPath()); paths.prepend(getTenmonIndexPath());
return paths; return paths;
} }
+5 -1
View File
@@ -15,10 +15,11 @@ class Solver : public QObject
QString _path; QString _path;
QString _error; QString _error;
std::shared_ptr<RawImage> _rawImage; std::shared_ptr<RawImage> _rawImage;
std::shared_ptr<RawImage> _rawImagePlanar;
public: public:
explicit Solver(QObject *parent = nullptr); explicit Solver(QObject *parent = nullptr);
~Solver(); ~Solver();
void setIndexFolders(const QStringList &list); void setIndexFolder(const QString &indexPath);
bool loadImage(const QString &path); bool loadImage(const QString &path);
bool loadImage(std::shared_ptr<RawImage> &image, const QString &path); bool loadImage(std::shared_ptr<RawImage> &image, const QString &path);
@@ -32,6 +33,8 @@ public:
void updateHeader(); void updateHeader();
void setParameters(SSolver::Parameters::ParametersProfile profile); void setParameters(SSolver::Parameters::ParametersProfile profile);
void setParameters(const SSolver::Parameters &parameters); void setParameters(const SSolver::Parameters &parameters);
void setSearchScale(double fovLow, double fowHigh, ScaleUnits units);
void setSearchPosition(double ra, double dec);
static QStringList getIndexPaths(); static QStringList getIndexPaths();
static QString getTenmonIndexPath(); static QString getTenmonIndexPath();
@@ -40,6 +43,7 @@ public slots:
signals: signals:
void solvingDone(); void solvingDone();
void extractionDone(); void extractionDone();
void logOutput(const QString &log);
}; };
#endif // SOLVER_H #endif // SOLVER_H