示例#1
0
AstKeyMap *smf_subinst_keymap( smf_subinst_t subinst, const smfData * indata,
                               const Grp * igrp, size_t idx, int * status ) {

  const smfHead * hdr = NULL;        /* Header of file to be examined */
  size_t i;
  smfData * sub_data = NULL;         /* File to be examined */
  AstKeyMap * sub_instruments;       /* Keymap to be filled */

  if (*status != SAI__OK) return NULL;

  if (subinst == SMF__SUBINST_NONE && !indata && !igrp) {
    *status = SAI__ERROR;
    errRep( "", "Must supply either a subinst, a smfData or a Grp"
            " (possible programming error)", status );
    return NULL;
  }

  /* Create new keymap */
  sub_instruments = astKeyMap( " " );

  /* prefill with the list of known sub-instruments. */
  for (i = 0; i < SMF__SUBINST_NSUBINST; i++ ) {
    const char * substr = smf_subinst_str( i, status );
    if (substr) astMapPut0I( sub_instruments, substr, 0, NULL );
  }

  /* If the current sub-instrument has not been supplied, get it from the file.
     Use indata in preference to the group */
  if( subinst == SMF__SUBINST_NONE ) {
    if (indata) {
      hdr = indata->hdr;
    } else {
      smf_open_file( igrp, idx, "READ", SMF__NOCREATE_DATA, &sub_data, status );
      if (sub_data) {
        hdr = sub_data->hdr;
      }
    }
    if (hdr) subinst = smf_calc_subinst( hdr, status );
  }

  /* flag this as being the relevant sub-instrument */
  if (subinst != SMF__SUBINST_NSUBINST ) {
    const char * substr = smf_subinst_str( subinst, status );
    if (substr) {
      astMapPut0I( sub_instruments, substr, 1, NULL );
    }
  }

  if (sub_data) smf_close_file( &sub_data, status );

  /* Free the keymap if we have bad status */
  if (*status != SAI__OK && sub_instruments) {
    sub_instruments = astAnnul( sub_instruments );
  }

  return sub_instruments;
}
示例#2
0
int *smf_jsatiles_data( Grp *igrp, size_t size, int *ntile, int *status ){

/* Local Variables */
   AstFrame *frm = NULL;
   AstFrameSet *fs;
   JCMTState *state;
   const char *trsys;
   const char *trsys_last;
   dim_t *hits = NULL;
   dim_t *ph;
   dim_t iframe;
   double *gx = NULL;
   double *gy = NULL;
   double *p1;
   double *p2;
   double *px;
   double *py;
   double *trac1 = NULL;
   double *trac2 = NULL;
   double fov;
   double point1[ 2 ];
   double point2[ 2 ];
   double search;
   int *tiles = NULL;
   int dim[ 2 ];
   int i;
   int ix;
   int iy;
   int lbnd[ 2 ];
   int ubnd[ 2 ];
   size_t ifile;
   smfData *data = NULL;
   smfHead *hdr = NULL;
   smfJSATiling skytiling;
   smf_inst_t inst = SMF__INST_NONE;
   smf_inst_t instrument;
   smf_subinst_t subinst;

/* Initialise */
   *ntile = 0;

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

/* Start an AST context so that all AST objects created in this function
   are annulled automatically. */
   astBegin;

/* Loop round all the input NDFs. */
   trsys_last = "";
   for( ifile = 1; ifile <= size && *status == SAI__OK; ifile++ ) {

/* Obtain information about the current input NDF. */
      smf_open_file( igrp, ifile, "READ", SMF__NOCREATE_DATA, &data,
                     status );

/* Get a pointer to the header. */
      hdr = data->hdr;

/* Get the instrument. */
      if( hdr->instrument == INST__SCUBA2 ) {
         subinst = smf_calc_subinst( hdr, status );
         if( subinst == SMF__SUBINST_850 ) {
            inst = SMF__INST_SCUBA_2_850;
         } else {
            inst = SMF__INST_SCUBA_2_450;
         }

      } else if( hdr->instrument == INST__ACSIS ) {
         inst = SMF__INST_HARP;

      } else if( *status == SAI__OK ) {
         *status = SAI__ERROR;
         smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
         errRep( "", "No tiles are yet defined for the instrument that "
                 "created ^FILE.", status );
      }

/* If this is the first file, it defines the instrument in use. */
      if( ifile == 1 ) {
         instrument = inst;

/* Get the parameters that define the layout of sky tiles for the
   instrument. */
         smf_jsatiling( instrument, &skytiling, status );

/* Create a FrameSet describing the whole sky in which each pixel
   corresponds to a single tile. The current Frame is ICRS (RA,Dec) and
   the base Frame is grid coords in which each grid pixel corresponds to
   a single tile. */
         smf_jsatile( 0, &skytiling, 0, NULL, &fs, NULL, lbnd, ubnd, status );

/* Allocate an image with one pixel for each tile, and fill it with
   zeros. */
         dim[ 0 ] = ubnd[ 0 ] - lbnd[ 0 ] + 1;
         dim[ 1 ] = ubnd[ 1 ] - lbnd[ 1 ] + 1;
         hits = astCalloc( dim[0]*dim[1], sizeof( *hits ) );

/* Get the radius of the field of view in radians. */
         fov = 0.5*(skytiling.fov*AST__DD2R)/3600.0;

/* If this is not the first file, report an error if the instrument has
   changed... */
      } else if( instrument != inst && *status == SAI__OK ) {
         smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
         errRep( "", "The file ^FILE was created by a different instrument "
                 "to the previous files.", status );
      }

/* Re-map the current Frame of the hits map WCS FrameSet to be the tracking
   system used by the current file (if it has changed). */
      trsys = sc2ast_convert_system( (hdr->allState)[0].tcs_tr_sys,
                                      status );
      if( *status == SAI__OK && strcmp( trsys, trsys_last ) ) {
         astSetC( fs, "System", trsys );
         trsys_last = trsys;
         frm = astGetFrame( fs, AST__CURRENT );
      }

/* Get the radius of the search circle. */
      search = fov + sqrt( hdr->instap[ 0 ]*hdr->instap[ 0 ] +
                           hdr->instap[ 1 ]*hdr->instap[ 1 ] );

/* Ensure our work arrays are big enough to hold the current file. */
      trac1 = astGrow( trac1, 4*hdr->nframes, sizeof( *trac1 ) );
      trac2 = astGrow( trac2, 4*hdr->nframes, sizeof( *trac2 ) );
      gx = astGrow( gx, 4*hdr->nframes, sizeof( *gx ) );
      gy = astGrow( gy, 4*hdr->nframes, sizeof( *gy ) );

/* Check pointers can be used safely. */
      if( *status == SAI__OK ) {

/* Loop round all time slices, getting the tracking coords at the corners
   of a box that enclose the field of view. */
         p1 = trac1;
         p2 = trac2;
         state = hdr->allState;
         for( iframe = 0; iframe < hdr->nframes; iframe++,state++ ) {
            point1[ 0 ] = state->tcs_tr_ac1;
            point1[ 1 ] = state->tcs_tr_ac2;
            for( i = 0; i < 4; i++ ) {
               astOffset2( frm, point1, i*AST__DPIBY2, search, point2 );
               *(p1++) = point2[ 0 ];
               *(p2++) = point2[ 1 ];
            }
         }

/* Convert them to grid coords in the hits map. */
         astTran2( fs, 4*hdr->nframes, trac1, trac2, 0, gx, gy );

/* Loop round them all again. Update the hits map to indicate how many
   points fall in each tile. */
         px = gx;
         py = gy;
         for( iframe = 0; iframe < 4*hdr->nframes; iframe++,px++,py++ ) {
            ix = (int)( *px + 0.5 ) - 1;
            iy = (int)( *py + 0.5 ) - 1;
            hits[ ix + iy*dim[ 0 ] ]++;
         }
      }

/* Close the current input data file. */
      smf_close_file( &data, status);
      data = NULL;
   }

/* Form a list of all the tiles that receive any data. */
   ph = hits;
   for( iy = 0; iy < dim[ 1 ]; iy++ ) {
      for( ix = 0; ix < dim[ 0 ]; ix++,ph++ ) {
         if( *ph > 0 ) {
            tiles = astGrow( tiles, ++(*ntile), sizeof( *tiles ) );
            if( *status == SAI__OK ) {
               tiles[ *ntile - 1 ] = smf_jsatilexy2i( ix, iy, &skytiling,
                                                      status );
            }
         }
      }
   }

/* Free resources. */
   hits = astFree( hits );
   trac1 = astFree( trac1 );
   trac2 = astFree( trac2 );
   gx = astFree( gx );
   gy = astFree( gy );

   if( *status != SAI__OK ) {
      tiles = astFree( tiles );
      *ntile = 0;
   }

   astEnd;

   return tiles;
}
示例#3
0
void smf_grp_related( const Grp *igrp, const size_t grpsize,
                      const int grouping, const int checksubinst,
                      double maxlen_s, double *srate_maxlen,
                      AstKeyMap *keymap, dim_t *maxconcatlen,
                      dim_t *maxfilelen, smfGroup **group,
                      Grp **basegrp, dim_t *pad, int *status ) {

  /* Local variables */
  size_t *chunk=NULL;         /* Array of flags for continuous chunks */
  dim_t * chunklen = NULL;    /* Length of continuous chunk */
  size_t currentindex = 0;    /* Counter */
  char cwave[10];             /* String containing wavelength */
  smfData *data = NULL;       /* Current smfData */
  double downsampscale=0;     /* Angular scale downsampling size */
  double downsampfreq=0;      /* Target downsampling frequency */
  AstKeyMap * grouped = NULL; /* Primary AstKeyMap for grouping */
  size_t i;                   /* Loop counter for index into Grp */
  int isFFT=0;                /* Set if data are 4d FFT */
  size_t j;                   /* Loop counter */
  int *keepchunk=NULL;        /* Flag for chunks that will be kept */
  dim_t maxconcat=0;          /* Longest continuous chunk length */
  dim_t maxflen=0;            /* Max file length in time steps */
  dim_t maxlen=0;             /* Maximum concat length in samples */
  int maxlen_scaled=0;        /* Set once maxlen has been scaled, if needed */
  dim_t maxpad=0;             /* Maximum padding neeed for any input file */
  size_t maxrelated = 0;      /* Keep track of max number of related items */
  size_t *new_chunk=NULL;     /* keeper chunks associated with subgroups */
  dim_t *new_tlen=NULL;       /* tlens for new_subgroup */
  size_t ngroups = 0;         /* Counter for subgroups to be stored */
  size_t nkeep = 0;           /* Number of chunks to keep */
  dim_t * piecelen = NULL;    /* Length of single file */
  smf_subinst_t refsubinst;   /* Subinst of first file */
  size_t **subgroups = NULL;  /* Array containing index arrays to parent Grp */
  smf_subinst_t subinst;      /* Subinst of current file */

  if ( *status != SAI__OK ) return;

  if( maxlen_s < 0 ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": maxlen_s cannot be < 0!", status );
    return;
  }

  /* Get downsampling parameters */

  if( keymap ) {
    smf_get_cleanpar( keymap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                      NULL, NULL, NULL, NULL, &downsampscale, &downsampfreq,
                      NULL, NULL, NULL, NULL, status );

    if( downsampscale && downsampfreq ) {
      *status = SAI__ERROR;
      errRep( "", FUNC_NAME ": both downsampscale and downsampfreq are set",
              status );
      return;
    }
  }

  /* Initialize refcwave */
  refsubinst = SMF__SUBINST_NONE;

  /* Loop over files in input Grp: remember Grps are indexed from 1 */
  grouped = astKeyMap( "SortBy=KeyUp" );
  for (i=1; i<=grpsize; i++) {
    char newkey[128];
    char dateobs[81];
    char subarray[10];
    size_t nrelated = 0;
    AstKeyMap * filemap = NULL;
    AstKeyMap * indexmap = NULL;

    /* First step: open file and harvest metadata */
    smf_open_file( NULL, igrp, i, "READ", SMF__NOCREATE_DATA, &data, status );
    if (*status != SAI__OK) break;

    if( i==1 ) {
      isFFT = smf_isfft( data, NULL, NULL, NULL, NULL, NULL, status );
    } else if( smf_isfft(data, NULL, NULL, NULL, NULL, NULL, status) != isFFT ){
      *status = SAI__ERROR;
      errRep( "", FUNC_NAME
              ": mixture of time-series and FFT data encountered!",
              status );
      break;
    }

    /* If maxlen has not been set, do it here */
    if( !maxlen && maxlen_s && data->hdr->steptime) {
      maxlen = (dim_t) (maxlen_s / data->hdr->steptime );
    }

    /* Return srate_maxlen if requested: may want to know this number
       even if maxlen_s is not set. Only calculate once, although it
       gets overwritten once later if down-sampling. */

    if( (i==1) && srate_maxlen && data->hdr->steptime ) {
      *srate_maxlen = 1. / (double) data->hdr->steptime;
    }


    /* If requested check to see if we are mixing wavelengths */
    if( checksubinst ) {
      if( refsubinst == SMF__SUBINST_NONE ) {
        refsubinst = smf_calc_subinst( data->hdr, status );
      }

      subinst = smf_calc_subinst( data->hdr, status );

      if( subinst != refsubinst ) {
        const char *refsubstr = smf_subinst_str( refsubinst, status );
        const char *substr = smf_subinst_str( subinst, status );

        *status = SAI__ERROR;
        smf_smfFile_msg( data->file, "FILE", 1, "<unknown>" );
        msgSetc( "REFSUB", refsubstr );
        msgSetc( "SUB", substr );
        errRep( "", FUNC_NAME
                ": ^FILE uses sub-instrument ^SUB which doesn't match "
                "reference ^REFSUB", status );
      }
    }

    /* Want to form a key that will be unique for a particular subscan
       We know that DATE-OBS will be set for SCUBA-2 files and be the same
       for a single set. Prefix by wavelength if we are grouping by wavelength.
     */
    newkey[0] = '\0';

    smf_find_subarray( data->hdr, subarray, sizeof(subarray), NULL, status );

    if( grouping == 1 ) {
      /* Group different wavelengths separately */
      smf_fits_getS( data->hdr, "WAVELEN", cwave, sizeof(cwave), status);
      one_strlcat( newkey, cwave, sizeof(newkey), status );
      one_strlcat( newkey, "_", sizeof(newkey), status );
    }

    if( grouping == 2 ) {
      /* Group different subarrays separately */
      one_strlcat( newkey, subarray, sizeof(newkey), status );
    }

    smf_fits_getS( data->hdr, "DATE-OBS", dateobs, sizeof(dateobs), status );
    one_strlcat( newkey, dateobs, sizeof(newkey), status );

    /* Include the dimentionality of the time series in the primary key
       so that we do not end up doing something confusing like relating
       a truncated file with a full length file */
    if (*status == SAI__OK) {
      dim_t dims[3];
      char formatted[32];
      smf_get_dims( data, &dims[0], &dims[1], NULL, &dims[2], NULL, NULL, NULL,
                    status );
      sprintf(formatted, "_%" DIM_T_FMT "_%" DIM_T_FMT "_%" DIM_T_FMT, dims[0], dims[1], dims[2]);
      one_strlcat( newkey, formatted, sizeof(newkey), status );
    }

    /* May want to read the dimensionality of the file outside of loop
       so that we can compare values when storing in the keymap */

    /* Now we want to create a keymap based on this key */
    if (!astMapGet0A( grouped, newkey, &filemap ) ) {
      int itemp = 0;
      double steptime = data->hdr->steptime;
      dim_t ntslice = 0;
      dim_t thispad;              /* Padding neeed for current input file */

      filemap = astKeyMap( " " );
      astMapPut0A( grouped, newkey, filemap, NULL );

      /* Fill up filemap with general information on this file */
      smf_find_seqcount( data->hdr, &itemp, status );
      astMapPut0I( filemap, "SEQCOUNT", itemp, NULL );

      smf_fits_getI( data->hdr, "NSUBSCAN", &itemp, status );
      astMapPut0I( filemap, "NSUBSCAN", itemp, NULL );

      /* Number of time slices */
      smf_get_dims( data, NULL, NULL, NULL, &ntslice, NULL, NULL, NULL,
                    status );

      /* Find length of down-sampled data, new steptime and maxlen */
      if( (downsampscale || downsampfreq) && data->hdr && (*status==SAI__OK) ) {
        double scalelen;

        if( downsampscale ) {
          if( data->hdr->scanvel != VAL__BADD ) {
             double oldscale = steptime * data->hdr->scanvel;
             scalelen = oldscale / downsampscale;
          } else if( *status == SAI__OK ) {
             *status = SAI__ERROR;
            scalelen = VAL__BADD;
            smf_smfFile_msg( data->file, "FILE", 1, "" );
            errRep( "", FUNC_NAME ": can't resample ^FILE because it has "
                    "unknown scan velocity", status );
          }
        } else {
          if( steptime ) {
            double oldsampfreq = 1./steptime;
            scalelen = downsampfreq / oldsampfreq;
          } else {
            *status = SAI__ERROR;
            scalelen = VAL__BADD;
            smf_smfFile_msg( data->file, "FILE", 1, "" );
            errRep( "", FUNC_NAME ": can't resample ^FILE because it has "
                    "unknown sample rate", status );
          }
        }

        /* only down-sample if it will be a reasonable factor */
        if( (*status==SAI__OK) && (scalelen <= SMF__DOWNSAMPLIMIT) ) {
          smf_smfFile_msg(data->file, "FILE", 1, "" );
          msgOutiff( MSG__VERB, "", FUNC_NAME
                     ": will down-sample file ^FILE from %5.1lf Hz to "
                     "%5.1lf Hz", status, (1./steptime), (scalelen/steptime) );

          ntslice = round(ntslice * scalelen);

          /* If maxlen has been requested, and we have not already worked
             out a scaled version (just uses the sample rates for the first
             file... should be close enough -- the alternative is a 2-pass
             system). */

          if( !maxlen_scaled ) {
            maxlen = round(maxlen*scalelen);
            maxlen_scaled = 1;
            msgOutiff( MSG__VERB, "", FUNC_NAME
                       ": requested maxlen %g seconds = %" DIM_T_FMT " down-sampled "
                       "time-slices", status, maxlen_s, maxlen );

            /* Return updated srate_maxlen for down-sampling if requested */
            if( srate_maxlen ) {
              *srate_maxlen = scalelen/steptime;
            }
          }
        }
      }

      /* Check that an individual file is too long (we assume related
         files are all the same) */
      if( maxlen && (ntslice > maxlen) && *status == SAI__OK) {
        *status = SAI__ERROR;
        msgSeti("NTSLICE",ntslice);
        msgSeti("MAXLEN",maxlen);
        smf_smfFile_msg( data->file, "FILE", 1, "" );
        errRep(FUNC_NAME,
               "Number of time steps in file ^FILE time exceeds maximum "
               "(^NTSLICE>^MAXLEN)", status);
      }

      /* Scaled values of ntslice and maximum length */
      astMapPut0I( filemap, "NTSLICE", ntslice, NULL );

      /* Work out the padding needed for this file including downsampling. */
      if( keymap ) {
        thispad = smf_get_padding( keymap, 0, data->hdr, VAL__BADD, status );
        if( thispad > maxpad ) maxpad = thispad;
      } else {
        thispad = 0;
      }
      astMapPut0I( filemap, "PADDING", thispad, NULL );

      /* Update maxflen */
      if( ntslice > maxflen ) {
        maxflen = ntslice;
      }

      /* Store OBSID or OBSIDSS depending on whether we are grouping by wavelength */
      if (grouping) {
        astMapPut0C( filemap, "OBSID", data->hdr->obsidss, NULL );
      } else {
        char obsid[81];
        smf_getobsidss( data->hdr->fitshdr, obsid, sizeof(obsid), NULL, 0, status );
        astMapPut0C( filemap, "OBSID", obsid, NULL );
      }
    }

    /* Store the file index in another keymap indexed by subarray */
    if ( !astMapGet0A( filemap, "GRPINDICES", &indexmap ) ) {
      indexmap = astKeyMap( "SortBy=KeyUp" );
      astMapPut0A( filemap, "GRPINDICES", indexmap, NULL );
    }

    astMapPut0I( indexmap, subarray, i, NULL );

    /* Need to track the largest number of related subarrays in a single slot */
    nrelated = astMapSize( indexmap );
    if (nrelated > maxrelated) maxrelated = nrelated;

    /* Free resources */
    filemap = astAnnul( filemap );
    indexmap = astAnnul( indexmap );
    smf_close_file( NULL, &data, status );
  }

  /* We now know how many groups there are */
  ngroups = astMapSize( grouped );

  /* Sort out chunking. The items are sorted by date and then by wavelength.
     We define a continuous chunk if it has the same OBSID, the same SEQCOUNT
     and NSUBSCAN increments by one from the previous entry.

     Also count number of related items in each slot.
   */
  if (*status == SAI__OK) {
    typedef struct { /* somewhere to store the values easily */
      char obsid[81];
      char related[81];  /* for concatenated subarrays */
      int nsubscan;
      int seqcount;
    } smfCompareSeq;
    smfCompareSeq current;
    smfCompareSeq previous;
    dim_t totlen = 0;
    size_t thischunk;

    /* Get the chunk flags and also store the size of the chunk */
    chunk = astCalloc( ngroups, sizeof(*chunk) );
    chunklen = astCalloc( ngroups, sizeof(*chunklen) );
    piecelen = astCalloc( ngroups, sizeof(*piecelen) );

    thischunk = 0;  /* The current chunk */
    for (i=0; i<ngroups; i++) {
      AstKeyMap * thismap = NULL;
      AstKeyMap * grpindices = NULL;
      const char * tempstr = NULL;
      int thistlen = 0;
      size_t nsubarrays = 0;

      /* Get the keymap entry for this slot */
      astMapGet0A( grouped, astMapKey(grouped, i), &thismap );

      /* Get info for length limits */
      astMapGet0I( thismap, "NTSLICE", &thistlen );
      piecelen[i] = thistlen;

      if (isFFT) {
        /* Never concatenate FFT data */
        thismap = astAnnul(thismap);
        chunk[i] = i;
        chunklen[i] = thistlen;
        continue;
      }

      /* Get indices information and retrieve the sub-instrument names
         in sort order to concatenate for comparison. We only store in
         a continuous chunk if we have the same subarrays for the whole
         chunk. */
      astMapGet0A( thismap, "GRPINDICES", &grpindices );
      nsubarrays = astMapSize( grpindices );
      (current.related)[0] = '\0';
      for (j = 0; j < nsubarrays; j++ ) {
        one_strlcat( current.related, astMapKey(grpindices, j), sizeof(current.related), status );
      }
      grpindices = astAnnul( grpindices );

      /* Fill in the current struct */
      astMapGet0I( thismap, "SEQCOUNT", &(current.seqcount) );
      astMapGet0I( thismap, "NSUBSCAN", &(current.nsubscan) );
      astMapGet0C( thismap, "OBSID", &tempstr );
      one_strlcpy( current.obsid, tempstr, sizeof(current.obsid), status );

      /* First chunk is special, else compare */
      if (i == 0) {
        totlen = thistlen;
      } else {
        if (  ( current.seqcount == previous.seqcount  ) &&
              ( current.nsubscan - previous.nsubscan == 1 ) &&
              ( strcmp( current.obsid, previous.obsid ) == 0 ) &&
              ( strcmp( current.related, previous.related ) == 0 ) ) {
          /* continuous - check length */
          totlen += thistlen;
          if ( maxlen && totlen > maxlen ) {
            thischunk++;
            totlen = thistlen; /* reset length */
          } else {
            /* Continuous */
          }
        } else {
          /* discontinuity */
          thischunk++;
          totlen = thistlen;  /* Update length of current chunk */
        }
      }

      chunklen[thischunk] = totlen;
      chunk[i] = thischunk;
      memcpy( &previous, &current, sizeof(current) );

      thismap = astAnnul( thismap );
    }
  }

  /* Decide if we are keeping a chunk by looking at the length. */
  maxconcat = 0;
  nkeep = 0;
  keepchunk = astMalloc( ngroups*sizeof(*keepchunk) );
  for (i=0; i<ngroups; i++) {
    size_t thischunk;

    thischunk = chunk[i];
    if ( chunklen[thischunk] < SMF__MINCHUNKSAMP ) {
      /* Warning message */
      msgSeti("LEN",chunklen[thischunk]);
      msgSeti("MIN",SMF__MINCHUNKSAMP);
      msgOut( " ", "SMF_GRP_RELATED: ignoring short chunk (^LEN<^MIN)",
              status);
      keepchunk[i] = 0;
    } else {
      keepchunk[i] = 1;
      if (maxconcat < chunklen[thischunk]) maxconcat = chunklen[thischunk];
      nkeep++;
    }

  }

  /* If no useful chunks generate an error */
  if( (*status==SAI__OK) && (!nkeep) ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": No useful chunks.", status );
    goto CLEANUP;
  }

  /* Allocate a subgroup array of the right size and fill it. They keymap
     is sorted by date (and wavelength) so we can always index into it by using
     indices from the subgroup. */
  subgroups = astCalloc( nkeep, sizeof(*subgroups) );
  new_chunk = astCalloc( nkeep, sizeof(*new_chunk) );
  new_tlen  = astCalloc( nkeep, sizeof(*new_tlen) );

  currentindex = 0;
  for (i=0;i<ngroups;i++) {
    AstKeyMap * thismap = NULL;
    AstKeyMap * grpindices = NULL;
    size_t nsubarrays = 0;
    size_t *indices = astCalloc( maxrelated, sizeof(*indices) );

    /* skip if we are dropping this chunk */
    if (!keepchunk[i]) continue;

    /* Get the keymap entry for this slot */
    astMapGet0A( grouped, astMapKey(grouped, i), &thismap );

    /* Get the indices keymap */
    astMapGet0A( thismap, "GRPINDICES", &grpindices );
    nsubarrays = astMapSize( grpindices );
    for (j=0; j<nsubarrays; j++) {
      int myindex;
      astMapGet0I( grpindices, astMapKey(grpindices, j), &myindex );
      indices[j] = myindex;
    }
    grpindices = astAnnul( grpindices );
    thismap = astAnnul( thismap );

    subgroups[currentindex] = indices;
    new_chunk[currentindex] = chunk[i];
    new_tlen[currentindex]  = piecelen[i];
    currentindex++;

  }

  /* Create the smfGroup */
  *group = smf_construct_smfGroup( igrp, subgroups, new_chunk, new_tlen,
                                   nkeep, maxrelated, 0, status );

  /* Return maxfilelen if requested */
  if( maxfilelen ) {
    *maxfilelen = maxflen;
  }

  /* Return maxconcatlen if requested */
  if( maxconcatlen ) {
    *maxconcatlen = maxconcat;
  }

  /* Create a base group for output files if required */
  /* Create a base group of filenames */
  if (*status == SAI__OK && basegrp ) {
    *basegrp = smf_grp_new( (*group)->grp, "Base Group", status );

    /* Loop over time chunks */
    for( i=0; (*status==SAI__OK)&&(i<(*group)->ngroups); i++ ) {
      size_t idx;
      /* Check for new continuous chunk */
      if( i==0 || ( (*group)->chunk[i] != (*group)->chunk[i-1]) ) {
        /* Loop over subarray */
        for( idx=0; idx<(*group)->nrelated; idx++ ) {
          size_t grpindex = (*group)->subgroups[i][idx];
          if ( grpindex > 0 ) {
            ndgCpsup( (*group)->grp, grpindex, *basegrp, status );
          }
        }
      }
    }
  }

 CLEANUP:
  keepchunk = astFree( keepchunk );
  chunk = astFree( chunk );
  chunklen = astFree( chunklen );
  piecelen = astFree( piecelen );
  grouped = astAnnul( grouped );

  if( *status != SAI__OK ) {
    /* free the group */
    if (basegrp && *basegrp) grpDelet( basegrp, status );
    if (group && *group) {
      smf_close_smfGroup( group, status );
    } else {
      /* have to clean up manually */
      new_chunk = astFree( new_chunk );
      new_tlen = astFree( new_tlen );
      if( subgroups ) {
        size_t isub;
        for( isub=0; isub<nkeep; isub++ ) {
          subgroups[isub] = astFree( subgroups[isub] );
        }
        subgroups = astFree( subgroups );
      }
    }
  }

  /* Return the maximum padding if required. */
  if( pad ) *pad = maxpad;
}
示例#4
0
void smf_getrefwcs( const char *param, Grp *igrp, AstFrameSet **specwcs,
                    AstFrameSet **spacewcs, int *isjsa, int *status ){

/* Local Variables */
   AstFrame *frm = NULL;
   AstFrameSet *refwcs = NULL;  /* The WCS FrameSet from the reference NDF */
   AstRegion *circle;
   char text[ 255 ];            /* Parameter value */
   int *tiles;
   int i;
   int jsatiles;
   int lbnd[2];                 /* Lower pixel index bounds of mid tile */
   int ntile;
   int perm[ 2 ];
   int refndf;                  /* NDF identifier for the refence NDF */
   int ubnd[2];                 /* Upper pixel index bounds of mid tile */
   size_t code;
   smfData *data = NULL;        /* Structure describing 1st input file */
   smfJSATiling skytiling;
   smf_inst_t inst = SMF__INST_NONE;
   smf_jsaproj_t proj;          /* Specific JSA projection to use */
   smf_subinst_t subinst;

/* Initialise the returned values. */
   *specwcs = NULL;
   *spacewcs = NULL;
   *isjsa = 0;

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

/* Begin an AST context. */
   astBegin;

/* If the JSAILES parameter is TRUE, then we use the JSA all-sky pixel
   grid regardless of the setting of REF. */
   parGet0l( "JSATILES", &jsatiles, status );
   if( jsatiles ) {
      strcpy( text, "JSA" );
      *isjsa = 1;

/* Otherwise, first get the parameter value as a string. Use subpar to avoid problem
   caused by interpretion of the text within the parameter system. */
   } else {
      subParFindpar( param, &code, status );
      subParGetname( code, text, sizeof(text), status );
   }

/* If no value was supplied, annul the error and do nothing more. */
   if( *status == PAR__NULL ) {
      errAnnul( status );

/* If it is "JSA", or one of the JSA projection codes, we return WCS that
   describes one of the the JSA all-sky pixel grids. */
   } else if( *status == SAI__OK ) {
      proj = smf_jsaproj_fromstr( text, 0, status );
      if( astChrMatch( text, "JSA" ) || proj != SMF__JSA_NULL ) {
         *isjsa = 1;

/* Report an error if the instrument cannot be determined. */
         if( !igrp ) {
            *status = SAI__ERROR;
            errRep( "", "smf_getrefwcs: Cannot use the JSA all-sky pixel "
                    "grid since no input group has been supplied (possibly "
                    "programming error).", status );
         } else {

/* Open the first input file. */
            smf_open_file( NULL, igrp, 1, "READ", SMF__NOCREATE_DATA, &data,
                           status );
            if( *status == SAI__OK ) {

/* Get the instrument. */
               if( data->hdr->instrument == INST__SCUBA2 ) {
                  subinst = smf_calc_subinst( data->hdr, status );
                  if( subinst == SMF__SUBINST_850 ) {
                     inst = SMF__INST_SCUBA_2_850;
                  } else {
                     inst = SMF__INST_SCUBA_2_450;
                  }

               } else if( data->hdr->instrument == INST__ACSIS ) {
                  inst = SMF__INST_ACSIS;

               } else if( *status == SAI__OK ) {
                  *status = SAI__ERROR;
                  if( data->file ) {
                     smf_smfFile_msg( data->file, "FILE", 1, "one or more of "
                                      "the input data files" );
                  } else {
                     msgSetc( "FILE", "one or more of the input data files" );
                  }
                  errRep( "", "No tiles are yet defined for the instrument that "
                          "created ^FILE.", status );
               }

/* Get the parameters that define the layout of sky tiles for the
   instrument. */
               smf_jsatiling( inst, &skytiling, status );

/* For "JSA" - choose the best projection. */
               if( astChrMatch( text, "JSA" ) ) {

/* Use the FITS headers in the first raw data file to create an AST Circle
   describing the approximate area of the observation within the tracking
   system. */
                  circle = smf_mapregion_approx( igrp, status );

/* Convert the circle to ICRS (as used by the JSA all-sky grid). */
                  astSetC( circle, "System", "ICRS" );

/* Get a list of the tiles that touch this circle. */
                  tiles = smf_jsatiles_region( circle, &skytiling,
                                               &ntile, status );

/* Choose the best projection (i.e. the projection that puts the circle
   furthest away from any singularities). */
                  proj = smf_jsaproj( ntile, tiles, &skytiling, status);

/* Free resources. */
                  tiles = astFree( tiles );
                  circle = astAnnul( circle );

/* If a good projection was specified, use it. Otherwise report an error. */
               } else if( proj == SMF__JSA_NULL && *status == SAI__OK ) {
                  *status = SAI__ERROR;
                  errRepf( "", "Bad value '%s' supplied for parameter %s.",
                           status, text, param );
               }

/* Report the projection type. */
               msgOutf( " ", "The %s will be created on the JSA %s "
                        "pixel grid.", status,
                        (data->hdr->instrument==INST__ACSIS)?"cube":"map",
                        smf_jsaproj_tostr( proj ) );

/* All tiles within the same JSA projection use the same WCS, so we get
   the WCS FrameSet for an arbitrary central tile, and use it for the
   full map. The exception is that tiles within the HPX facet that is
   split between bottom-left and top-right, use a different WCS (they
   have different reference points). But our choice of projection should
   mean that the map never falls in that facet. The base Frame will be
   GRID coords within the tile, and the current Frame will be ICRS
   (RA,Dec). */
               smf_jsatile( ((skytiling.ntpf * skytiling.ntpf - 1) * 2) / 3,
                            &skytiling, 0, proj, NULL, spacewcs, NULL, lbnd,
                            ubnd, status );

/* Change the base Frame to be PIXEL. */
               for( i = 1; i <= astGetI( *spacewcs, "NFrame" ); i++ ) {
                  frm = astGetFrame( *spacewcs, i );
                  if( astChrMatch( astGetC( frm, "Domain" ), "PIXEL" ) ) {
                     astSetI( *spacewcs, "Base", i );
                  }
                  frm = astAnnul( frm );
               }
            }

/* Close the current input data file. */
            smf_close_file( NULL, &data, status);
         }

/* Otherwise get the parameter value as an NDF. */
      } else {
         ndfAssoc( param, "READ", &refndf, status );

/* Get the WCS FrameSet from the reference NDF. */
         ndfGtwcs( refndf, &refwcs, status );

/* Attempt to extract a new FrameSet from this WCS FrameSet, in which the
   current Frame is a SkyFrame, and the base Frame is a 2D PIXEL Frame.
   Since the NDF library sets the GRID Frame to be the Base Frame, we need
   to make the PIXEL Frame the base Frame first. The NDF library ensures
   that the pixel Frame is Frame 2. */
         astSetI( refwcs, "Base", 2 );
         *spacewcs = atlFrameSetSplit( refwcs, "SKY", NULL, NULL, status );
         if( !(*spacewcs) ) {
            if( *status == SAI__OK ) {
               ndfMsg( "N", refndf );
               *status = SAI__ERROR;
               errRep( "", "The supplied reference NDF (^N) either has no "
                       "celestial WCS axes, or the celestial axes cannot "
                       "be separated from the non-celestial axes.", status );
            }

/* The rest of makemap assumes that the sky frame axes are in the default
   order (lon,lat). If this is not the case, permute them. */
         } else if( astGetI( *spacewcs, "IsLatAxis(1)" ) ) {
            perm[ 0 ] = 2;
            perm[ 1 ] = 1;
            astPermAxes( *spacewcs, perm );
         }

/* Now look for the spectral WCS (described by a DSBSpecFrame). */
         smf_getspectralwcs( refwcs, 1, specwcs, status );

/* We no longer need the NDF so annul it. */
         ndfAnnul( &refndf, status );
      }
   }

/* If no error has occurred, export any returned FrameSet pointers from
   the current AST context so that it will not be annulled when the AST
   context is ended. Otherwise, ensure a null pointer is returned. */
   if( *status == SAI__OK ) {
      if( *spacewcs ) astExport( *spacewcs );
      if( *specwcs ) astExport( *specwcs );
   } else {
      if( *spacewcs ) *spacewcs = astAnnul( *spacewcs );
      if( *specwcs ) *specwcs = astAnnul( *specwcs );
   }

/* End the AST context. This will annul all AST objects created within the
   context (except for those that have been exported from the context). */
   astEnd;

}