예제 #1
0
static void eratosthenes_once(struct eratosthenes *s, unsigned long limit, unsigned long p)
{
	unsigned long n = VAL_TO_BIT(3*p);
	unsigned long obits = LIMIT_TO_NBITS(s->limit);

	if (obits > n) {
		n = obits + p - 1 - ((obits - n - 1) % p);
	}

	assert((BIT_TO_VAL(n) % p) == 0);
	assert((BIT_TO_VAL(n) / p) > 1);

	while (n < LIMIT_TO_NBITS(limit)) {
		bitmap_clear_bit(s->b, n);
		n += p;
	}
}
예제 #2
0
static void eratosthenes_sieve_(struct eratosthenes *s, unsigned long limit)
{
	unsigned long p = 3;

	while ((p * p) < limit) {
		unsigned long n;

		eratosthenes_once(s, limit, p);

		n = bitmap_ffs(s->b, VAL_TO_BIT(p) + 1, LIMIT_TO_NBITS(limit));

		/* We should never run out of primes */
		assert(n < LIMIT_TO_NBITS(limit));

		p = BIT_TO_VAL(n);
	}
}
예제 #3
0
unsigned long eratosthenes_nextprime(const struct eratosthenes *s, unsigned long n)
{
	unsigned long i;

	if ((n + 1) >= s->limit)
		return 0;

	if (n < 2)
		return 2;

	if (n == 2)
		return 3;

	i = bitmap_ffs(s->b, VAL_TO_BIT(n) + 1, LIMIT_TO_NBITS(s->limit));
	if (i == LIMIT_TO_NBITS(s->limit))
		/* Reached the end of the sieve */
		return 0;

	return BIT_TO_VAL(i);
}
예제 #4
0
const char *smf_qual_str( smf_qfam_t family, int usebit, int bit_or_val,
                          const char **descr, int *status ) {

  /* Set a default value */
  const char * retval = NULL;
  const char * ldescr = "No description available";
  int qval = 0;

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

  /* Choose how we have been given a value */
  if (usebit) {
    qval = BIT_TO_VAL(bit_or_val);
  } else {
    qval = bit_or_val;
  }

  if (family == SMF__QFAM_TSERIES) {
    /* now switch on bit mask */
    switch( qval ) {
    case SMF__Q_BADDA:
      retval = "BADDA";
      ldescr = "Set iff a sample is flagged by the DA";
      break;

    case SMF__Q_BADB:
      retval = "BADBOL";
      ldescr = "Set iff all data from bolo to be ignored";
      break;

    case SMF__Q_SPIKE:
      retval = "SPIKE";
      ldescr = "Set iff a spike is detected";
      break;

    case SMF__Q_JUMP:
      retval = "DCJUMP";
      ldescr = "Set iff a DC jump is present";
      break;

    case SMF__Q_PAD:
      retval = "PAD";
      ldescr = "Set iff data are padding";
      break;

    case SMF__Q_APOD:
      retval = "APOD";
      ldescr = "Set iff data are apodized/boundary";
      break;

    case SMF__Q_STAT:
      retval = "STAT";
      ldescr = "Set iff telescope was stationary";
      break;

    case SMF__Q_COM:
      retval = "COM";
      ldescr = "Set iff data common-mode rejected";
      break;

    case SMF__Q_FILT:
      retval = "FILT";
      ldescr = "Set iff sample could not be filtered";
      break;

    case SMF__Q_NOISE:
      retval = "NOISE";
      ldescr = "Set if bolometer was too noisy";
      break;

    case SMF__Q_EXT:
      retval = "EXT";
      ldescr = "Set if extinction correction failed";
      break;

    case SMF__Q_LOWAP:
      retval = "LOWAP";
      ldescr = "Set iff apodisation factor is too low to invert";
      break;

    case SMF__Q_BADEF:
      retval = "BADEF";
      ldescr = "Set iff optical efficiency value is bad";
      break;

    default:
      retval = NULL;
    }
  } else if (family == SMF__QFAM_MAP) {
    /* now switch on bit mask */
    /*          012345678901234567890123456789012345678901234567890 << 50 characters */
    switch( qval ) {
    case SMF__MAPQ_ZERO:
      retval = "ZERO";
      ldescr = "Set iff output pixel was zeroed by the map-maker";
      break;

    default:
      retval = NULL;
    }
  } else if (family == SMF__QFAM_TCOMP) {
    /* now switch on bit mask */
    /*          012345678901234567890123456789012345678901234567890 << 50 characters */
    switch( qval ) {
    case SMF__TCOMPQ_BAD:
      retval = "BADBOLO";
      ldescr = "Set if bolometer data were inherently bad";
      break;
    case SMF__TCOMPQ_ENDS:
      retval = "ENDS";
      ldescr = "Set if the ends of the time series are bad";
      break;
    case SMF__TCOMPQ_BLIP:
      retval = "BLIP";
      ldescr = "Set if bolometer went bad for a moment";
      break;
    case SMF__TCOMPQ_MATCH:
      retval = "MATCH";
      ldescr = "Set if time series did not look like others";
      break;
    case SMF__TCOMPQ_TEL:
      retval = "TEL";
      ldescr = "Set if telescope was not in useful state";
      break;
    default:
      retval = NULL;
    }


  } else {
    *status = SAI__ERROR;
    errRep("", "Did not understand requested quality family",
           status );
  }

  if (descr) *descr = ldescr;

  return retval;
}
예제 #5
0
void smf_write_flagmap( ThrWorkForce *wf, smf_qual_t mask, smfArray *lut, smfArray *qua,
                        smfDIMMData *dat, const Grp *flagrootgrp,
                        size_t contchunk, const int *lbnd_out,
                        const int *ubnd_out, AstFrameSet *outfset,
                        int *status ) {

  AstFrameSet *tfset;          /* Temporary FrameSet pointer */
  Grp *mgrp=NULL;               /* Temporary group for map names */
  char *pname=NULL;             /* Poiner to name */
  char name[GRP__SZNAM+1];      /* Buffer for storing names */
  char tempstr[20];             /* Temporary string */
  char tmpname[GRP__SZNAM+1];   /* temp name buffer */
  dim_t nbolo;                  /* Number of bolometers */
  dim_t ntslice;                /* Number of time slices */
  double shift[ 1 ];            /* Shift from GRID to bit number */
  int *flagmap=NULL;            /* pointer to flagmap data */
  int *lut_data=NULL;           /* Pointer to DATA component of lut */
  int ibit;                     /* Quality bit number */
  int lbnd3d[3];                /* Lower bounds for 3D output */
  int npix;                     /* Number of pixels per plane */
  int target;                   /* Target value for incrementing pixel count */
  int ubnd3d[3];                /* Upper bounds for 3D output */
  size_t bstride;               /* Bolometer stride */
  size_t i;                     /* loop counter */
  size_t idx=0;                 /* index within subgroup */
  size_t ii;                    /* array offset index */
  size_t j;                     /* loop counter */
  size_t tstride;               /* Time stride */
  smfData *mapdata=NULL;        /* smfData for new map */
  smf_qual_t *qua_data=NULL;    /* Pointer to DATA component of qua */

  if( *status != SAI__OK ) return;

  if( !lut || !qua || !dat || !flagrootgrp || !lbnd_out || !ubnd_out ||
      !outfset ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": NULL inputs supplied", status );
    return;
  }

  /* Create a name for the flagmap, taking into account the chunk
     number. Only required if we are using a single output
     container. */
  pname = tmpname;
  grpGet( flagrootgrp, 1, 1, &pname, sizeof(tmpname), status );
  one_strlcpy( name, tmpname, sizeof(name), status );
  one_strlcat( name, ".", sizeof(name), status );

  sprintf(tempstr, "CH%02zd", contchunk);
  one_strlcat( name, tempstr, sizeof(name), status );
  mgrp = grpNew( "flagmap", status );
  grpPut1( mgrp, name, 0, status );

  msgOutf( "", "*** Writing flagmap %s", status, name );

  /* If a non-zero mask value wassupplied, the flagmap is 2-dimensional
     and each pixel value counts the number of samples flagged by any of
     the qualities included in the mask. */
  if( mask ) {

     smf_open_newfile( wf, mgrp, 1, SMF__INTEGER, 2, lbnd_out, ubnd_out, 0, &mapdata,
                       status);
     flagmap = mapdata->pntr[0];

     /* Loop over subgroup index (subarray) */
     for( idx=0; (idx<qua->ndat)&&(*status==SAI__OK); idx++ ) {

          smf_get_dims( qua->sdata[idx], NULL, NULL, &nbolo, &ntslice,
                        NULL, &bstride, &tstride, status );
          qua_data = (qua->sdata[idx]->pntr)[0];
          lut_data = (lut->sdata[idx]->pntr)[0];

          /* Loop over bolometer and time slice and create map */
          for( i=0; i<nbolo; i++ ) {
            /* Skip bolometers only if SMF__Q_BADB is set both in the
               data and the mask */
            if( !(qua_data[i*bstride] & mask & SMF__Q_BADB) ) {
              for( j=0; j<ntslice; j++ ) {
                ii = i*bstride + j*tstride;
                if( (qua_data[ii] & mask) && (lut_data[ii] != VAL__BADI) ) {
                  flagmap[lut_data[ii]]++;
                }
              }
            }
          }
        }

     /* Write WCS */
     smf_set_moving( (AstFrame *) outfset, NULL, status );
     ndfPtwcs( outfset, mapdata->file->ndfid, status );

  /* If the mask is zero, the flagmap is 3-dimensional and contains a
     plane for each quality bit, plus an additional plane (plane 1)
     containing the number of unflagged samples in each pixel. */
  } else {
     lbnd3d[ 0 ] = lbnd_out[ 0 ];
     lbnd3d[ 1 ] = lbnd_out[ 1 ];
     lbnd3d[ 2 ] = -1;
     ubnd3d[ 0 ] = ubnd_out[ 0 ];
     ubnd3d[ 1 ] = ubnd_out[ 1 ];
     ubnd3d[ 2 ] = SMF__NQBITS_TSERIES - 1;

     smf_open_newfile( wf, mgrp, 1, SMF__INTEGER, 3, lbnd3d, ubnd3d, 0,
                       &mapdata, status);
     flagmap = mapdata->pntr[0];

     /* No. of pixels in one plane */
     npix = ( ubnd3d[ 1 ] - lbnd3d[ 1 ] + 1 )*( ubnd3d[ 0 ] - lbnd3d[ 0 ] + 1 );

     /* Loop over each quality bit (-1 == "no flags"). */
     for( ibit = -1; ibit < SMF__NQBITS_TSERIES; ibit++ ) {

        /* The test of each sample is performed by checking if the
           sample's quality value ANDed with "mask" is equal to "target".
           This is requires since ibit==-1 (i.e. "count all samples that
           have no flags set") requires a different logic to the other
           ibit values. */
        if( ibit == -1 ) {
           mask = SMF__Q_GOOD;
           target = 0;
        } else {
           mask = BIT_TO_VAL(ibit);
           target = mask;
        }

        /* Loop over subgroup index (subarray) */
        for( idx=0; (idx<qua->ndat)&&(*status==SAI__OK); idx++ ) {

           smf_get_dims( qua->sdata[idx], NULL, NULL, &nbolo, &ntslice,
                           NULL, &bstride, &tstride, status );
           qua_data = (qua->sdata[idx]->pntr)[0];
           lut_data = (lut->sdata[idx]->pntr)[0];

           /* Loop over bolometer and time slice and create map */
           for( i=0; i<nbolo; i++ ) {

              /* Skip bolometers only if SMF__Q_BADB is set both in the
                 data and the mask */
              for( j=0; j<ntslice; j++ ) {
                 ii = i*bstride + j*tstride;
                 if( ( (qua_data[ii] & mask) == target ) &&
                     (lut_data[ii] != VAL__BADI) ) {
                   flagmap[lut_data[ii]]++;
                 }
              }
           }
        }

        /* Move the pointer on to th enext plane. */
        flagmap += npix;

     /* Next quality bit. */
     }

     /* Take a copy of the supplied FrameSet so we do not modify it. */
     tfset = astCopy( outfset );

     /* Set atributes for moving target if necessary. */
     smf_set_moving( (AstFrame *) tfset, NULL, status );

     /* Modify the WCS FrameSet so that the base and current Frames are
        3-dimensional. The current Frame is expanded by adding in a simple
        1D Frame representing quality bit, and the base Frame is expanded
        by adding in a 3rd GRID axis. Other Frames are left unchanged.
        The quality bit Frame and the new GRID axis are connected using
        a ShiftMap that gives the right zero-based bit numbers (which
        also correspond to PIXEL indices). */
     shift[ 0 ] = -2.0;
     atlAddWcsAxis( tfset, (AstMapping *) astShiftMap( 1, shift, " " ),
                    astFrame( 1, "Label(1)=Quality bit,Domain=QUALITY" ),
                    NULL, NULL, status );

     /* Store the FrameSet in the 3D NDF. */
     ndfPtwcs( tfset, mapdata->file->ndfid, status );

     tfset = astAnnul( tfset );
  }

  /* Clean up */
  if( mgrp ) grpDelet( &mgrp, status );
  smf_close_file( wf, &mapdata, status );

}
예제 #6
0
static void smf1_qual_unmap( void *job_data_ptr, int *status ) {
/*
*  Name:
*     smf1_qual_unmap

*  Purpose:
*     Executed in a worker thread to do various calculations for
*     smf_qual_unmap.

*  Invocation:
*     smf1_qual_unmap( void *job_data_ptr, int *status )

*  Arguments:
*     job_data_ptr = SmfQualUnmapData * (Given)
*        Data structure describing the job to be performed by the worker
*        thread.
*     status = int * (Given and Returned)
*        Inherited status.

*/

/* Local Variables: */
   SmfQualUnmapData *pdata;
   size_t *qcount;
   size_t i1;
   size_t i2;
   size_t i;
   size_t k;
   size_t nqbits;
   smf_qual_t *p1;
   unsigned char *p2;

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

/* Get a pointer that can be used for accessing the required items in the
   supplied structure. */
   pdata = (SmfQualUnmapData *) job_data_ptr;

   i1 = pdata->i1;
   i2 = pdata->i2;
   nqbits = pdata->nqbits;
   qcount = pdata->qcount;

   if( pdata->operation == 1 ){
      for( k=0; k<nqbits; k++ ) {
        qcount[k] = 0;
      }

      p1 = pdata->qual + i1;
      for( i = i1; i <= i2; i++,p1++) {
        for( k=0; k<nqbits; k++ ) {
          if( *p1 & BIT_TO_VAL(k) ) {
            qcount[k]++;
          }
        }
      }

   } else if( pdata->operation == 2 ){
      size_t curbit;
      size_t lowbit = pdata->lowbit;
      size_t highbit = pdata->highbit;
      p1 = pdata->qual + i1;
      p2 = pdata->qmap + i1;
      for( i = i1; i <= i2; i++,p1++,p2++) {
         curbit = 0;
         *p2 = 0;
         for( k=lowbit; k<=highbit; k++) {

/* was this bit used by this data array? */
            if( qcount[k] ) {

/* was the bit set for this location? */
              if( *p1 & BIT_TO_VAL(k) ) {
                *p2 |= BIT_TO_VAL(curbit);
              }

              curbit++;
            }
          }
        }

   } else if( pdata->operation == 3 ){

      p1 = pdata->qual + i1;
      p2 = pdata->qmap + i1;
      for( i = i1; i <= i2; i++,p1++,p2++) {

        *p2 = 0;
        if( *p1 ) {
          if ( *p1 & (SMF__Q_BADDA|SMF__Q_BADB|SMF__Q_NOISE) ) {
            *p2 |= SMF__TCOMPQ_BAD;
          }
          if ( *p1 & (SMF__Q_APOD|SMF__Q_PAD) ) {
            *p2 |= SMF__TCOMPQ_ENDS;
          }
          if ( *p1 & (SMF__Q_JUMP|SMF__Q_IP|SMF__Q_SPIKE|SMF__Q_FILT|SMF__Q_EXT|SMF__Q_LOWAP|SMF__Q_BADEF) ) {
            *p2 |= SMF__TCOMPQ_BLIP;
          }
          if ( *p1 & (SMF__Q_COM|SMF__Q_SSN|SMF__Q_PCA) ) {
            *p2 |= SMF__TCOMPQ_MATCH;
          }
          if ( *p1 & (SMF__Q_RING) ) {
            *p2 |= SMF__TCOMPQ_RING;
          }
          if ( *p1 & (SMF__Q_STAT) ) {
            *p2 |= SMF__TCOMPQ_TEL;
          }
          if (*p2 == 0 ) {

/* something went wrong. We missed a quality bit somewhere */
            msgOutiff(MSG__QUIET, "", FUNC_NAME ": Untested quality bit found"
                      " in position %zu with value %u", status,
                      i, (unsigned int)*p1);
          }
        }
      }

   } else {
      *status = SAI__ERROR;
      errRepf( "", "smf1_qual_unmap: Invalid operation (%d) supplied.",
               status, pdata->operation );
   }
}
예제 #7
0
smf_qual_t * smf_qual_map( ThrWorkForce *wf, int indf, const char mode[],
                           smf_qfam_t *family, size_t *nmap, int * status ) {

  size_t i;             /* Loop counter */
  int itemp = 0;        /* temporary int */
  smf_qfam_t lfamily = SMF__QFAM_NULL; /* Local quality family */
  size_t nout;          /* Number of elements mapped */
  size_t numqn = 0;     /* number of quality names */
  IRQLocs *qlocs = NULL;/* IRQ Quality */
  unsigned char *qmap;  /* pointer to mapped unsigned bytes */
  void *qpntr[1];       /* Somewhere to put the mapped pointer */
  smf_qual_t *retval = NULL; /* Returned pointer */
  int there;            /* Does the NDF Have a Quality component? */
  char xname[DAT__SZNAM+1];  /* Name of extension holding quality names */
  SmfQualMapData *job_data = NULL;
  SmfQualMapData *pdata;
  int nw;
  size_t step;
  int iw;


  if (*status != SAI__OK) return retval;

  /* Ensure jobs submitted to the workforce within this function are
     handled separately to any jobs submitted earlier (or later) by any
     other function. */
  thrBeginJobContext( wf, status );

  /* how many elements do we need */
  ndfSize( indf, &itemp, status );
  nout = itemp;
  if (nmap) *nmap = nout;

  /* malloc the QUALITY buffer. Initialise to zero to simplify logic
     below. It is difficult to determine in advance which case can use
     initialisation. */
  retval = astCalloc( nout, sizeof(*retval) );

  /* How many threads do we get to play with */
  nw = wf ? wf->nworker : 1;

  /* Find how many elements to process in each worker thread. */
  step = nout/nw;
  if( step == 0 ) step = 1;

  /* Allocate job data for threads, and store common values. Ensure that the
     last thread picks up any left-over elements.  */
  job_data = astCalloc( nw, sizeof(*job_data) );
  if( *status == SAI__OK ) {
    for( iw = 0; iw < nw; iw++ ) {
      pdata = job_data + iw;
      pdata->i1 = iw*step;
      if( iw < nw - 1 ) {
        pdata->i2 = pdata->i1 + step - 1;
      } else {
        pdata->i2 = nout - 1 ;
      }
      pdata->retval = retval;

    }
  }

  /* If the NDF has no QUality component, return the buffer filled with
     zeros. */
  ndfState( indf, "QUALITY", &there, status );
  if( there ) {

    /* READ and UPDATE mode require that the QUALITY is processed
       and copied before being returned. WRITE mode means that the
       buffer contains no information to copy yet. WRITE/ZERO
       and WRITE/BAD also require that we do not do any quality
       handling */
    if ( strncmp(mode, "WRITE",5) == 0 ) {
      /* WRITE and WRITE/ZERO are actually treated the same way
         because we always initialise */
      if ( strcmp( mode, "WRITE/BAD") == 0 ) {
        for( iw = 0; iw < nw; iw++ ) {
            pdata = job_data + iw;
            pdata->operation = 1;
            thrAddJob( wf, 0, pdata, smf1_qual_map, 0, NULL, status );
        }
        thrWait( wf, status );
      }

      /* unmap the NDF buffer and return the pointer */
      if (family) *family = lfamily;
      return retval;
    }

    /* Map the quality component (we always need to do this) */
    ndfMap( indf, "QUALITY", "_UBYTE", mode, &qpntr[0], &itemp, status );
    qmap = qpntr[0];

    /* Need to find out what quality names are in play so we
       can work out which family to translate them to */
    irqFind( indf, &qlocs, xname, status );
    numqn = irqNumqn( qlocs, status );

    if ( *status == IRQ__NOQNI || numqn == 0) {
      /* do not have any names defined so we have no choice
         in copying the values directly out the file */
      if (*status != SAI__OK) errAnnul( status );

      /* simple copy with type conversion */

      for( iw = 0; iw < nw; iw++ ) {
        pdata = job_data + iw;
        pdata->qmap = qmap;
        pdata->operation = 2;
        thrAddJob( wf, 0, pdata, smf1_qual_map, 0, NULL, status );
      }
      thrWait( wf, status );

    } else {
      IRQcntxt contxt = 0;
      int ndfqtosmf[NDFBITS];        /* NDF bit (arr index) and SMURF alternative */
      int ndfqtoval[NDFBITS];        /* NDF bit (arr index) and corresponding Qual value */
      int ndfqval[NDFBITS];          /* Bit values for NDF quality */
      int identity = 1;        /* Is this a simple identity map? */

      /* prefill the mapping with bit to bit mapping */
      for (i=0; i<NDFBITS; i++) {
        ndfqtosmf[i] = i;
        ndfqtoval[i] = BIT_TO_VAL(i);
        ndfqval[i] = ndfqtoval[i];
      }

      /* Now translate each name to a bit */
      for (i = 0; i < numqn && *status == SAI__OK; i++) {
        char qname[IRQ__SZQNM+1];
        char commnt[IRQ__SZCOM+1];
        int fixed;
        int value;
        int bit;
        int done;
        smf_qual_t qval;
        smf_qfam_t tmpfam = 0;

        irqNxtqn( qlocs, &contxt, qname, &fixed, &value, &bit,
                  commnt,sizeof(commnt), &done, status );
        bit--;    /* IRQ starts at 1 */

        /* Now convert the quality name to a quality value
           and convert that to a bit. These should all be
           less than 9 bits because they are in the NDF file. */
        qval = smf_qual_str_to_val( qname, &tmpfam, status );

        if (*status == SMF__BADQNM ) {
          /* annul status and just copy this bit from the file
             to SMURF without change. This might result in a clash
             of bits but we either do that or drop out the loop
             and assume everything is broken */
          if (*status != SAI__OK) errAnnul(status);
          ndfqtosmf[bit] = bit;
          ndfqtoval[bit] = BIT_TO_VAL(bit);

        } else if( *status == SAI__OK ){
          if (lfamily == SMF__QFAM_NULL) {
            lfamily = tmpfam;
          } else if (lfamily != tmpfam) {
            msgOutif(MSG__QUIET, "",
                     "WARNING: Quality names in file come from different families",
                     status );
          }
          ndfqtosmf[bit] = smf_qual_to_bit( qval, status );
          ndfqtoval[bit] = qval;

          /* not a 1 to 1 bit translation */
          if (bit != ndfqtosmf[bit]) identity = 0;
        }
      }

      /* Now copy from the file and translate the bits. If this is an
         identity mapping or we do not know the family then we go quick. */
      if (*status == SAI__OK) {
        if ( (identity && lfamily != SMF__QFAM_TCOMP) || lfamily == SMF__QFAM_NULL) {
          for( iw = 0; iw < nw; iw++ ) {
            pdata = job_data + iw;
            pdata->qmap = qmap;
            pdata->ndfqval = ndfqval;
            pdata->lfamily = lfamily;
            pdata->ndfqtoval = ndfqtoval;
            pdata->ndfqval = ndfqval;
            pdata->operation = 2;
            thrAddJob( wf, 0, pdata, smf1_qual_map, 0, NULL, status );
          }
          thrWait( wf, status );

        } else {

          for( iw = 0; iw < nw; iw++ ) {
            pdata = job_data + iw;
            pdata->qmap = qmap;
            pdata->ndfqval = ndfqval;
            pdata->lfamily = lfamily;
            pdata->ndfqtoval = ndfqtoval;
            pdata->ndfqval = ndfqval;
            pdata->operation = 3;
            thrAddJob( wf, 0, pdata, smf1_qual_map, 0, NULL, status );
          }
          thrWait( wf, status );

          /* we have uncompressed */
          if (lfamily == SMF__QFAM_TCOMP) lfamily = SMF__QFAM_TSERIES;
        }
      }
    }

    /* Free quality */
    irqRlse( &qlocs, status );

    /* no longer need the mapped data */
    ndfUnmap( indf, "QUALITY", status );
  }

  /* End the Thr job context */
  thrEndJobContext( wf, status );

  /* Free other resources. */
  job_data = astFree( job_data );

  if (family) *family = lfamily;
  return retval;
}
예제 #8
0
smf_qual_t * smf_qual_unmap( int indf, smf_qfam_t family, smf_qual_t * qual, int * status ) {
  int canwrite = 0;   /* can we write to the file? */
  size_t nqbits = 0;  /* Number of quality bits in this family */

  if (*status != SAI__OK) goto CLEANUP;

  /* do nothing if there is no quality */
  if (!qual) return NULL;

  /* if we do not have an NDF identifier we just free the memory */
  if (indf == NDF__NOID) goto CLEANUP;

  /* See if we have WRITE access to the file */
  ndfIsacc( indf, "WRITE", &canwrite, status );

  /* if we have WRITE access and the data were not mapped we have
     to copy to the file. Also check we have a non-NULL input pointer.
     If the data were mapped we still have to make sure the quality names
     are stored. */
  if ( canwrite && qual ) {
    int highbit = -1; /* highest bit used */
    size_t i;
    int itemp;
    int lowbit = -1;  /* Lowest bit used */
    size_t nout;
    int nqual = 0;
    void *qpntr[1];
    size_t qcount[SMF__NQBITS]; /* statically allocate the largest array */
    IRQLocs *qlocs;
    unsigned char * qmap;
    int there;

    ndfMsg( "FILE", indf );
    msgOutif( MSG__DEBUG, "", "Finalising quality for file ^FILE", status);

    if (family == SMF__QFAM_TCOMP ) {
      /* note that TCOMP is not an allowed quality because SMURF should not be
         using it anywhere in a permanent way. */
      *status = SAI__ERROR;
      ndfMsg( "NDF", indf );
      errRepf( "", "Unsupported quality family '%s' for quality unmapping of "
               "file ^NDF", status, smf_qfamily_str(family,status) );
      goto CLEANUP;
    } else if (family == SMF__QFAM_NULL) {
      /* In this case we have to assume that we just cast the quality
         to UBYTE and copy it without changing anything or naming the
         entries. Use a simple type conversion. */
      ndfMap( indf, "QUALITY", "_UBYTE", "WRITE", &qpntr[0], &itemp, status );
      qmap = qpntr[0];
      nout = itemp;

      for (i = 0; i<nout; i++) {
        qmap[i] = qual[i];
      }
      ndfUnmap( indf, "QUALITY", status );

      /* Turn on all quality */
      ndfSbb( 255, indf, status );

      /* we are finished so jump to tidy up */
      goto CLEANUP;
    }

    /* work out how many quality items are in this family */
    nqbits = smf_qfamily_count( family, status );

    /* initialize qcount */
    for (i=0; i<SMF__NQBITS; i++) {
      qcount[i] = 0;
    }

    /* how many pixels in NDF (assumed to be number in quality) */
    ndfSize( indf, &itemp, status );
    nout = itemp;

    /* Work out which bits are actually used */
    if (*status == SAI__OK) {
      size_t k;
      /* now we try to be a bit clever. It may be a mistake since we have to
         do multiple passes through "qual". First determine how many quality
         bits are actually set. */
      for (i = 0; i<nout; i++) {
        /* try all the bits */
        for( k=0; k<nqbits; k++ ) {
          if( qual[i] & BIT_TO_VAL(k) ) {
            qcount[k]++;
          }
        }
      }

      /* see how many we got */
      for (k=0; k<nqbits; k++) {
        if ( qcount[k] ) {
          nqual++;
          highbit = k;
          if (lowbit < 0) lowbit = k;
        }
      }
    }

    /* for IRQ we need to ensure the SMURF extension exists so open and annul it if it is missing.
       We are completely rewriting any IRQ information so we have to delete any previously existing
       IRQ extension. */
    irqDelet( indf, status );
    ndfXstat( indf, SMURF__EXTNAME, &there, status );
    if (!there) {
      HDSLoc * smurfloc = NULL;
      /* Create SMURF extension if it does not already exist */
      ndfXnew( indf, SMURF__EXTNAME, SMURF__EXTTYPE, 0, NULL, &smurfloc, status );
      if (smurfloc) datAnnul( &smurfloc, status );
    }
    irqNew( indf, SMURF__EXTNAME, &qlocs, status );

    /* malloced so we need to map and copy over the values. IRQ
       names need to be set BEFORE we copy. */

    /* Map the quality component with WRITE access */
    ndfMap( indf, "QUALITY", "_UBYTE", "WRITE", &qpntr[0], &itemp, status );
    qmap = qpntr[0];

    /* we assume the number of elements in "qual" is the same as in "qmap" */
    if (*status == SAI__OK) {
      size_t k;

      /* if we only have 8 or fewer bits active we can just compress
         by mapping them to the lower 8 bits. This will work if we also
         set the IRQ quality names in the NDF. */
      if (nqual == 0 ) {
        /* easy */
        memset( qmap, 0, nout * smf_dtype_sz( SMF__UBYTE, status ) );
      } else if ( nqual <= 8 ) {
        size_t curbit = 0;

        /* and the quality names. Start at lowbit and go to highbit
           knowing that we have shifted them down so that lowbit in qual
           is bit 0 in NDF. */
        for (k=lowbit; k<=(size_t)highbit; k++) {
          if (qcount[k]) {
            int fixed = 0;             /* is bit fixed? */
            const char * qdesc = NULL; /* Description of quality */
            const char * qstr = NULL;  /* Quality string identifier */
            curbit++;
            qstr = smf_qual_str( family, 1, k, &qdesc, status );

            irqAddqn( qlocs, qstr, 0, qdesc, status );
            irqFxbit( qlocs, qstr, curbit, &fixed, status );
          }
        }

        /* shift them down */
        for (i=0; i<nout; i++) {
          curbit = 0;
          qmap[i] = 0;

          for (k=lowbit; k<=(size_t)highbit; k++) {
            /* was this bit used by this data array? */
            if (qcount[k]) {
              /* was the bit set for this location? */
              if ( qual[i]&BIT_TO_VAL(k)) {
                qmap[i] |= BIT_TO_VAL(curbit);
              }
              curbit++;
            }
          }
        }

      } else {
        size_t curbit = 0;

        /* Quality names are now needed and we have to write them
           all out because we have not compressed the bits in the
           output quality array we've only compressed the input.
           To limit the number of active bits we'd have to copy the
           compressed bits to the output and then set the quality
           names but IRQ does not let you do that so you would need
           to run through the entire array first counting which bits
           were used. */

        for (k=0; k<SMF__NQBITS_TCOMP; k++) {
          int fixed = 0;
          const char * qdesc = NULL; /* Description of quality */
          const char * qstr = NULL;  /* Quality string identifier */
          qstr = smf_qual_str( SMF__QFAM_TCOMP, 1, k, &qdesc, status );

          /* Set the quality name */
          irqAddqn( qlocs, qstr, 0, qdesc, status );
          curbit++;
          irqFxbit( qlocs, qstr, curbit, &fixed, status );
        }

        /* compress them */
        for (i = 0; i<nout; i++) {
          qmap[i] = 0;
          if (qual[i]) {
            if ( qual[i] & (SMF__Q_BADDA|SMF__Q_BADB|SMF__Q_NOISE) ) {
              qmap[i] |= SMF__TCOMPQ_BAD;
            }
            if ( qual[i] & (SMF__Q_APOD|SMF__Q_PAD) ) {
              qmap[i] |= SMF__TCOMPQ_ENDS;
            }
            if ( qual[i] & (SMF__Q_JUMP|SMF__Q_SPIKE|SMF__Q_FILT|SMF__Q_EXT|SMF__Q_LOWAP|SMF__Q_BADEF) ) {
              qmap[i] |= SMF__TCOMPQ_BLIP;
            }
            if ( qual[i] & (SMF__Q_COM) ) {
              qmap[i] |= SMF__TCOMPQ_MATCH;
            }
            if ( qual[i] & (SMF__Q_STAT) ) {
              qmap[i] |= SMF__TCOMPQ_TEL;
            }
            if (qmap[i] == 0 ) {
              /* something went wrong. We missed a quality bit somewhere */
              msgOutiff(MSG__QUIET, "", FUNC_NAME ": Untested quality bit found"
                        " in position %zu with value %u", status,
                        i, (unsigned int)qual[i]);
            }
          }
        }

      }
    }

    /* Unmap quality */
    ndfUnmap( indf, "QUALITY", status );

    /* Set the badbits mask to enable all quality by default.
       Do not do this for MAP quality at the moment. */
    if (family != SMF__QFAM_MAP) ndfSbb( 255, indf, status );

    /* release IRQ resources */
    irqRlse( &qlocs, status );
  }

 CLEANUP:
  /* Tidy up */
  if (qual) qual = astFree( qual );
  return NULL;

}