LALInferenceXML.c 12.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
 *  Copyright (C) 2011 John Veitch
 *  
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with with program; see the file COPYING. If not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 */

/**
 * \file
 * \ingroup XML
 * \brief Implementation of the VOTable serializers XML LALInference API
 */

#include <string.h>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>

#include <lal/XLALError.h>

#include <lal/LALXML.h>
#include <lal/LALXMLVOTableCommon.h>
#include <lal/LALXMLVOTableSerializers.h>
#include <lal/LALInferenceXML.h>

#define INT4STR_MAXLEN          15
#define REAL8STR_MAXLEN         25
#define NAMESTR_MAXLEN          256

/**
 * \brief Serializes an array of \c LALInferenceVariables into a VOTable XML %node
 *
 * This function takes a \c LALInferenceVariables structure and serializes it into a VOTable
 * \c RESOURCE %node identified by the given name. The returned \c xmlNode can then be
 * embedded into an existing %node hierarchy or turned into a full VOTable document.
 * A VOTable Table element is returned, with fixed variables as PARAMs and the varying ones as FIELDs.
 * 
 * \param varsArray [in] Pointer to an array of \c LALInferenceVariables structures to be serialized
 * \param N [in] Number of items in the array
 * 
 * \return A pointer to a \c xmlNode that holds the VOTable fragment that represents
 * the \c LALInferenceVariables array.
 * In case of an error, a null-pointer is returned.\n
 * \b Important: the caller is responsible to free the allocated memory (when the
 * fragment isn't needed anymore) using \c xmlFreeNode. Alternatively, \c xmlFreeDoc
 * can be used later on when the returned fragment has been embedded in a XML document.
 *
 * \sa XLALCreateVOTParamNode
 * \sa XLALCreateVOTResourceNode
 *
 * \author John Veitch\n
 * 
 */
67
68
69



70
xmlNodePtr XLALInferenceVariablesArray2VOTTable(const LALInferenceVariables *varsArray, UINT4 N)
71
{
72
73
  xmlNodePtr fieldNodeList=NULL;
  xmlNodePtr paramNodeList=NULL;
74
  xmlNodePtr xmlTABLEDATAnode=NULL;
75
  xmlNodePtr VOTtableNode=NULL;
76
  xmlNodePtr tmpNode=NULL;
77
  xmlNodePtr field_ptr,param_ptr;
78
79
  LALInferenceVariableItem *varitem=NULL;
  void **valuearrays=NULL;
80
  UINT4 Nfields=0,i,j;
81
  const char *fn = __func__;
82
  char tablename[512]="\0";
83
84
85
  int err;

  
86
87
88
89
90
91
92
	/* Sanity check input */
	if(!varsArray) {
		XLALPrintError("Received null varsArray pointer");
		XLAL_ERROR_NULL(__func__,XLAL_EFAULT);
	}
	if(N==0) return(NULL);
	
93
94
	field_ptr=fieldNodeList;
	param_ptr=paramNodeList;
95
	varitem=varsArray[0].head;
96
	
97
  /* Build a list of PARAM and FIELD elements */
98
99
100
101
  while(varitem)
	{
		switch(varitem->vary){
			case LALINFERENCE_PARAM_LINEAR:
102
			case LALINFERENCE_PARAM_CIRCULAR:
103
104
			case LALINFERENCE_PARAM_OUTPUT:
			{
105
				tmpNode=LALInferenceVariableItem2VOTFieldNode(varitem);
106
107
108
109
110
111
				if(field_ptr) field_ptr=xmlAddNextSibling(field_ptr,tmpNode);
				else {field_ptr=tmpNode; fieldNodeList=field_ptr;}
				if(!field_ptr) {
					XLALPrintError ("%s: xmlAddNextSibling() failed to add next field node.\n", fn );
					XLAL_ERROR_NULL(fn, XLAL_EFAILED);
				}
112
				Nfields++;
113
114
115
116
				break;
			}
			case LALINFERENCE_PARAM_FIXED:
			{
117
				tmpNode=LALInferenceVariableItem2VOTParamNode(varitem);
118
119
120
121
122
123
				if(param_ptr) param_ptr=xmlAddNextSibling(param_ptr,tmpNode);
				else {param_ptr=tmpNode; paramNodeList=param_ptr;}
				if(!param_ptr) {
					XLALPrintError ("%s: xmlAddNextSibling() failed to add next param node.\n", fn );
					XLAL_ERROR_NULL(fn, XLAL_EFAILED);
				}
124
125
126
127
128
129
130
131
132
				break;
			}
			default: 
			{
				XLALPrintError("Unknown param vary type");
			}
		}
		varitem=varitem->next;
	}
133
  valuearrays=calloc(Nfields,sizeof(void *));
134
  VOTABLE_DATATYPE *dataTypes=calloc(Nfields,sizeof(VOTABLE_DATATYPE));
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  /* Build array of DATA for fields */
	for(j=0,varitem=varsArray[0].head; varitem; varitem=varitem->next)
	{
		switch(varitem->vary){
			case LALINFERENCE_PARAM_LINEAR:
			case LALINFERENCE_PARAM_CIRCULAR:
			case LALINFERENCE_PARAM_OUTPUT:
			{
				UINT4 typesize = LALInferenceTypeSize[LALInferenceGetVariableType(&varsArray[0],varitem->name)];
				valuearrays[j]=calloc(N,typesize);
				dataTypes[j]=LALInferenceVariableType2VOT(varitem->type);
				for(i=0;i<N;i++)
					memcpy((char *)valuearrays[j]+i*typesize,LALInferenceGetVariable(&varsArray[i],varitem->name),typesize);
				j++;
			}	
			default:
				continue;
		}
	}

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  UINT4 row,col;
     /* create TABLEDATA node */
    if ( ( xmlTABLEDATAnode = xmlNewNode ( NULL, CAST_CONST_XMLCHAR("TABLEDATA") ))== NULL ) {
      XLALPrintError ("%s: xmlNewNode() failed to create 'TABLEDATA' node.\n", fn );
      err = XLAL_ENOMEM;
      goto failed;
    }
    /* ---------- loop over data-arrays and generate each table-row */
    for ( row = 0; row < N; row ++ )
      {
        /* create TR node */
        xmlNodePtr xmlThisRowNode = NULL;
        if ( (xmlThisRowNode = xmlNewNode ( NULL, CAST_CONST_XMLCHAR("TR") )) == NULL ) {
          XLALPrintError ("%s: xmlNewNode() failed to create new 'TR' node.\n", fn );
          err = XLAL_EFAILED;
          goto failed;
        }
        if ( xmlAddChild(xmlTABLEDATAnode, xmlThisRowNode ) == NULL ) {
          XLALPrintError ("%s: failed to insert 'TR' node into 'TABLEDATA' node.\n", fn );
          err = XLAL_EFAILED;
          goto failed;
        }

        /* ----- loop over columns and generate each table element */
179
        for ( col = 0; col < Nfields; col ++ )
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
          {
            /* create TD node */
            xmlNodePtr xmlThisEntryNode = NULL;
            if ( (xmlThisEntryNode = xmlNewNode ( NULL, CAST_CONST_XMLCHAR("TD") )) == NULL ) {
              XLALPrintError ("%s: xmlNewNode() failed to create new 'TD' node.\n", fn );
              err = XLAL_EFAILED;
              goto failed;
            }
            if ( xmlAddChild(xmlThisRowNode, xmlThisEntryNode ) == NULL ) {
              XLALPrintError ("%s: failed to insert 'TD' node into 'TR' node.\n", fn );
              err = XLAL_EFAILED;
              goto failed;
            }

            const char* tmptxt;
            if ( (tmptxt = XLALVOTprintfFromArray ( dataTypes[col], NULL, valuearrays[col], row )) == NULL ){
              XLALPrintError ("%s: XLALVOTprintfFromArray() failed for row = %d, col = %d. errno = %d.\n", fn, row, col, xlalErrno );
              err = XLAL_EFUNC;
              goto failed;
            }

            xmlNodePtr xmlTextNode;
            if ( (xmlTextNode = xmlNewText (CAST_CONST_XMLCHAR(tmptxt) )) == NULL ) {
              XLALPrintError("%s: xmlNewText() failed to turn text '%s' into node\n", fn, tmptxt );
              err = XLAL_EFAILED;
              goto failed;
            }
            if ( xmlAddChild(xmlThisEntryNode, xmlTextNode ) == NULL ) {
              XLALPrintError ("%s: failed to insert text-node node into 'TD' node.\n", fn );
              err = XLAL_EFAILED;
              goto failed;
            }

          } /* for col < numFields */

      } /* for row < numRows */

217
  
218
219
  /* Create a TABLE from the FIELDs and TABLEDATA nodes */
  sprintf(tablename,"LALInferenceXMLTable");
220

221
  VOTtableNode= XLALCreateVOTTableNode (tablename, fieldNodeList, xmlTABLEDATAnode );
222
  /* Attach PARAMs to TABLE node */
223
224
  if(!(xmlAddChildList(VOTtableNode,paramNodeList))){
    XLALPrintError("%s: xmlAddChild failed\n",fn);
225
226
227
    err=XLAL_EFAILED;
    goto failed;
  }
228
  
229
  return(VOTtableNode);
230
231
232
233
234
235
  
  failed:
      XLAL_ERROR_NULL ( fn, err );

  return(NULL);
  
236
237
238
239
240
241
}

/**
 * \brief Serializes a \c LALInferenceVariables structure into a VOTable XML %node
 *
 * This function takes a \c LALInferenceVariables structure and serializes it into a VOTable
John Douglas Veitch's avatar
John Douglas Veitch committed
242
 * \c PARAM %node identified by the given name. The returned \c xmlNode can then be
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
 * embedded into an existing %node hierarchy or turned into a full VOTable document.
 *
 * \param vars [in] Pointer to the \c LALInferenceVariables structure to be serialized
 * \param name [in] Unique identifier of this particular \c LALInferenceVariables structure instance
 *
 * \return A pointer to a \c xmlNode that holds the VOTable fragment that represents
 * the \c LALInferenceVariables structure.
 * In case of an error, a null-pointer is returned.\n
 * \b Important: the caller is responsible to free the allocated memory (when the
 * fragment isn't needed anymore) using \c xmlFreeNode. Alternatively, \c xmlFreeDoc
 * can be used later on when the returned fragment has been embedded in a XML document.
 *
 * \sa LALInferenceVariableItem2VOTParamNode
 *
 * \author John Veitch\n
 * 
 */
xmlNodePtr XLALInferenceVariables2VOTNode (const LALInferenceVariables *const vars,const char *name)
{
  
  /* set up local variables */
  const char *fn = __func__;
  xmlNodePtr xmlChildNodeList = NULL;
  LALInferenceVariableItem *marker=vars->head;
  xmlNodePtr *xmlChildNodePtr=&xmlChildNodeList;

  
  /* Walk through the LALInferenceVariables adding each one */
  while(marker){
    *xmlChildNodePtr = (LALInferenceVariableItem2VOTParamNode(marker));
        if(!*xmlChildNodePtr) {
John Douglas Veitch's avatar
John Douglas Veitch committed
274
275
276
277
					/* clean up */
					xmlFreeNodeList(xmlChildNodeList);
					XLALPrintError("Couldn't create PARAM node: %s.%s\n", name,marker->name);
					XLAL_ERROR_NULL(fn, XLAL_EFAILED);
278
279
280
281
282
283
284
285
286
287
288
    }
    marker=marker->next;
    xmlChildNodePtr = &((*xmlChildNodePtr)->next);
  }
  return(xmlChildNodeList);
}

/**
 * \brief Serializes a \c LALInferenceVariableItem structure into a VOTable XML %node
 *
 * This function takes a \c LALInferenceVariableItem structure and serializes it into a VOTable
John Douglas Veitch's avatar
John Douglas Veitch committed
289
 * \c FIELD %node identified by the given name. The returned \c xmlNode can then be
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
 * embedded into an existing %node hierarchy or turned into a full VOTable document.
 *
 * \param varitem [in] Pointer to the \c LALInferenceVariables structure to be serialized
 * 
 * \return A pointer to a \c xmlNode that holds the VOTable fragment that represents
 * the \c LALInferenceVariableItem structure.
 * In case of an error, a null-pointer is returned.\n
 * \b Important: the caller is responsible to free the allocated memory (when the
 * fragment isn't needed anymore) using \c xmlFreeNode. Alternatively, \c xmlFreeDoc
 * can be used later on when the returned fragment has been embedded in a XML document.
 *
 * \sa XLALCreateVOTParamNode
 * 
 * \author John Veitch\n
 * 
 */

307
308
309
310
311
312
313
314
315
316
317
xmlNodePtr LALInferenceVariableItem2VOTFieldNode(LALInferenceVariableItem *varitem)
{
  VOTABLE_DATATYPE vo_type;
  CHAR *unitName={0};
  
  /* Special case for matrix */
  if(varitem->type==LALINFERENCE_gslMatrix_t)
    return(XLALgsl_matrix2VOTNode((gsl_matrix *)varitem->value, varitem->name, unitName));
	
	/* Special case for string */
	if(varitem->type==LALINFERENCE_string_t)
318
		return(XLALCreateVOTFieldNode(varitem->name,unitName,VOT_CHAR,"*"));
319
320
321
322
323
324
	
  /* Check the type of the item */
  vo_type=LALInferenceVariableType2VOT(varitem->type);
	
  return(XLALCreateVOTFieldNode(varitem->name,unitName,vo_type,NULL));
}
325
326
327
328
329
330
331
332
333
334
335

xmlNodePtr LALInferenceVariableItem2VOTParamNode(LALInferenceVariableItem *varitem)
{
  VOTABLE_DATATYPE vo_type;
  CHAR *unitName={0};
  CHAR valString[VARVALSTRINGSIZE_MAX]="";
  
  /* Special case for matrix */
  if(varitem->type==LALINFERENCE_gslMatrix_t)
    return(XLALgsl_matrix2VOTNode((gsl_matrix *)varitem->value, varitem->name, unitName));

336
337
	/* Special case for string */
	if(varitem->type==LALINFERENCE_string_t)
338
		return(XLALCreateVOTParamNode(varitem->name,unitName,VOT_CHAR,"*",varitem->value));
339
	
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
  /* Check the type of the item */
  vo_type=LALInferenceVariableType2VOT(varitem->type);
  
  LALInferencePrintVariableItem(valString, varitem);
  
  return(XLALCreateVOTParamNode(varitem->name,unitName,vo_type,NULL,valString));
}

/**
 * \brief Convert a \c LALInferenceVariableType into a VOType
 */
VOTABLE_DATATYPE LALInferenceVariableType2VOT(const LALInferenceVariableType litype){
  
  switch(litype){
    case LALINFERENCE_INT4_t: 		return VOT_INT4;
    case LALINFERENCE_INT8_t: 		return VOT_INT8;
    case LALINFERENCE_UINT4_t: 		return VOT_INT8; /* Need a signed INT8 to store an unsigned UINT4 */
    case LALINFERENCE_REAL4_t:		return VOT_REAL4;
    case LALINFERENCE_REAL8_t:		return VOT_REAL8;
    case LALINFERENCE_COMPLEX8_t: 	return VOT_COMPLEX8;
    case LALINFERENCE_COMPLEX16_t:	return VOT_COMPLEX16;
    case LALINFERENCE_string_t:		return VOT_CHAR;
    default: {XLALPrintError("Unsupported LALInferenceVarableType"); return VOT_DATATYPE_LAST;}
  }
}