GRAVI Pipeline Reference Manual  1.2.3
gravity_eop.c
1 /*
2  * This file is part of the GRAVITY Pipeline
3  * Copyright (C) 2002,2003 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 /*-----------------------------------------------------------------------------
25  Includes
26  -----------------------------------------------------------------------------*/
27 
28 #include <cpl.h>
29 #include <time.h>
30 
31 #include "gravi_data.h"
32 #include "gravi_dfs.h"
33 #include "gravi_pfits.h"
34 
35 #include "gravi_utils.h"
36 
37 #include "gravi_eop.h"
38 
39 /*-----------------------------------------------------------------------------
40  Private function prototypes
41  -----------------------------------------------------------------------------*/
42 
43 static int gravity_eop_create(cpl_plugin *);
44 static int gravity_eop_exec(cpl_plugin *);
45 static int gravity_eop_destroy(cpl_plugin *);
46 static int gravity_eop(cpl_frameset *, const cpl_parameterlist *);
47 cpl_error_code gravity_eop_compute_qc(cpl_table * eop_table,
48  cpl_propertylist* header,
49  double * mjd_lastfinal);
50 
51 /*-----------------------------------------------------------------------------
52  Static variables
53  -----------------------------------------------------------------------------*/
54 
55 static const char gravity_eop_short[] = "Download the last values of the Earth Orientation Parameters and DUT from IERS.";
56 static const char gravity_eop_description[] =
57 "This recipe downloads the latest version of the Earth Orientation Parameter \n"
58 "and DUT from the IERS site. File is created in the current directory. A web connection is required.\n"
59  GRAVI_RECIPE_FLOW"\n"
60  "* Download the IERS data\n"
61  "* Convert into CPL table\n"
62  "* Write product\n"
63  GRAVI_RECIPE_INPUT"\n"
64  "None : No input\n"
65  GRAVI_RECIPE_OUTPUT"\n"
66  GRAVI_EOP_MAP" : EOP calibration file (gravity_eop_calib.fits)\n"
67  "";
68 
69 static const char gravity_eop_name[] = "gravity_eop";
70 
71 /*-----------------------------------------------------------------------------
72  Function code
73  -----------------------------------------------------------------------------*/
74 
75 /*----------------------------------------------------------------------------*/
85 /*----------------------------------------------------------------------------*/
86 int cpl_plugin_get_info(cpl_pluginlist * list)
87 {
88  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
89  cpl_plugin * plugin = &recipe->interface;
90 
91  if (cpl_plugin_init(plugin,
92  CPL_PLUGIN_API,
93  GRAVI_BINARY_VERSION,
94  CPL_PLUGIN_TYPE_RECIPE,
95  gravity_eop_name,
96  gravity_eop_short,
97  gravity_eop_description,
98  "Cesar Enrique Garcia Dabo",
99  PACKAGE_BUGREPORT,
100  "LL",
101  gravity_eop_create,
102  gravity_eop_exec,
103  gravity_eop_destroy)) {
104  cpl_msg_error(cpl_func, "Plugin initialization failed");
105  (void)cpl_error_set_where(cpl_func);
106  return 1;
107  }
108 
109  if (cpl_pluginlist_append(list, plugin)) {
110  cpl_msg_error(cpl_func, "Error adding plugin to list");
111  (void)cpl_error_set_where(cpl_func);
112  return 1;
113  }
114 
115  return 0;
116 }
117 
118 /*----------------------------------------------------------------------------*/
126 /*----------------------------------------------------------------------------*/
127 static int gravity_eop_create(cpl_plugin * plugin)
128 {
129  cpl_recipe * recipe;
130  cpl_parameter * p;
131 
132  /* Do not create the recipe if an error code is already set */
133  if (cpl_error_get_code() != CPL_ERROR_NONE) {
134  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
135  cpl_func, __LINE__, cpl_error_get_where());
136  return (int)cpl_error_get_code();
137  }
138 
139  if (plugin == NULL) {
140  cpl_msg_error(cpl_func, "Null plugin");
141  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
142  }
143 
144  /* Verify plugin type */
145  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
146  cpl_msg_error(cpl_func, "Plugin is not a recipe");
147  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
148  }
149 
150  /* Get the recipe */
151  recipe = (cpl_recipe *)plugin;
152 
153  /* Create the parameters list in the cpl_recipe object */
154  recipe->parameters = cpl_parameterlist_new();
155  if (recipe->parameters == NULL) {
156  cpl_msg_error(cpl_func, "Parameter list allocation failed");
157  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
158  }
159 
160  /* --eop_host */
161  p = cpl_parameter_new_value ("gravity.eop.eop_host",
162  CPL_TYPE_STRING,
163  "FTP Host to retrieve the EOP from",
164  "gravity.eop",
165  "ftp.iers.org");
166  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "eop_host");
167  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
168  cpl_parameterlist_append (recipe->parameters, p);
169 
170  /* --eop_urlpath */
171  p = cpl_parameter_new_value ("gravity.eop.eop_urlpath",
172  CPL_TYPE_STRING,
173  "FTP URL path of the EOP file to retrieve",
174  "gravity.eop",
175  "/products/eop/rapid/standard/finals2000A.data");
176  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "eop_urlpath");
177  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
178  cpl_parameterlist_append (recipe->parameters, p);
179 
180  return 0;
181 }
182 
183 /*----------------------------------------------------------------------------*/
189 /*----------------------------------------------------------------------------*/
190 static int gravity_eop_exec(cpl_plugin * plugin)
191 {
192 
193  cpl_recipe * recipe;
194  int recipe_status;
195  cpl_errorstate initial_errorstate = cpl_errorstate_get();
196 
197  /* Return immediately if an error code is already set */
198  if (cpl_error_get_code() != CPL_ERROR_NONE) {
199  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
200  cpl_func, __LINE__, cpl_error_get_where());
201  return (int)cpl_error_get_code();
202  }
203 
204  if (plugin == NULL) {
205  cpl_msg_error(cpl_func, "Null plugin");
206  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
207  }
208 
209  /* Verify plugin type */
210  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
211  cpl_msg_error(cpl_func, "Plugin is not a recipe");
212  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
213  }
214 
215  /* Get the recipe */
216  recipe = (cpl_recipe *)plugin;
217 
218  /* Verify parameter and frame lists */
219  if (recipe->parameters == NULL) {
220  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
221  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
222  }
223  if (recipe->frames == NULL) {
224  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
225  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
226  }
227 
228  /* Invoke the recipe */
229  recipe_status = gravity_eop(recipe->frames, recipe->parameters);
230 
231  if (!cpl_errorstate_is_equal(initial_errorstate)) {
232  /* Dump the error history since recipe execution start.
233  At this point the recipe cannot recover from the error */
234  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
235  }
236 
237  return recipe_status;
238 }
239 
240 /*----------------------------------------------------------------------------*/
246 /*----------------------------------------------------------------------------*/
247 static int gravity_eop_destroy(cpl_plugin * plugin)
248 {
249  cpl_recipe * recipe;
250 
251  if (plugin == NULL) {
252  cpl_msg_error(cpl_func, "Null plugin");
253  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
254  }
255 
256  /* Verify plugin type */
257  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
258  cpl_msg_error(cpl_func, "Plugin is not a recipe");
259  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
260  }
261 
262  /* Get the recipe */
263  recipe = (cpl_recipe *)plugin;
264 
265  cpl_parameterlist_delete(recipe->parameters);
266 
267  return 0;
268 }
269 
270 /*----------------------------------------------------------------------------*/
277 /*----------------------------------------------------------------------------*/
278 static int gravity_eop(cpl_frameset * frameset,
279  const cpl_parameterlist * parlist)
280 {
281  const char * eop_host;
282  const char * eop_urlpath;
283  cpl_propertylist * applist;
284  char * timestamp_lastfinal;
285  double mjd_lastfinal;
286  char * filename;
287 
288  /* Message */
289  gravity_print_banner ();
290  cpl_msg_set_time_on();
291  cpl_msg_set_component_on();
292  gravi_msg_function_start(1);
293 
294  /* Use the errorstate to detect an error in a function that does not
295  return an error code. */
296  cpl_errorstate prestate = cpl_errorstate_get();
297 
298  /* Retrieving eop_host */
299  eop_host = gravi_param_get_string (parlist, "gravity.eop.eop_host");
300 
301  /* Retrieving eop_urlpath */
302  eop_urlpath = gravi_param_get_string (parlist, "gravity.eop.eop_urlpath");
303 
304  if (!cpl_errorstate_is_equal(prestate)) {
305  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
306  "Could not retrieve the input "
307  "parameters");
308  }
309 
310 
311  /* Retrieve EOP file from the site */
312  const char * eop_data;
313  int data_length;
314  cpl_msg_info (cpl_func, "Retrieving EOP file ");
315  eop_data = gravity_eop_download_finals2000A (eop_host, eop_urlpath, &data_length);
316 
317  if (eop_data == NULL || !cpl_errorstate_is_equal(prestate)) {
318  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
319  "Could not download data from server");
320  }
321 
322  /* Convert to a CPL_TABLE */
323  cpl_msg_info (cpl_func, "Convert EOP data to cpl_table");
324  cpl_table * eop_table = gravity_eop_data_totable (eop_data, data_length);
325 
326  /* Check for a change in the CPL error state */
327  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
328 
329  applist = cpl_propertylist_new();
330 
331  /* Add the product category */
332  cpl_propertylist_append_string (applist, CPL_DFS_PRO_CATG, GRAVI_EOP_MAP);
333  cpl_propertylist_append_string (applist, "ESO PRO TECH", "CATALOG");
334  cpl_propertylist_append_string (applist, "ESO PRO TYPE", "IERS");
335 
336  /* Add a QC parameter */
337  gravity_eop_compute_qc (eop_table, applist, &mjd_lastfinal);
338 
339  timestamp_lastfinal = gravi_convert_to_timestamp (mjd_lastfinal);
340 
341  /* Saving the product */
342  filename = cpl_sprintf("GRAVI_EOP_PARAM.%s.fits", timestamp_lastfinal);
343  cpl_table_save (eop_table, applist, NULL, filename, CPL_IO_CREATE);
344 
345  cpl_msg_info (cpl_func,"Update the frameset");
346 
347  /* Updating the frameset */
348  cpl_frame * product_frame = cpl_frame_new();
349  cpl_frame_set_filename (product_frame, filename);
350  cpl_frame_set_tag (product_frame, CPL_DFS_PRO_CATG);
351  cpl_frame_set_type (product_frame, CPL_FRAME_TYPE_TABLE);
352  cpl_frame_set_group (product_frame, CPL_FRAME_GROUP_PRODUCT);
353  cpl_frame_set_level (product_frame, CPL_FRAME_LEVEL_FINAL);
354  cpl_frameset_insert (frameset, product_frame);
355  cpl_ensure_code (cpl_errorstate_is_equal(prestate), cpl_error_get_code());
356 
357  /* Cleanup */
358  cpl_propertylist_delete (applist);
359  cpl_table_delete (eop_table);
360  free(eop_data);
361  cpl_free (filename);
362  cpl_free (timestamp_lastfinal);
363 
364  gravi_msg_function_exit(1);
365  return (int)cpl_error_get_code();
366 }
367 
368 cpl_error_code gravity_eop_compute_qc (cpl_table * eop_table,
369  cpl_propertylist* header,
370  double * mjd_lastfinal)
371 {
372  double mjd_start;
373  double mjd_lastprediction;
374  int null;
375 
376  mjd_start = cpl_table_get_double (eop_table, "MJD", 0, &null);
377  for(int i = 0 ; i < cpl_table_get_nrow(eop_table); i++)
378  {
379  const char * flag = cpl_table_get_string(eop_table, "FLAG", i);
380  if(!strncmp(flag, "I", 1))
381  *mjd_lastfinal = cpl_table_get_double(eop_table, "MJD", i, &null);
382  if(!strncmp(flag, "P", 1))
383  mjd_lastprediction = cpl_table_get_double(eop_table, "MJD", i, &null);
384  }
385 
386  cpl_msg_info (cpl_func, "QC EOP MJD START = %.3f", mjd_start);
387  cpl_msg_info (cpl_func, "QC EOP MJD LAST FINAL = %.3f", *mjd_lastfinal);
388  cpl_msg_info (cpl_func, "QC EOP MJD LAST PREDICTION = %.3f", mjd_lastprediction);
389 
390  cpl_propertylist_append_double (header, "ESO QC EOP MJD START", mjd_start);
391  cpl_propertylist_append_double (header, "ESO QC EOP MJD LAST FINAL", *mjd_lastfinal);
392  cpl_propertylist_append_double (header, "ESO QC EOP MJD LAST PREDICTION", mjd_lastprediction);
393  cpl_propertylist_append_double (header, "MJD-OBS", *mjd_lastfinal);
394 
395  return CPL_ERROR_NONE;
396 }
char * gravity_eop_download_finals2000A(const char *eop_host, const char *eop_urlpath, int *data_length)
Retrieve the Earth Orientation Parameters computed by IERS.
Definition: gravi_eop.c:559
cpl_table * gravity_eop_data_totable(const char *eop_data, int data_length)
Export a raw string buffer containing EOP data to a CPL table.
Definition: gravi_eop.c:918