MUSE Pipeline Reference Manual  1.0.2
muse_processinginfo.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2005-2013 European Southern Observatory
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 2 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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 /*----------------------------------------------------------------------------*
27  * Includes *
28  *----------------------------------------------------------------------------*/
29 #include <stdio.h>
30 #include <string.h>
31 #include <math.h>
32 #include <cpl.h>
33 
34 #include "muse_processing.h"
35 
36 #include "muse_utils.h"
37 
38 /*---------------------------------------------------------------------------*/
42 /*---------------------------------------------------------------------------*/
43 
46 /*----------------------------------------------------------------------------*
47  * Static variables *
48  *----------------------------------------------------------------------------*/
49 /*---------------------------------------------------------------------------*/
53 /*---------------------------------------------------------------------------*/
54 typedef struct muse_processinginfo_s {
55  struct muse_processinginfo_s *prev;
56  struct muse_processinginfo_s *next;
57  cpl_recipe *plugin;
58  cpl_recipeconfig *recipeconfig;
60  muse_processing_prepare_header_func *prepare_header;
62  muse_processing_get_frame_level_func *get_frame_level;
64  muse_processing_get_frame_mode_func *get_frame_mode;
66 
67 /*---------------------------------------------------------------------------*/
71 /*---------------------------------------------------------------------------*/
73 
74 /*---------------------------------------------------------------------------*/
78 /*---------------------------------------------------------------------------*/
79 
80 static muse_processinginfo_t *
81 muse_processinginfo_get(const cpl_recipe *aRecipe) {
82  if (muse_processinginfo != NULL) {
84  for (m = muse_processinginfo; m != NULL; m = m->next) {
85  if (m->plugin == aRecipe) {
86  return m;
87  }
88  }
89  }
90  return NULL;
91 }
92 
93 /*---------------------------------------------------------------------------*/
105 /*---------------------------------------------------------------------------*/
106 void
108 ( cpl_recipe *plugin,
109  cpl_recipeconfig *recipeconfig,
110  muse_processing_prepare_header_func *prepare_header,
111  muse_processing_get_frame_level_func *get_frame_level,
112  muse_processing_get_frame_mode_func *get_frame_mode) {
113 
115  if (muse_processinginfo == NULL) {
116  muse_processinginfo = cpl_calloc(1, sizeof(muse_processinginfo_t));
118  } else {
119  while (m->next != NULL) {
120  m = m->next;
121  }
122  m->next = cpl_calloc(1, sizeof(muse_processinginfo_t));
123  m->next->prev = m;
124  m = m->next;
125  }
126  m->plugin = plugin;
127  m->recipeconfig = recipeconfig;
128  m->prepare_header = prepare_header;
129  m->get_frame_level = get_frame_level;
130  m->get_frame_mode = get_frame_mode;
131 }
132 
133 /*---------------------------------------------------------------------------*/
141 /*---------------------------------------------------------------------------*/
142 void
143 muse_processinginfo_delete(cpl_recipe *aRecipe) {
145  if (m == NULL) {
146  return;
147  }
148  if (m == muse_processinginfo) {
149  muse_processinginfo = m->next;
150  if (muse_processinginfo != NULL) {
151  muse_processinginfo->prev = NULL;
152  }
153  } else {
154  m->prev->next = m->next;
155  if (m->next != NULL) {
156  m->next->prev = m->prev;
157  }
158  }
159  cpl_recipeconfig_delete(m->recipeconfig);
160  cpl_free(m);
161 }
162 
163 /*---------------------------------------------------------------------------*/
171 /*---------------------------------------------------------------------------*/
172 cpl_error_code muse_processing_prepare_header(const cpl_recipe *aRecipe,
173  const char *aFrametag,
174  cpl_propertylist *aHeader) {
176  return (m != NULL)? (* m->prepare_header)(aFrametag, aHeader): CPL_ERROR_NONE;
177 }
178 
179 /*---------------------------------------------------------------------------*/
186 /*---------------------------------------------------------------------------*/
187 cpl_frame_level
188 muse_processing_get_frame_level(const cpl_recipe *aRecipe,
189  const char *aFrametag) {
191  return (m != NULL)? (* m->get_frame_level)(aFrametag): CPL_FRAME_LEVEL_NONE;
192 }
193 
194 /*---------------------------------------------------------------------------*/
201 /*---------------------------------------------------------------------------*/
202 int
203 muse_processing_get_frame_mode(const cpl_recipe *aRecipe,
204  const char *aFrametag) {
206  return (m != NULL)?(* m->get_frame_mode)(aFrametag): MUSE_FRAME_MODE_ALL;
207 }
208 
209 /*---------------------------------------------------------------------------*/
215 /*---------------------------------------------------------------------------*/
216 cpl_recipeconfig *
217 muse_processing_get_recipeconfig(cpl_recipe *aRecipe) {
219  return (m != NULL)?m->recipeconfig: NULL;
220 }
221 
222 /*---------------------------------------------------------------------------*/
238 /*---------------------------------------------------------------------------*/
239 cpl_error_code
240 muse_processing_prepare_property(cpl_propertylist *aHeader, const char *aName,
241  cpl_type aType, const char *aDescription)
242 {
243  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
244  cpl_ensure_code(aName, CPL_ERROR_NULL_INPUT);
245 
246  cpl_error_code rc = CPL_ERROR_NONE;
247 
248  cpl_propertylist *list = cpl_propertylist_new();
249  cpl_propertylist_copy_property_regexp(list, aHeader, aName, 0);
250  if (cpl_propertylist_is_empty(list)) {
251  cpl_propertylist_delete(list);
252 
253  // The tag MUSE PRIVATE DOCUMENTATION is set in xmldoc.c and checked
254  // here:
255  // If it is not set (the normal case in a recipe), just an error
256  // message is generated in case of a missing header.
257  if (!cpl_propertylist_has(aHeader, "MUSE PRIVATE DOCUMENTATION")) {
258  cpl_msg_warning(__func__, "Property %s (%s) not used", aName,
259  aDescription);
260  return CPL_ERROR_DATA_NOT_FOUND;
261  }
262  // If this property is set (if the function is used from
263  // muse_xmldoc), then we add missing headers with some default
264  // values.
265  switch(aType) {
266  case CPL_TYPE_FLOAT:
267  cpl_propertylist_append_float(aHeader, aName, NAN);
268  break;
269  case CPL_TYPE_DOUBLE:
270  cpl_propertylist_append_double(aHeader, aName, NAN);
271  break;
272  case CPL_TYPE_STRING:
273  cpl_propertylist_append_string(aHeader, aName, "");
274  break;
275  case CPL_TYPE_INT:
276  cpl_propertylist_append_int(aHeader, aName, INT_MAX);
277  break;
278  case CPL_TYPE_LONG:
279  cpl_propertylist_append_long(aHeader, aName, LONG_MAX);
280  break;
281  case CPL_TYPE_BOOL:
282  cpl_propertylist_append_bool(aHeader, aName, FALSE);
283  break;
284  default:
285  return CPL_ERROR_INVALID_TYPE;
286  }
287 
288  /* XXX ugly: copied code from below for the moment to keep the case *
289  * of the documentation working */
290  cpl_property *property = cpl_propertylist_get_property(aHeader, aName);
291  if (aDescription != NULL && strlen(aDescription)>0) {
292  rc = cpl_property_set_comment(property, aDescription);
293  }
294  cpl_type type = cpl_property_get_type(property);
295  if (type != aType) {
296  cpl_msg_warning(__func__, "Type of property %s is %s but should be %s",
297  aName, cpl_type_get_name(type), cpl_type_get_name(aType));
298  return CPL_ERROR_TYPE_MISMATCH;
299  }
300  return CPL_ERROR_NONE;
301  } /* empty list of properties of regexp search */
302 
303  /* loop through the properties that matched the regular expressions */
304  int i;
305  for (i = 0; i < cpl_propertylist_get_size(list); i++) {
306  cpl_property *prop = cpl_propertylist_get(list, i);
307  cpl_property *property =
308  cpl_propertylist_get_property(aHeader, cpl_property_get_name(prop));
309  if (aDescription != NULL && strlen(aDescription)>0) {
310  rc = cpl_property_set_comment(property, aDescription);
311  }
312  cpl_type type = cpl_property_get_type(property);
313  if (type != aType) {
314  cpl_msg_warning(__func__, "Type of property %s is %s but should be %s",
315  aName, cpl_type_get_name(type), cpl_type_get_name(aType));
316  cpl_propertylist_delete(list);
317  return CPL_ERROR_TYPE_MISMATCH;
318  }
319  } /* for i (all regexp-found properties) */
320  cpl_propertylist_delete(list);
321  return rc;
322 }
323 
int muse_processing_get_frame_mode(const cpl_recipe *aRecipe, const char *aFrametag)
Get the mode for a product frame with a certain tag.
cpl_error_code muse_processing_prepare_header(const cpl_recipe *aRecipe, const char *aFrametag, cpl_propertylist *aHeader)
Prepare and check a FITS header for a certain frame tag.
struct muse_processinginfo_s muse_processinginfo_t
cpl_frame_level muse_processing_get_frame_level(const cpl_recipe *aRecipe, const char *aFrametag)
Get the level for a product frame with a certain tag.
void muse_processinginfo_delete(cpl_recipe *aRecipe)
Clear all information from the processing info and from the recipe config.
cpl_recipeconfig * muse_processing_get_recipeconfig(cpl_recipe *aRecipe)
Get the recipe (frame) configuration.
void muse_processinginfo_register(cpl_recipe *plugin, cpl_recipeconfig *recipeconfig, muse_processing_prepare_header_func *prepare_header, muse_processing_get_frame_level_func *get_frame_level, muse_processing_get_frame_mode_func *get_frame_mode)
Register extended functionalities for MUSE recipes.
static muse_processinginfo_t * muse_processinginfo_get(const cpl_recipe *aRecipe)
Get processinginfo for a certain recipe.
static muse_processinginfo_t * muse_processinginfo
cpl_error_code muse_processing_prepare_property(cpl_propertylist *aHeader, const char *aName, cpl_type aType, const char *aDescription)
Prepare and check the specified property.