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
SFTnaming.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010, 2014, 2016, 2022 Karl Wette
3 * Copyright (C) 2010 Chris Messenger
4 * Copyright (C) 2004, 2005 Reinhard Prix, Bernd Machenschalk, Alicia Sintes
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with with program; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22/*---------- includes ----------*/
23
24#define _XOPEN_SOURCE // for isascii()
25
26#include <ctype.h>
27
28#include "SFTinternal.h"
29
30/*---------- macros ----------*/
31
32#define LAST_ELEMENT(buf) ( (buf)[XLAL_NUM_ELEM(buf) - 1] )
33
34#define STRCPYCHK(name, dest, src) do { \
35 const char *const STRCPYCHK_p = (src); \
36 XLAL_CHECK( strlen(STRCPYCHK_p) < sizeof(dest), XLAL_ESIZE, "%s '%s' does not fit in a buffer of size %zu", name, STRCPYCHK_p, sizeof(dest) ); \
37 strncpy((dest), STRCPYCHK_p, sizeof(dest)); \
38 } while(0)
39
40/*---------- constants ----------*/
41
42/** SFT window specification; see \cite SFT-spec */
43static const struct {
44 const char *window_type;
45 const char *short_name;
48} windowspec_table[] = {
49 /* zero-parameter windows */
50 { .window_type = "unknown", .short_name = "UNKN", .B = 0 },
51 { .window_type = "rectangular", .short_name = "RECT", .B = 1 },
52 { .window_type = "hann", .short_name = "HANN", .B = 2 },
53 /* one-parameter windows */
54 { .window_type = "tukey", .short_name = "TKEY", .A = 1 },
55};
56
57/*---------- internal variables ----------*/
58
59/* Registry for special CW detectors which are assigned prefixes "[XYZ][0123456789]" */
61
62/*========== function definitions ==========*/
63
64/// \addtogroup SFTfileIO_h
65/// @{
66
67/**
68 * Register a special detector for use with CW codes.
69 *
70 * The special detector must have a 2-character prefix of the form "[XYZ][0123456789]".
71 */
72int
74{
75
76 // check input
77 XLAL_CHECK( specialDetector != NULL, XLAL_EFAULT );
78 XLAL_CHECK( specialDetector->frDetector.prefix[2] == 0, XLAL_EINVAL );
79
80 // store special CW detector in registry indexed by prefix
81
82 const int index_1 = ( ( int ) specialDetector->frDetector.prefix[0] ) - ( ( int ) 'X' );
83 XLAL_CHECK( 0 <= index_1 && index_1 < 3, XLAL_EINVAL,
84 "Special CW detector prefix '%s' must start with one of [XYZ]", specialDetector->frDetector.prefix );
85
86 const int index_2 = ( ( int ) specialDetector->frDetector.prefix[1] ) - ( ( int ) '0' );
87 XLAL_CHECK( 0 <= index_1 && index_1 < 9, XLAL_EINVAL,
88 "Special CW detector prefix '%s' must end with one of [0123456789]", specialDetector->frDetector.prefix );
89
90 const int index = 10 * index_1 + index_2;
91
92 SpecialDetectorRegistry[index] = *specialDetector;
93
94 return XLAL_SUCCESS;
95
96}
97
98/**
99 * Parses valid CW detector names and prefixes. 'name' input can be either a valid detector name or prefix
100 *
101 * \return XLAL_SUCCESS if 'name' is a valid detector name/prefix, an XLAL error code on failure
102 *
103 * If passed a non-NULL pointer 'prefix', will be set to the Allocated prefix string (2 characters+0)
104 * for valid detectors, NULL otherwise.
105 *
106 * If passed a non-NULL pointer 'lalCachedIndex', will set to index >= 0 into the
107 * lalCachedDetectors[] array if found there, or -1 if it's one of the "CW special" detectors
108 *
109 * \note This should be the *only* function defining valid CW detector names and prefixes
110 *
111 * \note 'prefix' is allocated here and needs to be free'ed by caller!
112 *
113 * \note Unless 'exactMatch' is true, if first two characters of 'name' match a valid detector prefix,
114 * that is accepted, which allows passing longer strings beginning with a detector prefix ('H1:blabla')
115 * without extra hassle
116 */
117int
118XLALFindCWDetector( CHAR **prefix, INT4 *lalCachedIndex, const CHAR *name, const BOOLEAN exactMatch )
119{
120 XLAL_CHECK( name != NULL, XLAL_EINVAL );
121 XLAL_CHECK( strlen( name ) >= 2, XLAL_EINVAL ); // need at least a full prefix 'letter+number'
122
123 // ----- first check if 'name' corresponds to one of our 'CW special' detectors
124 const UINT4 numSpecialDetectors = sizeof( SpecialDetectorRegistry ) / sizeof( SpecialDetectorRegistry[0] );
125 for ( UINT4 i = 0; i < numSpecialDetectors; i ++ ) {
127 if ( strncmp( prefix_i, name, 2 ) == 0 ) {
128 if ( exactMatch && strcmp( name + strlen( prefix_i ), "" ) != 0 ) {
129 XLAL_ERROR( XLAL_EINVAL, "Trailing garbage '%s' after detector prefix\n", name + strlen( prefix_i ) );
130 }
131 if ( prefix != NULL ) {
132 ( *prefix ) = XLALStringDuplicate( prefix_i );
133 }
134 if ( lalCachedIndex != NULL ) {
135 ( *lalCachedIndex ) = -1;
136 }
137 return XLAL_SUCCESS;
138 }
139 } // for i < numSpecialDetectors
140
141 // ----- if not found, go through list of 'official' cached lalsuite detectors
142 const UINT4 numLALDetectors = sizeof( lalCachedDetectors ) / sizeof( lalCachedDetectors[0] );
143 for ( UINT4 i = 0; i < numLALDetectors; i ++ ) {
144 const CHAR *prefix_i = lalCachedDetectors[i].frDetector.prefix;
145 const CHAR *name_i = lalCachedDetectors[i].frDetector.name;
146 if ( strncmp( prefix_i, name, 2 ) == 0 ) {
147 if ( exactMatch && strcmp( name + strlen( prefix_i ), "" ) != 0 ) {
148 XLAL_ERROR( XLAL_EINVAL, "Trailing garbage '%s' after detector prefix\n", name + strlen( prefix_i ) );
149 }
150 if ( prefix != NULL ) {
151 ( *prefix ) = XLALStringDuplicate( prefix_i );
152 }
153 if ( lalCachedIndex != NULL ) {
154 ( *lalCachedIndex ) = i;
155 }
156 return XLAL_SUCCESS;
157 }
158 if ( strncmp( name, name_i, strlen( name_i ) ) == 0 ) {
159 if ( exactMatch && strcmp( name + strlen( name_i ), "" ) != 0 ) {
160 XLAL_ERROR( XLAL_EINVAL, "Trailing garbage '%s' after detector prefix\n", name + strlen( name_i ) );
161 }
162 if ( prefix != NULL ) {
163 ( *prefix ) = XLALStringDuplicate( prefix_i );
164 }
165 if ( lalCachedIndex != NULL ) {
166 ( *lalCachedIndex ) = i;
167 }
168 return XLAL_SUCCESS;
169 }
170
171 } // for i < numLALDetectors
172
173 if ( prefix != NULL ) {
174 ( *prefix ) = NULL;
175 }
176 XLAL_ERROR( XLAL_EINVAL, "Unknown detector name '%s'\n", name );
177
178} // XLALFindCWDetector()
179
180
181/**
182 * Determine if 'name' is a valid detector name or prefix
183 *
184 * \return TRUE if 'name' is a valid detector name/prefix, FALSE otherwise
185 * (or if an error is encountered; this function does not raise XLAL errors)
186 */
189{
190 int UNUSED errnum;
191 int retn;
192 XLAL_TRY_SILENT( retn = XLALFindCWDetector( NULL, NULL, name, 1 ), errnum );
193 return ( retn == XLAL_SUCCESS );
194}
195
196
197/**
198 * Find the valid CW detector prefix. 'name' input can be either a valid detector name or prefix
199 *
200 * \note The returned string is allocated here!
201 */
202CHAR *
204{
205 XLAL_CHECK_NULL( name != NULL, XLAL_EINVAL );
206
207 CHAR *prefix = NULL;
208 XLAL_CHECK_NULL( XLALFindCWDetector( &prefix, NULL, name, 0 ) == XLAL_SUCCESS, XLAL_EINVAL, "Unknown detector name '%s'\n", name );
209
210 return prefix;
211} // XLALGetChannelPrefix()
212
213
214/**
215 * Find the site geometry-information 'LALDetector' for given a detector name (or prefix).
216 */
217const LALDetector *
219{
220 XLAL_CHECK_NULL( name != NULL, XLAL_EINVAL );
221
222 const INT4 numLALDetectors = sizeof( lalCachedDetectors ) / sizeof( lalCachedDetectors[0] );
223
224 // first turn the free-form 'detector-name' into a well-defined channel-prefix, and find lalCachedDetector[] index
225 INT4 lalCachedIndex = -1;
226 CHAR *prefix;
228
229 const LALDetector *site;
230
231 if ( strchr( "XYZ", prefix[0] ) != NULL ) { // special CW detector
232 const int index_1 = ( ( int ) prefix[0] ) - ( ( int ) 'X' );
233 XLAL_CHECK_NULL( 0 <= index_1 && index_1 < 3, XLAL_EFAILED );
234
235 const int index_2 = ( ( int ) prefix[1] ) - ( ( int ) '0' );
236 XLAL_CHECK_NULL( 0 <= index_1 && index_1 < 9, XLAL_EINVAL,
237 "Special CW detector prefix '%s' must be of the form [XYZ][0123456789]", prefix );
238
239 const int index = 10 * index_1 + index_2;
240
242 } else { // official LALSuite detector
243 XLAL_CHECK_NULL( ( lalCachedIndex >= 0 ) && ( lalCachedIndex < numLALDetectors ), XLAL_EFAILED, "Internal inconsistency found (for 'name=%s, prefix=%s')\n", name, prefix );
244 site = &lalCachedDetectors[lalCachedIndex];
245 }
246
247 XLALFree( prefix );
248
249 return site;
250
251} // XLALGetSiteInfo()
252
253
254/**
255 * Convenience function for filling out the string fields in a SFTFilenameSpec
256 */
258 SFTFilenameSpec *spec, /**< [out] SFT filename specification */
259 const CHAR *path, /**< [in] Path to the SFT file */
260 const CHAR *extn, /**< [in] Extension of the SFT file; defaults to 'sft' */
261 const CHAR *detector, /**< [in] 2-character detector prefix (e.g. 'H1', 'L1', 'V1') */
262 const CHAR *window_type, /**< [in] window function applied to SFT */
263 const CHAR *privMisc, /**< [in] For private SFTs: miscellaneous description field */
264 const CHAR *pubObsKind, /**< [in] For public SFTs: kind of data ('RUN', 'AUX', 'SIM', 'DEV') */
265 const CHAR *pubChannel /**< [in] For public SFTs: channel name of data used to make SFTs */
266)
267{
268
269 // check input
270 XLAL_CHECK( spec != NULL, XLAL_EFAULT );
271
272 // fill string fields
273 if ( path != NULL ) {
274 STRCPYCHK( "'spec->path'", spec->path, path );
275 }
276 if ( extn != NULL ) {
277 STRCPYCHK( "'spec->extn'", spec->extn, extn );
278 }
279 if ( detector != NULL ) {
280 STRCPYCHK( "'spec->detector'", spec->detector, detector );
281 }
282 if ( window_type != NULL ) {
283 STRCPYCHK( "'spec->window_type'", spec->window_type, window_type );
284 }
285 if ( privMisc != NULL ) {
286 STRCPYCHK( "'spec->privMisc'", spec->privMisc, privMisc );
287 }
288 if ( pubObsKind != NULL ) {
289 STRCPYCHK( "'spec->pubObsKind'", spec->pubObsKind, pubObsKind );
290 }
291 if ( pubChannel != NULL ) {
292 STRCPYCHK( "'spec->pubChannel'", spec->pubChannel, pubChannel );
293 }
294
295 return XLAL_SUCCESS;
296
297}
298
299/**
300 * Build an SFT file name from the given specification
301 */
303 const SFTFilenameSpec *spec /**< [in] SFT filename specification */
304)
305{
306
307 // check input
308 XLAL_CHECK_NULL( spec != NULL, XLAL_EFAULT );
309
310 // check specification
312 "'path' is not a null-terminated string" );
314 "'extn' is not a null-terminated string" );
316 "'numSFTs' must be strictly positive" );
318 "'detector' is not a null-terminated string" );
320 "'%s' is not a valid 2-character detector prefix", spec->detector );
322 "'SFTtimebase' must be strictly positive" );
324 "'window_type' is not a null-terminated string" );
326 "'privMisc' is not a null-terminated string" );
327 XLAL_CHECK_NULL( spec->pubObsRun == 0 || strlen( spec->privMisc ) == 0, XLAL_EINVAL,
328 "Public SFTs (with pubObsRun=%u) cannot include a private description '%s'",
329 spec->pubObsRun, spec->privMisc );
331 "Private description '%s' contains disallowed characters", spec->privMisc );
333 "'pubObsKind' is not a null-terminated string" );
334 XLAL_CHECK_NULL( spec->pubObsRun == 0 ||
335 strcmp( spec->pubObsKind, "RUN" ) == 0 ||
336 strcmp( spec->pubObsKind, "AUX" ) == 0 ||
337 strcmp( spec->pubObsKind, "SIM" ) == 0 ||
338 strcmp( spec->pubObsKind, "DEV" ) == 0, XLAL_EINVAL,
339 "'pubObsKind=%s' must be one of 'RUN'|'AUX'|'SIM'|'DEV'", spec->pubObsKind );
340 XLAL_CHECK_NULL( spec->pubObsRun == 0 || spec->pubRevision > 0, XLAL_EINVAL,
341 "Public SFTs (with pubObsRun=%u) must include a positive revision 'pubRevision'",
342 spec->pubObsRun );
344 "'pubChannel' is not a null-terminated string" );
345 XLAL_CHECK_NULL( spec->pubObsRun == 0 || strlen( spec->pubChannel ) > 0, XLAL_EINVAL,
346 "Public SFTs (with pubObsRun=%u) must include a channel name 'pubChannel'",
347 spec->pubObsRun );
348 XLAL_CHECK_NULL( spec->pubObsRun == 0 || strlen( spec->window_type ) > 0, XLAL_EINVAL,
349 "Public SFTs (with pubObsRun=%u) must include a window function 'window_type'",
350 spec->pubObsRun );
351 XLAL_CHECK_NULL( spec->nbFirstBinFreq == 0 || spec->nbBinWidthFreq > 0 || spec->nbBinWidthRem > 0, XLAL_EINVAL,
352 "Narrow-band SFTs (with nbFirstBinFreq>0) must have nbBinWidthFreq>0 or nbBinWidthRem>0" );
354 "'gpsStart' must be strictly positive" );
356 "'SFTspan' must be strictly positive" );
357
358 char windowspec_str[9];
359 if ( spec->pubObsRun > 0 ) {
360 XLAL_CHECK_NULL( build_sft_windowspec( NULL, &windowspec_str, spec->window_type, spec->window_param ) == XLAL_SUCCESS, XLAL_EINVAL,
361 "'%s' is not a valid SFT window function", spec->window_type );
362 }
363
364 // SFT filename string
365 char *fname = NULL;
366
367 // append SFT path, if any
368 if ( strlen( spec->path ) > 0 ) {
369 fname = XLALStringAppendFmt(
370 fname,
371 "%s/",
372 spec->path
373 );
374 XLAL_CHECK_NULL( fname != NULL, XLAL_EFUNC );
375 }
376
377 // append SFT filename fields <S>, <D1>, <D2>, <D3> (see \cite SFT-spec)
378 fname = XLALStringAppendFmt(
379 fname,
380 "%c-%d_%s_%dSFT",
381 spec->detector[0],
382 spec->numSFTs,
383 spec->detector,
384 spec->SFTtimebase
385 );
386 XLAL_CHECK_NULL( fname != NULL, XLAL_EFUNC );
387
388 // append optional SFT filename field <D4> (see \cite SFT-spec)
389 if ( spec->pubObsRun == 0 ) { // private SFT
390
391 if ( strlen( spec->privMisc ) > 0 ) { // miscellaneous description
392
393 // append private SFT miscellaneous description
394 fname = XLALStringAppendFmt(
395 fname,
396 "_%s",
397 spec->privMisc
398 );
399 XLAL_CHECK_NULL( fname != NULL, XLAL_EFUNC );
400
401 }
402
403 } else { // public SFT
404
405 // strip prefix and disallowed characters from channel name
406 char pubChannel[XLAL_NUM_ELEM( spec->pubChannel )];
407 strcpy( pubChannel, spec->pubChannel );
408 char *pubChannel_no_prefix = strchr( pubChannel, ':' );
409 if ( !pubChannel_no_prefix ) {
410 pubChannel_no_prefix = pubChannel;
411 }
412 XLAL_CHECK_NULL( XLALStringKeepChars( pubChannel_no_prefix, isascii ) != NULL, XLAL_EFUNC );
413 XLAL_CHECK_NULL( XLALStringKeepChars( pubChannel_no_prefix, isalnum ) != NULL, XLAL_EFUNC );
414
415 // append public SFT descriptor
416 fname = XLALStringAppendFmt(
417 fname,
418 "_O%d%s+R%d+C%s+W%s",
419 spec->pubObsRun,
420 spec->pubObsKind,
421 spec->pubRevision,
422 pubChannel_no_prefix,
423 windowspec_str
424 );
425 XLAL_CHECK_NULL( fname != NULL, XLAL_EFUNC );
426
427 }
428
429 // append optional SFT filename field <D5> (see \cite SFT-spec)
430 if ( spec->nbFirstBinFreq > 0 ) { // narrow-band SFTs
431
432 // append narrow-band SFT descriptor
433 fname = XLALStringAppendFmt(
434 fname,
435 "_NBF%04dHz%dW%04dHz%d",
436 spec->nbFirstBinFreq,
437 spec->nbFirstBinRem,
438 spec->nbBinWidthFreq,
439 spec->nbBinWidthRem
440 );
441 XLAL_CHECK_NULL( fname != NULL, XLAL_EFUNC );
442
443 }
444
445 // append optional SFT filename fields <G>, <T> (see \cite SFT-spec), and extension
446 fname = XLALStringAppendFmt(
447 fname,
448 "-%09d-%d.%s",
449 spec->gpsStart,
450 spec->SFTspan,
451 strlen( spec->extn ) > 0 ? spec->extn : "sft"
452 );
453 XLAL_CHECK_NULL( fname != NULL, XLAL_EFUNC );
454
455 return fname;
456
457} // XLALBuildSFTFilenameFromSpec(()
458
459
460/**
461 * Parse a SFT file path and return its specification
462 */
464 SFTFilenameSpec *spec, /**< [out] SFT filename specification */
465 const char *SFTpath /**< [in] SFT file path */
466)
467{
468
469 // check input
470 XLAL_CHECK( spec != NULL, XLAL_EFAULT );
471 XLAL_CHECK( SFTpath != NULL, XLAL_EFAULT );
472 XLALPrintInfo( "%s(): SFTpath='%s'\n",
473 __func__, SFTpath );
474
475 // clear specification
476 memset( spec, 0, sizeof( *spec ) );
477
478 // local copy of path
479 char localSFTpath[8192];
480 STRCPYCHK( "SFT filename and path", localSFTpath, SFTpath );
481
482 // split SFT filename
483 char *SFTfname = strrchr( localSFTpath, '/' );
484 if ( !SFTfname ) {
485 SFTfname = localSFTpath;
486 } else {
487 *SFTfname++ = '\0';
488 STRCPYCHK( "SFT path", spec->path, localSFTpath );
489 }
490 XLALPrintInfo( "%s(): spec->path='%s' SFTfname='%s'\n",
491 __func__, spec->path, SFTfname );
492
493 // split SFT filename <S>, <D>, <G>, <T> fields (see \cite SFT-spec)
494 char *S, *D, *G, *T;
495 {
496 char *p = SFTfname;
497 S = XLALStringToken( &p, "-", 1 );
498 XLAL_CHECK( S != NULL, XLAL_EINVAL,
499 "SFT file path '%s' contains no <S> field", SFTpath );
500 D = XLALStringToken( &p, "-", 1 );
501 XLAL_CHECK( D != NULL, XLAL_EINVAL,
502 "SFT file path '%s' contains no <D> field", SFTpath );
503 G = XLALStringToken( &p, "-", 1 );
504 XLAL_CHECK( G != NULL, XLAL_EINVAL,
505 "SFT file path '%s' contains no <G> field", SFTpath );
506 T = XLALStringToken( &p, ".", 1 );
507 XLAL_CHECK( T != NULL, XLAL_EINVAL,
508 "SFT file path '%s' contains no <T> field", SFTpath );
509 XLALPrintInfo( "%s(): S='%s' D='%s' G='%s' T='%s' extn='%s'\n",
510 __func__, S, D, G, T, p );
511 STRCPYCHK( "SFT extension", spec->extn, p );
512 }
513
514 // split SFT filename <D> field into <D1>, <D2>, <D3>[, <D4>, <D5>] fields (see \cite SFT-spec)
515 char *D1, *D2, *D3, *D4, *D5;
516 {
517 char *p = D;
518 D1 = XLALStringToken( &p, "_", 1 );
519 XLAL_CHECK( D1 != NULL, XLAL_EINVAL,
520 "SFT file path '%s' contains no <D1> field", SFTpath );
521 D2 = XLALStringToken( &p, "_", 1 );
522 XLAL_CHECK( D2 != NULL, XLAL_EINVAL,
523 "SFT file path '%s' contains no <D2> field", SFTpath );
524 D3 = XLALStringToken( &p, "_", 1 );
525 XLAL_CHECK( D3 != NULL, XLAL_EINVAL,
526 "SFT file path '%s' contains no <D3> field", SFTpath );
527 if ( p == NULL ) { // no <D4>, <D5> fields
528 D4 = NULL;
529 D5 = NULL;
530 } else if ( strncmp( p, "NBF", 3 ) == 0 ) { // old style SFT name: <D5> appears before <D4>
531 D5 = XLALStringToken( &p, "_", 1 );
532 D4 = p;
533 // ensure <D4> is a valid description field
534 XLAL_CHECK( XLALStringKeepChars( D4, isascii ) != NULL, XLAL_EFUNC );
535 XLAL_CHECK( XLALStringKeepChars( D4, isalnum ) != NULL, XLAL_EFUNC );
536 } else {
537 int underscores = 0;
538 for ( char *q = p; *q != '\0'; ++q ) {
539 if ( *q == '_' ) {
540 ++underscores;
541 }
542 }
543 if ( underscores > 1 ) { // old style SFT name: <D4> includes underscores
544 D5 = NULL;
545 D4 = p;
546 // ensure <D4> is a valid description field
547 XLAL_CHECK( XLALStringKeepChars( D4, isascii ) != NULL, XLAL_EFUNC );
548 XLAL_CHECK( XLALStringKeepChars( D4, isalnum ) != NULL, XLAL_EFUNC );
549 } else { // compliant SFT name
550 D4 = XLALStringToken( &p, "_", 1 );
551 D5 = XLALStringToken( &p, "_", 1 );
552 }
553 }
554 XLALPrintInfo( "%s(): D1='%s' D2='%s' D3='%s' D4='%s' D5='%s' p='%s'\n",
555 __func__, D1, D2, D3, D4, D5, p );
556 }
557
558 // parse required SFT filename fields <S>, <D1>, <D2>, <D3>, <G>, <T>
559 XLAL_CHECK( sscanf( D1, "%d", &spec->numSFTs ) == 1, XLAL_EFUNC,
560 "Could not parse 'numSFTs' from field D1='%s'", D1 );
561 XLAL_CHECK( spec->numSFTs > 0, XLAL_EINVAL,
562 "'numSFTs' must be strictly positive" );
563 STRCPYCHK( "SFT detector prefix", spec->detector, D2 );
565 "'%s' is not a valid 2-character detector prefix", spec->detector );
566 XLAL_CHECK( S[0] == spec->detector[0] && S[1] == '\0', XLAL_EINVAL,
567 "Inconsistent site/detector fields S='%s' and D2='%s'", S, D2 );
568 XLAL_CHECK( sscanf( D3, "%dSFT", &spec->SFTtimebase ) == 1, XLAL_EFUNC,
569 "Could not parse 'SFTtimebase' from field D3='%s'", D3 );
571 "'SFTtimebase' must be strictly positive" );
572 XLAL_CHECK( sscanf( G, "%d", &spec->gpsStart ) == 1, XLAL_EFUNC,
573 "Could not parse 'gpsStart' from field G='%s'", G );
574 XLAL_CHECK( spec->gpsStart > 0, XLAL_EINVAL,
575 "'gpsStart' must be strictly positive" );
576 XLAL_CHECK( sscanf( T, "%d", &spec->SFTspan ) == 1, XLAL_EFUNC,
577 "Could not parse 'SFTspan' from field T='%s'", T );
578 XLAL_CHECK( spec->SFTspan > 0, XLAL_EINVAL,
579 "'SFTspan' must be strictly positive" );
580
581 // parse optional SFT filename field <D4>
582 if ( D4 != NULL ) {
583 if ( strchr( D4, '+' ) ) { // public SFT
584 char *D41, *D42, *D43, *D44;
585 char *p = D4;
586 D41 = XLALStringToken( &p, "+", 1 );
587 XLAL_CHECK( D41 != NULL, XLAL_EINVAL,
588 "SFT file path '%s' contains no <D41> field", SFTpath );
589 D42 = XLALStringToken( &p, "+", 1 );
590 XLAL_CHECK( D42 != NULL, XLAL_EINVAL,
591 "SFT file path '%s' contains no <D42> field", SFTpath );
592 D43 = XLALStringToken( &p, "+", 1 );
593 XLAL_CHECK( D43 != NULL, XLAL_EINVAL,
594 "SFT file path '%s' contains no <D43> field", SFTpath );
595 D44 = XLALStringToken( &p, "+", 1 );
596 XLAL_CHECK( D44 != NULL, XLAL_EINVAL,
597 "SFT file path '%s' contains no <D44> field", SFTpath );
598 XLALPrintInfo( "%s(): D41='%s' D42='%s' D43='%s' D44='%s' p='%s'\n",
599 __func__, D41, D42, D43, D44, p );
600 char buf[8192];
601 XLAL_CHECK( sscanf( D41, "O%d%255s", &spec->pubObsRun, buf ) == 2, XLAL_EINVAL,
602 "Could not parse public SFT fields 'pubObsRun' and 'pubObsKind' from field D41='%s'", D41 );
603 STRCPYCHK( "Public SFT field 'pubObsKind'", spec->pubObsKind, buf );
604 XLAL_CHECK( sscanf( D42, "R%d", &spec->pubRevision ) == 1, XLAL_EFUNC,
605 "Could not parse public SFT field 'pubRevision' from field D42='%s'", D42 );
606 XLAL_CHECK( sscanf( D43, "C%255s", buf ) == 1, XLAL_EINVAL,
607 "Could not parse public SFT field 'pubChannel' from field D43='%s'", D43 );
608 STRCPYCHK( "Public SFT field 'pubChannel'", spec->pubChannel, buf );
609 XLAL_CHECK( sscanf( D44, "W%255s", buf ) == 1, XLAL_EINVAL,
610 "Could not parse public SFT fields 'window_type' and 'window_param' from field D44='%s'", D44 );
612 "'%s' does not specify a valid SFT window function", buf );
613 } else { // private SFT
615 "Private description '%s' contains disallowed characters", D4 );
616 STRCPYCHK( "Private SFT miscellaneous description", spec->privMisc, D4 );
617 }
618 }
619
620 // parse optional SFT filename field <D5>
621 if ( D5 != NULL ) { // narrow-band SFTs
622 XLAL_CHECK( sscanf( D5, "NBF%dHz%dW%dHz%d",
623 &spec->nbFirstBinFreq, &spec->nbFirstBinRem,
624 &spec->nbBinWidthFreq, &spec->nbBinWidthRem
625 ) == 4, XLAL_EINVAL,
626 "Could not parse narrow-band SFT field D5='%s'", D5 );
627 }
628
629 return XLAL_SUCCESS;
630
631} // XLALParseSFTFilenameIntoSpec()
632
633
634/**
635 * Check whether given string qualifies as a valid 'description' field of a
636 * FRAME filename (per \cite frame-naming-spec) or SFT filename (per \cite SFT-spec)
637 */
638int
640{
641 XLAL_CHECK( desc != NULL, XLAL_EINVAL );
642
643 size_t len = strlen( desc );
644
645 if ( len == 1 && isupper( desc[0] ) ) {
646 XLAL_ERROR( XLAL_EINVAL, "Single uppercase description reserved for class-1 raw frames!\n" );
647 }
648
649 for ( UINT4 i = 0; i < len; i ++ ) {
650 int c = desc[i];
651 // SFT filenames only allow alphanumeric characters, which is more restrictive than FRAME filenames which also allow [_+#]
652 XLAL_CHECK( isascii( c ) && isalnum( c ), XLAL_EINVAL, "Invalid chacter '%c' found, only ASCII alphanumeric are allowed\n", c );
653 } // for i < len
654
655 return XLAL_SUCCESS;
656
657} // XLALCheckValidDescriptionField()
658
659
660/**
661 * Check whether two SFT windows, each defined by a type name and parameter value, match.
662 *
663 * This builds standardized windowspec numbers out of the inputs and compares those,
664 * ensuring consistent rounding before the comparison.
665 */
666int
668 const CHAR *type1, /**< [in] type name of the first window */
669 const REAL8 param1, /**< [in] parameter value of the first window */
670 const CHAR *type2, /**< [in] type name of the second window */
671 const REAL8 param2 /**< [in] parameter value of the second window */
672)
673{
674
675 UINT2 spec1 = 0;
676 UINT2 spec2 = 0;
677
678 XLAL_CHECK( build_sft_windowspec( &spec1, NULL, type1, param1 ) == XLAL_SUCCESS, XLAL_EINVAL, "Failed to build windowspec from type '%s' and param '%f'", type1, param1 );
679 XLAL_CHECK( build_sft_windowspec( &spec2, NULL, type2, param2 ) == XLAL_SUCCESS, XLAL_EINVAL, "Failed to build windowspec from type '%s' and param '%f'", type2, param2 );
680
681 XLAL_CHECK( spec1 == spec2, XLAL_EINVAL );
682
683 return XLAL_SUCCESS;
684
685} // XLALCompareSFTWindows()
686
687
688/**
689 * Build an SFT 2-byte 'windowspec' or filename field 'windowspec_str' for the window given by 'window_type' and 'window_param'
690 */
691int build_sft_windowspec( UINT2 *windowspec, CHAR( *windowspec_str )[9], const char *window_type, REAL8 window_param )
692{
693
694 // check input
696
697 // default to unknown window
698 if ( windowspec ) {
699 *windowspec = windowspec_table[0].B;
700 }
701 if ( windowspec_str ) {
702 XLAL_CHECK( snprintf( *windowspec_str, sizeof( *windowspec_str ), "%s", windowspec_table[0].short_name ) < ( int ) sizeof( *windowspec_str ), XLAL_ESYS );
703 }
704
705 // lookup windows
706 for ( size_t w = 0; w < XLAL_NUM_ELEM( windowspec_table ); ++w ) {
708
709 // build windowspec and windowspec_str
710 if ( windowspec_table[w].A == 0 ) { /* zero-parameter windows */
711
712 XLAL_CHECK( window_param <= 0, XLAL_EINVAL, "Invalid window_param=%0.10g for SFT window type '%s'", window_param, window_type );
713
714 if ( windowspec ) {
715 *windowspec = windowspec_table[w].B;
716 }
717
718 if ( windowspec_str ) {
719 XLAL_CHECK( snprintf( *windowspec_str, sizeof( *windowspec_str ), "%s", windowspec_table[w].short_name ) < ( int ) sizeof( *windowspec_str ), XLAL_ESYS );
720 }
721
722 } else { /* one-parameter windows */
723
724 REAL8 Breal = window_param * 5000;
725 long B = lrint( Breal );
726 XLAL_CHECK( B == ( ( long ) Breal ), XLAL_ETOL, "SFT window_param=%0.10g cannot be exactly represented by an integer [0,5000]", window_param );
727 XLAL_CHECK( 0 <= B && B <= 5000, XLAL_ERANGE, "SFT window_param=%0.10g is out of range [0.0,1.0] (B=%ld)", window_param, B );
728
729 if ( windowspec ) {
730 *windowspec = windowspec_table[w].A * 5001 + B;
731 }
732
733 if ( windowspec_str ) {
734 XLAL_CHECK( snprintf( *windowspec_str, sizeof( *windowspec_str ), "%s%ld", windowspec_table[w].short_name, B ) < ( int ) sizeof( *windowspec_str ), XLAL_ESYS );
735 }
736
737 }
738
739 break;
740
741 }
742 }
743
744 return XLAL_SUCCESS;
745
746}
747
748
749/**
750 * Parse an SFT 2-byte 'windowspec' into a window name 'window_type' and possible parameter 'window_param'
751 */
752int parse_sft_windowspec( const UINT2 windowspec, const char **window_type, REAL8 *window_param )
753{
754
755 // parse windowspec
756 const UINT2 A = windowspec / 5001;
757 const UINT2 B = windowspec - 5001 * A;
758
759 // lookup windows
760 for ( size_t w = 0; w < XLAL_NUM_ELEM( windowspec_table ); ++w ) {
761 if ( A == windowspec_table[w].A ) {
762
763 // build window_type and window_param
764 if ( A == 0 && B == windowspec_table[w].B ) { /* zero-parameter windows */
765
766 if ( window_type ) {
767 *window_type = windowspec_table[w].window_type;
768 }
769
770 if ( window_param ) {
771 *window_param = 0;
772 }
773
774 return XLAL_SUCCESS;
775
776 } else if ( A > 0 ) { /* one-parameter windows */
777
778 if ( window_type ) {
779 *window_type = windowspec_table[w].window_type;
780 }
781
782 if ( window_param ) {
783 *window_param = ( ( REAL8 ) B ) / 5000;
784 }
785
786 return XLAL_SUCCESS;
787
788 }
789
790 }
791 }
792
793 XLAL_ERROR( XLAL_EINVAL, "Illegal SFT windowspec=%d : windowspecA=%d, windowspecB=%d",
794 windowspec, A, B );
795
796}
797
798
799/**
800 * Parse an SFT filename field 'windowspec_str' into a window name 'window_type' and possible parameter 'window_param'
801 */
802int parse_sft_windowspec_str( const CHAR *windowspec_str, CHAR( *window_type )[32], REAL8 *window_param )
803{
804
805 // check input
806 XLAL_CHECK( windowspec_str != NULL, XLAL_EFAULT );
807
808 // parse windowspec_str
809 char short_name[5];
810 long B = 0;
811 int parsed = sscanf( windowspec_str, "%4s%li", short_name, &B );
812 XLAL_CHECK( 0 < parsed, XLAL_EINVAL, "Could not parse SFT filename field windowspec_str='%s'", windowspec_str );
813 XLAL_CHECK( 0 <= B && B <= 5000, XLAL_ERANGE, "SFT window_param=%0.10g is out of range [0.0,1.0] (B=%ld)", ( ( REAL8 ) B ) / 5000, B );
814
815 // lookup windows
816 for ( size_t w = 0; w < XLAL_NUM_ELEM( windowspec_table ); ++w ) {
817 if ( strcmp( short_name, windowspec_table[w].short_name ) == 0 ) {
818
819 // build window_type
820 if ( window_type ) {
821 XLAL_CHECK( snprintf( *window_type, sizeof( *window_type ), "%s", windowspec_table[w].window_type ) < ( int ) sizeof( *window_type ), XLAL_ESYS );
822 }
823
824 // build window_param
825 if ( window_param ) {
826 if ( windowspec_table[w].A == 0 ) { /* zero-parameter windows */
827 *window_param = 0;
828 } else { /* one-parameter windows */
829 *window_param = ( ( REAL8 ) B ) / 5000;
830 }
831 }
832
833 return XLAL_SUCCESS;
834
835 }
836 }
837
838 XLAL_ERROR( XLAL_EINVAL, "Illegal SFT windowspec_str='%s'", windowspec_str );
839
840}
841
842/// @}
#define __func__
log an I/O error, i.e.
INT4 D2(REAL8 *f, REAL8 dx, INT4 n, REAL8 *d2f)
#define c
#define D(j)
Internal SFT types and functions.
const char * short_name
Definition: SFTnaming.c:45
const char * window_type
Definition: SFTnaming.c:44
#define LAST_ELEMENT(buf)
Definition: SFTnaming.c:32
UINT2 A
Definition: SFTnaming.c:46
#define STRCPYCHK(name, dest, src)
Definition: SFTnaming.c:34
static LALDetector SpecialDetectorRegistry[30]
Definition: SFTnaming.c:60
static const struct @6 windowspec_table[]
SFT window specification; see .
UINT2 B
Definition: SFTnaming.c:47
const char * name
Definition: SearchTiming.c:93
const double w
const LALDetector lalCachedDetectors[LAL_NUM_DETECTORS]
unsigned char BOOLEAN
#define XLAL_NUM_ELEM(x)
double REAL8
uint16_t UINT2
char CHAR
uint32_t UINT4
int32_t INT4
void XLALFree(void *p)
char char * XLALStringDuplicate(const char *s)
int XLALStringCaseCompare(const char *s1, const char *s2)
char * XLALStringKeepChars(char *s, int(*f)(int))
char * XLALStringAppendFmt(char *s, const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(2
char * XLALStringToken(char **s, const char *delim, int empty)
static const INT4 q
int parse_sft_windowspec(const UINT2 windowspec, const char **window_type, REAL8 *window_param)
Parse an SFT 2-byte 'windowspec' into a window name 'window_type' and possible parameter 'window_para...
Definition: SFTnaming.c:752
const LALDetector * XLALGetSiteInfo(const CHAR *name)
Find the site geometry-information 'LALDetector' for given a detector name (or prefix).
Definition: SFTnaming.c:218
int XLALRegisterSpecialCWDetector(const LALDetector *specialDetector)
Register a special detector for use with CW codes.
Definition: SFTnaming.c:73
CHAR * XLALGetChannelPrefix(const CHAR *name)
Find the valid CW detector prefix.
Definition: SFTnaming.c:203
int build_sft_windowspec(UINT2 *windowspec, CHAR(*windowspec_str)[9], const char *window_type, REAL8 window_param)
Build an SFT 2-byte 'windowspec' or filename field 'windowspec_str' for the window given by 'window_t...
Definition: SFTnaming.c:691
int XLALCompareSFTWindows(const CHAR *type1, const REAL8 param1, const CHAR *type2, const REAL8 param2)
Check whether two SFT windows, each defined by a type name and parameter value, match.
Definition: SFTnaming.c:667
char * XLALBuildSFTFilenameFromSpec(const SFTFilenameSpec *spec)
Build an SFT file name from the given specification.
Definition: SFTnaming.c:302
int XLALFindCWDetector(CHAR **prefix, INT4 *lalCachedIndex, const CHAR *name, const BOOLEAN exactMatch)
Parses valid CW detector names and prefixes.
Definition: SFTnaming.c:118
int XLALCheckValidDescriptionField(const char *desc)
Check whether given string qualifies as a valid 'description' field of a FRAME filename (per ) or SFT...
Definition: SFTnaming.c:639
int XLALParseSFTFilenameIntoSpec(SFTFilenameSpec *spec, const char *SFTpath)
Parse a SFT file path and return its specification.
Definition: SFTnaming.c:463
int parse_sft_windowspec_str(const CHAR *windowspec_str, CHAR(*window_type)[32], REAL8 *window_param)
Parse an SFT filename field 'windowspec_str' into a window name 'window_type' and possible parameter ...
Definition: SFTnaming.c:802
int XLALFillSFTFilenameSpecStrings(SFTFilenameSpec *spec, const CHAR *path, const CHAR *extn, const CHAR *detector, const CHAR *window_type, const CHAR *privMisc, const CHAR *pubObsKind, const CHAR *pubChannel)
Convenience function for filling out the string fields in a SFTFilenameSpec.
Definition: SFTnaming.c:257
BOOLEAN XLALIsValidCWDetector(const CHAR *name)
Determine if 'name' is a valid detector name or prefix.
Definition: SFTnaming.c:188
#define XLAL_TRY_SILENT(statement, errnum)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
#define XLAL_CHECK_NULL(assertion,...)
XLAL_SUCCESS
XLAL_EFAULT
XLAL_ERANGE
XLAL_EFUNC
XLAL_ETOL
XLAL_ESYS
XLAL_EINVAL
XLAL_EFAILED
T
path
string prefix
desc
LALFrDetector frDetector
CHAR prefix[3]
CHAR name[LALNameLength]
Structure specifying an SFT file name, following the convention in .
Definition: SFTfileIO.h:266
UINT4 pubRevision
For public SFTs: revision number of SFT production.
Definition: SFTfileIO.h:279
UINT4 SFTtimebase
Timebase in seconds of the SFT; set by XLALWriteSFT[Vector]2StandardFile()
Definition: SFTfileIO.h:271
UINT4 SFTspan
Total time interval in seconds covered by SFT file; set by XLALWriteSFT[Vector]2StandardFile()
Definition: SFTfileIO.h:275
UINT4 nbBinWidthRem
For narrow-band SFTs: remainder of division of SFT bandwidth by SFT time base.
Definition: SFTfileIO.h:284
UINT4 gpsStart
GPS time in seconds at the beginning of the first SFT in the file; set by XLALWriteSFT[Vector]2Standa...
Definition: SFTfileIO.h:274
CHAR pubChannel[256]
For public SFTs: channel name of data used to make SFTs.
Definition: SFTfileIO.h:280
UINT4 nbBinWidthFreq
For narrow-band SFTs: SFT bandwidth divided by SFT time base, rounded down.
Definition: SFTfileIO.h:283
CHAR detector[3]
2-character detector prefix (e.g.
Definition: SFTfileIO.h:270
CHAR pubObsKind[4]
For public SFTs: kind of data ('RUN', 'AUX', 'SIM', 'DEV')
Definition: SFTfileIO.h:278
UINT4 nbFirstBinRem
For narrow-band SFTs: remainder of division of SFT first bin frequency by SFT time base.
Definition: SFTfileIO.h:282
UINT4 numSFTs
Number of SFTs in the file; set by XLALWriteSFT[Vector]2StandardFile()
Definition: SFTfileIO.h:269
UINT4 pubObsRun
For public SFTs: observing run number.
Definition: SFTfileIO.h:277
CHAR extn[32]
Extension of the SFT file; defaults to 'sft'.
Definition: SFTfileIO.h:268
CHAR window_type[32]
window function applied to SFT
Definition: SFTfileIO.h:272
CHAR path[4096]
Path to the SFT file.
Definition: SFTfileIO.h:267
UINT4 nbFirstBinFreq
For narrow-band SFTs: SFT first bin frequency divided by SFT time base, rounded down.
Definition: SFTfileIO.h:281
REAL8 window_param
parameter of window function, if required
Definition: SFTfileIO.h:273
CHAR privMisc[256]
For private SFTs: miscellaneous description field.
Definition: SFTfileIO.h:276
enum @4 site