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;
102 int tns_at, is_public;
103 std::string end_prop_period;
104 double discovery_mag;
107
108 while (in.read_row(
109 id, name, ra_s, dec_s, type, redshift, host_name, host_redshift,
114 {
115 auto discovery_date =
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()),
124
125 objectNames(SkyObject::SUPERNOVA).append(QString(name.c_str()));
126
128 objectLists(SkyObject::SUPERNOVA)
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";
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 auto shownames = Options::showSupernovaNames();
263 auto age = Options::supernovaDetectionAge();
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";
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 {
321 if (unzippedBytes > 0)
322 {
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
341 KStarsLite::Instance()->data()->setFullTimeUpdate();
342#else
343 KStars::Instance()->data()->setFullTimeUpdate();
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
GeoLocation * geo()
Definition kstarsdata.h:230
static KStarsLite * Instance()
Definition kstarslite.h:77
static KStars * Instance()
Definition kstars.h:123
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
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
The sky coordinates of a point in the sky.
Definition skypoint.h:45
Represents the supernova object.
Definition supernova.h:34
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...)
Type type(const QSqlDatabase &db)
QString name(StandardShortcut id)
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 clear()
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 Tue Mar 26 2024 11:19:04 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.