예제 #1
0
smf_qual_t * smf_qual_unmap( ThrWorkForce *wf, int indf, smf_qfam_t family,
                             smf_qual_t * qual, smf_qual_t mask, int * status ) {
  int canwrite = 0;   /* can we write to the file? */
  size_t nqbits = 0;  /* Number of quality bits in this family */
  SmfQualUnmapData *job_data = NULL;
  SmfQualUnmapData *pdata;
  int nw;
  size_t step;
  int iw;

  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;

    /* 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->nqbits = nqbits;
        pdata->qual = qual;
        pdata->nout = nout;
      }
    }

    /* 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( iw = 0; iw < nw; iw++ ) {
        pdata = job_data + iw;
        pdata->operation = 1;
        thrAddJob( wf, 0, pdata, smf1_qual_unmap, 0, NULL, status );
      }
      thrWait( wf, status );

      for( iw = 0; iw < nw; iw++ ) {
        pdata = job_data + iw;
        for( k=0; k<nqbits; k++ ) {
          qcount[k] += pdata->qcount[k];
        }
      }

      /* Reset the counts to zero for any bits that are not required
         (i.e. are not set in "mask").  */
      for( k=0; k<nqbits; k++ ) {
         if( ! (mask & (1<<k)) ) qcount[k] = 0;
      }

      /* 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( iw = 0; iw < nw; iw++ ) {
          pdata = job_data + iw;
          pdata->operation = 2;
          pdata->qmap = qmap;
          pdata->highbit = highbit;
          pdata->lowbit = lowbit;
          for( k=0; k<nqbits; k++ ) {
            pdata->qcount[k] = qcount[k];
          }
          thrAddJob( wf, 0, pdata, smf1_qual_unmap, 0, NULL, status );
        }
        thrWait( wf, status );

      } 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( iw = 0; iw < nw; iw++ ) {
          pdata = job_data + iw;
          pdata->operation = 3;
          pdata->qmap = qmap;
          thrAddJob( wf, 0, pdata, smf1_qual_unmap, 0, NULL, status );
        }
        thrWait( wf, status );

      }
    }

    /* 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 */
  qual = astFree( qual );
  job_data = astFree( job_data );
  return NULL;

}
예제 #2
0
int smf_dataOrder( ThrWorkForce *wf, smfData *data, int isTordered,
                   int *status ) {

  /* Local Variables */
  size_t bstr1;                 /* bolometer index stride input */
  size_t bstr2;                 /* bolometer index stride output */
  dim_t i;                      /* loop counter */
  int inPlace=0;                /* If set change array in-place */
  dim_t nbolo;                  /* Number of bolometers */
  dim_t ndata;                  /* Number of data points */
  dim_t newdims[3];             /* Size of each dimension new buffer */
  int newlbnd[3];               /* New pixel origin */
  dim_t ntslice;                /* Number of time slices */
  size_t tstr1;                 /* time index stride input */
  size_t tstr2;                 /* time index stride output */
  int waschanged = 0;           /* did we chagne the order? */
  int writable;                 /* Is the NDF writable? */
  int freeold;                  /* Free the old array if change is not in place? */

  /* Main routine */
  if (*status != SAI__OK) return waschanged;

  /* Check for valid isTordered */
  if( (isTordered != 0) && (isTordered != 1) ) {
    *status = SAI__ERROR;
    msgSeti("ISTORDERED",isTordered);
    errRep( "", FUNC_NAME ": Invalid isTordered (0/1): ^ISTORDERED", status);
    return waschanged;
  }

  /* Check for a valid data */
  if( !data ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME ": NULL data supplied", status);
    return waschanged;
  }

  /* If value of isTordered matches current value in smfData return */
  if( data->isTordered == isTordered ) return waschanged;

  /* Make sure we're looking at 3-dimensions of bolo data */
  if( data->ndims != 3 ) {
    *status = SMF__WDIM;
    msgSeti("NDIMS",data->ndims);
    errRep( "", FUNC_NAME
           ": Don't know how to handle ^NDIMS dimensions, should be 3.",
            status);
    return waschanged;
  }

  /* We shouldn't be trying to change the order of FFT'd data */
  if( smf_isfft( data, NULL, NULL, NULL, NULL, NULL, status ) ) {
    *status = SAI__ERROR;
    errRep( "", FUNC_NAME
            ": Possible programming error, attempting to re-order FFT of a "
            "2D map!", status );
    return waschanged;
  }

  /* we are going to change */
  waschanged = 1;

  /* inPlace=1 if smfData was mapped! Free the old array if it was not
     stored in a file. */
  freeold = 1;
  if( data->file ){
     if (data->file->fd ){
        inPlace = 1;
        freeold = 0;

     /* Only change NDF values in-place if write access is abvaialble for
        the NDF. */
     } else if( data->file->ndfid ) {
        freeold = 0;
        ndfIsacc( data->file->ndfid, "WRITE", &writable, status );
        if( writable ) inPlace = 1;
     }
  }

  /* Calculate input data dimensions (before changing order) */
  smf_get_dims( data, NULL, NULL, &nbolo, &ntslice, &ndata, &bstr1, &tstr1,
                status);

  /* What will the dimensions/strides be in the newly-ordered array? */
  if( isTordered ) {
    newdims[0] = (data->dims)[1];
    newdims[1] = (data->dims)[2];
    newdims[2] = (data->dims)[0];
    newlbnd[0] = (data->lbnd)[1];
    newlbnd[1] = (data->lbnd)[2];
    newlbnd[2] = (data->lbnd)[0];
    bstr2 = 1;
    tstr2 = nbolo;
  } else {
    newdims[0] = (data->dims)[2];
    newdims[1] = (data->dims)[0];
    newdims[2] = (data->dims)[1];
    newlbnd[0] = (data->lbnd)[2];
    newlbnd[1] = (data->lbnd)[0];
    newlbnd[2] = (data->lbnd)[1];
    bstr2 = ntslice;
    tstr2 = 1;
  }

  /* Loop over elements of data->ptr and re-form arrays */
  for( i=0; i<2; i++ ) {
    data->pntr[i] = smf_dataOrder_array( wf, data->pntr[i], data->dtype,
                                         data->dtype, ndata,
                                         ntslice, nbolo, tstr1, bstr1, tstr2,
                                         bstr2, inPlace, freeold, status );
  }

  /* And Quality */
  data->qual = smf_dataOrder_array( wf, data->qual, SMF__QUALTYPE, SMF__QUALTYPE,
                                    ndata, ntslice, nbolo, tstr1, bstr1, tstr2,
                                    bstr2, inPlace, freeold, status );

  /* If NDF associated with data, modify dimensions of the data */
  if( data->file && (data->file->ndfid != NDF__NOID) ) {
    msgOutif(MSG__DEBUG, " ", FUNC_NAME
             ": Warning - current implementation does not modify NDF "
             "dimensions to match re-ordered data array", status);
  }

  /* If there is a LUT re-order it here */
  data->lut = smf_dataOrder_array( wf, data->lut, SMF__INTEGER, SMF__INTEGER, ndata,
                                   ntslice, nbolo, tstr1, bstr1, tstr2, bstr2,
                                   inPlace, 1, status );

  /* Set the new dimensions in the smfData */
  if( *status == SAI__OK ) {
    memcpy( data->dims, newdims, 3*sizeof(*newdims) );
    memcpy( data->lbnd, newlbnd, 3*sizeof(*newlbnd) );
    data->isTordered = isTordered;
  }

  /* Force any external quality to same ordering */
  if (data->sidequal) {
    int qchanged = 0;
    qchanged = smf_dataOrder( wf, data->sidequal, isTordered, status );
    /* and indicate if we changed anything (but not if we did not) */
    if (qchanged) waschanged = qchanged;
  }

  /* Re-order the axes in the time-series WCS FrameSet */
  if( data->hdr && data->hdr->tswcs ) {
    smf_tswcsOrder( &(data->hdr->tswcs), isTordered, status );
  }

  /* If the re-ordering was not done in-place, then the new buffer must
     have been allocated here. Set a flag so that smf_close_file knows to
     deallocate the memory. */
  if( ! inPlace ) data->isdyn = 1;

  return waschanged;
}
예제 #3
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;

}