Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
MakeSFTs.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2011, 2015, 2022 Karl Wette
3 * Copyright (C) 2007, 2009, 2011, 2015, 2016 Bernd Machenschalk
4 * Copyright (C) 2005--2007, 2012 Gregory Mendell
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/**
23 * \file
24 * \ingroup lalpulsar_bin_SFTTools
25 * \author Karl Wette, Evan Goetz, Gregory Mendell, Bernd Machenschalk, Xavier Siemens, Bruce Allen
26 * \brief Generate SFTs
27 */
28
29#include <stdlib.h>
30#include <stdio.h>
31#include <errno.h>
32#include <string.h>
33#include <stdbool.h>
34
35#include <lal/LALStdlib.h>
36#include <lal/LALStdio.h>
37#include <lal/UserInput.h>
38#include <lal/LogPrintf.h>
39#include <lal/Units.h>
40#include <lal/TimeSeries.h>
41#include <lal/BandPassTimeSeries.h>
42#include <lal/Window.h>
43#include <lal/RealFFT.h>
44#include <lal/SFTfileIO.h>
45#include <lal/LALFrStream.h>
46#include <lal/LALVCSInfo.h>
47#include <lal/LALPulsarVCSInfo.h>
48
49/* Prototypes */
50
51int main( int argc, char *argv[] )
52{
53
54 // Set help information
55 lalUserVarHelpBrief = "generate SFTs";
56
57 ////////// Parse user input //////////
58
59 // default output
60 LALStringVector *default_sft_write_path = NULL;
61 XLAL_CHECK_MAIN( ( default_sft_write_path = XLALCreateStringVector( ".", NULL ) ) != NULL, XLAL_EFUNC );
62
63 // Initialise user input variables
64 struct uvar_type {
65 char *frame_cache;
66 BOOLEAN frame_checksums;
67 LALStringVector *channel_name;
68 BOOLEAN allow_skipping;
69 INT4 gps_start_time;
70 INT4 gps_end_time;
71 INT4 sft_duration;
72 REAL8 overlap_fraction;
73 REAL8 high_pass_freq;
74 char *window_type;
75 REAL8 window_param;
76 REAL8 start_freq;
77 REAL8 band;
78 LALStringVector *sft_write_path;
79 UINT4 observing_run;
80 char *observing_kind;
81 UINT4 observing_revision;
82 char *misc_desc;
83 char *comment_field;
84 } uvar_struct = {
85 .sft_duration = 1800,
86 .overlap_fraction = 0,
87 .high_pass_freq = 0,
88 .window_param = 0,
89 .start_freq = 48,
90 .band = 2000,
91 .sft_write_path = default_sft_write_path,
92 .allow_skipping = false,
93 };
94 struct uvar_type *const uvar = &uvar_struct;
95
96 // Register user input variables
97 //
98 // - Input data
99 //
100 lalUserVarHelpOptionSubsection = "Input data";
102 frame_cache, STRING, 'C', REQUIRED,
103 "Path to frame cache file to read frames from. "
104 );
106 frame_checksums, BOOLEAN, 'k', OPTIONAL,
107 "Validate frame checksums. Default is to only validate checksums for " UVAR_STR( observing_kind ) "=RUN SFTs. "
108 );
110 channel_name, STRINGVector, 'N', REQUIRED,
111 "Name(s) of channel(s) to read within a frame. "
112 );
114 gps_start_time, INT4, 's', REQUIRED,
115 "GPS time to start generating SFTs. "
116 );
118 gps_end_time, INT4, 'e', REQUIRED,
119 "GPS time to end generating SFTs. "
120 );
122 allow_skipping, BOOLEAN, 'x', OPTIONAL,
123 "Channel is allowed to be skipped if it is not in frames or has too low sampling frequency. "
124 );
125 //
126 // - SFT generation
127 //
128 lalUserVarHelpOptionSubsection = "SFT generation";
130 sft_duration, INT4, 't', OPTIONAL,
131 "SFT duration in seconds. "
132 );
134 overlap_fraction, REAL8, 'P', OPTIONAL,
135 "Fraction of SFT duration to overlap SFTs by. "
136 "Example: use " UVAR_STR( overlap_fraction ) "=0.5 with " UVAR_STR( window_type ) "=hann windows. "
137 );
139 high_pass_freq, REAL8, 'f', REQUIRED,
140 "High pass filtering frequency in Hertz. "
141 );
143 window_type, STRING, 'w', REQUIRED,
144 "Window to apply to SFTs. See https://dcc.ligo.org/T040164/public for supported options.\n\n"
145 "The standard window applied to LVK production SFTs is documented in `lalpulsar_MakeSFTDAG`. "
146 );
148 window_param, REAL8, 'r', OPTIONAL,
149 "Parameter (if required) of window to apply to SFTs. "
150 );
152 start_freq, REAL8, 'F', OPTIONAL,
153 "Start frequency of the SFTs, in Hertz. "
154 );
156 band, REAL8, 'B', OPTIONAL,
157 "Frequency band of the SFTs, in Hertz. "
158 );
159 //
160 // - SFT output
161 //
162 lalUserVarHelpOptionSubsection = "SFT output";
164 sft_write_path, STRINGVector, 'p', OPTIONAL,
165 "Path(s) to write SFTs to, same order as channel name(s). "
166 );
168 observing_run, UINT4, 'O', REQUIRED,
169 "For >=1, SFTs will be named following the 'public' scheme from T040164-v2, and this number should correspond to the observing run the data comes from (without the leading 'O').\n\n"
170 "If set to 0, 'private' SFTs will be generated. "
171 );
173 observing_kind, STRING, 'K', OPTIONAL,
174 "For public SFTs (" UVAR_STR( observing_run ) ">=1) only, the kind of SFTs being generated: 'RUN', 'AUX', 'SIM', or 'DEV'. "
175 );
177 observing_revision, UINT4, 'R', OPTIONAL,
178 "For public SFTs (" UVAR_STR( observing_run ) ">=1) only, the revision number of the SFT production. "
179 );
181 misc_desc, STRING, 'X', OPTIONAL,
182 "For private SFTs only, a miscellaneous description field that will be included in the filenames. "
183 );
185 comment_field, STRING, 'c', OPTIONAL,
186 "Comment for SFT header. "
187 );
188 //
189 // - Defunct options
190 //
192 NULL, "frame_struct_type", STRING, 'u', DEFUNCT,
193 "No longer required; the frame channel type is determined automatically. "
194 );
196 NULL, "ht_data", BOOLEAN, 'H', DEFUNCT,
197 "No longer required; the frame channel type is determined automatically. "
198 );
200 NULL, "ifo", STRING, 'i', DEFUNCT,
201 "No longer required; the detector prefix is deduced from the channel name. "
202 );
204 NULL, "make_gps_dirs", BOOLEAN, 'D', DEFUNCT,
205 "No longer supported. "
206 );
208 NULL, "make_tmp_file", BOOLEAN, 'Z', DEFUNCT,
209 "Default behaviour. "
210 );
212 NULL, "sft_version", INT4, 'V', DEFUNCT,
213 "No longer supported. "
214 );
216 NULL, "use_single", BOOLEAN, 'S', DEFUNCT,
217 "No longer supported. "
218 );
220 NULL, "window_radius", REAL8, 0, DEFUNCT,
221 "Use " UVAR_STR( window_param ) " instead. "
222 );
223
224 // Parse user input
225 XLAL_CHECK_MAIN( xlalErrno == 0, XLAL_EFUNC, "A call to XLALRegisterUvarMember() failed" );
226 BOOLEAN should_exit = 0;
228 if ( should_exit ) {
229 return EXIT_FAILURE;
230 }
231
232 // Check user input:
233 //
234 // - Input data
235 //
236 XLALUserVarCheck( &should_exit,
237 uvar->gps_start_time > 0,
238 UVAR_STR( gps_start_time ) " must be strictly positive" );
239 XLALUserVarCheck( &should_exit,
240 uvar->gps_end_time > 0,
241 UVAR_STR( gps_end_time ) " must be strictly positive" );
242 //
243 // - SFT generation
244 //
245 XLALUserVarCheck( &should_exit,
246 uvar->sft_duration > 0,
247 UVAR_STR( sft_duration ) " must be strictly positive" );
248 XLALUserVarCheck( &should_exit,
249 uvar->gps_end_time - uvar->gps_start_time >= uvar->sft_duration,
250 "Cannot fit an SFT of duration %d between GPS times %d and %d\n",
251 uvar->sft_duration, uvar->gps_start_time, uvar->gps_end_time );
252 XLALUserVarCheck( &should_exit,
253 0 <= uvar->overlap_fraction && uvar->overlap_fraction < 1,
254 UVAR_STR( overlap_fraction ) " must be within range [0.0, 1.0)" );
255 XLALUserVarCheck( &should_exit,
256 uvar->high_pass_freq >= 0,
257 UVAR_STR( high_pass_freq ) " must be positive" );
258 if ( strcmp( uvar->window_type, "0" ) == 0 ) {
259 XLALUserVarCheck( &should_exit, 0,
260 UVAR_STR( window_type ) "=0 is deprecated; use " UVAR_STR( window_type ) "=rectangular" );
261 } else if ( strcmp( uvar->window_type, "1" ) == 0 ) {
262 XLALUserVarCheck( &should_exit, 0,
263 UVAR_STR( window_type ) "=1 is the old 'Matlab style Tukey window'; this EXACT window is "
264 "no longer supported BUT " UVAR_STR( window_type ) "=tukey will give you almost exactly "
265 "the same window; see https://dcc.ligo.org/LIGO-T040164/public for details" );
266 } else if ( strcmp( uvar->window_type, "2" ) == 0 ) {
267 XLALUserVarCheck( &should_exit, 0,
268 UVAR_STR( window_type ) "=2 is the old 'make_sfts.c Tukey window'; this window is "
269 "no longer supported. You probably want to use " UVAR_STR( window_type ) "=tukey, "
270 "although this will NOT give you exactly the same window" );
271 } else if ( strcmp( uvar->window_type, "3" ) == 0 ) {
272 XLALUserVarCheck( &should_exit, 0,
273 UVAR_STR( window_type ) "=3 is deprecated; use " UVAR_STR( window_type ) "=hann" );
274 } else {
275 XLALUserVarCheck( &should_exit,
276 XLALCheckNamedWindow( uvar->window_type, XLALUserVarWasSet( &uvar->window_param ) ) == XLAL_SUCCESS,
277 "Invalid/inconsistent " UVAR_STR( window_type ) " and/or " UVAR_STR( window_param ) );
278 }
279 XLALUserVarCheck( &should_exit,
280 uvar->window_param >= 0,
281 UVAR_STR( window_param ) " must be positive" );
282 XLALUserVarCheck( &should_exit,
283 uvar->start_freq >= 0,
284 UVAR_STR( start_freq ) " must be positive" );
285 XLALUserVarCheck( &should_exit,
286 uvar->band > 0,
287 UVAR_STR( band ) " must be strictly positive" );
288 //
289 // - SFT output
290 //
291 XLALUserVarCheck( &should_exit,
292 uvar->observing_run == 0
293 || ( XLALUserVarWasSet( &uvar->observing_kind )
294 && XLALUserVarWasSet( &uvar->observing_revision ) ),
295 "Must set " UVAR_STR( observing_kind ) " and " UVAR_STR( observing_revision ) " when using " UVAR_STR( observing_run ) ">0" );
296 XLALUserVarCheck( &should_exit,
297 uvar->observing_run == 0
298 || ( XLALUserVarWasSet( &uvar->observing_kind )
299 && ( strcmp( uvar->observing_kind, "RUN" ) == 0
300 || strcmp( uvar->observing_kind, "AUX" ) == 0
301 || strcmp( uvar->observing_kind, "SIM" ) == 0
302 || strcmp( uvar->observing_kind, "DEV" ) == 0 ) ),
303 UVAR_STR( observing_kind ) " must be one of 'RUN', 'AUX', 'SIM', or 'DEV'" );
304 XLALUserVarCheck( &should_exit,
305 uvar->observing_run == 0 || uvar->observing_revision > 0,
306 UVAR_STR( observing_revision ) " must be strictly positive" );
307 XLALUserVarCheck( &should_exit,
308 uvar->observing_run == 0 || !XLALUserVarWasSet( &uvar->misc_desc ),
309 UVAR_STR( observing_run ) "=0 is mutually exclusive with " UVAR_STR( misc_desc ) );
310 XLALUserVarCheck( &should_exit,
311 uvar->observing_run > 0
312 || !( XLALUserVarWasSet( &uvar->observing_kind )
313 || XLALUserVarWasSet( &uvar->observing_revision ) ),
314 "Setting " UVAR_STR( observing_kind ) " or " UVAR_STR( observing_revision ) " is not allowed with " UVAR_STR( observing_run ) "=0" );
315 XLALUserVarCheck( &should_exit,
316 uvar->channel_name->length == uvar->sft_write_path->length
317 || uvar->sft_write_path->length == 1,
318 "Number of channels in " UVAR_STR( channel_name ) " must be the same as the number of output paths in " UVAR_STR( sft_write_path ) "or a single path" );
319 XLALUserVarCheck( &should_exit,
320 uvar->observing_run > 0
321 || uvar->channel_name->length == 1,
322 "For private SFTs (" UVAR_STR( observing_run ) "=0), can only provide one channel at a time" );
323
324 // Exit if required
325 if ( should_exit ) {
326 return EXIT_FAILURE;
327 }
328 LogPrintf( LOG_NORMAL, "Parsed user input successfully\n" );
329
330 // Decide whether to validate frame checksums
331 bool frame_checksums = false;
332 if ( XLALUserVarWasSet( &uvar->frame_checksums ) ) {
333 if ( uvar->frame_checksums ) {
334 frame_checksums = true;
335 LogPrintf( LOG_NORMAL, "Validating frame checksums as " UVAR_STR( frame_checksums ) "=true\n" );
336 } else {
337 frame_checksums = false;
338 LogPrintf( LOG_NORMAL, "Not validating frame checksums as " UVAR_STR( frame_checksums ) "=false\n" );
339 }
340 } else if ( XLALUserVarWasSet( &uvar->observing_kind ) ) {
341 if ( strcmp( uvar->observing_kind, "RUN" ) == 0 ) {
342 frame_checksums = true;
343 LogPrintf( LOG_NORMAL, "Validating frame checksums as " UVAR_STR( observing_kind ) "=%s\n", uvar->observing_kind );
344 } else {
345 frame_checksums = false;
346 LogPrintf( LOG_NORMAL, "Not validating frame checksums as " UVAR_STR( observing_kind ) "=%s!=RUN\n", uvar->observing_kind );
347 }
348 } else {
349 frame_checksums = false;
350 LogPrintf( LOG_NORMAL, "Not validating frame checksums as neither " UVAR_STR( frame_checksums ) " nor " UVAR_STR( observing_kind ) " were given\n" );
351 }
352
353 ////////// Set up SFT generation //////////
354
355 // Build comment string from program name, VCS information, and full command line option log
356 // (including default values); this will include anything passed to --comment-field
357 char *SFT_comment = NULL;
358 {
359 char *vcs_info_str = XLALVCSInfoString( lalPulsarVCSInfoList, 0, NULL );
360 XLAL_CHECK_MAIN( vcs_info_str != NULL, XLAL_EFUNC );
361 char *cmd_line_str = XLALUserVarGetLogEx( UVAR_LOGFMT_CFGFILE, 0 );
362 XLAL_CHECK_MAIN( cmd_line_str != NULL, XLAL_EFUNC );
363 SFT_comment = XLALStringAppendFmt( SFT_comment, "Generated by %s\nVersion:\n%s\nOptions:\n%s\n", argv[0], vcs_info_str, cmd_line_str );
364 XLAL_CHECK_MAIN( SFT_comment != NULL, XLAL_EFUNC );
365 XLALFree( vcs_info_str );
366 XLALFree( cmd_line_str );
367 }
368
369 // Create frame cache
370 LALCache *framecache = XLALCacheImport( uvar->frame_cache );
371 XLAL_CHECK_MAIN( framecache != NULL, XLAL_EFUNC,
372 "Failed to open frame cache '%s'", uvar->frame_cache );
373
374 // Open frame stream
375 LALFrStream *framestream = XLALFrStreamCacheOpen( framecache );
376 XLAL_CHECK_MAIN( framestream != NULL, XLAL_EFUNC,
377 "Failed to open frame stream from cache '%s'", uvar->frame_cache );
378 LogPrintf( LOG_NORMAL, "Opened frame stream from cache '%s'\n", uvar->frame_cache );
379
380 // Set frame stream mode
381 {
383 mode |= LAL_FR_STREAM_VERBOSE_MODE; /* Display warnings and info */
384 if ( frame_checksums ) {
385 mode |= LAL_FR_STREAM_CHECKSUM_MODE; /* Ensure that file checksums are OK */
386 }
388 "Failed to set frame stream mode to %i", mode );
389 }
390
391 // Create SFT type for writing output
392 const UINT4 SFT_first_bin = lrint( uvar->start_freq * uvar->sft_duration );
393 const UINT4 SFT_bins = lrint( uvar->band * uvar->sft_duration );
394 SFTtype *SFT = XLALCreateSFT( SFT_bins );
395 XLAL_CHECK_MAIN( SFT != NULL, XLAL_EFUNC,
396 "Failed to allocate SFT of %u bins", SFT_bins );
397
398 ////////// Generate SFTs //////////
399
400 // SFT time series window, allocated once first time series data is read
401 REAL8Window *SFT_window = NULL;
402
403 // SFT FFT data vector and plan, allocated once first time series data is read
404 COMPLEX16Vector *SFT_fft_data = NULL;
405 REAL8FFTPlan *SFT_fft_plan = NULL;
406
407 // Read data from frame stream until SFT end time is reached
408 INT4 SFT_epoch_sec = uvar->gps_start_time;
409 INT4 num_SFTs_made = 0;
410 while ( 1 ) {
411
412 const LIGOTimeGPS SFT_epoch = { .gpsSeconds = SFT_epoch_sec, .gpsNanoSeconds = 0 };
413
414 // Loop over channels for this SFT interval
415 for ( UINT4 n = 0; n < uvar->channel_name->length; n++ ) {
416 // Check the channel in the framestream. It should return a type if it exists.
417 // Need to check both the beginning and end of the time interval.
418 // By default (uvar->require_channel = true), if the channel doesn't return a type, then this program fails
419 // Optionally, a user could specify that the channel is not required to be in the frame in which case no SFT is made
420 {
421 int errnum;
422 LALTYPECODE XLAL_INIT_DECL( laltype );
423
424 // Set the frame stream to the start of the SFT
425 XLAL_CHECK_MAIN( XLALFrStreamSeek( framestream, &SFT_epoch ) == 0, XLAL_EFUNC );
426
427 // First check the beginning
428 XLAL_TRY( laltype = XLALFrStreamGetTimeSeriesType( uvar->channel_name->data[n], framestream ), errnum );
429 if ( errnum != 0 && uvar->allow_skipping ) {
430 LogPrintf( LOG_CRITICAL, "--require-channel=FALSE and %s is not in frames\n", uvar->channel_name->data[n] );
431 LogPrintf( LOG_CRITICAL, "==> No SFTs will be made for channel %s\n", uvar->channel_name->data[n] );
432 continue;
433 } else if ( errnum != 0 ) {
434 XLAL_ERROR_MAIN( errnum );
435 }
436
437 // Shift the frame stream by SFT length minus one microsecond so that we don't hit the end of the framestream
438 XLAL_CHECK_MAIN( XLALFrStreamSeekO( framestream, uvar->sft_duration - 1e-6, SEEK_CUR ) == 0, XLAL_EFUNC );
439
440 // Now check the end
441 XLAL_TRY( laltype = XLALFrStreamGetTimeSeriesType( uvar->channel_name->data[n], framestream ), errnum );
442 if ( errnum != 0 && uvar->allow_skipping ) {
443 LogPrintf( LOG_CRITICAL, "--require-channel=FALSE and %s is not in frames\n", uvar->channel_name->data[n] );
444 LogPrintf( LOG_CRITICAL, "==> No SFTs will be made for channel %s\n", uvar->channel_name->data[n] );
445 continue;
446 } else if ( errnum != 0 ) {
447 XLAL_ERROR_MAIN( errnum );
448 }
449
450 // Return to the original position
451 XLAL_CHECK_MAIN( XLALFrStreamSeek( framestream, &SFT_epoch ) == 0, XLAL_EFUNC );
452 }
453
454 // Try to read in time series data for the next SFT
455 REAL8TimeSeries *SFT_time_series = NULL;
456 {
457 SFT_time_series = XLALFrStreamInputREAL8TimeSeries( framestream, uvar->channel_name->data[n], &SFT_epoch, uvar->sft_duration, 0 );
458 XLAL_CHECK_MAIN( SFT_time_series != NULL, XLAL_EFUNC,
459 "XLALFrStreamInputREAL8TimeSeries() failed at GPS time %" LAL_INT4_FORMAT, SFT_epoch_sec );
460 }
461
462 // Create SFT time series window
463 if ( SFT_window != NULL && SFT_window->data->length != SFT_time_series->data->length ) {
464 XLALDestroyREAL8Window( SFT_window );
465 SFT_window = NULL;
466 }
467 if ( SFT_window == NULL ) {
468 SFT_window = XLALCreateNamedREAL8Window( uvar->window_type, uvar->window_param, SFT_time_series->data->length );
469 XLAL_CHECK_MAIN( SFT_window != NULL, XLAL_EFUNC,
470 "Failed to allocate SFT time series window of %u elements at GPS time %" LAL_INT4_FORMAT, SFT_time_series->data->length, SFT_epoch_sec );
471 }
472
473 // Create SFT FFT data vector and plan
474 if ( SFT_fft_data != NULL && SFT_fft_data->length != SFT_time_series->data->length / 2 + 1 ) {
475 XLALDestroyCOMPLEX16Vector( SFT_fft_data );
476 XLALDestroyREAL8FFTPlan( SFT_fft_plan );
477 SFT_fft_data = NULL;
478 SFT_fft_plan = NULL;
479 }
480 if ( SFT_fft_data == NULL ) {
481 SFT_fft_data = XLALCreateCOMPLEX16Vector( SFT_time_series->data->length / 2 + 1 );
482 XLAL_CHECK_MAIN( SFT_fft_data != NULL, XLAL_EFUNC,
483 "Failed to allocate SFT FFT data vector of %u elements at GPS time %" LAL_INT4_FORMAT, SFT_time_series->data->length / 2 + 1, SFT_epoch_sec );
484 SFT_fft_plan = XLALCreateForwardREAL8FFTPlan( SFT_time_series->data->length, 0 );
485 XLAL_CHECK_MAIN( SFT_fft_plan != NULL, XLAL_EFUNC,
486 "Failed to allocate SFT FFT plan at GPS time %" LAL_INT4_FORMAT, SFT_epoch_sec );
487
488 // If the sampling rate is too low for the requested band, skip this channel if allowed
489 if ( SFT_fft_data->length < SFT_bins && uvar->allow_skipping ) {
490 LogPrintf( LOG_CRITICAL, "Sampling rate is too low for band requested, skipping %s\n", uvar->channel_name->data[n] );
491 XLALDestroyREAL8TimeSeries( SFT_time_series );
492 XLALDestroyREAL8Window( SFT_window );
493 XLALDestroyCOMPLEX16Vector( SFT_fft_data );
494 XLALDestroyREAL8FFTPlan( SFT_fft_plan );
495 SFT_window = NULL;
496 SFT_fft_data = NULL;
497 SFT_fft_plan = NULL;
498 continue;
499 }
500
501 // Exit with error if the data length is too short
502 XLAL_CHECK_MAIN( SFT_fft_data->length >= SFT_bins, XLAL_ESIZE );
503 }
504
505 // High-pass SFT time series data with Butterworth High Pass filter
506 if ( uvar->high_pass_freq > 0.0 ) {
507 char filtername[] = "Butterworth High Pass";
508 PassBandParamStruc filterpar = {
509 .name = filtername,
510 .nMax = 10,
511 .f2 = uvar->high_pass_freq,
512 .a2 = 0.5,
513 .f1 = -1.0,
514 .a1 = -1.0,
515 };
516 XLAL_CHECK_MAIN( XLALButterworthREAL8TimeSeries( SFT_time_series, &filterpar ) == XLAL_SUCCESS, XLAL_EFUNC,
517 "Failed to apply %s filter to SFT time series data at GPS time %" LAL_INT4_FORMAT, filterpar.name, SFT_epoch_sec );
518 }
519
520 // Window SFT time series data
521 XLAL_CHECK_MAIN( XLALUnitaryWindowREAL8Sequence( SFT_time_series->data, SFT_window ) != NULL, XLAL_EFUNC,
522 "Failed to apply window to SFT time series data at GPS time %" LAL_INT4_FORMAT, SFT_epoch_sec );
523
524 // Fourier transform SFT time series data
525 XLAL_CHECK_MAIN( XLALREAL8ForwardFFT( SFT_fft_data, SFT_time_series->data, SFT_fft_plan ) == XLAL_SUCCESS, XLAL_EFUNC,
526 "Failed to Fourier transform SFT time series data at GPS time %" LAL_INT4_FORMAT, SFT_epoch_sec );
527
528 // Initialise SFT type
529 SFT->name[0] = uvar->channel_name->data[n][0];
530 SFT->name[1] = uvar->channel_name->data[n][1] == '0' ? '1' : uvar->channel_name->data[n][1];
531 SFT->name[2] = 0;
532 SFT->epoch = SFT_time_series->epoch;
533 SFT->f0 = uvar->start_freq;
534 SFT->deltaF = 1.0 / ( ( REAL8 ) uvar->sft_duration );
535
536 // Copy and normalise SFT frequency series data into SFT
537 const REAL8 SFT_normalisation = SFT_time_series->deltaT;
538 for ( UINT4 k = 0; k < SFT_bins; ++k ) {
539 const REAL8 SFT_fft_re = creal( SFT_fft_data->data[k + SFT_first_bin] );
540 const REAL8 SFT_fft_im = cimag( SFT_fft_data->data[k + SFT_first_bin] );
541 SFT->data->data[k] = crectf( SFT_normalisation * SFT_fft_re, SFT_normalisation * SFT_fft_im );
542 }
543
544 // Build SFT filename spec
546 if ( uvar->sft_write_path->length > 1 ) {
547 XLAL_CHECK_MAIN( XLALFillSFTFilenameSpecStrings( &spec, uvar->sft_write_path->data[n], "sft_TO_BE_VALIDATED", NULL, uvar->window_type, uvar->misc_desc, uvar->observing_kind, uvar->channel_name->data[n] ) == XLAL_SUCCESS, XLAL_EFUNC );
548 } else {
549 XLAL_CHECK_MAIN( XLALFillSFTFilenameSpecStrings( &spec, uvar->sft_write_path->data[0], "sft_TO_BE_VALIDATED", NULL, uvar->window_type, uvar->misc_desc, uvar->observing_kind, uvar->channel_name->data[n] ) == XLAL_SUCCESS, XLAL_EFUNC );
550 }
551 spec.window_param = uvar->window_param;
552 spec.pubObsRun = uvar->observing_run;
553 spec.pubRevision = uvar->observing_revision;
554
555 // Write out SFT and retrieve filename
556 char *temp_SFT_filename = NULL;
557 {
558 int retn = XLALWriteSFT2StandardFile( SFT, &spec, SFT_comment );
559 temp_SFT_filename = XLALBuildSFTFilenameFromSpec( &spec );
561 "Failed to write SFT '%s' at GPS time %" LAL_INT4_FORMAT, temp_SFT_filename ? temp_SFT_filename : "<unknown>", SFT_epoch_sec );
562 XLAL_CHECK_MAIN( temp_SFT_filename != NULL, XLAL_EFUNC );
563 }
564
565 // Validate SFT
567 "Failed to validate SFT '%s' at GPS time %" LAL_INT4_FORMAT, temp_SFT_filename, SFT_epoch_sec );
568
569 // Move SFT to final filename
570 char *final_SFT_filename = XLALStringDuplicate( temp_SFT_filename );
571 char *const extn = strrchr( final_SFT_filename, '.' );
572 XLAL_CHECK_MAIN( extn != NULL, XLAL_ESYS );
573 XLAL_CHECK_MAIN( strlen( extn ) >= 4, XLAL_EFAILED );
574 strcpy( extn, ".sft" );
575 XLAL_CHECK_MAIN( rename( temp_SFT_filename, final_SFT_filename ) == 0, XLAL_ESYS,
576 "Failed to rename '%s' to '%s': %s", temp_SFT_filename, final_SFT_filename, strerror( errno ) );
577 LogPrintf( LOG_DEBUG, "Wrote SFT '%s'\n", final_SFT_filename );
578
579 // Increment number of SFTs made
580 if ( ++num_SFTs_made == 1 ) {
581 LogPrintf( LOG_NORMAL, "Generated first SFT at GPS time %" LAL_INT4_FORMAT "\n", SFT_epoch_sec );
582 }
583
584 // Free memory
585 XLALDestroyREAL8TimeSeries( SFT_time_series );
586 XLALFree( temp_SFT_filename );
587 XLALFree( final_SFT_filename );
588
589 // Set LALFrStream to correct location, if needed
590 if ( n < uvar->channel_name->length - 1 ) {
591 XLAL_CHECK_MAIN( XLALFrStreamSeek( framestream, &SFT_epoch ) == 0, XLAL_EFUNC );
592 }
593
594 }
595
596 // Advance to next SFT, overlapping if requested
597 {
598 const INT4 last_SFT_epoch_sec = SFT_epoch_sec;
599 SFT_epoch_sec += ( 1.0 - uvar->overlap_fraction ) * ( ( REAL8 ) uvar->sft_duration );
600 if ( SFT_epoch_sec + uvar->sft_duration > uvar->gps_end_time ) {
601 LogPrintf( LOG_NORMAL, "Generated last SFT at GPS time %" LAL_INT4_FORMAT "\n", last_SFT_epoch_sec );
602 LogPrintf( LOG_NORMAL, "Generated %" LAL_INT4_FORMAT " SFTs\n", num_SFTs_made );
603 break;
604 }
605 }
606 }
607
608 ////////// Free memory //////////
609
610 XLALFree( SFT_comment );
611
612 XLALDestroyCache( framecache );
613 XLALFrStreamClose( framestream );
614
615 XLALDestroyREAL8Window( SFT_window );
616 XLALDestroyCOMPLEX16Vector( SFT_fft_data );
617 XLALDestroyREAL8FFTPlan( SFT_fft_plan );
618 XLALDestroySFT( SFT );
619
621
623
624 return 0;
625}
int XLALButterworthREAL8TimeSeries(REAL8TimeSeries *series, PassBandParamStruc *params)
int k
void LALCheckMemoryLeaks(void)
const LALVCSInfoList lalPulsarVCSInfoList
NULL-terminated list of VCS and build information for LALPulsar and its dependencies
int main(int argc, char *argv[])
Definition: MakeSFTs.c:51
#define STRING(a)
const char * window_type
Definition: SFTnaming.c:44
double e
void XLALDestroyCache(LALCache *cache)
LALCache * XLALCacheImport(const char *fname)
LALTYPECODE
unsigned char BOOLEAN
double REAL8
#define XLAL_INIT_DECL(var,...)
#define crectf(re, im)
uint32_t UINT4
int32_t INT4
int XLALFrStreamSeek(LALFrStream *stream, const LIGOTimeGPS *epoch)
int XLALFrStreamSeekO(LALFrStream *stream, double dt, int whence)
LALFrStreamMode
int XLALFrStreamClose(LALFrStream *stream)
LALFrStream * XLALFrStreamCacheOpen(LALCache *cache)
int XLALFrStreamSetMode(LALFrStream *stream, int mode)
LAL_FR_STREAM_CHECKSUM_MODE
LAL_FR_STREAM_VERBOSE_MODE
LALTYPECODE XLALFrStreamGetTimeSeriesType(const char *chname, LALFrStream *stream)
REAL8TimeSeries * XLALFrStreamInputREAL8TimeSeries(LALFrStream *stream, const char *chname, const LIGOTimeGPS *start, double duration, size_t lengthlimit)
void XLALFree(void *p)
#define LAL_INT4_FORMAT
char char * XLALStringDuplicate(const char *s)
char * XLALStringAppendFmt(char *s, const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(2
char * XLALVCSInfoString(const LALVCSInfoList vcs_list, const int verbose, const char *prefix)
void LogPrintf(LogLevel_t, const char *format,...) _LAL_GCC_PRINTF_FORMAT_(2
LOG_CRITICAL
LOG_DEBUG
LOG_NORMAL
int XLALREAL8ForwardFFT(COMPLEX16Vector *output, const REAL8Vector *input, const REAL8FFTPlan *plan)
void XLALDestroyREAL8FFTPlan(REAL8FFTPlan *plan)
REAL8FFTPlan * XLALCreateForwardREAL8FFTPlan(UINT4 size, int measurelvl)
SFTtype * XLALCreateSFT(UINT4 numBins)
XLAL function to create one SFT-struct.
Definition: SFTtypes.c:152
char * XLALBuildSFTFilenameFromSpec(const SFTFilenameSpec *spec)
Build an SFT file name from the given specification.
Definition: SFTnaming.c:302
void XLALDestroySFT(SFTtype *sft)
Destructor for one SFT.
Definition: SFTtypes.c:176
int XLALWriteSFT2StandardFile(const SFTtype *sft, SFTFilenameSpec *SFTfnspec, const CHAR *SFTcomment)
Write the given SFTtype to a SFT file with a standard () filename.
Definition: SFTfileIO.c:656
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
int XLALCheckSFTFileIsValid(const char *fname)
Verify that the contents of a SFT file are valid.
Definition: SFTfileIO.c:834
LALStringVector * XLALCreateStringVector(const CHAR *str1,...)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
const char * lalUserVarHelpOptionSubsection
const char * lalUserVarHelpBrief
int XLALUserVarReadAllInput(BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list)
void XLALDestroyUserVars(void)
CHAR * XLALUserVarGetLogEx(UserVarLogFormat format, const BOOLEAN skip_unset)
#define XLALRegisterUvarMember(name, type, option, category,...)
#define UVAR_STR(n)
void XLALUserVarCheck(BOOLEAN *should_exit, const int assertion, const CHAR *fmt,...) _LAL_GCC_PRINTF_FORMAT_(3
#define XLALRegisterNamedUvar(cvar, name, type, option, category,...)
int XLALUserVarWasSet(const void *cvar)
UVAR_LOGFMT_CFGFILE
COMPLEX16Vector * XLALCreateCOMPLEX16Vector(UINT4 length)
void XLALDestroyCOMPLEX16Vector(COMPLEX16Vector *vector)
REAL8Window * XLALCreateNamedREAL8Window(const char *windowName, REAL8 beta, UINT4 length)
REAL8Sequence * XLALUnitaryWindowREAL8Sequence(REAL8Sequence *sequence, const REAL8Window *window)
void XLALDestroyREAL8Window(REAL8Window *window)
int XLALCheckNamedWindow(const char *windowName, const BOOLEAN haveBeta)
#define xlalErrno
#define XLAL_CHECK_MAIN(assertion,...)
#define XLAL_ERROR_MAIN(...)
#define XLAL_TRY(statement, errnum)
XLAL_SUCCESS
XLAL_EFUNC
XLAL_ESIZE
XLAL_ESYS
XLAL_EFAILED
n
COMPLEX16 * data
CHAR name[LALNameLength]
COMPLEX8Sequence * data
COMPLEX8 * data
REAL8Sequence * data
LIGOTimeGPS epoch
REAL8Sequence * data
Structure specifying an SFT file name, following the convention in .
Definition: SFTfileIO.h:266
UserInput_t uvar_struct
Definition: sw_inj_frames.c:93