LALInferenceXML.c 13.2 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
	printf("Finished walking through param list\n");
134
  valuearrays=calloc(Nfields,sizeof(void *));
135
  VOTABLE_DATATYPE *dataTypes=calloc(Nfields,sizeof(VOTABLE_DATATYPE));
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  /* 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;
		}
	}

156
  UINT4 row,col;
157
  printf("creating TABLEDATA node\n");
158
159
160
161
162
163
     /* 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;
    }
164
	printf("TABLEDATA = %lx\n",(unsigned long int)xmlTABLEDATAnode);
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    /* ---------- 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 */
182
        for ( col = 0; col < Nfields; col ++ )
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
          {
            /* 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;
198
						printf("Creating node for datatype %i, value %lf\n",dataTypes[col],((double *)valuearrays[col])[0]);
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
            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 */

221
  printf("Done creating TABLEDATA tree\n");
222
  
223
224
  /* Create a TABLE from the FIELDs and TABLEDATA nodes */
  sprintf(tablename,"LALInferenceXMLTable");
225
226
227
228
	printf("Creating table node\n");
	printf("fieldNodeList = %lx\n",(long unsigned int)fieldNodeList);
	printf("xmlTABLEDATAnode = %lx\n",(long unsigned int)xmlTABLEDATAnode);

229
  VOTtableNode= XLALCreateVOTTableNode (tablename, fieldNodeList, xmlTABLEDATAnode );
230
  printf("VOTTableNode = %lx\n",(long unsigned int)VOTtableNode);
231
  /* Attach PARAMs to TABLE node */
232
233
  if(!(xmlAddChildList(VOTtableNode,paramNodeList))){
    XLALPrintError("%s: xmlAddChild failed\n",fn);
234
235
236
    err=XLAL_EFAILED;
    goto failed;
  }
237
  
238
  return(VOTtableNode);
239
240
241
242
243
244
  
  failed:
      XLAL_ERROR_NULL ( fn, err );

  return(NULL);
  
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
}

/**
 * \brief Serializes a \c LALInferenceVariables structure 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.
 *
 * \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) {
        /* clean up */
        xmlFreeNodeList(xmlChildNodeList);
        XLALPrintError("Couldn't create PARAM node: %s.%s\n", name,marker->name);
        XLAL_ERROR_NULL(fn, XLAL_EFAILED);
    }
    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
 * \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.
 *
 * \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
 * 
 */

316
317
318
319
320
321
322
323
324
325
326
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)
327
		return(XLALCreateVOTFieldNode(varitem->name,unitName,VOT_CHAR,"*"));
328
329
330
331
332
333
	
  /* Check the type of the item */
  vo_type=LALInferenceVariableType2VOT(varitem->type);
	
  return(XLALCreateVOTFieldNode(varitem->name,unitName,vo_type,NULL));
}
334
335
336
337
338
339
340
341
342
343
344

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));

345
346
	/* Special case for string */
	if(varitem->type==LALINFERENCE_string_t)
347
		return(XLALCreateVOTParamNode(varitem->name,unitName,VOT_CHAR,"*",varitem->value));
348
	
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  /* 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;}
  }
}