Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
ReadPulsarParFile.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2013 Jolien Creighton, Matt Pitkin
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/**
21 * \author Matt Pitkin
22 * \date 2013
23 * \file
24 * \ingroup lalpulsar_general
25 * \brief Functions to read TEMPO pulsar parameter files
26 *
27 Functions for reading pulsar parameters from TEMPO .par files.
28
29 # Prototypes
30
31
32
33 # Description
34
35 Radio astronomers fit pulsar parameters using TEMPO(2) which will output
36 the parameters in a <tt>.par</tt> file. The values allowed in this file can be
37 found in the TEMPO documentation. Two function are available to extract these
38 parameters from the <tt>.par</tt> files:
39 <ul>
40 <li>\c XLALReadTEMPOParFileOrig - this will read parameters into a \c BinaryPulsarParams structure and set
41 any unused parameters to zero or \c NULL. To use this you must know the correct parameter name within
42 the structure. This is deprecated in favour of \c XLALReadTEMPOParFile and is no longer maintained</li>
43 <li>\c XLALReadTEMPOParFile - this reads the parameters into a linked list \c PulsarParameters structure, from which the
44 parameters can be accessed using the appropriate access function. These use a hash table to quick look-up.
45 The parameters are assigned names, which are used as the hash table keys, which are fully uppercase
46 versions of the TEMPO parameter names.
47 </ul>
48 All parameters read in are converted into SI units.
49
50 Functions are is also included which converts a string containing the right ascension or
51 declination in the format <tt>ddd/hh:mm:ss.s</tt> or <tt>ddd/hhmmss.s</tt>
52 (as is given in the <tt>.par</tt> file) into a \c REAL8 value in
53 radians.
54
55 # Notes
56
57*/
58
59#include <config.h>
60#include <string.h>
61#include <math.h>
62#include <locale.h>
63#include <ctype.h>
64#ifdef HAVE_UNISTD_H
65#include <unistd.h>
66#endif
67#include <lal/LALConstants.h>
68#include <lal/LALStdlib.h>
69#include <lal/LALString.h>
70#include <lal/ComputeFstat.h>
71#include <lal/TranslateAngles.h>
72#include <lal/TranslateMJD.h>
73#include <lal/LALHashFunc.h>
74#include <lal/ReadPulsarParFile.h>
75
76#ifdef __GNUC__
77#define UNUSED __attribute__ ((unused))
78#else
79#define UNUSED
80#endif
81
82
83#define DAYSTOSECS 86400.0 /* number of seconds in an SI day */
84
85size_t PulsarTypeSize[5] = {
86 sizeof( UINT4 ),
87 sizeof( REAL8 ),
88 sizeof( REAL8Vector * ),
89 sizeof( CHAR ) *PULSAR_PARNAME_MAX,
90 sizeof( void * )
91};
92
93
94/** Array for conversion from lowercase to uppercase */
95static const CHAR a2A[256] = {
96 ['a'] = 'A', ['b'] = 'B', ['c'] = 'C', ['d'] = 'D', ['e'] = 'E', ['f'] = 'F', ['g'] = 'G', ['h'] = 'H',
97 ['i'] = 'I', ['j'] = 'J', ['k'] = 'K', ['l'] = 'L', ['m'] = 'M', ['n'] = 'N', ['o'] = 'O', ['p'] = 'P',
98 ['q'] = 'Q', ['r'] = 'R', ['s'] = 'S', ['t'] = 'T', ['u'] = 'U', ['v'] = 'V', ['w'] = 'W', ['x'] = 'X',
99 ['y'] = 'Y', ['z'] = 'Z'
100};
101
102
103/** \brief Convert string to uppercase */
104static void strtoupper( CHAR *s )
105{
106 /* convert everything to uppercase */
107 CHAR c;
108 for ( ; *s; ++s ) {
109 if ( ( c = a2A[( int )( *s )] ) ) {
110 *s = c;
111 }
112 }
113}
114
115/* hash functions copied from LALInference.c */
116typedef struct taghash_elem {
117 const char *name;
118 PulsarParam *itemPtr;
119} hash_elem;
120
121static void *new_elem( const char *name, PulsarParam *itemPtr )
122{
123 hash_elem e = { .name = name, .itemPtr = itemPtr };
124 return memcpy( XLALMalloc( sizeof( e ) ), &e, sizeof( e ) );
125};
126
127static void del_elem( void *elem )
128{
129 XLALFree( elem );
130}
131
132
133/* Compute a hash value based on element */
134static UINT8 PulsarHash( const void *elem );
135static UINT8 PulsarHash( const void *elem )
136{
137 if ( !elem ) {
139 }
140 size_t len = strnlen( ( ( const hash_elem * )elem )->name, PULSAR_PARNAME_MAX );
141 return ( XLALCityHash64( ( ( const hash_elem * )elem )->name, len ) );
142}
143
144
145static int PulsarHashElemCmp( const void *elem1, const void *elem2 );
146static int PulsarHashElemCmp( const void *elem1, const void *elem2 )
147{
148 if ( !elem1 || !elem2 ) {
150 }
151 return ( strncmp( ( ( const hash_elem * )elem1 )->name, ( ( const hash_elem * )elem2 )->name, PULSAR_PARNAME_MAX ) );
152}
153
154
155/** \brief Get a pointer to a parameter of a given name from a \c PulsarParameters structure
156 *
157 * Note this function can only be used internally.
158 */
160{
161 /* (this function is only to be used internally) */
162 /* Returns pointer to item for given item name. */
163 if ( pars == NULL ) {
164 return NULL;
165 }
166 if ( pars->nparams == 0 ) {
167 return NULL;
168 }
169
170 PulsarParam *this = pars->head;
171
172 /* loop through all values checking the name */
173 while ( this != NULL ) {
174 if ( !strcmp( this->name, name ) ) {
175 break;
176 } else {
177 this = this->next;
178 }
179 }
180
181 return ( this );
182}
183
184
185/** \brief Get a pointer to a parameter of a given name from a \c PulsarParameters structure
186 *
187 * This function will return a pointer to the parameter. It will initially try and use the parameter's hash name,
188 * otherwise it will use \c PulsarGetParamItemSlow to loop through all parameters.
189 *
190 * Note this function can only be used internally.
191 */
193{
194 /* (this function is only to be used internally) */
195 /* Returns pointer to item for given item name. */
196 hash_elem tmp;
197 const hash_elem *match = NULL;
198
199 CHAR upperName[PULSAR_PARNAME_MAX];
201 strtoupper( upperName );
202
203 if ( pars == NULL ) {
204 return NULL;
205 }
206 if ( pars->nparams == 0 ) {
207 return NULL;
208 }
209 if ( !pars->hash_table ) {
210 return PulsarGetParamItemSlow( pars, upperName );
211 }
212
213 tmp.name = upperName;
214 XLALHashTblFind( pars->hash_table, &tmp, ( const void ** )&match );
215 if ( !match ) {
216 return NULL;
217 }
218
219 return match->itemPtr;
220}
221
222
223void *PulsarGetParam( const PulsarParameters *pars, const CHAR *name )
224{
225 /* Return the value of variable name from the pars structure */
226 PulsarParam *item = PulsarGetParamItem( pars, name );
227 if ( !item ) {
228 XLAL_ERROR_NULL( XLAL_EFAILED, "Entry \"%s\" not found.", name );
229 }
230
231 return ( item->value );
232}
233
234
236{
237 return PulsarGetParamItem( pars, name )->type;
238}
239
240
242{
243 /* check type is a REAL8 */
244 if ( PulsarGetParamType( pars, name ) == PULSARTYPE_REAL8_t ) {
245 return *( REAL8 * )PulsarGetParam( pars, name );
246 } else {
247 XLAL_ERROR_REAL8( XLAL_EINVAL, "Used wrong type for required parameter" );
248 }
249}
250
251
253{
254 /* if parameter is there return it otherwise return zero */
255 return PulsarCheckParam( pars, name ) ? PulsarGetREAL8Param( pars, name ) : 0.;
256}
257
258
260{
261 /* check type is a UINT4 */
262 if ( PulsarGetParamType( pars, name ) == PULSARTYPE_UINT4_t ) {
263 return *( UINT4 * )PulsarGetParam( pars, name );
264 } else {
265 XLAL_ERROR( XLAL_EINVAL, "Used wrong type for required parameter" );
266 }
267}
268
269
271{
272 /* if parameter is there return it otherwise return zero */
273 return PulsarCheckParam( pars, name ) ? PulsarGetUINT4Param( pars, name ) : 0;
274}
275
276
278{
279 /* check type is a string */
280 if ( PulsarGetParamType( pars, name ) == PULSARTYPE_string_t ) {
281 CHAR *rvalue = *( CHAR ** )PulsarGetParam( pars, name );
282 return rvalue;
283 } else {
284 XLAL_ERROR_NULL( XLAL_EINVAL, "Used wrong type for required parameter" );
285 }
286}
287
288
290{
291 /* check type is a REAL8Vector */
293 return *( REAL8Vector ** )PulsarGetParam( pars, name );
294 } else {
295 XLAL_ERROR_NULL( XLAL_EINVAL, "Used wrong type for required parameter" );
296 }
297}
298
299
301{
302 /* split the input name into the parameter name and an index e.g. FB0 into FB and 0, or GLEP_1 */
303 CHAR *namecopy = NULL, *token;
304 namecopy = XLALStringDuplicate( name );
305 REAL8 val = 0.;
306
307 if ( strchr( name, '_' ) ) { /* check for underscore delimiting numbers */
308 token = strtok( namecopy, "_" );
309 } else { /* name delimited by just numbers */
310 token = strtok( namecopy, "0123456789" );
311 }
312
313 const REAL8Vector *vpars = PulsarGetREAL8VectorParam( pars, token );
314
315 /* get the index value of the parameter name */
316 INT4 idx = -1;
317 INT4 loc = strlen( token );
318 if ( name[loc] == '_' ) {
319 loc++;
320 }
321 if ( sscanf( name + loc, "%d", &idx ) != 1 ) {
322 XLAL_ERROR_REAL8( XLAL_EINVAL, "Input parameter (%s) problem", name );
323 }
324
325 /* for glitch parameters GL, or WAVE parameters the index starts at 1, so shift it */
326 if ( !strncmp( name, "GL", 2 ) || !strncmp( name, "WAVE", 4 ) ) {
327 idx--;
328 }
329 if ( idx < 0 || ( UINT4 )idx > vpars->length - 1 ) {
330 XLAL_ERROR_REAL8( XLAL_EINVAL, "Input parameter index %d is wrong", idx );
331 }
332
333 val = vpars->data[idx];
334
335 XLALFree( namecopy );
336
337 return val;
338}
339
340
341void *PulsarGetParamErr( const PulsarParameters *pars, const CHAR *name )
342{
343 /* Return the error value of variable name from the pars structure */
344 PulsarParam *item = PulsarGetParamItem( pars, name );
345 if ( !item ) {
346 XLAL_ERROR_NULL( XLAL_EFAILED, "Entry \"%s\" not found.", name );
347 }
348
349 return ( item->err );
350}
351
352
354{
355 /* return the fit flag value */
356 PulsarParam *item = PulsarGetParamItem( pars, name );
357 if ( !item ) {
358 XLAL_ERROR_NULL( XLAL_EFAILED, "Entry \"%s\" not found.", name );
359 }
360
361 if ( item->fitFlag == NULL ) {
362 return NULL;
363 } else {
364 if ( item->fitFlag->data == NULL ) {
365 return NULL;
366 } else {
367 return item->fitFlag->data;
368 }
369 }
370}
371
372
374{
375 /* return the fit flag value(s) */
376 PulsarParam *item = PulsarGetParamItem( pars, name );
377 if ( !item ) {
378 XLAL_ERROR_NULL( XLAL_EFAILED, "Entry \"%s\" not found.", name );
379 }
380
381 if ( item->fitFlag == NULL ) {
382 return NULL;
383 } else {
384 return item->fitFlag;
385 }
386}
387
388
390{
391 /* Return the error value of variable name from the pars structure */
392 /* check type is a REAL8 */
393 if ( PulsarGetParamType( pars, name ) == PULSARTYPE_REAL8_t ) {
394 void *val = PulsarGetParamErr( pars, name );
395 if ( val == NULL ) {
396 return 0.; /* if no error is present return 0 */
397 } else {
398 return *( REAL8 * )val;
399 }
400 } else {
401 XLAL_ERROR_REAL8( XLAL_EINVAL, "Used wrong type for required parameter" );
402 }
403}
404
405
407{
408 /* Return the error value of variable name from the pars structure */
409 /* check type is a REAL8 */
411 void *val = PulsarGetParamErr( pars, name );
412 if ( val == NULL ) {
413 return NULL; /* if no error is present return NULL */
414 } else {
415 return *( REAL8Vector ** )val;
416 }
417 } else {
418 XLAL_ERROR_NULL( XLAL_EINVAL, "Used wrong type for required parameter" );
419 }
420}
421
422
424{
425 /* split the input name into the parameter name and an index e.g. FB0 into FB and 0*/
426 CHAR *namecopy = NULL, *token;
427 namecopy = XLALStringDuplicate( name );
428 REAL8 val = 0.;
429
430 if ( strchr( name, '_' ) ) { /* check for underscore delimiting numbers */
431 token = strtok( namecopy, "_" );
432 } else { /* name delimited by just numbers */
433 token = strtok( namecopy, "0123456789" );
434 }
435
436 const REAL8Vector *vpars = PulsarGetREAL8VectorParamErr( pars, token );
437
438 /* get the index value of the parameter name */
439 INT4 idx = -1;
440 INT4 loc = strlen( token );
441 if ( name[loc] == '_' ) {
442 loc++;
443 }
444 if ( sscanf( name + loc, "%d", &idx ) != 1 ) {
445 XLAL_ERROR_REAL8( XLAL_EINVAL, "Input parameter (%s) problem", name );
446 }
447
448 /* for glitch parameters GL, or WAVE parameters the index starts at 1, so shift it */
449 if ( !strncmp( name, "GL", 2 ) || !strncmp( name, "WAVE", 4 ) ) {
450 idx--;
451 }
452 if ( idx < 0 || ( UINT4 )idx > vpars->length - 1 ) {
453 XLAL_ERROR_REAL8( XLAL_EINVAL, "Input parameter index %d is wrong", idx );
454 }
455
456 val = vpars->data[idx];
457
458 XLALFree( namecopy );
459
460 return val;
461}
462
463
464void PulsarAddParam( PulsarParameters *pars, const CHAR *name, void *value, PulsarParamType type )
465{
466 /* Add the variable name with type type and value value to pars */
467 /* If variable already exists, it will over-write the current value if type compatible*/
468 PulsarParam *old = NULL;
469
470 /* create the hash table if it does not exist */
471 if ( !pars->hash_table ) {
473 }
474
475 /* Check input value is accessible */
476 if ( !value ) {
477 XLAL_ERROR_VOID( XLAL_EFAULT, "Unable to access value through null pointer; trying to add \"%s\".", name );
478 }
479
480 /* Check the name doesn't already exist */
481 if ( PulsarCheckParam( pars, name ) ) {
482 old = PulsarGetParamItem( pars, name );
483
484 /* If the type is incompatible, it should be removed */
485 if ( old->type != type || old->type == PULSARTYPE_REAL8Vector_t ) {
486 PulsarRemoveParam( pars, name );
487 } else {
488 PulsarSetParam( pars, name, value );
489 return;
490 }
491 }
492
493 /* If we get this far it is safe to create a new node for this variable */
494 PulsarParam *new = XLALMalloc( sizeof( PulsarParam ) );
495 memset( new, 0, sizeof( PulsarParam ) );
496 if ( new ) {
497 new->value = ( void * )XLALMalloc( PulsarTypeSize[type] );
498 new->fitFlag = NULL;
499
500 /* for REAL8 and REAL8Vector parameters initialise errors and fit flags to zero */
502 REAL8Vector *tmpvector = *( REAL8Vector ** )value;
503 UINT4 dlength = tmpvector->length;
504
505 new->fitFlag = XLALCreateUINT4Vector( dlength );
506 memset( new->fitFlag->data, 0, sizeof( UINT4 )*dlength ); // initialise to zero
507
509 memset( err->data, 0, sizeof( REAL8 )*dlength ); // initialise to zero
510
511 new->err = ( void * )XLALMalloc( PulsarTypeSize[type] );
512 memcpy( new->err, ( void * )&err, PulsarTypeSize[type] );
513 } else if ( type == PULSARTYPE_REAL8_t ) {
514 new->fitFlag = XLALCreateUINT4Vector( 1 );
515 memset( new->fitFlag->data, 0, sizeof( UINT4 ) ); // initialise to zero
516
517 new->err = ( void * )XLALMalloc( sizeof( UINT4Vector * ) );
518 REAL8 err = 0.;
519 memcpy( new->err, ( void * )&err, PulsarTypeSize[type] );
520 }
521 }
522
523 if ( new == NULL || new->value == NULL ) {
524 XLAL_ERROR_VOID( XLAL_ENOMEM, "Unable to allocate memory for list item." );
525 }
526
527 CHAR upperName[PULSAR_PARNAME_MAX];
529 strtoupper( upperName );
530
531 XLALStringCopy( new->name, upperName, PULSAR_PARNAME_MAX );
532 new->type = type;
533 memcpy( new->value, value, PulsarTypeSize[type] );
534 new->next = pars->head;
535 pars->head = new;
536 hash_elem *elem = new_elem( new->name, new );
537 XLALHashTblAdd( pars->hash_table, ( void * )elem );
538 pars->nparams++;
539}
540
541
543/* Typed version of PulsarAddParam for REAL8 values.*/
544{
545 PulsarAddParam( pars, name, ( void * )&value, PULSARTYPE_REAL8_t );
546}
547
548
550/* Typed version of PulsarAddParam for UINT4 values.*/
551{
552 PulsarAddParam( pars, name, ( void * )&value, PULSARTYPE_UINT4_t );
553}
554
555
557/* Typed version of PulsarAddParam for REAL8Vector values.*/
558{
559 REAL8Vector *fval = NULL;
560 fval = XLALCreateREAL8Vector( value->length );
561 memcpy( fval->data, value->data, sizeof( REAL8 )*value->length );
562 PulsarAddParam( pars, name, ( void * )&fval, PULSARTYPE_REAL8Vector_t );
563}
564
565
566void PulsarAddStringParam( PulsarParameters *pars, const CHAR *name, const CHAR *value )
567/* Typed version of PulsarAddParam for string values.*/
568{
569 CHAR *sval = NULL;
572 PulsarAddParam( pars, name, ( void * )&sval, PULSARTYPE_string_t );
573}
574
575
576/* Check for existence of name */
577int PulsarCheckParam( const PulsarParameters *pars, const CHAR *name )
578{
579 /* convert name to uppercase */
580 CHAR upperName[PULSAR_PARNAME_MAX];
582 strtoupper( upperName );
583
584 if ( PulsarGetParamItem( pars, upperName ) ) {
585 return 1;
586 } else {
587 return 0;
588 }
589}
590
591
593{
594 /* Free all variables inside the linked list, leaving only the head struct */
595 PulsarParam *this, *next = NULL;
596
597 if ( !pars ) {
598 return;
599 }
600
601 this = pars->head;
602
603 if ( this ) {
604 next = this->next;
605 }
606
607 while ( this ) {
608 if ( this->type == PULSARTYPE_REAL8Vector_t ) {
609 if ( this->value ) {
610 XLALDestroyREAL8Vector( *( REAL8Vector ** )this->value );
611 }
612 if ( this->err ) {
613 XLALDestroyREAL8Vector( *( REAL8Vector ** )this->err );
614 }
615 } else if ( this->type == PULSARTYPE_string_t ) {
616 if ( this->value ) {
617 XLALFree( *( CHAR ** )this->value );
618 }
619 }
620 if ( this->fitFlag ) {
621 XLALDestroyUINT4Vector( this->fitFlag );
622 }
623 XLALFree( this->value );
624 XLALFree( this->err );
625 XLALFree( this );
626 this = next;
627 if ( this ) {
628 next = this->next;
629 }
630 }
631 pars->head = NULL;
632 pars->nparams = 0;
633
634 if ( pars->hash_table ) {
636 }
637 pars->hash_table = NULL;
638}
639
640
641/* remove a given parameter */
643{
644 PulsarParam *this;
645
646 if ( !pars ) {
648 }
649
650 CHAR upperName[PULSAR_PARNAME_MAX];
652 strtoupper( upperName );
653
654 this = pars->head;
655 PulsarParam *parent = NULL;
656
657 while ( this ) {
658 if ( !strcmp( this->name, upperName ) ) {
659 break;
660 } else {
661 parent = this;
662 this = this->next;
663 }
664 }
665 if ( !this ) {
666 XLAL_PRINT_WARNING( "Entry \"%s\" not found.", upperName );
667 return;
668 }
669
670 if ( !parent ) {
671 pars->head = this->next;
672 } else {
673 parent->next = this->next;
674 }
675 /* Remove from hash table */
677 elem.name = this->name;
678 XLALHashTblRemove( pars->hash_table, ( void * )&elem );
679 if ( this->type == PULSARTYPE_REAL8Vector_t ) {
680 if ( this->value ) {
681 XLALDestroyREAL8Vector( *( REAL8Vector ** )this->value );
682 }
683 if ( this->err ) {
684 XLALDestroyREAL8Vector( *( REAL8Vector ** )this->err );
685 }
686 } else if ( this->type == PULSARTYPE_string_t ) {
687 if ( this->value ) {
688 XLALFree( *( CHAR ** )this->value );
689 }
690 }
691 if ( this->fitFlag ) {
692 XLALDestroyUINT4Vector( this->fitFlag );
693 }
694 XLALFree( this->value );
695 XLALFree( this->err );
696 this->value = NULL;
697 this->err = NULL;
698 this->fitFlag = NULL;
699 XLALFree( this );
700
701 this = NULL;
702 pars->nparams--;
703}
704
705
706/* Set the value of parameter name in the pars structure to value */
707void PulsarSetParam( PulsarParameters *pars, const CHAR *name, const void *value )
708{
709 PulsarParam *item;
710
711 /* convert name to uppercase */
712 CHAR upperName[PULSAR_PARNAME_MAX];
714 strtoupper( upperName );
715
716 item = PulsarGetParamItem( pars, upperName );
717 if ( !item ) {
718 XLAL_ERROR_VOID( XLAL_EINVAL, "Entry \"%s\" not found.", upperName );
719 }
720 memcpy( item->value, value, PulsarTypeSize[item->type] );
721}
722
723
724/* Set the value of parameter name error in the pars structure to value */
725void PulsarSetParamErr( PulsarParameters *pars, const CHAR *name, void *value, const UINT4 *fitFlag, UINT4 len )
726{
727 PulsarParam *item;
728
729 /* convert name to uppercase */
730 CHAR upperName[PULSAR_PARNAME_MAX];
732 strtoupper( upperName );
733
734 item = PulsarGetParamItem( pars, upperName );
735 if ( !item ) {
736 XLAL_ERROR_VOID( XLAL_EINVAL, "Entry \"%s\" not found.", name );
737 }
738
739 if ( item->err != NULL ) {
740 // Remove previous error values if present
741 if ( item->type == PULSARTYPE_REAL8Vector_t ) {
742 XLALDestroyREAL8Vector( *( REAL8Vector ** )item->err );
743 }
744 XLALFree( item->err );
745 }
746
747 if ( ( item->err = ( void * )XLALMalloc( PulsarTypeSize[PulsarGetParamType( pars, name )] ) ) == NULL ) {
748 XLAL_ERROR_VOID( XLAL_ENOMEM, "Unable to allocate memory for list item." );
749 }
750
751 // Remove previous fit flag if present
752 if ( item->fitFlag != NULL ) {
754
755 // set the fit flag values
756 item->fitFlag = NULL;
757 item->fitFlag = XLALCreateUINT4Vector( len );
758 memcpy( item->fitFlag->data, fitFlag, len * sizeof( UINT4 ) );
759 }
760
761 // set error values
762 memcpy( item->err, value, PulsarTypeSize[item->type] );
763}
764
765
766/* Set the value of parameter name error in the pars structure to value */
767void PulsarSetREAL8ParamErr( PulsarParameters *pars, const CHAR *name, REAL8 value, UINT4 fitFlag )
768{
769 PulsarSetParamErr( pars, name, ( void * )&value, &fitFlag, 1 );
770}
771
772
773/* Set the value of parameter name error in the pars structure to value */
774void PulsarSetREAL8VectorParamErr( PulsarParameters *pars, const CHAR *name, const REAL8Vector *value, const UINT4 *fitFlag )
775{
776 REAL8Vector *evals = NULL;
777 evals = XLALCreateREAL8Vector( value->length );
778 memcpy( evals->data, value->data, sizeof( REAL8 )*value->length );
779
780 PulsarSetParamErr( pars, name, ( void * )&evals, fitFlag, value->length );
781}
782
783
784/* free memory */
786{
787 if ( !pars ) {
788 return;
789 }
790
791 PulsarClearParams( pars );
792 if ( pars->hash_table ) {
794 }
795 XLALFree( pars );
796}
797
798
799/* create a copy of the parameters */
801{
802 /* Check that the source and origin differ */
803 if ( origin == target ) {
804 return;
805 }
806
807 if ( !origin ) {
808 XLAL_ERROR_VOID( XLAL_EFAULT, "Unable to access origin pointer." );
809 }
810
811 /* Make sure the structure is initialised */
812 if ( !target ) {
813 XLAL_ERROR_VOID( XLAL_EFAULT, "Unable to copy to uninitialised PulsarParameters structure." );
814 }
815
816 PulsarParam *this, *next = NULL;
817
818 this = origin->head;
819
820 if ( this ) {
821 next = this->next;
822 }
823
824 /* first clear target variables */
825 PulsarClearParams( target );
826
827 while ( this ) {
828 if ( this->type == PULSARTYPE_REAL8Vector_t ) {
829 const REAL8Vector *old = *( REAL8Vector ** )this->value;
831 if ( new ) {
832 memcpy( new->data, old->data, new->length * sizeof( REAL8 ) );
833 } else {
834 XLAL_ERROR_VOID( XLAL_ENOMEM, "Unable to copy vector!\n" );
835 }
836
837 PulsarAddREAL8VectorParam( target, this->name, ( const REAL8Vector * )new );
838
839 if ( this->err ) {
840 const REAL8Vector *olderr = *( REAL8Vector ** )this->err;
841 REAL8Vector *newerr = XLALCreateREAL8Vector( olderr->length );
842 if ( newerr ) {
843 memcpy( newerr->data, olderr->data, newerr->length * sizeof( REAL8 ) );
844 } else {
845 XLAL_ERROR_VOID( XLAL_ENOMEM, "Unable to copy vector!\n" );
846 }
847
848 const UINT4 *oldfit = PulsarGetParamFitFlag( origin, this->name );
849 UINT4 *newfit = ( UINT4 * )XLALCalloc( newerr->length, sizeof( UINT4 ) );
850
851 if ( newfit ) {
852 memcpy( newfit, oldfit, newerr->length * sizeof( UINT4 ) );
853 } else {
854 XLAL_ERROR_VOID( XLAL_ENOMEM, "Unable to copy vector!\n" );
855 }
856
857 PulsarSetREAL8VectorParamErr( target, this->name, ( const REAL8Vector * )newerr, ( const UINT4 * )newfit );
858 }
859 } else if ( this->type == PULSARTYPE_string_t ) {
860 CHAR *parstr = XLALStringDuplicate( *( CHAR ** )this->value );
861 PulsarAddStringParam( target, this->name, ( const CHAR * )parstr );
862 } else {
863 PulsarAddParam( target, this->name, this->value, this->type );
864
865 if ( ( this->type == PULSARTYPE_REAL8_t ) && this->err ) {
866 REAL8 err = *( REAL8 * )this->err;
867
868 const UINT4 *oldfit = PulsarGetParamFitFlag( origin, this->name );
869 UINT4 newfit = oldfit[0];
870
871 PulsarSetREAL8ParamErr( target, this->name, err, newfit );
872 }
873 }
874
875 this = next;
876 if ( this ) {
877 next = this->next;
878 }
879 }
880
881 return;
882}
883
884
885/* create functions for converting par file input e.g. from strings to floats, converting times, converting units */
886enum {
895
896
897#define DEFINE_CONV_FACTOR_FUNCTION( name, convfactor, type ) \
898 void ParConv ## name ( const CHAR *inval, void *out ){ \
899 CHAR *in = XLALStringDuplicate( inval ); \
900 if ( type != CONVSTRING && type != CONVINT ) { \
901 REAL8 x; \
902 if ( type == CONVFLOAT || type == CONVBINUNITS ){ \
903 /* check for exponents expressed as 'D/d' rather than 'E/e' and switch */ \
904 for ( INT4 i = 0; i < (INT4)strlen(in); i++ ) { \
905 if ( in[i] == 'D' || in[i] == 'd' ) { in[i] = 'e'; } \
906 } \
907 x = atof(in); \
908 if ( type == CONVBINUNITS ){ \
909 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */ \
910 if ( fabs( x ) > 1e-7 ) { x *= 1.e-12; } \
911 /* some of the parameter files in the ATNF catalogue have values of EDOT that are stupidly large e.g. O(1e33). \
912 * These can cause the time delay routines to fail, so if values of EDOT are greater than 10000 ignore them and \
913 * set it to zero */ \
914 if ( x > 10000. ) { x = 0.; } \
915 } \
916 else{ x *= convfactor; } \
917 } \
918 else if ( type == CONVHMS ) { /* convert to radians from hh:mm:ss.s format */ \
919 XLALTranslateHMStoRAD( &x, in ); \
920 } \
921 else if ( type == CONVDMS ) { /* convert to radians from hh:mm:ss.s format */ \
922 XLALTranslateDMStoRAD( &x, in ); \
923 } \
924 else if ( type == CONVMJD ) { /* convert an MJD to a GPS time */ \
925 x = XLALTTMJDtoGPS( atof(in) ); \
926 } \
927 memcpy(out, &x, sizeof(REAL8) ); \
928 } \
929 else if ( type == CONVSTRING ){ memcpy( out, in, strlen(in)+1 ); } \
930 else if ( type == CONVINT ) { /* convert to an integer */ \
931 UINT4 x; \
932 x = (UINT4)atoi(in); \
933 memcpy(out, &x, sizeof(UINT4) ); \
934 } \
935 XLALFree( in ); \
936 }
937
940DEFINE_CONV_FACTOR_FUNCTION( ToFloat, 1., CONVFLOAT ) /* just convert string to float */
941DEFINE_CONV_FACTOR_FUNCTION( ToInt, 0, CONVINT ) /* just convert string to float */
942DEFINE_CONV_FACTOR_FUNCTION( DegsToRads, LAL_PI_180, CONVFLOAT ) /* convert degrees to radians */
943DEFINE_CONV_FACTOR_FUNCTION( MasPerYrToRadPerSec, LAL_PI_180 / ( 3600.e3 * 365.25 * 86400. ), CONVFLOAT ) /* convert milliarcseconds/yr to radians/s */
944DEFINE_CONV_FACTOR_FUNCTION( SecsToRads, LAL_TWOPI / ( 24.*3600. ), CONVFLOAT ) /* convert seconds to radians */
945DEFINE_CONV_FACTOR_FUNCTION( ArcsecsToRads, LAL_PI_180 / 3600., CONVFLOAT ) /* convert arcseconds to radians */
946DEFINE_CONV_FACTOR_FUNCTION( MasToRads, LAL_PI_180 / 3600.0e3, CONVFLOAT ) /* convert milliarcseconds to radians */
947DEFINE_CONV_FACTOR_FUNCTION( InvArcsecsToInvRads, 3600. / LAL_PI_180, CONVFLOAT ) /* convert 1/arcsec to 1/rads */
948DEFINE_CONV_FACTOR_FUNCTION( DaysToSecs, DAYSTOSECS, CONVFLOAT ) /* convert days to seconds */
949DEFINE_CONV_FACTOR_FUNCTION( KpcToMetres, LAL_PC_SI * 1.e3, CONVFLOAT ) /* convert kiloparsecs to metres */
950DEFINE_CONV_FACTOR_FUNCTION( BinaryUnits, 1.e-12, CONVBINUNITS ) /* convert certain binary units as defined in TEMPO2 with factor */
951DEFINE_CONV_FACTOR_FUNCTION( MJDToGPS, 0, CONVMJD ) /* convert from MJD to GPS time */
952DEFINE_CONV_FACTOR_FUNCTION( DegPerYrToRadPerSec, LAL_PI_180 / ( 365.25 * DAYSTOSECS ), CONVFLOAT ) /* convert degs/year to rads/s */
953DEFINE_CONV_FACTOR_FUNCTION( SolarMassToKg, LALPULSAR_TEMPO2_MSUN_SI, CONVFLOAT ) /* convert solar masses to kg */
954DEFINE_CONV_FACTOR_FUNCTION( RAToRads, 0, CONVHMS ) /* convert right ascension to radians */
955DEFINE_CONV_FACTOR_FUNCTION( DecToRads, 0, CONVDMS ) /* convert declination to radians */
956DEFINE_CONV_FACTOR_FUNCTION( MicrosecToSec, 1.e-6, CONVFLOAT ) /* convert microseconds to seconds */
957
958/** Function type definition for a conversion function */
959typedef void ( *ParamConversionFunc )( const CHAR *in, void *out );
960
961/** A strcuture to contain all possible pulsar parameters that can be read in from a par file, and define
962 * the conversion function and type used for each */
963typedef struct tagParConversion {
964 CHAR name[PULSAR_PARNAME_MAX]; /** Parameter name */
965 ParamConversionFunc convfunc; /** Conversion function from string to required value */
966 ParamConversionFunc converrfunc; /** Conversion function for error from string to value */
967 PulsarParamType ptype; /** Parameter type */
970
971#define NUM_PARS 132 /* number of allowed parameters */
972
973/** Initialise conversion structure with most allowed TEMPO2 parameter names and conversion functions
974 * (convert all read in parameters to SI units where necessary). See http://arxiv.org/abs/astro-ph/0603381 and
975 * http://arxiv.org/abs/astro-ph/0603381 for parameter definitions.
976 *
977 * If requiring a new parameter to be read in in should be added to this structure and \c NUM_PARS should be
978 * incremented.
979 */
981 { .name = "F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* vector containing frequency and derivatives (Hz, Hz/s, Hz/s^2 ...) */
982 { .name = "P", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* vector containing period and derivatives (s, s/s, s/s^2 ...) */
983 { .name = "DIST", .convfunc = ParConvKpcToMetres, .converrfunc = ParConvKpcToMetres, .ptype = PULSARTYPE_REAL8_t }, /* distance to pulsar in metres */
984 { .name = "PX", .convfunc = ParConvMasToRads, .converrfunc = ParConvMasToRads, .ptype = PULSARTYPE_REAL8_t }, /* parallax (converted to radians) */
985 { .name = "DM", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* dispersion measure */
986 { .name = "DM1", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /*first derivative of the dispersion measure */
987
988 /* position parameters */
989 { .name = "RA", .convfunc = ParConvRAToRads, .converrfunc = ParConvSecsToRads, .ptype = PULSARTYPE_REAL8_t }, /* right ascension (converted to radians) */
990 { .name = "RAJ", .convfunc = ParConvRAToRads, .converrfunc = ParConvSecsToRads, .ptype = PULSARTYPE_REAL8_t }, /* right ascension (converted to radians) */
991 { .name = "DEC", .convfunc = ParConvDecToRads, .converrfunc = ParConvArcsecsToRads, .ptype = PULSARTYPE_REAL8_t }, /* declination (converted to radians) */
992 { .name = "DECJ", .convfunc = ParConvDecToRads, .converrfunc = ParConvArcsecsToRads, .ptype = PULSARTYPE_REAL8_t }, /* declination (converted to radians) */
993 { .name = "PMRA", .convfunc = ParConvMasPerYrToRadPerSec, .converrfunc = ParConvMasPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* proper motion in right ascension (converted to radians/s) */
994 { .name = "PMDEC", .convfunc = ParConvMasPerYrToRadPerSec, .converrfunc = ParConvMasPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* proper motion in declination (converted to radians/s) */
995 { .name = "ELONG", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t }, /* ecliptic longitude (converted from degs to rads) */
996 { .name = "ELAT", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t }, /* ecliptic latitude (converted from degs to rads) */
997 { .name = "PMELONG", .convfunc = ParConvMasPerYrToRadPerSec, .converrfunc = ParConvMasPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* proper motion in ecliptic longitude (converted to radians/s) */
998 { .name = "PMELAT", .convfunc = ParConvMasPerYrToRadPerSec, .converrfunc = ParConvMasPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* proper motion in ecliptic latitude (converted to radians/s) */
999 { .name = "BETA", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t }, /* an alias for ELONG also giving ecliptic latitude (converted from degs to rads) */
1000 { .name = "LAMBDA", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t }, /* an alias for ELAT also giving ecliptic longitude (converted from degs to rads) */
1001 { .name = "PMBETA", .convfunc = ParConvMasPerYrToRadPerSec, .converrfunc = ParConvMasPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* proper motion in ecliptic latitude (converted to radians/s) */
1002 { .name = "PMLAMBDA", .convfunc = ParConvMasPerYrToRadPerSec, .converrfunc = ParConvMasPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* proper motion in ecliptic longitude (converted to radians/s) */
1003
1004 /* epoch parameters */
1005 { .name = "PEPOCH", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t }, /* period epoch (saved as GPS time) */
1006 { .name = "POSEPOCH", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t }, /* position epoch (saved as GPS time) */
1007 { .name = "DMEPOCH", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t }, /* dispersion measure epoch (saved as GPS time) */
1008
1009 /* glitch parameters */
1010 { .name = "GLEP", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch epochs (saved as GPS times) */
1011 { .name = "GLPH", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch phase offsets (rotational phase) */
1012 { .name = "GLF0", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch frequency offsets (Hz) */
1013 { .name = "GLF1", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch frequency derivative offsets (Hz/s) */
1014 { .name = "GLF2", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch second frequency derivative offsets (Hz/s^2) */
1015 { .name = "GLF0D", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch decaying frequency component (Hz) */
1016 { .name = "GLTD", .convfunc = ParConvDaysToSecs, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8Vector_t }, /* glitch decay time (seconds) */
1017
1018 /* string parameters */
1019 { .name = "NAME", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* pulsar name */
1020 { .name = "PSR", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* pulsar name */
1021 { .name = "PSRJ", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* pulsar J name */
1022 { .name = "PSRB", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* pulsar B name */
1023
1024 /* binary parameters */
1025 { .name = "BINARY", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* binary model type */
1026 { .name = "A1", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* projected semi-major axis (light seconds) */
1027 { .name = "OM", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t }, /* angle of periastron (convert degrees to radians) */
1028 { .name = "ECC", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* eccentricity */
1029 { .name = "PB", .convfunc = ParConvDaysToSecs, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t }, /* orbital period (convert days to seconds) */
1030 { .name = "T0", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t }, /* time of perisatron (GPS) */
1031 { .name = "TASC", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t }, /* time ascending noise for ELL1 model (GPS) */
1032 { .name = "EPS1", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* e*sin(w0) for ELL1 model */
1033 { .name = "EPS2", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* e*cos(w0) for ELL1 model */
1034 { .name = "GAMMA", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* relativistic parameter */
1035 { .name = "OMDOT", .convfunc = ParConvDegPerYrToRadPerSec, .converrfunc = ParConvDegPerYrToRadPerSec, .ptype = PULSARTYPE_REAL8_t }, /* angle of periastron time derivative (degs/year converted to rad/s) */
1036 { .name = "XDOT", .convfunc = ParConvBinaryUnits, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* project semi-major axis time derivative (light sec/sec) */
1037 { .name = "PBDOT", .convfunc = ParConvBinaryUnits, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* period time derivative */
1038 { .name = "EDOT", .convfunc = ParConvBinaryUnits, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* eccentricity time derivative (1/s) */
1039 { .name = "EPS1DOT", .convfunc = ParConvBinaryUnits, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1040 { .name = "EPS2DOT", .convfunc = ParConvBinaryUnits, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1041 { .name = "XPBDOT", .convfunc = ParConvBinaryUnits, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1042 { .name = "SINI", .convfunc = ParConvToString, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_string_t }, /* sin of inclination angle */
1043 { .name = "MTOT", .convfunc = ParConvSolarMassToKg, .converrfunc = ParConvSolarMassToKg, .ptype = PULSARTYPE_REAL8_t }, /* total system mass (convert solar masses to kg) */
1044 { .name = "M2", .convfunc = ParConvSolarMassToKg, .converrfunc = ParConvSolarMassToKg, .ptype = PULSARTYPE_REAL8_t }, /* binary companion mass (convert solar masses to kg) */
1045 { .name = "DR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1046 { .name = "DTHETA", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1047 { .name = "SHAPMAX", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* used for DDS model */
1048
1049 /* multiple system terms for BT1P and BT2P models */
1050 { .name = "A1_2", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1051 { .name = "A1_3", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1052 { .name = "OM_2", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t },
1053 { .name = "OM_3", .convfunc = ParConvDegsToRads, .converrfunc = ParConvDegsToRads, .ptype = PULSARTYPE_REAL8_t },
1054 { .name = "PB_2", .convfunc = ParConvDaysToSecs, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t },
1055 { .name = "PB_3", .convfunc = ParConvDaysToSecs, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t },
1056 { .name = "T0_2", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t },
1057 { .name = "T0_3", .convfunc = ParConvMJDToGPS, .converrfunc = ParConvDaysToSecs, .ptype = PULSARTYPE_REAL8_t },
1058 { .name = "ECC_2", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1059 { .name = "ECC_3", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1060 { .name = "FB", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* orbital frequency components for the BTX model */
1061
1062 /* Aberration delay parameters */
1063 { .name = "A0", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1064 { .name = "B0", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1065
1066 /* Kopeikin terms */
1067 { .name = "D_AOP", .convfunc = ParConvInvArcsecsToInvRads, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t }, /* inverse arsecs converted to inverse radians */
1068 { .name = "KIN", .convfunc = ParConvDegsToRads, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t },
1069 { .name = "KOM", .convfunc = ParConvDegsToRads, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t },
1070
1071 /* FITWAVES parameters */
1072 { .name = "WAVE_OM", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* fundamental frequency (Hz) of sinusoids used for whitening */
1073 { .name = "WAVEEPOCH", .convfunc = ParConvMJDToGPS, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t }, /* frequency epoch (converted from MJD to GPS) */
1074 { .name = "WAVESIN", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* amplitudes of the sine terms for the kth sinusoids */
1075 { .name = "WAVECOS", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8Vector_t }, /* amplitudes of the cosine terms for the kth sinusoids */
1076
1077 /* TEMPO parameters */
1078 { .name = "EPHEM", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* ephemeris type e.g. DE405 */
1079 { .name = "UNITS", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* TEMPO2 units e.g. TDB */
1080 { .name = "START", .convfunc = ParConvMJDToGPS, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t }, /* start of observations */
1081 { .name = "FINISH", .convfunc = ParConvMJDToGPS, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t }, /* end of observations */
1082 { .name = "NTOA", .convfunc = ParConvToInt, .converrfunc = NULL, .ptype = PULSARTYPE_UINT4_t }, /* number of TOAs in observation */
1083 { .name = "TRES", .convfunc = ParConvMicrosecToSec, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t }, /* timing residual (convert microseconds to seconds) */
1084 { .name = "CLK", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* The observatory clock */
1085 { .name = "T2CMETHOD", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* Method for transforming from terrestrial to celestial frame */
1086 { .name = "TIMEEPH", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* Which time ephemeris to use */
1087
1088 /* GW parameters */
1089 { .name = "H0", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* gravitational wave amplitude */
1090 { .name = "APLUS", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* plus polarisation component of GW amplitude */
1091 { .name = "ACROSS", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* cross polarisation component of GW amplitude */
1092 { .name = "PHI0", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* gravitational wave initial phase (radians) */
1093 { .name = "PSI", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* gravitational wave polarisation angle (radians) */
1094 { .name = "COSIOTA", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* cosine of source inclination angle */
1095 { .name = "IOTA", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* the source inclination angle in radians */
1096 { .name = "C22", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW amplitude of C22 component */
1097 { .name = "C21", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW amplitude of C21 component */
1098 { .name = "PHI22", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* initial phase of C22 component (radians) */
1099 { .name = "PHI21", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* initial phase of C21 component (radians) */
1100 { .name = "CGW", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* speed of gravitational waves as a fraction of the speed of light */
1101 { .name = "LAMBDAPIN", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* parameters from http://uk.arxiv.org/abs/0909.4035 */
1102 { .name = "COSTHETA", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1103 { .name = "THETA", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1104 { .name = "I21", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1105 { .name = "I31", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t },
1106 { .name = "Q22", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* the l=m=2 mass quadrupole in kg m^2 */
1107
1108 /* GW non-GR polarisation mode amplitude parameters (assuming emission at twice the rotation frequency) */
1109 { .name = "HPLUS", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW tensor plus polarisation amplitude */
1110 { .name = "HCROSS", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW tensor cross polarisation amplitude */
1111 { .name = "PSITENSOR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW tensor angle polarisation */
1112 { .name = "PHI0TENSOR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* initial phase for tensor modes */
1113 { .name = "HSCALARB", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW scalar breathing mode polarisation amplitude */
1114 { .name = "HSCALARL", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW scalar longitudinal polarisation amplitude */
1115 { .name = "PSISCALAR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW scalar angle polarisation */
1116 { .name = "PHI0SCALAR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* initial phase for scalar modes */
1117 { .name = "HVECTORX", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector x-mode amplitude */
1118 { .name = "HVECTORY", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector y-mode amplitude */
1119 { .name = "PSIVECTOR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector angle polarisation */
1120 { .name = "PHI0VECTOR", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector polarisation initial phase */
1121
1122 /* GW non-GR polarisation mode amplitude parameters (assuming emission at the rotation frequency) */
1123 { .name = "H0_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GR 21 polarisation amplitude */
1124 { .name = "HPLUS_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW tensor plus polarisation amplitude */
1125 { .name = "HCROSS_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW tensor cross polarisation amplitude */
1126 { .name = "PSITENSOR_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW tensor angle polarisation */
1127 { .name = "PHI0TENSOR_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* initial phase for tensor modes */
1128 { .name = "HSCALARB_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW scalar breathing mode polarisation amplitude */
1129 { .name = "HSCALARL_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW scalar longitudinal polarisation amplitude */
1130 { .name = "PSISCALAR_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW scalar angle polarisation */
1131 { .name = "PHI0SCALAR_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* initial phase for scalar modes */
1132 { .name = "HVECTORX_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector x-mode amplitude */
1133 { .name = "HVECTORY_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector y-mode amplitude */
1134 { .name = "PSIVECTOR_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector angle polarisation */
1135 { .name = "PHI0VECTOR_F", .convfunc = ParConvToFloat, .converrfunc = ParConvToFloat, .ptype = PULSARTYPE_REAL8_t }, /* GW vector polarisation initial phase */
1136
1137 /* transient signal parameters */
1138 { .name = "TRANSIENTWINDOWTYPE", .convfunc = ParConvToString, .converrfunc = NULL, .ptype = PULSARTYPE_string_t }, /* window type, currently "RECT" (rectangular window) or "EXP" (exponentially decaying window) */
1139 { .name = "TRANSIENTSTARTTIME", .convfunc = ParConvMJDToGPS, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t }, /* transient start time in MJD */
1140 { .name = "TRANSIENTTAU", .convfunc = ParConvDaysToSecs, .converrfunc = NULL, .ptype = PULSARTYPE_REAL8_t } /* transient decay time scale (duration for "RECT" and decay constant for "EXP") */
1141};
1142
1143/** \brief Parse a single line from a pulsar parameter file
1144 *
1145 * This will parse a line from the TEMPO-style pulsar parameter file containing the
1146 * parameter given by \c name. The parameter will be added to the \c par structure.
1147 *
1148 * This function can only be used internally.
1149 */
1150static INT4 ParseParLine( PulsarParameters *par, const CHAR *name, FILE *fp )
1151{
1152 INT4 nread = 0; /* number of values read from line */
1154 /* three potential values on the line */
1156 INT4 i = 0, tmpnum = 0;
1157 CHAR *nname = NULL; /* duplicate of name */
1158
1159 if ( par == NULL ) {
1160 XLAL_ERROR( XLAL_EINVAL, "Error... PulsarParameter structure is not initialised!\n" );
1161 }
1162 if ( name == NULL ) {
1163 XLAL_ERROR( XLAL_EINVAL, "Error... parameter name is not set!\n" );
1164 }
1165 if ( fp == NULL ) {
1166 XLAL_ERROR( XLAL_EINVAL, "Error... parameter file pointer is NULL!\n" );
1167 }
1168
1169 /* parse the line from the fp pointer */
1170 if ( fgets( str, PULSAR_PARNAME_MAX, fp ) == NULL ) {
1171 XLAL_PRINT_WARNING( "No value for parameter %s", name );
1172 return XLAL_SUCCESS;
1173 }
1174
1175 /* scan the line for values */
1176 nread = sscanf( str, "%s %s %s", str1, str2, str3 );
1177
1178 if ( !nread ) {
1179 XLAL_PRINT_WARNING( "No value for parameter %s", name );
1180 return XLAL_SUCCESS;
1181 }
1182
1183 /* check for parameters with more than one possible name */
1184 if ( !strcmp( name, "E" ) ) {
1185 nname = XLALStringDuplicate( "ECC" );
1186 } else if ( !strcmp( name, "E_1" ) ) {
1187 nname = XLALStringDuplicate( "ECC_1" );
1188 } else if ( !strcmp( name, "E_2" ) ) {
1189 nname = XLALStringDuplicate( "ECC_2" );
1190 } else if ( !strcmp( name, "E_3" ) ) {
1191 nname = XLALStringDuplicate( "ECC_3" );
1192 } else {
1193 nname = XLALStringDuplicate( name );
1194 }
1195
1196 /* perform parameter dependent inputs */
1197 for ( i = 0; i < NUM_PARS; i++ ) {
1198 /* this has to be hard-coded for the F, WAVE, FB and glitch (GL) vector parameters */
1199
1200 /* check for parameters requiring placement in vectors */
1201 INT4 isfreq = ( !strncmp( nname, "F", 1 ) && !strcmp( "F", pc[i].name ) && sscanf( nname + strlen( "F" ), "%d", &tmpnum ) == 1 );
1202 INT4 isperiod = ( !strncmp( nname, "P", 1 ) && !strcmp( "P", pc[i].name ) && sscanf( nname + strlen( "P" ), "%d", &tmpnum ) == 1 );
1203 INT4 iswave = ( ( !strncmp( nname, "WAVE", 4 ) && ( !strcmp( "WAVESIN", pc[i].name ) || !strcmp( "WAVECOS", pc[i].name ) ) ) && strcmp( "WAVE_OM", nname ) && strcmp( "WAVEEPOCH", nname ) );
1204 INT4 isfb = ( !strncmp( nname, "FB", 2 ) && !strcmp( "FB", pc[i].name ) );
1205 INT4 isgl = ( !strncmp( nname, "GL", 2 ) && strstr( nname, pc[i].name ) && !strncmp( nname, pc[i].name, strlen( nname ) - 2 ) );
1206
1207 if ( !strcmp( nname, pc[i].name ) || isfreq || isperiod || iswave || isfb || isgl ) {
1208 UINT4 num = 0, nsize = 0;
1209
1210 if ( pc[i].convfunc == NULL ) {
1211 XLAL_PRINT_WARNING( "No conversion function for parameter %s. Skipping parameter.\n", pc[i].name );
1212 return XLAL_SUCCESS;
1213 }
1214
1215 /* add parameter */
1216 if ( isfreq || isperiod || isfb ) { /* add frequency/period and frequency/period derivative values, or FB values */
1217 REAL8Vector *ptr = NULL, *eptr = NULL;
1218 UINT4 *fitFlag = NULL;
1219
1220 if ( isfb ) {
1221 if ( strlen( nname ) > strlen( "FB" ) ) {
1222 if ( sscanf( nname + strlen( "FB" ), "%d", &num ) != 1 ) {
1223 XLAL_ERROR( XLAL_EINVAL, "Error...problem reading %s number from par file.\n", nname );
1224 }
1225 }
1226 } else if ( isfreq ) {
1227 if ( strlen( nname ) > strlen( "F" ) ) {
1228 if ( sscanf( nname + strlen( "F" ), "%d", &num ) != 1 ) {
1229 XLAL_ERROR( XLAL_EINVAL, "Error...problem reading %s number from par file.\n", nname );
1230 }
1231 }
1232 } else {
1233 if ( strlen( nname ) > strlen( "P" ) ) {
1234 if ( sscanf( nname + strlen( "P" ), "%d", &num ) != 1 ) {
1235 XLAL_ERROR( XLAL_EINVAL, "Error...problem reading %s number from par file.\n", nname );
1236 }
1237 }
1238 }
1239
1240 void *val = ( void * )XLALMalloc( PulsarTypeSize[PULSARTYPE_REAL8_t] );
1241
1242 pc[i].convfunc( str1, val );
1243
1244 nsize = num + 1;
1245 if ( PulsarCheckParam( par, pc[i].name ) ) {
1246 // count any previous values
1247 const REAL8Vector *cptr = PulsarGetREAL8VectorParam( par, pc[i].name );
1248 nsize = ( cptr->length > num + 1 ) ? cptr->length : ( num + 1 );
1249 }
1250
1251 // pointer for parameter values
1252 ptr = XLALCreateREAL8Vector( nsize );
1253 memset( ptr->data, 0, sizeof( REAL8 )*nsize );
1254
1255 // pointers for error and fit flags
1256 eptr = XLALCreateREAL8Vector( nsize );
1257 memset( eptr->data, 0, sizeof( REAL8 )*nsize ); // initialise with zeros
1258 fitFlag = ( UINT4 * )XLALCalloc( nsize, sizeof( UINT4 ) ); // set fit values to zero (no-fit) by default
1259
1260 if ( PulsarCheckParam( par, pc[i].name ) ) {
1261 // copy any previous values
1262 const REAL8Vector *cptr = PulsarGetREAL8VectorParam( par, pc[i].name );
1263 memcpy( ptr->data, cptr->data, cptr->length * sizeof( REAL8 ) );
1264
1265 /* copy any error values, as updating REAL8Vector parameters destroys the original PulsarParam structure */
1267 const UINT4 *ff = PulsarGetParamFitFlag( par, pc[i].name );
1268
1269 // copy any previous error values
1270 memcpy( eptr->data, ceptr->data, sizeof( REAL8 )*cptr->length );
1271 memcpy( fitFlag, ff, sizeof( UINT4 )*cptr->length );
1272 }
1273
1274 ptr->data[num] = *( REAL8 * )val;
1275
1276 // NOTE: this will destroy the previous held PulsarParam structure for this parameter
1278
1279 // (re-)add errors
1280 PulsarSetREAL8VectorParamErr( par, pc[i].name, ( const REAL8Vector * )eptr, ( const UINT4 * )fitFlag );
1281
1282 XLALFree( val );
1284 XLALDestroyREAL8Vector( eptr );
1285 XLALFree( fitFlag );
1286 } else if ( iswave && nread == 2 ) { /* add WAVE values */
1287 REAL8Vector *ptr1 = NULL, *ptr2 = NULL;
1288
1289 if ( strlen( nname ) > strlen( "WAVE" ) ) {
1290 if ( sscanf( nname + strlen( "WAVE" ), "%d", &num ) != 1 ) {
1291 XLAL_ERROR( XLAL_EINVAL, "Error...problem reading %s number from par file.\n", nname );
1292 }
1293 } else {
1294 break;
1295 }
1296
1297 num--; /* WAVE values start from WAVE1, so subtract 1 from the num for the vector index */
1298
1299 void *val1 = ( void * )XLALMalloc( PulsarTypeSize[PULSARTYPE_REAL8_t] );
1300 void *val2 = ( void * )XLALMalloc( PulsarTypeSize[PULSARTYPE_REAL8_t] );
1301
1302 pc[i].convfunc( str1, val1 );
1303 pc[i].convfunc( str2, val2 );
1304
1305 nsize = num + 1;
1306 if ( PulsarCheckParam( par, "WAVESIN" ) && PulsarCheckParam( par, "WAVECOS" ) ) {
1307 // count number of values
1308 const REAL8Vector *cptr = PulsarGetREAL8VectorParam( par, pc[i].name );
1309
1310 nsize = ( cptr->length > num + 1 ) ? cptr->length : ( num + 1 );
1311 }
1312
1313 // pointers for parameter values
1314 ptr1 = XLALCreateREAL8Vector( nsize );
1315 ptr2 = XLALCreateREAL8Vector( nsize );
1316 memset( ptr1->data, 0, sizeof( REAL8 )*nsize );
1317 memset( ptr2->data, 0, sizeof( REAL8 )*nsize );
1318
1319 if ( PulsarCheckParam( par, "WAVESIN" ) && PulsarCheckParam( par, "WAVECOS" ) ) {
1320 const REAL8Vector *cptr1 = PulsarGetREAL8VectorParam( par, "WAVESIN" );
1321 const REAL8Vector *cptr2 = PulsarGetREAL8VectorParam( par, "WAVECOS" );
1322
1323 // copy previous values
1324 memcpy( ptr1->data, cptr1->data, ptr1->length * sizeof( REAL8 ) );
1325 memcpy( ptr2->data, cptr2->data, ptr2->length * sizeof( REAL8 ) );
1326 }
1327
1328 ptr1->data[num] = *( REAL8 * )val1;
1329 ptr2->data[num] = *( REAL8 * )val2;
1330
1331 PulsarAddREAL8VectorParam( par, "WAVESIN", ( const REAL8Vector * )ptr1 );
1332 PulsarAddREAL8VectorParam( par, "WAVECOS", ( const REAL8Vector * )ptr2 );
1333
1334 XLALFree( val1 );
1335 XLALFree( val2 );
1336 XLALDestroyREAL8Vector( ptr1 );
1337 XLALDestroyREAL8Vector( ptr2 );
1338
1339 /* there are no errors on the wave parameters, so set defaults of zero and then break */
1340 UINT4 *fitFlag = ( UINT4 * )XLALCalloc( nsize, sizeof( UINT4 ) );
1341 REAL8Vector *eptr = XLALCreateREAL8Vector( nsize );
1342 memset( eptr->data, 0, sizeof( REAL8 )*nsize );
1343 PulsarSetREAL8VectorParamErr( par, "WAVESIN", ( const REAL8Vector * )eptr, ( const UINT4 * )fitFlag );
1344 PulsarSetREAL8VectorParamErr( par, "WAVECOS", ( const REAL8Vector * )eptr, ( const UINT4 * )fitFlag );
1345 XLALDestroyREAL8Vector( eptr );
1346 XLALFree( fitFlag );
1347
1348 break;
1349 } else if ( isgl ) { /* get glitch parameters */
1350 REAL8Vector *ptr = NULL, *eptr = NULL;
1351 UINT4 *fitFlag = NULL;
1352
1353 if ( sscanf( strstr( nname, "_" ) + 1, "%d", &num ) != 1 ) {
1354 XLAL_ERROR( XLAL_EINVAL, "Error...problem reading %s number from par file.\n", nname );
1355 }
1356
1357 num--; /* GL values start from e.g. GLF0_1, so subtract 1 from the num for the vector index */
1358
1359 void *val = ( void * )XLALMalloc( PulsarTypeSize[PULSARTYPE_REAL8_t] );
1360
1361 pc[i].convfunc( str1, val );
1362
1363 nsize = num + 1;
1364 if ( PulsarCheckParam( par, pc[i].name ) ) {
1365 // count previous values
1366 const REAL8Vector *cptr = PulsarGetREAL8VectorParam( par, pc[i].name );
1367 nsize = ( cptr->length > num + 1 ) ? cptr->length : ( num + 1 );
1368 }
1369
1370 // pointer for parameter values
1371 ptr = XLALCreateREAL8Vector( nsize );
1372 memset( ptr->data, 0, sizeof( REAL8 )*nsize );
1373
1374 // pointers for error and fit flags
1375 eptr = XLALCreateREAL8Vector( nsize );
1376 memset( eptr->data, 0, sizeof( REAL8 )*nsize ); // initialise with zeros
1377 fitFlag = ( UINT4 * )XLALCalloc( nsize, sizeof( UINT4 ) ); // set fit values to zero (no-fit) by default
1378
1379 if ( PulsarCheckParam( par, pc[i].name ) ) {
1380 // copy any previous values
1381 const REAL8Vector *cptr = PulsarGetREAL8VectorParam( par, pc[i].name );
1382 memcpy( ptr->data, cptr->data, cptr->length * sizeof( REAL8 ) );
1383
1384 /* copy any error values, as updating REAL8Vector parameters destroys the original PulsarParam structure */
1386 const UINT4 *ff = PulsarGetParamFitFlag( par, pc[i].name );
1387
1388 // copy any previous error values
1389 memcpy( eptr->data, ceptr->data, sizeof( REAL8 )*cptr->length );
1390 memcpy( fitFlag, ff, sizeof( UINT4 )*cptr->length );
1391 }
1392
1393 ptr->data[num] = *( REAL8 * )val;
1394
1396
1397 // (re-)add errors
1398 PulsarSetREAL8VectorParamErr( par, pc[i].name, ( const REAL8Vector * )eptr, ( const UINT4 * )fitFlag );
1399
1400 XLALFree( val );
1402 XLALDestroyREAL8Vector( eptr );
1403 XLALFree( fitFlag );
1404 } else {
1405 if ( pc[i].ptype != PULSARTYPE_string_t ) {
1406 void *val = ( void * )XLALMalloc( PulsarTypeSize[pc[i].ptype] );
1407 pc[i].convfunc( str1, val );
1408 PulsarAddParam( par, pc[i].name, val, pc[i].ptype );
1409 XLALFree( val );
1410 } else {
1411 CHAR *val = XLALStringDuplicate( str1 );
1412 PulsarAddStringParam( par, pc[i].name, ( const CHAR * )val );
1413 XLALFree( val );
1414 }
1415 }
1416
1417 /* check for error values */
1418 if ( ( nread == 2 && strcmp( str2, "1" ) ) || ( nread == 3 && !strcmp( str2, "1" ) ) ) {
1419 if ( pc[i].converrfunc == NULL ) {
1420 XLAL_PRINT_WARNING( "No conversion function for parameter %s error. No error being set.\n", pc[i].name );
1421 return XLAL_SUCCESS;
1422 }
1423
1424 void *val = ( void * )XLALMalloc( PulsarTypeSize[PULSARTYPE_REAL8_t] );
1425 UINT4 isFit = 0;
1426
1427 /* get the fit flag */
1428 if ( isfreq || isperiod || isfb || isgl ) { /* do this for REAL8Vector parameters */
1430 const UINT4 *fitFlag = PulsarGetParamFitFlag( par, pc[i].name );
1431
1432 XLAL_CHECK( ptr != NULL, XLAL_EFUNC, "No default errors set for parameter %s", pc[i].name );
1433
1434 // copy of parameter errors and fit flags
1435 REAL8Vector *eptr = XLALCreateREAL8Vector( ptr->length );
1436 UINT4 *ff = ( UINT4 * )XLALMalloc( sizeof( UINT4 ) * ptr->length );
1437
1438 memcpy( eptr->data, ptr->data, sizeof( REAL8 )*ptr->length );
1439 memcpy( ff, fitFlag, sizeof( UINT4 )*ptr->length );
1440
1441 if ( nread == 2 ) {
1442 pc[i].converrfunc( str2, val );
1443 } else {
1444 if ( !strcmp( str2, "1" ) ) {
1445 isFit = 1; /* a fit flag is set to one */
1446 }
1447 pc[i].converrfunc( str3, val );
1448 }
1449
1450 eptr->data[num] = *( REAL8 * )val;
1451 ff[num] = isFit;
1452
1453 PulsarSetREAL8VectorParamErr( par, pc[i].name, ( const REAL8Vector * )eptr, ( const UINT4 * )ff );
1454
1455 XLALDestroyREAL8Vector( eptr );
1456 XLALFree( ff );
1457 } else {
1458 if ( nread == 2 ) {
1459 pc[i].converrfunc( str2, val );
1460 } else {
1461 if ( !strcmp( str2, "1" ) ) {
1462 isFit = 1;
1463 }
1464 pc[i].converrfunc( str3, val );
1465 }
1466
1467 PulsarSetREAL8ParamErr( par, pc[i].name, *( REAL8 * )val, isFit );
1468 }
1469
1470 XLALFree( val );
1471 }
1472
1473 break;
1474 }
1475 }
1476
1477 XLALFree( nname );
1478
1479 return XLAL_SUCCESS;
1480}
1481
1483/* read in the pulsar parameter file */
1484PulsarParameters *XLALReadTEMPOParFile( const CHAR *pulsarAndPath )
1485{
1486 FILE *fp = NULL;
1487 CHAR str[PULSAR_PARNAME_MAX]; /* string to contain first value on line */
1488
1489 PulsarParameters *par = XLALCalloc( sizeof( *par ), 1 );
1490
1491 /* open file */
1492 if ( ( fp = fopen( pulsarAndPath, "r" ) ) == NULL ) {
1493 XLAL_PRINT_ERROR( "Error... Cannot open .par file %s\n", pulsarAndPath );
1494 XLALFree( par );
1496 }
1497
1498 int nread = 0; /* number of parameters read from a line in the par file */
1499 int UNUSED c;
1500
1501 /* read in the par file */
1502 while ( !feof( fp ) ) {
1503 /* Read in a line from the parameter file */
1504 nread = fscanf( fp, "%s", str );
1505 if ( nread == 1 ) {
1506 /* check for comment line and skip to end of line */
1507 if ( str[0] == '#' ) {
1508 c = fscanf( fp, "%*[^\n]" );
1509 continue;
1510 }
1511
1512 CHAR upperName[PULSAR_PARNAME_MAX];
1513 XLALStringCopy( upperName, str, PULSAR_PARNAME_MAX );
1514 strtoupper( upperName );
1515
1516 if ( XLAL_SUCCESS != ParseParLine( par, upperName, fp ) ) {
1517 XLAL_PRINT_WARNING( "Parameter \"%s\" could not be successfully parsed from par file", str );
1518 }
1519 }
1520 }
1521
1522 /* check for linked parameters SINI and KIN */
1523 if ( PulsarCheckParam( par, "SINI" ) ) {
1524 CHAR *sini = XLALStringDuplicate( PulsarGetStringParam( par, "SINI" ) );
1525 strtoupper( sini );
1526
1527 REAL8 sinid;
1528
1529 PulsarRemoveParam( par, "SINI" );
1530
1531 if ( !strcmp( sini, "KIN" ) ) {
1532 if ( PulsarCheckParam( par, "KIN" ) ) {
1533 sinid = sin( PulsarGetREAL8Param( par, "KIN" ) );
1534 PulsarAddParam( par, "SINI", &sinid, PULSARTYPE_REAL8_t );
1535 } else {
1536 XLAL_PRINT_ERROR( "Error... KIN not set in .par file %s\n", pulsarAndPath );
1538 XLALFree( par );
1540 }
1541 } else {
1542 sinid = atof( sini );
1543 PulsarAddParam( par, "SINI", &sinid, PULSARTYPE_REAL8_t );
1544 }
1545
1546 XLALFree( sini );
1547 }
1548
1549 fclose( fp );
1550
1551 return par;
1552}
1553
1554/* NOTE: Convert this function to be more like readParfile.C in TEMPO2 - read
1555 * in a line at a time using fgets and make each parameter a structure */
1556void
1558 CHAR *pulsarAndPath )
1559{
1560 XLAL_PRINT_DEPRECATION_WARNING( "XLALReadTEMPOParFile" );
1561
1562 FILE *fp = NULL;
1563 CHAR val[500][40]; /* string array to hold all the read in values
1564 500 strings of max 40 characters is enough */
1565 INT4 i = 0, j = 1, k;
1566 int UNUSED c;
1567
1568 if ( output == ( BinaryPulsarParams * )NULL ) {
1570 }
1571
1572 output->name = NULL;
1573 output->jname = NULL;
1574 output->bname = NULL;
1575
1576 output->model = NULL; /* set binary model to null - in case not a binary */
1577
1578 /* set all output params to zero*/
1579 output->e = 0.0; /* orbital eccentricity */
1580 output->Pb = 0.0; /* orbital period (days) */
1581 output->w0 = 0.0; /* longitude of periastron (deg) */
1582 output->x = 0.0; /* projected semi-major axis/speed of light (light secs) */
1583 output->T0 = 0.0; /* time of orbital periastron as measured in TDB (MJD) */
1584
1585 output->e2 = 0.0;
1586 output->Pb2 = 0.0;
1587 output->w02 = 0.0;
1588 output->x2 = 0.0;
1589 output->T02 = 0.0;
1590
1591 output->e3 = 0.0;
1592 output->Pb3 = 0.0;
1593 output->w03 = 0.0;
1594 output->x3 = 0.0;
1595 output->T03 = 0.0;
1596
1597 output->xpbdot = 0.0; /* (10^-12) */
1598
1599 output->eps1 = 0.0; /* e*sin(w) */
1600 output->eps2 = 0.0; /* e*cos(w) */
1601 output->eps1dot = 0.0;
1602 output->eps2dot = 0.0;
1603 output->Tasc = 0.0; /* time of the ascending node (used rather than T0) */
1604
1605 output->fb = NULL;
1606 output->fbErr = NULL;
1607 output->nfb = 0;
1608
1609 output->wdot = 0.0; /* precesion of longitude of periastron w = w0 + wdot(tb-T0) (degs/year) */
1610 output->gamma = 0.0; /* gravitational redshift and time dilation parameter (s)*/
1611 output->Pbdot = 0.0; /* rate of change of Pb (dimensionless 10^-12) */
1612 output->xdot = 0.0; /* rate of change of x(=asini/c) - optional (10^-12)*/
1613 output->edot = 0.0; /* rate of change of e (10^-12)*/
1614
1615 output->s = 0.0; /* Shapiro 'shape' parameter sin i */
1616 output->sstr = NULL;
1617
1618 output->shapmax = 0.;
1619
1620 /*output.r=0.0; Shapiro 'range' parameter */
1621 output->dr = 0.0;
1622 output->dth = 0.0; /* (10^-6) */
1623 output->a0 = 0.0;
1624 output->b0 = 0.0; /* abberation delay parameters */
1625
1626 output->M = 0.0; /* M = m1 + m2 (m1 = pulsar mass, m2 = companion mass) */
1627 output->m2 = 0.0; /* companion mass */
1628
1629 output->f0 = 0.0;
1630 output->f1 = 0.0;
1631 output->f2 = 0.0;
1632 output->f3 = 0.0;
1633 output->f4 = 0.0;
1634 output->f5 = 0.0;
1635 output->f6 = 0.0;
1636 output->f7 = 0.0;
1637 output->f8 = 0.0;
1638 output->f9 = 0.0;
1639 output->f10 = 0.0;
1640
1641 output->waveSin = NULL;
1642 output->waveCos = NULL;
1643 output->wave_om = 0.0;
1644 output->waveepoch = 0.0;
1645 output->nwaves = 0;
1646
1647 output->ra = 0.0;
1648 output->dec = 0.0;
1649 output->pmra = 0.0;
1650 output->pmdec = 0.0;
1651
1652 output->px = 0.; /* parallax (mas) */
1653 output->dist = 0.; /* distance (kpc) */
1654
1655 output->DM = 0.; /* dispersion measure */
1656 output->DM1 = 0.; /* first derivative of dispersion measure */
1657
1658 output->daop = 0.;
1659 output->daopset = 0;
1660 output->kin = 0.;
1661 output->kinset = 0;
1662 output->kom = 0.;
1663 output->komset = 0;
1664
1665 /* set all errors on params to zero */
1666 output->raErr = 0.0;
1667 output->decErr = 0.0;
1668 output->pmraErr = 0.0;
1669 output->pmdecErr = 0.0;
1670
1671 output->posepoch = 0.0;
1672 output->pepoch = 0.0;
1673
1674 output->posepochErr = 0.0;
1675 output->pepochErr = 0.0;
1676
1677 output->startTime = 0.0;
1678 output->finishTime = INFINITY;
1679
1680 output->xpbdotErr = 0.0; /* (10^-12) */
1681
1682 output->eps1Err = 0.0; /* e*sin(w) */
1683 output->eps2Err = 0.0; /* e*cos(w) */
1684 output->eps1dotErr = 0.0;
1685 output->eps2dotErr = 0.0;
1686 output->TascErr = 0.0; /* time of the ascending node (used rather than T0) */
1687
1688 output->wdotErr = 0.0; /* precesion of longitude of periastron w = w0 + wdot(tb-T0) (degs/year) */
1689 output->gammaErr = 0.0; /* gravitational redshift and time dilation parameter (s)*/
1690 output->PbdotErr = 0.0; /* rate of change of Pb (dimensionless 10^-12) */
1691 output->xdotErr = 0.0; /* rate of change of x(=asini/c) - optional (10^-12)*/
1692 output->edotErr = 0.0; /* rate of change of e (10^-12)*/
1693
1694 output->sErr = 0.0; /* Shapiro 'shape' parameter sin i */
1695 output->shapmaxErr = 0.;
1696
1697 /*output->rErr=0.0; Shapiro 'range' parameter */
1698 output->drErr = 0.0;
1699 output->dthErr = 0.0; /* (10^-6) */
1700 output->a0Err = 0.0;
1701 output->b0Err = 0.0; /* abberation delay parameters */
1702
1703 output->MErr = 0.0; /* M = m1 + m2 (m1 = pulsar mass, m2 = companion mass) */
1704 output->m2Err = 0.0; /* companion mass */
1705
1706 output->f0Err = 0.0;
1707 output->f1Err = 0.0;
1708 output->f2Err = 0.0;
1709 output->f3Err = 0.0;
1710 output->f4Err = 0.0;
1711 output->f5Err = 0.0;
1712 output->f6Err = 0.0;
1713 output->f7Err = 0.0;
1714 output->f8Err = 0.0;
1715 output->f9Err = 0.0;
1716 output->f10Err = 0.0;
1717
1718 output->eErr = 0.0;
1719 output->w0Err = 0.0;
1720 output->PbErr = 0.0;
1721 output->xErr = 0.0;
1722 output->T0Err = 0.0;
1723
1724 output->e2Err = 0.0;
1725 output->w02Err = 0.0;
1726 output->Pb2Err = 0.0;
1727 output->x2Err = 0.0;
1728 output->T02Err = 0.0;
1729
1730 output->e3Err = 0.0;
1731 output->w03Err = 0.0;
1732 output->Pb3Err = 0.0;
1733 output->x3Err = 0.0;
1734 output->T03Err = 0.0;
1735
1736 output->pxErr = 0.;
1737 output->distErr = 0.;
1738
1739 output->DMErr = 0.;
1740 output->DM1Err = 0.;
1741
1742 output->h0 = 0.;
1743 output->Q22 = 0.;
1744 output->cosiota = 0.;
1745 output->iota = 0.;
1746 output->psi = 0.;
1747 output->phi0 = 0.;
1748 output->Aplus = 0.;
1749 output->Across = 0.;
1750 output->I21 = 0.;
1751 output->I31 = 0.;
1752 output->lambdapin = 0.;
1753 output->costheta = 0.;
1754 output->theta = 0.;
1755 output->C22 = 0.;
1756 output->C21 = 0.;
1757 output->phi22 = 0.;
1758 output->phi21 = 0.;
1759
1760 output->hPlus = 0.;
1761 output->hCross = 0.;
1762 output->psiTensor = 0.;
1763 output->phi0Tensor = 0.;
1764 output->hScalarB = 0.;
1765 output->hScalarL = 0.;
1766 output->psiScalar = 0.;
1767 output->phi0Scalar = 0.;
1768 output->hVectorX = 0.;
1769 output->hVectorY = 0.;
1770 output->psiVector = 0.;
1771 output->phi0Vector = 0.;
1772
1773 output->h0Err = 0.;
1774 output->Q22Err = 0.;
1775 output->cosiotaErr = 0.;
1776 output->iotaErr = 0.;
1777 output->psiErr = 0.;
1778 output->phi0Err = 0.;
1779 output->AplusErr = 0.;
1780 output->AcrossErr = 0.;
1781 output->I21Err = 0.;
1782 output->I31Err = 0.;
1783 output->lambdapinErr = 0.;
1784 output->costhetaErr = 0.;
1785 output->thetaErr = 0.;
1786 output->C22Err = 0.;
1787 output->C21Err = 0.;
1788 output->phi22Err = 0.;
1789 output->phi21Err = 0.;
1790 output->hPlusErr = 0.;
1791 output->hCrossErr = 0.;
1792 output->psiTensorErr = 0.;
1793 output->phi0TensorErr = 0.;
1794 output->hScalarBErr = 0.;
1795 output->hScalarLErr = 0.;
1796 output->psiScalarErr = 0.;
1797 output->phi0ScalarErr = 0.;
1798 output->hVectorXErr = 0.;
1799 output->hVectorYErr = 0.;
1800 output->psiVectorErr = 0.;
1801 output->phi0VectorErr = 0.;
1802
1803 output->wave_omErr = 0.0;
1804
1805 output->cgw = 1.; /* initialise the GW speed to be the speed of light */
1806 output->cgwErr = 0.;
1807
1808 output->units = NULL;
1809 output->ephem = NULL;
1810
1811 if ( ( fp = fopen( pulsarAndPath, "r" ) ) == NULL ) {
1812 XLAL_PRINT_ERROR( "Error... Cannot open .par file %s\n", pulsarAndPath );
1814 }
1815
1816 /* read all the pulsar data into the string array */
1817 while ( !feof( fp ) ) {
1818 /* make sure val[i] is clear first */
1819 sprintf( val[i], "%s", "" );
1820
1821 c = fscanf( fp, "%s", val[i] );
1822
1823 /* if line starts with a '#' then skip to end of line */
1824 if ( val[i][0] == '#' ) {
1825 /* skip to the end of the line */
1826 c = fscanf( fp, "%*[^\n]" );
1827 if ( feof( fp ) ) {
1828 break;
1829 }
1830 continue;
1831 }
1832
1833 i++;
1834 }
1835
1836 k = i; /* k is the end number */
1837 i = 0; /* reset i */
1838
1839 /* set pulsar values for output */
1840 /* in .par files first column will param name, second will be param value,
1841 if third is defined it will be an integer to tell TEMPO whether to fit
1842 the param or not (don't need this), fourth will be the error on the
1843 param (in same units as the param) */
1844
1845 /* convert all epochs given in MJD in .par files to secs in TDB */
1846 while ( 1 ) {
1847 j = i;
1848 if ( !strcmp( val[i], "NAME" ) || !strcmp( val[i], "name" ) ) {
1849 output->name = XLALStringDuplicate( val[i + 1] );
1850 j++;
1851 } else if ( !strcmp( val[i], "PSRJ" ) || !strcmp( val[i], "psrj" ) ) {
1852 output->jname = XLALStringDuplicate( val[i + 1] );
1853 j++;
1854 } else if ( !strcmp( val[i], "PSRB" ) || !strcmp( val[i], "psrb" ) ) {
1855 output->bname = XLALStringDuplicate( val[i + 1] );
1856 j++;
1857 } else if ( !strcmp( val[i], "ra" ) || !strcmp( val[i], "RA" ) || !strcmp( val[i], "RAJ" ) ) {
1858 /* this can be in form hh:mm:ss.ss or hhmmss.ss */
1859 XLALTranslateHMStoRAD( &output->ra, val[i + 1] );
1860 j++;
1861
1862 /* only try to get error if one exists */
1863 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1864 /* assuming at the moment that error is in arcsec */
1865 output->raErr = LAL_TWOPI * atof( val[i + 3] ) / ( 24.0 * 60.0 * 60.0 );
1866 j += 2;
1867 }
1868 } else if ( !strcmp( val[i], "dec" ) || !strcmp( val[i], "DEC" ) || !strcmp( val[i], "DECJ" ) ) {
1869 XLALTranslateDMStoRAD( &output->dec, val[i + 1] );
1870 j++;
1871
1872 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1873 /* assuming at the moment that error is in arcsec */
1874 output->decErr = LAL_TWOPI * atof( val[i + 3] ) / ( 360.0 * 60.0 * 60.0 );
1875 j += 2;
1876 }
1877 } else if ( !strcmp( val[i], "pmra" ) || !strcmp( val[i], "PMRA" ) ) {
1878 /* convert pmra from mas/year to rads/sec */
1879 output->pmra = LAL_PI_180 * atof( val[i + 1] ) / ( 60.0 * 60.0 * 1000.*365.25 * 86400. );
1880 j++;
1881 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1882 output->pmraErr =
1883 LAL_PI_180 * atof( val[i + 3] ) / ( 60.0 * 60.0 * 1000.*365.25 * 86400. );
1884 j += 2;
1885 }
1886 } else if ( !strcmp( val[i], "pmdec" ) || !strcmp( val[i], "PMDEC" ) ) {
1887 /* convert pmdec from mas/year to rads/sec */
1888 output->pmdec = LAL_PI_180 * atof( val[j + 1] ) / ( 60.0 * 60.0 * 1000.*365.25 * 86400. );
1889 j++;
1890
1891 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1892 output->pmdecErr =
1893 LAL_PI_180 * atof( val[i + 3] ) / ( 60.0 * 60.0 * 1000.*365.25 * 86400. );
1894 j += 2;
1895 }
1896 } else if ( !strcmp( val[i], "pepoch" ) || !strcmp( val[i], "PEPOCH" ) ) {
1897 output->pepoch = XLALTTMJDtoGPS( atof( val[i + 1] ) ); /* convert all epochs to
1898 from MJD to GPS seconds in TDB */
1899 j++;
1900
1901 } else if ( !strcmp( val[i], "posepoch" ) || !strcmp( val[i], "POSEPOCH" ) ) {
1902 output->posepoch = XLALTTMJDtoGPS( atof( val[i + 1] ) );
1903 j++;
1904 /* position epoch in GPS seconds TDB */
1905 } else if ( !strcmp( val[i], "start" ) || !strcmp( val[i], "START" ) ) {
1906 output->startTime = XLALTTMJDtoGPS( atof( val[i + 1] ) ); /* convert all epochs to
1907 from MJD to GPS seconds in TDB */
1908 j++;
1909
1910 } else if ( !strcmp( val[i], "finish" ) || !strcmp( val[i], "FINISH" ) ) {
1911 output->finishTime = XLALTTMJDtoGPS( atof( val[i + 1] ) );
1912 j++;
1913 /* position epoch in GPS seconds TDB */
1914 } else if ( !strcmp( val[i], "f0" ) || !strcmp( val[i], "F0" ) ) {
1915 /* in .par files exponents sometimes shown as D/d rather than e/E
1916 need way to check this as atof will not convert D (but will
1917 work for e/E (if a d/D is present atof will convert the number
1918 before the d/D but not the exponent */
1919 CHAR *loc;
1920
1921 output->f0 = atof( val[i + 1] );
1922 j++;
1923
1924 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1925 /* check if exponent contains e/E or d/D or neither */
1926 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
1927 output->f0Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
1928 } else {
1929 output->f0Err = atof( val[i + 3] );
1930 }
1931 j += 2;
1932 }
1933 } else if ( !strcmp( val[i], "f1" ) || !strcmp( val[i], "F1" ) ) {
1934 CHAR *loc;
1935
1936 /* check if exponent contains e/E or d/D or neither */
1937 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
1938 output->f1 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
1939 } else {
1940 output->f1 = atof( val[i + 1] );
1941 }
1942 j++;
1943
1944 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1945 /* check if exponent contains e/E or d/D or neither */
1946 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
1947 output->f1Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
1948 } else {
1949 output->f1Err = atof( val[i + 3] );
1950 }
1951 j += 2;
1952 }
1953 } else if ( !strcmp( val[i], "f2" ) || !strcmp( val[i], "F2" ) ) {
1954 CHAR *loc;
1955
1956 /* check if exponent contains e/E or d/D or neither */
1957 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
1958 output->f2 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
1959 } else {
1960 output->f2 = atof( val[i + 1] );
1961 }
1962 j++;
1963
1964 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1965 /* check if exponent contains e/E or d/D or neither */
1966 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
1967 output->f2Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
1968 } else {
1969 output->f2Err = atof( val[i + 3] );
1970 }
1971 j += 2;
1972 }
1973 } else if ( !strcmp( val[i], "f3" ) || !strcmp( val[i], "F3" ) ) {
1974 CHAR *loc;
1975
1976 /* check if exponent contains e/E or d/D or neither */
1977 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
1978 output->f3 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
1979 } else {
1980 output->f3 = atof( val[i + 1] );
1981 }
1982 j++;
1983
1984 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
1985 /* check if exponent contains e/E or d/D or neither */
1986 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
1987 output->f3Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
1988 } else {
1989 output->f3Err = atof( val[i + 3] );
1990 }
1991 j += 2;
1992 }
1993 } else if ( !strcmp( val[i], "f4" ) || !strcmp( val[i], "F4" ) ) {
1994 CHAR *loc;
1995
1996 /* check if exponent contains e/E or d/D or neither */
1997 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
1998 output->f4 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
1999 } else {
2000 output->f4 = atof( val[i + 1] );
2001 }
2002 j++;
2003
2004 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2005 /* check if exponent contains e/E or d/D or neither */
2006 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2007 output->f4Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2008 } else {
2009 output->f4Err = atof( val[i + 3] );
2010 }
2011 j += 2;
2012 }
2013 } else if ( !strcmp( val[i], "f5" ) || !strcmp( val[i], "F5" ) ) {
2014 CHAR *loc;
2015
2016 /* check if exponent contains e/E or d/D or neither */
2017 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2018 output->f5 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2019 } else {
2020 output->f5 = atof( val[i + 1] );
2021 }
2022 j++;
2023
2024 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2025 /* check if exponent contains e/E or d/D or neither */
2026 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2027 output->f5Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2028 } else {
2029 output->f5Err = atof( val[i + 3] );
2030 }
2031 j += 2;
2032 }
2033 } else if ( !strcmp( val[i], "f6" ) || !strcmp( val[i], "F6" ) ) {
2034 CHAR *loc;
2035
2036 /* check if exponent contains e/E or d/D or neither */
2037 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2038 output->f6 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2039 } else {
2040 output->f6 = atof( val[i + 1] );
2041 }
2042 j++;
2043
2044 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2045 /* check if exponent contains e/E or d/D or neither */
2046 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2047 output->f6Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2048 } else {
2049 output->f6Err = atof( val[i + 3] );
2050 }
2051 j += 2;
2052 }
2053 } else if ( !strcmp( val[i], "f7" ) || !strcmp( val[i], "F7" ) ) {
2054 CHAR *loc;
2055
2056 /* check if exponent contains e/E or d/D or neither */
2057 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2058 output->f7 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2059 } else {
2060 output->f7 = atof( val[i + 1] );
2061 }
2062 j++;
2063
2064 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2065 /* check if exponent contains e/E or d/D or neither */
2066 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2067 output->f7Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2068 } else {
2069 output->f7Err = atof( val[i + 3] );
2070 }
2071 j += 2;
2072 }
2073 } else if ( !strcmp( val[i], "f8" ) || !strcmp( val[i], "F8" ) ) {
2074 CHAR *loc;
2075
2076 /* check if exponent contains e/E or d/D or neither */
2077 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2078 output->f8 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2079 } else {
2080 output->f8 = atof( val[i + 1] );
2081 }
2082 j++;
2083
2084 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2085 /* check if exponent contains e/E or d/D or neither */
2086 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2087 output->f8Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2088 } else {
2089 output->f8Err = atof( val[i + 3] );
2090 }
2091 j += 2;
2092 }
2093 } else if ( !strcmp( val[i], "f9" ) || !strcmp( val[i], "F9" ) ) {
2094 CHAR *loc;
2095
2096 /* check if exponent contains e/E or d/D or neither */
2097 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2098 output->f9 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2099 } else {
2100 output->f9 = atof( val[i + 1] );
2101 }
2102 j++;
2103
2104 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2105 /* check if exponent contains e/E or d/D or neither */
2106 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2107 output->f9Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2108 } else {
2109 output->f9Err = atof( val[i + 3] );
2110 }
2111 j += 2;
2112 }
2113 } else if ( !strcmp( val[i], "f10" ) || !strcmp( val[i], "F10" ) ) {
2114 CHAR *loc;
2115
2116 /* check if exponent contains e/E or d/D or neither */
2117 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2118 output->f10 = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2119 } else {
2120 output->f10 = atof( val[i + 1] );
2121 }
2122 j++;
2123
2124 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2125 /* check if exponent contains e/E or d/D or neither */
2126 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2127 output->f10Err = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2128 } else {
2129 output->f10Err = atof( val[i + 3] );
2130 }
2131 j += 2;
2132 }
2133 } else if ( !strcmp( val[i], "WAVE_OM" ) || !strcmp( val[i], "wave_om" ) ) {
2134 output->wave_om = atof( val[i + 1] );
2135 j++;
2136
2137 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2138 output->wave_omErr = atof( val[i + 3] );
2139 j += 2;
2140 }
2141 } else if ( !strcmp( val[i], "WAVEEPOCH" ) || !strcmp( val[i], "waveepoch" ) ) {
2142 output->waveepoch = XLALTTMJDtoGPS( atof( val[i + 1] ) );
2143 j++;
2144 } else if ( strstr( val[i], "WAVE" ) != NULL || strstr( val[i], "wave" ) != NULL ) {
2145 INT4 wnum = 0;
2146
2147 if ( sscanf( val[i] + 4, "%d", &wnum ) != 1 ) {
2148 fprintf( stderr, "Error reading WAVE number from par file\n" );
2149 exit( 1 );
2150 }
2151
2152 if ( wnum > output->nwaves ) {
2153 output->nwaves = wnum;
2154 output->waveSin = XLALRealloc( output->waveSin, wnum * sizeof( REAL8 ) );
2155 output->waveCos = XLALRealloc( output->waveCos, wnum * sizeof( REAL8 ) );
2156 }
2157
2158 output->waveSin[wnum - 1] = atof( val[i + 1] );
2159 output->waveCos[wnum - 1] = atof( val[i + 2] );
2160
2161 j++;
2162 } else if ( !strcmp( val[i], "binary" ) || !strcmp( val[i], "BINARY" ) ) {
2163 output->model = XLALStringDuplicate( val[i + 1] );
2164 j++;
2165 } else if ( !strcmp( val[i], "ephem" ) || !strcmp( val[i], "EPHEM" ) ) {
2166 output->ephem = XLALStringDuplicate( val[i + 1] );
2167 j++;
2168 } else if ( !strcmp( val[i], "units" ) || !strcmp( val[i], "UNITS" ) ) {
2169 output->units = XLALStringDuplicate( val[i + 1] );
2170 j++;
2171 } else if ( !strcmp( val[i], "a1" ) || !strcmp( val[i], "A1" ) ) {
2172 output->x = atof( val[i + 1] );
2173 j++;
2174
2175 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2176 output->xErr = atof( val[i + 3] );
2177 j += 2;
2178 }
2179 } else if ( !strcmp( val[i], "e" ) || !strcmp( val[i], "E" ) || !strcmp( val[i], "ECC" ) ||
2180 !strcmp( val[i], "ecc" ) ) {
2181 output->e = atof( val[i + 1] );
2182 j++;
2183
2184 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2185 output->eErr = atof( val[i + 3] );
2186 j += 2;
2187 }
2188 } else if ( !strcmp( val[i], "pb" ) || !strcmp( val[i], "PB" ) ) {
2189 output->Pb = atof( val[i + 1] ) * DAYSTOSECS;
2190 j++;
2191
2192 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2193 output->PbErr = atof( val[i + 3] ) * DAYSTOSECS;
2194 j += 2;
2195 }
2196 } else if ( !strcmp( val[i], "om" ) || !strcmp( val[i], "OM" ) ) {
2197 output->w0 = atof( val[i + 1] ) * LAL_PI_180; /* convert radians to seconds */
2198 j++;
2199
2200 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2201 output->w0Err = atof( val[i + 3] ) * LAL_PI_180;
2202 j += 2;
2203 }
2204 } else if ( !strcmp( val[i], "T0" ) ) {
2205 output->T0 = XLALTTMJDtoGPS( atof( val[i + 1] ) );
2206 j++;
2207
2208 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2209 output->T0Err = atof( val[i + 3] ) * DAYSTOSECS; /* convert to seconds */
2210 j += 2;
2211 }
2212 } else if ( !strcmp( val[i], "Tasc" ) || !strcmp( val[i], "TASC" ) ) {
2213 output->Tasc = XLALTTMJDtoGPS( atof( val[i + 1] ) );
2214 j++;
2215
2216 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2217 output->TascErr = atof( val[i + 3] ) * DAYSTOSECS; /* convert to seconds; */
2218 j += 2;
2219 }
2220 } else if ( !strcmp( val[i], "eps1" ) || !strcmp( val[i], "EPS1" ) ) {
2221 output->eps1 = atof( val[i + 1] );
2222 j++;
2223
2224 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2225 output->eps1Err = atof( val[i + 3] );
2226 j += 2;
2227 }
2228 } else if ( !strcmp( val[i], "eps2" ) || !strcmp( val[i], "EPS2" ) ) {
2229 output->eps2 = atof( val[i + 1] );
2230 j++;
2231
2232 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2233 output->eps2Err = atof( val[i + 3] );
2234 j += 2;
2235 }
2236 } else if ( !strcmp( val[i], "eps1dot" ) || !strcmp( val[i], "EPS1DOT" ) ) {
2237 output->eps1dot = atof( val[i + 1] );
2238 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */
2239 if ( fabs( output->eps1dot ) > 1e-7 ) {
2240 output->eps1dot *= 1.e-12;
2241 }
2242 j++;
2243
2244 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2245 output->eps1dotErr = atof( val[i + 3] );
2246 j += 2;
2247 }
2248 } else if ( !strcmp( val[i], "eps2dot" ) || !strcmp( val[i], "EPS2DOT" ) ) {
2249 output->eps2dot = atof( val[i + 1] );
2250 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */
2251 if ( fabs( output->eps2dot ) > 1e-7 ) {
2252 output->eps2dot *= 1.e-12;
2253 }
2254 j++;
2255
2256 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2257 output->eps2dotErr = atof( val[i + 3] );
2258 j += 2;
2259 }
2260 } else if ( !strcmp( val[i], "xpbdot" ) || !strcmp( val[i], "XPBDOT" ) ) {
2261 output->xpbdot = atof( val[i + 1] );
2262 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */
2263 if ( fabs( output->xpbdot ) > 1e-7 ) {
2264 output->xpbdot *= 1.e-12;
2265 }
2266 j++;
2267
2268 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2269 output->xpbdotErr = atof( val[i + 3] );
2270 j += 2;
2271 }
2272 } else if ( !strcmp( val[i], "omdot" ) || !strcmp( val[i], "OMDOT" ) ) {
2273 output->wdot = atof( val[i + 1] ) * LAL_PI_180 / ( 365.25 * DAYSTOSECS ); /* convert degs/years to rads/sec */
2274 j++;
2275
2276 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2277 output->wdotErr = atof( val[i + 3] ) * LAL_PI_180 / ( 365.25 * DAYSTOSECS );
2278 j += 2;
2279 }
2280 } else if ( !strcmp( val[i], "pbdot" ) || !strcmp( val[i], "PBDOT" ) ) {
2281 output->Pbdot = atof( val[i + 1] );
2282 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */
2283 if ( fabs( output->Pbdot ) > 1e-7 ) {
2284 output->Pbdot *= 1.e-12;
2285 }
2286 j++;
2287
2288 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2289 output->PbdotErr = atof( val[i + 3] );
2290 j += 2;
2291 }
2292 } else if ( !strcmp( val[i], "xdot" ) || !strcmp( val[i], "XDOT" ) ) {
2293 output->xdot = atof( val[i + 1] );
2294 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */
2295 if ( fabs( output->xdot ) > 1e-7 ) {
2296 output->xdot *= 1.e-12;
2297 }
2298 j++;
2299
2300 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2301 output->xdotErr = atof( val[i + 3] );
2302 j += 2;
2303 }
2304 } else if ( !strcmp( val[i], "edot" ) || !strcmp( val[i], "EDOT" ) ) {
2305 output->edot = atof( val[i + 1] );
2306 /* TEMPO2 checks if this is > 1e-7 then it's in units of 1e-12, so needs converting */
2307 if ( fabs( output->edot ) > 1e-7 ) {
2308 output->edot *= 1.e-12;
2309 }
2310 j++;
2311
2312 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2313 output->edotErr = atof( val[i + 3] );
2314 j += 2;
2315 }
2316
2317 /* some of the parameter files in the ATNF catalogue have values
2318 of EDOT that are stupidly large e.g. O(1e33). These can cause
2319 the time delay routines to fail, so if values of EDOT are
2320 greater than 10000 ignore them and set it to zero */
2321 if ( output->edot > 10000 ) {
2322 output->edot = 0.;
2323 output->edotErr = 0.;
2324 }
2325 } else if ( !strcmp( val[i], "gamma" ) || !strcmp( val[i], "GAMMA" ) ) {
2326 output->gamma = atof( val[i + 1] );
2327 j++;
2328
2329 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2330 output->gammaErr = atof( val[i + 3] );
2331 j += 2;
2332 }
2333 } else if ( !strcmp( val[i], "sini" ) || !strcmp( val[i], "SINI" ) ) {
2334 output->sstr = XLALStringDuplicate( val[i + 1] );
2335 j++;
2336
2337 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2338 output->sErr = atof( val[i + 3] );
2339 j += 2;
2340 }
2341 } else if ( !strcmp( val[i], "mtot" ) || !strcmp( val[i], "MTOT" ) ) {
2342 output->M = atof( val[i + 1] ) * LALPULSAR_TEMPO2_MSUN_SI;
2343 j++;
2344
2345 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2346 output->MErr = atof( val[i + 3] ) * LALPULSAR_TEMPO2_MSUN_SI;
2347 j += 2;
2348 }
2349 } else if ( !strcmp( val[i], "m2" ) || !strcmp( val[i], "M2" ) ) {
2350 output->m2 = atof( val[i + 1] ) * LALPULSAR_TEMPO2_MSUN_SI;
2351 j++;
2352
2353 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2354 output->m2Err = atof( val[i + 3] ) * LALPULSAR_TEMPO2_MSUN_SI;
2355 j += 2;
2356 }
2357 } else if ( !strcmp( val[i], "a0" ) || !strcmp( val[i], "A0" ) ) {
2358 output->a0 = atof( val[i + 1] );
2359 j++;
2360
2361 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2362 output->a0Err = atof( val[i + 3] );
2363 j += 2;
2364 }
2365 } else if ( !strcmp( val[i], "b0" ) || !strcmp( val[i], "B0" ) ) {
2366 output->b0 = atof( val[i + 1] );
2367 j++;
2368
2369 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2370 output->b0Err = atof( val[i + 3] );
2371 j += 2;
2372 }
2373 } else if ( !strcmp( val[i], "dr" ) || !strcmp( val[i], "DR" ) ) {
2374 output->dr = atof( val[i + 1] );
2375 j++;
2376
2377 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2378 output->drErr = atof( val[i + 3] );
2379 j += 2;
2380 }
2381 } else if ( !strcmp( val[i], "dtheta" ) || !strcmp( val[i], "DTHETA" ) ) {
2382 output->dth = atof( val[i + 1] );
2383 j++;
2384
2385 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2386 output->dthErr = atof( val[i + 3] );
2387 j += 2;
2388 }
2389 } else if ( !strcmp( val[i], "shapmax" ) || !strcmp( val[i], "SHAPMAX" ) ) {
2390 output->shapmax = atof( val[i + 1] );
2391 j++;
2392
2393 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2394 output->shapmaxErr = atof( val[i + 3] );
2395 j += 2;
2396 }
2397 }
2398
2399 /* parameters for Kopeikin terms */
2400 else if ( !strcmp( val[i], "D_AOP" ) || !strcmp( val[i], "d_aop" ) ) {
2401 /* convert into 1/rads (factor from T2model.C in TEMPO2 */
2402 output->daop = atof( val[i + 1] ) * 3600.0 / LAL_PI_180;
2403 output->daopset = 1;
2404 j++;
2405 } else if ( !strcmp( val[i], "KIN" ) || !strcmp( val[i], "kin" ) ) {
2406 output->kin = atof( val[i + 1] ) * LAL_PI_180; /* convert degs to rads */
2407 output->kinset = 1;
2408 j++;
2409 } else if ( !strcmp( val[i], "KOM" ) || !strcmp( val[i], "kom" ) ) {
2410 output->kom = atof( val[i + 1] ) * LAL_PI_180; /* convert degs to rads */
2411 output->komset = 1;
2412 j++;
2413 }
2414
2415 /* parameters for distance */
2416 else if ( !strcmp( val[i], "px" ) || !strcmp( val[i], "PX" ) ) { /* parallax */
2417 /* convert from mas to rads (factor from T2model.C in TEMPO2) */
2418 output->px = atof( val[i + 1] ) * LAL_PI_180 / 3600.0e3;
2419 j++;
2420
2421 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2422 output->pxErr = atof( val[i + 3] );
2423 j += 2;
2424 }
2425 } else if ( !strcmp( val[i], "dist" ) || !strcmp( val[i], "DIST" ) ) { /* distance */
2426 output->dist = atof( val[i + 1] ); /* in kpc */
2427 j++;
2428
2429 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2430 output->distErr = atof( val[i + 3] );
2431 j += 2;
2432 }
2433 }
2434
2435 /* dispersion measure parameters */
2436 else if ( !strcmp( val[i], "dm" ) || !strcmp( val[i], "DM" ) ) {
2437 output->DM = atof( val[i + 1] );
2438 j++;
2439
2440 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2441 output->DMErr = atof( val[i + 3] );
2442 j += 2;
2443 }
2444 } else if ( !strcmp( val[i], "dm1" ) || !strcmp( val[i], "DM1" ) ) {
2445 output->DM1 = atof( val[i + 1] );
2446 j++;
2447
2448 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2449 output->DM1Err = atof( val[i + 3] );
2450 j += 2;
2451 }
2452 }
2453
2454 /* add parameters extra orbital parameters for the BT1P and BT2P models */
2455 else if ( !strcmp( val[i], "a1_2" ) || !strcmp( val[i], "A1_2" ) ) {
2456 output->x2 = atof( val[i + 1] );
2457 j++;
2458
2459 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2460 output->x2Err = atof( val[i + 3] );
2461 j += 2;
2462 }
2463 } else if ( !strcmp( val[i], "e_2" ) || !strcmp( val[i], "E_2" ) ||
2464 !strcmp( val[i], "ECC_2" ) || !strcmp( val[i], "ecc_2" ) ) {
2465 output->e2 = atof( val[i + 1] );
2466 j++;
2467
2468 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2469 output->e2Err = atof( val[i + 3] );
2470 j += 2;
2471 }
2472 } else if ( !strcmp( val[i], "pb_2" ) || !strcmp( val[i], "PB_2" ) ) {
2473 output->Pb2 = atof( val[i + 1] ) * DAYSTOSECS;
2474 j++;
2475
2476 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2477 output->Pb2Err = atof( val[i + 3] ) * DAYSTOSECS;
2478 j += 2;
2479 }
2480 } else if ( !strcmp( val[i], "om_2" ) || !strcmp( val[i], "OM_2" ) ) {
2481 output->w02 = atof( val[i + 1] ) * LAL_PI_180;
2482 j++;
2483
2484 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2485 output->w02Err = atof( val[i + 3] ) * LAL_PI_180;
2486 j += 2;
2487 }
2488 } else if ( !strcmp( val[i], "T0_2" ) ) {
2489 output->T02 = XLALTTMJDtoGPS( atof( val[i + 1] ) );
2490 j++;
2491
2492 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2493 output->T02Err = atof( val[i + 3] ) * DAYSTOSECS; /* convert to seconds */
2494 j += 2;
2495 }
2496 } else if ( !strcmp( val[i], "a1_3" ) || !strcmp( val[i], "A1_3" ) ) {
2497 output->x3 = atof( val[i + 1] );
2498 j++;
2499
2500 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2501 output->x3Err = atof( val[i + 3] );
2502 j += 2;
2503 }
2504 } else if ( !strcmp( val[i], "e_3" ) || !strcmp( val[i], "E_3" ) ||
2505 !strcmp( val[i], "ECC_3" ) || !strcmp( val[i], "ecc_3" ) ) {
2506 output->e3 = atof( val[i + 1] );
2507 j++;
2508
2509 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2510 output->e3Err = atof( val[i + 3] );
2511 j += 2;
2512 }
2513 } else if ( !strcmp( val[i], "pb_3" ) || !strcmp( val[i], "PB_3" ) ) {
2514 output->Pb3 = atof( val[i + 1] ) * DAYSTOSECS;
2515 j++;
2516
2517 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2518 output->Pb3Err = atof( val[i + 3] ) * DAYSTOSECS;
2519 j += 2;
2520 }
2521 } else if ( !strcmp( val[i], "om_3" ) || !strcmp( val[i], "OM_3" ) ) {
2522 output->w03 = atof( val[i + 1] ) * LAL_PI_180;
2523 j++;
2524
2525 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2526 output->w03Err = atof( val[i + 3] ) * LAL_PI_180;
2527 j += 2;
2528 }
2529 } else if ( !strcmp( val[i], "T0_3" ) ) {
2530 output->T03 = XLALTTMJDtoGPS( atof( val[i + 1] ) );
2531 j++;
2532
2533 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2534 output->T03Err = atof( val[i + 3] ) * DAYSTOSECS; /* convert to seconds */
2535 j += 2;
2536 }
2537 }
2538 /* orbital frequency coefficients for BTX model (up to 12 FB coefficients), but
2539 only one orbit at the moment i.e. only a two body system */
2540 else if ( val[i][0] == 'F' && val[i][1] == 'B' ) {
2541 INT4 fbnum = 0;
2542 CHAR *loc;
2543
2544 if ( strlen( val[i] ) == 2 ) {
2545 fbnum = 0; /* only one coefficient */
2546 } else {
2547 if ( sscanf( val[i] + 2, "%d", &fbnum ) != 1 ) {
2548 fprintf( stderr, "Error reading FB value from par file\n" );
2549 exit( 1 );
2550 }
2551 }
2552
2553 /* add to number of coefficients */
2554 if ( output->nfb < fbnum + 1 ) {
2555 output->fb = XLALRealloc( output->fb, ( fbnum + 1 ) * sizeof( REAL8 ) );
2556 output->fbErr = XLALRealloc( output->fbErr, ( fbnum + 1 ) * sizeof( REAL8 ) );
2557 output->nfb = fbnum + 1;
2558 }
2559
2560 /* check if exponent contains e/E or d/D or neither */
2561 if ( ( loc = strstr( val[i + 1], "D" ) ) != NULL || ( loc = strstr( val[i + 1], "d" ) ) != NULL ) {
2562 output->fb[fbnum] = atof( val[i + 1] ) * pow( 10, atof( loc + 1 ) );
2563 } else {
2564 output->fb[fbnum] = atof( val[i + 1] );
2565 }
2566 j++;
2567
2568 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2569 /* check if exponent contains e/E or d/D or neither */
2570 if ( ( loc = strstr( val[i + 3], "D" ) ) != NULL || ( loc = strstr( val[i + 3], "d" ) ) != NULL ) {
2571 output->fbErr[fbnum] = atof( val[i + 3] ) * pow( 10, atof( loc + 1 ) );
2572 } else {
2573 output->fbErr[fbnum] = atof( val[i + 3] );
2574 }
2575 j += 2;
2576 }
2577 }
2578 /* read in pulsar gravitational wave parameters */
2579 else if ( !strcmp( val[i], "h0" ) || !strcmp( val[i], "H0" ) ) {
2580 output->h0 = atof( val[i + 1] );
2581 j++;
2582
2583 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2584 output->h0Err = atof( val[i + 3] );
2585 j += 2;
2586 }
2587 } else if ( !strcmp( val[i], "q22" ) || !strcmp( val[i], "Q22" ) ) {
2588 output->Q22 = atof( val[i + 1] );
2589 j++;
2590
2591 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2592 output->Q22Err = atof( val[i + 3] );
2593 j += 2;
2594 }
2595 } else if ( !strcmp( val[i], "cosiota" ) || !strcmp( val[i], "COSIOTA" ) ||
2596 !strcmp( val[i], "ciota" ) || !strcmp( val[i], "CIOTA" ) ) {
2597 output->cosiota = atof( val[i + 1] );
2598 j++;
2599
2600 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2601 output->cosiotaErr = atof( val[i + 3] );
2602 j += 2;
2603 }
2604 } else if ( !strcmp( val[i], "iota" ) || !strcmp( val[i], "IOTA" ) ) {
2605 output->iota = atof( val[i + 1] );
2606 j++;
2607
2608 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2609 output->iotaErr = atof( val[i + 3] );
2610 j += 2;
2611 }
2612 } else if ( !strcmp( val[i], "psi" ) || !strcmp( val[i], "PSI" ) ) {
2613 output->psi = atof( val[i + 1] );
2614 j++;
2615
2616 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2617 output->psiErr = atof( val[i + 3] );
2618 j += 2;
2619 }
2620 } else if ( !strcmp( val[i], "phi0" ) || !strcmp( val[i], "PHI0" ) ) {
2621 output->phi0 = atof( val[i + 1] );
2622 j++;
2623
2624 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2625 output->phi0Err = atof( val[i + 3] );
2626 j += 2;
2627 }
2628 } else if ( !strcmp( val[i], "aplus" ) || !strcmp( val[i], "APLUS" ) ) {
2629 output->Aplus = atof( val[i + 1] );
2630 j++;
2631
2632 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2633 output->AplusErr = atof( val[i + 3] );
2634 j += 2;
2635 }
2636 } else if ( !strcmp( val[i], "across" ) || !strcmp( val[i], "ACROSS" ) ) {
2637 output->Across = atof( val[i + 1] );
2638 j++;
2639
2640 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2641 output->AcrossErr = atof( val[i + 3] );
2642 j += 2;
2643 }
2644 } else if ( !strcmp( val[i], "i21" ) || !strcmp( val[i], "I21" ) ) {
2645 output->I21 = atof( val[i + 1] );
2646 j++;
2647
2648 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2649 output->I21Err = atof( val[i + 3] );
2650 j += 2;
2651 }
2652 } else if ( !strcmp( val[i], "i31" ) || !strcmp( val[i], "I31" ) ) {
2653 output->I31 = atof( val[i + 1] );
2654 j++;
2655
2656 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2657 output->I31Err = atof( val[i + 3] );
2658 j += 2;
2659 }
2660 } else if ( !strcmp( val[i], "lambdapin" ) || !strcmp( val[i], "LAMBDAPIN" ) ) {
2661 output->lambdapin = atof( val[i + 1] );
2662 j++;
2663
2664 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2665 output->lambdapinErr = atof( val[i + 3] );
2666 j += 2;
2667 }
2668 } else if ( !strcmp( val[i], "costheta" ) || !strcmp( val[i], "COSTHETA" ) ) {
2669 output->costheta = atof( val[i + 1] );
2670 j++;
2671
2672 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2673 output->costhetaErr = atof( val[i + 3] );
2674 j += 2;
2675 }
2676 } else if ( !strcmp( val[i], "theta" ) || !strcmp( val[i], "THETA" ) ) {
2677 output->theta = atof( val[i + 1] );
2678 j++;
2679
2680 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2681 output->thetaErr = atof( val[i + 3] );
2682 j += 2;
2683 }
2684 } else if ( !strcmp( val[i], "c22" ) || !strcmp( val[i], "C22" ) ) {
2685 output->C22 = atof( val[i + 1] );
2686 j++;
2687
2688 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2689 output->C22Err = atof( val[i + 3] );
2690 j += 2;
2691 }
2692 } else if ( !strcmp( val[i], "c21" ) || !strcmp( val[i], "C21" ) ) {
2693 output->C21 = atof( val[i + 1] );
2694 j++;
2695
2696 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2697 output->C21Err = atof( val[i + 3] );
2698 j += 2;
2699 }
2700 } else if ( !strcmp( val[i], "phi22" ) || !strcmp( val[i], "PHI22" ) ) {
2701 output->phi22 = atof( val[i + 1] );
2702 j++;
2703
2704 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2705 output->phi22Err = atof( val[i + 3] );
2706 j += 2;
2707 }
2708 } else if ( !strcmp( val[i], "phi21" ) || !strcmp( val[i], "phi21" ) ) {
2709 output->phi21 = atof( val[i + 1] );
2710 j++;
2711
2712 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2713 output->phi21Err = atof( val[i + 3] );
2714 j += 2;
2715 }
2716 } else if ( !strcmp( val[i], "hplus" ) || !strcmp( val[i], "HPLUS" ) ) {
2717 output->hPlus = atof( val[i + 1] );
2718 j++;
2719
2720 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2721 output->hPlus = atof( val[i + 3] );
2722 j += 2;
2723 }
2724 } else if ( !strcmp( val[i], "hcross" ) || !strcmp( val[i], "HCROSS" ) ) {
2725 output->hCross = atof( val[i + 1] );
2726 j++;
2727
2728 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2729 output->hCrossErr = atof( val[i + 3] );
2730 j += 2;
2731 }
2732 } else if ( !strcmp( val[i], "psitensor" ) || !strcmp( val[i], "PSITENSOR" ) ) {
2733 output->psiTensor = atof( val[i + 1] );
2734 j++;
2735
2736 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2737 output->psiTensorErr = atof( val[i + 3] );
2738 j += 2;
2739 }
2740 } else if ( !strcmp( val[i], "phi0tensor" ) || !strcmp( val[i], "PHI0TENSOR" ) ) {
2741 output->phi0Tensor = atof( val[i + 1] );
2742 j++;
2743
2744 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2745 output->phi0TensorErr = atof( val[i + 3] );
2746 j += 2;
2747 }
2748 } else if ( !strcmp( val[i], "hscalarb" ) || !strcmp( val[i], "HSCALARB" ) ) {
2749 output->hScalarB = atof( val[i + 1] );
2750 j++;
2751
2752 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2753 output->hScalarBErr = atof( val[i + 3] );
2754 j += 2;
2755 }
2756 } else if ( !strcmp( val[i], "hscalarl" ) || !strcmp( val[i], "HSCALARL" ) ) {
2757 output->hScalarL = atof( val[i + 1] );
2758 j++;
2759
2760 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2761 output->hScalarLErr = atof( val[i + 3] );
2762 j += 2;
2763 }
2764 } else if ( !strcmp( val[i], "psiscalar" ) || !strcmp( val[i], "PSISCALAR" ) ) {
2765 output->psiScalar = atof( val[i + 1] );
2766 j++;
2767
2768 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2769 output->psiScalarErr = atof( val[i + 3] );
2770 j += 2;
2771 }
2772 } else if ( !strcmp( val[i], "phi0scalar" ) || !strcmp( val[i], "PHI0SCALAR" ) ) {
2773 output->phi0Scalar = atof( val[i + 1] );
2774 j++;
2775
2776 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2777 output->phi0ScalarErr = atof( val[i + 3] );
2778 j += 2;
2779 }
2780 } else if ( !strcmp( val[i], "hvectorx" ) || !strcmp( val[i], "HVECTORX" ) ) {
2781 output->hVectorX = atof( val[i + 1] );
2782 j++;
2783
2784 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2785 output->hVectorXErr = atof( val[i + 3] );
2786 j += 2;
2787 }
2788 } else if ( !strcmp( val[i], "hvectory" ) || !strcmp( val[i], "HVECTORY" ) ) {
2789 output->hVectorY = atof( val[i + 1] );
2790 j++;
2791
2792 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2793 output->hVectorYErr = atof( val[i + 3] );
2794 j += 2;
2795 }
2796 } else if ( !strcmp( val[i], "psivector" ) || !strcmp( val[i], "PSIVECTOR" ) ) {
2797 output->psiVector = atof( val[i + 1] );
2798 j++;
2799
2800 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2801 output->psiVectorErr = atof( val[i + 3] );
2802 j += 2;
2803 }
2804 } else if ( !strcmp( val[i], "phi0vector" ) || !strcmp( val[i], "PHI0VECTOR" ) ) {
2805 output->phi0Vector = atof( val[i + 1] );
2806 j++;
2807
2808 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2809 output->phi0VectorErr = atof( val[i + 3] );
2810 j += 2;
2811 }
2812 } else if ( !strcmp( val[i], "cgw" ) || !strcmp( val[i], "CGW" ) ) {
2813 output->cgw = atof( val[i + 1] );
2814 j++;
2815
2816 if ( atoi( val[i + 2] ) == 1 && i + 2 < k ) {
2817 output->cgwErr = atof( val[i + 3] );
2818 j += 2;
2819 }
2820 }
2821
2822 if ( j == i ) {
2823 i++;
2824 } else {
2825 i += ( j - i );
2826 }
2827
2828 if ( i >= k ) {
2829 break;
2830 }
2831 }
2832
2833 /*fprintf(stderr, "Have I got to the end of LALReadPARFile.\n");*/
2834 fclose( fp );
2835
2836 /* check linked parameters */
2837 if ( output->sstr != NULL ) {
2838 if ( !strcmp( output->sstr, "KIN" ) || !strcmp( output->sstr, "kin" ) ) {
2839 if ( output->kinset ) {
2840 output->s = sin( output->kin );
2841 } else {
2842 XLAL_PRINT_ERROR( "Error... KIN not set in .par file %s\n", pulsarAndPath );
2844 }
2845 } else {
2846 output->s = atof( output->sstr );
2847 }
2848 }
2849}
2850
2852/* function to print out to screen all the pulsar parameters and there associated errors */
2854{
2855 fprintf( stderr, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n" );
2856 fprintf( stderr, "PULSAR %s :\n", params.name );
2857 fprintf( stderr, "sky position:\tra %.7lf +/- %.3le rads, dec %.7lf +/- %.3le rads\n", params.ra,
2858 params.raErr, params.dec, params.decErr );
2859 if ( params.pmra != 0. || params.pmdec != 0. )
2860 fprintf( stderr, "proper motion:\tra %.4le +/- %.1le rads/s, dec %.4le +/- %.1le rads/s\n",
2861 params.pmra, params.pmraErr, params.pmdec, params.pmdecErr );
2862 if ( params.pepoch != 0. || params.posepoch != 0. )
2863 fprintf( stderr, "epochs:\tperiod %lf (GPS), position %lf (GPS)\n", params.pepoch,
2864 params.posepoch );
2865 fprintf( stderr, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n\n" );
2866
2867 fprintf( stderr, "Frequency parameters\n" );
2868 if ( params.f0 != 0. ) {
2869 fprintf( stderr, "\tf0 = %.10lf +/- %.3le (Hz)\n", params.f0, params.f0Err );
2870 }
2871 if ( params.f1 != 0. ) {
2872 fprintf( stderr, "\tf1 = %.5le +/- %.3le (Hz/s)\n", params.f1, params.f1Err );
2873 }
2874 if ( params.f2 != 0. ) {
2875 fprintf( stderr, "\tf1 = %.5le +/- %.3le (Hz/s^2)\n", params.f2, params.f2Err );
2876 }
2877 /* print binary parameters */
2878 if ( params.model != NULL ) {
2879 fprintf( stderr, "\nBinary parameters:\tmodel %s\n", params.model );
2880
2881 fprintf( stderr, "Keplarian parameters:-\n" );
2882 if ( params.Pb != 0. ) {
2883 fprintf( stderr, "\tperiod = %lf +/- %.3le (days)\n", params.Pb, params.PbErr );
2884 }
2885 if ( params.x != 0. )
2886 fprintf( stderr, "\tprojected semi-major axis = %lf +/- %.3le (light sec)\n", params.x,
2887 params.xErr );
2888 if ( params.e != 0. ) {
2889 fprintf( stderr, "\teccentricity = %lf +/- %.3le\n", params.e, params.eErr );
2890 }
2891 if ( params.w0 != 0. )
2892 fprintf( stderr, "\tlongitude of periastron = %lf +/- %.3lf (degs)\n", params.w0,
2893 params.w0Err );
2894 if ( params.T0 != 0. ) {
2895 fprintf( stderr, "\ttime of periastron = %lf +/- %.3lf (GPS)\n", params.T0, params.T0Err );
2896 }
2897 if ( params.Tasc != 0. )
2898 fprintf( stderr, "\ttime of ascending node = %lf +/- %.3lf (GPS)\n", params.Tasc,
2899 params.TascErr );
2900 if ( params.eps1 != 0. )
2901 fprintf( stderr, "\tfirst Laplace-Lagrange parameter (eps1) = %le +/- %.3le\n", params.eps1,
2902 params.eps1Err );
2903 if ( params.eps2 != 0. )
2904 fprintf( stderr, "\tsecond Laplace-Lagrange parameter (eps1) = %le +/- %.3le\n", params.eps2,
2905 params.eps2Err );
2906 if ( params.eps2 != 0. )
2907 fprintf( stderr, "\tsecond Laplace-Lagrange parameter (eps1) = %le +/- %.3le\n", params.eps2,
2908 params.eps2Err );
2909
2910 /*fprintf(stderr, "Post-Newtonian parameters:-\n");
2911 if(params.gamma != 0.)
2912 fprintf(stderr, "\tGravitational redshift parameter = %le +/- %.3le\n", params.gamma,
2913 params.gammaErr);*/
2914
2915 }
2916}
2918
2920{
2921 FILE *fp = NULL;
2922 CHAR *firstline = XLALStringDuplicate( "" );
2923 CHAR onechar[2];
2924 INT4 i = 0, numPars = 0, c = 1, sl = 0;
2925 LALStringVector *tmpparams = NULL; /* temporary parameter names */
2926 LALStringVector *params = NULL;
2927 UINT4Vector *dims = NULL;
2928
2929 /* check the file exists */
2930 if ( access( corfile, F_OK ) != 0 ) {
2931 XLAL_PRINT_ERROR( "Error... correlation matrix file does not exist!\n" );
2933 }
2934
2935 /* open file */
2936 if ( ( fp = fopen( corfile, "r" ) ) == NULL ) {
2937 XLAL_PRINT_ERROR( "Error... cannot open correlation matrix file!\n" );
2939 }
2940
2941 /* read in first line of the file */
2942 while ( !strchr( fgets( onechar, 2, fp ), '\n' ) ) {
2943 firstline = XLALStringAppend( firstline, onechar );
2944 }
2945
2946 sl = strlen( firstline );
2947
2948 /* count the number of parameters */
2949 for ( i = 0; i < sl; i++ ) {
2950 /* use isspace as delimiters could be unknown generic whitespace */
2951 if ( !isspace( firstline[i] ) ) {
2952 if ( c ) {
2953 numPars++;
2954 c = 0;
2955 }
2956 } else {
2957 c = 1;
2958 }
2959 }
2960
2961 /* parse the line and put into the params vector */
2962 rewind( fp ); /* rewind to start of the file */
2963 for ( i = 0; i < numPars; i++ ) {
2964 CHAR tmpStr[128];
2965
2966 if ( fscanf( fp, "%s", tmpStr ) == EOF ) {
2967 XLAL_PRINT_ERROR( "Error... Problem reading first line of correlation\
2968 matrix!\n" );
2970 }
2971
2972 tmpparams = XLALAppendString2Vector( tmpparams, tmpStr );
2973
2974 /* convert some parameter names to a more common convention */
2975 if ( !XLALStringCaseCompare( tmpStr, "RAJ" ) ) { /* convert RAJ to ra */
2977 } else if ( !XLALStringCaseCompare( tmpStr, "DECJ" ) ) { /* convert DECJ to dec */
2979 } else {
2981 }
2982 }
2983
2984 dims = XLALCreateUINT4Vector( 2 );
2985 dims->data[0] = numPars;
2986 dims->data[1] = numPars;
2987
2988 /* set the correlation matrix to the correct size */
2989 cormat = XLALResizeREAL8Array( cormat, dims );
2990
2991 /* read through covariance values */
2992 for ( i = 0; i < numPars; i++ ) {
2993 CHAR tmpStr[128];
2994 INT4 j = 0;
2995
2996 if ( fscanf( fp, "%s", tmpStr ) == EOF ) {
2997 XLAL_PRINT_ERROR( "Error... problem reading in correlation matrix!\n" );
2999 }
3000
3001 if ( strcmp( tmpStr, tmpparams->data[i] ) ) {
3002 XLAL_PRINT_ERROR( "Error... problem reading in correlation matrix. \
3003Parameters not in consistent order!\n" );
3005 }
3006
3007 for ( j = 0; j < i + 1; j++ ) {
3008 REAL8 tmpval = 0.;
3009
3010 if ( fscanf( fp, "%lf", &tmpval ) == EOF ) {
3011 XLAL_PRINT_ERROR( "Error... problem reading in correlation matrix!\n" );
3013 }
3014
3015 /* if off diagonal values are +/-1 set to +/- 0.99999 */
3016 if ( j != i && fabs( tmpval ) == 1. ) {
3017 tmpval *= 0.99999;
3018 }
3019
3020 cormat->data[i * numPars + j] = tmpval;
3021
3022 /* set opposite elements */
3023 if ( j != i ) {
3024 cormat->data[j * numPars + i] = tmpval;
3025 }
3026 }
3027 }
3028
3029 XLALDestroyStringVector( tmpparams );
3030
3031 return params;
3032}
3033
3034
3035/* functions for converting times given in Terrestrial time TT or TDB in MJD to
3036times in GPS - this is important for epochs given in .par files which are in
3037TDB. TT and GPS are different by a factor of 51.184 secs, this is just the
3038historical factor of 32.184 secs between TT and TAI (International Atomic Time)
3039and the other 19 seconds come from the leap seonds added between the TAI and
3040UTC up to the point of definition of GPS time at UTC 01/01/1980 (see
3041http://www.stjarnhimlen.se/comp/time.html for details) */
3042
3043/* a very good paper describing the tranforms between different time systems
3044and why they are necessary can be found in Seidelmann and Fukushima, A&A 265
3045(1992) http://ukads.nottingham.ac.uk/abs/1992A%26A...265..833S */
3046
3047/** This function converts a MJD format time corrected to Terrestrial Time (TT)
3048 * into an equivalent GPS time */
3050{
3051
3052 LIGOTimeGPS GPS;
3053 REAL8 mjdInt, mjdFrac;
3054 mjdFrac = modf( MJD, &mjdInt );
3055 XLAL_CHECK_REAL8( XLALTranslateMJDTTtoGPS( &GPS, ( INT4 )mjdInt, mjdFrac ) != NULL, XLAL_EFUNC );
3056
3057 return XLALGPSGetREAL8( &GPS );
3058}
3059
3060/** If you have an MJD arrival time on the Earth then this will convert it to
3061 * the equivalent GPS time in TDB (see Table 1 of Seidelmann and Fukushima,
3062 * Astronomy & Astrophysics, 265, 833-838 (1992).
3063 *
3064 * Note that XLALBarycenter performs these TDBtoTT corrections (i.e. the
3065 * Einstein delay) when correcting a GPS time on the Earth to TDB. Also, for
3066 * TEMPO produced pulsar epochs given in MJD these are already in the TDB
3067 * system and an equivalent GPS time in the TDB can be calculated just using
3068 * \c XLALTTMJDtoGPS.
3069 */
3071{
3072 REAL8 GPS;
3073 REAL8 T, TDBtoTT;
3074
3075 /* Check not before the start of GPS time */
3076 XLAL_CHECK_REAL8( MJD >= GPS0MJD, XLAL_EDOM, "Input MJD time %.1f is not in range, must be > %.1f.\n", MJD, GPS0MJD );
3077
3078 /* use factors from Table 1 of Seidelmann and Fukushima, Astronomy &
3079 * Astrophysics, 265, 833-838 (1992) where TDB = TDT + P
3080 * and:
3081 * P = 0.0016568 sin(35999.37 degs x T + 357.5 degs) +
3082 0.0000224 sin(32964.5 degs x T + 246.0 degs) +
3083 0.0000138 sin(71998.7 degs x T + 355.0 degs) +
3084 0.0000048 sin(3034.9 degs x T + 25.0 degs) +
3085 0.0000047 sin(34777.3 degs x T + 230.0 degs)
3086 * and T is the elapsed time from J2000 (which has a Julian day date of
3087 * JD 2451545.0) in Julian centuries.*/
3088 T = MJD + ( XLAL_MJD_REF - XLAL_EPOCH_J2000_0_JD );
3089 T /= 36525.; /* covert days to Julian centuries */
3090
3091 /* time diff in seconds (the Einstein delay) */
3092 TDBtoTT = 0.0016568 * sin( ( 35999.37 * T + 357.5 ) * LAL_PI_180 ) +
3093 0.0000224 * sin( ( 32964.5 * T + 246.0 ) * LAL_PI_180 ) +
3094 0.0000138 * sin( ( 71998.7 * T + 355.0 ) * LAL_PI_180 ) +
3095 0.0000048 * sin( ( 3034.9 * T + 25.0 ) * LAL_PI_180 ) +
3096 0.0000047 * sin( ( 34777.3 * T + 230.0 ) * LAL_PI_180 );
3097
3098 /* convert TDB to TT (TDB-TDBtoTT) and then convert TT to GPS */
3099 /* there is the magical number factor of 32.184 + 19 leap seconds to the
3100 * start of GPS time */
3101 GPS = ( MJD - GPS0MJD ) * 86400. - GPS_TDT - TDBtoTT;
3102
3103 return GPS;
3104}
3105
3106
3107/** If you have an MJD arrival time on the Earth then this will convert it to
3108 * the equivalent GPS time in TCB (see Table 1 of Seidelmann and Fukushima,
3109 * Astronomy & Astrophysics, 265, 833-838, 1992).
3110 *
3111 * Note that for default TEMPO2 produced pulsar epochs given in MJD these are
3112 * already in the TCB system and an equivalent GPS time in the TCB can be
3113 * calculated just using \c XLALTTMJDtoGPS. */
3115{
3116 REAL8 GPS;
3117 REAL8 Tdiff;
3118 REAL8 TCBtoTDB;
3119
3120 /* Check not before the start of GPS time (MJD 44244) */
3121 XLAL_CHECK_REAL8( MJD >= GPS0MJD, XLAL_EDOM, "Input MJD time %.1f is not in\
3122 range, must be > %.1f.\n", MJD, GPS0MJD );
3123
3124 /* from Seidelmann and Fukushima we have a linear drift term:
3125 * TCB - TDB = 1.550506e-8 x (JD - 2443144.5) x 86400
3126 */
3127 Tdiff = ( MJD + XLAL_MJD_REF - 2443144.5 ) * 86400.;
3128 TCBtoTDB = 1.550506e-8 * Tdiff;
3129
3130 /* convert from TDB to GPS */
3131 GPS = XLALTDBMJDtoGPS( MJD );
3132
3133 /* add extra factor as the MJD was really in TCB not TDB) */
3134 GPS -= TCBtoTDB;
3135
3136 return GPS;
3137}
int j
ProcessParamsTable * ptr
int k
#define c
void PulsarSetParam(PulsarParameters *pars, const CHAR *name, const void *value)
Set the value of a parameter in the PulsarParameters structure.
const REAL8Vector * PulsarGetREAL8VectorParam(const PulsarParameters *pars, const CHAR *name)
Return a REAL8Vector parameter.
static int PulsarHashElemCmp(const void *elem1, const void *elem2)
static PulsarParam * PulsarGetParamItemSlow(const PulsarParameters *pars, const CHAR *name)
Get a pointer to a parameter of a given name from a PulsarParameters structure.
static void del_elem(void *elem)
static PulsarParam * PulsarGetParamItem(const PulsarParameters *pars, const CHAR *name)
Get a pointer to a parameter of a given name from a PulsarParameters structure.
#define DAYSTOSECS
void PulsarSetREAL8ParamErr(PulsarParameters *pars, const CHAR *name, REAL8 value, UINT4 fitFlag)
Set the error value for a REAL8 parameter.
void PulsarAddREAL8Param(PulsarParameters *pars, const CHAR *name, REAL8 value)
Add a REAL8 parameter to the PulsarParameters structure.
void PulsarCopyParams(PulsarParameters *origin, PulsarParameters *target)
Function to copy a PulsarParameters structure.
const REAL8Vector * PulsarGetREAL8VectorParamErr(const PulsarParameters *pars, const CHAR *name)
Return a REAL8Vector parameter error value.
REAL8 PulsarGetREAL8VectorParamErrIndividual(const PulsarParameters *pars, const CHAR *name)
Return an individual REAL8 value from a REAL8Vector parameter.
REAL8 PulsarGetREAL8ParamErr(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter error value.
REAL8 PulsarGetREAL8ParamOrZero(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter if it exists, otherwise return zero.
static const CHAR a2A[256]
Array for conversion from lowercase to uppercase.
#define DEFINE_CONV_FACTOR_FUNCTION(name, convfactor, type)
ParConversion
static void strtoupper(CHAR *s)
Convert string to uppercase.
@ CONVSTRING
@ CONVINT
@ CONVDMS
@ CONVFLOAT
@ CONVMJD
@ CONVHMS
@ CONVBINUNITS
int PulsarCheckParam(const PulsarParameters *pars, const CHAR *name)
Check for the existence of the parameter name in the PulsarParameters structure.
void PulsarSetREAL8VectorParamErr(PulsarParameters *pars, const CHAR *name, const REAL8Vector *value, const UINT4 *fitFlag)
Set the error values for a REAL8Vector parameter.
REAL8 XLALTCBMJDtoGPS(REAL8 MJD)
If you have an MJD arrival time on the Earth then this will convert it to the equivalent GPS time in ...
void * PulsarGetParam(const PulsarParameters *pars, const CHAR *name)
Get the required parameter value from the PulsarParameters structure.
PulsarParameters * XLALReadTEMPOParFile(const CHAR *pulsarAndPath)
Read in the parameters from a TEMPO(2) parameter file into a PulsarParameters structure.
void PulsarClearParams(PulsarParameters *pars)
Free all the parameters from a PulsarParameters structure.
void PulsarSetParamErr(PulsarParameters *pars, const CHAR *name, void *value, const UINT4 *fitFlag, UINT4 len)
Set the value of the error of a parameter in the PulsarParameters structure.
LALStringVector * XLALReadTEMPOCorFile(REAL8Array *cormat, CHAR *corfile)
This function will read in a TEMPO-style parameter correlation matrix.
static UINT8 PulsarHash(const void *elem)
void PrintPulsarParameters(BinaryPulsarParams params)
function to print out all the pulsar parameters read in from a par file
static INT4 ParseParLine(PulsarParameters *par, const CHAR *name, FILE *fp)
Parse a single line from a pulsar parameter file.
void PulsarAddParam(PulsarParameters *pars, const CHAR *name, void *value, PulsarParamType type)
Add a parameter and value to the PulsarParameters structure.
REAL8 PulsarGetREAL8Param(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter.
void PulsarRemoveParam(PulsarParameters *pars, const CHAR *name)
Remove a given parameter from a PulsarParameters structure.
REAL8 XLALTDBMJDtoGPS(REAL8 MJD)
If you have an MJD arrival time on the Earth then this will convert it to the equivalent GPS time in ...
UINT4 PulsarGetUINT4Param(const PulsarParameters *pars, const CHAR *name)
Return a UINT4 parameter.
const CHAR * PulsarGetStringParam(const PulsarParameters *pars, const CHAR *name)
Return a string parameter.
static void * new_elem(const char *name, PulsarParam *itemPtr)
REAL8 XLALTTMJDtoGPS(REAL8 MJD)
This function converts a MJD format time corrected to Terrestrial Time (TT) into an equivalent GPS ti...
void PulsarFreeParams(PulsarParameters *pars)
Function to free memory from pulsar parameters.
void PulsarAddStringParam(PulsarParameters *pars, const CHAR *name, const CHAR *value)
Add a string parameter to the PulsarParameters structure.
size_t PulsarTypeSize[5]
#define NUM_PARS
void PulsarAddREAL8VectorParam(PulsarParameters *pars, const CHAR *name, const REAL8Vector *value)
Add a REAL8Vector parameter to the PulsarParameters structure.
void * PulsarGetParamErr(const PulsarParameters *pars, const CHAR *name)
Get the required parameter error value from the PulsarParameters structure.
REAL8 PulsarGetREAL8VectorParamIndividual(const PulsarParameters *pars, const CHAR *name)
Return an individual REAL8 value from a REAL8Vector parameter.
ParConversion pc[NUM_PARS]
Initialise conversion structure with most allowed TEMPO2 parameter names and conversion functions (co...
const UINT4 * PulsarGetParamFitFlag(const PulsarParameters *pars, const CHAR *name)
Get the fit flag array for a given parameter from the PulsarParameters structure.
const UINT4Vector * PulsarGetParamFitFlagAsVector(const PulsarParameters *pars, const CHAR *name)
Get the fit flag array for a given parameter from the PulsarParameters structure.
void XLALReadTEMPOParFileOrig(BinaryPulsarParams *output, CHAR *pulsarAndPath)
function to read in a TEMPO parameter file
PulsarParamType PulsarGetParamType(const PulsarParameters *pars, const char *name)
Get the required parameter's type.
UINT4 PulsarGetUINT4ParamOrZero(const PulsarParameters *pars, const CHAR *name)
Return a UINT4 parameter if it exists, otherwise return zero.
void PulsarAddUINT4Param(PulsarParameters *pars, const CHAR *name, UINT4 value)
Add a UINT4 parameter to the PulsarParameters structure.
void ParConvKpcToMetres(const CHAR *in, void *out)
Convert the input string from kiloparsecs to metres.
void ParConvToString(const CHAR *in, void *out)
Copy the input string into the output pointer.
void ParConvDegsToRads(const CHAR *in, void *out)
Convert the input string from degrees to radians.
void ParConvInvArcsecsToInvRads(const CHAR *in, void *out)
Convert the input string from 1/acrseconds to 1/radians.
void ParConvDegPerYrToRadPerSec(const CHAR *in, void *out)
Convert the input string from degrees per year to radians per second.
void ParConvSecsToRads(const CHAR *in, void *out)
Convert the input string from seconds to radians.
void ParConvBinaryUnits(const CHAR *in, void *out)
Convert the binary system parameter from a string to a double, but make the check (as performed by TE...
#define GPS_TDT
#define LALPULSAR_TEMPO2_MSUN_SI
void ParConvDaysToSecs(const CHAR *in, void *out)
Convert the input string from days to seconds.
void ParConvSolarMassToKg(const CHAR *in, void *out)
Convert the input string from solar masses to kilograms.
PulsarParamType
An enumerated type for denoting the type of a variable.
@ PULSARTYPE_REAL8Vector_t
@ PULSARTYPE_UINT4_t
@ PULSARTYPE_string_t
@ PULSARTYPE_REAL8_t
void ParConvMicrosecToSec(const CHAR *in, void *out)
Convert an input string from microseconds into seconds.
void ParConvMasPerYrToRadPerSec(const CHAR *in, void *out)
Convert the input string from milliarcsecs per year to radians per second.
void ParConvMasToRads(const CHAR *in, void *out)
Convert the input string from milliarcsecs to radians.
void ParConvToInt(const CHAR *in, void *out)
Convert the input string into a unsigned integer number.
void ParConvMJDToGPS(const CHAR *in, void *out)
Convert the input string from a TT MJD value into a GPS time.
void ParConvRAToRads(const CHAR *in, void *out)
Convert a right ascension input string in the format "hh:mm:ss.s" into radians.
void ParConvToFloat(const CHAR *in, void *out)
Conversion functions from units used in TEMPO parameter files into SI units.
#define GPS0MJD
void ParConvDecToRads(const CHAR *in, void *out)
Convert a declination input string in the format "dd:mm:ss.s" into radians.
#define PULSAR_PARNAME_MAX
void ParConvArcsecsToRads(const CHAR *in, void *out)
Convert the input string from arcseconds to radians.
const char * name
Definition: SearchTiming.c:93
#define fscanf
#define fprintf
double e
REAL8Array * XLALResizeREAL8Array(REAL8Array *, UINT4Vector *)
#define XLAL_MJD_REF
#define XLAL_EPOCH_J2000_0_JD
#define LAL_PI_180
#define LAL_TWOPI
uint64_t UINT8
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
UINT8 XLALCityHash64(const char *buf, size_t len)
int XLALHashTblFind(const LALHashTbl *ht, const void *x, const void **y)
int XLALHashTblAdd(LALHashTbl *ht, void *x)
int XLALHashTblRemove(LALHashTbl *ht, const void *x)
LALHashTbl * XLALHashTblCreate(LALHashTblDtorFcn dtor, LALHashTblHashFcn hash, LALHashTblCmpFcn cmp)
void XLALHashTblDestroy(LALHashTbl *ht)
void * XLALMalloc(size_t n)
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
char char * XLALStringDuplicate(const char *s)
int XLALStringCaseCompare(const char *s1, const char *s2)
size_t XLALStringCopy(char *dst, const char *src, size_t size)
int char * XLALStringAppend(char *s, const char *append)
void XLALDestroyStringVector(LALStringVector *vect)
LALStringVector * XLALAppendString2Vector(LALStringVector *vect, const CHAR *string)
int XLALTranslateHMStoRAD(REAL8 *radians, const CHAR *hms)
int XLALTranslateDMStoRAD(REAL8 *radians, const CHAR *dms)
LIGOTimeGPS * XLALTranslateMJDTTtoGPS(LIGOTimeGPS *gps, INT4 mjdDays, REAL8 mjdFracDays)
void XLALDestroyUINT4Vector(UINT4Vector *vector)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
UINT4Vector * XLALCreateUINT4Vector(UINT4 length)
#define XLAL_ERROR_VOID(...)
#define XLAL_ERROR_REAL8(...)
#define XLAL_ERROR_NULL(...)
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
#define XLAL_PRINT_WARNING(...)
#define XLAL_CHECK_REAL8(assertion,...)
#define XLAL_PRINT_ERROR(...)
#define XLAL_PRINT_DEPRECATION_WARNING(replacement)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EIO
XLAL_EINVAL
XLAL_EFAILED
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
T
out
A structure to contain all pulsar parameters and associated errors.
The PulsarParam list node structure.
void * value
Parameter value.
struct tagPulsarParam * next
void * err
Parameter error/uncertainty.
UINT4Vector * fitFlag
Set to 1 if the parameter has been fit in the par file.
PulsarParamType type
Parameter type e.g.
The PulsarParameters structure to contain a set of pulsar parameters.
PulsarParam * head
A linked list of PulsarParam structures.
LALHashTbl * hash_table
Hash table of parameters.
INT4 nparams
The total number of parameters in the structure.
REAL8 * data
REAL8 * data
UINT4 * data
LALInferenceVariableItem * itemPtr
const char * name
double ra
double dec