CppEphem
CECorrections.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * CECorrections.h: CppEphem *
3  * ----------------------------------------------------------------------- *
4  * Copyright © 2019 JCardenzana *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 
38 #include "CECorrections.h"
39 #include "CEDate.h"
40 #include "CEException.h"
41 #include <sofam.h>
42 #include <exception>
43 #include <iostream>
44 #include <cmath>
45 #include <fstream>
46 
47 #ifndef NOCURL
48 #include <curl/curl.h>
49 #endif
50 
51 // #ifndef CECORRFILEPATH
52 // #define CECORRFILEPATH std::string("")
53 // #endif
54 
55 
56 /**********************************************************************/
60 {
61  init_members();
62 }
63 
64 
65 /**********************************************************************/
69 {
70  copy_members(other);
71 }
72 
73 
74 /**********************************************************************/
80 double CECorrections::dut1(const double& mjd) const
81 {
82  // Update the cache
84 
85  // return cached value
86  return cache_nut_dut1_;
87 }
88 
89 
90 /**********************************************************************/
96 double CECorrections::xpolar(const double& mjd) const
97 {
98  // Update the cache
100 
101  // return cached value
102  return cache_nut_xp_;
103 }
104 
105 
106 /**********************************************************************/
112 double CECorrections::ypolar(const double& mjd) const
113 {
114  // Update the cache
115  UpdateNutationCache(mjd);
116 
117  // return cached value
118  return cache_nut_yp_;
119 }
120 
121 
122 /**********************************************************************/
128 double CECorrections::deps(const double& mjd) const
129 {
130  // Update the cache
131  UpdateTtUt1Cache(mjd);
132 
133  // return cached value
134  return cache_nut_deps_;
135 }
136 
137 
138 /**********************************************************************/
144 double CECorrections::dpsi(const double& mjd) const
145 {
146  // Update the cache
147  UpdateTtUt1Cache(mjd);
148 
149  // return cached value
150  return cache_nut_dpsi_;
151 }
152 
153 
154 /**********************************************************************/
160 double CECorrections::ttut1(const double& mjd) const
161 {
162  // Update the cache
163  UpdateTtUt1Cache(mjd);
164 
165  // return cached value
166  return cache_ttut1_delt_;
167 }
168 
169 
170 /**********************************************************************/
177 {
178  if (this != &other) {
179  free_members();
180  init_members();
181  copy_members(other);
182  }
183  return *this;
184 }
185 
186 
187 /**********************************************************************/
192 void CECorrections::SetNutationFile(const std::string& filename)
193 {
194  nutation_file_ = filename;
195 }
196 
197 
198 /**********************************************************************/
203 void CECorrections::SetTtUt1HistFile(const std::string& filename)
204 {
205  ttut1_file_hist_ = filename;
206 }
207 
208 
209 /**********************************************************************/
214 void CECorrections::SetTtUt1PredFile(const std::string& filename)
215 {
216  ttut1_file_pred_ = filename;
217 }
218 
219 
220 /**********************************************************************/
225 void CECorrections::SetInterp(bool set_interp)
226 {
227  // Only update if the value is different
228  if (set_interp != interp_) {
229  interp_ = set_interp;
230  // Update cached dates to force recompute
231  cache_nut_mjd_ = -1.0e30;
232  cache_ttut1_mjd_ = -1.0e30;
233  }
234 }
235 
236 
237 /**********************************************************************/
241 {
242  // Clear the nutation vectors
243  nutation_mjd_.clear();
244  nutation_dut1_.clear();
245  nutation_xp_.clear();
246  nutation_yp_.clear();
247  nutation_deps_.clear();
248  nutation_dpsi_.clear();
249 
250  // Clear the TT-UT1 vectors
251  ttut1_mjd_.clear();
252  ttut1_delt_.clear();
253 }
254 
255 
256 /**********************************************************************/
262 {
266  nutation_xp_ = other.nutation_xp_;
267  nutation_yp_ = other.nutation_yp_;
270 
273  ttut1_delt_ = other.ttut1_delt_;
274 
275  // Caching values
284 }
285 
286 
287 /**********************************************************************/
291 {
292  // Note that CECORRFILEPATH is defined at compile time
293  interp_ = false;
294 
295  nutation_file_ = std::string(CECORRFILEPATH) + "/nutation.txt";
296  nutation_mjd_ = std::vector<int>(0);
297  nutation_dut1_ = std::vector<double>(0);
298  nutation_xp_ = std::vector<double>(0);
299  nutation_yp_ = std::vector<double>(0);
300  nutation_deps_ = std::vector<double>(0);
301  nutation_dpsi_ = std::vector<double>(0);
302 
303  ttut1_file_hist_ = std::string(CECORRFILEPATH) + "/ttut1_historic.txt";
304  ttut1_file_pred_ = std::string(CECORRFILEPATH) + "/ttut1_predicted.txt";
305  ttut1_mjd_ = std::vector<double>(0);
306  ttut1_delt_ = std::vector<double>(0);
307 
308  // Nutation cached values
309  cache_nut_mjd_ = -1e30;
310  cache_nut_dut1_ = 0.0;
311  cache_nut_xp_ = 0.0;
312  cache_nut_yp_ = 0.0;
313  cache_nut_deps_ = 0.0;
314  cache_nut_dpsi_ = 0.0;
315 
316  // TT-UT1 cached values
317  cache_ttut1_mjd_ = -1e30;
318  cache_ttut1_delt_ = 63.8285; // Default to J2000 reference date value
319 }
320 
321 
322 /**********************************************************************/
325 std::ifstream CECorrections::LoadFile(const std::string& filename,
326  const std::string& url) const
327 {
328  // Check if the file has been stored
329  std::ifstream corrections_file(filename, std::ios::in);
330 
331  // Try downloading the file
332  if (!corrections_file.is_open()) {
333  // Close the file so there's no funny business while attempting
334  // to write to it
335  corrections_file.close();
336 
337  // Try downloading the correction files
338  if (!DownloadTable(filename, url)) {
339  throw CEException::exception();
340  }
341 
342  // Try to open the file again
343  corrections_file.open(filename, std::ios::in);
344 
345  // Make sure the file is open
346  if (!corrections_file.is_open()) {
347  std::string msg = "Unable to load corrections file: " + filename;
348  throw CEException::corr_file_load_error(__func__, msg);
349  }
350  }
351 
352  return corrections_file;
353 }
354 
355 
356 /**********************************************************************/
361 bool CECorrections::DownloadTable(const std::string& filename,
362  const std::string& url) const
363 {
364  bool success = true;
365  #ifndef NOCURL
366  try {
367  CURL *curl;
368  FILE *fp;
369  CURLcode res;
370  curl = curl_easy_init();
371  if (curl)
372  {
373  fp = fopen(filename.c_str(), "wb");
374  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
375  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
376  curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
377  res = curl_easy_perform(curl);
378  curl_easy_cleanup(curl);
379  fclose(fp);
380  // TODO: handle the result
381  }
382  }
383  // Catch exceptions that may happen
384  catch (std::exception& e) {
385  std::cerr << "ERROR trying to download corrections files: "
386  << e.what() << std::endl;
387  success = false;
388  }
389  #else
390  std::cout << "CppEphem was not compiled with curl support. To download "
391  << "the corrections file automatically, recompile with -DNOCURL=0."
392  << std::endl;
393  success = false;
394  #endif
395 
396  return success;
397 }
398 
399 
400 /**********************************************************************/
405 bool CECorrections::LoadNutation(void) const
406 {
407  bool loaded = true;
408  if (nutation_mjd_.size() == 0) {
409  // Check if the file has been stored
410  std::string url = "http://maia.usno.navy.mil/ser7/finals2000A.all";
411  std::ifstream corrections_file = LoadFile(nutation_file_, url);
412 
413  // Try to load values from the file
414  try {
415  // Allocate an approximate amount of memory for the values
416  nutation_mjd_.reserve(20000);
417  nutation_dut1_.reserve(20000);
418  nutation_xp_.reserve(20000);
419  nutation_yp_.reserve(20000);
420  nutation_deps_.reserve(20000);
421  nutation_dpsi_.reserve(20000);
422 
423  // Preliminary storage values
424  int mjd;
425  double dut1;
426  double xp;
427  double yp;
428  double deps;
429  double dpsi;
430 
431  // Loop through each line of the file
432  std::string line;
433  while(std::getline(corrections_file, line)) {
434  mjd = std::stoi(line.substr(7,8));
435 
436  // Try to load dut1, xypolar from bulletin B positions
437  try {
438  dut1 = std::stod(line.substr(154,11));
439  xp = std::stod(line.substr(134,10));
440  yp = std::stod(line.substr(144,10));
441  deps = std::stod(line.substr(175,10));
442  dpsi = std::stod(line.substr(165,10));
443  }
444  // Otherwise load from bulletin A positions
445  catch (std::exception& e) {
446  try {
447  dut1 = std::stod(line.substr(58,10));
448  xp = std::stod(line.substr(18, 9));
449  yp = std::stod(line.substr(37, 9));
450  deps = std::stod(line.substr(116,9));
451  dpsi = std::stod(line.substr(97,9));
452  }
453  catch (std::exception& e) {
454  // Reached end of useable fields in the file
455  break;
456  }
457  }
458 
459  // The Standards of Fundamental Astronomy expects angles in
460  // units of radians, so xp, yp, deps, and dpsi need to be converted
461  nutation_mjd_.push_back( mjd );
462  nutation_dut1_.push_back( dut1 );
463  nutation_xp_.push_back( xp * DAS2R ); // arcsec -> radians
464  nutation_yp_.push_back( yp * DAS2R ); // arcsec -> radians
465  nutation_deps_.push_back( deps * DMAS2R ); // marcsec -> radians
466  nutation_dpsi_.push_back( dpsi * DMAS2R ); // marcsec -> radians
467  }
468 
469  // Close the corrections file
470  corrections_file.close();
471 
472  // Shrink up the vectors so we dont take more memory than necessary
473  nutation_mjd_.shrink_to_fit();
474  nutation_dut1_.shrink_to_fit();
475  nutation_xp_.shrink_to_fit();
476  nutation_yp_.shrink_to_fit();
477  nutation_deps_.shrink_to_fit();
478  nutation_dpsi_.shrink_to_fit();
479 
480  } catch (std::exception& e) {
481  std::cerr << "ERROR Unable to load corrections from file" << std::endl;
482  std::cerr << e.what() << std::endl;
483  loaded = false;
484  }
485  }
486  return loaded;
487 }
488 
489 
490 /**********************************************************************/
495 bool CECorrections::LoadTtUt1(void) const
496 {
497  bool loaded = true;
498  if (ttut1_mjd_.size() == 0) {
499 
500  try{
501  // Check if the file has been stored
502  std::string url = "http://maia.usno.navy.mil/ser7/deltat.data";
503  std::ifstream corrections_file = LoadFile(ttut1_file_hist_, url);
504 
505  // Allocate an approximate amount of memory for the values
506  ttut1_mjd_.reserve(5000);
507 
508  // Preliminary storage values
509  int mjd;
510  double delt;
511 
512  // Loop through each line of the file
513  std::string line;
514  while(std::getline(corrections_file, line)) {
515 
516  // Extract the Gregorian vector date
517  std::vector<double> greg_vect(4, 0.0);
518  greg_vect[0] = std::stod(line.substr(1,4));
519  greg_vect[1] = std::stod(line.substr(6,2));
520  greg_vect[2] = std::stod(line.substr(9,2));
521  mjd = CEDate::GregorianVect2MJD(greg_vect);
522 
523  // Try to load delta T from the file
524  try {
525  delt = std::stod(line.substr(13,7));
526  }
527  // Otherwise load from bulletin A positions
528  catch (std::exception& e) {
529  // Reached end of useable fields in the file
530  break;
531  }
532 
533  // Store the values into a vector
534  ttut1_mjd_.push_back( mjd );
535  ttut1_delt_.push_back( delt );
536  }
537 
538  // Close the corrections file
539  corrections_file.close();
540 
541  // Load the predicted corrections for the future
542  url = "http://maia.usno.navy.mil/ser7/deltat.preds";
543  corrections_file = LoadFile(ttut1_file_pred_, url);
544 
545  // Loop through each line of the file
546  std::getline(corrections_file, line); // First line is a header
547  while(std::getline(corrections_file, line)) {
548 
549  // Extract the MJD
550  mjd = std::stoi(line.substr(3,9));
551 
552  // Only add this value if it is actually from a later date
553  // than the last entry in the vector
554  if (mjd > ttut1_mjd_.back()) {
555 
556  // Try to load delta T from the file
557  try {
558  delt = std::stod(line.substr(24,5));
559  }
560  // Otherwise load from bulletin A positions
561  catch (std::exception& e) {
562  // Reached end of useable fields in the file
563  break;
564  }
565 
566  // Store the values into a vector
567  ttut1_mjd_.push_back( mjd );
568  ttut1_delt_.push_back( delt );
569  }
570  }
571 
572  // Shrink up the vectors so we dont take more memory than necessary
573  ttut1_mjd_.shrink_to_fit();
574  ttut1_delt_.shrink_to_fit();
575 
576  } catch (std::exception& e) {
577  std::cerr << "ERROR Unable to load corrections from file" << std::endl;
578  std::cerr << e.what() << std::endl;
579  loaded = false;
580  }
581  }
582  return loaded;
583 }
584 
585 
586 /**********************************************************************/
591 void CECorrections::UpdateNutationCache(const double& mjd) const
592 {
593  // Check if the nutation actually needs to be updated
594  if (mjd != cache_nut_mjd_) {
595  // Make sure nutation corrections are loaded
596  LoadNutation();
597 
598  // Compute the closest index associated with the MJD
599  int indx = (std::lower_bound(nutation_mjd_.begin(),nutation_mjd_.end(), mjd)
600  - nutation_mjd_.begin() ) - 1;
601 
602  // Make sure the MJD date is covered by stored correction values
603  if ((indx < 0) || (indx >= nutation_mjd_.size()-1)) {
604  // TODO: Make this a warning message
605  std::string min_mjd(std::to_string(nutation_mjd_.front()));
606  std::string max_mjd(std::to_string(nutation_mjd_.back()));
607  std::string msg = "Invalid mjd: " + std::to_string(mjd) + ". Accepted " +
608  "range is " + min_mjd + " - " + max_mjd;
609  throw CEException::invalid_value(__func__, msg);
610  }
611 
612  // Get the uninterpolated value
613  else if (!interp_) {
615  cache_nut_xp_ = nutation_xp_[indx];
616  cache_nut_yp_ = nutation_yp_[indx];
619  }
620 
621  // Otherwise interpolate between closest two values (a bit slower)
622  else {
623  double mjd_lower( nutation_mjd_[indx] );
624  double mjd_upper( nutation_mjd_[indx+1] );
625 
626  cache_nut_dut1_ = InterpValue(mjd, mjd_lower, mjd_upper,
627  nutation_dut1_[indx],
628  nutation_dut1_[indx+1]);
629  cache_nut_xp_ = InterpValue(mjd, mjd_lower, mjd_upper,
630  nutation_xp_[indx],
631  nutation_xp_[indx+1]);
632  cache_nut_yp_ = InterpValue(mjd, mjd_lower, mjd_upper,
633  nutation_yp_[indx],
634  nutation_yp_[indx+1]);
635  cache_nut_deps_ = InterpValue(mjd, mjd_lower, mjd_upper,
636  nutation_deps_[indx],
637  nutation_deps_[indx+1]);
638  cache_nut_dpsi_ = InterpValue(mjd, mjd_lower, mjd_upper,
639  nutation_dpsi_[indx],
640  nutation_dpsi_[indx+1]);
641  }
642 
643  cache_nut_mjd_ = mjd;
644  }
645 
646  return;
647 }
648 
649 
650 /**********************************************************************/
655 void CECorrections::UpdateTtUt1Cache(const double& mjd) const
656 {
657  // Check if the nutation actually needs to be updated
658  if (mjd != cache_ttut1_mjd_) {
659  // Make sure nutation corrections are loaded
660  LoadTtUt1();
661 
662  // Compute the closest index associated with the MJD
663  int indx = (std::lower_bound(ttut1_mjd_.begin(), ttut1_mjd_.end(), mjd)
664  - ttut1_mjd_.begin()) - 1;
665 
666  // Make sure the MJD date is covered by stored correction values
667  if ((indx < 0) || (indx >= ttut1_mjd_.size()-1)) {
668  // TODO: Make this a warning message
669  std::string min_mjd(std::to_string(ttut1_mjd_.front()));
670  std::string max_mjd(std::to_string(ttut1_mjd_.back()));
671  std::string msg = "Invalid mjd: " + std::to_string(mjd) + ". Accepted " +
672  "range is " + min_mjd + " - " + max_mjd;
673  throw CEException::invalid_value(__func__, msg);
674  }
675 
676  // Get the uninterpolated value
677  else if (!interp_) {
679  }
680 
681  // Otherwise interpolate between closest two values (a bit slower)
682  else {
683  double mjd_lower( ttut1_mjd_[indx] );
684  double mjd_upper( ttut1_mjd_[indx+1] );
685 
686  cache_ttut1_delt_ = InterpValue(mjd, mjd_lower, mjd_upper,
687  ttut1_delt_[indx],
688  ttut1_delt_[indx+1]);
689  }
690 
691  cache_ttut1_mjd_ = mjd;
692  }
693 
694  return;
695 }
696 
697 
698 /**********************************************************************/
708 double CECorrections::InterpValue(const double& x,
709  const double& x0, const double& x1,
710  const double& y0, const double& y1) const
711 {
712  return (y0*(x1 - x) + y1*(x - x0)) / (x1-x0);
713 }
CECorrections::DownloadTable
bool DownloadTable(const std::string &filename, const std::string &url) const
Downloads the IERS earth orientation correction parameters.
Definition: CECorrections.cpp:360
CECorrections::cache_nut_deps_
double cache_nut_deps_
Definition: CECorrections.h:112
CECorrections::init_members
void init_members(void)
Initialize data members.
Definition: CECorrections.cpp:289
CECorrections::nutation_dut1_
std::vector< double > nutation_dut1_
Definition: CECorrections.h:92
CECorrections::dut1
double dut1(const double &mjd) const
Return the DUT1 correction parameter (represents UT1 - UTC in seconds)
Definition: CECorrections.cpp:79
CECorrections::SetTtUt1PredFile
void SetTtUt1PredFile(const std::string &filename)
Sets the name of the predicted values TT-UT1 corrections file.
Definition: CECorrections.cpp:213
CppEphem::yp
double yp(const double &mjd)
Polar motion (x) for a given modified julian date (radians)
Definition: CENamespace.cpp:160
CECorrections::cache_nut_xp_
double cache_nut_xp_
Definition: CECorrections.h:110
CECorrections::ttut1_file_pred_
std::string ttut1_file_pred_
File for predicted TT-UT1 corrections.
Definition: CECorrections.h:88
CECorrections::CECorrections
CECorrections()
Constructor for coordinate corrections object.
Definition: CECorrections.cpp:58
CECorrections::InterpValue
double InterpValue(const double &x, const double &x0, const double &x1, const double &y0, const double &y1) const
Return the interpolated value at a given x value between two known values.
Definition: CECorrections.cpp:707
CECorrections::cache_nut_dpsi_
double cache_nut_dpsi_
Definition: CECorrections.h:113
CECorrections
Definition: CECorrections.h:28
CECorrections::cache_nut_dut1_
double cache_nut_dut1_
Definition: CECorrections.h:109
CECorrections::deps
double deps(const double &mjd) const
Return the offset in obliquity correction parameter (radians)
Definition: CECorrections.cpp:127
CECorrections::SetInterp
void SetInterp(bool set_interp)
Defines that the correction values should be interpolated.
Definition: CECorrections.cpp:224
CECorrections::cache_nut_mjd_
double cache_nut_mjd_
Definition: CECorrections.h:108
CECorrections::nutation_file_
std::string nutation_file_
File for nutation corrections.
Definition: CECorrections.h:86
CECorrections::copy_members
void copy_members(const CECorrections &other)
Copy data members from another object.
Definition: CECorrections.cpp:260
CECorrections::xpolar
double xpolar(const double &mjd) const
Return the x-polar motion correction parameter (radians)
Definition: CECorrections.cpp:95
CEDate.h
CECorrections::nutation_deps_
std::vector< double > nutation_deps_
Definition: CECorrections.h:95
CECorrections::cache_ttut1_mjd_
double cache_ttut1_mjd_
Definition: CECorrections.h:114
CEException.h
CECorrections::cache_nut_yp_
double cache_nut_yp_
Definition: CECorrections.h:111
CECorrections::UpdateTtUt1Cache
void UpdateTtUt1Cache(const double &mjd) const
Recompute cached values of nutation valeus if necessary.
Definition: CECorrections.cpp:654
CECorrections::ttut1_file_hist_
std::string ttut1_file_hist_
File for historic TT-UT1 corrections.
Definition: CECorrections.h:87
CECorrections::ttut1
double ttut1(const double &mjd) const
Return the TT-UT1 correction at a given date (in seconds)
Definition: CECorrections.cpp:159
CECorrections::SetTtUt1HistFile
void SetTtUt1HistFile(const std::string &filename)
Sets the name of the historic values TT-UT1 corrections file.
Definition: CECorrections.cpp:202
CECorrections::nutation_mjd_
std::vector< int > nutation_mjd_
Definition: CECorrections.h:91
CECorrections::nutation_xp_
std::vector< double > nutation_xp_
Definition: CECorrections.h:93
CECorrections::LoadFile
std::ifstream LoadFile(const std::string &filename, const std::string &url) const
Initialize data members.
Definition: CECorrections.cpp:324
CECorrections::nutation_dpsi_
std::vector< double > nutation_dpsi_
Definition: CECorrections.h:96
CECorrections::free_members
void free_members(void)
Free data member objects.
Definition: CECorrections.cpp:239
CEDate::GregorianVect2MJD
static double GregorianVect2MJD(std::vector< double > gregorian)
Gregorian calendar vector formatted date -> Modified Julian date converter.
Definition: CEDate.cpp:362
CECorrections::ttut1_delt_
std::vector< double > ttut1_delt_
Definition: CECorrections.h:99
CECorrections::ypolar
double ypolar(const double &mjd) const
Return the y-polar motion correction parameter (radians)
Definition: CECorrections.cpp:111
CECorrections::UpdateNutationCache
void UpdateNutationCache(const double &mjd) const
Recompute cached values of nutation valeus if necessary.
Definition: CECorrections.cpp:590
CECorrections::SetNutationFile
void SetNutationFile(const std::string &filename)
Sets the name of the nutation corrections file.
Definition: CECorrections.cpp:191
CEException::invalid_value
Definition: CEException.h:73
CECorrections::dpsi
double dpsi(const double &mjd) const
Return the offset in longitude correction parameter (radians)
Definition: CECorrections.cpp:143
CECorrections::interp_
bool interp_
Definition: CECorrections.h:104
CECorrections::cache_ttut1_delt_
double cache_ttut1_delt_
Definition: CECorrections.h:115
CECorrections::ttut1_mjd_
std::vector< double > ttut1_mjd_
Definition: CECorrections.h:98
CECorrections::operator=
CECorrections & operator=(const CECorrections &other)
Overloaded assignment operator.
Definition: CECorrections.cpp:175
CECorrections.h
CECorrections::LoadTtUt1
bool LoadTtUt1(void) const
Loads the TT-UT1 correction values.
Definition: CECorrections.cpp:494
CEException::corr_file_load_error
Definition: CEException.h:89
CECorrections::LoadNutation
bool LoadNutation(void) const
Loads the IERS earth orientation correction parameters.
Definition: CECorrections.cpp:404
CppEphem::xp
double xp(const double &mjd)
Polar motion (x) for a given modified julian date (radians)
Definition: CENamespace.cpp:148
CECorrections::nutation_yp_
std::vector< double > nutation_yp_
Definition: CECorrections.h:94