void getMetric( LALStatus *stat, REAL4 g[3], REAL4 x[2], void *params ) { PtoleMetricIn *patch = params; /* avoid pesky gcc warnings */ REAL8Vector *metric = NULL; /* for output of metric */ /* Set up shop. */ INITSTATUS(stat); ATTATCHSTATUSPTR( stat ); TRY( LALDCreateVector( stat->statusPtr, &metric, 6 ), stat ); /* Translate input. */ patch->position.longitude = x[1]; patch->position.latitude = x[0]; /* Call the real metric function. */ LALPtoleMetric( stat->statusPtr, metric, patch ); BEGINFAIL( stat ) TRY( LALDDestroyVector( stat->statusPtr, &metric ), stat ); ENDFAIL( stat ); LALProjectMetric( stat->statusPtr, metric, 0 ); BEGINFAIL( stat ) TRY( LALDDestroyVector( stat->statusPtr, &metric ), stat ); ENDFAIL( stat ); /* Translate output. */ g[1] = metric->data[2]; g[0] = metric->data[5]; g[2] = metric->data[4]; /* Clean up and leave. */ TRY( LALDDestroyVector( stat->statusPtr, &metric ), stat ); DETATCHSTATUSPTR( stat ); RETURN( stat ); } /* getMetric() */
/** * \brief Unified "wrapper" to provide a uniform interface to LALPtoleMetric() and LALCoherentMetric(). * \author Reinhard Prix * * The parameter structure of LALPtoleMetric() was used, because it's more compact. */ void LALPulsarMetric ( LALStatus *stat, REAL8Vector **metric, PtoleMetricIn *input ) { MetricParamStruc params = empty_MetricParamStruc; PulsarTimesParamStruc spinParams = empty_PulsarTimesParamStruc; PulsarTimesParamStruc baryParams = empty_PulsarTimesParamStruc; PulsarTimesParamStruc compParams = empty_PulsarTimesParamStruc; REAL8Vector *lambda = NULL; UINT4 i, nSpin, dim; INITSTATUS(stat); ATTATCHSTATUSPTR (stat); ASSERT ( input, stat, PTOLEMETRICH_ENULL, PTOLEMETRICH_MSGENULL ); ASSERT ( metric != NULL, stat, PTOLEMETRICH_ENULL, PTOLEMETRICH_MSGENULL ); ASSERT ( *metric == NULL, stat, PTOLEMETRICH_ENONULL, PTOLEMETRICH_MSGENONULL ); if (input->metricType == LAL_PMETRIC_COH_EPHEM) { ASSERT ( input->ephemeris != NULL, stat, PTOLEMETRICH_ENULL, PTOLEMETRICH_MSGENULL); } if ( input->spindown ) nSpin = input->spindown->length; else nSpin = 0; /* allocate the output-metric */ dim = 3 + nSpin; /* dimensionality of parameter-space: Alpha,Delta,f + spindowns */ TRY ( LALDCreateVector (stat->statusPtr, metric, dim * (dim+1)/2), stat); switch (input->metricType) { case LAL_PMETRIC_COH_PTOLE_ANALYTIC: /* use Ben&Ian's analytic ptolemaic metric */ LALPtoleMetric (stat->statusPtr, *metric, input); BEGINFAIL(stat) { LALDDestroyVector (stat->statusPtr, metric); }ENDFAIL(stat); break; case LAL_PMETRIC_COH_PTOLE_NUMERIC: /* use CoherentMetric + Ptolemaic timing */ case LAL_PMETRIC_COH_EPHEM: /* use CoherentMetric + ephemeris timing */ /* Set up constant parameters for barycentre transformation. */ baryParams.epoch = input->epoch; baryParams.t0 = 0; /* FIXME: should be redundant now, with Detector passed */ baryParams.latitude = input->site->frDetector.vertexLatitudeRadians; baryParams.longitude = input->site->frDetector.vertexLongitudeRadians; baryParams.site = input->site; LALGetEarthTimes( stat->statusPtr, &baryParams ); BEGINFAIL(stat) { LALDDestroyVector (stat->statusPtr, metric); }ENDFAIL(stat); /* set timing-function for earth-motion: either ptolemaic or ephemeris */ if (input->metricType == LAL_PMETRIC_COH_PTOLE_NUMERIC) { baryParams.t1 = LALTBaryPtolemaic; baryParams.dt1 = LALDTBaryPtolemaic; } else /* use precise ephemeris-timing */ { baryParams.t1 = LALTEphemeris; /* LAL-bug: fix type of LALTEphemeris! */ baryParams.dt1 = LALDTEphemeris; baryParams.ephemeris = input->ephemeris; } /* Set up input structure for CoherentMetric() */ if (nSpin) { /* Set up constant parameters for spindown transformation. */ spinParams.epoch = input->epoch; spinParams.t0 = 0; /* Set up constant parameters for composed transformation. */ compParams.epoch = input->epoch; compParams.t1 = baryParams.t1; compParams.dt1 = baryParams.dt1; compParams.t2 = LALTSpin; compParams.dt2 = LALDTSpin; compParams.constants1 = &baryParams; compParams.constants2 = &spinParams; compParams.nArgs = 2; params.dtCanon = LALDTComp; params.constants = &compParams; } else /* simple case: just account for earth motion */ { params.dtCanon = baryParams.dt1; params.constants = &baryParams; } params.start = 0; params.deltaT = (REAL8) input->duration; params.n = 1; /* only 1 stack */ params.errors = 0; /* Set up the parameter list. */ LALDCreateVector( stat->statusPtr, &lambda, nSpin + 2 + 1 ); BEGINFAIL(stat) { LALDDestroyVector (stat->statusPtr, metric); }ENDFAIL(stat); lambda->data[0] = (REAL8) input->maxFreq; lambda->data[1] = (REAL8) input->position.longitude; /* Alpha */ lambda->data[2] = (REAL8) input->position.latitude; /* Delta */ if ( nSpin ) { for (i=0; i < nSpin; i++) lambda->data[3 + i] = (REAL8) input->spindown->data[i]; } /* _finally_ we can call the metric */ LALCoherentMetric( stat->statusPtr, *metric, lambda, ¶ms ); BEGINFAIL(stat) { LALDDestroyVector (stat->statusPtr, metric); LALDDestroyVector( stat->statusPtr, &lambda ); }ENDFAIL(stat); LALDDestroyVector( stat->statusPtr, &lambda ); BEGINFAIL(stat) { LALDDestroyVector (stat->statusPtr, metric); }ENDFAIL(stat); break; default: XLALPrintError ("Unknown metric type `%d`\n", input->metricType); ABORT (stat, PTOLEMETRICH_EMETRIC, PTOLEMETRICH_MSGEMETRIC); break; } /* switch type */ DETATCHSTATUSPTR (stat); RETURN (stat); } /* LALPulsarMetric() */
int main( int argc, char *argv[] ) { static LALStatus status; /* Status structure */ PtoleMetricIn in; /* PtoleMetric() input structure */ REAL8 mismatch; /* mismatch threshold of mesh */ REAL8Vector *metric; /* Parameter-space metric */ int j, k; /* Parameter-space indices */ int opt; /* Command-line option. */ BOOLEAN grace; /* Whether or not we use xmgrace */ BOOLEAN nongrace; /* Whether or not to output data to file*/ int ra, dec, i; /* Loop variables for xmgrace option */ FILE *pvc = NULL; /* Temporary file for xmgrace option */ FILE *fnongrace = NULL;/* File contaning ellipse coordinates */ int metric_code; /* Which metric code to use: */ /* 1 = Ptolemetric */ /* 2 = CoherentMetric + DTBarycenter */ /* 3 = CoherentMetric + DTEphemeris */ REAL8Vector *tevlambda; /* (f, a, d, ...) for CoherentMetric */ MetricParamStruc tevparam; /* Input structure for CoherentMetric */ PulsarTimesParamStruc tevpulse; /* Input structure for CoherentMetric */ /* (this is a member of tevparam) */ EphemerisData *eph; /* To store ephemeris data */ int detector; /* Which detector to use: */ /* 1 = Hanford, 2 = Livingston, */ /* 3 = Virgo, 4 = GEO, 5 = TAMA */ REAL8 ra_point; /* RA at which metric is evaluated */ REAL8 dec_point; /* dec at which metric is evaluated */ float a,b,c,d,e,f; /* To input point in standard format */ int ra_min, ra_max; /* Min and max RA for ellipse plot */ int dec_min, dec_max; /* Min and max dec for ellipse plot */ float c_ellipse; /* Centers of ellipses */ float r_ellipse; /* Radii of ellipses */ REAL8 determinant; /* Determinant of projected metric */ REAL4 f0; /* carrier frequency */ UINT2 numSpindown; /* Number of spindowns */ char earth[] = TEST_DATA_DIR "earth00-19-DE405.dat.gz"; char sun[] = TEST_DATA_DIR "sun00-19-DE405.dat.gz"; /* Defaults that can be overwritten: */ metric_code = 1; in.epoch.gpsSeconds = tevpulse.epoch.gpsSeconds = 731265908; in.epoch.gpsNanoSeconds = tevpulse.epoch.gpsNanoSeconds = 0.0; mismatch = 0.02; nongrace = 0; in.duration = tevparam.deltaT = DEFAULT_DURATION; grace = 0; detector = 4; ra_point = (24.1/60)*LAL_PI_180; /* 47 Tuc */ dec_point = -(72+5./60)*LAL_PI_180; ra_min = 0; ra_max = 90; dec_min = 0; dec_max = 85; f0 = 1000; numSpindown = 0; /* Parse options. */ while ((opt = LALgetopt( argc, argv, "a:b:c:d:ef:l:m:n:pt:s:x" )) != -1) { switch (opt) { case 'a': metric_code = atoi( LALoptarg ); break; case 'b': in.epoch.gpsSeconds = tevpulse.epoch.gpsSeconds = atoi( LALoptarg ); break; case 'c': if( sscanf( LALoptarg, "%f:%f:%f:%f:%f:%f", &a, &b, &c, &d, &e, &f ) != 6) { fprintf( stderr, "coordinates should be hh:mm:ss:dd:mm:ss\n" ); } ra_point = (15*a+b/4+c/240)*LAL_PI_180; dec_point = (d+e/60+f/3600)*LAL_PI_180; break; case 'd': detector = atoi( LALoptarg ); break; case 'e': break; case 'f': f0 = atof( LALoptarg ); break; case 'l': if( sscanf( LALoptarg, "%d:%d:%d:%d", &ra_min, &ra_max, &dec_min, &dec_max) != 4) { fprintf( stderr, "coordinates should be ra_min, ra_max, dec_min, dec_max all in degrees" ); } break; case 'm': mismatch = atof( LALoptarg ); break; case 'n': numSpindown = atoi( LALoptarg ); break; case 'p': nongrace = 1; break; case 's': break; case 't': in.duration = tevparam.deltaT = atof( LALoptarg ); break; case 'x': grace = 1; break; } } /* Allocate storage. */ metric = NULL; LALDCreateVector( &status, &metric, (3+numSpindown)*(4+numSpindown)/2 ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } tevlambda = NULL; LALDCreateVector( &status, &tevlambda, 3+numSpindown ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } /* Position in parameter space (sky, frequency, spindowns) */ in.position.system = COORDINATESYSTEM_EQUATORIAL; in.position.longitude = tevlambda->data[1] = ra_point; in.position.latitude = tevlambda->data[2] = dec_point; in.maxFreq = tevlambda->data[0] = f0; in.spindown = NULL; if( numSpindown > 0 ) { LALCreateVector( &status, &(in.spindown), numSpindown ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } for( i=0; i<numSpindown; i++ ) { in.spindown->data[i] = 0; tevlambda->data[i+3] = 0; } } /* Detector site */ if(detector==1) tevpulse.site = &lalCachedDetectors[LALDetectorIndexLHODIFF]; if(detector==2) tevpulse.site = &lalCachedDetectors[LALDetectorIndexLLODIFF]; if(detector==3) tevpulse.site = &lalCachedDetectors[LALDetectorIndexVIRGODIFF]; if(detector==4) tevpulse.site = &lalCachedDetectors[LALDetectorIndexGEO600DIFF]; if(detector==5) tevpulse.site = &lalCachedDetectors[LALDetectorIndexTAMA300DIFF]; in.site = tevpulse.site; tevpulse.latitude = in.site->frDetector.vertexLatitudeRadians; tevpulse.longitude = in.site->frDetector.vertexLongitudeRadians; /* CoherentMetric constants */ tevparam.constants = &tevpulse; tevparam.n = 1; tevparam.errors = 0; tevparam.start = 0; /* start time relative to epoch */ tevpulse.t0 = 0.0; /* spindown definition time relative to epoch */ /* Fill in the fields tevpulse.tMidnight & tevpulse.tAutumn: */ LALGetEarthTimes( &status, &tevpulse ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } /* Read in ephemeris data from files: */ eph = (EphemerisData *)LALMalloc(sizeof(EphemerisData)); eph->ephiles.earthEphemeris = earth; eph->ephiles.sunEphemeris = sun; LALInitBarycenter( &status, eph ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } tevpulse.ephemeris = eph; /* Choose CoherentMetric timing function */ if( metric_code == 2 ) { tevpulse.t1 = LALTBaryPtolemaic; tevpulse.dt1 = LALDTBaryPtolemaic; } if( metric_code == 3 ) { tevpulse.t1 = LALTEphemeris; tevpulse.dt1 = LALDTEphemeris; } tevpulse.t2 = LALTSpin; tevpulse.dt2 = LALDTSpin; tevpulse.constants1 = &tevpulse; tevpulse.constants2 = &tevpulse; tevpulse.nArgs = 2; if( numSpindown > 0 ) { tevparam.dtCanon = LALDTComp; } else { if( metric_code == 2 ) tevparam.dtCanon = LALDTBaryPtolemaic; if( metric_code == 3 ) tevparam.dtCanon = LALDTEphemeris; } /* Evaluate metric components. */ if(metric_code==1) { LALPtoleMetric( &status, metric, &in ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } } if(metric_code==2 || metric_code==3) { LALCoherentMetric( &status, metric, tevlambda, &tevparam ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } } /* Print metric. */ printf("\nmetric (f0, alpha, delta, ...) at the requested point\n"); for (j=0; j<=2+numSpindown; j++) { for (k=0; k<=j; k++) printf( " %+.4e", metric->data[k+j*(j+1)/2] ); printf("\n"); } /* Print determinants. */ determinant = metric->data[5]*metric->data[2] - pow(metric->data[4],2); printf( "\nSky-determinant %e\n", determinant ); if( numSpindown == 1 ) { determinant = metric->data[2] * metric->data[5] * metric->data[9] - metric->data[2] * metric->data[8] * metric->data[8] + metric->data[4] * metric->data[8] * metric->data[7] - metric->data[4] * metric->data[4] * metric->data[9] + metric->data[7] * metric->data[4] * metric->data[8] - metric->data[7] * metric->data[7] * metric->data[5]; printf( "S&S determinant %e\n", determinant ); } /* Project carrier frequency out of metric. */ LALProjectMetric( &status, metric, 0 ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } /* Print projected metric. */ printf("\nf-projected metric (alpha, delta, ...) at the requested point\n"); for (j=1; j<=2+numSpindown; j++) { for (k=1; k<=j; k++) printf( " %+.4e", metric->data[k+j*(j+1)/2] ); printf( "\n" ); } /* Print determinants. */ determinant = metric->data[5]*metric->data[2] - pow(metric->data[4],2); printf( "\nSky-determinant %e\n", determinant ); if( numSpindown == 1 ) { determinant = metric->data[2] * metric->data[5] * metric->data[9] - metric->data[2] * metric->data[8] * metric->data[8] + metric->data[4] * metric->data[8] * metric->data[7] - metric->data[4] * metric->data[4] * metric->data[9] + metric->data[7] * metric->data[4] * metric->data[8] - metric->data[7] * metric->data[7] * metric->data[5]; printf( "S&S determinant %e\n", determinant ); } /* Here is the code that uses xmgrace with the -x option, */ /* and outputs data to a file with the -t option. */ if (grace || nongrace) { /* Take care of preliminaries. */ if(grace) { pvc = popen( "xmgrace -pipe", "w" ); if( !pvc ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESYS ); return GENERALMETRICTESTC_ESYS; } fprintf( pvc, "@xaxis label \"Right ascension (degrees)\"\n" ); fprintf( pvc, "@yaxis label \"Declination (degrees)\"\n" ); } if(nongrace) { fnongrace = fopen( "nongrace.data", "w" ); if( !fnongrace ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESYS ); return GENERALMETRICTESTC_ESYS; } } /* Step around the sky: a grid in ra and dec. */ j = 0; for (dec=dec_max; dec>=dec_min; dec-=10) { for (ra=ra_min; ra<=ra_max; ra+=15) { REAL8 gaa, gad, gdd, angle, smaj, smin; /* Get the metric at this ra, dec. */ in.position.longitude = tevlambda->data[1] = ra*LAL_PI_180; in.position.latitude = tevlambda->data[2] = dec*LAL_PI_180; /* Evaluate metric: */ if(metric_code==1) { LALPtoleMetric( &status, metric, &in ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } } if(metric_code==2 || metric_code==3) { LALCoherentMetric( &status, metric, tevlambda, &tevparam ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } } /* Project metric: */ LALProjectMetric( &status, metric, 0 ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGESUB ); return GENERALMETRICTESTC_ESUB; } determinant = metric->data[5]*metric->data[2]-pow(metric->data[4],2.0); if(determinant < 0.0) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMET ); return GENERALMETRICTESTC_EMET; } /* Rename \gamma_{\alpha\alpha}. */ gaa = metric->data[2]; /* Rename \gamma_{\alpha\delta}. */ gad = metric->data[4]; /* Rename \gamma_{\delta\delta}. */ gdd = metric->data[5]; /* Semiminor axis from larger eigenvalue of metric. */ smin = gaa+gdd + sqrt( pow(gaa-gdd,2) + pow(2*gad,2) ); smin = sqrt(2*mismatch/smin); /* Semiminor axis from smaller eigenvalue of metric. */ smaj = gaa+gdd - sqrt( pow(gaa-gdd,2) + pow(2*gad,2) ); /*printf("ra = %d, dec = %d, temp = %g\n", ra, dec, smaj);*/ smaj = sqrt(2*mismatch/smaj); /* Angle of semimajor axis with "horizontal" (equator). */ angle = atan2( gad, mismatch/smaj/smaj-gdd ); if (angle <= -LAL_PI_2) angle += LAL_PI; if (angle > LAL_PI_2) angle -= LAL_PI; if(grace) { /* Print set header. */ fprintf( pvc, "@s%d color (0,0,0)\n", j ); fprintf( pvc, "@target G0.S%d\n@type xy\n", j++ ); /* Print center of patch. */ fprintf( pvc, "%16.8g %16.8g\n", (float)ra, (float)dec ); } if(nongrace) /* Print center of patch. */ fprintf( fnongrace, "%16.8g %16.8g\n", (float)ra, (float)dec ); /* Loop around patch ellipse. */ for (i=0; i<=SPOKES; i++) { c_ellipse = LAL_TWOPI*i/SPOKES; r_ellipse = MAGNIFY*LAL_180_PI*smaj*smin / sqrt( pow(smaj*sin(c_ellipse),2) + pow(smin*cos(c_ellipse),2) ); if(grace) fprintf( pvc, "%e %e\n", ra+r_ellipse*cos(angle-c_ellipse), dec+r_ellipse*sin(angle-c_ellipse) ); if(nongrace) fprintf( fnongrace, "%e %e\n", ra+r_ellipse*cos(angle-c_ellipse), dec+r_ellipse*sin(angle-c_ellipse) ); } /* for (a...) */ } /* for (ra...) */ } /* for (dec...) */ if(grace) fclose( pvc ); if(nongrace) fclose( fnongrace ); } /* if (grace || nongrace) */ printf("\nCleaning up and leaving...\n"); LALFree( eph->ephemE ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } LALFree( eph->ephemS ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } LALFree( eph ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } LALDDestroyVector( &status, &metric ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } LALDDestroyVector( &status, &tevlambda ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } if( in.spindown ) LALDestroyVector( &status, &(in.spindown) ); if( status.statusCode ) { printf( "%s line %d: %s\n", __FILE__, __LINE__, GENERALMETRICTESTC_MSGEMEM ); return GENERALMETRICTESTC_EMEM; } LALCheckMemoryLeaks(); return 0; } /* main() */