Kstars

supernovaecomponent.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Jasem Mutlaq <[email protected]>
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 
39 const QString SupernovaeComponent::tnsDataFilename("tns_public_objects.csv");
40 const QString SupernovaeComponent::tnsDataFilenameZip("tns-daily.csv.gz");
41 const QString SupernovaeComponent::tnsDataUrl(
42  "https://indilib.org/jdownloads/kstars/tns-daily.csv.gz");
43 
44 SupernovaeComponent::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 
73 void 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
228 void 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  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";
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 
297 void 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 
334 void 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 
348 void SupernovaeComponent::downloadError(const QString &errorString)
349 {
350  KSNotification::error(i18n("Error downloading supernova data: %1", errorString));
351  downloadJob->deleteLater();
352 }
virtual bool drawSupernova(Supernova *sup)=0
Draw a Supernova.
void append(const T &value)
QFuture< T > run(Function function,...)
int size() const const
void update(KSNumbers *num=nullptr) override
Update the sky positions of this component.
bool remove()
QString getType() const
Definition: supernova.h:48
Type type(const QSqlDatabase &db)
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
bool copy(const QString &newName)
KStarsData * data() const
Definition: kstarslite.h:86
SkyObject * objectNearest(SkyPoint *p, double &maxrad) override
Find the SkyObject nearest the given SkyPoint.
void clear()
CachingDms * lst()
Definition: kstarsdata.h:224
static KStarsLite * Instance()
Definition: kstarslite.h:77
QObject * sender() const const
float mag() const
Definition: skyobject.h:206
QString getHostGalaxy() const
Definition: supernova.h:51
void setFullTimeUpdate()
The Sky is updated more frequently than the moon, which is updated more frequently than the planets.
Definition: kstarsdata.cpp:313
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
static KStars * Instance()
Definition: kstars.h:123
bool empty() const const
FILE * fopen(const QString &pathname, const char *mode)
QString i18n(const char *text, const TYPE &arg...)
Store several time-dependent astronomical quantities.
Definition: ksnumbers.h:42
const CachingDms * lat() const
Definition: geolocation.h:70
void draw(SkyPainter *skyp) override
std::string toStdString() const const
QUrl fromLocalFile(const QString &localFile)
GeoLocation * geo()
Definition: kstarsdata.h:230
void appendListObject(SkyObject *object)
Add an object to the Object list.
QTextStream & dec(QTextStream &stream)
QDateTime fromString(const QString &string, Qt::DateFormat format)
Draws things on the sky, without regard to backend.
Definition: skypainter.h:39
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=nullptr) const
Computes the angular distance between two SkyObjects.
Definition: skypoint.cpp:899
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
void slotTriggerDataFileUpdate()
This initiates updating of the data file.
QString right(int n) const const
const double & Degrees() const
Definition: dms.h:141
const char * name(StandardAction id)
QString filePath(const QString &fileName) const const
void clear()
KStarsData * data() const
Definition: kstars.h:135
static float zoomMagnitudeLimit()
Information about an object in the sky.
Definition: skyobject.h:41
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Oct 3 2023 04:02:55 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.