Kstars

supernovaecomponent.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 Based on Samikshan Bairagya GSoC work.
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7*/
8
9#include "supernovaecomponent.h"
10
11#ifndef KSTARS_LITE
12#include "kstars.h"
13#include "skymap.h"
14#else
15#include "kstarslite.h"
16#endif
17#include "dms.h"
18#include "kstars_debug.h"
19#include "ksnotification.h"
20#include "kstarsdata.h"
21#include "Options.h"
22#include "skylabeler.h"
23#include "skymesh.h"
24#include "skypainter.h"
25#include "auxiliary/filedownloader.h"
26#include "projections/projector.h"
27#include "auxiliary/kspaths.h"
28
29#include <QtConcurrent>
30#include <QJsonDocument>
31#include <QJsonValue>
32
33#include <zlib.h>
34#include <fstream>
35#include <stdio.h>
36
37#include <csv.h>
38
39const QString SupernovaeComponent::tnsDataFilename("tns_public_objects.csv");
40const QString SupernovaeComponent::tnsDataFilenameZip("tns-daily.csv.gz");
41const QString SupernovaeComponent::tnsDataUrl(
42 "https://indilib.org/jdownloads/kstars/tns-daily.csv.gz");
43
44SupernovaeComponent::SupernovaeComponent(SkyComposite *parent) : ListComponent(parent)
45{
46 //QtConcurrent::run(this, &SupernovaeComponent::loadData);
47 //loadData(); MagnitudeLimitShowSupernovae
48 connect(Options::self(), &Options::SupernovaDownloadUrlChanged, this,
49 &SupernovaeComponent::loadData);
50 connect(Options::self(), &Options::MagnitudeLimitShowSupernovaeChanged, this,
51 &SupernovaeComponent::loadData);
52}
53
55{
56 if (!selected() || !m_DataLoaded)
57 return;
58
59 KStarsData *data = KStarsData::Instance();
60 for (auto so : m_ObjectList)
61 {
62 if (num)
63 so->updateCoords(num);
64 so->EquatorialToHorizontal(data->lst(), data->geo()->lat());
65 }
66}
67
69{
70 return Options::showSupernovae();
71}
72
73void SupernovaeComponent::loadData()
74{
75 clear();
76 objectNames(SkyObject::SUPERNOVA).clear();
77 objectLists(SkyObject::SUPERNOVA).clear();
78
79 auto sFileName = KSPaths::locate(QStandardPaths::AppLocalDataLocation, QString(tnsDataFilename));
80
81 try
82 {
83 io::CSVReader<26, io::trim_chars<' '>, io::double_quote_escape<',', '\"'>,
84 io::ignore_overflow>
85 in(sFileName.toLocal8Bit());
86 // skip header
87 const char *line = in.next_line();
88 if (line == nullptr)
89 {
90 qCritical() << "file is empty\n";
91 return;
92 }
93
94 std::string id, name, ra_s, dec_s, type;
95 double redshift;
96 std::string host_name;
97 double host_redshift;
98 std::string reporting_group, disc_datasource, classifying_group, assoc_group,
99 disc_internal_name, disc_instrument, classifying_instrument;
100 int tns_at, is_public;
101 std::string end_prop_period;
102 double discovery_mag;
103 std::string discovery_filter, discovery_date_s, sender, remarks,
104 discovery_bibcode, classification_bibcode, ext_catalog;
105
106 while (in.read_row(
107 id, name, ra_s, dec_s, type, redshift, host_name, host_redshift,
108 reporting_group, disc_datasource, classifying_group, assoc_group,
109 disc_internal_name, disc_instrument, classifying_instrument, tns_at,
110 is_public, end_prop_period, discovery_mag, discovery_filter, discovery_date_s,
111 sender, remarks, discovery_bibcode, classification_bibcode, ext_catalog))
112 {
113 auto discovery_date =
114 QDateTime::fromString(discovery_date_s.c_str(), Qt::ISODate);
115 QString qname = QString(name.c_str());
116 dms ra(QString(ra_s.c_str()), false);
117 dms dec(QString(dec_s.c_str()), true);
118
119 Supernova *sup = new Supernova(
120 qname, ra, dec, QString(type.c_str()), QString(host_name.c_str()),
121 QString(discovery_date_s.c_str()), redshift, discovery_mag, discovery_date);
122
123 objectNames(SkyObject::SUPERNOVA).append(QString(name.c_str()));
124
125 appendListObject(sup);
126 objectLists(SkyObject::SUPERNOVA)
127 .append(QPair<QString, const SkyObject *>(qname, sup));
128 }
129
130 m_DataLoading = false;
131 m_DataLoaded = true;
132 }
133 catch (io::error::can_not_open_file &ex)
134 {
135 qCCritical(KSTARS) << "could not open file " << sFileName.toLocal8Bit() << "\n";
136 return;
137 }
138 catch (std::exception &ex)
139 {
140 qCCritical(KSTARS) << "unknown exception happened:" << ex.what() << "\n";
141 }
142}
143
145{
146 if (!selected() || !m_DataLoaded)
147 return nullptr;
148
149 SkyObject *oBest = nullptr;
150 double rBest = maxrad;
151
152 for (auto &so : m_ObjectList)
153 {
154 double r = so->angularDistanceTo(p).Degrees();
155 //qDebug()<<r;
156 if (r < rBest)
157 {
158 oBest = so;
159 rBest = r;
160 }
161 }
162 maxrad = rBest;
163 return oBest;
164}
165
167{
168 //adjust maglimit for ZoomLevel
169 double lgmin = log10(MINZOOM);
170 double lgz = log10(Options::zoomFactor());
171
172 return 14.0 + 2.222 * (lgz - lgmin) +
173 2.222 * log10(static_cast<double>(Options::starDensity()));
174}
175
177{
178 //qDebug()<<"selected()="<<selected();
179 if (!selected())
180 return;
181 else if (!m_DataLoaded)
182 {
183 if (!m_DataLoading)
184 {
185 m_DataLoading = true;
186#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
187 QtConcurrent::run(&SupernovaeComponent::loadData, this);
188#else
189 QtConcurrent::run(this, &SupernovaeComponent::loadData);
190#endif
191 }
192 return;
193 }
194
195 double maglim = zoomMagnitudeLimit();
196 double refage = Options::supernovaDetectionAge();
197 bool hostOnly = Options::supernovaeHostOnly();
198 bool classifiedOnly = Options::supernovaeClassifiedOnly();
199
200 for (auto so : m_ObjectList)
201 {
202 Supernova *sup = dynamic_cast<Supernova *>(so);
203 float mag = sup->mag();
204 float age = sup->getAgeDays();
205 QString type = sup->getType();
206
207 if (mag > float(Options::magnitudeLimitShowSupernovae()))
208 continue;
209
210 if (age > refage)
211 continue;
212
213 // only SN with host galaxy?
214 if (hostOnly && sup->getHostGalaxy() == "")
215 continue;
216
217 // Do not draw if mag>maglim
218 if (mag > maglim && Options::limitSupernovaeByZoom())
219 continue;
220
221 // classified SN only?
222 if (classifiedOnly && type == "")
223 continue;
224
225 skyp->drawSupernova(sup);
226 }
227}
228
229#if 0
230void SupernovaeComponent::notifyNewSupernovae()
231{
232#ifndef KSTARS_LITE
233 //qDebug()<<"New Supernovae discovered";
234 QList<SkyObject *> latestList;
235 foreach (SkyObject * so, latest)
236 {
237 Supernova * sup = (Supernova *)so;
238
239 if (sup->getMagnitude() > float(Options::magnitudeLimitAlertSupernovae()))
240 {
241 //qDebug()<<"Not Bright enough to be notified";
242 continue;
243 }
244
245 //qDebug()<<"Bright enough to be notified";
246 latestList.append(so);
247 }
248 if (!latestList.empty())
249 {
250 NotifyUpdatesUI * ui = new NotifyUpdatesUI(0);
251 ui->addItems(latestList);
252 ui->show();
253 }
254 // if (!latest.empty())
255 // KMessageBox::informationList(0, i18n("New Supernovae discovered!"), latestList, i18n("New Supernovae discovered!"));
256#endif
257}
258#endif
259
261{
262 delete (downloadJob);
263 downloadJob = new FileDownloader();
264 QString url = Options::supernovaDownloadUrl();
265 QString output = QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
266 .filePath(tnsDataFilenameZip);
267
268 if (!url.startsWith("file://"))
269 {
270 qInfo() << "fetching data from web: " << url << "\n";
271 downloadJob->setProgressDialogEnabled(true, i18n("Supernovae Update"),
272 i18n("Downloading Supernovae updates..."));
273
274 QObject::connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
275 QObject::connect(downloadJob, SIGNAL(error(QString)), this,
276 SLOT(downloadError(QString)));
277
278 downloadJob->setDownloadedFileURL(QUrl::fromLocalFile(output));
279 downloadJob->get(QUrl(url));
280 }
281 else
282 {
283 // if we have a local file as url
284 // copy data manually to target location
285 QString fname = url.right(url.size() - 7);
286 qInfo() << "fetching data from local file at: " << fname << "\n";
287 QFile::remove(fname);
288 auto res = QFile::copy(fname, output);
289 qInfo() << "copy returned: " << res << "\n";
290 // uncompress csv
291 unzipData();
292 // Reload Supernova
293 loadData();
294 }
295}
296
297void SupernovaeComponent::unzipData()
298{
299 // TODO: error handling
300 std::string ifpath =
301 QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
302 .filePath(tnsDataFilenameZip)
303 .toStdString();
304 std::string ofpath =
305 QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
306 .filePath(tnsDataFilename)
307 .toStdString();
308 auto fhz = gzopen(ifpath.c_str(), "rb");
309 auto fout = fopen(ofpath.c_str(), "wb");
310
311 if (fhz == NULL)
312 {
313 printf("Error: Failed to gzopen %s\n", ifpath.c_str());
314 exit(0);
315 }
316 unsigned char unzipBuffer[8192];
317 unsigned int unzippedBytes;
318 while (true)
319 {
320 unzippedBytes = gzread(fhz, unzipBuffer, 8192);
321 if (unzippedBytes > 0)
322 {
323 fwrite(unzipBuffer, 1, unzippedBytes, fout);
324 }
325 else
326 {
327 break;
328 }
329 }
330 gzclose(fhz);
331 fclose(fout);
332}
333
334void SupernovaeComponent::downloadReady()
335{
336 // uncompress csv
337 unzipData();
338 // Reload Supernova
339 loadData();
340#ifdef KSTARS_LITE
342#else
344#endif
345 downloadJob->deleteLater();
346}
347
348void SupernovaeComponent::downloadError(const QString &errorString)
349{
350 KSNotification::error(i18n("Error downloading supernova data: %1", errorString));
351 downloadJob->deleteLater();
352}
const CachingDms * lat() const
Definition geolocation.h:70
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition ksnumbers.h:43
KStarsData is the backbone of KStars.
Definition kstarsdata.h:72
CachingDms * lst()
Definition kstarsdata.h:224
void setFullTimeUpdate()
The Sky is updated more frequently than the moon, which is updated more frequently than the planets.
GeoLocation * geo()
Definition kstarsdata.h:230
static KStarsLite * Instance()
Definition kstarslite.h:77
KStarsData * data() const
Definition kstarslite.h:86
static KStars * Instance()
Definition kstars.h:121
KStarsData * data() const
Definition kstars.h:133
An abstract parent class, to be inherited by SkyComponents that store a QList of SkyObjects.
void appendListObject(SkyObject *object)
Add an object to the Object list.
SkyComposite is a kind of container class for SkyComponent objects.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
float mag() const
Definition skyobject.h:206
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
virtual bool drawSupernova(Supernova *sup)=0
Draw a Supernova.
The sky coordinates of a point in the sky.
Definition skypoint.h:45
Represents the supernova object.
Definition supernova.h:34
QString getType() const
Definition supernova.h:48
QString getHostGalaxy() const
Definition supernova.h:51
void slotTriggerDataFileUpdate()
This initiates updating of the data file.
void draw(SkyPainter *skyp) override
SkyObject * objectNearest(SkyPoint *p, double &maxrad) override
Find the SkyObject nearest the given SkyPoint.
static float zoomMagnitudeLimit()
void update(KSNumbers *num=nullptr) override
Update the sky positions of this component.
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
QString i18n(const char *text, const TYPE &arg...)
QString name(GameStandardAction id)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
QString filePath(const QString &fileName) const const
bool copy(const QString &fileName, const QString &newName)
bool remove()
void clear()
void append(QList< T > &&value)
bool empty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * sender() const const
QString right(qsizetype n) const const
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
std::string toStdString() const const
QTextStream & dec(QTextStream &stream)
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl fromLocalFile(const QString &localFile)
void show()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.