Changeset 38986 for trunk/Ohana/src/relastro/src/UpdateObjects.c
- Timestamp:
- Oct 27, 2015, 4:49:06 PM (11 years ago)
- Location:
- trunk/Ohana
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
src/relastro/src/UpdateObjects.c (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana
-
Property svn:mergeinfo
set to
/branches/eam_branches/ipp-20150625/Ohana merged eligible
-
Property svn:mergeinfo
set to
-
trunk/Ohana/src/relastro/src/UpdateObjects.c
r37807 r38986 2 2 # define PAR_TOOFEW 5 3 3 4 int UpdateObjects_Chips (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats, int i, off_t m, int applyGalaxyOffset); 5 int UpdateObjects_Stack (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats); 6 7 static off_t Nmax; 8 static double *X, *dX; 9 static double *Y, *dY; 10 static double *R, *dR; 11 static double *D, *dD; 12 static double *pX; 13 static double *pY; 14 static double *T; 15 static double *dT; 16 static double *C_blue; 17 static double *C_red; 18 19 static Coords coords; 20 21 static time_t T2000; 22 23 void initFitStats (FitStats *fitStats) { 24 fitStats->Nave = 0; 25 fitStats->Npm = 0; 26 fitStats->Npar = 0; 27 fitStats->Nskip = 0; 28 fitStats->Noffset = 0; 29 return; 30 } 31 32 void sumFitStats (FitStats *srcFitStats, FitStats *tgtFitStats) { 33 tgtFitStats->Nave += srcFitStats->Nave ; 34 tgtFitStats->Npm += srcFitStats->Npm ; 35 tgtFitStats->Npar += srcFitStats->Npar ; 36 tgtFitStats->Nskip += srcFitStats->Nskip ; 37 tgtFitStats->Noffset += srcFitStats->Noffset ; 38 return; 39 } 40 41 void initObjectData (Catalog *catalog, int Ncatalog) { 42 43 off_t i, j; 44 45 Nmax = 0; 46 for (i = 0; i < Ncatalog; i++) { 47 for (j = 0; j < catalog[i].Naverage; j++) { 48 Nmax = MAX (Nmax, catalog[i].average[j].Nmeasure); 49 } 50 } 51 52 ALLOCATE (R, double, MAX (1, Nmax)); 53 ALLOCATE (D, double, MAX (1, Nmax)); 54 ALLOCATE (T, double, MAX (1, Nmax)); 55 ALLOCATE (X, double, MAX (1, Nmax)); 56 ALLOCATE (Y, double, MAX (1, Nmax)); 57 58 ALLOCATE (dR, double, MAX (1, Nmax)); 59 ALLOCATE (dD, double, MAX (1, Nmax)); 60 ALLOCATE (dT, double, MAX (1, Nmax)); 61 ALLOCATE (dX, double, MAX (1, Nmax)); 62 ALLOCATE (dY, double, MAX (1, Nmax)); 63 64 ALLOCATE (pX, double, MAX (1, Nmax)); 65 ALLOCATE (pY, double, MAX (1, Nmax)); 66 67 ALLOCATE (C_blue, double, MAX (1, Nmax)); 68 ALLOCATE (C_red, double, MAX (1, Nmax)); 69 70 /* project coordinates to a plane centered on the object with units of arcsec */ 71 InitCoords (&coords, "DEC--SIN"); 72 coords.cdelt1 = coords.cdelt2 = 1.0 / 3600.0; 73 74 // use J2000 as a reference time 75 T2000 = ohana_date_to_sec ("2000/01/01,12:00:00"); 76 } 77 78 void freeObjectData () { 79 80 free (R); 81 free (D); 82 free (T); 83 free (X); 84 free (Y); 85 86 free (dR); 87 free (dD); 88 free (dT); 89 free (dX); 90 free (dY); 91 92 free (pX); 93 free (pY); 94 95 free (C_blue); 96 free (C_red); 97 } 4 int DumpObjectsWith2MASS (Catalog *catalog, int Ncatalog); 98 5 99 6 // This function operates on both Measure and MeasureTiny. In the big stages, this should 100 7 // be called with just MeasureTiny set and Measure == NULL 101 8 int UpdateObjects (Catalog *catalog, int Ncatalog, int Nloop) { 102 103 initObjectData (catalog, Ncatalog);104 9 105 10 // XXX in the future, use catalog[0].Nsecfilt only? allow catalogs to have variable Nsecfilt? … … 109 14 } 110 15 111 FitStats sumStatsChips; initFitStats (&sumStatsChips); 112 FitStats sumStatsStack; initFitStats (&sumStatsStack); 16 int NmeasureMax = CatalogMaxNmeasure (catalog, Ncatalog); 17 18 // allocate summary stats with Nmax = 0, Nboot = 0 19 FitStats *sumStatsChips = FitStatsInit (0, 0); 20 FitStats *sumStatsStack = FitStatsInit (0, 0); 21 22 FitStats *fitStatsChips = FitStatsInit (NmeasureMax, N_BOOTSTRAP_SAMPLES); 23 FitStats *fitStatsStack = FitStatsInit (NmeasureMax, N_BOOTSTRAP_SAMPLES); 24 25 AstromErrorSetLoop (Nloop, FALSE); 113 26 114 27 int i; … … 117 30 if (VERBOSE2) fprintf (stderr, "astrometrize catalog %d : "OFF_T_FMT" ave, "OFF_T_FMT" meas\n", i, catalog[i].Naverage, catalog[i].Nmeasure); 118 31 119 FitStats fitStatsChips; initFitStats (&fitStatsChips);120 FitStats fitStatsStack; initFitStats (&fitStatsStack);32 FitStatsReset (fitStatsChips); 33 FitStatsReset (fitStatsStack); 121 34 122 35 off_t j; … … 129 42 SecFilt *secfilt = &catalog[i].secfilt[j*Nsecfilt]; 130 43 131 UpdateObjects_Stack(average, secfilt, measure, measureBig, Nsecfilt, &fitStatsStack); 132 UpdateObjects_Chips(average, secfilt, measure, measureBig, Nsecfilt, &fitStatsChips, i, m, Nloop); 133 } 134 if (VERBOSE2) fprintf (stderr, "catalog %d : chips "OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par : Nskip "OFF_T_FMT", Noffset "OFF_T_FMT"\n", i, fitStatsChips.Nave, fitStatsChips.Npm, fitStatsChips.Npar, fitStatsChips.Nskip, fitStatsChips.Noffset); 135 if (VERBOSE2) fprintf (stderr, "catalog %d : stack "OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par : Nskip "OFF_T_FMT", Noffset "OFF_T_FMT"\n", i, fitStatsStack.Nave, fitStatsStack.Npm, fitStatsStack.Npar, fitStatsStack.Nskip, fitStatsStack.Noffset); 136 sumFitStats (&fitStatsChips, &sumStatsChips); 137 sumFitStats (&fitStatsStack, &sumStatsStack); 138 } 139 freeObjectData (); 140 141 if (VERBOSE && (Ncatalog > 1)) fprintf (stderr, "fitted "OFF_T_FMT" objects ("OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par), skipped "OFF_T_FMT", "OFF_T_FMT" have too large an offset\n", (sumStatsChips.Nave + sumStatsChips.Npm + sumStatsChips.Npar), sumStatsChips.Nave, sumStatsChips.Npm, sumStatsChips.Npar, sumStatsChips.Nskip, sumStatsChips.Noffset); 142 if (VERBOSE && (Ncatalog > 1)) fprintf (stderr, "fitted "OFF_T_FMT" objects ("OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par), skipped "OFF_T_FMT", "OFF_T_FMT" have too large an offset\n", (sumStatsStack.Nave + sumStatsStack.Npm + sumStatsStack.Npar), sumStatsStack.Nave, sumStatsStack.Npm, sumStatsStack.Npar, sumStatsStack.Nskip, sumStatsStack.Noffset); 44 UpdateObjects_Stack(average, secfilt, measure, measureBig, Nsecfilt, fitStatsStack); 45 UpdateObjects_Chips(average, secfilt, measure, measureBig, Nsecfilt, fitStatsChips, i, m); 46 } 47 if (VERBOSE2) fprintf (stderr, "catalog %d : chips "OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par : Nskip "OFF_T_FMT", Noffset "OFF_T_FMT"\n", i, fitStatsChips->Nave, fitStatsChips->Npm, fitStatsChips->Npar, fitStatsChips->Nskip, fitStatsChips->Noffset); 48 if (VERBOSE2) fprintf (stderr, "catalog %d : stack "OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par : Nskip "OFF_T_FMT", Noffset "OFF_T_FMT"\n", i, fitStatsStack->Nave, fitStatsStack->Npm, fitStatsStack->Npar, fitStatsStack->Nskip, fitStatsStack->Noffset); 49 FitStatsSum (fitStatsChips, sumStatsChips); 50 FitStatsSum (fitStatsStack, sumStatsStack); 51 } 52 53 // DumpObjectsWith2MASS (catalog, Ncatalog); 54 55 FitStatsFree (fitStatsChips); 56 FitStatsFree (fitStatsStack); 57 58 if (VERBOSE && (Ncatalog > 1)) fprintf (stderr, "fitted "OFF_T_FMT" objects ("OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par), skipped "OFF_T_FMT", "OFF_T_FMT" have too large an offset\n", (sumStatsChips->Nave + sumStatsChips->Npm + sumStatsChips->Npar), sumStatsChips->Nave, sumStatsChips->Npm, sumStatsChips->Npar, sumStatsChips->Nskip, sumStatsChips->Noffset); 59 if (VERBOSE && (Ncatalog > 1)) fprintf (stderr, "fitted "OFF_T_FMT" objects ("OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par), skipped "OFF_T_FMT", "OFF_T_FMT" have too large an offset\n", (sumStatsStack->Nave + sumStatsStack->Npm + sumStatsStack->Npar), sumStatsStack->Nave, sumStatsStack->Npm, sumStatsStack->Npar, sumStatsStack->Nskip, sumStatsStack->Noffset); 60 61 FitStatsFree (sumStatsChips); 62 FitStatsFree (sumStatsStack); 63 143 64 return (TRUE); 144 65 } … … 146 67 // This function operates on both Measure and MeasureTiny. In the big stages, this should 147 68 // be called with just MeasureTiny set and Measure == NULL 148 int UpdateObjects_Chips (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats, int i, off_t m, int applyGalaxyOffset) { 149 150 int setRefColor = areImagesMatched(); 69 int DumpObjectsWith2MASS (Catalog *catalog, int Ncatalog) { 70 71 int i; 72 for (i = 0; i < Ncatalog; i++) { 73 off_t j; 74 for (j = 0; j < catalog[i].Naverage; j++) { 75 /* calculate the average value of R,D for a single star */ 76 off_t m = catalog[i].average[j].measureOffset; 77 78 off_t k; 79 for (k = 0; k < catalog[i].average[j].Nmeasure; k++) { 80 MeasureTiny *measure = &catalog[i].measureT[m+k]; 81 if (measure->dbFlags & ID_MEAS_OBJECT_HAS_2MASS) { 82 fprintf (stderr, "0x%08x 0x%08x : %12.8f %12.8f %5d\n", catalog[i].average[j].objID, catalog[i].average[j].catID, measure->R, measure->D, measure->photcode); 83 } 84 } 85 } 86 } 87 return (TRUE); 88 } 89 90 // This function operates on both Measure and MeasureTiny. In the big stages, this should 91 // be called with just MeasureTiny set and Measure == NULL 92 int UpdateObjects_Chips (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats, int cat, off_t measOff) { 93 94 int k; 151 95 152 96 /* calculate the average value of R,D for a single star */ 153 97 154 PMFit fit; memset (&fit, 0, sizeof(fit));155 PMFit fitAve; memset (&fitAve, 0, sizeof(fitAve)); fitAve.chisq = NAN;156 PMFit fitPM; memset (&fitPM, 0, sizeof(fitPM)); fitPM.chisq = NAN;157 PMFit fitPAR; memset (&fitPAR, 0, sizeof(fitPAR)); fitPAR.chisq = NAN;98 FitAstromResult fitPos, fitPM, fitPar; 99 FitAstromResultInit (&fitPos); 100 FitAstromResultInit (&fitPM); 101 FitAstromResultInit (&fitPar); 158 102 159 103 // if we fail to fit the astrometry for some reason, we need to set/reset these … … 167 111 if (average[0].Nmeasure == 0) return TRUE; 168 112 169 int NcBlue = 0;170 int NcRed = 0;171 int N = 0;172 173 113 int mode = FIT_MODE; // start with the globally-defined fit mode 174 114 … … 177 117 XVERB |= (average[0].objID == OBJ_ID_DST) && (average[0].catID == CAT_ID_DST); 178 118 179 // find the basic properties of the detections for this object (Tmin, Tmax, Tmean) 180 off_t k; 181 for (k = 0; k < average[0].Nmeasure; k++) { 182 183 if (XVERB) { 184 char *date = ohana_sec_to_date (measure[k].t); 185 int dbFlagsBig = measureBig ? measureBig[k].dbFlags : 0; 186 fprintf (stderr, OFF_T_FMT" %f %f %s : 0x%08x : 0x%08x\n", k, measure[k].R, measure[k].D, date, measure[k].dbFlags, dbFlagsBig); 187 free (date); 188 } 189 190 // SKIP gpc1 stack data 191 if (isGPC1stack(measure[k].photcode)) continue; 192 193 // SKIP gpc1 forced-warp data 194 if (isGPC1warp(measure[k].photcode)) continue; 195 196 // reset the bit to note that a detection was used (or not) 197 measure[k].dbFlags &= ~ID_MEAS_USED_OBJ; 198 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_USED_OBJ; } 199 200 // does the measurement pass the supplied filtering constraints? 201 // MeasFilterTestTiny does not test psfQF 202 // exclude bad detections based on: photcodes, psfQF, time range, photflags & astromBadMask, mag_inst 203 int keepMeasure = measureBig ? MeasFilterTest(&measureBig[k], FALSE) : MeasFilterTestTiny(&measure[k], FALSE); 204 if (!keepMeasure) { 205 continue; 206 } 207 208 double Ri = getMeanR (&measure[k], average, secfilt); 209 double Di = getMeanD (&measure[k], average, secfilt); 210 211 // if we are correcting for the Galaxy Motion Model, only should apply it here 212 // (a) when we are working to correct the images (mean R,D assumed to be at J2000) and 213 // (b) if we think the measure R,D is already at the image epoch position 214 if (USE_GALAXY_MODEL && applyGalaxyOffset) { 215 Ri -= measure[k].RoffGAL / 3600.0; 216 Di -= measure[k].DoffGAL / 3600.0; 217 } 218 219 // XXX add in dR,dD GAL here 220 221 // mark (as POOR) any measurements which are deviant from the mean by > ExcludeBogusRadius 222 if (ExcludeBogus) { 223 coords.crval1 = average[0].R; 224 coords.crval2 = average[0].D; 225 double Xi, Yi; 226 RD_to_XY (&Xi, &Yi, Ri, Di, &coords); 227 double radius = hypot(Xi, Yi); 228 if (radius > ExcludeBogusRadius) { 229 measure[k].dbFlags |= ID_MEAS_POOR_ASTROM; 230 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_POOR_ASTROM; } 231 continue; 232 } 233 measure[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; 234 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; } 235 } 236 237 // outlier rejection 238 if (FALSE && FlagOutlier && (measure[k].dbFlags & ID_MEAS_POOR_ASTROM)) { 239 continue; 240 } 241 242 R[N] = Ri; 243 D[N] = Di; 244 245 // measure[k].t is UNIX seconds, T2000 is UNIX seconds for J2000. 246 // T[] is time in years since J2000 (jd = 2451545) 247 T[N] = (measure[k].t - T2000) / (86400*365.25) ; // time relative to J2000 in years 248 249 // dX, dY : error in arcsec -- 250 dX[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_RA); 251 dY[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_DEC); 252 253 // allow a given photcode or measurement to be 254 // ignored if the error is NAN (for photcode, set astromErrSys to NaN) 255 if (isnan(dX[N])) continue; 256 if (isnan(dY[N])) continue; 257 258 // add systematic error in quadrature, if desired 259 // only do this after the fit has converged (or you will never improve the poor images) 260 // if (INCLUDE_SYS_ERR) { 261 // float dRsys = FromShortPixels(measure[k].dRsys); 262 // dX[N] = hypot(dX[N], dRsys); 263 // dY[N] = hypot(dY[N], dRsys); 264 // } 265 266 // dX[N] = 0.1; 267 // dY[N] = 0.1; 268 269 dT[N] = measure[k].dt; 270 271 // XXX this is (slightly) inconsistent: dX,dY are the X and Y direction errors in 272 // arcseconds. dR, dD are the errors in those directions in degrees. IF we have 273 // non-circular errors (different values for X and Y), then dR and dD will be 274 // incorrect: they would need to be rotated to take out the position angle 275 dR[N] = dX[N] / 3600.0; 276 dD[N] = dY[N] / 3600.0; 277 278 if (setRefColor) { 279 float colorBlue = getColorBlue (m+k, i); 280 if (!isnan(colorBlue)) { 281 C_blue[NcBlue] = colorBlue; 282 NcBlue++; 283 } 284 float colorRed = getColorRed (m+k, i); 285 if (!isnan(colorRed)) { 286 C_red[NcRed] = colorRed; 287 NcRed++; 288 } 289 } 290 291 measure[k].dbFlags |= ID_MEAS_USED_OBJ; 292 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_USED_OBJ; } 293 294 N++; 295 } // loop over measurements : average[0].Nmeasure 296 297 if (N < 1) { 119 // select the measurements to be used in this analysis 120 UpdateObjects_SelectMeasures (fitStats, average, secfilt, measure, measureBig, FALSE); 121 122 // if there are no exposure detections, use the stack position 123 if (fitStats->Npoints < 1) { 298 124 if (isfinite(average[0].Rstk) && isfinite(average[0].Dstk)) { 299 125 average[0].R = average[0].Rstk; … … 301 127 average[0].dR = average[0].dRstk; 302 128 average[0].dD = average[0].dDstk; 129 average[0].flags |= ID_STACK_ASTROM; 303 130 } 304 131 return FALSE; 305 132 } 306 133 307 // if we have too few good detections for the desired fit, or too limited a 308 // baseline, use a fit with fewer parameters. XXX if we have too few measurements 309 // for even the average position, consider including the lower-quality detections? 310 311 // find Tmin & Tmax from the list of accepted measurements 312 double Tmean = 0.0; 313 double Tmin = T[0]; 314 double Tmax = T[0]; 315 for (k = 0; k < N; k++) { 316 Tmin = MIN(Tmin, T[k]); 317 Tmax = MAX(Tmax, T[k]); 318 Tmean += T[k]; 319 } 320 double Trange = Tmax - Tmin; 321 322 if (RELASTRO_OP == OP_HIGH_SPEED) { 323 Tmean = 0.5*(Tmax - Tmin); 324 } else { 325 Tmean /= (float) N; 326 } 327 328 /* we need to do the fit in a locally linear space; choose a ref coordinate */ 329 coords.crval1 = R[0]; 330 coords.crval2 = D[0]; 134 double Tmean, Trange, parRange; 135 FitAstromPoints_Project (fitStats, &Tmean, &Trange, &parRange); 331 136 332 137 // to judge the quality of the PM and PAR fits, we need to fit all three models and compare Chisq 333 138 334 // project all of the R,D coordinates to a plane centered on this coordinate. set 335 // the times to be relative to Tmean (this is required for parallax as well) 336 for (k = 0; k < N; k++) { 337 RD_to_XY (&X[k], &Y[k], R[k], D[k], &coords); 338 T[k] -= Tmean; 339 if (XVERB) { 340 fprintf (stderr, OFF_T_FMT" %f %f %f %f %f +/- %f %f\n", k, T[k], R[k], D[k], X[k], Y[k], dX[k], dY[k]); 341 } 342 } 139 // if we have too few good detections for the desired fit, or too limited a baseline, 140 // use a fit with fewer parameters. 343 141 344 142 // *** first fit for the proper motion (skip fit if Trange or Npts is too small) *** … … 346 144 if (Trange < PM_DT_MIN) { 347 145 mode = FIT_AVERAGE; 348 goto skipPM;349 } 350 if ( N<= PM_TOOFEW) {146 goto justPosition; 147 } 148 if (fitStats->Npoints <= PM_TOOFEW) { 351 149 mode = FIT_AVERAGE; 352 goto skipPM; 353 } 354 355 FitPM (&fitPM, X, dX, Y, dY, T, N, XVERB); 356 357 if (XVERB) fprintf (stderr, "fitted PM: %f - %f : %f %f : %f %f : %f vs %f\n", Tmin, Tmax, fitPM.Ro, fitPM.Do, fitPM.uR, fitPM.uD, fitPM.chisq, fitAve.chisq); 150 goto justPosition; 151 } 152 153 if (fitStats->NfitAlloc == 1) { 154 // if N_BOOTSTRAP_SAMPLES = 1, no bootstrap resampling: 155 FitPM (&fitPM, fitStats->fitdataPM, fitStats->points, fitStats->Npoints); 156 } else { 157 fitStats->Nfit = 0; 158 for (k = 0; k < fitStats->NfitAlloc; k++) { 159 BootstrapResample (fitStats->sample, fitStats->points, fitStats->Npoints); 160 if (!FitPM (&fitStats->fit[k], fitStats->fitdataPM, fitStats->sample, fitStats->Npoints)) continue; 161 fitStats->Nfit ++; 162 } 163 BootstrapRobustStats (&fitPM, fitStats->fit, fitStats->Nfit, FIT_RESULT_RA); 164 BootstrapRobustStats (&fitPM, fitStats->fit, fitStats->Nfit, FIT_RESULT_DEC); 165 BootstrapRobustStats (&fitPM, fitStats->fit, fitStats->Nfit, FIT_RESULT_uR); 166 BootstrapRobustStats (&fitPM, fitStats->fit, fitStats->Nfit, FIT_RESULT_uD); 167 } 168 FitAstromSetChisq (&fitPM, fitStats->points, fitStats->Npoints, FIT_PM_ONLY); 358 169 359 170 // project Ro, Do back to RA,DEC 360 XY_to_RD (&fitPM.Ro, &fitPM.Do, fitPM.Ro, fitPM.Do, &coords); 361 if (XVERB) fprintf (stderr, "project: %f %f : %f %f : %f\n", fitPM.Ro, fitPM.Do, fitPM.uR, fitPM.uD, fitPM.p); 171 XY_to_RD (&fitPM.Ro, &fitPM.Do, fitPM.Ro, fitPM.Do, &fitStats->coords); 362 172 if (fabs(fitPM.Ro) < 0.01) fprintf (stderr, "watch out for 0,360 boundary\n"); 363 // XXX : does this make sense at 0,360 boundary?364 173 365 174 fitPM.p = fitPM.dp = 0.0; … … 374 183 } 375 184 376 skipPM:377 185 // fit the parallax + proper-motion model 378 186 // NOTE : we only fit PAR if we have already fitted for proper motion. if we do not fit PM or we fail 379 187 // to fit PM, we do not attempt PAR. thus failure to fit PAR falls back to PM-only 380 188 if (mode == FIT_PM_AND_PAR) { 381 if (Trange < PM_DT_MIN) {382 mode = FIT_PM_ONLY;383 goto skipPAR;384 }385 if (N <= PAR_TOOFEW) {386 mode = FIT_PM_ONLY;387 goto skipPAR;388 }389 float pXmin = +2.0;390 float pXmax = -2.0;391 float pYmin = +2.0;392 float pYmax = -2.0;393 for (k = 0; k < N; k++) {394 ParFactor (&pX[k], &pY[k], R[k], D[k], T[k], Tmean);395 pXmin = MIN (pXmin, pX[k]);396 pXmax = MAX (pXmax, pX[k]);397 pYmin = MIN (pYmin, pY[k]);398 pYmax = MAX (pYmax, pY[k]);399 }400 float dXRange = pXmax - pXmin;401 float dYRange = pYmax - pYmin;402 float parRange = hypot (dXRange, dYRange);403 404 189 if (parRange < PAR_FACTOR_MIN) { 405 190 mode = FIT_PM_ONLY; 406 goto skipPAR; 407 } 408 409 FitPMandPar (&fitPAR, X, dX, Y, dY, T, pX, pY, N, XVERB); 410 if (XVERB) fprintf (stderr, "fitted PM+PAR: %f - %f : %f %f : %f %f : %f %f : %f vs %f vs %f\n", Tmin, Tmax, fitPAR.Ro, fitPAR.Do, fitPAR.uR, fitPAR.uD, fitPAR.p, fitPAR.dp, fitPAR.chisq, fitPM.chisq, fitAve.chisq); 411 412 XY_to_RD (&fitPAR.Ro, &fitPAR.Do, fitPAR.Ro, fitPAR.Do, &coords); 191 goto justPosition; 192 } 193 if (fitStats->Npoints <= PAR_TOOFEW) { 194 mode = FIT_PM_ONLY; 195 goto justPosition; 196 } 197 198 if (fitStats->NfitAlloc == 1) { 199 // if N_BOOTSTRAP_SAMPLES = 1, no bootstrap resampling: 200 FitPMandPar (&fitPar, fitStats->fitdataPar, fitStats->points, fitStats->Npoints); 201 } else { 202 fitStats->Nfit = 0; 203 for (k = 0; k < fitStats->NfitAlloc; k++) { 204 BootstrapResample (fitStats->sample, fitStats->points, fitStats->Npoints); 205 FitPMandPar (&fitStats->fit[k], fitStats->fitdataPar, fitStats->sample, fitStats->Npoints); 206 fitStats->Nfit ++; 207 } 208 BootstrapRobustStats (&fitPar, fitStats->fit, fitStats->Nfit, FIT_RESULT_RA); 209 BootstrapRobustStats (&fitPar, fitStats->fit, fitStats->Nfit, FIT_RESULT_DEC); 210 BootstrapRobustStats (&fitPar, fitStats->fit, fitStats->Nfit, FIT_RESULT_uR); 211 BootstrapRobustStats (&fitPar, fitStats->fit, fitStats->Nfit, FIT_RESULT_uD); 212 BootstrapRobustStats (&fitPar, fitStats->fit, fitStats->Nfit, FIT_RESULT_PLX); 213 } 214 FitAstromSetChisq (&fitPar, fitStats->points, fitStats->Npoints, FIT_PM_AND_PAR); 215 216 // project Ro, Do back to RA,DEC 217 XY_to_RD (&fitPar.Ro, &fitPar.Do, fitPar.Ro, fitPar.Do, &fitStats->coords); 218 if (fabs(fitPar.Ro) < 0.01) fprintf (stderr, "watch out for 0,360 boundary\n"); 219 413 220 average[0].flags |= ID_STAR_FIT_PAR; 414 221 fitStats->Npar ++; 415 222 416 if (fabs(fitPM.Ro) < 0.01) fprintf (stderr, "watch out for 0,360 boundary\n");417 418 223 // XXX a hard-wired hack... 419 if ((fabs(fitP AR.uR) > 2.0) || (fabs(fitPAR.uD) > 2.0)) {224 if ((fabs(fitPar.uR) > 2.0) || (fabs(fitPar.uD) > 2.0)) { 420 225 mode = FIT_PM_ONLY; 421 226 } 422 227 } 423 228 424 skipPAR:229 justPosition: 425 230 { 426 // ALWAYS fit the average model 427 StatType statsR, statsD; 428 liststats_pos (X, dX, N, &statsR, XVERB); // WARNING: this function modifies R (do not use after here) 429 liststats_pos (Y, dY, N, &statsD, XVERB); // WARNING: this function modifies D (do not use after here) 231 // use bootstrap resampling to check the error distribution 232 // if we only have one point, this is silly... 233 234 if (fitStats->NfitAlloc == 1) { 235 FitAstromResultSetPM (&fitPos, 1, average); 236 FitPosPMfixed (&fitPos, fitStats->fitdataPos, fitStats->points, fitStats->Npoints); 237 } else { 238 fitStats->Nfit = 0; 239 FitAstromResultSetPM (fitStats->fit, fitStats->NfitAlloc, average); 240 for (k = 0; k < fitStats->NfitAlloc; k++) { 241 BootstrapResample (fitStats->sample, fitStats->points, fitStats->Npoints); 242 FitPosPMfixed (&fitStats->fit[k], fitStats->fitdataPos, fitStats->sample, fitStats->Npoints); 243 fitStats->Nfit ++; 244 } 245 BootstrapRobustStats (&fitPos, fitStats->fit, fitStats->Nfit, FIT_RESULT_RA); 246 BootstrapRobustStats (&fitPos, fitStats->fit, fitStats->Nfit, FIT_RESULT_DEC); 247 } 248 FitAstromSetChisq (&fitPos, fitStats->points, fitStats->Npoints, FIT_AVERAGE); 430 249 431 250 // project Ro, Do back to RA,DEC 432 XY_to_RD (&fitAve.Ro, &fitAve.Do, statsR.mean, statsD.mean, &coords); 433 if (XVERB) fprintf (stderr, "average: %f %f\n", fitAve.Ro, fitAve.Do); 434 435 fitAve.dRo = statsR.sigma; 436 fitAve.dDo = statsD.sigma; 437 438 fitAve.chisq = (N > 1) ? 0.5 * (statsR.chisq + statsD.chisq) : NAN; 439 fitAve.Nfit = N; 440 441 fitAve.uR = fitAve.duR = 0.0; 442 fitAve.uD = fitAve.duD = 0.0; 443 fitAve.p = fitAve.dp = 0.0; 251 XY_to_RD (&fitPos.Ro, &fitPos.Do, fitPos.Ro, fitPos.Do, &fitStats->coords); 444 252 average[0].flags |= ID_STAR_FIT_AVE; 445 253 fitStats->Nave ++; 446 254 } 447 255 256 // update the bit flags of which points were used 257 for (k = 0; k < fitStats->Npoints; k++) { 258 int Nm = fitStats->points[k].measure; 259 myAssert (Nm >= 0, "oops"); 260 measure[Nm].dbFlags |= ID_MEAS_USED_OBJ; 261 if (measureBig) { measureBig[Nm].dbFlags |= ID_MEAS_USED_OBJ; } 262 } 263 264 // we can set the star reference-image color only if we have loaded the image data 265 int setRefColor = areImagesMatched(); 448 266 if (setRefColor) { 267 float *C_blue = NULL; 268 float *C_red = NULL; 269 ALLOCATE (C_blue, float, fitStats->Npoints); 270 ALLOCATE (C_red, float, fitStats->Npoints); 271 272 int NcBlue = 0; 273 int NcRed = 0; 274 275 for (k = 0; k < fitStats->Npoints; k++) { 276 int Nm = fitStats->points[k].measure; 277 float colorBlue = getColorBlue (measOff + Nm, cat); 278 if (!isnan(colorBlue)) { 279 C_blue[NcBlue] = colorBlue; 280 NcBlue++; 281 } 282 float colorRed = getColorRed (measOff + Nm, cat); 283 if (!isnan(colorRed)) { 284 C_red[NcRed] = colorRed; 285 NcRed++; 286 } 287 } 288 289 // need to reassign here if isfinite() 449 290 float colorMedian; 450 dsort (C_blue, NcBlue);291 fsort (C_blue, NcBlue); 451 292 colorMedian = (NcBlue > 0) ? C_blue[(int)(0.5*NcBlue)] : NAN; 452 293 average[0].refColorBlue = colorMedian; 453 dsort (C_red, NcRed);294 fsort (C_red, NcRed); 454 295 colorMedian = (NcRed > 0) ? C_red[(int)(0.5*NcRed)] : NAN; 455 296 average[0].refColorRed = colorMedian; 297 298 free (C_blue); 299 free (C_red); 456 300 } 457 301 … … 459 303 // XXXX for now, just use the mode as the result: 460 304 int result = mode; 305 FitAstromResult fit; 306 FitAstromResultInit (&fit); 461 307 462 308 switch (result) { 463 309 case FIT_AVERAGE: 464 310 average[0].flags |= ID_STAR_USE_AVE; 465 fit = fit Ave;311 fit = fitPos; 466 312 break; 467 313 case FIT_PM_ONLY: … … 471 317 case FIT_PM_AND_PAR: 472 318 average[0].flags |= ID_STAR_USE_PAR; 473 fit = fitP AR;319 fit = fitPar; 474 320 break; 475 321 } … … 503 349 504 350 // what is the offset relative to the mean fit position? 505 coords.crval1 = average[0].R;506 coords.crval2 = average[0].D;507 if (isnan( coords.crval1)) {351 fitStats->coords.crval1 = average[0].R; 352 fitStats->coords.crval2 = average[0].D; 353 if (isnan(fitStats->coords.crval1)) { 508 354 return (FALSE); 509 355 } 510 if (isnan( coords.crval2)) {356 if (isnan(fitStats->coords.crval2)) { 511 357 return (FALSE); 512 358 } 513 359 514 360 double dXoff, dYoff; 515 RD_to_XY (&dXoff, &dYoff, fit.Ro, fit.Do, & coords);361 RD_to_XY (&dXoff, &dYoff, fit.Ro, fit.Do, &fitStats->coords); 516 362 float dPos = hypot (dXoff, dYoff); 517 363 if (dPos > MaxMeanOffset) { 518 364 if (fitStats->Noffset < 100) { 519 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", coords.crval1,coords.crval2, fit.Ro, fit.Do, dXoff, dYoff);365 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", fitStats->coords.crval1, fitStats->coords.crval2, fit.Ro, fit.Do, dXoff, dYoff); 520 366 } 521 367 fitStats->Noffset ++; … … 531 377 average[0].uR, 532 378 average[0].uD, 533 fit Ave.chisq, fitPM.chisq, fitPAR.chisq);379 fitPos.chisq, fitPM.chisq, fitPar.chisq); 534 380 535 381 average[0].R = fit.Ro; // RA in degrees … … 546 392 average[0].dP = fit.dp; // parallax error in arcsec 547 393 548 average[0].ChiSqAve = fit Ave.chisq;394 average[0].ChiSqAve = fitPos.chisq; 549 395 average[0].ChiSqPM = fitPM.chisq; 550 average[0].ChiSqPar = fitP AR.chisq;551 552 average[0].Tmean = (Tmean * 86400 * 365.25) + T2000;396 average[0].ChiSqPar = fitPar.chisq; 397 398 average[0].Tmean = (Tmean * 86400 * 365.25) + fitStats->T2000; 553 399 average[0].Trange = (Trange * 86400 * 365.25); 554 400 average[0].Npos = fit.Nfit; … … 563 409 // be called with just MeasureTiny set and Measure == NULL 564 410 int UpdateObjects_Stack (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats) { 565 566 off_t k;567 411 568 412 // set the default values … … 573 417 574 418 /* calculate the average value of R,D for a single star */ 575 PMFit fitAve; 576 memset (&fitAve, 0, sizeof(fitAve)); 577 fitAve.chisq = NAN; 419 FitAstromResult fitPos; 420 FitAstromResultInit (&fitPos); 578 421 579 422 if (average[0].Nmeasure == 0) return TRUE; 580 581 int N = 0;582 423 583 424 int XVERB = FALSE; … … 585 426 XVERB |= (average[0].objID == OBJ_ID_DST) && (average[0].catID == CAT_ID_DST); 586 427 428 // select the measurements to be used in this analysis 429 UpdateObjects_SelectMeasures (fitStats, average, secfilt, measure, measureBig, TRUE); 430 431 // too few measurements for average position (require 2 values) 432 if (fitStats->Npoints < 1) return FALSE; // XXX ?? 433 434 double Tmean, Trange, parRange; 435 FitAstromPoints_Project (fitStats, &Tmean, &Trange, &parRange); 436 437 FitPosPMfixed (&fitPos, fitStats->fitdataPos, fitStats->points, fitStats->Npoints); 438 FitAstromSetChisq (&fitPos, fitStats->points, fitStats->Npoints, FIT_AVERAGE); 439 440 // project Ro, Do back to RA,DEC 441 XY_to_RD (&fitPos.Ro, &fitPos.Do, fitPos.Ro, fitPos.Do, &fitStats->coords); 442 443 // XXX choose stack flag? average[0].flags |= ID_STAR_FIT_AVE; 444 fitStats->Nave ++; 445 446 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f)\n", 447 average[0].R, 448 average[0].D, 449 fitPos.Ro, fitPos.Do, 450 3600*(average[0].R - fitPos.Ro), 451 3600*(average[0].D - fitPos.Do)); 452 453 // make sure that the fit succeeded 454 int status = TRUE; 455 status &= finite(fitPos.Ro); 456 status &= finite(fitPos.Do); 457 status &= finite(fitPos.dRo); 458 status &= finite(fitPos.dDo); 459 if (!status) { 460 fitStats->Nskip ++; 461 return FALSE; 462 } 463 464 // what is the offset relative to the mean fit position? 465 fitStats->coords.crval1 = average[0].R; 466 fitStats->coords.crval2 = average[0].D; 467 468 double dXoff, dYoff; 469 RD_to_XY (&dXoff, &dYoff, fitPos.Ro, fitPos.Do, &fitStats->coords); 470 float dPos = hypot (dXoff, dYoff); 471 if (dPos > MaxMeanOffset) { 472 if (fitStats->Noffset < 100) { 473 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", fitStats->coords.crval1, fitStats->coords.crval2, fitPos.Ro, fitPos.Do, dXoff, dYoff); 474 } 475 fitStats->Noffset ++; 476 return FALSE; 477 } 478 479 // set the stack position values 480 average[0].Rstk = fitPos.Ro; // RA in degrees 481 average[0].Dstk = fitPos.Do; // DEC in degrees 482 average[0].dRstk = fitPos.dRo; // RA scatter in arcsec 483 average[0].dDstk = fitPos.dDo; // DEC scatter in arcsec 484 485 return (TRUE); 486 } 487 488 int UpdateObjects_SelectMeasures (FitStats *fit, Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int isStack) { 489 490 // I've already allocated fit->points (and fit->sample) with space for fit->NpointsAlloc entries 491 492 int has2MASS = FALSE; 493 494 int Npoints = fit->Npoints = 0; 495 FitAstromPoint *points = fit->points; 496 497 int TESTPT2 = FALSE; 498 TESTPT2 |= CAT_ID_SRC && OBJ_ID_SRC && (average[0].catID == CAT_ID_SRC) && (average[0].objID == OBJ_ID_SRC); 499 TESTPT2 |= CAT_ID_DST && OBJ_ID_DST && (average[0].catID == CAT_ID_DST) && (average[0].objID == OBJ_ID_DST); 500 if (TESTPT2) { 501 fprintf (stderr, "got test det\n"); 502 } 503 587 504 // find the basic properties of the detections for this object (Tmin, Tmax, Tmean) 505 off_t k; 588 506 for (k = 0; k < average[0].Nmeasure; k++) { 589 507 590 if ( XVERB) {508 if (0) { 591 509 char *date = ohana_sec_to_date (measure[k].t); 592 510 int dbFlagsBig = measureBig ? measureBig[k].dbFlags : 0; 593 fprintf (stderr, "stack: "OFF_T_FMT" %f %f %s : 0x%08x : 0x%08x\n", k, measure[k].R, measure[k].D, date, measure[k].dbFlags, dbFlagsBig);511 fprintf (stderr, OFF_T_FMT" %f %f %s : 0x%08x : 0x%08x\n", k, measure[k].R, measure[k].D, date, measure[k].dbFlags, dbFlagsBig); 594 512 free (date); 595 513 } 596 514 597 // SKIP everything except gpc1 stack data 598 if (!isGPC1stack(measure[k].photcode)) continue; 599 515 // SKIP gpc1 forced-warp data 516 if (isGPC1warp(measure[k].photcode)) continue; 517 518 // SKIP gpc1 stack data 519 if (isStack) { 520 if (!isGPC1stack(measure[k].photcode)) continue; 521 } else { 522 if ( isGPC1stack(measure[k].photcode)) continue; 523 } 524 525 // reset the bit to note that a detection was used (or not) 526 measure[k].dbFlags &= ~ID_MEAS_USED_OBJ; 527 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_USED_OBJ; } 528 529 // does the measurement pass the supplied filtering constraints? 530 // MeasFilterTestTiny does not test psfQF 600 531 // exclude bad detections based on: photcodes, psfQF, time range, photflags & astromBadMask, mag_inst 601 532 int keepMeasure = measureBig ? MeasFilterTest(&measureBig[k], FALSE) : MeasFilterTestTiny(&measure[k], FALSE); … … 604 535 } 605 536 606 R[N] = getMeanR (&measure[k], average, secfilt); 607 D[N] = getMeanD (&measure[k], average, secfilt); 608 609 // dX, dY : error in arcsec -- 610 dX[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_RA); 611 dY[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_DEC); 537 double Ri = measure[k].R; 538 double Di = measure[k].D; 539 540 // mark (as POOR) any measurements which are deviant from the mean by > ExcludeBogusRadius 541 if (ExcludeBogus) { 542 fit->coords.crval1 = average[0].R; 543 fit->coords.crval2 = average[0].D; 544 double Xi, Yi; 545 RD_to_XY (&Xi, &Yi, Ri, Di, &fit->coords); 546 double radius = hypot(Xi, Yi); 547 if (radius > ExcludeBogusRadius) { 548 measure[k].dbFlags |= ID_MEAS_POOR_ASTROM; 549 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_POOR_ASTROM; } 550 continue; 551 } 552 measure[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; 553 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; } 554 } 555 556 // outlier rejection 557 if (FALSE && FlagOutlier && (measure[k].dbFlags & ID_MEAS_POOR_ASTROM)) { 558 continue; 559 } 560 561 FitAstromPointInit (&points[Npoints]); 562 563 points[Npoints].R = Ri; 564 points[Npoints].D = Di; 565 566 // measure[k].t is UNIX seconds, T2000 is UNIX seconds for J2000. 567 // T[] is time in years since J2000 (jd = 2451545) 568 points[Npoints].T = (measure[k].t - fit->T2000) / (86400*365.25) ; // time relative to J2000 in years 569 570 // add measured systematic error in quadrature? only do this after the fit has 571 // converged (or you will never improve the poor images) 572 573 // dX,dY are the X and Y direction errors in arcseconds. dR, dD are the errors in 574 // those directions in degrees. IF we have non-circular errors (different values for 575 // X and Y), then dR and dD will be incorrect: they would need to be rotated to take 576 // out the position angle 577 578 // dX, dY : error in arcsec: 579 points[Npoints].dX = GetAstromErrorTiny (&measure[k], ERROR_MODE_RA); 580 points[Npoints].dY = GetAstromErrorTiny (&measure[k], ERROR_MODE_DEC); 612 581 613 582 // allow a given photcode or measurement to be 614 583 // ignored if the error is NAN (for photcode, set astromErrSys to NaN) 615 if (isnan(dX[N])) continue; 616 if (isnan(dY[N])) continue; 617 618 // XXX this is (slightly) inconsistent: dX,dY are the X and Y direction errors in 619 // arcseconds. dR, dD are the errors in those directions in degrees. IF we have 620 // non-circular errors (different values for X and Y), then dR and dD will be 621 // incorrect: they would need to be rotated to take out the position angle 622 dR[N] = dX[N] / 3600.0; 623 dD[N] = dY[N] / 3600.0; 624 625 // XXX use a different flag for stack measurements? 626 // measure[k].dbFlags |= ID_MEAS_USED_OBJ; 627 // if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_USED_OBJ; } 628 629 N++; 584 if (isnan(points[Npoints].dX)) continue; 585 if (isnan(points[Npoints].dY)) continue; 586 587 points[Npoints].dT = measure[k].dt; 588 589 points[Npoints].measure = k; 590 Npoints++; 591 592 if ((measure[k].photcode >= 2011) && (measure[k].photcode <= 2013)) { 593 has2MASS = TRUE; 594 } 595 596 myAssert (Npoints <= fit->NpointsAlloc, "oops"); 630 597 } // loop over measurements : average[0].Nmeasure 631 598 632 // if we have too few good detections for the desired fit, or too limited a 633 // baseline, use a fit with fewer parameters. XXX if we have too few measurements 634 // for even the average position, consider including the lower-quality detections? 635 636 // too few measurements for average position (require 2 values) 637 if (N < 1) return FALSE; // XXX ?? 638 639 // find the mean position 640 StatType statsR, statsD; 641 liststats_pos (R, dR, N, &statsR, XVERB); // WARNING: this function modifies R (do not use after here) 642 liststats_pos (D, dD, N, &statsD, XVERB); // WARNING: this function modifies D (do not use after here) 643 644 fitAve.Ro = statsR.mean; 645 fitAve.dRo = 3600.0*statsR.sigma; 646 647 fitAve.Do = statsD.mean; 648 fitAve.dDo = 3600.0*statsD.sigma; 649 650 fitAve.chisq = 0.5 * (statsR.chisq + statsD.chisq); 651 fitAve.Nfit = N; 652 653 // XXX choose stack flag? average[0].flags |= ID_STAR_FIT_AVE; 654 fitStats->Nave ++; 655 656 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f)\n", 657 average[0].R, 658 average[0].D, 659 fitAve.Ro, fitAve.Do, 660 3600*(average[0].R - fitAve.Ro), 661 3600*(average[0].D - fitAve.Do)); 662 663 // make sure that the fit succeeded 664 int status = TRUE; 665 status &= finite(fitAve.Ro); 666 status &= finite(fitAve.Do); 667 status &= finite(fitAve.dRo); 668 status &= finite(fitAve.dDo); 669 if (!status) { 670 fitStats->Nskip ++; 671 return FALSE; 672 } 673 674 // what is the offset relative to the mean fit position? 675 coords.crval1 = average[0].R; 676 coords.crval2 = average[0].D; 677 678 double dXoff, dYoff; 679 RD_to_XY (&dXoff, &dYoff, fitAve.Ro, fitAve.Do, &coords); 680 float dPos = hypot (dXoff, dYoff); 681 if (dPos > MaxMeanOffset) { 682 if (fitStats->Noffset < 100) { 683 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", coords.crval1, coords.crval2, fitAve.Ro, fitAve.Do, dXoff, dYoff); 684 } 685 fitStats->Noffset ++; 686 return FALSE; 687 } 688 689 // set the stack position values 690 average[0].Rstk = fitAve.Ro; // RA in degrees 691 average[0].Dstk = fitAve.Do; // DEC in degrees 692 average[0].dRstk = fitAve.dRo; // RA scatter in arcsec 693 average[0].dDstk = fitAve.dDo; // DEC scatter in arcsec 694 599 int TESTPT = FALSE; 600 TESTPT |= CAT_ID_SRC && OBJ_ID_SRC && (average[0].catID == CAT_ID_SRC) && (average[0].objID == OBJ_ID_SRC); 601 TESTPT |= CAT_ID_DST && OBJ_ID_DST && (average[0].catID == CAT_ID_DST) && (average[0].objID == OBJ_ID_DST); 602 if (TESTPT) { 603 fprintf (stderr, "got test det\n"); 604 } 605 606 // XXX flag measurements from stars with 2MASS 607 for (k = 0; k < average[0].Nmeasure; k++) { 608 // reset the bit to note that a detection was used (or not) 609 if (has2MASS) { 610 measure[k].dbFlags |= ID_MEAS_OBJECT_HAS_2MASS; 611 } else { 612 measure[k].dbFlags &= ~ID_MEAS_OBJECT_HAS_2MASS; 613 } 614 } 615 616 fit->Npoints = Npoints; 617 return TRUE; 618 } 619 620 int FitAstromPoints_Project (FitStats *fitStats, double *Tmean, double *Trange, double *parRange) { 621 622 int k; 623 624 int Npoints = fitStats->Npoints; 625 FitAstromPoint *points = fitStats->points; 626 627 // find Tmin & Tmax from the list of accepted measurements 628 double Tmin = points[0].T; 629 double Tmax = points[0].T; 630 double pRmin = +2.0; 631 double pRmax = -2.0; 632 double pDmin = +2.0; 633 double pDmax = -2.0; 634 635 *Tmean = 0.0; 636 637 double Tsum = 0.0; 638 double Wsum = 0.0; 639 for (k = 0; k < Npoints; k++) { 640 Tmin = MIN(Tmin, points[k].T); 641 Tmax = MAX(Tmax, points[k].T); 642 643 float wx = 1.0 / SQ(points[k].dX); 644 645 Tsum += points[k].T * wx; 646 Wsum += wx; 647 648 // at this point, T is in years since J2000 649 ParFactor (&points[k].pR, &points[k].pD, points[k].R, points[k].D, points[k].T); 650 pRmin = MIN (pRmin, points[k].pR); 651 pRmax = MAX (pRmax, points[k].pR); 652 pDmin = MIN (pDmin, points[k].pD); 653 pDmax = MAX (pDmax, points[k].pD); 654 } 655 *Trange = Tmax - Tmin; 656 657 // mean epoch 658 *Tmean = Tsum / Wsum; 659 660 // for HIGH_SPEED, just use the center of the range 661 if (RELASTRO_OP == OP_HIGH_SPEED) { 662 *Tmean = 0.5*(Tmax - Tmin); 663 } 664 665 *parRange = hypot (pRmax - pRmin, pDmax - pDmin); 666 667 /* we need to do the fit in a locally linear space; choose a ref coordinate */ 668 fitStats->coords.crval1 = points[0].R; 669 fitStats->coords.crval2 = points[0].D; 670 671 // project all of the R,D coordinates to a plane centered on this coordinate. set 672 // the times to be relative to Tmean 673 for (k = 0; k < Npoints; k++) { 674 RD_to_XY (&points[k].X, &points[k].Y, points[k].R, points[k].D, &fitStats->coords); 675 points[k].T -= *Tmean; 676 } 677 return TRUE; 678 } 679 680 int CatalogMaxNmeasure (Catalog *catalog, int Ncatalog) { 681 682 int i, j; 683 684 int Nmax = 0; 685 for (i = 0; i < Ncatalog; i++) { 686 for (j = 0; j < catalog[i].Naverage; j++) { 687 Nmax = MAX (Nmax, catalog[i].average[j].Nmeasure); 688 } 689 } 690 return Nmax; 691 } 692 693 int BootstrapResample (FitAstromPoint *sample, FitAstromPoint *points, int Npoints) { 694 int i; 695 696 // I need to draw Npoints random entries from 'points' with replacement: 697 for (i = 0; i < Npoints; i++) { 698 int N = Npoints * drand48(); 699 sample[i] = points[N]; 700 } 701 return TRUE; 702 } 703 704 // calculate mean and sigma points for the 5 fit parameter 705 int BootstrapRobustStats (FitAstromResult *result, FitAstromResult *fit, int Nfit, int mode) { 706 707 // generate a histogram for the selected element 708 double *values = NULL; 709 ALLOCATE (values, double, Nfit); 710 711 int i; 712 713 for (i = 0; i < Nfit; i++) { 714 switch (mode) { 715 case FIT_RESULT_RA: 716 values[i] = fit[i].Ro; 717 break; 718 case FIT_RESULT_DEC: 719 values[i] = fit[i].Do; 720 break; 721 case FIT_RESULT_uR: 722 values[i] = fit[i].uR; 723 break; 724 case FIT_RESULT_uD: 725 values[i] = fit[i].uD; 726 break; 727 case FIT_RESULT_PLX: 728 values[i] = fit[i].p; 729 break; 730 default: 731 myAbort ("invalid option"); 732 } 733 } 734 735 dsort (values, Nfit); 736 737 double median; 738 if (Nfit % 2) { 739 int Ncenter = Nfit / 2; 740 median = values[Ncenter]; 741 } else { 742 int Ncenter = Nfit / 2 - 1; 743 median = 0.5*(values[Ncenter] + values[Ncenter + 1]); 744 } 745 746 double Slo = VectorFractionInterpolate (values, 0.158655, Nfit); 747 double Shi = VectorFractionInterpolate (values, 0.841345, Nfit); 748 double sigma = (Shi - Slo) / 2.0; 749 750 switch (mode) { 751 case FIT_RESULT_RA: 752 result->Ro = median; 753 result->dRo = sigma; 754 break; 755 case FIT_RESULT_DEC: 756 result->Do = median; 757 result->dDo = sigma; 758 break; 759 case FIT_RESULT_uR: 760 result->uR = median; 761 result->duR = sigma; 762 break; 763 case FIT_RESULT_uD: 764 result->uD = median; 765 result->duD = sigma; 766 break; 767 case FIT_RESULT_PLX: 768 result->p = median; 769 result->dp = sigma; 770 break; 771 default: 772 myAbort ("invalid option"); 773 } 774 775 return TRUE; 776 } 777 778 double VectorFractionInterpolate (double *values, float fraction, int Npts) { 779 780 float F = fraction * Npts; 781 int N = fraction * Npts; 782 783 if (N < 0 ) return NAN; 784 if (N >= Npts - 2) return NAN; 785 786 // interpolate between N,N+1 787 788 double S = (F - N) * (values[N+1] - values[N]) + values[N]; 789 return S; 790 } 791 792 int FitAstromSetChisq (FitAstromResult *fit, FitAstromPoint *points, int Npoints, FitMode mode) { 793 794 int i; 795 796 // add up the chi square for the fit 797 double chisq = 0.0; 798 for (i = 0; i < Npoints; i++) { 799 double Xf = fit->Ro + fit->uR*points[i].T + fit->p*points[i].pR; 800 double Yf = fit->Do + fit->uD*points[i].T + fit->p*points[i].pD; 801 chisq += SQ(points[i].X - Xf) / SQ(points[i].dX); 802 chisq += SQ(points[i].Y - Yf) / SQ(points[i].dY); 803 } 804 switch (mode) { 805 case FIT_AVERAGE: 806 fit->chisq = chisq / (2.0*Npoints - 2.0); 807 break; 808 case FIT_PM_ONLY: 809 fit->chisq = chisq / (2.0*Npoints - 4.0); 810 break; 811 case FIT_PM_AND_PAR: 812 fit->chisq = chisq / (2.0*Npoints - 5.0); 813 break; 814 default: 815 myAbort ("invalid mode"); 816 } 817 fit->Nfit = Npoints; 695 818 return (TRUE); 696 819 } 697 820 698 699 700 /* fitting proper-motion and parallax: 701 702 given a source at position r,d, at a time t, we need to calculate a vector (pr,pd) 703 704 let x,y be the coordinate in the linearized frame with y parallel to DEC lines 705 706 L,B are the ecliptic longitude and latitude of the object, 707 dL and dB are the offsets in the L and B directions 708 709 dL = sin(t - topp) 710 dB = cos(t - topp)*sin(B) 711 712 these need to be rotated to the R,D frame to yield pR,pD. Then, the equation of motion 713 for the source in the x,y frame is: 714 715 x = Ro + uR * (t - to) + p * pR 716 y = Do + uD * (t - to) + p * pD 717 718 the unknowns in these equations are Ro, uR, Do, uD, and p 719 720 XXX think through the concepts for the pole a bit better. all objects near the pole 721 move the same way with the same phase. choose a projection center and define dL,dB relative 722 to that center point coordinate system? 723 724 */ 821 int FitAstromResultSetPM (FitAstromResult *fit, int Nfit, Average *average) { 822 823 int i; 824 825 if (USE_GALAXY_MODEL) { 826 for (i = 0; i < Nfit; i++) { 827 fit->uR = average->uRgal; 828 fit->uD = average->uDgal; 829 } 830 } else { 831 for (i = 0; i < Nfit; i++) { 832 fit->uR = 0.0; 833 fit->uD = 0.0; 834 } 835 } 836 837 return TRUE; 838 }
Note:
See TracChangeset
for help on using the changeset viewer.
