Changeset 19515
- Timestamp:
- Sep 11, 2008, 3:09:39 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/psastro/src/psastroModelAdjust.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psastro/src/psastroModelAdjust.c
r15891 r19515 1 1 # include "psastroStandAlone.h" 2 2 # define NONLIN_TOL 0.001 /* tolerance in pixels */ 3 # define DEBUG 0 4 5 bool psastroModelAdjustBoresite (pmFPAfile *output, pmChip *refChip); 3 6 4 7 bool psastroModelAdjust (pmConfig *config) { … … 13 16 } 14 17 18 // if we have not measured the boresite position, no adjustment is needed 19 bool fitBoresite = psMetadataLookupBool (&status, recipe, "PSASTRO.MODEL.FIT.BORESITE"); 20 if (!status) psAbort ("Can't find recipe option PSASTRO.MODEL.FIT.BORESITE"); 21 22 // as an alternative to fit the boresite from a rotation sequence, we can set the boresite 23 // relative to the reference chip coordinates 24 bool setBoresite = psMetadataLookupBool (&status, recipe, "PSASTRO.MODEL.SET.BORESITE"); 25 if (!status) psAbort ("Can't find recipe option PSASTRO.MODEL.SET.BORESITE"); 26 27 if (fitBoresite && setBoresite) { 28 psError(PS_ERR_IO, true, "invalid to choose both FIT.BORESITE and SET.BORESITE"); 29 return false; 30 } 31 15 32 pmFPAfile *output = psMetadataLookupPtr (&status, config->files, "PSASTRO.OUT.MODEL"); 16 33 if (!status) psAbort ("Can't find output pmFPAfile PSASTRO.OUT.MODEL"); … … 29 46 if (!refChip->toFPA) psAbort ("invalid astrometry for reference chip"); 30 47 31 psPlane *boreCH = psPlaneAlloc(); 32 psPlane *boreFP = psPlaneAlloc(); 33 psPlane *boreTP = psPlaneAlloc(); 48 // save the TPA region for tranformation inversions below 49 // psRegion *tpaRegion = pmAstromFPInTP (output->fpa); 50 psRegion *fpaRegion = pmAstromFPAExtent (output->fpa); 51 52 if (DEBUG) psastroDumpCorners ("corners.up.raw.dat", "corners.dn.raw.dat", output->fpa); 53 54 if (setBoresite) { 55 float boreXchip = psMetadataLookupF32 (&status, recipe, "PSASTRO.MODEL.BORESITE.X"); 56 float boreYchip = psMetadataLookupF32 (&status, recipe, "PSASTRO.MODEL.BORESITE.Y"); 57 psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.X0", PS_META_REPLACE, "boresite parameter", boreXchip); 58 psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.Y0", PS_META_REPLACE, "boresite parameter", boreYchip); 59 } 60 61 if (fitBoresite || setBoresite) { 62 psastroModelAdjustBoresite (output, refChip); 63 } else { 64 // FPA.BORE.X0,Y0 should be 0,0 in the focal plane, not the chip. Ask for the 65 // coordinates which make refChip->toFPA(x,y) = (0,0) 66 psPlane *PT = psPlaneTransformGetCenter (refChip->toFPA, NONLIN_TOL); 67 psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.X0", PS_META_REPLACE, "boresite parameter", PT->x); 68 psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.BORE.Y0", PS_META_REPLACE, "boresite parameter", PT->y); 69 psFree (PT); 70 } 71 72 // rotate the chip-to-FPA transforms to have 0.0 posangle for refChip; 73 // compensate by rotating fpa to TPA transform 74 75 // get the current posangle of the ref chip 76 float chipAngle = atan2 (refChip->toFPA->y->coeff[1][0], refChip->toFPA->x->coeff[1][0]); 77 fprintf (stderr, "chipAngle: %f\n", chipAngle*PS_DEG_RAD); 78 // psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "boresite parameter", posangle); 79 80 // rotate the chip transforms 81 for (int i = 0; i < output->fpa->chips->n; i++) { 82 pmChip *chip = output->fpa->chips->data[i]; 83 if (!chip->toFPA) continue; 84 // skip chips without astrometry 85 86 // save the region of this chip for the inversion below 87 psRegion *region = pmChipPixels (chip); 88 89 psPlaneTransform *toFPA = psPlaneTransformRotate (NULL, chip->toFPA, chipAngle); 90 psFree (chip->toFPA); 91 chip->toFPA = toFPA; 92 93 // invert the new fromFPA transform to get the new toFPA transform 94 psPlaneTransform *fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50); 95 psFree (chip->fromFPA); 96 chip->fromFPA = fromFPA; 97 98 psFree (region); 99 100 // save the transformation in the header 101 pmAstromWriteBilevelChip (chip->hdu->header, chip, NONLIN_TOL); 102 } 103 104 // get the current posangle of the fpa 105 float fpaAngle = atan2 (output->fpa->toTPA->y->coeff[1][0], output->fpa->toTPA->x->coeff[1][0]); 106 fprintf (stderr, "fpaAngle: %f\n", fpaAngle*PS_DEG_RAD); 107 // psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "boresite parameter", posangle); 108 109 // remove the fpa rotation to generate a rotation-free model 110 psPlaneTransform *toTPA = psPlaneTransformRotate (NULL, output->fpa->toTPA, fpaAngle); 111 psFree (output->fpa->toTPA); 112 output->fpa->toTPA = toTPA; 113 114 psFree (output->fpa->fromTPA); 115 output->fpa->fromTPA = psPlaneTransformInvert(NULL, output->fpa->toTPA, *fpaRegion, 50); 116 117 // the model now describes the unrotated focal-plane 118 if (DEBUG) psastroDumpCorners ("corners.up.rot.dat", "corners.dn.rot.dat", output->fpa); 119 120 psMetadata *header = output->fpa->hdu->header; 121 pmAstromWriteBilevelMosaic (header, output->fpa, NONLIN_TOL); 122 123 psFree (fpaRegion); 124 125 return true; 126 } 127 128 bool psastroModelAdjustBoresite (pmFPAfile *output, pmChip *refChip) { 129 130 bool status; 131 132 psPlane *boreCH = psPlaneAlloc(); 133 psPlane *boreFP = psPlaneAlloc(); 134 psPlane *boreTP = psPlaneAlloc(); 34 135 psSphere *boreSky = psSphereAlloc(); 35 136 … … 46 147 // skip the chips without astrometry 47 148 48 psPlaneTransform *fromFPA = psPlaneTransformSetCenter (NULL, chip->fromFPA, boreFP->x, boreFP->y); 149 // save the FPA region of this chip for the inversion below 150 psRegion *region = pmChipPixels (chip); 151 152 // the current toFPA returns boreFP->x,y for the boresite; subtract this from the transformations 153 chip->toFPA->x->coeff[0][0] -= boreFP->x; 154 chip->toFPA->y->coeff[0][0] -= boreFP->y; 155 156 // psPlaneTransform *toFPA = psPlaneTransformSetCenter (NULL, chip->toFPA, -boreFP->x, -boreFP->y); 157 // psFree (chip->toFPA); 158 // chip->toFPA = toFPA; 159 160 // invert the new fromFPA transform to get the new toFPA transform 161 // the region used here is the region covered by the chip in the FPA 162 psPlaneTransform *fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50); 49 163 psFree (chip->fromFPA); 50 164 chip->fromFPA = fromFPA; 51 165 52 // invert the new fromFPA transform to get the new toFPA transform53 psRegion *region = pmChipPixels (chip);54 psFree (chip->toFPA);55 chip->toFPA = psPlaneTransformInvert(NULL, chip->fromFPA, *region, 50);56 166 psFree (region); 57 167 } 58 168 59 // XXX we have now shifted the (0,0) pixel of the focal plane to the true boresite from the 60 // reported boresite. At this point, we need to shift the tangent plane to use the new 61 // center as well. if the toTPA transform were not linear, we would need to modify fromFPA 62 // to yield 0,0 at the new boresite location (ie, find Po,Qo = toTPA(Lo,Mo), probably could modify the 63 // toTPA/fromTPA transforms to use the new ref pixel, but this would only give us a tranf 64 65 // save the old (L,M) = (0,0) TP coordinate 66 float Po = output->fpa->toTPA->x->coeff[0][0]; 67 float Qo = output->fpa->toTPA->y->coeff[0][0]; 68 69 // the new toTPA yields the same TP coordinates for FP coordinates offset by Lo,Mo 70 psPlaneTransform *toTPA = psPlaneTransformSetCenter (NULL, output->fpa->toTPA, boreFP->x, boreFP->y); 71 psFree (output->fpa->toTPA); 72 output->fpa->toTPA = toTPA; 73 74 // we are going to shift P,Q to have toTPA(0,0) = Po, Qo. 75 // find the sky coordinates of the 0,0 pixel for the new frame 76 boreTP->x = output->fpa->toTPA->x->coeff[0][0] - Po; 77 boreTP->y = output->fpa->toTPA->y->coeff[0][0] - Qo; 169 if (DEBUG) psastroDumpCorners ("corners.up.shf.dat", "corners.dn.shf.dat", output->fpa); 170 171 // we have now adjusted the chips to use the correct boresite position as the center of the focal-plane system. 172 // we now need to reconstruct the TP to FP transformation, starting from stars projected about this new boresite position. 173 174 // find the R,D of the new boresite (boreFP -> 0,0; 0,0 -> -boreFP) 175 boreFP->x = -boreFP->x; 176 boreFP->y = -boreFP->y; 177 psPlaneTransformApply (boreTP, output->fpa->toTPA, boreFP); 78 178 psDeproject (boreSky, boreTP, output->fpa->toSky); // find the RA,DEC coord of the focal-plane coordinate 79 179 80 // adjust the new TP frame to yield the same old (L,M) = 0,0 TP coordinate: 81 output->fpa->toTPA->x->coeff[0][0] = Po; 82 output->fpa->toTPA->y->coeff[0][0] = Qo; 83 84 // set the projection to use the new (P,Q) = (0,0) position 85 output->fpa->toSky->R = boreSky->r; 86 output->fpa->toSky->D = boreSky->d; 87 180 psProjection *newSky = psProjectionAlloc (boreSky->r, boreSky->d, output->fpa->toSky->Xs, output->fpa->toSky->Ys, output->fpa->toSky->type); 181 182 // generate a collection of points on the sky using the old toTPA transformation and toSky projection, projected with the newSky projection 183 // this is the FPA coordinate range covered by the FP: 88 184 psRegion *fpaRegion = pmAstromFPAExtent (output->fpa); 89 90 psFree (output->fpa->fromTPA); 91 output->fpa->fromTPA = psPlaneTransformInvert(NULL, output->fpa->toTPA, *fpaRegion, 50); 92 93 // rotate the chip to FPA transforms to have 0.0 posangle; 94 // compensate by rotating fpa to TPA transforms 95 96 // get the current posangle of the ref chip 97 float posangle = atan2 (refChip->toFPA->y->coeff[1][0], refChip->toFPA->x->coeff[1][0]); 98 psMetadataAddF32 (output->fpa->concepts, PS_LIST_TAIL, "FPA.POSANGLE", PS_META_REPLACE, "boresite parameter", posangle); 99 100 // rotate the chip transforms 101 for (int i = 0; i < output->fpa->chips->n; i++) { 102 pmChip *chip = output->fpa->chips->data[i]; 103 if (!chip->toFPA) continue; 104 // skip chips without astrometry 105 106 psPlaneTransform *toFPA = psPlaneTransformRotate (NULL, chip->toFPA, posangle); 107 psFree (chip->toFPA); 108 chip->toFPA = toFPA; 109 110 // invert the new fromFPA transform to get the new toFPA transform 111 psRegion *region = pmChipPixels (chip); 112 psFree (chip->fromFPA); 113 chip->fromFPA = psPlaneTransformInvert(NULL, chip->toFPA, *region, 50); 114 psFree (region); 115 116 // XXX temporary output dump 117 psMetadata *header = chip->hdu->header; 118 // XXX to make the output single-level, this needs to be in a loop *after* the fromTPA rotation below 119 // pmAstromWriteWCS (header, output->fpa, chip, NONLIN_TOL); 120 pmAstromWriteBilevelChip (header, chip, NONLIN_TOL); 121 } 122 123 psPlaneTransform *fromTPA = psPlaneTransformRotate (NULL, output->fpa->fromTPA, posangle); 124 psFree (output->fpa->fromTPA); 125 output->fpa->fromTPA = fromTPA; 126 127 psFree (output->fpa->toTPA); 128 output->fpa->toTPA = psPlaneTransformInvert(NULL, output->fpa->fromTPA, *fpaRegion, 50); 129 130 psMetadata *header = output->fpa->hdu->header; 131 pmAstromWriteBilevelMosaic (header, output->fpa, NONLIN_TOL); 132 185 float dx = (fpaRegion->x1 - fpaRegion->x0) / 50.0; 186 float dy = (fpaRegion->y1 - fpaRegion->y0) / 50.0; 187 188 psPlane fp, tp; 189 psSphere sky; 190 191 psVector *FPx = psVectorAllocEmpty (100, PS_TYPE_F32); 192 psVector *FPy = psVectorAllocEmpty (100, PS_TYPE_F32); 193 psVector *TPx = psVectorAllocEmpty (100, PS_TYPE_F32); 194 psVector *TPy = psVectorAllocEmpty (100, PS_TYPE_F32); 195 196 // XXX a test: boreFP->x,y, should transform to tp.x,y = 0,0 197 fp.x = boreFP->x; 198 fp.y = boreFP->y; 199 psPlaneTransformApply (&tp, output->fpa->toTPA, &fp); 200 psDeproject (&sky, &tp, output->fpa->toSky); // find the RA,DEC coord of the focal-plane coordinate 201 psProject (&tp, &sky, newSky); // find the RA,DEC coord of the focal-plane coordinate 202 203 int Npts = 0; 204 for (fp.x = fpaRegion->x0; fp.x <= fpaRegion->x1; fp.x += dx) { 205 for (fp.y = fpaRegion->y0; fp.y <= fpaRegion->y1; fp.y += dy) { 206 psPlaneTransformApply (&tp, output->fpa->toTPA, &fp); 207 psDeproject (&sky, &tp, output->fpa->toSky); // find the RA,DEC coord of the focal-plane coordinate 208 psProject (&tp, &sky, newSky); // find the RA,DEC coord of the focal-plane coordinate 209 210 // we are fitting points in the NEW FP system to points in the NEW TP system 211 FPx->data.F32[Npts] = fp.x - boreFP->x; 212 FPy->data.F32[Npts] = fp.y - boreFP->y; 213 TPx->data.F32[Npts] = tp.x; 214 TPy->data.F32[Npts] = tp.y; 215 psVectorExtend (FPx, 100, 1); 216 psVectorExtend (FPy, 100, 1); 217 psVectorExtend (TPx, 100, 1); 218 psVectorExtend (TPy, 100, 1); 219 Npts ++; 220 } 221 } 133 222 psFree (fpaRegion); 134 223 224 // fit both up and down transformations to the same points 225 psVectorFitPolynomial2D (output->fpa->toTPA->x, NULL, 0, TPx, NULL, FPx, FPy); 226 psVectorFitPolynomial2D (output->fpa->toTPA->y, NULL, 0, TPy, NULL, FPx, FPy); 227 psVectorFitPolynomial2D (output->fpa->fromTPA->x, NULL, 0, FPx, NULL, TPx, TPy); 228 psVectorFitPolynomial2D (output->fpa->fromTPA->y, NULL, 0, FPy, NULL, TPx, TPy); 229 230 psFree (output->fpa->toSky); 231 output->fpa->toSky = newSky; 232 233 if (DEBUG) psastroDumpCorners ("corners.up.bore.dat", "corners.dn.bore.dat", output->fpa); 234 235 psFree (FPx); 236 psFree (FPy); 237 psFree (TPx); 238 psFree (TPy); 239 240 psFree (boreCH); 241 psFree (boreFP); 242 psFree (boreTP); 243 psFree (boreSky); 135 244 return true; 136 245 }
Note:
See TracChangeset
for help on using the changeset viewer.
