IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Sep 15, 2016, 3:10:46 PM (10 years ago)
Author:
eugene
Message:

rather than attempt to force the WRP chip-level CRVAL1,2 entries to be (0,0), we re-work the keywords to use CRPIX1,2 = (0,0)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/czw_branch/20160809/psModules/src/astrom/pmAstrometryWCS.c

    r39685 r39697  
    4343    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
    4444    if (!wcs) {
    45         return false;
     45        return false;
    4646    }
    4747
     
    7070    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
    7171    if (!wcs) {
    72         return false;
     72        return false;
    7373    }
    7474
     
    8686    pmAstromWCS *wcs = pmAstromWCSfromHeader (header);
    8787    if (!wcs) {
    88         psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from header");
    89         return false;
     88        psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from header");
     89        return false;
    9090    }
    9191
     
    9696
    9797    if (!status1 || !status2) {
    98         Nx = psMetadataLookupS32 (&status1, header, "IMNAXIS1");
    99         Ny = psMetadataLookupS32 (&status2, header, "IMNAXIS2");
     98        Nx = psMetadataLookupS32 (&status1, header, "IMNAXIS1");
     99        Ny = psMetadataLookupS32 (&status2, header, "IMNAXIS2");
    100100    }
    101101
    102102    if (!status1 || !status2) {
    103         Nx = psMetadataLookupS32 (&status1, header, "ZNAXIS1");
    104         Ny = psMetadataLookupS32 (&status2, header, "ZNAXIS2");
     103        Nx = psMetadataLookupS32 (&status1, header, "ZNAXIS1");
     104        Ny = psMetadataLookupS32 (&status2, header, "ZNAXIS2");
    105105    }
    106106
    107107    if (!status1 || !status2) {
    108         psFree (wcs);
    109         psError(PS_ERR_UNKNOWN, false, "missing required FPA size in header");
    110         return false;
     108        psFree (wcs);
     109        psError(PS_ERR_UNKNOWN, false, "missing required FPA size in header");
     110        return false;
    111111    }
    112112
     
    123123    pmAstromWCS *wcs = pmAstromWCSBilevelChipFromFPA (chip, tol);
    124124    if (!wcs) {
    125         psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa");
    126         return false;
     125        psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa");
     126        return false;
    127127    }
    128128
     
    139139    pmAstromWCS *wcs = pmAstromWCSBilevelMosaicFromFPA (fpa, tol);
    140140    if (!wcs) {
    141         psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa");
    142         return false;
     141        psError(PS_ERR_UNKNOWN, false, "failure to determine WCS terms from fpa");
     142        return false;
    143143    }
    144144
     
    163163
    164164    if (chip == NULL)
    165         return false;
     165        return false;
    166166    if (sky == NULL)
    167         return false;
     167        return false;
    168168    if (wcs == NULL)
    169         return false;
     169        return false;
    170170
    171171    psPlane *Chip = psPlaneAlloc();
     
    188188
    189189    if (chip == NULL)
    190         return false;
     190        return false;
    191191    if (sky == NULL)
    192         return false;
     192        return false;
    193193    if (wcs == NULL)
    194         return false;
     194        return false;
    195195
    196196    psError(PS_ERR_UNKNOWN, true, "not yet implemented: needs to invert the transformation");
     
    223223    char *ctype = psMetadataLookupPtr (&status, header, "CTYPE2");
    224224    if (!status) {
    225         psLogMsg ("psastro", 5, "warning: no WCS metadata in header\n");
    226         return NULL;
     225        psLogMsg ("psastro", 5, "warning: no WCS metadata in header\n");
     226        return NULL;
    227227    }
    228228
     
    232232    type = psProjectTypeFromString (ctype);
    233233    if (type == PS_PROJ_NTYPE) {
    234         psLogMsg ("psastro", 2, "warning: unknown projection type %s\n", ctype);
    235         return NULL;
     234        psLogMsg ("psastro", 2, "warning: unknown projection type %s\n", ctype);
     235        return NULL;
    236236    }
    237237
     
    243243
    244244    if (cdKeys && pcKeys) {
    245         // XXX make this an option
    246         psLogMsg ("psastro", 5, "warning: both CDi_j and PC00i00j defined in headers, using PC00i00j terms\n");
     245        // XXX make this an option
     246        psLogMsg ("psastro", 5, "warning: both CDi_j and PC00i00j defined in headers, using PC00i00j terms\n");
    247247    }
    248248    if (!cdKeys && !pcKeys) {
    249         psError(PS_ERR_UNKNOWN, true, "missing both CDi_j and PC00i00j WCS terms");
    250         // XXX we could default here to RA, DEC, ROTANGLE
    251         return NULL;
     249        psError(PS_ERR_UNKNOWN, true, "missing both CDi_j and PC00i00j WCS terms");
     250        // XXX we could default here to RA, DEC, ROTANGLE
     251        return NULL;
    252252    }
    253253    if (isPoly) {
    254         if (!pcKeys) {
    255             psError(PS_ERR_UNKNOWN, true, "polynomial terms defined, but missing PC00i00j WCS terms");
    256             return NULL;
    257         }
    258         if (fitOrder == 0)
    259             fitOrder = 1;
    260         if ((fitOrder > 3) || (fitOrder < 1)) {
    261             psError(PS_ERR_UNKNOWN, true, "NPLYTERM value undefined: %d", fitOrder);
    262             return NULL;
    263         }
     254        if (!pcKeys) {
     255            psError(PS_ERR_UNKNOWN, true, "polynomial terms defined, but missing PC00i00j WCS terms");
     256            return NULL;
     257        }
     258        if (fitOrder == 0)
     259            fitOrder = 1;
     260        if ((fitOrder > 3) || (fitOrder < 1)) {
     261            psError(PS_ERR_UNKNOWN, true, "NPLYTERM value undefined: %d", fitOrder);
     262            return NULL;
     263        }
    264264    } else {
    265         fitOrder = 1;
     265        fitOrder = 1;
    266266    }
    267267
     
    280280    // XXX if type == ZPN, look for PV2_%d elements:
    281281    if (type == PS_PROJ_ZPN) {
    282       psVector *maxRadial = psVectorAlloc (21, PS_TYPE_F64);
    283       for (int i = 0; i <= 20; i++) {
    284         char name[64];
    285         snprintf (name, 64, "PV2_%d", i);
    286 
    287         maxRadial->data.F64[i] = 0.0;
    288         double value = psMetadataLookupF64 (&status, header, name);
    289 
    290         if (status) {
    291           maxRadial->data.F64[i] = value;
    292           maxRadial->n = i;
    293         }
    294 
    295         // PV2_1 is implicit if not present
    296         if ((i == 1) && !status) {
    297           maxRadial->data.F64[i] = 1.0;
    298           continue;
    299         }
    300       }
    301       maxRadial->n ++;
    302       wcs->toSky->radial = maxRadial;
     282        psVector *maxRadial = psVectorAlloc (21, PS_TYPE_F64);
     283        for (int i = 0; i <= 20; i++) {
     284            char name[64];
     285            snprintf (name, 64, "PV2_%d", i);
     286
     287            maxRadial->data.F64[i] = 0.0;
     288            double value = psMetadataLookupF64 (&status, header, name);
     289
     290            if (status) {
     291                maxRadial->data.F64[i] = value;
     292                maxRadial->n = i;
     293            }
     294
     295            // PV2_1 is implicit if not present
     296            if ((i == 1) && !status) {
     297                maxRadial->data.F64[i] = 1.0;
     298                continue;
     299            }
     300        }
     301        maxRadial->n ++;
     302        wcs->toSky->radial = maxRadial;
    303303    }
    304304
     
    314314    // test the CDELTi varient
    315315    if (pcKeys) {
    316         wcs->wcsCDkeys = 0;
    317         wcs->cdelt1 = psMetadataLookupF64 (&status, header, "CDELT1");
    318         wcs->cdelt2 = psMetadataLookupF64 (&status, header, "CDELT2");
    319 
    320         // test the CROTAi varient:
    321         // XXX double check lambda..
    322         double rotate = psMetadataLookupF64 (&status, header, "CROTA2");
    323         if (status) {
    324             wcs->trans->x->coeff[1][0] = +wcs->cdelt1 * cos(rotate*PM_RAD_DEG); // == PC1_1
    325             wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2
    326             wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1
    327             wcs->trans->y->coeff[0][1] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2
    328             return wcs;
    329         }
    330 
    331         // FITS WCS PCi,j has units of unity
    332         // wcs->trans has units of degrees/pixel
    333         wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC001001"); // == PC1_1
    334         wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC001002"); // == PC1_2
    335         wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC002001"); // == PC2_1
    336         wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC002002"); // == PC2_2
    337 
    338         if (isPoly) {
    339             // Elixir-style polynomial terms
    340             // XXX currently, Elixir/DVO cannot accept mixed orders
    341             for (int i = 0; i <= fitOrder; i++) {
    342                 for (int j = 0; j <= fitOrder; j++) {
    343                     if (i + j < 2)
    344                         continue;
    345                     if (i + j > fitOrder) {
    346                         wcs->trans->x->coeffMask[i][j] = PS_POLY_MASK_SET;
    347                         wcs->trans->y->coeffMask[i][j] = PS_POLY_MASK_SET;
    348                         continue;
    349                     }
    350                     sprintf (name, "PCA1X%1dY%1d", i, j);
    351                     wcs->trans->x->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);
    352                     sprintf (name, "PCA2X%1dY%1d", i, j);
    353                     wcs->trans->y->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);
    354                 }
    355             }
    356         }
    357         return wcs;
     316        wcs->wcsCDkeys = 0;
     317        wcs->cdelt1 = psMetadataLookupF64 (&status, header, "CDELT1");
     318        wcs->cdelt2 = psMetadataLookupF64 (&status, header, "CDELT2");
     319
     320        // test the CROTAi varient:
     321        // XXX double check lambda..
     322        double rotate = psMetadataLookupF64 (&status, header, "CROTA2");
     323        if (status) {
     324            wcs->trans->x->coeff[1][0] = +wcs->cdelt1 * cos(rotate*PM_RAD_DEG); // == PC1_1
     325            wcs->trans->x->coeff[0][1] = -wcs->cdelt2 * sin(rotate*PM_RAD_DEG); // == PC1_2
     326            wcs->trans->y->coeff[1][0] = +wcs->cdelt1 * sin(rotate*PM_RAD_DEG); // == PC2_1
     327            wcs->trans->y->coeff[0][1] = +wcs->cdelt2 * cos(rotate*PM_RAD_DEG); // == PC2_2
     328            return wcs;
     329        }
     330
     331        // FITS WCS PCi,j has units of unity
     332        // wcs->trans has units of degrees/pixel
     333        wcs->trans->x->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC001001"); // == PC1_1
     334        wcs->trans->x->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC001002"); // == PC1_2
     335        wcs->trans->y->coeff[1][0] = wcs->cdelt1 * psMetadataLookupF64 (&status, header, "PC002001"); // == PC2_1
     336        wcs->trans->y->coeff[0][1] = wcs->cdelt2 * psMetadataLookupF64 (&status, header, "PC002002"); // == PC2_2
     337
     338        if (isPoly) {
     339            // Elixir-style polynomial terms
     340            // XXX currently, Elixir/DVO cannot accept mixed orders
     341            for (int i = 0; i <= fitOrder; i++) {
     342                for (int j = 0; j <= fitOrder; j++) {
     343                    if (i + j < 2)
     344                        continue;
     345                    if (i + j > fitOrder) {
     346                        wcs->trans->x->coeffMask[i][j] = PS_POLY_MASK_SET;
     347                        wcs->trans->y->coeffMask[i][j] = PS_POLY_MASK_SET;
     348                        continue;
     349                    }
     350                    sprintf (name, "PCA1X%1dY%1d", i, j);
     351                    wcs->trans->x->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);
     352                    sprintf (name, "PCA2X%1dY%1d", i, j);
     353                    wcs->trans->y->coeff[i][j] = pow(wcs->cdelt1, i) * pow(wcs->cdelt2, j) * psMetadataLookupF64 (&status, header, name);
     354                }
     355            }
     356        }
     357        return wcs;
    358358    }
    359359
    360360    // test the CDi_j varient
    361361    if (cdKeys) {
    362         wcs->wcsCDkeys = 1;
    363 
    364         wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1
    365         wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2
    366         wcs->trans->y->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD2_1"); // == PC2_1
    367         wcs->trans->y->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD2_2"); // == PC2_2
    368         wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
    369         wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
    370         return wcs;
     362        wcs->wcsCDkeys = 1;
     363
     364        wcs->trans->x->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD1_1"); // == PC1_1
     365        wcs->trans->x->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD1_2"); // == PC1_2
     366        wcs->trans->y->coeff[1][0] = psMetadataLookupF64 (&status, header, "CD2_1"); // == PC2_1
     367        wcs->trans->y->coeff[0][1] = psMetadataLookupF64 (&status, header, "CD2_2"); // == PC2_2
     368        wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
     369        wcs->cdelt2 = hypot (wcs->trans->y->coeff[1][0], wcs->trans->y->coeff[0][1]);
     370        return wcs;
    371371    }
    372372    psLogMsg ("psastro", 2, "warning: missing rotation matrix?\n");
     
    402402
    403403    if (wcs->toSky->type == PS_PROJ_ZPN) {
    404       psAssert (wcs->toSky->radial, "missing radial vector");
    405       for (int i = 0; i < wcs->toSky->radial->n; i++) {
    406         if (wcs->toSky->radial->data.F64[i] == 0.0) continue;
    407         snprintf (name, 16, "PV2_%d", i);
    408         psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->toSky->radial->data.F64[i]);
    409       }
     404        psAssert (wcs->toSky->radial, "missing radial vector");
     405        for (int i = 0; i < wcs->toSky->radial->n; i++) {
     406            if (wcs->toSky->radial->data.F64[i] == 0.0) continue;
     407            snprintf (name, 16, "PV2_%d", i);
     408            psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->toSky->radial->data.F64[i]);
     409        }
    410410    }
    411411
     
    414414    if (!wcs->wcsCDkeys) {
    415415
    416       double cdelt1 = wcs->cdelt1;
    417       double cdelt2 = wcs->cdelt2;
    418       psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1);
    419       psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2);
    420 
    421       // test the PC00i00j varient:
    422       psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1
    423       psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2
    424       psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1
    425       psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2
    426 
    427       // Elixir-style polynomial terms
    428       // XXX currently, Elixir/DVO cannot accept mixed orders
    429       // XXX need to respect the masks
    430       // XXX is wcs->cdelt1,2 always consistent?
    431       int fitOrder = wcs->trans->x->nX;
    432       if (fitOrder > 1) {
    433         for (int i = 0; i <= fitOrder; i++) {
    434           for (int j = 0; j <= fitOrder; j++) {
    435             if (i + j < 2)
    436               continue;
    437             if (i + j > fitOrder)
    438               continue;
    439             sprintf (name, "PCA1X%1dY%1d", i, j);
    440             psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
    441             sprintf (name, "PCA2X%1dY%1d", i, j);
    442             psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
    443           }
    444         }
    445         psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", fitOrder);
    446       }
    447 
    448       // remove any existing 'CDi_j style' wcs keywords
    449       if (psMetadataLookup(header, "CD1_1")) {
    450         psMetadataRemoveKey(header, "CD1_1");
    451         psMetadataRemoveKey(header, "CD1_2");
    452         psMetadataRemoveKey(header, "CD2_1");
    453         psMetadataRemoveKey(header, "CD2_2");
    454       }
    455 
    456       // Remove 'CDi_jX' WCS keywords
    457       psString cd11 = psStringCopy("CD1_1 ");
    458       psString cd12 = psStringCopy("CD1_2 ");
    459       psString cd21 = psStringCopy("CD2_1 ");
    460       psString cd22 = psStringCopy("CD2_2 ");
    461       for (char extra = 'A'; extra <= 'Z'; extra++) {
    462           cd11[strlen(cd11)-1] = extra;
    463           if (psMetadataLookup(header, cd11)) {
    464               cd12[strlen(cd12)-1] = extra;
    465               cd21[strlen(cd21)-1] = extra;
    466               cd22[strlen(cd22)-1] = extra;
    467               psMetadataRemoveKey(header, cd11);
    468               psMetadataRemoveKey(header, cd12);
    469               psMetadataRemoveKey(header, cd21);
    470               psMetadataRemoveKey(header, cd22);
    471           }
    472       }
    473       psFree(cd11);
    474       psFree(cd12);
    475       psFree(cd21);
    476       psFree(cd22);
     416        double cdelt1 = wcs->cdelt1;
     417        double cdelt2 = wcs->cdelt2;
     418        psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT1", PS_META_REPLACE, "", cdelt1);
     419        psMetadataAddF64 (header, PS_LIST_TAIL, "CDELT2", PS_META_REPLACE, "", cdelt2);
     420
     421        // test the PC00i00j varient:
     422        psMetadataAddF64 (header, PS_LIST_TAIL, "PC001001", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0] / cdelt1); // == PC1_1
     423        psMetadataAddF64 (header, PS_LIST_TAIL, "PC001002", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1] / cdelt2); // == PC1_2
     424        psMetadataAddF64 (header, PS_LIST_TAIL, "PC002001", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0] / cdelt1); // == PC2_1
     425        psMetadataAddF64 (header, PS_LIST_TAIL, "PC002002", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1] / cdelt2); // == PC2_2
     426
     427        // Elixir-style polynomial terms
     428        // XXX currently, Elixir/DVO cannot accept mixed orders
     429        // XXX need to respect the masks
     430        // XXX is wcs->cdelt1,2 always consistent?
     431        int fitOrder = wcs->trans->x->nX;
     432        if (fitOrder > 1) {
     433            for (int i = 0; i <= fitOrder; i++) {
     434                for (int j = 0; j <= fitOrder; j++) {
     435                    if (i + j < 2)
     436                        continue;
     437                    if (i + j > fitOrder)
     438                        continue;
     439                    sprintf (name, "PCA1X%1dY%1d", i, j);
     440                    psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->x->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
     441                    sprintf (name, "PCA2X%1dY%1d", i, j);
     442                    psMetadataAddF64 (header, PS_LIST_TAIL, name, PS_META_REPLACE, "", wcs->trans->y->coeff[i][j] / pow(cdelt1, i) / pow(cdelt2, j));
     443                }
     444            }
     445            psMetadataAddS32 (header, PS_LIST_TAIL, "NPLYTERM", PS_META_REPLACE, "", fitOrder);
     446        }
     447
     448        // remove any existing 'CDi_j style' wcs keywords
     449        if (psMetadataLookup(header, "CD1_1")) {
     450            psMetadataRemoveKey(header, "CD1_1");
     451            psMetadataRemoveKey(header, "CD1_2");
     452            psMetadataRemoveKey(header, "CD2_1");
     453            psMetadataRemoveKey(header, "CD2_2");
     454        }
     455
     456        // Remove 'CDi_jX' WCS keywords
     457        psString cd11 = psStringCopy("CD1_1 ");
     458        psString cd12 = psStringCopy("CD1_2 ");
     459        psString cd21 = psStringCopy("CD2_1 ");
     460        psString cd22 = psStringCopy("CD2_2 ");
     461        for (char extra = 'A'; extra <= 'Z'; extra++) {
     462            cd11[strlen(cd11)-1] = extra;
     463            if (psMetadataLookup(header, cd11)) {
     464                cd12[strlen(cd12)-1] = extra;
     465                cd21[strlen(cd21)-1] = extra;
     466                cd22[strlen(cd22)-1] = extra;
     467                psMetadataRemoveKey(header, cd11);
     468                psMetadataRemoveKey(header, cd12);
     469                psMetadataRemoveKey(header, cd21);
     470                psMetadataRemoveKey(header, cd22);
     471            }
     472        }
     473        psFree(cd11);
     474        psFree(cd12);
     475        psFree(cd21);
     476        psFree(cd22);
    477477
    478478
    479479    } else {
    480480
    481       psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_1", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0]);
    482       psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_2", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1]);
    483       psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_1", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0]);
    484       psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_2", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1]);
    485 
    486       if (psMetadataLookup(header, "PC001001")) {
    487         psMetadataRemoveKey(header, "PC001001");
    488         psMetadataRemoveKey(header, "PC001002");
    489         psMetadataRemoveKey(header, "PC002001");
    490         psMetadataRemoveKey(header, "PC002002");
    491       }
     481        psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_1", PS_META_REPLACE, "", wcs->trans->x->coeff[1][0]);
     482        psMetadataAddF64 (header, PS_LIST_TAIL, "CD1_2", PS_META_REPLACE, "", wcs->trans->x->coeff[0][1]);
     483        psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_1", PS_META_REPLACE, "", wcs->trans->y->coeff[1][0]);
     484        psMetadataAddF64 (header, PS_LIST_TAIL, "CD2_2", PS_META_REPLACE, "", wcs->trans->y->coeff[0][1]);
     485
     486        if (psMetadataLookup(header, "PC001001")) {
     487            psMetadataRemoveKey(header, "PC001001");
     488            psMetadataRemoveKey(header, "PC001002");
     489            psMetadataRemoveKey(header, "PC002001");
     490            psMetadataRemoveKey(header, "PC002002");
     491        }
    492492    }
    493493
     
    507507    // cdelt1,2 has units of degree/pixel
    508508    for (int i = 0; i <= toFPA->x->nX; i++) {
    509         for (int j = 0; j <= toFPA->x->nX; j++) {
    510             toFPA->x->coeff[i][j] *= pixelScale/wcs->cdelt1;
    511             toFPA->y->coeff[i][j] *= pixelScale/wcs->cdelt2;
    512         }
     509        for (int j = 0; j <= toFPA->x->nX; j++) {
     510            toFPA->x->coeff[i][j] *= pixelScale/wcs->cdelt1;
     511            toFPA->y->coeff[i][j] *= pixelScale/wcs->cdelt2;
     512        }
    513513    }
    514514
     
    524524        psFree(fpa->toTPA);
    525525        psFree(fpa->fromTPA);
    526         fpa->toTPA = psPlaneTransformIdentity (1);
    527         fpa->fromTPA = psPlaneTransformIdentity (1);
    528         fpa->toSky = toSky;
     526        fpa->toTPA = psPlaneTransformIdentity (1);
     527        fpa->fromTPA = psPlaneTransformIdentity (1);
     528        fpa->toSky = toSky;
    529529    } else {
    530530
    531         // this section allows the loaded chip to be included in an fpa structure in which
    532         // other chips have already been loaded (ie, the fpa->toTPA, fpa->toSky components have
    533         // already been defined).  we have to adjust to match the existing transformation.
    534 
    535         if (fpa->toTPA == NULL)
    536             psAbort("projection defined, tangent-plane not defined");
    537         if (fpa->fromTPA == NULL)
    538             psAbort("projection defined, tangent-plane not defined");
    539 
    540         // convert from pixels on this chip to pixels on reference chip
    541         // rX has units of refpixels / pixel
    542         double rX = toSky->Xs / fpa->toSky->Xs;
    543         double rY = toSky->Ys / fpa->toSky->Ys;
    544 
    545         for (int i = 0; i <= toFPA->x->nX; i++) {
    546             for (int j = 0; j <= toFPA->x->nY; j++) {
    547                 toFPA->x->coeff[i][j] *= rX;
    548                 toFPA->y->coeff[i][j] *= rY;
    549             }
    550         }
    551 
    552         // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter
    553         // XXX this only works if toTPA is at most a linear transformation
    554         psPlaneTransform *toFPAnew = psPlaneTransformAlloc(toFPA->x->nX, toFPA->x->nY);
    555         for (int i = 0; i <= toFPA->x->nX; i++) {
    556           for (int j = 0; j <= toFPA->x->nY; j++) {
    557             double f1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[1][0]*toFPA->x->coeff[i][j];
    558             double f2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[0][1]*toFPA->y->coeff[i][j];
    559             toFPAnew->x->coeff[i][j] = f1 + f2;
    560 
    561             double g1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[1][0]*toFPA->x->coeff[i][j];
    562             double g2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[0][1]*toFPA->y->coeff[i][j];
    563             toFPAnew->y->coeff[i][j] = g1 + g2;
    564           }
    565         }
    566         toFPAnew->x->coeff[0][0] += fpa->fromTPA->x->coeff[0][0];
    567         toFPAnew->y->coeff[0][0] += fpa->fromTPA->y->coeff[0][0];
    568 
    569         psFree (toFPA);
    570         toFPA = toFPAnew;
    571 
    572         // adjust reference pixel for new toSky reference coordinate
    573         // find the FPA coordinate of 0,0 for this chip.
    574         psPlane *fpOld = psPlaneAlloc();
    575         psPlane *fpNew = psPlaneAlloc();
    576         psPlane *tp = psPlaneAlloc();
    577         psSphere *sky = psSphereAlloc();
    578 
    579         sky->r = toSky->R;
    580         sky->d = toSky->D;
    581         psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection
    582         psPlaneTransformApply (fpOld, fpa->fromTPA, tp);
    583 
    584         sky->r = fpa->toSky->R;
    585         sky->d = fpa->toSky->D;
    586         psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection
    587         psPlaneTransformApply (fpNew, fpa->fromTPA, tp);
    588 
    589         toFPA->x->coeff[0][0] -= fpNew->x - fpOld->x;
    590         toFPA->y->coeff[0][0] -= fpNew->y - fpOld->y;
    591 
    592         psFree (sky);
    593         psFree (tp);
    594         psFree (fpOld);
    595         psFree (fpNew);
    596 
    597         psFree (toSky);
     531        // this section allows the loaded chip to be included in an fpa structure in which
     532        // other chips have already been loaded (ie, the fpa->toTPA, fpa->toSky components have
     533        // already been defined).  we have to adjust to match the existing transformation.
     534
     535        if (fpa->toTPA == NULL)
     536            psAbort("projection defined, tangent-plane not defined");
     537        if (fpa->fromTPA == NULL)
     538            psAbort("projection defined, tangent-plane not defined");
     539
     540        // convert from pixels on this chip to pixels on reference chip
     541        // rX has units of refpixels / pixel
     542        double rX = toSky->Xs / fpa->toSky->Xs;
     543        double rY = toSky->Ys / fpa->toSky->Ys;
     544
     545        for (int i = 0; i <= toFPA->x->nX; i++) {
     546            for (int j = 0; j <= toFPA->x->nY; j++) {
     547                toFPA->x->coeff[i][j] *= rX;
     548                toFPA->y->coeff[i][j] *= rY;
     549            }
     550        }
     551
     552        // apply the exiting fromTPA transformation to make the new toFPA consistent with the toTPA layter
     553        // XXX this only works if toTPA is at most a linear transformation
     554        psPlaneTransform *toFPAnew = psPlaneTransformAlloc(toFPA->x->nX, toFPA->x->nY);
     555        for (int i = 0; i <= toFPA->x->nX; i++) {
     556            for (int j = 0; j <= toFPA->x->nY; j++) {
     557                double f1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[1][0]*toFPA->x->coeff[i][j];
     558                double f2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->x->coeff[0][1]*toFPA->y->coeff[i][j];
     559                toFPAnew->x->coeff[i][j] = f1 + f2;
     560
     561                double g1 = toFPA->x->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[1][0]*toFPA->x->coeff[i][j];
     562                double g2 = toFPA->y->coeffMask[i][j] ? 0.0 : fpa->fromTPA->y->coeff[0][1]*toFPA->y->coeff[i][j];
     563                toFPAnew->y->coeff[i][j] = g1 + g2;
     564            }
     565        }
     566        toFPAnew->x->coeff[0][0] += fpa->fromTPA->x->coeff[0][0];
     567        toFPAnew->y->coeff[0][0] += fpa->fromTPA->y->coeff[0][0];
     568
     569        psFree (toFPA);
     570        toFPA = toFPAnew;
     571
     572        // adjust reference pixel for new toSky reference coordinate
     573        // find the FPA coordinate of 0,0 for this chip.
     574        psPlane *fpOld = psPlaneAlloc();
     575        psPlane *fpNew = psPlaneAlloc();
     576        psPlane *tp = psPlaneAlloc();
     577        psSphere *sky = psSphereAlloc();
     578
     579        sky->r = toSky->R;
     580        sky->d = toSky->D;
     581        psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection
     582        psPlaneTransformApply (fpOld, fpa->fromTPA, tp);
     583
     584        sky->r = fpa->toSky->R;
     585        sky->d = fpa->toSky->D;
     586        psProject (tp, sky, fpa->toSky); // find the focal-plane coord of this RA,DEC coord using the ref chip projection
     587        psPlaneTransformApply (fpNew, fpa->fromTPA, tp);
     588
     589        toFPA->x->coeff[0][0] -= fpNew->x - fpOld->x;
     590        toFPA->y->coeff[0][0] -= fpNew->y - fpOld->y;
     591
     592        psFree (sky);
     593        psFree (tp);
     594        psFree (fpOld);
     595        psFree (fpNew);
     596
     597        psFree (toSky);
    598598    }
    599599
     
    613613    // XXX if the inversion fails, we probably do not have a valid transform anyway
    614614    if (!chip->fromFPA) {
    615       psWarning ("failed to find a valid transformation");
    616       psFree (chip->toFPA);
    617       return false;
     615        psWarning ("failed to find a valid transformation");
     616        psFree (chip->toFPA);
     617        return false;
    618618    }
    619619
    620620    // this can take a very long time...
    621621    while (fpa->toSky->R < 0)
    622         fpa->toSky->R += 2.0*M_PI;
     622        fpa->toSky->R += 2.0*M_PI;
    623623    while (fpa->toSky->R > 2.0*M_PI)
    624         fpa->toSky->R -= 2.0*M_PI;
     624        fpa->toSky->R -= 2.0*M_PI;
    625625
    626626    fpa->wcsCDkeys = wcs->wcsCDkeys;
    627627
    628628    psTrace ("psastro", 5, "toFPA: %f %f  (%f,%f),(%f,%f)\n",
    629              chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0],
    630              chip->toFPA->x->coeff[1][0], chip->toFPA->x->coeff[0][1],
    631              chip->toFPA->y->coeff[1][0], chip->toFPA->y->coeff[0][1]);
     629             chip->toFPA->x->coeff[0][0], chip->toFPA->y->coeff[0][0],
     630             chip->toFPA->x->coeff[1][0], chip->toFPA->x->coeff[0][1],
     631             chip->toFPA->y->coeff[1][0], chip->toFPA->y->coeff[0][1]);
    632632
    633633    psTrace ("psastro", 5, "frFPA: %f %f  (%f,%f),(%f,%f)\n",
    634              chip->fromFPA->x->coeff[0][0], chip->fromFPA->y->coeff[0][0],
    635              chip->fromFPA->x->coeff[1][0], chip->fromFPA->x->coeff[0][1],
    636              chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]);
     634             chip->fromFPA->x->coeff[0][0], chip->fromFPA->y->coeff[0][0],
     635             chip->fromFPA->x->coeff[1][0], chip->fromFPA->x->coeff[0][1],
     636             chip->fromFPA->y->coeff[1][0], chip->fromFPA->y->coeff[0][1]);
    637637
    638638    return true;
     
    648648     */
    649649
    650     // create transformation with 0,0 reference pixel and units of microns/pixel
    651650    psFree (chip->toFPA);
    652     chip->toFPA = psPlaneTransformSetCenter (NULL, wcs->trans, -wcs->crpix1, -wcs->crpix2);
     651    chip->toFPA = psPlaneTransformAlloc(wcs->trans->x->nX, wcs->trans->x->nY);
     652
     653    // copy the toFPA x,y, transformations to the wcs version
     654    chip->toFPA->x = psPolynomial2DCopy (chip->toFPA->x, wcs->trans->x);
     655    chip->toFPA->y = psPolynomial2DCopy (chip->toFPA->y, wcs->trans->y);
     656
     657    // these need to be set based on crval1,2
     658    chip->toFPA->x->coeff[0][0] = wcs->crval1;
     659    chip->toFPA->y->coeff[0][0] = wcs->crval2;
    653660
    654661    // determine the inverse transformation: we need the chip pixels covered by this transform
     
    675682    // convert fpa->toTPA to units of unity (microns/micron)
    676683    for (int i = 0; i <= fpa->toTPA->x->nX; i++) {
    677         for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
    678             fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1;
    679             fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2;
    680         }
     684        for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
     685            fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1;
     686            fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2;
     687        }
    681688    }
    682689
     
    720727
    721728    for (int i = 0; i <= toTPA->x->nX; i++) {
    722         for (int j = 0; j <= toTPA->x->nY; j++) {
    723             double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];
    724             double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];
    725             toTPA->x->coeff[i][j] = f1 + f2;
    726 
    727             double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];
    728             double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];
    729             toTPA->y->coeff[i][j] = g1 + g2;
    730         }
     729        for (int j = 0; j <= toTPA->x->nY; j++) {
     730            double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];
     731            double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];
     732            toTPA->x->coeff[i][j] = f1 + f2;
     733
     734            double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];
     735            double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];
     736            toTPA->y->coeff[i][j] = g1 + g2;
     737        }
    731738    }
    732739    toTPA->x->coeff[0][0] += fpa->toTPA->x->coeff[0][0];
     
    752759    psPlane *center = psPlaneTransformGetCenter (tpa1, tol);
    753760    if (!center) {
    754         psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
    755         psFree (toTPA);
    756         psFree (tpa1);
    757         psFree (wcs);
    758         return NULL;
     761        psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
     762        psFree (toTPA);
     763        psFree (tpa1);
     764        psFree (wcs);
     765        return NULL;
    759766    }
    760767
     
    789796    // convert wcs->trans to a matrix with units of degrees/pixel
    790797    for (int i = 0; i <= wcs->trans->x->nX; i++) {
    791         for (int j = 0; j <= wcs->trans->x->nY; j++) {
    792             wcs->trans->x->coeff[i][j] *= pdelt1;
    793             wcs->trans->y->coeff[i][j] *= pdelt2;
    794         }
     798        for (int j = 0; j <= wcs->trans->x->nY; j++) {
     799            wcs->trans->x->coeff[i][j] *= pdelt1;
     800            wcs->trans->y->coeff[i][j] *= pdelt2;
     801        }
    795802    }
    796803
     
    811818*/
    812819
    813 // convert the chip-level toFPA to a wcs polynomial transformation
     820// convert the chip-level toFPA to a wcs polynomial transformation.  the pmAstromWCS
     821// structure represents a single layer transformation (e.g., RA-TAN, RA-WRP).  Here we are
     822// converting the chip-level to a WRP projection in the structure.  Later, this will be
     823// converted to the WCS keywords
     824
    814825pmAstromWCS *pmAstromWCSBilevelChipFromFPA (const pmChip *chip, double tol)
    815826{
     
    822833    pmAstromWCS *wcs = pmAstromWCSAlloc(chip->toFPA->x->nX, chip->toFPA->x->nY);
    823834
     835    // copy the toFPA x,y, transformations to the wcs version
     836    wcs->trans->x = psPolynomial2DCopy (wcs->trans->x, chip->toFPA->x);
     837    wcs->trans->y = psPolynomial2DCopy (wcs->trans->y, chip->toFPA->y);
     838
    824839    // Chip to FPA transformation is a Cartesian 'projection'
    825840    // reference pixel for FPA is 0.0, 0.0
    826841    wcs->toSky = psProjectionAlloc (0.0, 0.0, 1.0, 1.0, PS_PROJ_WRP);
    827     wcs->crval1 = 0.0;
    828     wcs->crval2 = 0.0;
    829 
    830     // given transformation, solve for coordinates which yields output coordinates of 0,0
    831     psPlane *center = psPlaneTransformGetCenter (chip->toFPA, tol);
    832     if (!center) {
    833         psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
    834         psFree (wcs);
    835         return NULL;
    836     }
    837 
    838     // adjust wcs transform to use center as reference coordinate
    839     // resulting transformation has units of microns/pixel
    840     psPlaneTransformSetCenter (wcs->trans, chip->toFPA, center->x, center->y);
    841 
    842     // calculated center is crpix1,2
    843     wcs->crpix1 = center->x;
    844     wcs->crpix2 = center->y;
    845     psFree (center);
    846 
     842
     843    // reference pixel (CRPIX1,2) is (0.0, 0.0):
     844    wcs->crpix1 = 0.0;
     845    wcs->crpix2 = 0.0;
     846
     847    // we need to set CRVAL1,2 for the 0,0 pixel:
     848    wcs->crval1 = psPolynomial2DEval (chip->toFPA->x, 0.0, 0.0);
     849    wcs->crval2 = psPolynomial2DEval (chip->toFPA->y, 0.0, 0.0);
     850
     851    wcs->toSky->R = wcs->crval1*PM_RAD_DEG;
     852    wcs->toSky->D = wcs->crval2*PM_RAD_DEG;
     853
     854    // these need to be set to 0.0 since they have been moved to crpix1,crpix2
     855    wcs->trans->x->coeff[0][0] = 0.0;
     856    wcs->trans->y->coeff[0][0] = 0.0;
     857   
    847858    // output coordinates are in microns : CDELT1,2 has units of microns/pixel
    848859    wcs->cdelt1 = hypot (wcs->trans->x->coeff[1][0], wcs->trans->x->coeff[0][1]);
     
    872883    psPlane *center = psPlaneTransformGetCenter (fpa->toTPA, tol);
    873884    if (!center) {
    874         psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
    875         psFree (wcs);
    876         return NULL;
     885        psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
     886        psFree (wcs);
     887        return NULL;
    877888    }
    878889
     
    892903    // convert wcs->trans to units of degree/micron
    893904    for (int i = 0; i <= wcs->trans->x->nX; i++) {
    894         for (int j = 0; j <= wcs->trans->x->nY; j++) {
    895             wcs->trans->x->coeff[i][j] *= pdelt1;
    896             wcs->trans->y->coeff[i][j] *= pdelt2;
    897         }
     905        for (int j = 0; j <= wcs->trans->x->nY; j++) {
     906            wcs->trans->x->coeff[i][j] *= pdelt1;
     907            wcs->trans->y->coeff[i][j] *= pdelt2;
     908        }
    898909    }
    899910
     
    918929    int k=0;
    919930    for (int j=0; j<nSamples; j++) {
    920         double y = bounds->y0 + (j * deltaY / nSamples);
    921         for (int i=0; i<nSamples; i++) {
    922             psPlane *s = psPlaneAlloc();
    923             s->x = bounds->x0 + (i * deltaX / nSamples);
    924             s->y = y;
    925             psArraySet(src, k, s);
    926             psPlane *d = psPlaneTransformApply(NULL, trans, s);
    927             psArraySet(dst, k, d);
    928             psFree(s);  // drop our refs to s and d
    929             psFree(d);
    930             ++k;
    931         }
     931        double y = bounds->y0 + (j * deltaY / nSamples);
     932        for (int i=0; i<nSamples; i++) {
     933            psPlane *s = psPlaneAlloc();
     934            s->x = bounds->x0 + (i * deltaX / nSamples);
     935            s->y = y;
     936            psArraySet(src, k, s);
     937            psPlane *d = psPlaneTransformApply(NULL, trans, s);
     938            psArraySet(dst, k, d);
     939            psFree(s);  // drop our refs to s and d
     940            psFree(d);
     941            ++k;
     942        }
    932943    }
    933944
     
    935946
    936947    if (!psPlaneTransformFit(newTrans, src, dst, 0, 0)) {
    937         psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
    938         return NULL;
     948        psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
     949        return NULL;
    939950    }
    940951
     
    945956    printf("   i     chip_x  tpa_x     tpa_x_fit     dx         chip_y    tpa_y     tpa_y_fit     dy     dx > 0.5 || dy > 0.5\n");
    946957    for (int i=0; i<psArrayLength(dst); i++) {
    947         psPlane *d = (psPlane *) psArrayGet(dst, i);
    948         psPlane *s = (psPlane *) psArrayGet(src, i);
    949 
    950         new = psPlaneTransformApply(new, newTrans, s);
    951 
    952         double xerr = new->x - d->x;
    953         double yerr = new->y - d->y;
    954         bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5);
    955         printf("%4d %9.2f %9.2f %9.2f %9.4f     %9.2f %9.2f %9.2f %9.4f   %s\n"
    956         , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : "");
     958        psPlane *d = (psPlane *) psArrayGet(dst, i);
     959        psPlane *s = (psPlane *) psArrayGet(src, i);
     960
     961        new = psPlaneTransformApply(new, newTrans, s);
     962
     963        double xerr = new->x - d->x;
     964        double yerr = new->y - d->y;
     965        bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5);
     966        printf("%4d %9.2f %9.2f %9.2f %9.4f     %9.2f %9.2f %9.2f %9.4f   %s\n"
     967               , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : "");
    957968    }
    958969    psFree(new);
     
    972983
    973984    if (outFPA == NULL) {
    974         outFPA = inFPA;
     985        outFPA = inFPA;
    975986    }
    976987    if (outChip == NULL) {
    977         outChip = inChip;
     988        outChip = inChip;
    978989    }
    979990    if (outputBounds == NULL) {
    980         outputBounds = pmChipPixels(outChip);
     991        outputBounds = pmChipPixels(outChip);
    981992    }
    982993
     
    984995    psPlaneTransform *chipToTPA = psPlaneTransformCombine(NULL, inChip->toFPA, inFPA->toTPA, *outputBounds, 50);
    985996    if (!chipToTPA) {
    986         psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA");
    987         return false;
     997        psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA");
     998        return false;
    988999    }
    9891000
     
    9921003    psFree(chipToTPA);
    9931004    if (!chipToFPA) {
    994         psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed");
    995         return false;
     1005        psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed");
     1006        return false;
    9961007    }
    9971008
     
    9991010    psPlaneTransform *outToFPA;
    10001011    if (offset_x != 0. && offset_y != 0.) {
    1001         outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y);
    1002         psFree(chipToFPA);
     1012        outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y);
     1013        psFree(chipToFPA);
    10031014    } else {
    1004         outToFPA = chipToFPA;
     1015        outToFPA = chipToFPA;
    10051016    }
    10061017
    10071018    psPlaneTransform *outFromFPA = psPlaneTransformInvert(NULL, outToFPA, *outputBounds, 50);
    10081019    if (!outFromFPA) {
    1009         psFree(outToFPA);
    1010         psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
    1011         return false;
     1020        psFree(outToFPA);
     1021        psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
     1022        return false;
    10121023    }
    10131024
     
    10611072
    10621073    for (int j = 0; j < nSamples; j++) {
    1063         double y = bounds->y0 + (j * deltaY / nSamples);
    1064         for (int i =  0; i < nSamples; i++) {
    1065 
    1066             psSphere srcSky;
    1067             psPlane *srcChip = psPlaneAlloc();
    1068             psPlane *dstTP = psPlaneAlloc();
    1069 
    1070             srcChip->x = bounds->x0 + (i * deltaX / nSamples);
    1071             srcChip->y = y;
    1072 
    1073             psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip);
    1074             psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP);
    1075             psDeproject (&srcSky, &srcTP, inFPA->toSky);
    1076 
    1077             // fprintf (stderr, "%f %f | %f %f | %f %f | %f %f\n", srcChip->x, srcChip->y, srcFP.x, srcFP.y, srcTP.x, srcTP.y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD);
    1078 
    1079             psProject (dstTP, &srcSky, outFPA->toSky);
    1080 
    1081             srcChip->x -= bounds->x0;
    1082             srcChip->y -= bounds->y0;
    1083             psArrayAdd (src, 100, srcChip);
    1084             psArrayAdd (dst, 100, dstTP);
    1085 
    1086             psFree(srcChip);  // drop our refs to s and d
    1087             psFree(dstTP);
    1088         }
     1074        double y = bounds->y0 + (j * deltaY / nSamples);
     1075        for (int i =  0; i < nSamples; i++) {
     1076
     1077            psSphere srcSky;
     1078            psPlane *srcChip = psPlaneAlloc();
     1079            psPlane *dstTP = psPlaneAlloc();
     1080
     1081            srcChip->x = bounds->x0 + (i * deltaX / nSamples);
     1082            srcChip->y = y;
     1083
     1084            psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip);
     1085            psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP);
     1086            psDeproject (&srcSky, &srcTP, inFPA->toSky);
     1087
     1088            // fprintf (stderr, "%f %f | %f %f | %f %f | %f %f\n", srcChip->x, srcChip->y, srcFP.x, srcFP.y, srcTP.x, srcTP.y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD);
     1089
     1090            psProject (dstTP, &srcSky, outFPA->toSky);
     1091
     1092            srcChip->x -= bounds->x0;
     1093            srcChip->y -= bounds->y0;
     1094            psArrayAdd (src, 100, srcChip);
     1095            psArrayAdd (dst, 100, dstTP);
     1096
     1097            psFree(srcChip);  // drop our refs to s and d
     1098            psFree(dstTP);
     1099        }
    10891100    }
    10901101
     
    10941105
    10951106    if (!psPlaneTransformFit(newToFPA, src, dst, 0, 0)) {
    1096         psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
    1097         psFree(src);
    1098         psFree(dst);
    1099         return NULL;
     1107        psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
     1108        psFree(src);
     1109        psFree(dst);
     1110        return NULL;
    11001111    }
    11011112
     
    11031114    for (int i = 0; i < src->n; i++) {
    11041115
    1105         psSphere srcSky, dstSky;
    1106         psPlane *srcChip = src->data[i];
    1107         psPlane *dstTP   = dst->data[i];
    1108 
    1109         psPlaneTransformApply (&srcFP, newToFPA, srcChip);
    1110         psDeproject (&srcSky, &srcFP, outFPA->toSky);
    1111         psDeproject (&dstSky, dstTP, outFPA->toSky);
    1112 
    1113         double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0;
    1114         double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0;
    1115         fprintf (stderr, "%f %f | %f %f | %f %f | %f %f | %f %f | %f %f\n", dX, dY, srcChip->x, srcChip->y, srcFP.x, srcFP.y, dstTP->x, dstTP->y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD, dstSky.r*PS_DEG_RAD, dstSky.d*PS_DEG_RAD);
     1116        psSphere srcSky, dstSky;
     1117        psPlane *srcChip = src->data[i];
     1118        psPlane *dstTP   = dst->data[i];
     1119
     1120        psPlaneTransformApply (&srcFP, newToFPA, srcChip);
     1121        psDeproject (&srcSky, &srcFP, outFPA->toSky);
     1122        psDeproject (&dstSky, dstTP, outFPA->toSky);
     1123
     1124        double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0;
     1125        double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0;
     1126        fprintf (stderr, "%f %f | %f %f | %f %f | %f %f | %f %f | %f %f\n", dX, dY, srcChip->x, srcChip->y, srcFP.x, srcFP.y, dstTP->x, dstTP->y, srcSky.r*PS_DEG_RAD, srcSky.d*PS_DEG_RAD, dstSky.r*PS_DEG_RAD, dstSky.d*PS_DEG_RAD);
    11161127
    11171128    }
     
    11241135    psPlaneTransform *newFromFPA = psPlaneTransformInvert(NULL, newToFPA, *bounds, 1);
    11251136    if (!newFromFPA) {
    1126         psFree(newToFPA);
    1127         psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
    1128         return false;
     1137        psFree(newToFPA);
     1138        psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
     1139        return false;
    11291140    }
    11301141
     
    11491160
    11501161    if (!wcs)
    1151         return;
     1162        return;
    11521163    psFree (wcs->trans);
    11531164    psFree (wcs->toSky);
     
    11711182/*****
    11721183
    1173 For mosaic astrometry, we need to have a starting set of projection terms in which the
    1174 chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or
    1175 microns).  This set of projections, coupled with an identity toTPA (ie, no distortion) will
    1176 result in substantial errors between the observed and predicted star positions on the focal
    1177 plane: this is the measurement of the optical distortion in the camera.  At the same time,
    1178 we need to carry around the transformations which allow us to make an accurate calculation
    1179 of the position of the stars based on the input (per-chip) astrometry.  These
    1180 transformations will allow us to match the raw and ref stars robustly.  To convert the
    1181 per-chip astrometry (which may have been calculated with a different plate scale for each
    1182 chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust
    1183 the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for
    1184 each chip (eg, cdelt1).  Thus, we need to carry around both the
     1184      For mosaic astrometry, we need to have a starting set of projection terms in which the
     1185      chip-to-FPA terms result in a fixed physical unit on the focal plane (eg, pixels or
     1186      microns).  This set of projections, coupled with an identity toTPA (ie, no distortion) will
     1187      result in substantial errors between the observed and predicted star positions on the focal
     1188      plane: this is the measurement of the optical distortion in the camera.  At the same time,
     1189      we need to carry around the transformations which allow us to make an accurate calculation
     1190      of the position of the stars based on the input (per-chip) astrometry.  These
     1191      transformations will allow us to match the raw and ref stars robustly.  To convert the
     1192      per-chip astrometry (which may have been calculated with a different plate scale for each
     1193      chip) to a collection of astrometry terms for chips in a single mosaic, we need to adjust
     1194      the chip-to-FPA scaling (eg, pc11) to match the variations in the effective plate scale for
     1195      each chip (eg, cdelt1).  Thus, we need to carry around both the
    11851196
    11861197*****/
Note: See TracChangeset for help on using the changeset viewer.