IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 39979


Ignore:
Timestamp:
Feb 22, 2017, 11:17:26 AM (9 years ago)
Author:
eugene
Message:

if the input WCS does not have CRPIX1,2 as 0.0, 0.0, then we need to reset to 0,0 when converting to psTransformation objects

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/astrom/pmAstrometryWCS.c

    r39926 r39979  
    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
     
    522522
    523523    if (fpa->toSky == NULL) {
    524         psFree(fpa->toTPA);
    525         psFree(fpa->fromTPA);
    526         fpa->toTPA = psPlaneTransformIdentity (1);
    527         fpa->fromTPA = psPlaneTransformIdentity (1);
    528         fpa->toSky = toSky;
     524        psFree(fpa->toTPA);
     525        psFree(fpa->fromTPA);
     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;
     
    649649
    650650    psFree (chip->toFPA);
    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;
     651    if ((fabs(wcs->crpix1) > 0.01) || (fabs(wcs->crpix2) > 0.01)) {
     652      chip->toFPA = psPlaneTransformSetCenter (NULL, wcs->trans, -wcs->crpix1, -wcs->crpix2);
     653    } else {
     654      chip->toFPA = psPlaneTransformAlloc(wcs->trans->x->nX, wcs->trans->x->nY);
     655
     656      // copy the toFPA x,y, transformations to the wcs version
     657      chip->toFPA->x = psPolynomial2DCopy (chip->toFPA->x, wcs->trans->x);
     658      chip->toFPA->y = psPolynomial2DCopy (chip->toFPA->y, wcs->trans->y);
     659
     660      // these need to be set based on crval1,2
     661      chip->toFPA->x->coeff[0][0] = wcs->crval1;
     662      chip->toFPA->y->coeff[0][0] = wcs->crval2;
     663    }
    660664
    661665    // determine the inverse transformation: we need the chip pixels covered by this transform
     
    682686    // convert fpa->toTPA to units of unity (microns/micron)
    683687    for (int i = 0; i <= fpa->toTPA->x->nX; i++) {
    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         }
     688        for (int j = 0; j <= fpa->toTPA->x->nY; j++) {
     689            fpa->toTPA->x->coeff[i][j] /= wcs->cdelt1;
     690            fpa->toTPA->y->coeff[i][j] /= wcs->cdelt2;
     691        }
    688692    }
    689693
     
    729733
    730734    for (int i = 0; i <= toTPA->x->nX; i++) {
    731         for (int j = 0; j <= toTPA->x->nY; j++) {
    732             double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];
    733             double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];
    734             toTPA->x->coeff[i][j] = f1 + f2;
    735 
    736             double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];
    737             double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];
    738             toTPA->y->coeff[i][j] = g1 + g2;
    739         }
     735        for (int j = 0; j <= toTPA->x->nY; j++) {
     736            double f1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[1][0]*chip->toFPA->x->coeff[i][j];
     737            double f2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->x->coeff[0][1]*chip->toFPA->y->coeff[i][j];
     738            toTPA->x->coeff[i][j] = f1 + f2;
     739
     740            double g1 = chip->toFPA->x->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[1][0]*chip->toFPA->x->coeff[i][j];
     741            double g2 = chip->toFPA->y->coeffMask[i][j] ? 0.0 : fpa->toTPA->y->coeff[0][1]*chip->toFPA->y->coeff[i][j];
     742            toTPA->y->coeff[i][j] = g1 + g2;
     743        }
    740744    }
    741745    toTPA->x->coeff[0][0] += fpa->toTPA->x->coeff[0][0];
     
    761765    psPlane *center = psPlaneTransformGetCenter (tpa1, tol);
    762766    if (!center) {
    763         psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
    764         psFree (toTPA);
    765         psFree (tpa1);
    766         psFree (wcs);
    767         return NULL;
     767        psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
     768        psFree (toTPA);
     769        psFree (tpa1);
     770        psFree (wcs);
     771        return NULL;
    768772    }
    769773
     
    798802    // convert wcs->trans to a matrix with units of degrees/pixel
    799803    for (int i = 0; i <= wcs->trans->x->nX; i++) {
    800         for (int j = 0; j <= wcs->trans->x->nY; j++) {
    801             wcs->trans->x->coeff[i][j] *= pdelt1;
    802             wcs->trans->y->coeff[i][j] *= pdelt2;
    803         }
     804        for (int j = 0; j <= wcs->trans->x->nY; j++) {
     805            wcs->trans->x->coeff[i][j] *= pdelt1;
     806            wcs->trans->y->coeff[i][j] *= pdelt2;
     807        }
    804808    }
    805809
     
    885889    psPlane *center = psPlaneTransformGetCenter (fpa->toTPA, tol);
    886890    if (!center) {
    887         psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
    888         psFree (wcs);
    889         return NULL;
     891        psError(PS_ERR_UNKNOWN, false, "Unable to solve for TPA center.");
     892        psFree (wcs);
     893        return NULL;
    890894    }
    891895
     
    905909    // convert wcs->trans to units of degree/micron
    906910    for (int i = 0; i <= wcs->trans->x->nX; i++) {
    907         for (int j = 0; j <= wcs->trans->x->nY; j++) {
    908             wcs->trans->x->coeff[i][j] *= pdelt1;
    909             wcs->trans->y->coeff[i][j] *= pdelt2;
    910         }
     911        for (int j = 0; j <= wcs->trans->x->nY; j++) {
     912            wcs->trans->x->coeff[i][j] *= pdelt1;
     913            wcs->trans->y->coeff[i][j] *= pdelt2;
     914        }
    911915    }
    912916
     
    931935    int k=0;
    932936    for (int j=0; j<nSamples; j++) {
    933         double y = bounds->y0 + (j * deltaY / nSamples);
    934         for (int i=0; i<nSamples; i++) {
    935             psPlane *s = psPlaneAlloc();
    936             s->x = bounds->x0 + (i * deltaX / nSamples);
    937             s->y = y;
    938             psArraySet(src, k, s);
    939             psPlane *d = psPlaneTransformApply(NULL, trans, s);
    940             psArraySet(dst, k, d);
    941             psFree(s);  // drop our refs to s and d
    942             psFree(d);
    943             ++k;
    944         }
     937        double y = bounds->y0 + (j * deltaY / nSamples);
     938        for (int i=0; i<nSamples; i++) {
     939            psPlane *s = psPlaneAlloc();
     940            s->x = bounds->x0 + (i * deltaX / nSamples);
     941            s->y = y;
     942            psArraySet(src, k, s);
     943            psPlane *d = psPlaneTransformApply(NULL, trans, s);
     944            psArraySet(dst, k, d);
     945            psFree(s);  // drop our refs to s and d
     946            psFree(d);
     947            ++k;
     948        }
    945949    }
    946950
     
    948952
    949953    if (!psPlaneTransformFit(newTrans, src, dst, 0, 0)) {
    950         psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
    951         return NULL;
     954        psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
     955        return NULL;
    952956    }
    953957
     
    958962    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");
    959963    for (int i=0; i<psArrayLength(dst); i++) {
    960         psPlane *d = (psPlane *) psArrayGet(dst, i);
    961         psPlane *s = (psPlane *) psArrayGet(src, i);
    962 
    963         new = psPlaneTransformApply(new, newTrans, s);
    964 
    965         double xerr = new->x - d->x;
    966         double yerr = new->y - d->y;
    967         bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5);
    968         printf("%4d %9.2f %9.2f %9.2f %9.4f     %9.2f %9.2f %9.2f %9.4f   %s\n"
    969                , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : "");
     964        psPlane *d = (psPlane *) psArrayGet(dst, i);
     965        psPlane *s = (psPlane *) psArrayGet(src, i);
     966
     967        new = psPlaneTransformApply(new, newTrans, s);
     968
     969        double xerr = new->x - d->x;
     970        double yerr = new->y - d->y;
     971        bool bigerr = (fabs(xerr) > .5) || (fabs(yerr) > .5);
     972        printf("%4d %9.2f %9.2f %9.2f %9.4f     %9.2f %9.2f %9.2f %9.4f   %s\n"
     973               , i, s->x, new->x, d->x, xerr, s->y, new->y, d->y, yerr, bigerr ? "BIGERR" : "");
    970974    }
    971975    psFree(new);
     
    985989
    986990    if (outFPA == NULL) {
    987         outFPA = inFPA;
     991        outFPA = inFPA;
    988992    }
    989993    if (outChip == NULL) {
    990         outChip = inChip;
     994        outChip = inChip;
    991995    }
    992996    if (outputBounds == NULL) {
    993         outputBounds = pmChipPixels(outChip);
     997        outputBounds = pmChipPixels(outChip);
    994998    }
    995999
     
    9971001    psPlaneTransform *chipToTPA = psPlaneTransformCombine(NULL, inChip->toFPA, inFPA->toTPA, *outputBounds, 50);
    9981002    if (!chipToTPA) {
    999         psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA");
    1000         return false;
     1003        psError(PS_ERR_UNKNOWN, false, "failed to create chipToTPA");
     1004        return false;
    10011005    }
    10021006
     
    10051009    psFree(chipToTPA);
    10061010    if (!chipToFPA) {
    1007         psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed");
    1008         return false;
     1011        psError(PS_ERR_UNKNOWN, false, "linear fit of chip to TPA transform failed");
     1012        return false;
    10091013    }
    10101014
     
    10121016    psPlaneTransform *outToFPA;
    10131017    if (offset_x != 0. && offset_y != 0.) {
    1014         outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y);
    1015         psFree(chipToFPA);
     1018        outToFPA = psPlaneTransformSetCenter(NULL, chipToFPA, offset_x, offset_y);
     1019        psFree(chipToFPA);
    10161020    } else {
    1017         outToFPA = chipToFPA;
     1021        outToFPA = chipToFPA;
    10181022    }
    10191023
    10201024    psPlaneTransform *outFromFPA = psPlaneTransformInvert(NULL, outToFPA, *outputBounds, 50);
    10211025    if (!outFromFPA) {
    1022         psFree(outToFPA);
    1023         psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
    1024         return false;
     1026        psFree(outToFPA);
     1027        psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
     1028        return false;
    10251029    }
    10261030
     
    10741078
    10751079    for (int j = 0; j < nSamples; j++) {
    1076         double y = bounds->y0 + (j * deltaY / nSamples);
    1077         for (int i =  0; i < nSamples; i++) {
    1078 
    1079             psSphere srcSky;
    1080             psPlane *srcChip = psPlaneAlloc();
    1081             psPlane *dstTP = psPlaneAlloc();
    1082 
    1083             srcChip->x = bounds->x0 + (i * deltaX / nSamples);
    1084             srcChip->y = y;
    1085 
    1086             psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip);
    1087             psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP);
    1088             psDeproject (&srcSky, &srcTP, inFPA->toSky);
    1089 
    1090             // 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);
    1091 
    1092             psProject (dstTP, &srcSky, outFPA->toSky);
    1093 
    1094             srcChip->x -= bounds->x0;
    1095             srcChip->y -= bounds->y0;
    1096             psArrayAdd (src, 100, srcChip);
    1097             psArrayAdd (dst, 100, dstTP);
    1098 
    1099             psFree(srcChip);  // drop our refs to s and d
    1100             psFree(dstTP);
    1101         }
     1080        double y = bounds->y0 + (j * deltaY / nSamples);
     1081        for (int i =  0; i < nSamples; i++) {
     1082
     1083            psSphere srcSky;
     1084            psPlane *srcChip = psPlaneAlloc();
     1085            psPlane *dstTP = psPlaneAlloc();
     1086
     1087            srcChip->x = bounds->x0 + (i * deltaX / nSamples);
     1088            srcChip->y = y;
     1089
     1090            psPlaneTransformApply (&srcFP, inChip->toFPA, srcChip);
     1091            psPlaneTransformApply (&srcTP, inFPA->toTPA, &srcFP);
     1092            psDeproject (&srcSky, &srcTP, inFPA->toSky);
     1093
     1094            // 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);
     1095
     1096            psProject (dstTP, &srcSky, outFPA->toSky);
     1097
     1098            srcChip->x -= bounds->x0;
     1099            srcChip->y -= bounds->y0;
     1100            psArrayAdd (src, 100, srcChip);
     1101            psArrayAdd (dst, 100, dstTP);
     1102
     1103            psFree(srcChip);  // drop our refs to s and d
     1104            psFree(dstTP);
     1105        }
    11021106    }
    11031107
     
    11071111
    11081112    if (!psPlaneTransformFit(newToFPA, src, dst, 0, 0)) {
    1109         psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
    1110         psFree(src);
    1111         psFree(dst);
    1112         return NULL;
     1113        psError(PS_ERR_UNKNOWN, false, "linear fit to transform failed");
     1114        psFree(src);
     1115        psFree(dst);
     1116        return NULL;
    11131117    }
    11141118
     
    11161120    for (int i = 0; i < src->n; i++) {
    11171121
    1118         psSphere srcSky, dstSky;
    1119         psPlane *srcChip = src->data[i];
    1120         psPlane *dstTP   = dst->data[i];
    1121 
    1122         psPlaneTransformApply (&srcFP, newToFPA, srcChip);
    1123         psDeproject (&srcSky, &srcFP, outFPA->toSky);
    1124         psDeproject (&dstSky, dstTP, outFPA->toSky);
    1125 
    1126         double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0;
    1127         double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0;
    1128         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);
     1122        psSphere srcSky, dstSky;
     1123        psPlane *srcChip = src->data[i];
     1124        psPlane *dstTP   = dst->data[i];
     1125
     1126        psPlaneTransformApply (&srcFP, newToFPA, srcChip);
     1127        psDeproject (&srcSky, &srcFP, outFPA->toSky);
     1128        psDeproject (&dstSky, dstTP, outFPA->toSky);
     1129
     1130        double dX = (srcSky.r*PS_DEG_RAD - dstSky.r*PS_DEG_RAD)*3600.0;
     1131        double dY = (srcSky.d*PS_DEG_RAD - dstSky.d*PS_DEG_RAD)*3600.0;
     1132        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);
    11291133
    11301134    }
     
    11371141    psPlaneTransform *newFromFPA = psPlaneTransformInvert(NULL, newToFPA, *bounds, 1);
    11381142    if (!newFromFPA) {
    1139         psFree(newToFPA);
    1140         psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
    1141         return false;
     1143        psFree(newToFPA);
     1144        psError(PS_ERR_UNKNOWN, false, "inversion of fit of output chip toFPA failed");
     1145        return false;
    11421146    }
    11431147
     
    11621166
    11631167    if (!wcs)
    1164         return;
     1168        return;
    11651169    psFree (wcs->trans);
    11661170    psFree (wcs->toSky);
Note: See TracChangeset for help on using the changeset viewer.