void GaussSmoother::trim_weights_by_frac_max(float frac ) { assert(frac < 1.0f); int first_keep, last_keep; first_keep = last_keep = -1; float weights_max = crawutils::max_vect(this->weights); float thresh = weights_max * frac; for ( size_t i = 0 ; i < this->weights.size() ; i++ ) { if ( fabs(weights[i]) >= thresh ) { first_keep = (int)i; break; } } for ( size_t i = weights.size() - 1; i>= first_keep ; i-- ) { if ( fabs(weights[i]) >= thresh ) { last_keep = (int)i; break; } } assert( first_keep > -1 && last_keep >= first_keep); std::vector<float> new_weights(last_keep - first_keep + 1); for ( int i = 0 ; i < (int)new_weights.size() ; i++ ) { new_weights[i] = weights[first_keep+i]; } this->set_weight_size((int)new_weights.size()); this->set_weights(new_weights); }
static fz_weights * make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip) { fz_weights *weights; float F, G; float window; int j; if (dst_w < src_w) { /* Scaling down */ F = dst_w / src_w; G = 1; } else { /* Scaling up */ F = 1; G = src_w / dst_w; } window = filter->width / F; DBUG(("make_weights src_w=%d x=%g dst_w=%g patch_l=%d patch_r=%d F=%g window=%g\n", src_w, x, dst_w, patch_l, patch_r, F, window)); weights = new_weights(ctx, filter, src_w, dst_w, patch_r-patch_l, n, flip, patch_l); if (!weights) return NULL; for (j = patch_l; j < patch_r; j++) { /* find the position of the centre of dst[j] in src space */ float centre = (j - x + 0.5f)*src_w/dst_w - 0.5f; int l, r; l = ceilf(centre - window); r = floorf(centre + window); DBUG(("%d: centre=%g l=%d r=%d\n", j, centre, l, r)); init_weights(weights, j); for (; l <= r; l++) { add_weight(weights, j, l, filter, x, F, G, src_w, dst_w); } check_weights(weights, j, dst_w_int, x, dst_w); if (vertical) { reorder_weights(weights, j, src_w); } } weights->count++; /* weights->count = dst_w_int now */ return weights; }
static fz_weights * make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip, fz_scale_cache *cache) { fz_weights *weights; float F, G; float window; int j; if (cache) { if (cache->src_w == src_w && cache->x == x && cache->dst_w == dst_w && cache->filter == filter && cache->vertical == vertical && cache->dst_w_int == dst_w_int && cache->patch_l == patch_l && cache->patch_r == patch_r && cache->n == n && cache->flip == flip) { return cache->weights; } cache->src_w = src_w; cache->x = x; cache->dst_w = dst_w; cache->filter = filter; cache->vertical = vertical; cache->dst_w_int = dst_w_int; cache->patch_l = patch_l; cache->patch_r = patch_r; cache->n = n; cache->flip = flip; fz_free(ctx, cache->weights); cache->weights = NULL; } if (dst_w < src_w) { /* Scaling down */ F = dst_w / src_w; G = 1; } else { /* Scaling up */ F = 1; G = src_w / dst_w; } window = filter->width / F; weights = new_weights(ctx, filter, src_w, dst_w, patch_r-patch_l, n, flip, patch_l); if (!weights) return NULL; for (j = patch_l; j < patch_r; j++) { /* find the position of the centre of dst[j] in src space */ float centre = (j - x + 0.5f)*src_w/dst_w - 0.5f; int l, r; l = ceilf(centre - window); r = floorf(centre + window); init_weights(weights, j); for (; l <= r; l++) { add_weight(weights, j, l, filter, x, F, G, src_w, dst_w); } check_weights(weights, j, dst_w_int, x, dst_w); if (vertical) { reorder_weights(weights, j, src_w); } } weights->count++; /* weights->count = dst_w_int now */ if (cache) { cache->weights = weights; } return weights; }
int main(int argc, char *argv[]) { Cmdline *cmd; struct psrfits pfi, pfo; // input and output struct subband_info si; int stat=0, padding=0, userN=0; // Call usage() if we have no command line arguments if (argc == 1) { Program = argv[0]; usage(); exit(0); } // Parse the command line using the excellent program Clig cmd = parseCmdline(argc, argv); // Open the input PSRFITs files psrfits_set_files(&pfi, cmd->argc, cmd->argv); // Use the dynamic filename allocation if (pfi.numfiles==0) pfi.filenum = cmd->startfile; pfi.tot_rows = pfi.N = pfi.T = pfi.status = 0; int rv = psrfits_open(&pfi); if (rv) { fits_report_error(stderr, rv); exit(1); } // Read the user weights if requested si.userwgts = NULL; if (cmd->wgtsfileP) { read_weights(cmd->wgtsfile, &userN, &si.userwgts); if (userN != pfi.hdr.nchan) { printf("Error!: Input data has %d channels, but '%s' contains only %d weights!\n", pfi.hdr.nchan, cmd->wgtsfile, userN); exit(0); } printf("Overriding input channel weights with those in '%s'\n", cmd->wgtsfile); } // Initialize the subbanding // (including reading the first row of data and // putting it in si->fbuffer) init_subbanding(&pfi, &pfo, &si, cmd); if (cmd->outputbasenameP) strcpy(pfo.basefilename, cmd->outputbasename); // Loop through the data do { // Put the overlapping parts from the next block into si->buffer float *ptr = pfi.sub.fdata + si.buflen * si.bufwid; if (padding==0) stat = psrfits_read_part_DATA(&pfi, si.max_overlap, si.numunsigned, ptr); if (stat || padding) { // Need to use padding since we ran out of data printf("Adding a missing row (#%d) of padding to the subbands.\n", pfi.tot_rows); // Now fill the last part of si->fbuffer with the chan_avgs so that // it acts like a correctly read block (or row) fill_chans_with_avgs(si.max_overlap, si.bufwid, ptr, si.chan_avgs); } //print_raw_chan_stats(pfi.sub.data, pfi.hdr.nsblk, // pfi.hdr.nchan, pfi.hdr.npol); // if the input data isn't 8 bit, unpack: if (pfi.hdr.nbits == 2) pf_unpack_2bit_to_8bit(&pfi, si.numunsigned); else if (pfi.hdr.nbits == 4) pf_unpack_4bit_to_8bit(&pfi, si.numunsigned); if ((pfo.hdr.ds_time_fact == 1) && (pfo.hdr.ds_freq_fact == 1)) { // No subbanding is needed, so just copy the float buffer // This is useful if we are just changing the number of bits // Could do it without a copy by simply exchanging pointers // to the fdata buffers in pfo and pfi... memcpy(pfo.sub.fdata, pfi.sub.fdata, pfi.hdr.nsblk * pfi.hdr.npol * pfi.hdr.nchan * sizeof(float)); } else { // Now create the subbanded row in the output buffer make_subbands(&pfi, &si); } // Output only Stokes I (in place via floats) if (pfo.hdr.onlyI && pfo.hdr.npol==4) get_stokes_I(&pfo); // Downsample in time (in place via floats) if (pfo.hdr.ds_time_fact > 1) downsample_time(&pfo); // Compute new scales and offsets so that we can pack // into 8-bits reliably if (pfo.rownum == 1) new_scales_and_offsets(&pfo, si.numunsigned, cmd); // Convert the floats back to bytes in the output array un_scale_and_offset_data(&pfo, si.numunsigned); //print_raw_chan_stats(pfo.sub.data, pfo.hdr.nsblk / pfo.hdr.ds_time_fact, // pfo.hdr.nchan / pfo.hdr.ds_freq_fact, pfo.hdr.npol); // pack into 2 or 4 bits if needed if (pfo.hdr.nbits == 2) pf_pack_8bit_to_2bit(&pfo, si.numunsigned); else if (pfo.hdr.nbits == 4) pf_pack_8bit_to_4bit(&pfo, si.numunsigned); // Write the new row to the output file pfo.sub.offs = (pfo.tot_rows+0.5) * pfo.sub.tsubint; psrfits_write_subint(&pfo); // Break out of the loop here if stat is set if (stat) break; // shift the last part of the current row into the "last-row" // part of the data buffer memcpy(si.fbuffer, si.fbuffer + si.buflen * si.bufwid, si.max_overlap * si.bufwid * sizeof(float)); // Read the next row (or padding) padding = get_current_row(&pfi, &si); // Set the new weights properly new_weights(&pfi, &pfo); } while (pfi.status == 0); print_clips(&pfo); rv = psrfits_close(&pfi); if (rv>100) { fits_report_error(stderr, rv); } rv = psrfits_close(&pfo); if (rv>100) { fits_report_error(stderr, rv); } exit(0); }
void init_subbanding(struct psrfits *pfi, struct psrfits *pfo, struct subband_info *si, Cmdline *cmd) { int ii, jj, kk, cindex; double lofreq, dtmp; // If -nsub is not set, do no subbanding if (!cmd->nsubP) cmd->nsub = pfi->hdr.nchan; // Don't change the number of output bits unless we explicitly ask to if (!cmd->outbitsP) cmd->outbits = pfi->hdr.nbits; si->nsub = cmd->nsub; si->nchan = pfi->hdr.nchan; si->npol = pfi->hdr.npol; si->numunsigned = si->npol; if (si->npol==4) { if (strncmp(pfi->hdr.poln_order, "AABBCRCI", 8)==0) si->numunsigned = 2; if (strncmp(pfi->hdr.poln_order, "IQUV", 4)==0) si->numunsigned = 1; } si->chan_per_sub = si->nchan / si->nsub; si->bufwid = si->nchan * si->npol; // Freq * polns si->buflen = pfi->hdr.nsblk; // Number of spectra in each row // Check the downsampling factor in time if (si->buflen % cmd->dstime) { fprintf(stderr, "Error!: %d spectra per row is not evenly divisible by -dstime of %d!\n", si->buflen, cmd->dstime); exit(1); } // Check the downsampling factor in frequency if (si->nchan % si->nsub) { fprintf(stderr, "Error! %d channels is not evenly divisible by %d subbands!\n", si->nchan, si->nsub); exit(1); } si->dm = cmd->dm; si->sub_df = pfi->hdr.df * si->chan_per_sub; si->sub_freqs = (float *)malloc(sizeof(float) * si->nsub); si->chan_delays = (double *)malloc(sizeof(double) * si->nchan); si->sub_delays = (double *)malloc(sizeof(double) * si->nsub); si->idelays = (int *)malloc(sizeof(int) * si->nchan); si->weights = (float *)malloc(sizeof(float) * si->nsub); si->offsets = (float *)malloc(sizeof(float) * si->nsub * si->npol); si->scales = (float *)malloc(sizeof(float) * si->nsub * si->npol); si->chan_avgs = (float *)malloc(sizeof(float) * si->bufwid); si->chan_stds = (float *)malloc(sizeof(float) * si->bufwid); /* Alloc data buffers for the input PSRFITS file */ pfi->sub.dat_freqs = (float *)malloc(sizeof(float) * pfi->hdr.nchan); pfi->sub.dat_weights = (float *)malloc(sizeof(float) * pfi->hdr.nchan); pfi->sub.dat_offsets = (float *)malloc(sizeof(float) * pfi->hdr.nchan * pfi->hdr.npol); pfi->sub.dat_scales = (float *)malloc(sizeof(float) * pfi->hdr.nchan * pfi->hdr.npol); pfi->sub.rawdata = (unsigned char *)malloc(pfi->sub.bytes_per_subint); if (pfi->hdr.nbits!=8) { pfi->sub.data = (unsigned char *)malloc(pfi->sub.bytes_per_subint * (8 / pfi->hdr.nbits)); } else { pfi->sub.data = pfi->sub.rawdata; } // Read the first row of data psrfits_read_subint(pfi); if (si->userwgts) // Always overwrite if using user weights memcpy(pfi->sub.dat_weights, si->userwgts, pfi->hdr.nchan * sizeof(float)); // Reset the read counters since we'll re-read pfi->rownum--; pfi->tot_rows--; pfi->N -= pfi->hdr.nsblk; // Compute the subband properties, DM delays and offsets lofreq = pfi->sub.dat_freqs[0] - pfi->hdr.df * 0.5; for (ii = 0, cindex = 0 ; ii < si->nsub ; ii++) { dtmp = lofreq + ((double)ii + 0.5) * si->sub_df; si->sub_freqs[ii] = dtmp; si->sub_delays[ii] = delay_from_dm(si->dm, dtmp); // Determine the dispersion delays and convert them // to offsets in units of sample times for (jj = 0 ; jj < si->chan_per_sub ; jj++, cindex++) { si->chan_delays[cindex] = delay_from_dm(si->dm, pfi->sub.dat_freqs[cindex]); si->chan_delays[cindex] -= si->sub_delays[ii]; si->idelays[cindex] = (int)rint(si->chan_delays[cindex] / pfi->hdr.dt); } } // Now determine the earliest and latest delays si->max_early = si->max_late = 0; for (ii = 0 ; ii < si->nchan ; ii++) { if (si->idelays[ii] < si->max_early) si->max_early = si->idelays[ii]; if (si->idelays[ii] > si->max_late) si->max_late = si->idelays[ii]; } si->max_overlap = abs(si->max_early) + si->max_late; // This buffer will hold the float-converted input data, plus the bits // of data from the previous and next blocks si->fbuffer = (float *)calloc((si->buflen + 2 * si->max_overlap) * si->bufwid, sizeof(float)); // The input data will be stored directly in the buffer space // So the following is really just an offset into the bigger buffer pfi->sub.fdata = si->fbuffer + si->max_overlap * si->bufwid; // Now start setting values for the output arrays *pfo = *pfi; // We are changing the number of bits in the data if (pfi->hdr.nbits != cmd->outbits) pfo->hdr.nbits = cmd->outbits; // Determine the length of the outputfiles to use if (cmd->filetimeP) { pfo->rows_per_file = 10 * \ (int) rint(0.1 * (cmd->filetime / pfi->sub.tsubint)); } else if (cmd->filelenP) { long long filelen; int bytes_per_subint; filelen = cmd->filelen * (1L<<30); // In GB bytes_per_subint = (pfo->hdr.nbits * pfo->hdr.nchan * pfo->hdr.npol * pfo->hdr.nsblk) / \ (8 * si->chan_per_sub * cmd->dstime * (cmd->onlyIP ? 4 : 1)); pfo->rows_per_file = filelen / bytes_per_subint; pfo->sub.bytes_per_subint = bytes_per_subint; } else { // By default, keep the filesize roughly constant pfo->rows_per_file = pfi->rows_per_file * si->chan_per_sub * cmd->dstime * (cmd->onlyIP ? 4 : 1) * pfi->hdr.nbits / pfo->hdr.nbits; } pfo->filenum = 0; // This causes the output files to be created pfo->filename[0] = '\0'; pfo->rownum = 1; pfo->tot_rows = 0; pfo->N = 0; // Set the "orig" values to those of the input file pfo->hdr.orig_nchan = pfi->hdr.nchan; pfo->hdr.orig_df = pfi->hdr.df; { char *inpath, *infile; split_path_file(pfi->basefilename, &inpath, &infile); sprintf(pfo->basefilename, "%s_subs", infile); free(inpath); free(infile); } // Reset different params pfo->sub.dat_freqs = si->sub_freqs; pfo->sub.dat_weights = si->weights; pfo->sub.dat_offsets = si->offsets; pfo->sub.dat_scales = si->scales; pfo->hdr.ds_freq_fact = si->chan_per_sub; pfo->hdr.ds_time_fact = cmd->dstime; pfo->hdr.onlyI = cmd->onlyIP; pfo->hdr.chan_dm = si->dm; pfo->sub.rawdata = (unsigned char *)malloc(si->nsub * si->npol * si->buflen); if (pfo->hdr.nbits!=8) { pfo->sub.data = (unsigned char *)malloc(si->nsub * si->npol * si->buflen * (8 / pfo->hdr.nbits)); } else { pfo->sub.data = pfo->sub.rawdata; } si->outfbuffer = (float *)calloc(si->nsub * si->npol * si->buflen, sizeof(float)); pfo->sub.fdata = si->outfbuffer; // Now re-read the first row (i.e. for "real" this time) get_current_row(pfi, si); // Set the new weights properly new_weights(pfi, pfo); // Now fill the first part of si->fbuffer with the chan_avgs so that // it acts like a previously read block (or row) fill_chans_with_avgs(si->max_overlap, si->bufwid, si->fbuffer, si->chan_avgs); }