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
spec_coherence.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2021-2025 Evan Goetz
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* \file
22* \ingroup lalpulsar_bin_fscan
23*/
24
25#include <libgen.h>
26#include <unistd.h>
27#include <lal/SFTfileIO.h>
28#include <lal/LALStdio.h>
29#include <lal/LogPrintf.h>
30#include <lal/UserInput.h>
31#include <lal/LALPulsarVCSInfo.h>
32
33#include "fscanutils.h"
34
35int main( int argc, char **argv )
36{
37 lalUserVarHelpBrief = "Compute coherence between two channels from SFTs for Fscan";
38 lalUserVarHelpDescription = "Provide SFTs to this program for computing coherence between two channels, saved as ASCII data file for use by Fscan";
39
40 FILE *COHOUT = NULL;
41 int fopenerr = 0;
42
43 SFTCatalog *catalog_a = NULL, *catalog_b = NULL;
44 SFTVector *sft_vect_a = NULL, *sft_vect_b = NULL;
45 SFTConstraints XLAL_INIT_DECL( constraints );
46 LIGOTimeGPS startTime, endTime;
47 REAL8Vector *psd_a = NULL, *psd_b = NULL;
48 COMPLEX16Vector *coh = NULL;
49 REAL8 f0 = 0, deltaF = 0;
50 CHAR outbase[256], outfile0[512];
51
52 CHAR *SFTpattA = NULL, *SFTpattB = NULL, *outputDir = NULL, *outputBname = NULL, *header = NULL;
53 INT4 startGPS = 0, endGPS = 0;
54 REAL8 f_min = 0.0, f_max = 0.0, timebaseline = 0;
55
56 /* Default for output directory */
57 XLAL_CHECK_MAIN( ( outputDir = XLALStringDuplicate( "." ) ) != NULL, XLAL_EFUNC );
58
59 BOOLEAN allow_skipping = 0;
60
61 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &SFTpattA, "ChASFTs", STRING, 'p', REQUIRED, "SFT location/pattern. Possibilities are:\n"
62 " - '<SFT file>;<SFT file>;...', where <SFT file> may contain wildcards\n - 'list:<file containing list of SFT files>'" ) == XLAL_SUCCESS, XLAL_EFUNC );
63 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &SFTpattB, "ChBSFTs", STRING, 'q', REQUIRED, "SFT location/pattern. Possibilities are:\n"
64 " - '<SFT file>;<SFT file>;...', where <SFT file> may contain wildcards\n - 'list:<file containing list of SFT files>'" ) == XLAL_SUCCESS, XLAL_EFUNC );
65 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &startGPS, "startGPS", INT4, 's', REQUIRED, "Starting GPS time (SFT timestamps must be >= this)" ) == XLAL_SUCCESS, XLAL_EFUNC );
66 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &endGPS, "endGPS", INT4, 'e', REQUIRED, "Ending GPS time (SFT timestamps must be < this)" ) == XLAL_SUCCESS, XLAL_EFUNC );
67 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &f_min, "fMin", REAL8, 'f', REQUIRED, "Minimum frequency" ) == XLAL_SUCCESS, XLAL_EFUNC );
68 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &f_max, "fMax", REAL8, 'F', REQUIRED, "Maximum frequency" ) == XLAL_SUCCESS, XLAL_EFUNC );
69 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &outputDir, "outputDir", STRING, 'd', OPTIONAL, "Output directory for data files" ) == XLAL_SUCCESS, XLAL_EFUNC );
70 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &outputBname, "outputBname", STRING, 'o', OPTIONAL, "Base name of output files" ) == XLAL_SUCCESS, XLAL_EFUNC );
71 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &timebaseline, "timeBaseline", REAL8, 't', REQUIRED, "The time baseline of sfts" ) == XLAL_SUCCESS, XLAL_EFUNC );
72 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &allow_skipping, "allow_skipping", BOOLEAN, 'x', OPTIONAL, "Allow to exit without an error if no SFTs are found" ) == XLAL_SUCCESS, XLAL_EFUNC );
73 XLAL_CHECK_MAIN( XLALRegisterNamedUvar( &header, "header", STRING, 'H', OPTIONAL, "Header line in the output file; if not provided then no header line will be made" ) == XLAL_SUCCESS, XLAL_EFUNC );
74
75 BOOLEAN should_exit = 0;
77 if ( should_exit ) {
78 return ( 1 );
79 }
80
81 printf( "Starting spec_coherence...\n" );
82
83 /* Provide the constraints to the catalog */
84 startTime.gpsSeconds = startGPS;
85 startTime.gpsNanoSeconds = 0;
86 constraints.minStartTime = &startTime;
87 endTime.gpsSeconds = endGPS;
88 endTime.gpsNanoSeconds = 0;
89 constraints.maxStartTime = &endTime;
90
91 int errnumA, errnumB;
92 printf( "Calling XLALSFTdataFind with SFTpattA=%s\n", SFTpattA );
93 XLAL_TRY( catalog_a = XLALSFTdataFind( SFTpattA, &constraints ), errnumA );
94 printf( "Calling XLALSFTdataFind with SFTpattB=%s\n", SFTpattB );
95 XLAL_TRY( catalog_b = XLALSFTdataFind( SFTpattB, &constraints ), errnumB );
96
97 /* Ensure that some SFTs were found given the start and end time and IFO constraints unless --allow_skipping is true */
98 if ( errnumA != 0 || errnumB != 0 ) {
99 if ( errnumA != 0 && allow_skipping ) {
100 LogPrintf( LOG_CRITICAL, "Channel A %s found no SFTs, exiting with code %d due to --allow_skipping=true\n", SFTpattA, XLAL_EUSR0 );
101 if ( catalog_a != NULL ) {
102 XLALDestroySFTCatalog( catalog_a );
103 }
104 if ( catalog_b != NULL ) {
105 XLALDestroySFTCatalog( catalog_b );
106 }
108 exit( XLAL_EUSR0 );
109 } else if ( errnumA != 0 ) {
110 XLAL_ERROR_MAIN( errnumA );
111 }
112 if ( errnumB != 0 && allow_skipping ) {
113 LogPrintf( LOG_CRITICAL, "Channel B %s found no SFTs, exiting with code %d due to --allow_skipping=true\n", SFTpattB, XLAL_EUSR0 );
114 if ( catalog_a != NULL ) {
115 XLALDestroySFTCatalog( catalog_a );
116 }
117 if ( catalog_b != NULL ) {
118 XLALDestroySFTCatalog( catalog_b );
119 }
121 exit( XLAL_EUSR0 );
122 } else if ( errnumB != 0 ) {
123 XLAL_ERROR_MAIN( errnumB );
124 }
125 }
126
127 XLAL_CHECK_MAIN( catalog_a->length > 0, XLAL_EFAILED, "No SFTs found for Ch A, please examine start time, end time, frequency range, etc." );
128 XLAL_CHECK_MAIN( catalog_b->length > 0, XLAL_EFAILED, "No SFTs found for Ch B, please examine start time, end time, frequency range, etc." );
129
130 LogPrintf( LOG_NORMAL, "Channel A %s has length of %u SFT files\n", SFTpattA, catalog_a->length );
131 LogPrintf( LOG_NORMAL, "Channel B %s has length of %u SFT files\n", SFTpattB, catalog_b->length );
132
133 if ( XLALUserVarWasSet( &outputBname ) ) {
134 snprintf( outbase, sizeof( outbase ), "%s/%s", outputDir, outputBname );
135 } else {
136 snprintf( outbase, sizeof( outbase ), "%s/spec_%.2f_%.2f_%d_%d_coh", outputDir, f_min, f_max, startTime.gpsSeconds, endTime.gpsSeconds );
137 }
138
139 snprintf( outfile0, sizeof( outfile0 ), "%s.txt", outbase );
140
141 COHOUT = fopen( outfile0, "w" );
142 fopenerr = errno;
143 XLAL_CHECK_MAIN( COHOUT != NULL, XLAL_EIO, "Failed to open '%s' for writing: %s", outfile0, strerror( fopenerr ) );
144
145 // Write header line to files, if provided
146 if ( XLALUserVarWasSet( &header ) ) {
147 fprintf( COHOUT, "# %s\n", header );
148 }
149
150 UINT4 nAve = 0;
151
152 printf( "Looping over SFTs to compute coherence\n" );
153 for ( UINT4 j = 0; j < catalog_a->length; j++ ) {
154 /* Extract one SFT at a time from the catalog */
155 fprintf( stderr, "Extracting SFT %d...\n", j );
156 XLAL_CHECK_MAIN( ( sft_vect_a = extract_one_sft( catalog_a, catalog_a->data[j].header.epoch, f_min, f_max ) ) != NULL, XLAL_EFUNC );
157
158 /* If no SFT from the B list was found, then just continue with the next SFT in the A list */
159 XLAL_TRY( sft_vect_b = extract_one_sft( catalog_b, catalog_a->data[j].header.epoch, f_min, f_max ), errnumB );
160 if ( errnumB != 0 ) {
161 LogPrintf( LOG_CRITICAL, "Failed to find B channel SFT at time %d, [%.9f, %.9f) Hz\n", catalog_a->data[j].header.epoch.gpsSeconds, f_min, f_max );
162 continue;
163 }
164
165 /* Check time baseline of the SFTs to confirm they match */
166 XLAL_CHECK_MAIN( sft_vect_a->data[0].deltaF * timebaseline == 1.0, XLAL_EINVAL, "Time baseline of SFTs and the request do not match" );
167 XLAL_CHECK_MAIN( sft_vect_b->data[0].deltaF * timebaseline == 1.0, XLAL_EINVAL, "Time baseline of SFTs and the request do not match" );
168
169 /* For the first time through the loop, we allocate some vectors */
170 if ( nAve == 0 ) {
171 UINT4 numBins = sft_vect_a->data->data->length;
172 f0 = sft_vect_a->data->f0;
173 deltaF = sft_vect_a->data->deltaF;
174
176 XLAL_CHECK_MAIN( ( psd_a = XLALCreateREAL8Vector( numBins ) ) != NULL, XLAL_EFUNC );
177 XLAL_CHECK_MAIN( ( psd_b = XLALCreateREAL8Vector( numBins ) ) != NULL, XLAL_EFUNC );
178 }
179
180 /* Loop over the SFT bins computing cross spectrum (AB) and auto spectrum (AA and BB) */
181 if ( nAve == 0 ) {
182 for ( UINT4 i = 0; i < sft_vect_a->data->data->length; i++ ) {
183 coh->data[i] = sft_vect_a->data[0].data->data[i] * conj( sft_vect_b->data[0].data->data[i] );
184 psd_a->data[i] = sft_vect_a->data[0].data->data[i] * conj( sft_vect_a->data[0].data->data[i] );
185 psd_b->data[i] = sft_vect_b->data[0].data->data[i] * conj( sft_vect_b->data[0].data->data[i] );
186 }
187 } else {
188 for ( UINT4 i = 0; i < sft_vect_a->data->data->length; i++ ) {
189 coh->data[i] += sft_vect_a->data[0].data->data[i] * conj( sft_vect_b->data[0].data->data[i] );
190 psd_a->data[i] += sft_vect_a->data[0].data->data[i] * conj( sft_vect_a->data[0].data->data[i] );
191 psd_b->data[i] += sft_vect_b->data[0].data->data[i] * conj( sft_vect_b->data[0].data->data[i] );
192 }
193 }
194 /* Destroys current SFT Vectors */
195 XLALDestroySFTVector( sft_vect_a );
196 XLALDestroySFTVector( sft_vect_b );
197 sft_vect_a = sft_vect_b = NULL;
198
199 nAve++;
200 }
201
202 XLAL_CHECK_MAIN( nAve > 0, XLAL_EFAILED, "No SFTs were found to be matching" );
203
204 /* compute the final coherence (|AB|**2 / (AA * BB)) and print to file */
205 for ( UINT4 i = 0; i < coh->length; i++ ) {
206 REAL8 f = f0 + ( ( REAL4 )i ) * deltaF;
207 REAL8 COH = coh->data[i] * conj( coh->data[i] ) / ( psd_a->data[i] * psd_b->data[i] );
208 fprintf( COHOUT, "%16.8f %g\n", f, COH );
209 }
210
211 fprintf( stderr, "Destroying Variables\n" );
212 XLALDestroySFTCatalog( catalog_a );
213 XLALDestroySFTCatalog( catalog_b );
214
216 XLALDestroyREAL8Vector( psd_a );
217 XLALDestroyREAL8Vector( psd_b );
218
219 fprintf( stderr, "Closing Files\n" );
220 fclose( COHOUT );
221
223 fprintf( stderr, "Done Destroying Variables\n" );
224 fprintf( stderr, "end of spec_coherence\n" );
225 fprintf( stderr, "Spec_coherence_done!\n" );
226
227 return ( 0 );
228
229}
230/* END main */
int j
const LALVCSInfoList lalPulsarVCSInfoList
NULL-terminated list of VCS and build information for LALPulsar and its dependencies
#define STRING(a)
#define fprintf
SFTVector * extract_one_sft(const SFTCatalog *full_catalog, const LIGOTimeGPS starttime, const REAL8 f_min, const REAL8 f_max)
Definition: fscanutils.c:31
unsigned char BOOLEAN
double REAL8
#define XLAL_INIT_DECL(var,...)
char CHAR
uint32_t UINT4
int32_t INT4
float REAL4
char char * XLALStringDuplicate(const char *s)
void LogPrintf(LogLevel_t, const char *format,...) _LAL_GCC_PRINTF_FORMAT_(2
LOG_CRITICAL
LOG_NORMAL
void XLALDestroySFTVector(SFTVector *vect)
XLAL interface to destroy an SFTVector.
Definition: SFTtypes.c:300
void XLALDestroySFTCatalog(SFTCatalog *catalog)
Free an 'SFT-catalogue'.
Definition: SFTcatalog.c:329
SFTCatalog * XLALSFTdataFind(const CHAR *file_pattern, const SFTConstraints *constraints)
Find the list of SFTs matching the file_pattern and satisfying the given constraints,...
Definition: SFTcatalog.c:71
const char * lalUserVarHelpBrief
int XLALUserVarReadAllInput(BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list)
void XLALDestroyUserVars(void)
const char * lalUserVarHelpDescription
#define XLALRegisterNamedUvar(cvar, name, type, option, category,...)
int XLALUserVarWasSet(const void *cvar)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
COMPLEX16Vector * XLALCreateCOMPLEX16Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
void XLALDestroyCOMPLEX16Vector(COMPLEX16Vector *vector)
#define XLAL_CHECK_MAIN(assertion,...)
#define XLAL_ERROR_MAIN(...)
#define XLAL_TRY(statement, errnum)
XLAL_SUCCESS
XLAL_EUSR0
XLAL_EFUNC
XLAL_EIO
XLAL_EINVAL
XLAL_EFAILED
int deltaF
int main(int argc, char **argv)
COMPLEX16 * data
COMPLEX8Sequence * data
A vector of COMPLEX8FrequencySeries.
COMPLEX8FrequencySeries * data
Pointer to the data array.
COMPLEX8 * data
INT4 gpsNanoSeconds
REAL8 * data
An "SFT-catalogue": a vector of SFTdescriptors, as returned by XLALSFTdataFind()
Definition: SFTfileIO.h:238
SFTDescriptor * data
array of data-entries describing matched SFTs
Definition: SFTfileIO.h:243
UINT4 length
number of SFTs in catalog
Definition: SFTfileIO.h:242
'Constraints' for SFT-matching: which detector, within which time-stretch and which timestamps exactl...
Definition: SFTfileIO.h:212
SFTtype header
SFT-header info.
Definition: SFTfileIO.h:228
double f_min
double f_max