Changeset 37261
- Timestamp:
- Aug 14, 2014, 2:25:44 PM (12 years ago)
- Location:
- trunk/Ohana/src/relastro
- Files:
-
- 1 added
- 4 edited
-
Makefile (modified) (2 diffs)
-
include/relastro.h (modified) (2 diffs)
-
src/ParFactor.c (modified) (1 diff)
-
src/UpdateObjects.c (modified) (4 diffs)
-
src/extra.c (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/relastro/Makefile
r36833 r37261 59 59 $(SRC)/save_catalogs.$(ARCH).o \ 60 60 $(SRC)/CoordOps.$(ARCH).o \ 61 $(SRC)/extra.$(ARCH).o \ 61 62 $(SRC)/FixProblemImages.$(ARCH).o \ 62 63 $(SRC)/StarMaps.$(ARCH).o \ … … 117 118 $(SRC)/save_catalogs.$(ARCH).o \ 118 119 $(SRC)/CoordOps.$(ARCH).o \ 120 $(SRC)/extra.$(ARCH).o \ 119 121 $(SRC)/high_speed_catalogs.$(ARCH).o \ 120 122 $(SRC)/high_speed_objects.$(ARCH).o \ -
trunk/Ohana/src/relastro/include/relastro.h
r37038 r37261 133 133 int Nmeas; 134 134 } StatType; 135 136 typedef struct { 137 off_t Nave; 138 off_t Npm; 139 off_t Npar; 140 off_t Nskip; 141 off_t Noffset; 142 } FitStats; 135 143 136 144 /* global variables set in parameter file */ … … 535 543 int areImagesLoaded (); 536 544 int areImagesMatched (); 545 546 int isGPC1chip (int photcode); 547 int isGPC1stack (int photcode); 548 int isGPC1warp (int photcode); -
trunk/Ohana/src/relastro/src/ParFactor.c
r33652 r37261 63 63 double jd, lambda, beta, epsilon, Radius; 64 64 65 /* given a time T in UNIX seconds, determine the solar longitude S */ 65 /* given a Time relative to Tmean, Tmean in years since J2000, determine the solar 66 longitude S */ 66 67 67 68 // jd = ohana_sec_to_jd (365.25*86400.0*(Time + Tmean)); -
trunk/Ohana/src/relastro/src/UpdateObjects.c
r37246 r37261 1 1 # include "relastro.h" 2 # define PAR_TOOFEW 5 3 4 int UpdateObjects_Chips (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats, int i, off_t m); 5 int UpdateObjects_Stack (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats); 2 6 3 7 static off_t Nmax; … … 13 17 static double *C_red; 14 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 15 41 void initObjectData (Catalog *catalog, int Ncatalog) { 16 42 … … 41 67 ALLOCATE (C_blue, double, MAX (1, Nmax)); 42 68 ALLOCATE (C_red, double, MAX (1, Nmax)); 43 }44 45 void freeObjectData () {46 47 free (R);48 free (D);49 free (T);50 free (X);51 free (Y);52 53 free (dR);54 free (dD);55 free (dT);56 free (dX);57 free (dY);58 59 free (pX);60 free (pY);61 62 free (C_blue);63 free (C_red);64 }65 66 // This function operates on both Measure and MeasureTiny. In the big stages, this should67 // be called with just MeasureTiny set and Measure == NULL68 int UpdateObjects (Catalog *catalog, int Ncatalog) {69 70 off_t j, k, m;71 int i, N, NcBlue, NcRed, Nsecfilt, mode, result, status, XVERB;72 StatType statsR, statsD;73 Coords coords;74 PMFit fitAve, fitPM, fitPAR, fit;75 time_t T2000;76 off_t Nave, Npm, Npar, Nskip, Noffset;77 off_t NaveSum, NpmSum, NparSum, NskipSum, NoffSum;78 double Tmin, Tmax, Tmean, Trange;79 80 memset (&fit, 0, sizeof(fit));81 memset (&fitAve, 0, sizeof(fitAve));82 memset (&fitPM, 0, sizeof(fitPM));83 memset (&fitPAR, 0, sizeof(fitPAR));84 initObjectData (catalog, Ncatalog);85 86 int setRefColor = areImagesMatched();87 69 88 70 /* project coordinates to a plane centered on the object with units of arcsec */ … … 97 79 strcpy (coords.ctype, "DEC--SIN"); 98 80 99 XVERB = FALSE;100 101 81 // use J2000 as a reference time 102 T2000 = ohana_date_to_sec ("2000/01/01"); 82 T2000 = ohana_date_to_sec ("2000/01/01,12:00:00"); 83 } 84 85 void freeObjectData () { 86 87 free (R); 88 free (D); 89 free (T); 90 free (X); 91 free (Y); 92 93 free (dR); 94 free (dD); 95 free (dT); 96 free (dX); 97 free (dY); 98 99 free (pX); 100 free (pY); 101 102 free (C_blue); 103 free (C_red); 104 } 105 106 // This function operates on both Measure and MeasureTiny. In the big stages, this should 107 // be called with just MeasureTiny set and Measure == NULL 108 int UpdateObjects (Catalog *catalog, int Ncatalog) { 109 110 initObjectData (catalog, Ncatalog); 111 103 112 // XXX in the future, use catalog[0].Nsecfilt only? allow catalogs to have variable Nsecfilt? 104 105 Nsecfilt = GetPhotcodeNsecfilt (); 113 int Nsecfilt = GetPhotcodeNsecfilt (); 106 114 if (Ncatalog) { 107 115 assert (catalog[0].Nsecfilt == Nsecfilt); 108 116 } 109 117 110 NaveSum = NparSum = NpmSum = NoffSum = NskipSum = 0; 118 FitStats sumStatsChips; initFitStats (&sumStatsChips); 119 FitStats sumStatsStack; initFitStats (&sumStatsStack); 120 121 int i; 111 122 for (i = 0; i < Ncatalog; i++) { 112 123 113 124 if (VERBOSE2) fprintf (stderr, "astrometrize catalog %d : "OFF_T_FMT" ave, "OFF_T_FMT" meas\n", i, catalog[i].Naverage, catalog[i].Nmeasure); 114 125 115 Nave = Npar = Npm = Nskip = Noffset = 0; 126 FitStats fitStatsChips; initFitStats (&fitStatsChips); 127 FitStats fitStatsStack; initFitStats (&fitStatsStack); 128 129 off_t j; 116 130 for (j = 0; j < catalog[i].Naverage; j++) { 117 131 /* calculate the average value of R,D for a single star */ 118 119 XVERB = FALSE; 120 fitAve.chisq = NAN; 121 fitPM.chisq = NAN; 122 fitPAR.chisq = NAN; 123 124 // if we fail to fit the astrometry for some reason, we need to set/reset these 125 catalog[i].average[j].flags |= ID_STAR_NO_ASTROM; 126 catalog[i].average[j].ChiSqAve = NAN; 127 catalog[i].average[j].ChiSqPM = NAN; 128 catalog[i].average[j].ChiSqPar = NAN; 129 catalog[i].average[j].Npos = 0; 130 131 if (catalog[i].average[j].Nmeasure == 0) { 132 off_t m = catalog[i].average[j].measureOffset; 133 MeasureTiny *measure = &catalog[i].measureT[m]; 134 Measure *measureBig = catalog[i].measure ? &catalog[i].measure[m] : NULL; 135 Average *average = &catalog[i].average[j]; 136 SecFilt *secfilt = &catalog[i].secfilt[j*Nsecfilt]; 137 138 UpdateObjects_Stack(average, secfilt, measure, measureBig, Nsecfilt, &fitStatsStack); 139 UpdateObjects_Chips(average, secfilt, measure, measureBig, Nsecfilt, &fitStatsChips, i, m); 140 } 141 if (VERBOSE) 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); 142 if (VERBOSE) 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); 143 sumFitStats (&fitStatsChips, &sumStatsChips); 144 sumFitStats (&fitStatsStack, &sumStatsStack); 145 } 146 freeObjectData (); 147 148 if (VERBOSE) 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); 149 if (VERBOSE) 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); 150 return (TRUE); 151 } 152 153 // This function operates on both Measure and MeasureTiny. In the big stages, this should 154 // be called with just MeasureTiny set and Measure == NULL 155 int UpdateObjects_Chips (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats, int i, off_t m) { 156 157 int setRefColor = areImagesMatched(); 158 159 /* calculate the average value of R,D for a single star */ 160 161 PMFit fit; memset (&fit, 0, sizeof(fit)); 162 PMFit fitAve; memset (&fitAve, 0, sizeof(fitAve)); fitAve.chisq = NAN; 163 PMFit fitPM; memset (&fitPM, 0, sizeof(fitPM)); fitPM.chisq = NAN; 164 PMFit fitPAR; memset (&fitPAR, 0, sizeof(fitPAR)); fitPAR.chisq = NAN; 165 166 // if we fail to fit the astrometry for some reason, we need to set/reset these 167 average[0].flags |= ID_STAR_NO_ASTROM; 168 average[0].ChiSqAve = NAN; 169 average[0].ChiSqPM = NAN; 170 average[0].ChiSqPar = NAN; 171 average[0].Npos = 0; 172 173 // an object with no measurements is externally supplied 174 if (average[0].Nmeasure == 0) return TRUE; 175 176 int NcBlue = 0; 177 int NcRed = 0; 178 int N = 0; 179 180 int mode = FIT_MODE; // start with the globally-defined fit mode 181 182 int XVERB = FALSE; 183 XVERB |= (average[0].objID == OBJ_ID_SRC) && (average[0].catID == CAT_ID_SRC); 184 XVERB |= (average[0].objID == OBJ_ID_DST) && (average[0].catID == CAT_ID_DST); 185 186 // find the basic properties of the detections for this object (Tmin, Tmax, Tmean) 187 off_t k; 188 for (k = 0; k < average[0].Nmeasure; k++) { 189 190 if (XVERB) { 191 char *date = ohana_sec_to_date (measure[k].t); 192 int dbFlagsBig = measureBig ? measureBig[k].dbFlags : 0; 193 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); 194 free (date); 195 } 196 197 // SKIP gpc1 stack data 198 if (isGPC1stack(measure[k].photcode)) continue; 199 200 // SKIP gpc1 forced-warp data 201 if (isGPC1warp(measure[k].photcode)) continue; 202 203 // reset the bit to note that a detection was used (or not) 204 measure[k].dbFlags &= ~ID_MEAS_USED_OBJ; 205 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_USED_OBJ; } 206 207 // does the measurement pass the supplied filtering constraints? 208 // MeasFilterTestTiny does not test psfQF 209 // exclude bad detections based on: photcodes, psfQF, time range, photflags & astromBadMask, mag_inst 210 int keepMeasure = measureBig ? MeasFilterTest(&measureBig[k], FALSE) : MeasFilterTestTiny(&measure[k], FALSE); 211 if (!keepMeasure) { 212 continue; 213 } 214 215 double Ri = getMeanR (&measure[k], average, secfilt); 216 double Di = getMeanD (&measure[k], average, secfilt); 217 218 // mark (as POOR) any measurements which are deviant from the mean by > ExcludeBogusRadius 219 if (ExcludeBogus) { 220 coords.crval1 = average[0].R; 221 coords.crval2 = average[0].D; 222 double Xi, Yi; 223 RD_to_XY (&Xi, &Yi, Ri, Di, &coords); 224 double radius = hypot(Xi, Yi); 225 if (radius > ExcludeBogusRadius) { 226 measure[k].dbFlags |= ID_MEAS_POOR_ASTROM; 227 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_POOR_ASTROM; } 132 228 continue; 133 229 } 134 135 NcBlue = 0; 136 NcRed = 0; 137 N = 0; 138 m = catalog[i].average[j].measureOffset; 139 MeasureTiny *measure = &catalog[i].measureT[m]; 140 Measure *measureBig = catalog[i].measure ? &catalog[i].measure[m] : NULL; 141 // when we update the output measure values, we need to do it here 142 143 mode = FIT_MODE; 144 145 // XVERB |= (catalog[i].averge[j].objID == 0xc90) && (catalog[i].average[j].catID == 0x2a1e); 146 XVERB |= (catalog[i].average[j].objID == OBJ_ID_SRC) && (catalog[i].average[j].catID == CAT_ID_SRC); 147 XVERB |= (catalog[i].average[j].objID == OBJ_ID_DST) && (catalog[i].average[j].catID == CAT_ID_DST); 148 149 // find the basic properties of the detections for this object (Tmin, Tmax, Tmean) 150 for (k = 0; k < catalog[i].average[j].Nmeasure; k++) { 151 152 if (XVERB) { 153 char *date = ohana_sec_to_date (measure[k].t); 154 int dbFlagsBig = measureBig ? measureBig[k].dbFlags : 0; 155 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); 156 free (date); 157 } 158 159 // reset the bit to note that a detection was used (or not) 160 measure[k].dbFlags &= ~ID_MEAS_USED_OBJ; 161 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_USED_OBJ; } 162 163 // does the measurement pass the supplied filtering constraints? 164 // MeasFilterTestTiny does not test psfQF 165 // exclude bad detections based on: photcodes, psfQF, time range, photflags & astromBadMask, mag_inst 166 int keepMeasure = measureBig ? MeasFilterTest(&measureBig[k], FALSE) : MeasFilterTestTiny(&measure[k], FALSE); 167 if (!keepMeasure) { 168 continue; 169 } 170 171 // mark (as POOR) any measurements which are deviant from the mean by > ExcludeBogusRadius 172 if (ExcludeBogus) { 173 double Ri = getMeanR (&measure[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 174 double Di = getMeanD (&measure[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 175 coords.crval1 = catalog[i].average[j].R; 176 coords.crval2 = catalog[i].average[j].D; 177 double Xi, Yi; 178 RD_to_XY (&Xi, &Yi, Ri, Di, &coords); 179 double radius = hypot(Xi, Yi); 180 if (radius > ExcludeBogusRadius) { 181 measure[k].dbFlags |= ID_MEAS_POOR_ASTROM; 182 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_POOR_ASTROM; } 183 continue; 184 } 185 measure[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; 186 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; } 187 } 188 189 // outlier rejection 190 if (FALSE && FlagOutlier && (measure[k].dbFlags & ID_MEAS_POOR_ASTROM)) { 191 continue; 192 } 193 194 R[N] = getMeanR (&measure[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 195 D[N] = getMeanD (&measure[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 196 197 // XXX I think this is a problem: T[] is time in years relative to J2000, but ParFactor expects 198 // to get Time in years relative to UNIX Tzero (1970/01/01) 199 T[N] = (measure[k].t - T2000) / (86400*365.25) ; // time relative to J2000 in years 200 201 // dX, dY : error in arcsec -- 202 dX[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_RA); 203 dY[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_DEC); 204 205 // allow a given photcode or measurement to be 206 // ignored if the error is NAN (for photcode, set astromErrSys to NaN) 207 if (isnan(dX[N])) continue; 208 if (isnan(dY[N])) continue; 209 210 // add systematic error in quadrature, if desired 211 // only do this after the fit has converged (or you will never improve the poor images) 212 // if (INCLUDE_SYS_ERR) { 213 // float dRsys = FromShortPixels(measure[k].dRsys); 214 // dX[N] = hypot(dX[N], dRsys); 215 // dY[N] = hypot(dY[N], dRsys); 216 // } 217 218 // dX[N] = 0.1; 219 // dY[N] = 0.1; 220 221 dT[N] = measure[k].dt; 222 223 // XXX this is (slightly) inconsistent: dX,dY are the X and Y direction errors in 224 // arcseconds. dR, dD are the errors in those directions in degrees. IF we have 225 // non-circular errors (different values for X and Y), then dR and dD will be 226 // incorrect: they would need to be rotated to take out the position angle 227 dR[N] = dX[N] / 3600.0; 228 dD[N] = dY[N] / 3600.0; 229 230 if (setRefColor) { 231 float colorBlue = getColorBlue (m+k, i); 232 if (!isnan(colorBlue)) { 233 C_blue[NcBlue] = colorBlue; 234 NcBlue++; 235 } 236 float colorRed = getColorRed (m+k, i); 237 if (!isnan(colorRed)) { 238 C_red[NcRed] = colorRed; 239 NcRed++; 240 } 241 } 242 243 measure[k].dbFlags |= ID_MEAS_USED_OBJ; 244 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_USED_OBJ; } 245 246 N++; 247 } // loop over measurements : catalog[i].average[j].Nmeasure 248 249 // if we have too few good detections for the desired fit, or too limited a 250 // baseline, use a fit with fewer parameters. XXX if we have too few measurements 251 // for even the average position, consider including the lower-quality detections? 252 253 // find Tmin & Tmax from the list of accepted measurements 254 Tmean = 0; 255 Tmin = Tmax = T[0]; 256 for (k = 0; k < N; k++) { 257 Tmin = MIN(Tmin, T[k]); 258 Tmax = MAX(Tmax, T[k]); 259 Tmean += T[k]; 230 measure[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; 231 if (measureBig) { measureBig[k].dbFlags &= ~ID_MEAS_POOR_ASTROM; } 232 } 233 234 // outlier rejection 235 if (FALSE && FlagOutlier && (measure[k].dbFlags & ID_MEAS_POOR_ASTROM)) { 236 continue; 237 } 238 239 R[N] = Ri; 240 D[N] = Di; 241 242 // measure[k].t is UNIX seconds, T2000 is UNIX seconds for J2000. 243 // T[] is time in years since J2000 (jd = 2451545) 244 T[N] = (measure[k].t - T2000) / (86400*365.25) ; // time relative to J2000 in years 245 246 // dX, dY : error in arcsec -- 247 dX[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_RA); 248 dY[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_DEC); 249 250 // allow a given photcode or measurement to be 251 // ignored if the error is NAN (for photcode, set astromErrSys to NaN) 252 if (isnan(dX[N])) continue; 253 if (isnan(dY[N])) continue; 254 255 // add systematic error in quadrature, if desired 256 // only do this after the fit has converged (or you will never improve the poor images) 257 // if (INCLUDE_SYS_ERR) { 258 // float dRsys = FromShortPixels(measure[k].dRsys); 259 // dX[N] = hypot(dX[N], dRsys); 260 // dY[N] = hypot(dY[N], dRsys); 261 // } 262 263 // dX[N] = 0.1; 264 // dY[N] = 0.1; 265 266 dT[N] = measure[k].dt; 267 268 // XXX this is (slightly) inconsistent: dX,dY are the X and Y direction errors in 269 // arcseconds. dR, dD are the errors in those directions in degrees. IF we have 270 // non-circular errors (different values for X and Y), then dR and dD will be 271 // incorrect: they would need to be rotated to take out the position angle 272 dR[N] = dX[N] / 3600.0; 273 dD[N] = dY[N] / 3600.0; 274 275 if (setRefColor) { 276 float colorBlue = getColorBlue (m+k, i); 277 if (!isnan(colorBlue)) { 278 C_blue[NcBlue] = colorBlue; 279 NcBlue++; 260 280 } 261 // XXX add the parallax factor range as a criterion as well 262 Trange = Tmax - Tmin; 263 if (Trange < PM_DT_MIN) mode = FIT_AVERAGE; 264 if (((mode == FIT_PM_ONLY) || (mode == FIT_PM_AND_PAR)) && (N <= PM_TOOFEW)) mode = FIT_AVERAGE; 265 266 if (RELASTRO_OP == OP_HIGH_SPEED) { 267 Tmean = 0.5*(Tmax - Tmin); 268 } else { 269 Tmean /= (float) N; 281 float colorRed = getColorRed (m+k, i); 282 if (!isnan(colorRed)) { 283 C_red[NcRed] = colorRed; 284 NcRed++; 270 285 } 271 272 // too few measurements for average position (require 2 values) 273 if (N < SRC_MEAS_TOOFEW) { 274 if (N < 2) continue; 286 } 287 288 measure[k].dbFlags |= ID_MEAS_USED_OBJ; 289 if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_USED_OBJ; } 290 291 N++; 292 } // loop over measurements : average[0].Nmeasure 293 294 if (N < 1) { 295 if (isfinite(average[0].Rstk) && isfinite(average[0].Dstk)) { 296 average[0].R = average[0].Rstk; 297 average[0].D = average[0].Dstk; 298 average[0].dR = average[0].dRstk; 299 average[0].dD = average[0].dDstk; 300 } 301 return FALSE; 302 } 303 304 // if we have too few good detections for the desired fit, or too limited a 305 // baseline, use a fit with fewer parameters. XXX if we have too few measurements 306 // for even the average position, consider including the lower-quality detections? 307 308 // find Tmin & Tmax from the list of accepted measurements 309 double Tmean = 0.0; 310 double Tmin = T[0]; 311 double Tmax = T[0]; 312 for (k = 0; k < N; k++) { 313 Tmin = MIN(Tmin, T[k]); 314 Tmax = MAX(Tmax, T[k]); 315 Tmean += T[k]; 316 } 317 double Trange = Tmax - Tmin; 318 319 if (RELASTRO_OP == OP_HIGH_SPEED) { 320 Tmean = 0.5*(Tmax - Tmin); 321 } else { 322 Tmean /= (float) N; 323 } 324 325 /* we need to do the fit in a locally linear space; choose a ref coordinate */ 326 coords.crval1 = R[0]; 327 coords.crval2 = D[0]; 328 329 // to judge the quality of the PM and PAR fits, we need to fit all three models and compare Chisq 330 331 // *** first fit for the proper motion (skip fit if Trange or Npts is too small) *** 332 if ((mode == FIT_PM_ONLY) || (mode == FIT_PM_AND_PAR)) { 333 if (Trange < PM_DT_MIN) { 334 mode = FIT_AVERAGE; 335 goto skipPM; 336 } 337 if (N <= PM_TOOFEW) { 338 mode = FIT_AVERAGE; 339 goto skipPM; 340 } 341 342 // project all of the R,D coordinates to a plane centered on this coordinate. set 343 // the times to be relative to Tmean (this is required for parallax as well) 344 for (k = 0; k < N; k++) { 345 RD_to_XY (&X[k], &Y[k], R[k], D[k], &coords); 346 T[k] -= Tmean; 347 if (XVERB) { 348 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]); 275 349 } 276 277 /* we need to do the fit in a locally linear space; choose a ref coordinate */ 278 coords.crval1 = R[0]; 279 coords.crval2 = D[0]; 280 281 // to judge the quality of the PM and PAR fits, we need to fit all three models and compare Chisq 282 283 if ((mode == FIT_PM_ONLY) || (mode == FIT_PM_AND_PAR)) { 284 // project all of the R,D coordinates to a plane centered on this coordinate. set 285 // the times to be relative to Tmean (this is required for parallax as well) 286 for (k = 0; k < N; k++) { 287 RD_to_XY (&X[k], &Y[k], R[k], D[k], &coords); 288 T[k] -= Tmean; 289 if (XVERB) { 290 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]); 291 } 292 } 293 294 FitPM (&fitPM, X, dX, Y, dY, T, N, XVERB); 295 296 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); 297 298 // project Ro, Do back to RA,DEC 299 XY_to_RD (&fitPM.Ro, &fitPM.Do, fitPM.Ro, fitPM.Do, &coords); 300 if (XVERB) fprintf (stderr, "project: %f %f : %f %f : %f\n", fitPM.Ro, fitPM.Do, fitPM.uR, fitPM.uD, fitPM.p); 301 302 fitPM.p = fitPM.dp = 0.0; 303 catalog[i].average[j].flags |= ID_STAR_FIT_PM; 304 Npm ++; 305 306 // XXX a hard-wired hack... 307 if ((fabs(fitPM.uR) > 2.0) || (fabs(fitPM.uD) > 2.0)) { 308 mode = FIT_AVERAGE; 309 catalog[i].average[j].flags |= ID_STAR_BAD_PM; 310 } 311 } 312 313 if (mode == FIT_PM_AND_PAR) { 314 float pXmin = +2.0; 315 float pXmax = -2.0; 316 float pYmin = +2.0; 317 float pYmax = -2.0; 318 for (k = 0; k < N; k++) { 319 ParFactor (&pX[k], &pY[k], R[k], D[k], T[k], Tmean); 320 pXmin = MIN (pXmin, pX[k]); 321 pXmax = MAX (pXmax, pX[k]); 322 pYmin = MIN (pYmin, pY[k]); 323 pYmax = MAX (pYmax, pY[k]); 324 } 325 float dXRange = pXmax - pXmin; 326 float dYRange = pYmax - pYmin; 327 float parRange = hypot (dXRange, dYRange); 350 } 351 352 FitPM (&fitPM, X, dX, Y, dY, T, N, XVERB); 353 354 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); 355 356 // project Ro, Do back to RA,DEC 357 XY_to_RD (&fitPM.Ro, &fitPM.Do, fitPM.Ro, fitPM.Do, &coords); 358 if (XVERB) fprintf (stderr, "project: %f %f : %f %f : %f\n", fitPM.Ro, fitPM.Do, fitPM.uR, fitPM.uD, fitPM.p); 359 360 fitPM.p = fitPM.dp = 0.0; 361 average[0].flags |= ID_STAR_FIT_PM; 362 fitStats->Npm ++; 363 364 // XXX a hard-wired hack... 365 if ((fabs(fitPM.uR) > 2.0) || (fabs(fitPM.uD) > 2.0)) { 366 mode = FIT_AVERAGE; 367 average[0].flags |= ID_STAR_BAD_PM; 368 } 369 } 370 371 skipPM: 372 // fit the parallax + proper-motion model 373 // NOTE : we only fit PAR if we have already fitted for proper motion. if we do not fit PM or we fail 374 // to fit PM, we do not attempt PAR. thus failure to fit PAR falls back to PM-only 375 if (mode == FIT_PM_AND_PAR) { 376 if (Trange < PM_DT_MIN) { 377 mode = FIT_PM_ONLY; 378 goto skipPAR; 379 } 380 if (N <= PAR_TOOFEW) { 381 mode = FIT_PM_ONLY; 382 goto skipPAR; 383 } 384 float pXmin = +2.0; 385 float pXmax = -2.0; 386 float pYmin = +2.0; 387 float pYmax = -2.0; 388 for (k = 0; k < N; k++) { 389 ParFactor (&pX[k], &pY[k], R[k], D[k], T[k], Tmean); 390 pXmin = MIN (pXmin, pX[k]); 391 pXmax = MAX (pXmax, pX[k]); 392 pYmin = MIN (pYmin, pY[k]); 393 pYmax = MAX (pYmax, pY[k]); 394 } 395 float dXRange = pXmax - pXmin; 396 float dYRange = pYmax - pYmin; 397 float parRange = hypot (dXRange, dYRange); 328 398 329 # define PAR_TOOFEW 5 330 if ((parRange >= PAR_FACTOR_MIN) && (N > PAR_TOOFEW)) { 331 FitPMandPar (&fitPAR, X, dX, Y, dY, T, pX, pY, N, XVERB); 332 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); 333 334 XY_to_RD (&fitPAR.Ro, &fitPAR.Do, fitPAR.Ro, fitPAR.Do, &coords); 335 catalog[i].average[j].flags |= ID_STAR_FIT_PAR; 336 Npar ++; 337 338 // XXX a hard-wired hack... 339 if ((fabs(fitPAR.uR) > 2.0) || (fabs(fitPAR.uD) > 2.0)) { 340 mode = FIT_AVERAGE; 341 catalog[i].average[j].flags |= ID_STAR_BAD_PM; 342 } 343 } else { 344 // need to set mode = FIT_PM_ONLY if we do not fit for parallax 345 mode = FIT_PM_ONLY; 346 } 347 } 348 349 // fit the average model 350 if ((mode == FIT_AVERAGE) || (mode == FIT_PM_ONLY) || (mode == FIT_PM_AND_PAR)) { 351 liststats_pos (R, dR, N, &statsR, XVERB); // WARNING: this function modifies R (do not use after here) 352 liststats_pos (D, dD, N, &statsD, XVERB); // WARNING: this function modifies D (do not use after here) 353 354 fitAve.Ro = statsR.mean; 355 fitAve.dRo = 3600.0*statsR.sigma; 356 357 fitAve.Do = statsD.mean; 358 fitAve.dDo = 3600.0*statsD.sigma; 359 360 fitAve.chisq = 0.5 * (statsR.chisq + statsD.chisq); 361 fitAve.Nfit = N; 362 363 fitAve.uR = fitAve.duR = 0.0; 364 fitAve.uD = fitAve.duD = 0.0; 365 fitAve.p = fitAve.dp = 0.0; 366 catalog[i].average[j].flags |= ID_STAR_FIT_AVE; 367 Nave ++; 368 } 369 370 if (setRefColor) { 371 float colorMedian; 372 dsort (C_blue, NcBlue); 373 colorMedian = (NcBlue > 0) ? C_blue[(int)(0.5*NcBlue)] : NAN; 374 catalog[i].average[j].refColorBlue = colorMedian; 375 dsort (C_red, NcRed); 376 colorMedian = (NcRed > 0) ? C_red[(int)(0.5*NcRed)] : NAN; 377 catalog[i].average[j].refColorRed = colorMedian; 378 } 379 380 /* choose the result based on the chisq values */ 381 // XXXX for now, just use the mode as the result: 382 result = mode; 383 384 switch (result) { 385 case FIT_AVERAGE: 386 catalog[i].average[j].flags |= ID_STAR_USE_AVE; 387 fit = fitAve; 388 break; 389 case FIT_PM_ONLY: 390 catalog[i].average[j].flags |= ID_STAR_USE_PM; 391 fit = fitPM; 392 break; 393 case FIT_PM_AND_PAR: 394 catalog[i].average[j].flags |= ID_STAR_USE_PAR; 395 fit = fitPAR; 396 break; 397 } 398 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f) pm=(%f %f) plx=(%f +/- %f)\n", 399 catalog[i].average[j].R, 400 catalog[i].average[j].D, 401 fit.Ro, fit.Do, 402 3600*(catalog[i].average[j].R - fit.Ro), 403 3600*(catalog[i].average[j].D - fit.Do), 404 fit.uR, fit.uD, fit.p, fit.dp); 405 406 // make sure that the fit succeeded 407 status = TRUE; 408 status &= finite(fit.Ro); 409 status &= finite(fit.Do); 410 status &= finite(fit.dRo); 411 status &= finite(fit.dDo); 412 status &= finite(fit.uR); 413 status &= finite(fit.uD); 414 status &= finite(fit.duR); 415 status &= finite(fit.duD); 416 status &= finite(fit.p); 417 status &= finite(fit.dp); 418 if (!status) { 419 Nskip ++; 420 continue; 421 } 422 423 // what is the offset relative to the mean fit position? 424 coords.crval1 = catalog[i].average[j].R; 425 coords.crval2 = catalog[i].average[j].D; 426 427 double dXoff, dYoff; 428 RD_to_XY (&dXoff, &dYoff, fit.Ro, fit.Do, &coords); 429 float dPos = hypot (dXoff, dYoff); 430 if (dPos > MaxMeanOffset) { 431 if (Noffset < 100) { 432 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", coords.crval1, coords.crval2, fit.Ro, fit.Do, dXoff, dYoff); 433 } 434 Noffset ++; 435 continue; 436 } 437 438 439 // the measure fields must be updated before the average fields 440 for (k = 0; k < catalog[i].average[j].Nmeasure; k++) { 441 setMeanR (fit.Ro, &measure[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 442 setMeanD (fit.Do, &measure[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 443 if (measureBig) { 444 setMeanR_Big (fit.Ro, &measureBig[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 445 setMeanD_Big (fit.Do, &measureBig[k], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]); 446 } 447 } 448 449 catalog[i].average[j].R = fit.Ro; // RA in degrees 450 catalog[i].average[j].D = fit.Do; // DEC in degrees 451 catalog[i].average[j].dR = fit.dRo; // RA scatter in arcsec 452 catalog[i].average[j].dD = fit.dDo; // DEC scatter in arcsec 453 454 catalog[i].average[j].uR = fit.uR; // RA proper motion in arcsec/year 455 catalog[i].average[j].uD = fit.uD; // DEC proper motion in arcsec/year 456 catalog[i].average[j].duR = fit.duR; // RA proper motion error in arcsec/year 457 catalog[i].average[j].duD = fit.duD; // DEC proper motion error in arcsec/year 458 459 catalog[i].average[j].P = fit.p; // parallax in arcsec 460 catalog[i].average[j].dP = fit.dp; // parallax error in arcsec 461 462 catalog[i].average[j].ChiSqAve = fitAve.chisq; 463 catalog[i].average[j].ChiSqPM = fitPM.chisq; 464 catalog[i].average[j].ChiSqPar = fitPAR.chisq; 465 catalog[i].average[j].Tmean = (Tmean * 86400 * 365.25) + T2000; 466 catalog[i].average[j].Trange = (Trange * 86400 * 365.25); 467 catalog[i].average[j].Npos = fit.Nfit; 468 469 // XXX EAM 20140812: for a test, set average.Rstk,Dstk, etc to match R,D 470 catalog[i].average[j].Rstk = fit.Ro; // RA in degrees 471 catalog[i].average[j].Dstk = fit.Do; // DEC in degrees 472 catalog[i].average[j].dRstk = fit.dRo; // RA scatter in arcsec 473 catalog[i].average[j].dDstk = fit.dDo; // DEC scatter in arcsec 474 475 // unset the NO_ASTROM bit (not(NO_ASTROM) == HAVE_ASTROM) 476 catalog[i].average[j].flags &= ~ID_STAR_NO_ASTROM; 477 478 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f) pm=(%f %f) chisq=(%f, %f, %f)\n", 479 catalog[i].average[j].R, 480 catalog[i].average[j].D, 481 fit.Ro, fit.Do, 482 3600*(catalog[i].average[j].R - fit.Ro), 483 3600*(catalog[i].average[j].D - fit.Do), 484 catalog[i].average[j].uR, 485 catalog[i].average[j].uD, 486 fitAve.chisq, fitPM.chisq, fitPAR.chisq); 487 } 488 489 NaveSum += Nave; 490 NpmSum += Npm; 491 NparSum += Npar; 492 NskipSum += Nskip; 493 NoffSum += Noffset; 494 if (VERBOSE) fprintf (stderr, "catalog %d : "OFF_T_FMT" ave, "OFF_T_FMT" pm, "OFF_T_FMT" par : Nskip "OFF_T_FMT", Noffset "OFF_T_FMT"\n", i, Nave, Npm, Npar, Nskip, Noffset); 495 } 496 497 freeObjectData (); 498 499 if (VERBOSE) 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", (NaveSum + NpmSum + NparSum), NaveSum, NpmSum, NparSum, NskipSum, NoffSum); 399 if (parRange < PAR_FACTOR_MIN) { 400 mode = FIT_PM_ONLY; 401 goto skipPAR; 402 } 403 404 FitPMandPar (&fitPAR, X, dX, Y, dY, T, pX, pY, N, XVERB); 405 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); 406 407 XY_to_RD (&fitPAR.Ro, &fitPAR.Do, fitPAR.Ro, fitPAR.Do, &coords); 408 average[0].flags |= ID_STAR_FIT_PAR; 409 fitStats->Npar ++; 410 411 // XXX a hard-wired hack... 412 if ((fabs(fitPAR.uR) > 2.0) || (fabs(fitPAR.uD) > 2.0)) { 413 mode = FIT_PM_ONLY; 414 } 415 } 416 417 skipPAR: 418 { 419 // ALWAYS fit the average model 420 StatType statsR, statsD; 421 liststats_pos (R, dR, N, &statsR, XVERB); // WARNING: this function modifies R (do not use after here) 422 liststats_pos (D, dD, N, &statsD, XVERB); // WARNING: this function modifies D (do not use after here) 423 424 fitAve.Ro = statsR.mean; 425 fitAve.dRo = 3600.0*statsR.sigma; 426 427 fitAve.Do = statsD.mean; 428 fitAve.dDo = 3600.0*statsD.sigma; 429 430 fitAve.chisq = (N > 1) ? 0.5 * (statsR.chisq + statsD.chisq) : NAN; 431 fitAve.Nfit = N; 432 433 fitAve.uR = fitAve.duR = 0.0; 434 fitAve.uD = fitAve.duD = 0.0; 435 fitAve.p = fitAve.dp = 0.0; 436 average[0].flags |= ID_STAR_FIT_AVE; 437 fitStats->Nave ++; 438 } 439 440 if (setRefColor) { 441 float colorMedian; 442 dsort (C_blue, NcBlue); 443 colorMedian = (NcBlue > 0) ? C_blue[(int)(0.5*NcBlue)] : NAN; 444 average[0].refColorBlue = colorMedian; 445 dsort (C_red, NcRed); 446 colorMedian = (NcRed > 0) ? C_red[(int)(0.5*NcRed)] : NAN; 447 average[0].refColorRed = colorMedian; 448 } 449 450 /* choose the result based on the chisq values */ 451 // XXXX for now, just use the mode as the result: 452 int result = mode; 453 454 switch (result) { 455 case FIT_AVERAGE: 456 average[0].flags |= ID_STAR_USE_AVE; 457 fit = fitAve; 458 break; 459 case FIT_PM_ONLY: 460 average[0].flags |= ID_STAR_USE_PM; 461 fit = fitPM; 462 break; 463 case FIT_PM_AND_PAR: 464 average[0].flags |= ID_STAR_USE_PAR; 465 fit = fitPAR; 466 break; 467 } 468 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f) pm=(%f %f) plx=(%f +/- %f)\n", 469 average[0].R, 470 average[0].D, 471 fit.Ro, fit.Do, 472 3600*(average[0].R - fit.Ro), 473 3600*(average[0].D - fit.Do), 474 fit.uR, fit.uD, fit.p, fit.dp); 475 476 // make sure that the fit succeeded 477 int status = TRUE; 478 status &= finite(fit.Ro); 479 status &= finite(fit.Do); 480 status &= finite(fit.dRo); 481 status &= finite(fit.dDo); 482 status &= finite(fit.uR); 483 status &= finite(fit.uD); 484 status &= finite(fit.duR); 485 status &= finite(fit.duD); 486 status &= finite(fit.p); 487 status &= finite(fit.dp); 488 if (!status) { 489 fitStats->Nskip ++; 490 return FALSE; // XXX ?? 491 } 492 493 // what is the offset relative to the mean fit position? 494 coords.crval1 = average[0].R; 495 coords.crval2 = average[0].D; 496 497 double dXoff, dYoff; 498 RD_to_XY (&dXoff, &dYoff, fit.Ro, fit.Do, &coords); 499 float dPos = hypot (dXoff, dYoff); 500 if (dPos > MaxMeanOffset) { 501 if (fitStats->Noffset < 100) { 502 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", coords.crval1, coords.crval2, fit.Ro, fit.Do, dXoff, dYoff); 503 } 504 fitStats->Noffset ++; 505 return FALSE; // XXX ?? 506 } 507 508 average[0].R = fit.Ro; // RA in degrees 509 average[0].D = fit.Do; // DEC in degrees 510 average[0].dR = fit.dRo; // RA scatter in arcsec 511 average[0].dD = fit.dDo; // DEC scatter in arcsec 512 513 average[0].uR = fit.uR; // RA proper motion in arcsec/year 514 average[0].uD = fit.uD; // DEC proper motion in arcsec/year 515 average[0].duR = fit.duR; // RA proper motion error in arcsec/year 516 average[0].duD = fit.duD; // DEC proper motion error in arcsec/year 517 518 average[0].P = fit.p; // parallax in arcsec 519 average[0].dP = fit.dp; // parallax error in arcsec 520 521 average[0].ChiSqAve = fitAve.chisq; 522 average[0].ChiSqPM = fitPM.chisq; 523 average[0].ChiSqPar = fitPAR.chisq; 524 525 average[0].Tmean = (Tmean * 86400 * 365.25) + T2000; 526 average[0].Trange = (Trange * 86400 * 365.25); 527 average[0].Npos = fit.Nfit; 528 529 // unset the NO_ASTROM bit (not(NO_ASTROM) == HAVE_ASTROM) 530 average[0].flags &= ~ID_STAR_NO_ASTROM; 531 532 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f) pm=(%f %f) chisq=(%f, %f, %f)\n", 533 average[0].R, 534 average[0].D, 535 fit.Ro, fit.Do, 536 3600*(average[0].R - fit.Ro), 537 3600*(average[0].D - fit.Do), 538 average[0].uR, 539 average[0].uD, 540 fitAve.chisq, fitPM.chisq, fitPAR.chisq); 541 500 542 return (TRUE); 501 543 } 544 545 // This function operates on both Measure and MeasureTiny. In the big stages, this should 546 // be called with just MeasureTiny set and Measure == NULL 547 int UpdateObjects_Stack (Average *average, SecFilt *secfilt, MeasureTiny *measure, Measure *measureBig, int Nsecfilt, FitStats *fitStats) { 548 549 off_t k; 550 551 // set the default values 552 average[0].Rstk = NAN; // RA in degrees 553 average[0].Dstk = NAN; // DEC in degrees 554 average[0].dRstk = NAN; // RA scatter in arcsec 555 average[0].dDstk = NAN; // DEC scatter in arcsec 556 557 /* calculate the average value of R,D for a single star */ 558 PMFit fitAve; 559 memset (&fitAve, 0, sizeof(fitAve)); 560 fitAve.chisq = NAN; 561 562 if (average[0].Nmeasure == 0) return TRUE; 563 564 int N = 0; 565 566 int XVERB = FALSE; 567 XVERB |= (average[0].objID == OBJ_ID_SRC) && (average[0].catID == CAT_ID_SRC); 568 XVERB |= (average[0].objID == OBJ_ID_DST) && (average[0].catID == CAT_ID_DST); 569 570 // find the basic properties of the detections for this object (Tmin, Tmax, Tmean) 571 for (k = 0; k < average[0].Nmeasure; k++) { 572 573 if (XVERB) { 574 char *date = ohana_sec_to_date (measure[k].t); 575 int dbFlagsBig = measureBig ? measureBig[k].dbFlags : 0; 576 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); 577 free (date); 578 } 579 580 // SKIP everything except gpc1 stack data 581 if (!isGPC1stack(measure[k].photcode)) continue; 582 583 // exclude bad detections based on: photcodes, psfQF, time range, photflags & astromBadMask, mag_inst 584 int keepMeasure = measureBig ? MeasFilterTest(&measureBig[k], FALSE) : MeasFilterTestTiny(&measure[k], FALSE); 585 if (!keepMeasure) { 586 continue; 587 } 588 589 R[N] = getMeanR (&measure[k], average, secfilt); 590 D[N] = getMeanD (&measure[k], average, secfilt); 591 592 // dX, dY : error in arcsec -- 593 dX[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_RA); 594 dY[N] = GetAstromErrorTiny (&measure[k], ERROR_MODE_DEC); 595 596 // allow a given photcode or measurement to be 597 // ignored if the error is NAN (for photcode, set astromErrSys to NaN) 598 if (isnan(dX[N])) continue; 599 if (isnan(dY[N])) continue; 600 601 // XXX this is (slightly) inconsistent: dX,dY are the X and Y direction errors in 602 // arcseconds. dR, dD are the errors in those directions in degrees. IF we have 603 // non-circular errors (different values for X and Y), then dR and dD will be 604 // incorrect: they would need to be rotated to take out the position angle 605 dR[N] = dX[N] / 3600.0; 606 dD[N] = dY[N] / 3600.0; 607 608 // XXX use a different flag for stack measurements? 609 // measure[k].dbFlags |= ID_MEAS_USED_OBJ; 610 // if (measureBig) { measureBig[k].dbFlags |= ID_MEAS_USED_OBJ; } 611 612 N++; 613 } // loop over measurements : average[0].Nmeasure 614 615 // if we have too few good detections for the desired fit, or too limited a 616 // baseline, use a fit with fewer parameters. XXX if we have too few measurements 617 // for even the average position, consider including the lower-quality detections? 618 619 // too few measurements for average position (require 2 values) 620 if (N < 1) return FALSE; // XXX ?? 621 622 // find the mean position 623 StatType statsR, statsD; 624 liststats_pos (R, dR, N, &statsR, XVERB); // WARNING: this function modifies R (do not use after here) 625 liststats_pos (D, dD, N, &statsD, XVERB); // WARNING: this function modifies D (do not use after here) 626 627 fitAve.Ro = statsR.mean; 628 fitAve.dRo = 3600.0*statsR.sigma; 629 630 fitAve.Do = statsD.mean; 631 fitAve.dDo = 3600.0*statsD.sigma; 632 633 fitAve.chisq = 0.5 * (statsR.chisq + statsD.chisq); 634 fitAve.Nfit = N; 635 636 // XXX choose stack flag? average[0].flags |= ID_STAR_FIT_AVE; 637 fitStats->Nave ++; 638 639 if (XVERB) fprintf (stderr, "%f %f -> %f %f (%f,%f)\n", 640 average[0].R, 641 average[0].D, 642 fitAve.Ro, fitAve.Do, 643 3600*(average[0].R - fitAve.Ro), 644 3600*(average[0].D - fitAve.Do)); 645 646 // make sure that the fit succeeded 647 int status = TRUE; 648 status &= finite(fitAve.Ro); 649 status &= finite(fitAve.Do); 650 status &= finite(fitAve.dRo); 651 status &= finite(fitAve.dDo); 652 if (!status) { 653 fitStats->Nskip ++; 654 return FALSE; 655 } 656 657 // what is the offset relative to the mean fit position? 658 coords.crval1 = average[0].R; 659 coords.crval2 = average[0].D; 660 661 double dXoff, dYoff; 662 RD_to_XY (&dXoff, &dYoff, fitAve.Ro, fitAve.Do, &coords); 663 float dPos = hypot (dXoff, dYoff); 664 if (dPos > MaxMeanOffset) { 665 if (fitStats->Noffset < 100) { 666 fprintf (stderr, "(%f,%f) -> (%f,%f) (%f,%f)\n", coords.crval1, coords.crval2, fitAve.Ro, fitAve.Do, dXoff, dYoff); 667 } 668 fitStats->Noffset ++; 669 return FALSE; 670 } 671 672 // set the stack position values 673 average[0].Rstk = fitAve.Ro; // RA in degrees 674 average[0].Dstk = fitAve.Do; // DEC in degrees 675 average[0].dRstk = fitAve.dRo; // RA scatter in arcsec 676 average[0].dDstk = fitAve.dDo; // DEC scatter in arcsec 677 678 return (TRUE); 679 } 680 681 502 682 503 683 /* fitting proper-motion and parallax:
Note:
See TracChangeset
for help on using the changeset viewer.
