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 qDeleteAll(m_ObjectList);
76 m_ObjectList.clear();
77
78 objectNames(SkyObject::SUPERNOVA).clear();
79 objectLists(SkyObject::SUPERNOVA).clear();
80
81 auto sFileName = KSPaths::locate(QStandardPaths::AppLocalDataLocation, QString(tnsDataFilename));
82
83 try
84 {
85 io::CSVReader<26, io::trim_chars<' '>, io::double_quote_escape<',', '\"'>,
86 io::ignore_overflow>
87 in(sFileName.toLocal8Bit());
88 // skip header
89 const char *line = in.next_line();
90 if (line == nullptr)
91 {
92 qCritical() << "file is empty\n";
93 return;
94 }
95
96 std::string id, name, ra_s, dec_s, type;
97 double redshift;
98 std::string host_name;
99 double host_redshift;
100 std::string reporting_group, disc_datasource, classifying_group, assoc_group,
101 disc_internal_name, disc_instrument, classifying_instrument;
102 int tns_at, is_public;
103 std::string end_prop_period;
104 double discovery_mag;
105 std::string discovery_filter, discovery_date_s, sender, remarks,
106 discovery_bibcode, classification_bibcode, ext_catalog;
107
108 while (in.read_row(
109 id, name, ra_s, dec_s, type, redshift, host_name, host_redshift,
110 reporting_group, disc_datasource, classifying_group, assoc_group,
111 disc_internal_name, disc_instrument, classifying_instrument, tns_at,
112 is_public, end_prop_period, discovery_mag, discovery_filter, discovery_date_s,
113 sender, remarks, discovery_bibcode, classification_bibcode, ext_catalog))
114 {
115 auto discovery_date =
116 QDateTime::fromString(discovery_date_s.c_str(), Qt::ISODate);
117 QString qname = QString(name.c_str());
118 dms ra(QString(ra_s.c_str()), false);
119 dms dec(QString(dec_s.c_str()), true);
120
121 Supernova *sup = new Supernova(
122 qname, ra, dec, QString(type.c_str()), QString(host_name.c_str()),
123 QString(discovery_date_s.c_str()), redshift, discovery_mag, discovery_date);
124
125 objectNames(SkyObject::SUPERNOVA).append(QString(name.c_str()));
126
127 appendListObject(sup);
128 objectLists(SkyObject::SUPERNOVA)
129 .append(QPair<QString, const SkyObject *>(qname, sup));
130 }
131
132 m_DataLoading = false;
133 m_DataLoaded = true;
134 }
135 catch (io::error::can_not_open_file &ex)
136 {
137 qCCritical(KSTARS) << "could not open file " << sFileName.toLocal8Bit() << "\n";
138 return;
139 }
140 catch (std::exception &ex)
141 {
142 qCCritical(KSTARS) << "unknown exception happened:" << ex.what() << "\n";
143 }
144}
145
147{
148 if (!selected() || !m_DataLoaded)
149 return nullptr;
150
151 SkyObject *oBest = nullptr;
152 double rBest = maxrad;
153
154 for (auto &so : m_ObjectList)
155 {
156 double r = so->angularDistanceTo(p).Degrees();
157 //qDebug()<<r;
158 if (r < rBest)
159 {
160 oBest = so;
161 rBest = r;
162 }
163 }
164 maxrad = rBest;
165 return oBest;
166}
167
169{
170 //adjust maglimit for ZoomLevel
171 double lgmin = log10(MINZOOM);
172 double lgz = log10(Options::zoomFactor());
173
174 return 14.0 + 2.222 * (lgz - lgmin) +
175 2.222 * log10(static_cast<double>(Options::starDensity()));
176}
177
179{
180 //qDebug()<<"selected()="<<selected();
181 if (!selected())
182 return;
183 else if (!m_DataLoaded)
184 {
185 if (!m_DataLoading)
186 {
187 m_DataLoading = true;
188 QtConcurrent::run(this, &SupernovaeComponent::loadData);
189 }
190 return;
191 }
192
193 double maglim = zoomMagnitudeLimit();
194 double refage = Options::supernovaDetectionAge();
195 bool hostOnly = Options::supernovaeHostOnly();
196 bool classifiedOnly = Options::supernovaeClassifiedOnly();
197
198 for (auto so : m_ObjectList)
199 {
200 Supernova *sup = dynamic_cast<Supernova *>(so);
201 float mag = sup->mag();
202 float age = sup->getAgeDays();
203 QString type = sup->getType();
204
205 if (mag > float(Options::magnitudeLimitShowSupernovae()))
206 continue;
207
208 if (age > refage)
209 continue;
210
211 // only SN with host galaxy?
212 if (hostOnly && sup->getHostGalaxy() == "")
213 continue;
214
215 // Do not draw if mag>maglim
216 if (mag > maglim && Options::limitSupernovaeByZoom())
217 continue;
218
219 // classified SN only?
220 if (classifiedOnly && type == "")
221 continue;
222
223 skyp->drawSupernova(sup);
224 }
225}
226
227#if 0
228void SupernovaeComponent::notifyNewSupernovae()
229{
230#ifndef KSTARS_LITE
231 //qDebug()<<"New Supernovae discovered";
232 QList<SkyObject *> latestList;
233 foreach (SkyObject * so, latest)
234 {
235 Supernova * sup = (Supernova *)so;
236
237 if (sup->getMagnitude() > float(Options::magnitudeLimitAlertSupernovae()))
238 {
239 //qDebug()<<"Not Bright enough to be notified";
240 continue;
241 }
242
243 //qDebug()<<"Bright enough to be notified";
244 latestList.append(so);
245 }
246 if (!latestList.empty())
247 {
248 NotifyUpdatesUI * ui = new NotifyUpdatesUI(0);
249 ui->addItems(latestList);
250 ui->show();
251 }
252 // if (!latest.empty())
253 // KMessageBox::informationList(0, i18n("New Supernovae discovered!"), latestList, i18n("New Supernovae discovered!"));
254#endif
255}
256#endif
257
259{
260 delete (downloadJob);
261 downloadJob = new FileDownloader();
262 QString url = Options::supernovaDownloadUrl();
263 QString output = QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
264 .filePath(tnsDataFilenameZip);
265
266 if (!url.startsWith("file://"))
267 {
268 qInfo() << "fetching data from web: " << url << "\n";
269 downloadJob->setProgressDialogEnabled(true, i18n("Supernovae Update"),
270 i18n("Downloading Supernovae updates..."));
271
272 QObject::connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
273 QObject::connect(downloadJob, SIGNAL(error(QString)), this,
274 SLOT(downloadError(QString)));
275
276 downloadJob->setDownloadedFileURL(QUrl::fromLocalFile(output));
277 downloadJob->get(QUrl(url));
278 }
279 else
280 {
281 // if we have a local file as url
282 // copy data manually to target location
283 QString fname = url.right(url.size() - 7);
284 qInfo() << "fetching data from local file at: " << fname << "\n";
285 QFile::remove(fname);
286 auto res = QFile::copy(fname, output);
287 qInfo() << "copy returned: " << res << "\n";
288 // uncompress csv
289 unzipData();
290 // Reload Supernova
291 loadData();
292 }
293}
294
295void SupernovaeComponent::unzipData()
296{
297 // TODO: error handling
298 std::string ifpath =
299 QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
300 .filePath(tnsDataFilenameZip)
301 .toStdString();
302 std::string ofpath =
303 QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation))
304 .filePath(tnsDataFilename)
305 .toStdString();
306 auto fhz = gzopen(ifpath.c_str(), "rb");
307 auto fout = fopen(ofpath.c_str(), "wb");
308
309 if (fhz == NULL)
310 {
311 printf("Error: Failed to gzopen %s\n", ifpath.c_str());
312 exit(0);
313 }
314 unsigned char unzipBuffer[8192];
315 unsigned int unzippedBytes;
316 while (true)
317 {
318 unzippedBytes = gzread(fhz, unzipBuffer, 8192);
319 if (unzippedBytes > 0)
320 {
321 fwrite(unzipBuffer, 1, unzippedBytes, fout);
322 }
323 else
324 {
325 break;
326 }
327 }
328 gzclose(fhz);
329 fclose(fout);
330}
331
332void SupernovaeComponent::downloadReady()
333{
334 // uncompress csv
335 unzipData();
336 // Reload Supernova
337 loadData();
338#ifdef KSTARS_LITE
340#else
342#endif
343 downloadJob->deleteLater();
344}
345
346void SupernovaeComponent::downloadError(const QString &errorString)
347{
348 KSNotification::error(i18n("Error downloading supernova data: %1", errorString));
349 downloadJob->deleteLater();
350}
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:123
KStarsData * data() const
Definition kstars.h:135
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)
void clear()
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 Fri Jul 26 2024 11:59:52 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.