ISCE_INSAR/contrib/alos2proc/src/mbf.c

599 lines
19 KiB
C

//////////////////////////////////////
// Cunren Liang, NASA JPL/Caltech
// Copyright 2017
//////////////////////////////////////
#include "resamp.h"
#include <fftw3.h>
int mbf(char *inputfile, char *outputfile, int nrg, float prf, float prf_frac, float nb, float nbg, float nboff, float bsl, float *kacoeff, float *dopcoeff1, float *dopcoeff2){
/*
inputfile: input file
outputfile: output file
nrg: file width
prf: PRF
prf_frac: fraction of PRF processed
(represents azimuth bandwidth)
nb: number of lines in a burst
(float, in terms of 1/PRF)
nbg: number of lines in a burst gap
(float, in terms of 1/PRF)
nboff: number of unsynchronized lines in a burst
(float, in terms of 1/PRF, with sign, see burst_sync.py for rules of sign)
(the image to be processed is always considered to be master)
bsl: start line number of a burst
(float, the line number of the first line of the full-aperture SLC is zero)
(no need to be first burst, any one is OK)
kacoeff[0-2]: FM rate coefficients
(three coefficients of a quadratic polynomial with regard to)
(range sample number. range sample number starts with zero)
dopcoeff1[0-3]: Doppler centroid frequency coefficients of this image
(four coefficients of a third order polynomial with regard to)
(range sample number. range sample number starts with zero)
dopcoeff2[0-3]: Doppler centroid frequency coefficients of the other image
(four coefficients of a third order polynomial with regard to)
(range sample number. range sample number starts with zero)
*/
FILE *infp;
FILE *outfp;
fcomplex **in; //data read in
fcomplex *out; //data written to output file
fcomplex *filter; //multi-band bandpass filter
fcomplex *filter_j;
fcomplex *deramp; //deramp signal
fcomplex *reramp; //reramp signal
fcomplex *data; //data to be filtered.
//int nrg; //file width
int naz; //file length
//float prf; //assume prf are the same
//float prf_frac; // azimuth processed bandwidth = prf_frac * prf
//float nb; //burst length in terms of pri. number of lines
//float nbg; //burst gap length in terms of pri. number of lines
float nbc; //burst cycle length in terms of pri. number of lines
//float nboff; //number of unsynchronized lines in a burst with sign
//see burst_sync.py for rules of sign.
//the image to be processed is always considered to be master
//and the other image is always considered to be slave
//float bsl; //burst start line, input float
//float kacoeff[3]; //FM rate along range (experessed by quadratic polynomial
//as a function of range sample number)
//float dopcoeff1[4]; //doppler centroid frequency along range (expressed by quadratic polynomial
//as a function of range sample number). this image
//float dopcoeff2[4]; //doppler centroid frequency along range (expressed by quadratic polynomial
//as a function of range sample number). the other image
//ATTENTION: MAKE RANGE NUMBER THE SAME ACCORDING RANGE OFFSET!!!
float pri; // 1.0/prf
float *ka;
float *dop1;
float *dop2;
float *nfa; //full aperture length in terms of pri. number of lines
float *freqs; //burst starting doppler centroid frequency
float *freqe; //burst ending doppler centroid frequency
float *bis; //burst imaged area start line numbers
float *bie; //burst imaged area ending line numbers
float *bic; //burst imaged area center line number, corresponding to the center of raw burst,
//rather than the actual center of imaged area
float *bica; //burst imaged area center line number, corresponding to the actual center of imaged area
float deramp_center; //line number where center frequency is zero Hz after deramping
float bis_min;
float bis_max;
float bie_min;
float bie_max;
int bis_out; //starting line number of the data block written out
int bie_out; //ending line number of the data block written out
int bis_in; //start line number of the data block read in
int bie_in; //ending line number of the data block read in
int bis_out2; //starting line number of the data block written out
int bie_out2; //ending line number of the data block written out
int bis_in2; //start line number of the data block read in
int bie_in2; //ending line number of the data block read in
float nb_new;
float nbg_new;
float nbc_new;
float bsl_new;
int nbc_new_int;
int nburst_new; //number of bursts in a burst cycle
float bfw; //bandwidth of burst in Hz
float bfc; //center frequency of burst in Hz
int nfft; //fft length
int nfilter; //filter length, MUST BE ODD
int hnfilter; //half filter length
int edgl; //number of lines on the starting and ending edges
float beta; //kaiser window beta
float sc; //constant to scale the data read in to avoid large values
//during fft and ifft
int edgl_flag; //flag to indicate how many lines to keep on the starting and ending edges
//0: do not remove data on the edges
//1: remove data less than half convolution
//2: remove all data of incomplete convolution
int deramp_center_flag; //flag to indicate the location with zero center frequency after
//deramping
//0: center (raw burst center) of the burst whose ending/start line number is used
//1: center of the burst cycle being processed
//2: center (raw burst center) of the center burst in the burst cycle being processed
float tmp1, tmp2, tmp3;
int i, j, k;
fftwf_plan p_forward;
fftwf_plan p_backward;
fftwf_plan p_forward_filter;
/*****************************************************************************/
//I just put these parametes which can be set here. These can also be set via
//arguments before running the programs if modifying the code to accept these
//arguments.
beta = 1.0;
nfilter = 257; //MUST BE ODD
sc = 10000.0;
edgl_flag = 0;
deramp_center_flag = 0;
/*****************************************************************************/
//open files
infp = openfile(inputfile, "rb");
outfp = openfile(outputfile, "wb");
printf("\n\ninput parameters:\n");
printf("input file: %s\n", inputfile);
printf("output file: %s\n", outputfile);
printf("nrg: %d\n", nrg);
printf("prf: %f\n", prf);
printf("prf_frac: %f\n", prf_frac);
printf("nb: %f\n", nb);
printf("nbg: %f\n", nbg);
printf("nboff: %f\n", nboff);
printf("bsl: %f\n", bsl);
printf("kacoeff: %f, %f, %f\n", kacoeff[0], kacoeff[1], kacoeff[2]);
printf("dopcoeff1: %f, %f, %f, %f\n", dopcoeff1[0], dopcoeff1[1], dopcoeff1[2], dopcoeff1[3]);
printf("dopcoeff2: %f, %f, %f, %f\n", dopcoeff2[0], dopcoeff2[1], dopcoeff2[2], dopcoeff2[3]);
if(nfilter % 2 != 1){
fprintf(stderr, "filter length must be odd!\n");
exit(1);
}
naz = file_length(infp, nrg, sizeof(fcomplex));
printf("file width: %d, file length: %d\n\n", nrg, naz);
ka = array1d_float(nrg);
dop1 = array1d_float(nrg);
dop2 = array1d_float(nrg);
nfa = array1d_float(nrg);
freqs = array1d_float(nrg);
freqe = array1d_float(nrg);
bis = array1d_float(nrg);
bie = array1d_float(nrg);
bic = array1d_float(nrg);
bica = array1d_float(nrg);
in = array2d_fcomplex(naz, nrg);
out = array1d_fcomplex(naz);
pri = 1.0/prf;
nbc = nb + nbg;
hnfilter = (nfilter - 1) / 2;
//find burst starting line closest to first line and after first line
for(i = -100000; i < 100000; i++){
tmp1 = bsl + (nb + nbg) * i;
if(tmp1 >= 0){
bsl = tmp1;
break;
}
}
//calculate something
for(i = 0; i < nrg; i++){
//azimuth FM rate. we follow the convention ka > 0
ka[i] = kacoeff[2] * i * i + kacoeff[1] * i + kacoeff[0];
ka[i] = -ka[i];
//doppler centroid frequency
dop1[i] = dopcoeff1[0] + dopcoeff1[1] * i + dopcoeff1[2] * i * i + dopcoeff1[3] * i * i * i;
dop1[i] *= prf;
dop2[i] = dopcoeff2[0] + dopcoeff2[1] * i + dopcoeff2[2] * i * i + dopcoeff2[3] * i * i * i;
dop2[i] *= prf;
//full aperture length
nfa[i] = prf * prf_frac / ka[i] / pri;
//consider burst synchronization
//these are the same for all columns
if(fabs(nboff) >= 0.8 * nb){
fprintf(stderr, "burst synchronization is too small!\n\n");
exit(1);
}
if(nboff < 0){
bsl_new = bsl - nboff;
}
else{
bsl_new = bsl;
}
nb_new = nb - fabs(nboff);
nbg_new = nbg + fabs(nboff);
nbc_new = nbc;
nbc_new_int = (int)(nbc_new + 0.5);
//starting and ending doppler centroid frequency of the burst
//if the overall doppler centroid frequency = 0
freqs[i] = -(prf * prf_frac - nb_new * pri * ka[i]) / 2.0;
freqe[i] = (prf * prf_frac - nb_new * pri * ka[i]) / 2.0;
//consider doppler centroid frequency
freqs[i] += dop1[i];
freqe[i] += dop1[i];
//consider doppler centroid frequency of the other image
tmp1 = dop2[i] - dop1[i];
if(tmp1 > 0){
freqs[i] += tmp1;
}
else{
freqe[i] += tmp1;
}
//check if doppler centroid frequency difference too big
if(freqe[i] - freqs[i] < nbc_new * pri * ka[i]){
fprintf(stderr, "Doppler centroid frequency difference too large!\n\n");
exit(1);
}
//starting and ending index of imaged area by the burst
bic[i] = bsl_new + (nb_new - 1.0) / 2.0; //this should be the same for all columns
bis[i] = freqs[i] / ka[i] / pri + bic[i];
bie[i] = freqe[i] / ka[i] / pri + bic[i];
bica[i] = (bis[i] + bie[i]) / 2.0;
}
//find the max and min of starting and ending index
bis_min = bis[0];
bis_max = bis[0];
bie_min = bie[0];
bie_max = bie[0];
for(i = 0; i < nrg; i++){
if(bis[i] < bis_min){
bis_min = bis[i];
}
if(bis[i] > bis_max){
bis_max = bis[i];
}
if(bie[i] < bie_min){
bie_min = bie[i];
}
if(bie[i] > bie_max){
bie_max = bie[i];
}
}
//read in data
readdata((fcomplex *)in[0], (size_t)naz * (size_t)nrg * sizeof(fcomplex), infp);
//initialize output data
//for(j = 0; j < naz; j++){
// for(k = 0; k < nrg; k++){
// out[j][k].re = 0.0;
// out[j][k].im = 0.0;
// }
//}
for(i = 0; i < nrg; i++){
if((i + 1) % 100 == 0 || (i+1) == nrg)
fprintf(stderr,"processing: %6d of %6d\r", i+1, nrg);
if((i+1) == nrg)
fprintf(stderr,"\n");
//initialize output data
memset((void *)out, 0, (size_t)naz*sizeof(fcomplex));
//initialize start and ending line number
if(dop1[i] > dop2[i]){
bis_out = roundfi(bie[i]) + 1;
//bie_out = roundfi(bie[i]) + 1 + (nbc_new - 1);
//changed to use nbc_new_int. 27-JAN-2015
bie_out = roundfi(bie[i]) + 1 + (nbc_new_int - 1);
}
else{
bis_out = roundfi(bis[i]);
//bie_out = roundfi(bis[i]) + (nbc_new - 1);
//changed to use nbc_new_int. 27-JAN-2015
bie_out = roundfi(bis[i]) + (nbc_new_int - 1);
}
//consider the filter length
bis_in = bis_out - (nfilter - 1) / 2;
bie_in = bie_out + (nfilter - 1) / 2;
//to make circular convolution equivalent to linear convolution
nfft = next_pow2(bie_in - bis_in + 1 + nfilter - 1);
//initialize filter
filter = array1d_fcomplex(nfft);
filter_j = array1d_fcomplex(nfft);
//create plans before initializing data, because FFTW_MEASURE overwrites the in/out arrays.
p_forward_filter = fftwf_plan_dft_1d(nfft, (fftwf_complex*)filter, (fftwf_complex*)filter, FFTW_FORWARD, FFTW_ESTIMATE);
//for(j = 0; j < nfft; j++){
// filter[j].re = 0.0;
// filter[j].im = 0.0;
//}
//initialize output data
memset((void *)filter, 0, (size_t)nfft*sizeof(fcomplex));
nburst_new = (int)ceil( fabs(freqe[i]-freqs[i]) / (nbc_new * pri * ka[i]) );
//choose deramp center
if(dop1[i] > dop2[i]){
if(deramp_center_flag == 0){
deramp_center = bic[i];
}
else if(deramp_center_flag == 1){
deramp_center = (bica[i] + nbc_new);
}
else{
deramp_center = bic[i] + (int)((nburst_new+1) / 2) * nbc_new;
}
}
else{
if(deramp_center_flag == 0){
deramp_center = bic[i];
}
else if(deramp_center_flag == 1){
deramp_center = bica[i];
}
else{
deramp_center = bic[i] + (int)(nburst_new / 2) * nbc_new;
}
}
//create filters
for(j = 0; j <= nburst_new; j++){
//center frequency of bandpass filter
//determined by distance of raw burst center and deramp center
if(dop1[i] > dop2[i]){
bfc = (deramp_center - (bic[i] + j*nbc_new)) * pri * ka[i];
//do not include first burst in this case
if(j == 0){
continue;
}
}
else{
bfc = (deramp_center - (bic[i] - j*nbc_new)) * pri * ka[i];
//do not include last burst in this case
if(j == nburst_new){
break;
}
}
//bandwidth of bandpass filter
bfw = nb_new * pri * ka[i];
//create filter: first sample corresponding to first fully convolution sample
bandpass_filter(bfw/prf, bfc/prf, nfilter, nfft, nfilter-1, beta, filter_j);
//add the filters to form the filter to be used
for(k = 0; k < nfft; k++){
filter[k].re += filter_j[k].re;
filter[k].im += filter_j[k].im;
}
}
//forward fft
//four1((float *)filter - 1, nfft, -1);
fftwf_execute(p_forward_filter);
//create deramp signal: this applies no matter whether dop1[i] is larger,
//and no matter bic is on the left or right.
deramp = array1d_fcomplex(nfft);
for(j = 0; j < nfft; j++){
//distance between fft center and deramp center
//tmp1 = bis_in + (nfft - 1.0) / 2.0 - bic[i];
tmp1 = bis_in + (nfft - 1.0) / 2.0 - deramp_center;
//if(tmp1 <= 0){
// fprintf(stderr, "WARNING: very large doppler centroid frequnecy\n\n");
//}
//index used in deramp signal
tmp2 = j - (nfft - 1.0) / 2.0 + tmp1;
//deramp signal
tmp3 = - PI * ka[i] * (tmp2 * pri) * (tmp2 * pri);
deramp[j].re = cos(tmp3);
deramp[j].im = sin(tmp3);
}
//rereamp signal
reramp = array1d_fcomplex(nfft);
for(j = 0; j < nfft; j++){
reramp[j].re = deramp[j].re;
reramp[j].im = -deramp[j].im;
}
//circ_shift(reramp, nfft, -abs(nfilter-1));
circ_shift(reramp, nfft, -abs( (nfilter-1)/2 ));
/**********************************************/
/* do the filtering */
/**********************************************/
//filter the data
data = array1d_fcomplex(nfft);
//create plans before initializing data, because FFTW_MEASURE overwrites the in/out arrays.
p_forward = fftwf_plan_dft_1d(nfft, (fftwf_complex*)data, (fftwf_complex*)data, FFTW_FORWARD, FFTW_ESTIMATE);
p_backward = fftwf_plan_dft_1d(nfft, (fftwf_complex*)data, (fftwf_complex*)data, FFTW_BACKWARD, FFTW_ESTIMATE);
for(j = -10000; j < 10000; j++){
//bis_out2 = bis_out + j * nbc_new;
//bie_out2 = bie_out + j * nbc_new;
//bis_in2 = bis_in + j * nbc_new;
//bie_in2 = bie_in + j * nbc_new;
//changed to use nbc_new_int. 27-JAN-2015
bis_out2 = bis_out + j * nbc_new_int;
bie_out2 = bie_out + j * nbc_new_int;
bis_in2 = bis_in + j * nbc_new_int;
bie_in2 = bie_in + j * nbc_new_int;
//find data to be filtered
if(bie_in2 <= -1){
continue;
}
else if(bis_in2 >= naz){
break;
}
else{
//first zero the data
//for(k = 0; k < nfft; k++){
// data[k].re = 0.0;
// data[k].im = 0.0;
//}
memset((void *)data, 0, (size_t)nfft*sizeof(fcomplex));
//get data
for(k = bis_in2; k <= bie_in2; k++){
if(k <= -1 || k >= naz){
data[k-bis_in2].re = 0.0;
data[k-bis_in2].im = 0.0;
}
else{
data[k-bis_in2].re = in[k][i].re / sc;
data[k-bis_in2].im = in[k][i].im / sc;
}
}
}
//deramp the data
#pragma omp parallel for private(k) shared(nfft, data, deramp)
for(k = 0; k < nfft; k++){
data[k] = cmul(data[k], deramp[k]);
}
//forward fft
//four1((float *)data - 1, nfft, -1);
fftwf_execute(p_forward);
//multiplication in the frequency domain
#pragma omp parallel for private(k) shared(nfft, data, filter)
for(k = 0; k < nfft; k++)
data[k] = cmul(data[k], filter[k]);
//backward fft
//four1((float *)data - 1, nfft, 1);
fftwf_execute(p_backward);
//reramp
#pragma omp parallel for private(k) shared(nfft, data, reramp)
for(k = 0; k < nfft; k++){
data[k] = cmul(data[k], reramp[k]);
}
//get the filtered data
for(k = bis_out2; k <= bie_out2; k++){
if(edgl_flag == 0){ //do not remove data on the edges
edgl = 0;
}
else if(edgl_flag == 1){ //remove data less than half convolution
edgl = (nfft - 1) / 2;
}
else{ //remove data of incomplete convolution
edgl = nfft - 1;
}
if((k >= (0+edgl)) && (k <= naz-1-edgl)){
out[k].re = data[k-bis_out2].re * sc / nfft;
out[k].im = data[k-bis_out2].im * sc / nfft;
}
}
}//j: block of data of each column
fftwf_destroy_plan(p_forward);
fftwf_destroy_plan(p_backward);
fftwf_destroy_plan(p_forward_filter);
free_array1d_fcomplex(filter);
free_array1d_fcomplex(filter_j);
free_array1d_fcomplex(deramp);
free_array1d_fcomplex(reramp);
free_array1d_fcomplex(data);
//overwrite original data
for(j = 0; j < naz; j++){
in[j][i].re = out[j].re;
in[j][i].im = out[j].im;
}
}//i: each column
writedata((fcomplex *)in[0], (size_t)naz * (size_t)nrg * sizeof(fcomplex), outfp);
//free arrays
free_array1d_float(ka);
free_array1d_float(dop1);
free_array1d_float(dop2);
free_array1d_float(nfa);
free_array1d_float(freqs);
free_array1d_float(freqe);
free_array1d_float(bis);
free_array1d_float(bie);
free_array1d_float(bic);
free_array1d_float(bica);
free_array2d_fcomplex(in);
free_array1d_fcomplex(out);
//close files
fclose(infp);
fclose(outfp);
return 0;
}//end main()
//////////////////////////////////////////////////////////////////////////////////////////////////////