예제 #1
0
void fts2_getmirrorpositions(smfData* data, double* positions, int* size, int* status)
{
  if(*status != SAI__OK) { return; }

  char ftsMode[SZFITSTR];
  size_t count      = 0;    /* Size */
  HDSLoc* hdsLoc    = NULL; /* Pointer to HDS location */
  HDSLoc* hdsLocPos = NULL; /* Pointer to mirror positions */

  smf_fits_getS(data->hdr, "FTS_MODE", ftsMode, sizeof(ftsMode), status);
  if(strncmp(ftsMode, "FSCAN", 5) == 0 ) {
    hdsLoc = smf_get_xloc(data, "JCMTSTATE", "EXT", "READ", 0, 0, status);
    datFind(hdsLoc, "FTS_POS", &hdsLocPos, status);
    datSize(hdsLocPos, &count, status);
    datGetVD(hdsLocPos, count, positions, &count, status);
    *size = (int) count;
  } else if(strncmp(ftsMode, "STEPINT", 7) == 0 ) {
    *status = SAI__ERROR;
    errRep(FUNC_NAME, "STEPINT mode is NOT supported!", status);
  } else {
    *status = SAI__ERROR;
    errRep(FUNC_NAME, "Unknown Scan Mode is found!", status);
  }

  if(hdsLoc) { datAnnul(&hdsLoc, status); }
  if(hdsLocPos) { datAnnul(&hdsLocPos, status); }
}
예제 #2
0
파일: datCcopy.c 프로젝트: Starlink/hds-v5
int
datCcopy(const HDSLoc *locator1, const HDSLoc *locator2, const char *name,
         HDSLoc **locator3, int *status ) {
  char type_str[DAT__SZTYP+1];
  hdsdim hdims[DAT__MXDIM];
  int ndims;

  if (*status != SAI__OK) return *status;

  /* Validate input locators. */
  dat1ValidateLocator( "datCcopy", 1, locator1, 1, status );
  dat1ValidateLocator( "datCcopy", 1, locator2, 0, status );

  if (dat1IsStructure(locator1, status)) {

    /* need the type and dimensionality of the structure to create
       in new location */
    datType( locator1, type_str, status );
    datShape( locator1, DAT__MXDIM, hdims, &ndims, status );

    *locator3 = dat1New( locator2, 0, name, type_str, ndims, hdims, status );

  } else {
    hdsbool_t state = 0;
    /* We only copy if the primitive object is defined */
    datState( locator1, &state, status );
    if ( state ) {
      datCopy( locator1, locator2, name, status );
    } else {
      /* Undefined so just make something of the right shape and type */
      datType( locator1, type_str, status );
      datShape( locator1, DAT__MXDIM, hdims, &ndims, status );
      datNew( locator2, name, type_str, ndims, hdims, status );
    }

    /* and get a locator to the copied entity */
    datFind( locator2, name, locator3, status );

  }

  return *status;
}
예제 #3
0
파일: hds.c 프로젝트: trmrsh/starlink-pyndf
static PyObject*
pydat_find(HDSObject *self, PyObject *args)
{
    PyObject* pobj1;
    const char* name;
    if(!PyArg_ParseTuple(args, "s:pydat_find", &name))
        return NULL;

    // Recover C-pointer passed via Python
    HDSLoc* loc1 = HDS_retrieve_locator( self );
    HDSLoc* loc2 = NULL;

    int status = SAI__OK;
    errBegin(&status);
    datFind(loc1, name, &loc2, &status);
    if (raiseHDSException(&status)) return NULL;

    // PyCObject to pass pointer along to other wrappers
    return HDS_create_object(loc2);
};
예제 #4
0
void atlKy2hd( AstKeyMap *keymap, HDSLoc *loc, int *status ) {
    /*
    *  Name:
    *     atlKy2hd

    *  Purpose:
    *     Copies values from an AST KeyMap to a primitive HDS object.

    *  Language:
    *     C.

    *  Invocation:
    *     void atlKy2hd( AstKeyMap *keymap, HDSLoc *loc, int *status )

    *  Description:
    *     This routine copies the contents of an AST KeyMap into a supplied
    *     HDS structure.

    *  Arguments:
    *     keymap
    *        An AST pointer to the KeyMap.
    *     loc
    *        A locator for the HDS object into which the KeyMap contents
    *        are to be copied. A new component is added to the HDS object for
    *        each entry in the KeyMap.
    *     status
    *        The inherited status.

    *  Copyright:
    *     Copyright (C) 2008, 2010, 2012 Science & Technology Facilities Council.
    *     All Rights Reserved.

    *  Licence:
    *     This program is free software; you can redistribute it and/or
    *     modify it under the terms of the GNU General Public License as
    *     published by the Free Software Foundation; either version 2 of
    *     the License, or (at your option) any later version.
    *
    *     This program is distributed in the hope that it will be
    *     useful,but WITHOUT ANY WARRANTY; without even the implied
    *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    *     PURPOSE. See the GNU General Public License for more details.
    *
    *     You should have received a copy of the GNU General Public License
    *     along with this program; if not, write to the Free Software
    *     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
    *     02110-1301, USA

    *  Authors:
    *     DSB: David S. Berry
    *     TIMJ: Tim Jenness (JAC, Hawaii)
    *     {enter_new_authors_here}

    *  History:
    *     29-APR-2008 (DSB):
    *        Original version.
    *     2010-09-23 (TIMJ):
    *        Fix arrays of strings.
    *     2010-09-30 (TIMJ):
    *        Make sure that we are using the correct status pointer in AST.
    *     2010-10-01 (TIMJ):
    *        Sort the keys when writing to HDS structured.
    *     2010-10-04 (TIMJ):
    *        Support Short ints in keymap
    *     14-SEP-2012 (DSB):
    *        Moved from kaplibs to atl.
    *     17-SEP-2012 (DSB):
    *        Add support for undefined values.
    *     {enter_further_changes_here}

    *  Bugs:
    *     {note_any_bugs_here}
    */

    /* Local Varianles: */
    AstObject **objArray = NULL;
    AstObject *obj = NULL;
    HDSLoc *cloc = NULL;
    HDSLoc *dloc = NULL;
    const char *cval = NULL;
    const char *key;
    double dval;
    float fval;
    int i;
    int ival;
    int j;
    int lenc;
    int nval;
    char *oldsortby;
    int *oldstat = NULL;
    int size;
    int type;
    int veclen;
    size_t el;
    void *pntr = NULL;

    /* Check inherited status */
    if( *status != SAI__OK ) return;

    /* Make sure that we are checking AST status */
    oldstat = astWatch( status );

    /* If set, save the old SortBy value and then ensure alphabetical sorting.
       We need to take a copy of the original string since the buffer in which
       the string is stored may be re-used by subsequent incocations of astGetC.  */
    if( astTest( keymap, "SortBy" ) ) {
        int nc = 0;
        oldsortby = astAppendString( NULL, &nc, astGetC( keymap, "SortBy" ) );
    } else {
        oldsortby = NULL;
    }
    astSet( keymap, "SortBy=KeyUp" );

    /* Loop round each entry in the KeyMap. */
    size = astMapSize( keymap );
    for( i = 0; i < size; i++ ) {

        if (*status != SAI__OK) break;

        /* Get the key. the data type and the vector length for the current
           KeyMap entry. */
        key = astMapKey( keymap, i );
        type = astMapType( keymap, key );
        veclen = astMapLength( keymap, key );

        /* If the current entry holds one or more nested KeyMaps, then we call
           this function recursively to add them into a new HDS component. */
        if( type == AST__OBJECTTYPE ) {

            /* First deal with scalar entries holding a single KeyMap. */
            if( veclen == 1 ) {
                datNew( loc, key, "KEYMAP_ENTRY", 0, NULL, status );
                datFind( loc, key, &cloc, status );

                (void) astMapGet0A( keymap, key, &obj );

                if( astIsAKeyMap( obj ) ) {
                    atlKy2hd( (AstKeyMap *) obj, cloc, status );

                } else if( *status == SAI__OK ) {
                    *status = SAI__ERROR;
                    errRep( "", "atlKy2hd: Supplied KeyMap contains unusable AST "
                            "objects (programming error).", status );
                }

                datAnnul( &cloc, status );

                /* Now deal with vector entries holding multiple KeyMaps. */
            } else {
                datNew( loc, key, "KEYMAP_ENTRY", 1, &veclen, status );
                datFind( loc, key, &cloc, status );

                objArray = astMalloc( sizeof( AstObject *) * (size_t)veclen );
                if( objArray ) {
                    (void) astMapGet1A( keymap, key, veclen, &nval, objArray );

                    for( j = 1; j <= veclen; j++ ) {
                        datCell( cloc, 1, &j, &dloc, status );

                        if( astIsAKeyMap( objArray[ j - 1 ] ) ) {
                            atlKy2hd( (AstKeyMap *) objArray[ j - 1 ], dloc, status );

                        } else if( *status == SAI__OK ) {
                            *status = SAI__ERROR;
                            errRep( "", "atlKy2hd: Supplied KeyMap contains unusable AST "
                                    "objects (programming error).", status );
                        }

                        datAnnul( &dloc, status );
                    }

                    objArray = astFree( objArray );
                }

                datAnnul( &cloc, status );
            }

            /* For primitive types... */
        } else if( type == AST__INTTYPE ) {
            if( veclen == 1 ) {
                datNew0I( loc, key, status );
                datFind( loc, key, &cloc, status );
                (void) astMapGet0I( keymap, key, &ival );
                datPut0I( cloc, ival, status );
                datAnnul( &cloc, status );

            } else {
                datNew1I( loc, key, veclen, status );
                datFind( loc, key, &cloc, status );
                datMapV( cloc, "_INTEGER", "WRITE", &pntr, &el, status );
                (void) astMapGet1I( keymap, key, veclen, &nval, (int *) pntr );
                datUnmap( cloc, status );
                datAnnul( &cloc, status );
            }

        } else if( type == AST__SINTTYPE ) {
            short sval = 0;
            if( veclen == 1 ) {
                datNew0W( loc, key, status );
                datFind( loc, key, &cloc, status );
                (void) astMapGet0S( keymap, key, &sval );
                datPut0W( cloc, sval, status );
                datAnnul( &cloc, status );

            } else {
                datNew1W( loc, key, veclen, status );
                datFind( loc, key, &cloc, status );
                datMapV( cloc, "_WORD", "WRITE", &pntr, &el, status );
                (void) astMapGet1S( keymap, key, veclen, &nval, (short *) pntr );
                datUnmap( cloc, status );
                datAnnul( &cloc, status );
            }

        } else if( type == AST__DOUBLETYPE ) {
            if( veclen == 1 ) {
                datNew0D( loc, key, status );
                datFind( loc, key, &cloc, status );
                (void) astMapGet0D( keymap, key, &dval );
                datPut0D( cloc, dval, status );
                datAnnul( &cloc, status );

            } else {
                datNew1D( loc, key, veclen, status );
                datFind( loc, key, &cloc, status );
                datMapV( cloc, "_DOUBLE", "WRITE", &pntr, &el, status );
                (void) astMapGet1D( keymap, key, veclen, &nval, (double *) pntr );
                datUnmap( cloc, status );
                datAnnul( &cloc, status );
            }

        } else if( type == AST__FLOATTYPE ) {
            if( veclen == 1 ) {
                datNew0R( loc, key, status );
                datFind( loc, key, &cloc, status );
                (void) astMapGet0F( keymap, key, &fval );
                datPut0R( cloc, fval, status );
                datAnnul( &cloc, status );

            } else {
                datNew1R( loc, key, veclen, status );
                datFind( loc, key, &cloc, status );
                datMapV( cloc, "_REAL", "WRITE", &pntr, &el, status );
                (void) astMapGet1F( keymap, key, veclen, &nval, (float *) pntr );
                datUnmap( cloc, status );
                datAnnul( &cloc, status );
            }

        } else if( type == AST__STRINGTYPE ) {
            lenc = astMapLenC( keymap, key );

            if( veclen == 1 ) {
                datNew0C( loc, key, lenc, status );
                datFind( loc, key, &cloc, status );
                (void) astMapGet0C( keymap, key, &cval );
                datPut0C( cloc, cval, status );
                datAnnul( &cloc, status );

            } else {
                datNew1C( loc, key, lenc, veclen, status );
                datFind( loc, key, &cloc, status );
                datMapV( cloc, "_CHAR", "WRITE", &pntr, &el, status );
                (void) atlMapGet1C( keymap, key, veclen*lenc, lenc, &nval,
                                    (char *) pntr, status );
                datUnmap( cloc, status );
                datAnnul( &cloc, status );
            }

            /* KeyMap "UNDEF" values are always scalar and have no corresponding HDS
               data type. So arbitrarily use an "_INTEGER" primitive with no defined
               value to represent a KeyMap UNDEF value. */
        } else if( type == AST__UNDEFTYPE ) {
            datNew0L( loc, key, status );

            /* Unknown or unsupported data types. */
        } else if( *status == SAI__OK ) {
            *status = SAI__ERROR;
            msgSeti( "T", type );
            errRep( "", "atlKy2hd: Supplied KeyMap contains entries with "
                    "unusable data type (^T) (programming error).", status );
        }
    }

    /* If it was originally set, re-instate the old SortBy value in the KeyMap,
       then free the memory. Otherwise, clear the SortBy attribute. */
    if( oldsortby ) {
        astSetC( keymap, "SortBy", oldsortby );
        oldsortby = astFree( oldsortby );
    } else {
        astClear( keymap, "SortBy" );
    }

    /* Reset AST status */
    astWatch( oldstat );

}
예제 #5
0
void smf_ext2km( int indf, const char *xname, AstKeyMap *keymap,
                 int mode, int *status ){

/* Local Variables */
   HDSLoc *cloc = NULL;
   HDSLoc *sloc = NULL;
   HDSLoc *xloc = NULL;
   const char *key = NULL;
   hdsdim diml[NDF__MXDIM];
   hdsdim dimu[NDF__MXDIM];
   int dim[ NDF__MXDIM ];
   int i;
   int idim;
   int lbnd[ NDF__MXDIM ];
   int ncomp;
   int ndim;
   int nentry;
   int ntime = 0;
   int prim;
   int there;
   int ubnd[ NDF__MXDIM ];

/* Check the inherited status */
   if( *status != SAI__OK ) return;

/* Get the shape of the NDF. */
   ndfBound( indf, 3, lbnd, ubnd, &ndim, status );

/* Get a locator to the named extension. */
   ndfXloc( indf, xname, "READ", &xloc, status );

/* Select the name of the prototype component that determines the length
   of the arrays to be copied. */
   if( !strcmp( xname, "JCMTSTATE" ) ) {
      key = "RTS_NUM";
   } else if( !strcmp( xname, "ACSIS" ) ) {
      key = "TSYS";
   } else {
      cloc = NULL;
      msgSetc( "X", xname );
      errRep( "", "smf_ext2km: Unknown extension specified - '^X'. "
              "Must be 'JCMTSTATE' or 'ACSIS'.", status );
   }

/* Check the prorotype component is present in the extension. Report an
   error if not. */
   datThere( xloc, key, &there, status );
   if( !there && *status == SAI__OK ) {
      msgSetc( "C", key );
      msgSetc( "X", xname );
      errRep( "", "smf_ext2km: Component '^C' not found in extension "
              "^X", status );

/* If it is present, get the length of its last pixel axis. This is the
   length of the arrays to be copied. */
   } else {
      datFind( xloc, key, &cloc, status );
      datShape( cloc, NDF__MXDIM, dim, &ndim, status );
      ntime = dim[ ndim - 1 ];
      datAnnul( &cloc, status );
   }

/* First deal with mode 1... */
/* ========================= */
   if( mode == 1 ) {

/* Loop round every component in the extension. */
      datNcomp( xloc, &ncomp, status );
      for( i = 1; i <= ncomp; i++ ) {
         datIndex( xloc, i, &cloc, status );

/* Check the component has primitive values. */
         datPrim( cloc, &prim, status );
         if( prim ) {

/* Get the shape of the component. */
            datShape( cloc, NDF__MXDIM, dim, &ndim, status );

/* Skip over this component if the length of its final axis is not equal
   to the expected number of time slices. */
            if( ndim > 0 && dim[ ndim - 1 ] == ntime ) {

/* Also skip if we are dealing with the ACSIS extension and the array has
   only 1 (or zero) axes. */
               if( ndim > 1 || strcmp( xname, "ACSIS" ) ) {

/* Cut a section from the HDS array so that it matches the pixel bounds of
   the NDF . */
                  for( idim = 0; idim < ndim - 1; idim++ ) {
                     diml[ idim ] = 1;
                     dimu[ idim ] = dim[ idim ];
                  }
                  diml[ idim ] = lbnd[ 2 ];
                  dimu[ idim ] = ubnd[ 2 ];
                  datSlice( cloc, ndim, diml, dimu, &sloc, status );

/* Store the values as a new entry in "keymap". */
                  kpg1Hdsky( sloc, keymap, 2, 1, status );

/* Annul the locator for the slice. */
                  datAnnul( &sloc, status );
               }
            }
         }
         datAnnul( &cloc, status );
      }

/* Now deal with mode 2... */
/* ========================= */
   } else if( mode == 2 ) {

/* Loop round every entry in the KeyMap. */
      nentry = astMapSize( keymap );
      for( i = 0; i < nentry; i++ ) {
         key = astMapKey( keymap, i );

/* See if the supplied extension has a component with the same name. */
         datThere( xloc, key, &there, status );

/* If it did, check the component is primitive. */
         if( there && *status == SAI__OK ) {
            datFind( xloc, key, &cloc, status );
            datPrim( cloc, &prim, status );
            if( prim ) {

/* Check the final axis of the primitive array has a length equal to the
   expected number of time slices. */
               datShape( cloc, NDF__MXDIM, dim, &ndim, status );
               if( ndim > 0 && dim[ ndim - 1 ] == ntime ) {

/* Also skip if we are dealing with the ACSIS extension and the array has
   only 1 (or zero) axes. */
                  if( ndim > 1 || strcmp( xname, "ACSIS" ) ) {

/* Cut a section from the HDS array so that it matches the pixel bounds of
   the NDF . */
                     for( idim = 0; idim < ndim - 1; idim++ ) {
                        diml[ idim ] = 1;
                        dimu[ idim ] = dim[ idim ];
                     }
                     diml[ idim ] = lbnd[ 2 ];
                     dimu[ idim ] = ubnd[ 2 ];
                     datSlice( cloc, ndim, diml, dimu, &sloc, status );

/* Append the values to the end of the existing KeyMap entry. */
                     kpg1Hdsky( sloc, keymap, 1, 3, status );

/* Annul the locator for the slice. */
                     datAnnul( &sloc, status );

                  }

               } else if( *status == SAI__OK ) {
                  *status = SAI__ERROR;
                  msgSetc( "X", xname );
                  msgSetc( "K", key );
                  ndfMsg( "F", indf );
                  errRep( "", "The ^X.^K array has an unexpected shape in "
                          "\"^F\".", status );
               }

            } else if( *status == SAI__OK ) {
               *status = SAI__ERROR;
               msgSetc( "X", xname );
               msgSetc( "K", key );
               ndfMsg( "F", indf );
               errRep( "", "The ^X.^K array has an unexpected data type in "
                       "\"^F\".", status );
            }

            datAnnul( &cloc, status );

         } else if( *status == SAI__OK ) {
            *status = SAI__ERROR;
            msgSetc( "X", xname );
            msgSetc( "K", key );
            ndfMsg( "F", indf );
            errRep( "", "The ^X.^K array is missing in \"^F\".", status );
         }

      }

/* Now tidy up. */
/* ============ */

/* Report an error if the "mode" value was illegal. */
   } else if( *status == SAI__OK ) {
      *status = SAI__ERROR;
      msgSeti( "MODE", mode );
      errRep( "", "smf_ext2km: Illegal value (^MODE) supplied for "
              "argument MODE (programming error).", status );
   }

/* Free resources. */
   datAnnul( &xloc, status );
}
예제 #6
0
void smf_subip(  ThrWorkForce *wf, smfArray *res, smfArray *lut, int *lbnd_out,
                 int *ubnd_out, AstKeyMap *keymap, AstFrameSet *outfs, int *status ) {

/* Local Variables: */
   HDSLoc *loc = NULL;
   HDSLoc *sloc = NULL;
   SmfSubIPData *job_data = NULL;
   SmfSubIPData *pdata;
   char ipref[200];
   char subname[10];
   const char *ipdata;
   const char *qu;
   dim_t bolostep;
   dim_t nbolo;
   dim_t ntslice;
   double *angcdata;
   double *c0data;
   double *imapdata;
   double *ipang;
   double *p0data;
   double *p1data;
   int angcndf;
   int c0ndf;
   int imapndf;
   int iw;
   int nmap;
   int nw;
   int p0ndf;
   int p1ndf;
   size_t bstride;
   size_t idx;
   size_t tstride;
   smfData *data;
   smf_qual_t *qua_data;

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* Check if we have pol2 data, and see if it is Q or U. */
   qu = NULL;
   for( idx = 0; idx < res->ndat; idx++ ) {
      data = res->sdata[idx];

      if( !strcmp( data->hdr->dlabel, "Q" ) ){
         if( !qu ) {
            qu = "Q";
         } else if( strcmp( qu, "Q" ) ) {
            *status = SAI__ERROR;
            break;
         }

      } else if( !strcmp( data->hdr->dlabel, "U" ) ) {
         if( !qu ) {
            qu = "U";
         } else if( strcmp( qu, "U" ) ) {
            *status = SAI__ERROR;
            break;
         }

      } else if( qu ) {
         *status = SAI__ERROR;
         qu = NULL;
         break;
      }
   }

/* Report an error if there is a mix of pol2 and non-pol2, or a mix of Q
   and U. */
   if( *status != SAI__OK ) {
      if( qu ) {
         errRep( "", "smf_subip: Input data contains mix of Q and U "
                 "data", status );
      } else {
         errRep( "", "smf_subip: Input data contains mix of POL2 and "
                 "non-POL2 data", status );
      }

/* If we have pol2 data, get the path to the total intensity image that
   is to be used to define the level of IP correction required. If no
   value is supplied, annul the error and set "qu" NULL to indicate we should
   leave immediately. */
   } else if( qu && *status == SAI__OK ) {
      parGet0c( "IPREF", ipref, sizeof(ipref), status );
      if( *status == PAR__NULL ) {
         errAnnul( status );
         qu = NULL;
      }
   }

/* If we are applying IP correction... */
   if( qu && *status == SAI__OK ) {
      msgOutf( "", "smf_subip: applying instrumental polarisation %s "
               "correction based on total intensity map `%s'", status,
               qu, ipref );

/* Get an identifier for the IPREF NDF. */
      ndfFind( NULL, ipref, &imapndf, status );

/* Resample the NDFs data values onto the output map grid. */
      imapdata = smf_alignndf( imapndf, outfs, lbnd_out, ubnd_out,
                               status );

/* Annul the NDF identifier. */
      ndfAnnul( &imapndf, status );

/* Create structures used to pass information to the worker threads. */
      nw = wf ? wf->nworker : 1;
      job_data = astMalloc( nw*sizeof( *job_data ) );

/* Get the path to the container file holding the IP model parameters. */
      ipdata = "$STARLINK_DIR/share/smurf/ipdata.sdf";
      astMapGet0C( keymap, "IPDATA", &ipdata );

/* Open the container file. */
      hdsOpen( ipdata, "READ", &loc, status );

/* Do the IP correction for each subarray (s8a, s8b, etc) in turn. */
      for( idx = 0; idx < res->ndat && *status == SAI__OK; idx++ ) {
         data = res->sdata[idx];

/* Get an array holding the angle (rad.s) from north to focal plane Y,
   measured positive in the sense of rotation from focal plane Y to focal
   plane X, for every bolometer sample in the smfData. The values are bolo
   ordered so that "bstride" is 1 and "tstsride" is nbolo. */
         ipang = smf1_calcang( data, status );

/* Get the number of bolometers and time slices for the current subarray,
   together with the strides between adjacent bolometers and adjacent
   time slices. */
         smf_get_dims( data,  NULL, NULL, &nbolo, &ntslice, NULL, &bstride,
                       &tstride, status );

/* Get a locator for the structure holding the IP parameters for the
   current subarray */
         smf_find_subarray( data->hdr, subname, sizeof( subname ), NULL,
                            status );
         datFind( loc, subname, &sloc, status );

/* Begin an NDF context. */
         ndfBegin();

/* Get identifiers for the NDFs holding the individual parameters. Each
   NDF holds a parameter value for each bolometer. */
         ndfFind( sloc, "P0", &p0ndf, status );
         ndfFind( sloc, "P1", &p1ndf, status );
         ndfFind( sloc, "C0", &c0ndf, status );
         ndfFind( sloc, "ANGC", &angcndf, status );

/* Map them. Check each one has the expected number of elements. */
         ndfMap( p0ndf, "DATA", "_DOUBLE", "READ", (void **) &p0data,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", p0ndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

         ndfMap( p1ndf, "DATA", "_DOUBLE", "READ", (void **) &p1data,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", p1ndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

         ndfMap( c0ndf, "DATA", "_DOUBLE", "READ", (void **) &c0data,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", c0ndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

         ndfMap( angcndf, "DATA", "_DOUBLE", "READ", (void **) &angcdata,
                 &nmap, status );
         if( nmap != (int) nbolo && *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "N", angcndf );
            errRep( "", "smf_subip: Bad dimensions for ^N - should be 32x40.", status );
         }

/* Get a pointer to the quality array for the residuals. */
         qua_data = smf_select_qualpntr( data, NULL, status );

/* See how many bolometers to process in each thread. */
         bolostep = nbolo/nw;
         if( bolostep == 0 ) bolostep = 1;

/* Create jobs to apply the IP correction to a range of bolometers. */
         for( iw = 0; iw < nw; iw++ ) {
            pdata = job_data + iw;

/* Set the range of bolometers (b1 to b2) to be processed by the current
   job. */
            pdata->b1 = iw*bolostep;
            if( iw < nw - 1 ) {
               pdata->b2 = pdata->b1 + bolostep - 1;
            } else {
               pdata->b2 = nbolo - 1 ;
            }

/* Store the other info needed by the worker thread. */
            pdata->ntslice = ntslice;
            pdata->nbolo = nbolo;
            pdata->res_data = res->sdata[idx]->pntr[0];
            pdata->lut_data = lut->sdata[idx]->pntr[0];
            pdata->qua_data = qua_data;
            pdata->ipang = ipang;
            pdata->bstride = bstride;
            pdata->tstride = tstride;
            pdata->imapdata = imapdata;
            pdata->qu = qu;
            pdata->p0data = p0data;
            pdata->p1data = p1data;
            pdata->c0data = c0data;
            pdata->angcdata = angcdata;
            pdata->allstate = data->hdr->allState;

/* Submit the job for execution by the next available thread. */
            thrAddJob( wf, 0, pdata, smf1_subip, 0, NULL, status );
         }

/* Wait for all jobs to complete. */
         thrWait( wf, status );

/* End the NDF context, thus unmapping and freeing all NDF identifiers
   created since the context was started. */
         ndfEnd( status );

/* Free locator for subarray IP parameters. */
         datAnnul( &sloc, status );
         ipang = astFree( ipang );
      }

/* Free resources. */
      datAnnul( &loc, status );
      imapdata = astFree( imapdata );
      job_data = astFree( job_data );
   }
}
void cupidStoreConfig( HDSLoc *loc, AstKeyMap *config, int *status ){
/*
*+
*  Name:
*     cupidStoreConfig

*  Purpose:
*     Store the configuraton used by CLUMPS in the given CUPID extension.

*  Language:
*     Starlink C

*  Synopsis:
*     void cupidStoreConfig( HDSLoc *loc, AstKeyMap *config, int *status )

*  Description:
*     This function extracts each keyword/value pair from the given
*     configuration keymap, and stores them in the CUPID extension.

*  Parameters:
*     loc
*        HDS locator for the CUPID extension.
*     config
*        An AST KeyMap holding the configuration parameters.
*     status
*        Pointer to the inherited status value.

*  Copyright:
*     Copyright (C) 2005 Particle Physics & Astronomy Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David S. Berry
*     TIMJ: Tim Jenness (JAC, Hawaii)
*     {enter_new_authors_here}

*  History:
*     9-NOV-2005 (DSB):
*        Original version.
*     15-JUL-2008 (TIMJ):
*        Tweak to GRP C API.
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local Variables: */

   Grp *grp;             /* Pointer to group */
   HDSLoc *aloc;         /* HDS locator for entire CONFIG array */
   HDSLoc *cloc;         /* HDS locator for single cell of ONFIG array */
   char name[ GRP__SZNAM + 1 ];/* Value extracted from GRP group */
   char *pname;          /* Pointer to pass to grpGet */
   int el;               /* Index of element to store */
   int i;                /* Index of next entry in group */
   int n;                /* Number of entries in group */
   int nc;               /* Number of characters in group entry */
   int ncmax;            /* Max number of characters in any group entry */
   int subs[ 1 ];        /* Array containing required cell index */
   int there;                   /* Does component exist?*/

/* Abort if an error has already occurred. */
   if( *status != SAI__OK ) return;

/* Initialise all HDS locator pointers to NULL since HDS now objects if it
   receives an uninitialised pointer. */
   aloc = NULL;
   cloc = NULL;

/* Create a GRP group containing the required text. */
   grp = NULL;
   kpg1Kygrp( config, &grp, status );

/* Get the number of values in the group. Pass on if it is zero. */
   n = grpGrpsz( grp, status );
   if( n ) {

/* We need to pass a pointer to the "name" variable to grpGet */
      pname = name;

/* Scan the group to find the length of the longest value. */
      ncmax = 0;
      for( i = 1; i <= n; i++ ) {
         grpGet( grp, i, 1, &pname, GRP__SZNAM + 1, status );
         nc = astChrLen( name );
         if( nc > ncmax ) ncmax = nc;
      }

/* Create a suitable array of character strings in the CUPID extension,
   and get a locator for the whole array. */
      datThere( loc, "CONFIG", &there, status );
      if( there ) datErase( loc, "CONFIG", status );
      datNewC( loc, "CONFIG", ncmax + 1, 1, &n, status );
      datFind( loc, "CONFIG", &aloc, status );

/* Store each list item in the new array. */
      el = 1;
      for( i = 0; i < n; i++ ) {
         subs[ 0 ]= i + 1;
         cloc = NULL;
         datCell( aloc, 1, subs, &cloc, status );
         grpGet( grp, subs[ 0 ], 1, &pname, GRP__SZNAM + 1, status );
         nc = astChrLen( pname );
         datPutC( cloc, 0, &el, pname, astChrLen( name ), status );
         datAnnul( &cloc, status );
      }

/* Free resources. */
      datAnnul( &aloc, status );
   }

/* Delete the group */
   grpDelet( &grp, status );

}
예제 #8
0
void cupidGCNdfClump( HDSLoc **obj, double sum, double *par, double rms,
                    int ndim, int *lbox, int *ubox, int list_size,
                    double *mlist, int *plist, int *lbnd, int iclump,
                    int *dax, AstKeyMap *extra, int bad, int *status ){
/*
*+
*  Name:
*     cupidGCNdfClump

*  Purpose:
*     Create an NDF containing a description of a single clump.

*  Language:
*     Starlink C

*  Synopsis:
*     void cupidGCNdfClump( HDSLoc **obj, double sum, double *par, double rms,
*                         int ndim, int *lbox, int *ubox, int list_size,
*                         double *mlist, int *plist, int *lbnd, int iclump,
*                         int *dax, AstKeyMap *extra, int bad,
*                         int *status )

*  Description:
*     This function creates a temporary NDF and stores the integrated
*     intensity of the clump in its Data component. The bounds of the NDF
*     will be the smallest possible which still encompass the clump. In
*     addition, if required it will create a Cupid extension in the NDF
*     containing
*
*     - The parameters of a Gaussian approximation to the clump (if supplied).
*     - Any supplied extra information.

*  Parameters:
*     obj
*        A pointer to a locator for an HDS array of NDF objects. The array
*        will be extended to accomodate the new NDF. If NULL is supplied a
*        new temporary HDS object is created, and the locator stored at the
*        given address.
*     sum
*        The integrated intensity in the clump. Note, unlike par[0] and
*        par[1], this value should not be normalised to the RMS noise.
*     par
*        Pointer to an array holding the parameters of a Gaussian
*        approximation to the clump, or NULL. How many of these are used
*        depends on the value of "ndim": if "ndim" is 1 only elements 0 to
*        3 are used, if "ndim" is 2 only elements 0 to 6 are used, if "ndim"
*        is 3 all elements are used. All axis values are represented in GRID
*        pixels:
*
*           par[0]: Peak intensity of clump (in units of the RMS noise level).
*           par[1]: Constant intensity offset (in units of the RMS noise level).
*           par[2]: Model centre on internal axis 0 (in pixels)
*           par[3]: Intrinsic FWHM on axis 0 (in pixels)
*           par[4]: Model centre on internal axis 1 (in pixels)
*           par[5]: Intrinsic FWHM on axis 1 (in pixels)
*           par[6]: Spatial orientation angle (in radians, positive from
*                   +ve GRID1 axis to +ve GRID2 axis).
*           par[7]: Model centre on internal axis 3 (velocity) (in pixels)
*           par[8]: Intrinsic FWHM on velocity axis (in pixels)
*           par[9]: Axis 0 of internal velocity gradient vector (in velocity
*                   pixels per spatial pixel).
*           par[10]: Axis 1 of internal velocity gradient vector (in
*                   velocity pixels per spatial pixel).
*     rms
*        The RMS noise level.
*     ndim
*        The number of pixel axes in the array.
*     lbox
*        The lower grid index bounds of the area containing the clump
*        (using internal axis numbering).
*     ubox
*        The upper grid index bounds of the area containing the clump
*        (using internal axis numbering).
*     list_size
*        The number of values supplied in mlist and plist.
*     mlist
*        An array of "list_size" elements containing the clump values at
*        each pixel.
*     plist
*        An array of "ndim*list_size" elements in which each group of
*        "ndim" adjacent values forms the grid indices of the corresponding
*        value in "mlist". This uses external axis ordering.
*     lbnd
*        Pointer to array holding the pixel indices of the first pixel in
*        the user-supplied NDF (using external axis numbering).
*     iclump
*        The index of the current clump.
*     dax
*        Array holding external axis number indexed by internal axis number.
*     extra
*        An AstKeyMap holding extra diagnositic information to add to the
*        clump structure.
*     bad
*        Set the Unit component of the NDF to "BAD". This is used as a
*        flag to indicate that the clump touches too many areas of bad
*        pixels.
*     status
*        Pointer to the inherited status value.

*  Copyright:
*     Copyright (C) 2009 Science and Technology Facilities Council.
*     Copyright (C) 2005,2007 Particle Physics & Astronomy Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

*  Authors:
*     DSB: David S. Berry
*     TIMJ: Tim Jenness (JAC, Hawaii)
*     {enter_new_authors_here}

*  History:
*     10-NOV-2005 (DSB):
*        Original version.
*     5-MAR-2007 (DSB):
*        Initiaslise "exloc" locator to NULL before calling datFind.
*     13-JAN-2009 (TIMJ):
*        DO NOT CAST int* to size_t* since that is not going to work for long.
*     26-JAN-2011 (DSB):
*        Ensure the "m" pointer is incremented even if the currrent model pixel
*        is off the edge of the NDF. Previously, this bug caused a stripey
*        "aliasing" type effect if the supplied model data extends outside the
*        bounds of the NDF.
*     25-MAY-2017 (DSB):
*        Switch off group history and provenance recording during this
*        function. This is because it can inflate the time taken to run
*        findclumps enormously if there are many thousands of clumps.
*     {enter_further_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*-
*/

/* Local Variables: */

   const char *cen[] = { "CENTRE1", "CENTRE2", "CENTRE3" };
   const char *fwhm[] = { "FWHM1", "FWHM2", "FWHM3" };
   const char *vgrad[] = { "VGRAD1", "VGRAD2", "VGRAD3" };

   HDSLoc *cloc;                /* Cell locator */
   HDSLoc *dloc;                /* Component locator */
   HDSLoc *xloc;                /* Extension locator */
   HDSLoc *exloc;               /* Locator for structure holding extra info */
   const char *key;             /* KeyMap key name */
   double *ipd;                 /* Pointer to Data array */
   double *m;                   /* Pointer to next data value */
   double dval;                 /* Double value to store */
   int *p;                      /* Pointer to next grid axis value */
   int el;                      /* Number of elements mapped */
   int elb[ 3 ];                /* The lower NDF limit on each external axis */
   int elbox[ 3 ];              /* The lower box limit on each external axis */
   int estep[ 3 ];              /* The step size on each external axis */
   int eub[ 3 ];                /* The upper NDF limit on each external axis */
   int eubox[ 3 ];              /* The upper box limit on each external axis */
   int i;                       /* Point index */
   int indf;                    /* NDF identifier */
   int iv;                      /* 1D vector index for current data value */
   int j;                       /* Axis index */
   int lb[ 3 ];                 /* Lower pixel index bounds of NDF */
   int nex;                     /* No. of extra items of information */
   int ok;                      /* Pixel within clump NDF? */
   int old_ghstate;             /* Non-zero if group history recording is switched on */
   int old_pvstate;             /* Non-zero if provenance recording is switched on */
   int place;                   /* NDF place holder */
   int pv;                      /* Pixel offset */
   size_t oldsize;              /* Size of original NDF */
   hdsdim size[1];              /* No of elements in NDF array */
   int step[ 3 ];               /* The step size on each internal axis */
   int ub[ 3 ];                 /* Upper pixel index bounds of NDF */

/* Abort if an error has already occurred. */
   if( *status != SAI__OK ) return;

/* If no array was supplied create one of length 1. */
   if( !(*obj) ) {
      size[0] = 1;
      datTemp( "NDF", 1, size, obj, status );

/* Otherwise, get the number of NDFs already in the supplied array of
   NDFs, and increase it by 1. */
   } else {
      datSize( *obj, &oldsize, status );
      size[0] = oldsize + 1;
      datAlter( *obj, 1, size, status );
   }

/* Get a locator for the new cell. */
   cloc = NULL;
   datCell( *obj, 1, size, &cloc, status );

/* Begin an NDF context */
   ndfBegin();

/* Temporaily switch off group history and provenance recording since there
   can be thousands of clump NDFs. */
   ndgHltgh( 0, &old_ghstate, status );
   ndgHltpv( 0, &old_pvstate, status );

/* Find the pixel index bounds of the NDF and the step between adjacent
   pixels on each axis. */
   lb[ 0 ] = lbox[ 0 ] - 1 + lbnd[ dax[ 0 ] ];
   ub[ 0 ] = ubox[ 0 ] - 1 + lbnd[ dax[ 0 ] ];
   step[ 0 ] = 1;

   for( i = 1; i < ndim; i++ ) {
      lb[ i ] = lbox[ i ] - 1 + lbnd[ dax[ i ] ];
      ub[ i ] = ubox[ i ] - 1 + lbnd[ dax[ i ] ];
      step[ i ] = ( ub[ i - 1 ] - lb[ i - 1 ] + 1 )*step[ i - 1 ];
   }

/* Convert lbox, lb, ub and step from internal axis numbering to external axis
   numbering. */
   for( i = 0; i < ndim; i++ ) {
     elbox[ dax[ i ] ] = lbox[ i ];
     eubox[ dax[ i ] ] = ubox[ i ];
     elb[ dax[ i ] ] = lb[ i ];
     eub[ dax[ i ] ] = ub[ i ];
     estep[ dax[ i ] ] = step[ i ];
   }

/* Create a place holder for the new NDF within the new cell. The NDF will be
   copied to its final resting place before the program exits. */
   ndfPlace( cloc, " ", &place, status );

/* Create the NDF to receive the clump values. The size of this NDF is the
   minimum needed to contain the clump. */
   ndfNew( "_DOUBLE", ndim, elb, eub, &place, &indf, status );

/* Map the NDFs Data array, filling it with bad values. */
   ndfMap( indf, "DATA", "_DOUBLE", "WRITE/BAD", (void *) &ipd, &el, status );
   if( ipd ) {

/* Store every supplied model value in the NDF data array. */
      m = mlist;
      p = plist;
      for( i = 0; i < list_size; i++,m++ ) {

/* Find the 1D vector index into the NDF data array corresponding to the
   grid indices (within the user supplied NDF) of the current point.*/
         pv = *(p++);
         iv = pv - elbox[ 0 ];
         ok = ( pv >= elbox[ 0 ] && pv <= eubox[ 0 ] );
         for( j = 1; j < ndim; j++ ) {
            pv = *(p++);
            iv += ( pv - elbox[ j ] )*estep[ j ];
            if( pv < elbox[ j ] || pv > eubox[ j ] ) ok = 0;
         }

/* Store the value. */
         if( ok ) ipd[ iv ] = *m;
      }

/* Unmap the NDFs Data array. */
      ndfUnmap( indf, "DATA", status );
   }

/* If required, create a Cupid extension in the NDF. */
   if( par || extra ) {
      xloc = NULL;
      ndfXnew( indf, "CUPID", "CUPID_EXT", 0, NULL, &xloc, status );

/* First do Gaussian parameters. */
      if( par ) {

/* Store the integrated intensity in the clump. */
         dloc = NULL;
         datNew( xloc, "SUM", "_DOUBLE", 0, NULL, status );
         datFind( xloc, "SUM", &dloc, status );
         datPutD( dloc, 0, NULL, &sum, status );
         datAnnul( &dloc, status );

/* Store the parameters of the Gaussian approximation, taking out the
   normalisation by the RMS noise level.*/
         datNew( xloc, "PEAK", "_DOUBLE", 0, NULL, status );
         datFind( xloc, "PEAK", &dloc, status );
         dval = rms*par[ 0 ];
         datPutD( dloc, 0, NULL, &dval, status );
         datAnnul( &dloc, status );

         datNew( xloc, "OFFSET", "_DOUBLE", 0, NULL, status );
         datFind( xloc, "OFFSET", &dloc, status );
         dval = rms*par[ 1 ];
         datPutD( dloc, 0, NULL, &dval, status );
         datAnnul( &dloc, status );

         datNew( xloc, cen[ dax[ 0 ] ], "_DOUBLE", 0, NULL, status );
         datFind( xloc, cen[ dax[ 0 ] ], &dloc, status );
         dval = par[ 2 ] + lbnd[ dax[ 0 ] ] - 1.5;
         datPutD( dloc, 0, NULL, &dval, status );
         datAnnul( &dloc, status );

         datNew( xloc, fwhm[ dax[ 0 ] ], "_DOUBLE", 0, NULL, status );
         datFind( xloc, fwhm[ dax[ 0 ] ], &dloc, status );
         datPutD( dloc, 0, NULL, par + 3, status );
         datAnnul( &dloc, status );

         if( ndim > 1 ) {
            datNew( xloc, cen[ dax[ 1 ] ], "_DOUBLE", 0, NULL, status );
            datFind( xloc, cen[ dax[ 1 ] ], &dloc, status );
            dval = par[ 4 ] + lbnd[ dax[ 1 ] ] - 1.5;
            datPutD( dloc, 0, NULL, &dval, status );
            datAnnul( &dloc, status );

            datNew( xloc, fwhm[ dax[ 1 ] ], "_DOUBLE", 0, NULL, status );
            datFind( xloc, fwhm[ dax[ 1 ] ], &dloc, status );
            datPutD( dloc, 0, NULL, par + 5, status );
            datAnnul( &dloc, status );

            datNew( xloc, "ANGLE", "_DOUBLE", 0, NULL, status );
            datFind( xloc, "ANGLE", &dloc, status );
            dval = par[ 6 ]*AST__DR2D;
            datPutD( dloc, 0, NULL,  &dval, status );
            datAnnul( &dloc, status );

            if( ndim > 2 ) {

               datNew( xloc, cen[ dax[ 2 ] ], "_DOUBLE", 0, NULL, status );
               datFind( xloc, cen[ dax[ 2 ] ], &dloc, status );
               dval = par[ 7 ] + lbnd[ dax[ 2 ] ] - 1.5;
               datPutD( dloc, 0, NULL, &dval, status );
               datAnnul( &dloc, status );

               datNew( xloc, fwhm[ dax[ 2 ] ], "_DOUBLE", 0, NULL, status );
               datFind( xloc, fwhm[ dax[ 2 ] ], &dloc, status );
               datPutD( dloc, 0, NULL, par + 8, status );
               datAnnul( &dloc, status );

               datNew( xloc, vgrad[ dax[ 0 ] ], "_DOUBLE", 0, NULL, status );
               datFind( xloc, vgrad[ dax[ 0 ] ], &dloc, status );
               datPutD( dloc, 0, NULL, par + 9, status );
               datAnnul( &dloc, status );

               datNew( xloc, vgrad[ dax[ 1 ] ], "_DOUBLE", 0, NULL, status );
               datFind( xloc, vgrad[ dax[ 1 ] ], &dloc, status );
               datPutD( dloc, 0, NULL, par + 10, status );
               datAnnul( &dloc, status );

            }
         }
      }

/* Now store any extra diagnostic information. */
      if( extra ) {
         datNew( xloc, "EXTRA", "EXTRA", 0, NULL, status );
         exloc = NULL;
         datFind( xloc, "EXTRA", &exloc, status );

         nex = astMapSize( extra );
         for( i = 0; i < nex; i++ ) {
            key = astMapKey( extra, i );
            if( astMapGet0D( extra, key, &dval ) ) {
               datNew( exloc, key, "_DOUBLE", 0, NULL, status );
               datFind( exloc, key, &dloc, status );
               datPutD( dloc, 0, NULL, &dval, status );
               datAnnul( &dloc, status );
            }
         }

         datAnnul( &exloc, status );

      }

/* Release the extension locator. */
      datAnnul( &xloc, status );
   }

/* If required set the Unit component to "BAD". */
   if( bad ) ndfCput( "BAD", indf, "Unit", status );

/* Switch group history and provenance recording back to their original
   states. */
   ndgHltgh( old_ghstate, NULL, status );
   ndgHltpv( old_pvstate, NULL, status );

/* End the NDF context */
   ndfEnd( status );

/* Release the cell locator. */
   datAnnul( &cloc, status );

}
예제 #9
0
void smurf_jsatileinfo( int *status ) {

/* Local Variables */
   AstCmpRegion *overlap;
   AstFitsChan *fc;
   AstFrameSet *fs;
   AstObject *obj;
   AstRegion *region;
   AstRegion *target;
   HDSLoc *cloc = NULL;
   HDSLoc *xloc = NULL;
   char *jcmt_tiles;
   char *tilendf = NULL;
   char text[ 200 ];
   double dec[ 8 ];
   double dist;
   double dlbnd[ 2 ];
   double dubnd[ 2 ];
   double gx[ 8 ];
   double gy[ 8 ];
   double maxdist;
   double norm_radec[2];
   double point1[ 2 ];
   double point2[ 2 ];
   double ra[ 8 ];
   double ra0;
   double dec0;
   int *ipntr;
   int axes[ 2 ];
   int create;
   int dirlen;
   int el;
   int exists;
   int flag;
   int i;
   int indf1;
   int indf2;
   int indf3;
   int itile;
   int iv;
   int jtile;
   int lbnd[ 2 ];
   int local_origin;
   int nc;
   int place;
   int tlbnd[ 2 ];
   int tubnd[ 2 ];
   int ubnd[ 2 ];
   smf_jsaproj_t proj;
   int xt;
   int yt;
   smfJSATiling skytiling;
   void *pntr;

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* Start a new AST context. */
   astBegin;

/* Get the instrument to use abnd get the parameters describing the
   layout of its JSA tiles. */
   smf_jsainstrument( "INSTRUMENT", NULL, SMF__INST_NONE, &skytiling,
                      status );

/* Return the maximum tile index. */
   parPut0i( "MAXTILE", skytiling.ntiles - 1, status );

/* Abort if an error has occurred. */
   if( *status != SAI__OK ) goto L999;

/* Decide what sort of projection to use. */
   parChoic( "PROJ", "HPX", "HPX,HPX12,XPHN,XPHS", 1, text, sizeof(text),
             status );
   proj = smf_jsaproj_fromstr( text, 1, status );

/* If required, create an all-sky NDF in which each pixel covers the area
   of a single tile, and holds the integer tile index. The NDF has an
   initial size of 1x1 pixels, but is expanded later to the required size. */
   lbnd[ 0 ] = ubnd[ 0 ] = lbnd[ 1 ] = ubnd[ 1 ] = 1;
   ndfCreat( "ALLSKY", "_INTEGER", 2, lbnd, ubnd, &indf3, status );

/* If a null (!) value was supplied for parameter ALLSKY, annull the
   error and pass on. */
   if( *status == PAR__NULL ) {
      errAnnul( status );

/* Otherwise, create a FrameSet describing the whole sky in which each
   pixel corresponds to a single tile. */
   } else {
      smf_jsatile( -1, &skytiling, 0, proj, NULL, &fs, NULL, lbnd, ubnd,
                   status );

/* Change the bounds of the output NDF. */
      ndfSbnd( 2, lbnd, ubnd, indf3, status );

/* Store the FrameSet in the NDF. */
      ndfPtwcs( fs, indf3, status );

/* Map the data array. */
      ndfMap( indf3, "Data", "_INTEGER", "WRITE/BAD", (void **) &ipntr, &el,
              status );

/* Create all-sky map using XPH projection. */
      if( *status == SAI__OK ) {

/* Loop round every tile index. */
         for( jtile = 0; jtile < skytiling.ntiles; jtile++ ) {

/* Get the zero-based (x,y) indices of the tile within an HPX projection.
   This flips the bottom left half-facet up to the top right. */
            smf_jsatilei2xy( jtile, &skytiling, &xt, &yt, NULL, status );

/* Convert these HPX indices to the corresponding indices within the
   required projection. Note, the lower left facet is split by the above
   call to smf_jsatilei2xy tile (i.e. (xt,yt) indices are *not* in the
   "raw" mode). For instance, (0,0) is not a valid tile. */
            smf_jsatilexyconv( &skytiling, proj, xt, yt, 0, &xt, &yt, status );

/* Get the vector index of the corresponding element of the all-sky NDF. */
            if( proj == SMF__JSA_HPX || proj == SMF__JSA_HPX12 ) {
               iv = xt + 5*skytiling.ntpf*yt;
            } else {
               iv = xt + 4*skytiling.ntpf*yt;
            }

/* Report an error if this element has already been assigned a tile
   index. Otherwise, store the tile index. */
            if( ipntr[ iv ] == VAL__BADI ) {
               ipntr[ iv ] = jtile;
            } else if( *status == SAI__OK ) {
               *status = SAI__ERROR;
               errRepf( "", "%s projection assigns multiple tiles to "
                        "pixel (%d,%d).", status, text, xt, yt );
               break;
            }
         }
      }

/* Store NDF title. */
      sprintf( text, "JSA tile indices for %s data", skytiling.name );
      ndfCput( text, indf3, "TITLE", status );

/* Store the instrument as a component in the SMURF extension. */
      ndfXnew( indf3, "SMURF", "INSTRUMENT", 0, 0, &xloc, status );
      ndfXpt0c( skytiling.name, indf3, "SMURF", "INSTRUMENT", status );
      datAnnul( &xloc, status );

/* Close the NDF. */
      ndfAnnul( &indf3, status );
   }

/* Abort if an error has occurred. */
   if( *status != SAI__OK ) goto L999;

/* Get the zero-based index of the required tile. If a null value is
   supplied, annull the error and skip to the end. */
   parGdr0i( "ITILE", 0, 0, skytiling.ntiles - 1, 0, &itile, status );
   if( *status == PAR__NULL ) {
       errAnnul( status );
       goto L999;
   }

/* See if the pixel origin is to be at the centre of the tile. */
   parGet0l( "LOCAL", &local_origin, status );

/* Display the tile number. */
   msgBlank( status );
   msgSeti( "ITILE", itile );
   msgSeti( "MAXTILE", skytiling.ntiles - 1);
   msgOut( " ", "   Tile ^ITILE (from 0 to ^MAXTILE):", status );

/* Get the FITS header, FrameSet and Region defining the tile, and the tile
   bounds in pixel indices. */
   smf_jsatile( itile, &skytiling, local_origin,  proj, &fc, &fs, &region,
                lbnd, ubnd, status );

/* Write the FITS headers out to a file, annulling the error if the
   header is not required. */
   if( *status == SAI__OK ) {
      atlDumpFits( "HEADER", fc, status );
      if( *status == PAR__NULL ) errAnnul( status );
   }

/* If required, write the Region out to a text file. */
   if( *status == SAI__OK ) {
      atlCreat( "REGION", (AstObject *) region, status );
      if( *status == PAR__NULL ) errAnnul( status );
   }

/* Store the lower and upper pixel bounds of the tile. */
   parPut1i( "LBND", 2, lbnd, status );
   parPut1i( "UBND", 2, ubnd, status );

/* Display pixel bounds on the screen. */
   msgSeti( "XL", lbnd[ 0 ] );
   msgSeti( "XU", ubnd[ 0 ] );
   msgSeti( "YL", lbnd[ 1 ] );
   msgSeti( "YU", ubnd[ 1 ] );
   msgOut( " ", "      Pixel bounds: (^XL:^XU,^YL:^YU)", status );

/* Get the RA,Dec at the tile centre. */
   if( astTest( fs, "SkyRef" ) ) {
      ra0 = astGetD( fs, "SkyRef(1)" );
      dec0 = astGetD( fs, "SkyRef(2)" );

/* Format the central RA and Dec. and display. Call astNorm on the
   coordinates provided that the frame set has the correct number of
   axes (which it should as it comes from smf_jsatile). */
      norm_radec[0] = ra0;
      norm_radec[1] = dec0;
      if (astGetI(fs, "Naxes") == 2) astNorm(fs, norm_radec);
      msgSetc( "RACEN",  astFormat( fs, 1, norm_radec[ 0 ] ));
      msgSetc( "DECCEN",  astFormat( fs, 2, norm_radec[ 1 ] ));
      msgOut( " ", "      Centre (ICRS): RA=^RACEN DEC=^DECCEN", status );

/* Transform a collection of points on the edge of the region (corners and
   side mid-points) from GRID coords to RA,Dec. */
      point1[ 0 ] = 0.5;
      point1[ 1 ] = 0.5;
      point2[ 0 ] = ubnd[ 0 ] - lbnd[ 0 ] + 1;
      point2[ 1 ] = ubnd[ 1 ] - lbnd[ 1 ] + 1;

      gx[ 0 ] = point1[ 0 ];         /* Bottom left */
      gy[ 0 ] = point1[ 1 ];

      gx[ 1 ] = point1[ 0 ];         /* Centre left */
      gy[ 1 ] = gy[ 0 ];

      gx[ 2 ] = point1[ 0 ];         /* Top left */
      gy[ 2 ] = point2[ 1 ];

      gx[ 3 ] = gx[ 0 ];             /* Top centre */
      gy[ 3 ] = point2[ 1 ];

      gx[ 4 ] = point2[ 0 ];         /* Top right */
      gy[ 4 ] = point2[ 1 ];

      gx[ 5 ] = point2[ 0 ];         /* Centre right */
      gy[ 5 ] = gy[ 0 ];

      gx[ 6 ] = point2[ 0 ];         /* Bottom right */
      gy[ 6 ] = point1[ 1 ];

      gx[ 7 ] = gx[ 0 ];             /* Bottom centre */
      gy[ 7 ] = point1[ 1 ];

      astTran2( fs, 8, gx, gy, 1, ra, dec );

/* Find the arc-distance from the centre to the furthest point from the
   centre. */
      point1[ 0 ] = ra0;
      point1[ 1 ] = dec0;
      maxdist = -1.0;

      for( i = 1; i < 8; i++ ) {
         if( ra[ i ] != AST__BAD && dec[ i ] != AST__BAD ) {
            point2[ 0 ] = ra[ i ];
            point2[ 1 ] = dec[ i ];
            dist = astDistance( fs, point1, point2 );
            if( dist > maxdist ) maxdist = dist;
         }
      }

/* Convert from radius to diameter. */
      maxdist *= 2.0;

/* Format this size as a dec value (i.e. arc-distance) and display it. */
      if( maxdist > 0.0 ) {
         msgSetc( "SIZE",  astFormat( fs, 2, maxdist ) );
         msgOut( " ", "      Size: ^SIZE", status );
      } else {
         maxdist = AST__BAD;
         msgOut( " ", "      Size: <unknown>", status );
      }

/* If a discontinuity passes through the tile, the centre and size may be
   unknown. */
   } else {
      ra0 = AST__BAD;
      dec0 = AST__BAD;
      maxdist = AST__BAD;
      msgOut( " ", "      Centre (ICRS): RA=<unknown> DEC=<unknown>", status );
      msgOut( " ", "      Size: <unknown>", status );
   }

/* Write the tile centre ra and dec in radians to the output parameters. */
   parPut0d( "RACEN", norm_radec[ 0 ], status );
   parPut0d( "DECCEN", norm_radec[ 1 ], status );

/* Write the size to the output parameter as radians. */
   parPut0d( "SIZE", maxdist, status );

/* Get the translation of the environment variable JSA_TILE_DIR. */
   jcmt_tiles = getenv( "JSA_TILE_DIR" );

/* Initialise the path to the tile's NDF to hold the root directory.
   Use the current working directory if JSA_TILE_DIR is undefined. */
   if( jcmt_tiles ) {
      nc = 0;
      tilendf = astAppendString( tilendf, &nc, jcmt_tiles );

   } else {

      nc = 512;
      jcmt_tiles = astMalloc( nc );

      while( !getcwd( jcmt_tiles, nc ) ) {
         nc *= 2;
         jcmt_tiles = astRealloc( jcmt_tiles, nc );
      }

      nc = 0;
      tilendf = astAppendString( tilendf, &nc, jcmt_tiles );
      jcmt_tiles = astFree( jcmt_tiles );
   }

/* Complete the path to the tile's NDF. */
   tilendf = astAppendString( tilendf, &nc, "/" );
   tilendf = astAppendString( tilendf, &nc, skytiling.subdir );
   dirlen = nc;
   sprintf( text, "/tile_%d.sdf", itile );
   tilendf = astAppendString( tilendf, &nc, text );

/* Write it to the output parameter. */
   parPut0c( "TILENDF", tilendf, status );

/* See if the NDF exists, and store the flag in the output parameter. */
   exists = access( tilendf, F_OK ) ? 0 : 1;
   parPut0l( "EXISTS", exists, status );

/* If the NDF does not exist, create it if required. */
   parGet0l( "CREATE", &create, status );
   if( !exists && create && *status == SAI__OK ) {

/* Write the NDF info to the screen. */
      msgSetc( "NDF",  tilendf );
      msgOutif( MSG__NORM, " ", "      NDF: ^NDF (created)", status );

/* Temporarily terminate the NDF path at the end of the subdirectory. */
      tilendf[ dirlen ] = 0;

/* Create the required directory (does nothing if the directory
   already exists).  It is given read/write/search permissions for owner
   and group, and read/search permissions for others. */
      (void) mkdir( tilendf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );

/* Replace the character temporarily overwritten above. */
      tilendf[ dirlen ] = '/';

/* Now create the tile's NDF. */
      ndfPlace( NULL, tilendf, &place, status );
      ndfNew( skytiling.type, 2, lbnd, ubnd, &place, &indf1, status );

/* Fill its data array with zeros. */
      ndfMap( indf1, "Data", skytiling.type, "WRITE/ZERO", &pntr, &el,
              status );

/* Store the WCS FrameSet. */
      ndfPtwcs( fs, indf1, status );

/* If the instrument jsatiles.have variance, fill the variance array with zeros. */
      if( skytiling.var ) {
         ndfMap( indf1, "Variance", skytiling.type, "WRITE/ZERO", &pntr,
                 &el, status );
      }

/* Create a SMURF extension. */
      ndfXnew( indf1, SMURF__EXTNAME, SMURF__EXTTYPE, 0, NULL, &xloc, status );

/* Store the tile number and instrument name in the extension. */
      datNew0I( xloc, "TILE", status );
      datFind( xloc, "TILE", &cloc, status );
      datPut0I( cloc, itile, status );
      datAnnul( &cloc, status );

      datNew0C( xloc, "INSTRUMENT", strlen( skytiling.name ), status );
      datFind( xloc, "INSTRUMENT", &cloc, status );
      datPut0C( cloc, skytiling.name, status );
      datAnnul( &cloc, status );

/* Create a weights NDF within the SMURF extension, and fill its data
   array with zeros. */
      ndfPlace( xloc, "WEIGHTS", &place, status );
      ndfNew( skytiling.type, 2, lbnd, ubnd, &place, &indf2, status );
      ndfMap( indf2, "Data", skytiling.type, "WRITE/ZERO", &pntr, &el,
              status );
      ndfPtwcs( fs, indf2, status );
      ndfAnnul( &indf2, status );

/* Annul the extension locator and the main NDF identifier. */
      datAnnul( &xloc, status );
      ndfAnnul( &indf1, status );

/* Write the NDF info to the screen. */
   } else {
      msgSetc( "NDF",  tilendf );
      msgSetc( "E",  exists ? "exists" : "does not exist" );
      msgOut( " ", "      NDF: ^NDF (^E)", status );
   }

/* Initialise TBND and TLBND to indicate no overlap. */
   tlbnd[ 0 ] = 1;
   tlbnd[ 1 ] = 1;
   tubnd[ 0 ] = 0;
   tubnd[ 1 ] = 0;

/* Attempt to to get an AST Region (assumed to be in some 2D sky coordinate
   system) using parameter "TARGET". */
   if( *status == SAI__OK ) {
      kpg1Gtobj( "TARGET", "Region",
                 (void (*)( void )) F77_EXTERNAL_NAME(ast_isaregion),
                 &obj, status );

/* Annul the error if none was obtained. */
      if( *status == PAR__NULL ) {
         errAnnul( status );

/* Otherwise, use the supplied object. */
      } else {
         target = (AstRegion *) obj;

/* If the target Region is 3-dimensional, remove the third axis, which
   is assumed to be a spectral axis. */
         if( astGetI( target, "Naxes" ) == 3 ) {
            axes[ 0 ] = 1;
            axes[ 1 ] = 2;
            target = astPickAxes( target, 2, axes, NULL );
         }

/* See if there is any overlap between the target and the tile. */
         overlap = NULL;
         flag = astOverlap( region, target );

         if( flag == 0 ) {
            msgOut( "", "      Cannot convert between the coordinate system of the "
                    "supplied target and the tile.", status );

         } else if( flag == 1 || flag == 6 ) {
            msgOut( "", "      There is no overlap between the target and the tile.",
                    status );

         } else if( flag == 2 ) {
            msgOut( "", "      The tile is contained within the target.",
                    status );
            tlbnd[ 0 ] = lbnd[ 0 ];
            tlbnd[ 1 ] = lbnd[ 1 ];
            tubnd[ 0 ] = ubnd[ 0 ];
            tubnd[ 1 ] = ubnd[ 1 ];

         } else if( flag == 3 ) {
            overlap = astCmpRegion( region, target, AST__AND, " " );

         } else if( flag == 4 ) {
            overlap = astCmpRegion( region, target, AST__AND, " " );

         } else if( flag == 5 ) {
            msgOut( "", "      The target and tile are identical.",
                    status );
            tlbnd[ 0 ] = lbnd[ 0 ];
            tlbnd[ 1 ] = lbnd[ 1 ];
            tubnd[ 0 ] = ubnd[ 0 ];
            tubnd[ 1 ] = ubnd[ 1 ];

         } else if( *status == SAI__OK ) {
            *status = SAI__OK;
            errRepf( "", "Unexpected value %d returned by astOverlap "
                     "(programming error).", status, flag );
         }

/* If a region containing the intersection of the tile and target was
   created above, map it into the grid coordinate system of the tile. */
         if( overlap ) {
            overlap = astMapRegion( overlap, astGetMapping( fs, AST__CURRENT,
                                                            AST__BASE ),
                                    astGetFrame( fs, AST__BASE ) );

/* Get its GRID bounds. */
            astGetRegionBounds( overlap, dlbnd, dubnd );

/* Convert to integer. */
            tlbnd[ 0 ] = ceil( dlbnd[ 0 ] - 0.5 );
            tlbnd[ 1 ] = ceil( dlbnd[ 1 ] - 0.5 );
            tubnd[ 0 ] = ceil( dubnd[ 0 ] - 0.5 );
            tubnd[ 1 ] = ceil( dubnd[ 1 ] - 0.5 );

/* Convert to PIXEL indices within the tile. */
            tlbnd[ 0 ] += lbnd[ 0 ] - 1;
            tlbnd[ 1 ] += lbnd[ 1 ] - 1;
            tubnd[ 0 ] += lbnd[ 0 ] - 1;
            tubnd[ 1 ] += lbnd[ 1 ] - 1;

            msgOutf( "", "      The target overlaps section (%d:%d,%d:%d).",
                     status, tlbnd[ 0 ], tubnd[ 0 ], tlbnd[ 1 ], tubnd[ 1 ] );
         }
      }
   }

/* Store the pixel index bounds of the tiles overlap with the target. */
   parPut1i( "TLBND", 2, tlbnd, status );
   parPut1i( "TUBND", 2, tubnd, status );

/* Arrive here if an error occurs. */
   L999:;

/* Free resources. */
   tilendf = astFree( tilendf );

/* End the AST context. */
   astEnd;

/* Issue a status indication.*/
   msgBlank( status );
   if( *status == SAI__OK ) {
      msgOutif( MSG__VERB, "", "JSATILEINFO succeeded.", status);
   } else {
      msgOutif( MSG__VERB, "", "JSATILEINFO failed.", status);
   }
}
예제 #10
0
void smurf_unmakemap( int *status ) {

/* Local Variables */
   AstFrameSet *wcsin = NULL; /* WCS Frameset for input cube */
   AstMapping *skymap;        /* GRID->SkyFrame Mapping from input WCS */
   AstSkyFrame *abskyfrm;     /* Input SkyFrame (always absolute) */
   AstSkyFrame *skyfrm = NULL;/* SkyFrame from the input WCS Frameset */
   Grp *igrp1 = NULL;         /* Group of input sky files */
   Grp *igrp2 = NULL;         /* Group of input template files */
   Grp *igrpc = NULL;         /* Group of input COM files */
   Grp *igrpg = NULL;         /* Group of input GAI files */
   Grp *igrpq = NULL;         /* Group of input Q  sky files */
   Grp *igrpu = NULL;         /* Group of input U sky files */
   Grp *ogrp = NULL;          /* Group containing output file */
   HDSLoc *cloc = NULL;       /* HDS locator for component ipdata structure */
   HDSLoc *iploc = NULL;      /* HDS locator for top level ipdata structure */
   ThrWorkForce *wf = NULL;   /* Pointer to a pool of worker threads */
   char ipdata[ 200 ];        /* Text buffer for IPDATA value */
   char pabuf[ 10 ];          /* Text buffer for parameter value */
   char subarray[ 5 ];        /* Name of SCUBA-2 subarray (s8a,s8b,etc) */
   dim_t iel;                 /* Index of next element */
   dim_t ndata;               /* Number of elements in array */
   dim_t ntslice;             /* Number of time slices in array */
   double *ang_data = NULL;   /* Pointer to the FP orientation angles */
   double *angc_data = NULL;  /* Pointer to the instrumental ANGC data */
   double *c0_data = NULL;    /* Pointer to the instrumental C0 data */
   double *gai_data = NULL;   /* Pointer to the input GAI map */
   double *in_data = NULL;    /* Pointer to the input I sky map */
   double *inc_data = NULL;   /* Pointer to the input COM data */
   double *inq_data = NULL;   /* Pointer to the input Q sky map */
   double *inu_data = NULL;   /* Pointer to the input U sky map */
   double *outq_data = NULL;  /* Pointer to the Q time series data */
   double *outu_data = NULL;  /* Pointer to the U time series data */
   double *p0_data = NULL;    /* Pointer to the instrumental P0 data */
   double *p1_data = NULL;    /* Pointer to the instrumental P1 data */
   double *pd;                /* Pointer to next element */
   double *pq = NULL;         /* Pointer to next Q time series value */
   double *pu = NULL;         /* Pointer to next U time series value */
   double *qinst_data = NULL; /* Pointer to the instrumental Q data */
   double *uinst_data = NULL; /* Pointer to the instrumental U data */
   double amp16;              /* Amplitude of 16 Hz signal */
   double amp2;               /* Amplitude of 2 Hz signal */
   double amp4;               /* Amplitude of 4 Hz signal */
   double angrot;             /* Angle from focal plane X axis to fixed analyser */
   double paoff;              /* WPLATE value corresponding to POL_ANG=0.0 */
   double params[ 4 ];        /* astResample parameters */
   double phase16;            /* Phase of 16 Hz signal */
   double phase2;             /* Phase of 2 Hz signal */
   double phase4;             /* Phase of 4 Hz signal */
   double sigma;              /* Standard deviation of noise to add to output */
   int alignsys;              /* Align data in the map's system? */
   int cdims[ 3 ];            /* Common-mode NDF dimensions */
   int dims[ NDF__MXDIM ];    /* NDF dimensions */
   int flag;                  /* Was the group expression flagged? */
   int gdims[ 3 ];            /* GAI model NDF dimensions */
   int harmonic;              /* The requested harmonic */
   int ifile;                 /* Input file index */
   int indf;                  /* Input sky map NDF identifier */
   int indfangc;              /* IP ANGC values NDF identifier */
   int indfc0;                /* IP C0 values NDF identifier */
   int indfc;                 /* Input COM NDF identifier */
   int indfcs;                /* NDF identifier for matching section of COM */
   int indfg;                 /* Input GAI NDF identifier */
   int indfin;                /* Input template cube NDF identifier */
   int indfiq;                /* Input instrumental Q NDF */
   int indfiu;                /* Input instrumental U NDF */
   int indfout;               /* Output cube NDF identifier */
   int indfp0;                /* IP P0 values NDF identifier */
   int indfp1;                /* IP P1 values NDF identifier */
   int indfq;                 /* Input Q map NDF identifier */
   int indfu;                 /* Input U map NDF identifier */
   int interp = 0;            /* Pixel interpolation method */
   int lbndc[ 3 ];            /* Array of lower bounds of COM NDF */
   int moving;                /* Is the telescope base position changing? */
   int ndim;                  /* Number of pixel axes in NDF */
   int ndimc;                 /* Number of pixel axes in common-mode NDF */
   int ndimg;                 /* Number of pixel axes in GAI NDF */
   int nel;                   /* Number of elements in array */
   int nelc;                  /* Number of elements in COM array */
   int nelg;                  /* Number of elements in GAI array */
   int nelqu;                 /* Number of elements in Q or U array */
   int ngood;                 /* No. of good values in putput cube */
   int nparam = 0;            /* No. of parameters required for interpolation scheme */
   int pasign;                /* Indicates sense of POL_ANG value */
   int sdim[ 2 ];             /* Array of significant pixel axes */
   int slbnd[ 2 ];            /* Array of lower bounds of input map */
   int subnd[ 2 ];            /* Array of upper bounds of input map */
   int ubndc[ 3 ];            /* Array of upper bounds of COM NDF */
   size_t ncom;               /* Number of com files */
   size_t ngai;               /* Number of gai files */
   size_t nskymap;            /* Number of supplied sky cubes */
   size_t outsize;            /* Number of files in output group */
   size_t size;               /* Number of files in input group */
   smfData *odata = NULL;     /* Pointer to output data struct */

/* Check inherited status */
   if( *status != SAI__OK ) return;

/* Begin an AST context */
   astBegin;

/* Begin an NDF context. */
   ndfBegin();

/* Find the number of cores/processors available and create a pool of
   threads of the same size. */
   wf = thrGetWorkforce( thrGetNThread( SMF__THREADS, status ), status );

/* Get an identifier for the input NDF. We use NDG (via kpg1Rgndf)
   instead of calling ndfAssoc directly since NDF/HDS has problems with
   file names containing spaces, which NDG does not have. */
   kpg1Rgndf( "IN", 1, 1, "", &igrp1, &nskymap, status );
   ndgNdfas( igrp1, 1, "READ", &indf, status );

/* Map the data array in the input sky map. */
   ndfMap( indf, "DATA", "_DOUBLE", "READ", (void **) &in_data, &nel,
           status );

/* Get the WCS FrameSet from the sky map, together with its pixel index
   bounds. */
   kpg1Asget( indf, 2, 0, 1, 1, sdim, slbnd, subnd, &wcsin, status );

/* Check the current Frame is a SKY frame. */
   skyfrm = astGetFrame( wcsin, AST__CURRENT );
   if( !astIsASkyFrame( skyfrm ) && *status == SAI__OK ) {
      ndfMsg( "N", indf );
      *status = SAI__ERROR;
      errRep( " ", " Current Frame in ^N is not a SKY Frame.", status );
   }

/* Get a copy of the current frame that represents absolute coords rather
   than offsets. We assume the target is moving if the map represents
   offsets. */
   moving = ( *status == SAI__OK &&
              !strcmp( astGetC( skyfrm, "SkyRefIs" ), "Origin" ) ) ? 1 : 0;
   abskyfrm = astCopy( skyfrm );
   astClear( abskyfrm, "SkyRefIs" );

/* If the ALIGNSYS parameter is TRUE then we align the raw data with the
   map in the current system of the map, rather than the default ICRS. */
   parGet0l( "ALIGNSYS", &alignsys, status );
   if( alignsys ) astSetC( abskyfrm, "AlignSystem", astGetC( abskyfrm,
                                                             "System" ) );

/* Get the Mapping from the Sky Frame to grid axis in the iput map. */
   skymap = astGetMapping( wcsin, AST__CURRENT, AST__BASE );

/* Get the pixel interpolation scheme to use. */
   parChoic( "INTERP", "NEAREST", "NEAREST,LINEAR,SINC,"
             "SINCSINC,SINCCOS,SINCGAUSS,SOMB,SOMBCOS",
             1, pabuf, 10, status );

   if( !strcmp( pabuf, "NEAREST" ) ) {
      interp = AST__NEAREST;
      nparam = 0;

   } else if( !strcmp( pabuf, "LINEAR" ) ) {
      interp = AST__LINEAR;
      nparam = 0;

   } else if( !strcmp( pabuf, "SINC" ) ) {
      interp = AST__SINC;
      nparam = 1;

   } else if( !strcmp( pabuf, "SINCSINC" ) ) {
      interp = AST__SINCSINC;
      nparam = 2;

   } else if( !strcmp( pabuf, "SINCCOS" ) ) {
      interp = AST__SINCCOS;
      nparam = 2;

   } else if( !strcmp( pabuf, "SINCGAUSS" ) ) {
      interp = AST__SINCGAUSS;
      nparam = 2;

   } else if( !strcmp( pabuf, "SOMB" ) ) {
      interp = AST__SOMB;
      nparam = 1;

   } else if( !strcmp( pabuf, "SOMBCOS" ) ) {
      interp = AST__SOMBCOS;
      nparam = 2;

   } else if( *status == SAI__OK ) {
      nparam = 0;
      *status = SAI__ERROR;
      msgSetc( "V", pabuf );
      errRep( "", "Support not available for INTERP = ^V (programming "
              "error)", status );
   }

/* Get an additional parameter vector if required. */
   if( nparam > 0 ) parExacd( "PARAMS", nparam, params, status );

/* Get a group of reference time series files to use as templates for
   the output time series files.*/
   ndgAssoc( "REF", 1, &igrp2, &size, &flag, status );

/* Get output file(s) */
   kpg1Wgndf( "OUT", igrp2, size, size, "More output files required...",
              &ogrp, &outsize, status );

/* Get he noise level to add to the output data. */
   parGet0d( "SIGMA", &sigma, status );

/* Get any Q and U input maps. */
   if( *status == SAI__OK ) {

      kpg1Rgndf( "QIN", 1, 1, "", &igrpq, &nskymap, status );
      ndgNdfas( igrpq, 1, "READ", &indfq, status );
      ndfMap( indfq, "DATA", "_DOUBLE", "READ", (void **) &inq_data, &nelqu,
              status );
      if( nelqu != nel && *status == SAI__OK ) {
         ndfMsg( "Q", indfq );
         *status = SAI__ERROR;
         errRep( "", "Q image '^Q' is not the same size as the I image.",
                 status );
      }

      kpg1Rgndf( "UIN", 1, 1, "", &igrpu, &nskymap, status );
      ndgNdfas( igrpu, 1, "READ", &indfu, status );
      ndfMap( indfu, "DATA", "_DOUBLE", "READ", (void **) &inu_data, &nelqu,
              status );
      if( nelqu != nel && *status == SAI__OK ) {
         ndfMsg( "U", indfu );
         *status = SAI__ERROR;
         errRep( "", "U image '^U' is not the same size as the I image.",
                 status );
      }

      if( *status == PAR__NULL ) {
         ndfAnnul( &indfq, status );
         ndfAnnul( &indfu, status );
         inq_data = NULL;
         inu_data = NULL;
         errAnnul( status );
      } else {
         parGet0d( "ANGROT", &angrot, status );
         parGet0d( "PAOFF", &paoff, status );
         parGet0l( "PASIGN", &pasign, status );
      }
   }

/* Get any common-mode files. */
   if( *status == SAI__OK ) {
      kpg1Rgndf( "COM", size, size, "", &igrpc, &ncom, status );
      if( *status == PAR__NULL ) {
         errAnnul( status );
         ncom = 0;
      }
   }

/* Get any GAI files. */
   if( *status == SAI__OK ) {
      kpg1Rgndf( "GAI", size, size, "", &igrpg, &ngai, status );
      if( *status == PAR__NULL ) {
         errAnnul( status );
         ngai = 0;
      }
   }

/* Get any instrumental polarisation files. */
   if( *status == SAI__OK ) {

/* First see if the user wants to use the "INSTQ/INSTU" scheme for
   specifying instrumental polarisation. */
      ndfAssoc( "INSTQ", "Read", &indfiq, status );
      ndfAssoc( "INSTU", "Read", &indfiu, status );

      if( *status == PAR__NULL ) {
         ndfAnnul( &indfiq, status );
         ndfAnnul( &indfiu, status );
         errAnnul( status );

      } else {
         msgOut( " ", "Using user-defined IP model", status );

         ndfDim( indfiq, 2, dims, &ndim, status );
         if( dims[ 0 ] != 32 || dims[ 1 ] != 40 ) {
            *status = SAI__ERROR;
            ndfMsg( "N", indfiq );
            errRep( " ", "Instrumental polarisation file ^N has bad "
                    "dimensions - should be 32x40.", status );
         } else {
            ndfMap( indfiq, "DATA", "_DOUBLE", "READ", (void **) &qinst_data,
                    &nel, status );
         }

         ndfDim( indfiu, 2, dims, &ndim, status );
         if( dims[ 0 ] != 32 || dims[ 1 ] != 40 ) {
            *status = SAI__ERROR;
            ndfMsg( "N", indfiu );
            errRep( " ", "Instrumental polarisation file ^N has bad "
                    "dimensions - should be 32x40.", status );
         } else {
            ndfMap( indfiu, "DATA", "_DOUBLE", "READ", (void **) &uinst_data,
                    &nel, status );
         }
      }

/* If not, see if the user wants to use the Johnstone/Kennedy instrumental
   polarisation model. The IPDATA parameter gives the path to an HDS
   container file contining NDFs holding the required IP data for all
   subarrays. */
      if( !qinst_data ) {
         parGet0c( "IPDATA", ipdata, sizeof(ipdata), status );
         if( *status == PAR__NULL ) {
            errAnnul( status );
         } else {
            msgOutf( " ", "Using Johnstone/Kennedy IP model in %s",
                     status, ipdata );
            hdsOpen( ipdata, "READ", &iploc, status );
         }
      }
   }

/* Loop round all the template time series files. */
   for( ifile = 1; ifile <= (int) size && *status == SAI__OK; ifile++ ) {

/* Start a new NDF context. */
      ndfBegin();

/* Create the output NDF by propagating everything from the input, except
   for quality and variance. */
      ndgNdfas( igrp2, ifile, "READ", &indfin, status );

      ndfMsg( "FILE", indfin );
      msgSeti( "THISFILE", ifile );
      msgSeti( "NUMFILES", size );
      msgOutif( MSG__NORM, " ", "Simulating ^THISFILE/^NUMFILES ^FILE",
                status );

      ndgNdfpr( indfin, "DATA,HISTORY,LABEL,TITLE,WCS,UNITS,EXTENSION(*)",
                ogrp, ifile, &indfout, status );
      ndfAnnul( &indfin, status );
      ndfAnnul( &indfout, status );

/* We now re-open the output NDF and then modify its data values. */
      smf_open_file( wf, ogrp, ifile, "UPDATE", 0, &odata, status );

/* Issue a suitable message and abort if anything went wrong. */
      if( *status != SAI__OK ) {
         errRep( FUNC_NAME, "Could not open input template file.", status );
         break;

      } else {
         if( odata->file == NULL ) {
            *status = SAI__ERROR;
            errRep( FUNC_NAME, "No smfFile associated with smfData.",
                    status );
            break;

         } else if( odata->hdr == NULL ) {
            *status = SAI__ERROR;
            errRep( FUNC_NAME, "No smfHead associated with smfData.",
                    status );
            break;
         }
      }

/* Check the reference time series contains double precision values. */
      smf_dtype_check_fatal( odata, NULL, SMF__DOUBLE, status );

/* Get the total number of data elements, and the number of time slices. */
      smf_get_dims( odata, NULL, NULL, NULL, &ntslice, &ndata, NULL,
                    NULL, status );

/* Get the subarray name */
      smf_fits_getS( odata->hdr, "SUBARRAY", subarray, sizeof(subarray),
                     status );

/* If we are using the Johnstone/Kennedy IP model, open and map the
   relevant parameter NDFs within the IPDATA container file. */
      if( iploc ) {
         datFind( iploc, subarray, &cloc, status );

         ndfFind( cloc, "C0", &indfc0, status );
         ndfDim( indfc0, 2, dims, &ndim, status );
         if( dims[ 0 ] != 32 || dims[ 1 ] != 40 ) {
            *status = SAI__ERROR;
            ndfMsg( "N", indfc0 );
            errRep( " ", "Instrumental polarisation file ^N has bad "
                    "dimensions - should be 32x40.", status );
         } else {
            ndfMap( indfc0, "DATA", "_DOUBLE", "READ", (void **) &c0_data,
                    &nel, status );
         }

         ndfFind( cloc, "P0", &indfp0, status );
         ndfDim( indfp0, 2, dims, &ndim, status );
         if( dims[ 0 ] != 32 || dims[ 1 ] != 40 ) {
            *status = SAI__ERROR;
            ndfMsg( "N", indfp0 );
            errRep( " ", "Instrumental polarisation file ^N has bad "
                    "dimensions - should be 32x40.", status );
         } else {
            ndfMap( indfp0, "DATA", "_DOUBLE", "READ", (void **) &p0_data,
                    &nel, status );
         }

         ndfFind( cloc, "P1", &indfp1, status );
         ndfDim( indfp1, 2, dims, &ndim, status );
         if( dims[ 0 ] != 32 || dims[ 1 ] != 40 ) {
            *status = SAI__ERROR;
            ndfMsg( "N", indfp1 );
            errRep( " ", "Instrumental polarisation file ^N has bad "
                    "dimensions - should be 32x40.", status );
         } else {
            ndfMap( indfp1, "DATA", "_DOUBLE", "READ", (void **) &p1_data,
                    &nel, status );
         }

         ndfFind( cloc, "ANGC", &indfangc, status );
         ndfDim( indfangc, 2, dims, &ndim, status );
         if( dims[ 0 ] != 32 || dims[ 1 ] != 40 ) {
            *status = SAI__ERROR;
            ndfMsg( "N", indfangc );
            errRep( " ", "Instrumental polarisation file ^N has bad "
                    "dimensions - should be 32x40.", status );
         } else {
            ndfMap( indfangc, "DATA", "_DOUBLE", "READ", (void **) &angc_data,
                    &nel, status );
         }
      }

/* Open any COM file. */
      if( ncom ) {
         ndgNdfas( igrpc, ifile, "READ", &indfc, status );
         ndfDim( indfc, 3, cdims, &ndimc, status );

/* Check its dimensions. */
         if( *status == SAI__OK ) {
            if( ndimc == 1 ) {
               if( cdims[ 0 ] < (int) ntslice ) {
                  *status = SAI__ERROR;
                  ndfMsg( "C", indfc );
                  ndfMsg( "R", indfin );
                  msgSeti( "N", cdims[ 0 ] );
                  msgSeti( "M", ntslice );
                  errRep( " ", "Supplied COM file (^C) has ^N time-slices, but "
                          "the reference NDF (^R) has ^M time-slices.", status );
               } else {
                  ndfBound( indfc, 3, lbndc, ubndc, &ndimc, status );
                  ubndc[ 0 ] = lbndc[ 0 ] + ntslice - 1;
                  ndfSect( indfc, 1, lbndc, ubndc, &indfcs, status );
               }
            } else if( ndimc == 3 ) {
               if( cdims[ 0 ] != 1 || cdims[ 1 ] != 1 ) {
                  *status = SAI__ERROR;
                  ndfMsg( "C", indfc );
                  errRep( " ", "Supplied 3D COM file (^C) has bad "
                          "dimensions for axis 1 and/or 2 (should "
                          "both be 1 pixel long).", status );
               } else if( cdims[ 2 ] < (int) ntslice ) {
                  *status = SAI__ERROR;
                  ndfMsg( "C", indfc );
                  ndfMsg( "R", indfin );
                  msgSeti( "N", cdims[ 2 ] );
                  msgSeti( "M", ntslice );
                  errRep( " ", "Supplied COM file (^C) has ^N time-slices, but "
                          "the reference NDF (^R) has ^M time-slices.", status );
               } else {
                  ndfBound( indfc, 3, lbndc, ubndc, &ndimc, status );
                  ubndc[ 2 ] = lbndc[ 2 ] + ntslice - 1;
                  ndfSect( indfc, 3, lbndc, ubndc, &indfcs, status );
               }
            } else {
               *status = SAI__ERROR;
               ndfMsg( "C", indfc );
               msgSeti( "N", ndimc );
               errRep( " ", "Supplied COM file (^C) has ^N dimensions - "
                       "must be 3.", status );
            }
         }

         ndfMap( indfcs, "DATA", "_DOUBLE", "READ", (void **) &inc_data,
                 &nelc, status );

      } else {
         indfcs = NDF__NOID;
         inc_data = NULL;
      }

/* Open any GAI files. */
      if( ngai ) {
         ndgNdfas( igrpg, ifile, "READ", &indfg, status );
         ndfDim( indfg, 3, gdims, &ndimg, status );

/* Check its dimensions, and map it if OK. */
         if( *status == SAI__OK ) {
            if( ndimg != 2 ) {
               *status = SAI__ERROR;
               ndfMsg( "C", indfg );
               msgSeti( "N", ndimg );
               errRep( " ", "Supplied GAI file (^C) has ^N dimensions - "
                       "must be 2.", status );
            } else if( gdims[ 0 ] != 32 || gdims[ 1 ] != 40 ) {
               *status = SAI__ERROR;
               ndfMsg( "C", indfg );
               errRep( " ", "Supplied GAI file (^C) has has bad "
                       "dimensions - should be 32x40.", status );
            }
         }
         ndfMap( indfg, "DATA", "_DOUBLE", "READ", (void **) &gai_data,
                 &nelg, status );

      } else {
         indfg = NDF__NOID;
         gai_data = NULL;
      }

/* Fill the output with bad values. */
      if( *status == SAI__OK ) {
         pd = odata->pntr[ 0 ];
         for( iel = 0; iel < ndata; iel++ ) *(pd++) = VAL__BADD;
      }

/* Resample the sky map data into the output time series. */
      smf_resampmap( wf, odata, abskyfrm, skymap, moving, slbnd, subnd,
                     interp, params, sigma, in_data, odata->pntr[ 0 ],
                     NULL, &ngood, status );

/* Add on any COM data. */
      smf_addcom( wf, odata, inc_data, status );

/* Issue a wrning if there is no good data in the output cube. */
      if( ngood == 0 ) msgOutif( MSG__NORM, " ", "   Output contains no "
                                 "good data values.", status );

/* If Q and U maps have been given, allocate room to hold resampled Q and
   U values, and fill them with bad values. */
      if( inq_data && inu_data ) {
         pq = outq_data = astMalloc( ndata*sizeof( *outq_data ) );
         pu = outu_data = astMalloc( ndata*sizeof( *outu_data ) );
         if( *status == SAI__OK ) {
            for( iel = 0; iel < ndata; iel++ ) {
               *(pu++) = VAL__BADD;
               *(pq++) = VAL__BADD;
            }
         }

/* Determine the harmonic to use. */
         parGet0i( "HARMONIC", &harmonic, status );

/* If producing the normal 8 Hz harmonic, get the amplitude and phase of a
   other signals to add onto the 8 Hz signal. */
         if( harmonic == 4 ) {
            parGet0d( "AMP2", &amp2, status );
            parGet0d( "PHASE2", &phase2, status );
            parGet0d( "AMP4", &amp4, status );
            parGet0d( "PHASE4", &phase4, status );
            parGet0d( "AMP16", &amp16, status );
            parGet0d( "PHASE16", &phase16, status );
         } else {
            amp2 = 0.0;
            phase2 = 0.0;
            amp4 = 0.0;
            phase4 = 0.0;
            amp16 = 0.0;
            phase16 = 0.0;
         }

/* Allocate room for an array to hold the angle from the Y pixel axis
   in the sky map to the focal plane Y axis, in radians, at each time
   slice. Positive rotation is in the same sense as rotation from
   focal plane X to focal plane Y. */
         ang_data = astMalloc( ntslice*sizeof( *ang_data ) );

/* Resample them both into 3D time series. These Q/U values arw with
  respect to the sky image Y axis. */
         smf_resampmap( wf, odata, abskyfrm, skymap, moving, slbnd, subnd,
                        interp, params, sigma, inq_data, outq_data,
                        ang_data, &ngood, status );
         smf_resampmap( wf, odata, abskyfrm, skymap, moving, slbnd, subnd,
                        interp, params, sigma, inu_data, outu_data,
                        NULL, &ngood, status );

/* Combine these time series with the main output time series so that the
   main output is analysed intensity. */
         smf_uncalc_iqu( wf, odata, odata->pntr[ 0 ], outq_data, outu_data,
                         ang_data, pasign, AST__DD2R*paoff, AST__DD2R*angrot,
                         amp2, AST__DD2R*phase2, amp4, AST__DD2R*phase4,
                         amp16, AST__DD2R*phase16, qinst_data, uinst_data,
                         c0_data, p0_data, p1_data, angc_data, harmonic,
                         status );

/* Release work space. */
         outq_data = astFree( outq_data );
         outu_data = astFree( outu_data );
         ang_data = astFree( ang_data );
      }

/* Factor in any GAI data. */
      smf_addgai( wf, odata, gai_data, status );

/* Close the output time series file. */
      smf_close_file( wf, &odata, status );

/* Close the IP data container for the current subarray, if it is open. */
      if( cloc ) datAnnul( &cloc, status );

/* End the NDF context. */
      ndfEnd( status );
   }

/* Close any input data file that is still open due to an early exit from
   the above loop. */
   if( odata != NULL ) {
      smf_close_file( wf, &odata, status );
      odata = NULL;
   }

/* Free remaining resources. */
   if( igrp1 != NULL) grpDelet( &igrp1, status);
   if( igrp2 != NULL) grpDelet( &igrp2, status);
   if( igrpq != NULL) grpDelet( &igrpq, status);
   if( igrpu != NULL) grpDelet( &igrpu, status);
   if( igrpc != NULL) grpDelet( &igrpc, status);
   if( igrpg != NULL) grpDelet( &igrpg, status);
   if( ogrp != NULL) grpDelet( &ogrp, status);
   if( iploc ) datAnnul( &iploc, status );

/* End the NDF context. */
   ndfEnd( status );

/* End the tile's AST context. */
   astEnd;

/* Issue a status indication.*/
   if( *status == SAI__OK ) {
      msgOutif(MSG__VERB," ",TASK_NAME " succeeded, time series written.", status);
   } else {
      msgOutif(MSG__VERB," ",TASK_NAME " failed.", status);
   }
}
예제 #11
0
void clumpinfo( int *status ) {
    /*
    *+
    *  Name:
    *     CLUMPINFO

    *  Purpose:
    *     Obtain information about one or more previously identified clumps.

    *  Language:
    *     C

    *  Type of Module:
    *     ADAM A-task

    *  Description:
    *     This application returns various items of information about a
    *     single clump, or a collection of clumps, previously identified
    *     using FINDCLUMPS or EXTRACTCLUMPS.

    *  Usage:
    *     clumpinfo ndf clumps quiet

    *  ADAM Parameters:
    *     CLUMPS = LITERAL (Read)
    *        Specifies the indices of the clumps to be included in the
    *        returned information. It can take any of the following values:
    *
    *        - "ALL" or "*" --  All clumps.
    *
    *        - "xx,yy,zz" -- A list of clump indices.
    *
    *        - "xx:yy" --  Clump indices between xx and yy inclusively.  When
    *        xx is omitted the range begins from one; when yy is omitted the
    *        range ends with the final clump index.
    *
    *        - Any reasonable combination of above values separated by
    *        commas.
    *     FLBND( ) = _DOUBLE (Write)
    *          The lower bounds of the bounding box enclosing the selected
    *          clumps in the current WCS Frame of the input NDF. Celestial axis
    *          values are always in units of radians, but spectral axis units
    *          will be in the spectral units used by the current WCS Frame.
    *     FUBND( ) = _DOUBLE (Write)
    *          The upper bounds of the bounding box enclosing the selected
    *          clumps. See parameter FLBND for more details.
    *     LBOUND( ) = _INTEGER (Write)
    *          The lower pixel bounds of bounding box enclosing the selected
    *          clumps.
    *     NCLUMPS = _INTEGER (Write)
    *        The total number of clumps descrriptions stored within the supplied
    *        NDF.
    *     NDF = NDF (Read)
    *        The NDF defining the previously identified clumps. This
    *        should contain a CUPID extension describing all the identified
    *        clumps, in the format produced by FINDCLUMPS or EXTRACTCLUMPS.
    *     QUIET = _LOGICAL (Read)
    *        If TRUE, then no information is written out to the screen,
    *        although the output parameters are still assigned values. [FALSE]
    *     UBOUND( ) = _INTEGER (Write)
    *          The upper pixel bounds of bounding box enclosing the selected
    *          clumps.

    *  Notes:
    *     - It is hoped to extend the range of information reported by this
    *     application as new requirements arise.

    *  Synopsis:
    *     void clumpinfo( int *status );

    *  Copyright:
    *     Copyright (C) 2007 Particle Physics & Astronomy Research Council.
    *     All Rights Reserved.

    *  Licence:
    *     This program is free software; you can redistribute it and/or
    *     modify it under the terms of the GNU General Public License as
    *     published by the Free Software Foundation; either version 2 of
    *     the License, or (at your option) any later version.
    *
    *     This program is distributed in the hope that it will be
    *     useful, but WITHOUT ANY WARRANTY; without even the implied
    *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
    *     PURPOSE. See the GNU General Public License for more details.
    *
    *     You should have received a copy of the GNU General Public License
    *     along with this program; if not, write to the Free Software
    *     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
    *     02110-1301, USA

    *  Authors:
    *     DSB: David S. Berry
    *     {enter_new_authors_here}

    *  History:
    *     22-MAR-2007 (DSB):
    *        Original version.
    *     {enter_further_changes_here}

    *  Bugs:
    *     {note_any_bugs_here}

    *-
    */

    /* Local Variables: */
    AstFrame *cfrm;      /* Pointer to current WCS Frame */
    AstMapping *cmap;    /* Pointer to PIXEL->current Frame Mapping */
    CupidClumpInfo info; /* Structure holding returned information */
    Grp *grp = NULL;     /* GRP group holding input NDF name */
    HDSLoc *aloc = NULL; /* Locator for CLUMPS array in CUPID extension */
    HDSLoc *cloc = NULL; /* Locator for a single CLUMP structure */
    HDSLoc *xloc = NULL; /* Locator for CUPID extension */
    char *p;             /* Pointer into tmpstr string */
    char tmpstr[ 100 ];  /* Buffer for temporary strings */
    const char *dom;     /* Pointer to axis Domain name */
    double flbnd[ NDF__MXDIM ]; /* Lower bounds of WCS bounding box */
    double fubnd[ NDF__MXDIM ]; /* Upper bounds of WCS bounding box */
    double plbnd[ NDF__MXDIM ]; /* Lower bounds of PIXEL bounding box */
    double pubnd[ NDF__MXDIM ]; /* Upper bounds of PIXEL bounding box */
    int *clump_flags = NULL;  /* Flags indicating if each clump is to be used */
    int *clump_indices = NULL;/* List of indices of clumps to be used */
    int i;               /* Loop count */
    int iclump;          /* One-based clump index */
    int indf;            /* NDF identifier for input NDF */
    int ipix;            /* Index of PIXEL Frame */
    size_t nclumps;      /* No. of clump descriptions within the supplied NDF */
    int nuse;            /* Number of clumps to be used */
    int primary;         /* Value for locator primary flag */
    int quiet;           /* Supress screen output? */
    size_t size;         /* Number of values in group "*grp" */
    int there;           /* Does the enquired object exist? */

    /* Abort if an error has already occurred. */
    if( *status != SAI__OK ) return;

    /* Begin an AST context */
    astBegin;

    /* Start an NDF context */
    ndfBegin();



    /* Obtain the input NDF and get a locator for the array of clump
       descriptions within it.
       -----------------------------------------------------------------  */

    /* Get an identifier for the input NDF. We use NDG (via kpg1_Rgndf)
       instead of calling ndfAssoc directly since NDF/HDS has problems with
       file names containing spaces, which NDG does not have. */
    kpg1Rgndf( "NDF", 1, 1, "", &grp, &size, status );
    ndgNdfas( grp, 1, "READ", &indf, status );
    grpDelet( &grp, status );

    /* Check the NDF has a suitable CUPID extension containing an array of
       clump cut-outs. Get an HDS locator for the array. */
    ndfXstat( indf, "CUPID", &there, status );
    if( !there ) {
        if( *status == SAI__OK ) {
            *status = SAI__ERROR;
            ndfMsg( "NDF", indf );
            errRep( "", "The NDF \"^NDF\" does not contain a CUPID extension "
                    "such as created by FINDCLUMPS or EXTRACTCLUMPS.", status );
        }

    } else {
        ndfXloc( indf, "CUPID", "READ", &xloc, status );
        datThere( xloc, "CLUMPS", &there, status );
        if( !there ) {
            if( *status == SAI__OK ) {
                *status = SAI__ERROR;
                ndfMsg( "NDF", indf );
                errRep( "", "The CUPID extension within NDF \"^NDF\" does not "
                        "contain an array of clumps such as created by "
                        "FINDCLUMPS or EXTRACTCLUMPS.", status );
            }

        } else {
            datFind( xloc, "CLUMPS", &aloc, status );
            primary = 1;
            datPrmry( 1, &aloc, &primary, status );

        }
        datAnnul( &xloc, status );
    }

    /* Abort if we have no clumps array locator, or if an error occurred. */
    if( !aloc || *status != SAI__OK ) goto L999;



    /* Calculate the required clump information, and store it in the "info"
       structure.
       -----------------------------------------------------------------  */

    /* Indicate that the structure holding the returned information has not
       yet been initialised. */
    info.init = 0;

    /* Get the WCS FrameSet from the input NDF, and store a pointer to it in
       the "info" structure. */
    kpg1Gtwcs( indf, &(info.iwcs), status );

    /* Get the number of clumps defined within the input NDF. */
    datSize( aloc, &nclumps, status );

    /* Get the list of clump indices to iclude in the returned information. */
    clump_flags = astMalloc( sizeof( int )*nclumps );
    clump_indices = astMalloc( sizeof( int )*nclumps );
    kpg1Gilst( 1, (int) nclumps, (int) nclumps, "CLUMPS", clump_flags, clump_indices,
               &nuse, status );

    /* Loop round all clumps that are to be used. */
    for( i = 0; i < nuse && *status == SAI__OK; i++ ) {
        iclump = clump_indices[ i ];

        /* Get a locator for this clump. */
        datCell( aloc, 1, &iclump, &cloc, status );

        /* Update the returned information to include this clump. */
        cupidClumpInfo1( cloc, &info, status );

        /* Annul the clump structure locator. */
        datAnnul( &cloc, status );

    }



    /* Write out the information to the screen and to appropriate output
       parameters.
       -----------------------------------------------------------------  */

    /* See if screen output is required. */
    parGet0l( "QUIET", &quiet, status );
    if( !quiet ) msgBlank( status );

    /* The number of clumps defined within the input NDF... */
    parPut0i( "NCLUMPS", (int) nclumps, status );
    if( ! quiet ) {
        msgSeti( "NCLUMPS", (int) nclumps );
        msgOut( "", "   Total no. of clumps: ^NCLUMPS", status );
    }

    /* Pixel index bounding box... */
    parPut1i( "LBOUND", info.npix, info.lbnd, status );
    parPut1i( "UBOUND", info.npix, info.ubnd, status );

    if( !quiet ) {
        p = tmpstr + sprintf( tmpstr, "( " );
        for( i = 0; i < info.npix; i++) {
            p += sprintf( p, "%d:%d", info.lbnd[ i ], info.ubnd[ i ] );
            if( i < info.npix - 1 ) p += sprintf( p, ", " );
        }
        p += sprintf( p, " )" );

        msgSetc( "SECTION", tmpstr );
        msgOut( "", "   Pixel index bounding box: ^SECTION", status );
    }

    /* WCS bounding box (first convert the pixel index bounding box into WCS
       coords)... */
    cfrm = astGetFrame( info.iwcs, AST__CURRENT );

    kpg1Asffr( info.iwcs, "PIXEL", &ipix, status );
    cmap = astGetMapping( info.iwcs, ipix, AST__CURRENT );

    for( i = 0; i < info.npix; i++ ) {
        plbnd[ i ] = info.lbnd[ i ] - 1.0;
        pubnd[ i ] = info.ubnd[ i ];
    }

    for( i = 0; i < info.nwcs; i++ ) {
        astMapBox( cmap, plbnd, pubnd, 1, i + 1, flbnd + i, fubnd + i,
                   NULL, NULL);
    }

    astNorm( cfrm, flbnd );
    astNorm( cfrm, fubnd );

    parPut1d( "FLBND", info.nwcs,  flbnd, status );
    parPut1d( "FUBND", info.nwcs,  fubnd, status );

    if( !quiet ) {
        msgOut( "", "   WCS bounding box:", status );

        for( i = 0; i < info.nwcs; i++) {
            msgSetc( "L", astFormat( cfrm, i + 1, flbnd[ i ] ) );
            msgSetc( "U", astFormat( cfrm, i + 1, fubnd[ i ] ) );

            sprintf( tmpstr, "Domain(%d)", i + 1 );
            dom = astGetC( cfrm, tmpstr );
            if( dom && strcmp( dom, "SKY" ) ) {
                sprintf( tmpstr, "Unit(%d)", i + 1 );
                msgSetc( "UNT", astGetC( cfrm, tmpstr ) );
            } else {
                msgSetc( "UNT", "" );
            }

            sprintf( tmpstr, "Label(%d)", i + 1 );
            msgSetc( "LAB", astGetC( cfrm, tmpstr ) );

            msgOut( "", "        ^LAB: ^L -> ^U ^UNT", status );
        }
    }

    if( !quiet ) msgBlank( status );



    /* Tidy up.
       --------      */
L999:
    ;

    /* Free resources. */
    clump_flags = astFree( clump_flags );
    clump_indices = astFree( clump_indices );
    if( aloc ) datAnnul( &aloc, status );

    /* End the NDF context */
    ndfEnd( status );

    /* End the AST context */
    astEnd;

    /* If an error has occurred, issue another error report identifying the
       program which has failed (i.e. this one). */
    if( *status != SAI__OK ) {
        errRep( "CLUMPINFO_ERR", "CLUMPINFO: Failed to obtain information "
                "about one or more previously identified clumps.", status );
    }

}
예제 #12
0
파일: hdsTest.c 프로젝트: andrecut/starlink
int main (void) {

    /*  Local Variables: */
    const char path[] = "hds_ctest";
    int status = DAT__OK;
    hdsdim dim[] = { 10, 20 };
    hdsdim dimd[1];
    const char * chararr[] = { "TEST1", "TEST2", "Longish String" };
    char *retchararr[4];
    char buffer[1024];  /* plenty large enough */
    double darr[] = { 4.5, 2.5 };
    double retdarr[2];
    void *mapv;    /* Mapped void* */
    double *mapd;  /* Mapped _DOUBLE */
    float  *mapf;  /* Mapped _REAL */
    int *mapi;     /* Mapped _INTEGER */
    int64_t *mapi64; /* Mapped _INT64 */
    HDSLoc * loc1 = NULL;
    HDSLoc * loc2 = NULL;
    HDSLoc * loc3 = NULL;
    size_t actval;
    size_t nel;
    size_t nelt;
    size_t nbytes;
    size_t i;
    int n;
    double sumd;
    int sumi;
    int64_t sumi64;
    int64_t test64;
    int64_t testin64;
    const int64_t VAL__BADK = (-9223372036854775807 - 1);

    emsBegin(&status);

    /* Force 64-bit mode */
    hdsTune( "64BIT", 1, &status );

    /* Create a new container file */
    hdsNew( path, "HDS_TEST", "NDF", 0, dim, &loc1, &status );

    /* Some components */
    datNew( loc1, "DATA_ARRAY", "_INTEGER", 2, dim, &status );
    datNew1C( loc1, "ONEDCHAR", 14, 3, &status );
    datNew1D( loc1, "ONEDD", 2, &status );
    datNew0K( loc1, "TESTI64", &status );
    datNew0K( loc1, "TESTBADI64", &status );

    /* Populate */
    testin64 = 9223372036854775800;
    datFind( loc1, "TESTI64", &loc2, &status );
    datPut0K( loc2, testin64, &status );
    datGet0K( loc2, &test64, &status );
    datAnnul( &loc2, &status );
    if (status == DAT__OK) {
        if ( test64 != testin64 ) {
            status = DAT__FATAL;
            emsRepf( "TESTI64", "Test _INT64 value %" PRIi64 " did not match expected %"PRIi64,
                     &status, test64, testin64 );
        }
    }

    datFind( loc1, "TESTBADI64", &loc2, &status );
    datPut0K( loc2, VAL__BADK, &status );
    datGet0K( loc2, &test64, &status );
    datAnnul( &loc2, &status );
    if (status == DAT__OK) {
        if ( test64 != VAL__BADK ) {
            status = DAT__FATAL;
            emsRepf( "TESTBADI64", "Test _INT64 value %" PRIi64 " did not match expected VAL__BADK",
                     &status, test64 );
        }
    }

    datFind( loc1, "ONEDCHAR", &loc2, &status );
    datPutVC( loc2, 3, chararr, &status );

    /* Check contents */
    datGetVC(loc2, 3, 1024, buffer, retchararr, &actval, &status);
    if (status == DAT__OK) {
        if (actval == 3) {
            for (i = 0; i < 3; i++ ) {
                if (strncmp( chararr[i], retchararr[i], strlen(chararr[i]) ) ) {
                    status = DAT__DIMIN;
                    emsSetc( "IN", chararr[i]);
                    emsSetc( "OUT", retchararr[i] );
                    emsRep( "GET1C","Values from Get1C differ (^IN != ^OUT)", &status);
                    break;
                }
            }
        } else {
            status = DAT__DIMIN;
            emsRep( "GET1C","Did not get back as many strings as put in", &status);
        }
    }

    datAnnul( &loc2, &status );

    datFind( loc1, "ONEDD", &loc2, &status );
    datPutVD( loc2, 2, darr, &status );

    /* Check contents */
    datGetVD( loc2, 2, retdarr, &actval, &status);
    if (status == DAT__OK) {
        if (actval == 2) {
            for (i = 0; i < 2; i++ ) {
                if (darr[i] != retdarr[i]) {
                    status = DAT__DIMIN;
                    emsRep( "GETVD","Values from getVD differ", &status);
                    break;
                }
            }
        } else {
            status = DAT__DIMIN;
            emsRep( "GETVD","Did not get back as many values as put in", &status);
        }
    }

    /* Try mapping - _DOUBLE */
    dimd[0] = 2;
    datMapD(loc2, "READ", 1, dimd, &mapd, &status);
    if (status == DAT__OK) {
        for (i = 0; i < 2; i++ ) {
            if (darr[i] != mapd[i]) {
                status = DAT__DIMIN;
                emsRep( "MAPD","Values from MapD differ", &status);
                break;
            }
        }
    }
    datUnmap(loc2, &status);

    /* Try mapping - _FLOAT */
    datMapR(loc2, "READ", 1, dimd, &mapf, &status);
    if (status == DAT__OK) {
        for (i = 0; i < 2; i++ ) {
            if ( (float)darr[i] != mapf[i]) {
                status = DAT__DIMIN;
                emsRep( "MAPR","Values from MapR differ", &status);
                break;
            }
        }
    }
    datUnmap(loc2, &status);

    /* Annul */
    datAnnul( &loc2, &status );

    /* Find and map DATA_ARRAY */
    datFind( loc1, "DATA_ARRAY", &loc2, &status );
    datMapV( loc2, "_REAL", "WRITE", &mapv, &nel, &status );
    mapf = mapv;
    if (status == DAT__OK) {
        nelt = dim[0] * dim[1];
        if ( nelt != nel) {
            status = DAT__FATAL;
            emsSeti( "NEL", (int)nel );
            emsSeti( "NORI", (int)nelt );
            emsRep( "SIZE","Number of elements originally (^NORI) not the same as now (^NEL)", &status);
        }
    }
    sumd = 0.0;
    for (i = 1; i <= nel; i++) {
        mapf[i-1] = (float)i;
        sumd += (double)i;
    }
    datUnmap( loc2, &status );
    datAnnul( &loc2, &status );
    hdsClose( &loc1, &status );

    /* Re-open */
    hdsOpen( path, "UPDATE", &loc1, &status );

    /* Look for the data array and map it */
    datFind( loc1, "DATA_ARRAY", &loc2, &status );
    datVec( loc2, &loc3, &status );
    datSize( loc3, &nel, &status);
    if (status == DAT__OK) {
        nelt = dim[0] * dim[1];
        if ( nelt != nel) {
            status = DAT__FATAL;
            emsSeti( "NEL", (int)nel );
            emsSeti( "NORI", (int)nelt );
            emsRep( "SIZE","Number of elements before (^NORI) not the same as now (^NEL)", &status);
        }
    }

    datPrec( loc3, &nbytes, &status );
    if (status == DAT__OK) {
        if ( nbytes != 4) {
            status = DAT__FATAL;
            emsSeti( "NB", nbytes );
            emsRep( "PREC","Precision for _REAL not 4 bytes but ^NB", &status);
        }
    }

    /* Try hdsShow */
    hdsShow("LOCATORS", &status);
    hdsShow("FILES", &status);
    hdsInfoI(NULL, "LOCATORS", "!HDS_TEST.,YYY", &n, &status );
    hdsInfoI(NULL, "FILES", NULL, &n, &status );

    datAnnul( &loc3, &status );

    datMapV( loc2, "_INTEGER", "READ", &mapv, &nel, &status );
    mapi = mapv;
    if (status == DAT__OK) {
        nelt = dim[0] * dim[1];
        if ( nelt != nel) {
            status = DAT__FATAL;
            emsSeti( "NEL", (int)nel );
            emsSeti( "NORI", (int)nelt );
            emsRep( "SIZE","Number of elements originally (^NORI) not the same as now (^NEL)", &status);
        }
    }
    sumi = 0;
    for (i = 0; i < nel; i++) {
        sumi += mapi[i];
    }
    datUnmap( loc2, &status );

    if (status == DAT__OK) {
        if (sumi != (int)sumd) {
            status = DAT__FATAL;
            emsSeti( "I", sumi );
            emsSeti( "D", (int)sumd );
            emsRep("SUM","Sum was not correct. Got ^I rather than ^D", &status );
        }
    }

    /* _INT64 test */
    datMapV( loc2, "_INT64", "READ", &mapv, &nel, &status );
    mapi64 = mapv;
    if (status == DAT__OK) {
        nelt = dim[0] * dim[1];
        if ( nelt != nel) {
            status = DAT__FATAL;
            emsSeti( "NEL", (int)nel );
            emsSeti( "NORI", (int)nelt );
            emsRep( "SIZE","Number of elements originally (^NORI) not the same as now (^NEL)", &status);
        }
    }
    sumi64 = 0;
    for (i = 0; i < nel; i++) {
        sumi64 += mapi64[i];
    }
    datUnmap( loc2, &status );

    if (status == DAT__OK) {
        if (sumi64 != (int)sumd) {
            status = DAT__FATAL;
            emsSeti( "I", (int)sumi64 );
            emsSeti( "D", (int)sumd );
            emsRep("SUM","Sum was not correct. Got ^I rather than ^D", &status );
        }
    }


    /* Tidy up and close */
    hdsErase( &loc1, &status );

    if (status == DAT__OK) {
        printf("HDS C installation test succeeded\n");
        emsEnd(&status);
        return EXIT_SUCCESS;
    } else {
        printf("HDS C installation test failed\n");
        emsEnd(&status);
        return EXIT_FAILURE;
    }


}