GRAVI Pipeline Reference Manual  0.9.6
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 
50 /*-----------------------------------------------------------------------------
51  Static variables
52  -----------------------------------------------------------------------------*/
53 
54 static const char gravity_eop_short[] = "Download the last values of the Earth Orientation Parameters and DUT from IERS.";
55 static const char gravity_eop_description[] =
56 "This recipe download the latest version of the Earth Orientation Parameter \n"
57 "and DUT from the IERS site. A web connection is required.\n"
58 "The recipe doesn't need any input, but it creates the following product:\n"
59 "gravity_eop_calib.fits " GRAVI_EOP_MAP "\n"
60 "\n";
61 
62 static const char gravity_eop_name[] = "gravity_eop";
63 
64 /*-----------------------------------------------------------------------------
65  Function code
66  -----------------------------------------------------------------------------*/
67 
68 /*----------------------------------------------------------------------------*/
78 /*----------------------------------------------------------------------------*/
79 int cpl_plugin_get_info(cpl_pluginlist * list)
80 {
81  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
82  cpl_plugin * plugin = &recipe->interface;
83 
84  if (cpl_plugin_init(plugin,
85  CPL_PLUGIN_API,
86  GRAVI_BINARY_VERSION,
87  CPL_PLUGIN_TYPE_RECIPE,
88  gravity_eop_name,
89  gravity_eop_short,
90  gravity_eop_description,
91  "Cesar Enrique Garcia Dabo",
92  PACKAGE_BUGREPORT,
93  "LL",
94  gravity_eop_create,
95  gravity_eop_exec,
96  gravity_eop_destroy)) {
97  cpl_msg_error(cpl_func, "Plugin initialization failed");
98  (void)cpl_error_set_where(cpl_func);
99  return 1;
100  }
101 
102  if (cpl_pluginlist_append(list, plugin)) {
103  cpl_msg_error(cpl_func, "Error adding plugin to list");
104  (void)cpl_error_set_where(cpl_func);
105  return 1;
106  }
107 
108  return 0;
109 }
110 
111 /*----------------------------------------------------------------------------*/
119 /*----------------------------------------------------------------------------*/
120 static int gravity_eop_create(cpl_plugin * plugin)
121 {
122  cpl_recipe * recipe;
123  cpl_parameter * p;
124 
125  /* Do not create the recipe if an error code is already set */
126  if (cpl_error_get_code() != CPL_ERROR_NONE) {
127  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
128  cpl_func, __LINE__, cpl_error_get_where());
129  return (int)cpl_error_get_code();
130  }
131 
132  if (plugin == NULL) {
133  cpl_msg_error(cpl_func, "Null plugin");
134  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
135  }
136 
137  /* Verify plugin type */
138  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
139  cpl_msg_error(cpl_func, "Plugin is not a recipe");
140  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
141  }
142 
143  /* Get the recipe */
144  recipe = (cpl_recipe *)plugin;
145 
146  /* Create the parameters list in the cpl_recipe object */
147  recipe->parameters = cpl_parameterlist_new();
148  if (recipe->parameters == NULL) {
149  cpl_msg_error(cpl_func, "Parameter list allocation failed");
150  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
151  }
152 
153  /* --eop_host */
154  p = cpl_parameter_new_value ("gravity.eop.eop_host",
155  CPL_TYPE_STRING,
156  "FTP Host to retrieve the EOP from",
157  "gravity.eop",
158  "ftp.iers.org");
159  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "eop_host");
160  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
161  cpl_parameterlist_append (recipe->parameters, p);
162 
163  /* --eop_urlpath */
164  p = cpl_parameter_new_value ("gravity.eop.eop_urlpath",
165  CPL_TYPE_STRING,
166  "FTP URL path of the EOP file to retrieve",
167  "gravity.eop",
168  "/products/eop/rapid/standard/finals2000A.data");
169  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "eop_urlpath");
170  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
171  cpl_parameterlist_append (recipe->parameters, p);
172 
173  return 0;
174 }
175 
176 /*----------------------------------------------------------------------------*/
182 /*----------------------------------------------------------------------------*/
183 static int gravity_eop_exec(cpl_plugin * plugin)
184 {
185 
186  cpl_recipe * recipe;
187  int recipe_status;
188  cpl_errorstate initial_errorstate = cpl_errorstate_get();
189 
190  /* Return immediately if an error code is already set */
191  if (cpl_error_get_code() != CPL_ERROR_NONE) {
192  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
193  cpl_func, __LINE__, cpl_error_get_where());
194  return (int)cpl_error_get_code();
195  }
196 
197  if (plugin == NULL) {
198  cpl_msg_error(cpl_func, "Null plugin");
199  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
200  }
201 
202  /* Verify plugin type */
203  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
204  cpl_msg_error(cpl_func, "Plugin is not a recipe");
205  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
206  }
207 
208  /* Get the recipe */
209  recipe = (cpl_recipe *)plugin;
210 
211  /* Verify parameter and frame lists */
212  if (recipe->parameters == NULL) {
213  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
214  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
215  }
216  if (recipe->frames == NULL) {
217  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
218  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
219  }
220 
221  /* Invoke the recipe */
222  recipe_status = gravity_eop(recipe->frames, recipe->parameters);
223 
224  if (!cpl_errorstate_is_equal(initial_errorstate)) {
225  /* Dump the error history since recipe execution start.
226  At this point the recipe cannot recover from the error */
227  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
228  }
229 
230  return recipe_status;
231 }
232 
233 /*----------------------------------------------------------------------------*/
239 /*----------------------------------------------------------------------------*/
240 static int gravity_eop_destroy(cpl_plugin * plugin)
241 {
242  cpl_recipe * recipe;
243 
244  if (plugin == NULL) {
245  cpl_msg_error(cpl_func, "Null plugin");
246  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
247  }
248 
249  /* Verify plugin type */
250  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
251  cpl_msg_error(cpl_func, "Plugin is not a recipe");
252  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
253  }
254 
255  /* Get the recipe */
256  recipe = (cpl_recipe *)plugin;
257 
258  cpl_parameterlist_delete(recipe->parameters);
259 
260  return 0;
261 }
262 
263 /*----------------------------------------------------------------------------*/
270 /*----------------------------------------------------------------------------*/
271 static int gravity_eop(cpl_frameset * frameset,
272  const cpl_parameterlist * parlist)
273 {
274  const char * eop_host;
275  const char * eop_urlpath;
276  cpl_propertylist * applist;
277 
278  /* Message */
279  gravity_print_banner ();
280  cpl_msg_set_time_on();
281  cpl_msg_set_component_on();
282  gravi_msg_function_start(1);
283 
284  /* Use the errorstate to detect an error in a function that does not
285  return an error code. */
286  cpl_errorstate prestate = cpl_errorstate_get();
287 
288  /* Retrieving eop_host */
289  eop_host = gravi_param_get_string (parlist, "gravity.eop.eop_host");
290 
291  /* Retrieving eop_urlpath */
292  eop_urlpath = gravi_param_get_string (parlist, "gravity.eop.eop_urlpath");
293 
294  if (!cpl_errorstate_is_equal(prestate)) {
295  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
296  "Could not retrieve the input "
297  "parameters");
298  }
299 
300 
301  /* Retrieve EOP file from the site */
302  const char * eop_data;
303  int data_length;
304  cpl_msg_info (cpl_func, "Retrieving EOP file ");
305  eop_data = gravity_eop_download_finals2000A (eop_host, eop_urlpath, &data_length);
306 
307  if (eop_data == NULL || !cpl_errorstate_is_equal(prestate)) {
308  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
309  "Could not download data from server");
310  }
311 
312  /* Convert to a CPL_TABLE */
313  cpl_msg_info (cpl_func, "Convert EOP data to cpl_table");
314  cpl_table * eop_table = gravity_eop_data_totable (eop_data, data_length);
315 
316  /* Check for a change in the CPL error state */
317  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
318 
319  applist = cpl_propertylist_new();
320 
321  /* Add the product category */
322  cpl_propertylist_append_string (applist, CPL_DFS_PRO_CATG, GRAVI_EOP_MAP);
323  cpl_propertylist_append_string (applist, "ESO PRO TECH", "CATALOG");
324  cpl_propertylist_append_string (applist, "ESO PRO TYPE", "IERS");
325 
326  /* Add a QC parameter */
327  gravity_eop_compute_qc (eop_table, applist);
328 
329  /* Saving the product */
330  cpl_table_save (eop_table, applist, NULL, "gravity_eop.fits", CPL_IO_CREATE);
331 
332  cpl_msg_info (cpl_func,"Update the frameset");
333 
334  /* Updating the frameset */
335  cpl_frame * product_frame = cpl_frame_new();
336  cpl_frame_set_filename (product_frame, "gravity_eop.fits");
337  cpl_frame_set_tag (product_frame, CPL_DFS_PRO_CATG);
338  cpl_frame_set_type (product_frame, CPL_FRAME_TYPE_TABLE);
339  cpl_frame_set_group (product_frame, CPL_FRAME_GROUP_PRODUCT);
340  cpl_frame_set_level (product_frame, CPL_FRAME_LEVEL_FINAL);
341  cpl_frameset_insert (frameset, product_frame);
342  cpl_ensure_code (cpl_errorstate_is_equal(prestate), cpl_error_get_code());
343 
344  /* Cleanup */
345  cpl_propertylist_delete (applist);
346  cpl_table_delete (eop_table);
347 
348  gravi_msg_function_exit(1);
349  return (int)cpl_error_get_code();
350 }
351 
352 cpl_error_code gravity_eop_compute_qc (cpl_table * eop_table,
353  cpl_propertylist* header)
354 {
355  double mjd_start;
356  double mjd_lastfinal;
357  double mjd_lastprediction;
358  int null;
359 
360  mjd_start = cpl_table_get_double (eop_table, "MJD", 0, &null);
361  for(int i = 0 ; i < cpl_table_get_nrow(eop_table); i++)
362  {
363  const char * flag = cpl_table_get_string(eop_table, "FLAG", i);
364  if(!strncmp(flag, "I", 1))
365  mjd_lastfinal = cpl_table_get_double(eop_table, "MJD", i, &null);
366  if(!strncmp(flag, "P", 1))
367  mjd_lastprediction = cpl_table_get_double(eop_table, "MJD", i, &null);
368  }
369 
370  cpl_msg_info (cpl_func, "QC EOP MJD START = %.3f", mjd_start);
371  cpl_msg_info (cpl_func, "QC EOP MJD LAST FINAL = %.3f", mjd_lastfinal);
372  cpl_msg_info (cpl_func, "QC EOP MJD LAST PREDICTION = %.3f", mjd_lastprediction);
373 
374  cpl_propertylist_append_double (header, "ESO QC EOP MJD START", mjd_start);
375  cpl_propertylist_append_double (header, "ESO QC EOP MJD LAST FINAL", mjd_lastfinal);
376  cpl_propertylist_append_double (header, "ESO QC EOP MJD LAST PREDICTION", mjd_lastprediction);
377  cpl_propertylist_append_double (header, "MJD-OBS", mjd_lastfinal);
378 
379  return CPL_ERROR_NONE;
380 }