/*Filters the given float array to the low "keepSamples" spectral components (low-pass filter). If keepSamples is small, the filter is strong (only lets the lowest freqencies by)*/ void filter_lowPass(float *arr,int fftLen,int keepSamples) { int i; /*Init.*/ complexFloat *fft=(complexFloat *)MALLOC(sizeof(complexFloat)*fftLen); cfft1d(fftLen,NULL,0); /*Copy arr into fft buffer.*/ for (i=0;i<fftLen;i++) { fft[i].real = arr[i]; fft[i].imag = 0; } cfft1d(fftLen,fft,-1);/*Forward FFT.*/ /*Filter out high frequencies.*/ for (i=1+keepSamples;i<fftLen-keepSamples;i++) { fft[i].real = 0; fft[i].imag = 0; } cfft1d(fftLen,fft,1);/*Reverse FFT.*/ /*Copy (smoothed) fft buffer back into arr.*/ for (i=0;i<fftLen;i++) arr[i]=Cabs(fft[i]); FREE(fft); }
void cfft(int n, float ream[], double *comm, int *info) { complex *xx, *com; com = (complex *) comm; xx = (complex *) ream; cfft1d(-1, n, xx, com, info); }
void fft_init(int n, float ream[], double *comm, int *info) { complex *xx, *com; /* Allocate communication work array */ // comm = (double *)malloc((5*n+100)*sizeof(double)); com = (complex *) comm; xx = (complex *) ream; /* Initialize communication work array */ cfft1d(0, n, xx, com, info); }
/*Return the average doppler centroid (in fractional PRF) of inFile using fftLen lines starting at startLine*/ double fftEstDop(getRec *inFile,int startLine,int xStride,int fftLen) { int x,y,i,wid=inFile->nSamples; float *power,peak; complexFloat *in,*fft; /*Allocate arrays.*/ in=(complexFloat *)MALLOC(sizeof(complexFloat)*fftLen*wid); fft=(complexFloat *)MALLOC(sizeof(complexFloat)*fftLen); power=(float *)MALLOC(sizeof(float)*fftLen); /*Set power sum to zero.*/ for (i=0;i<fftLen;i++) power[i]=0; /*Read in fftLen lines of data.*/ for (y=0;y<fftLen;y++) getSignalLine(inFile,startLine+y,&(in[y*wid]),0,wid); /*FFT each column, add to power sum array.*/ cfft1d(fftLen,NULL,0); for (x=0;x<wid;x+=xStride) { for (y=0;y<fftLen;y++) fft[y]=in[y*wid+x]; cfft1d(fftLen,fft,-1); for (i=0;i<fftLen;i++) power[i] += fft[i].real*fft[i].real + fft[i].imag*fft[i].imag; } /*Find peak of azimuth power array-- this is the center of the doppler.*/ power[0]=0.0;/*Zero out DC component (misleading).*/ filter_lowPass(power,fftLen,4);/*Do a low-pass on the power array.*/ peak=findPeak(power,fftLen); if (!quietflag) printf("Peak at %f\n",peak); FREE(in); FREE(fft); FREE(power); return peak/fftLen; }
/* processPatch: Performs all processing necessary on the given patch. Expects a fully prepared patch. - read in & range compress the data (rciq). - fft the data along azimuth. - range migrate the data (rmpatch). - azimuth compress the data (acpatch). the data is returned in the patch's trans array. */ void processPatch(patch *p,const getRec *signalGetRec,const rangeRef *r, const satellite *s) { int i; update_status("Range compressing"); if (!quietflag) printf(" RANGE COMPRESSING CHANNELS...\n"); elapse(0); rciq(p,signalGetRec,r); if (!quietflag) elapse(1); if (s->debugFlag & AZ_RAW_T) debugWritePatch(p,"az_raw_t"); update_status("Starting azimuth compression"); if (!quietflag) printf(" TRANSFORMING LINES...\n"); elapse(0); cfft1d(p->n_az,NULL,0); for (i=0; i<p->n_range; i++) cfft1d(p->n_az,&p->trans[i*p->n_az],-1); if (!quietflag) elapse(1); if (s->debugFlag & AZ_RAW_F) debugWritePatch(p,"az_raw_f"); if (!(s->debugFlag & NO_RCM)) { update_status("Range cell migration"); if (!quietflag) printf(" START RANGE MIGRATION CORRECTION...\n"); elapse(0); rmpatch(p,s); if (!quietflag) elapse(1); if (s->debugFlag & AZ_MIG_F) debugWritePatch(p,"az_mig_f"); } update_status("Finishing azimuth compression"); if (!quietflag) printf(" INVERSE TRANSFORMING LINES...\n"); elapse(0); acpatch(p,s); if (!quietflag) elapse(1); /* if (!quietflag) printf(" Range-Doppler done...\n");*/ }
void sgifftcall(fcomplex * indata, long nn, int isign) { int expon; double fracpart; static complex *coeff[30]; /* Determine the twoth power of the length of the data */ fracpart = frexp((double) nn, &expon); expon--; /* If we are calling using an nn we haven't seen before */ if (coeff[expon] == NULL) { /* Allocate coefficient array */ coeff[expon] = cfft1di(nn, NULL); } /* Do the FFT */ cfft1d(isign, nn, (complex *) indata, 1, coeff[expon]); }
int main(int argc,char **argv) { int lines,samps; /* Number of image lines and samples */ int fftLen,start_line; /* FFT length, & line to start processing at*/ int x,y,i,k; /* Counters */ int f_lo1,f_lo2,f_hi1,f_hi2; /* Filter frequency indicies */ int chunk_size,chunk_int; /* Size of current datablock, & temp value*/ int last_chunk; /* Size of the last chunk */ int compensate_for_last_chunk=1; /* If last chunk = 0 dont loop for last chunk*/ char *inName, *parmName, *outName; /* Input filename */ float filtStart[2], filtEnd[2]; /* Filter start and stop variables */ float df, stop; /* Delta and counter variables */ complexFloat *inBuf,*outBuf; /* Input/Output Image Buffers */ complexFloat *fftBuf; /* FFT Buffer for the image */ float *ampBuf,*phsBuf; /* Amplitude and Phase Buffers */ float *time_vector,A,B,shift; /* Time vector, & freq modulation shift vars*/ float chunk_float; /* Temporary value */ FILE *inF, *freqF, *outF1; /* Input and Output file pointers */ float cur_time, f_s; /* Current time to increment the time vector by */ meta_parameters *inMeta, *outMeta; /* Meta info about the images */ /* Usage is shown if the user doesn't give 3 arguements */ if(argc!=4) { usage(argv[0]); } StartWatch(); printf("Program cpx_filter\n"); /* Get the filename and filter start and end frequencies from the command line*/ inName=argv[1]; if(findExt(inName)==NULL) inName = appendExt(argv[1],".cpx"); outName=argv[2]; parmName=argv[3]; /* Get input metadata. Make sure data_type is complex */ inMeta = meta_read(inName); if (inMeta->general->data_type < COMPLEX_BYTE) { switch (inMeta->general->data_type) { case ASF_BYTE: inMeta->general->data_type=COMPLEX_BYTE; break; case INTEGER16: inMeta->general->data_type=COMPLEX_INTEGER16; break; case INTEGER32: inMeta->general->data_type=COMPLEX_INTEGER32; break; case REAL32: inMeta->general->data_type=COMPLEX_REAL32; break; case REAL64: inMeta->general->data_type=COMPLEX_REAL64; break; } meta_write (inMeta, inName); } /* Open the frequency parameter file and read the parameters */ if((freqF=FOPEN(parmName,"r"))==NULL) { printf("Frequency Parameter File %s could not be Opened!\n",parmName); exit(EXIT_FAILURE); } fscanf(freqF,"%f\n",&f_s); fscanf(freqF,"%f\n",&shift); fscanf(freqF,"%f %f\n", &filtStart[0], &filtEnd[0]); fscanf(freqF,"%f %f\n", &filtStart[1], &filtEnd[1]); printf("\n"); printf("Input file is %s\n",inName); printf("Output file is %s.cpx\n",outName); printf("Parameter file is %s\n",parmName); printf("Filtering from frequencies %.2f to %.2f Hz and %.2f to %.2f in Azimuth\n",filtStart[0],filtEnd[0],filtStart[1],filtEnd[1]); printf("The sampling frequency is %f Hz\n",f_s); printf("Shifting the spectrum by %.2f Hz\n",shift); /* Get the number of lines and samples from the input meta file */ lines = inMeta->general->line_count; samps = inMeta->general->sample_count; chunk_size = BLOCK_SIZE; chunk_float = (float)lines/chunk_size; chunk_int = lines/chunk_size; last_chunk = (int)((chunk_float-(float)chunk_int) * (float)BLOCK_SIZE + 0.5); if( (2*TOSS_SIZE) > last_chunk) compensate_for_last_chunk=0; printf("Chunk Size is set to %d, the last chunk is %d lines\n", chunk_size, last_chunk); /* Compute the FFT length based on the number of lines. Must be a power of 2 */ i = (log10(chunk_size)/log10(2)) + 1; fftLen = pow(2,i); printf("FFT Length is %d\n",fftLen); cfft1d(fftLen,NULL,0); printf("The Input Image has %d lines and %d samples\n",lines,samps); /* Allocate the memory for all the buffers */ inBuf = (complexFloat *)MALLOC(sizeof(complexFloat)*samps*fftLen); outBuf = (complexFloat *)MALLOC(sizeof(complexFloat)*samps*fftLen); fftBuf = (complexFloat *)MALLOC(sizeof(complexFloat)*fftLen); ampBuf = (float *)MALLOC(sizeof(float)*fftLen); phsBuf = (float *)MALLOC(sizeof(float)*fftLen); time_vector = (float *)MALLOC(sizeof(float)*lines); /* Open the Complex Image File */ if((inF=FOPEN(inName,"rb"))==NULL) { printf("Complex Image file %s could not be opened\n",inName); exit(EXIT_FAILURE); } strcat(outName,".cpx"); if((outF1=FOPEN(outName,"wb"))==NULL) { printf("Unable to write output %s\n",outName); exit(EXIT_FAILURE); } outMeta = meta_copy(inMeta); outMeta->general->line_count = chunk_int*(BLOCK_SIZE-2*TOSS_SIZE)+(last_chunk-2*TOSS_SIZE); outMeta->general->sample_count = samps; meta_write(outMeta, outName); /* Find the filter frequency index values */ df = f_s/fftLen; stop = 0; i = 0; while(stop<filtStart[0]) { f_lo1 = i; stop = df*i; i++; } stop = 0; i = 0; while(stop<filtStart[1]) { f_lo2=i; stop=df*i; i++; } i = fftLen; stop = df*i; while(stop>filtEnd[0]) { f_hi1 = i; stop = df*i; i--; } i = fftLen; stop = df*i; while(stop>filtEnd[1]) { f_hi2 = i; stop = df*i; i--; } /* Zero out all the arrays and begin processing data */ cur_time = 0; for(i=0; i<fftLen; i++) { ampBuf[i] = 0; phsBuf[i] = 0; } for(k=0; k<chunk_int+compensate_for_last_chunk; k++) { printf("\nProcessing Chunk %d of %d\n",k,lines/chunk_size); start_line = (k==0) ? 0 : (k*chunk_size)-(2*TOSS_SIZE); if (k==chunk_int) chunk_size=last_chunk; cur_time=start_line*(1/f_s); /* Read in the data chunk & put in proper endian order */ printf("Reading %d Lines Starting at Line %d\n",chunk_size,start_line); get_complexFloat_lines(inF, inMeta, start_line, chunk_size, inBuf); /* Process the each column */ printf("Performing the FFT and Filtering Operations\n"); for(x=0; x<samps; x++) { if(x%1000 == 0) printf("Processing Column %d\n",x); for(y=0;y<fftLen;y++) { fftBuf[y].real = 0; fftBuf[y].imag = 0; } for(y=0;y<chunk_size;y++) { fftBuf[y].real = inBuf[y*samps+x].real; fftBuf[y].imag = inBuf[y*samps+x].imag; } cfft1d(fftLen,fftBuf,-1); for (i=0; i<fftLen; i++) { ampBuf[i] = sqrt(fftBuf[i].real*fftBuf[i].real + fftBuf[i].imag*fftBuf[i].imag); if(fftBuf[i].imag!=0.0 || fftBuf[i].real!=0.0) phsBuf[i] = atan2(fftBuf[i].imag,fftBuf[i].real); else phsBuf[i] = 0; if(((i>f_lo1)&&(i<f_hi1)) || ((i>f_lo2) && (i<f_hi2))) { ampBuf[i] = 0; phsBuf[i] = 0; } fftBuf[i].real = ampBuf[i]*cos(phsBuf[i]); fftBuf[i].imag = ampBuf[i]*sin(phsBuf[i]); } cfft1d(fftLen,fftBuf,1); for(i=0;i<chunk_size;i++) { outBuf[i*samps+x].real = fftBuf[i].real; outBuf[i*samps+x].imag = fftBuf[i].imag; } } printf("Finished the FFT and Filtering Operations\n"); /* Perform the time-domain frequency shift */ if(shift != 0.0) { for(i=0; i<chunk_size; i++) time_vector[i] = cur_time+(1/f_s)*i; printf("\nPerforming time-domain frequency shift of %.2f Hz\n",shift); for(y=0; y<chunk_size; y++) { for(x=0; x<samps; x++) { A = outBuf[y*samps+x].real; B = outBuf[y*samps+x].imag; outBuf[y*samps+x].real = A*cos(2*pi*shift*time_vector[y]) - B*sin(2*pi*shift*time_vector[y]); outBuf[y*samps+x].imag = B*cos(2*pi*shift*time_vector[y]) + A*sin(2*pi*shift*time_vector[y]); } } } /* Write out the data file in big endian format */ printf("Writing the output lines %d to %d in file %s\n", start_line, start_line+chunk_size-TOSS_SIZE, outName); put_complexFloat_lines(outF1, outMeta, start_line, samps*(chunk_size-TOSS_SIZE), outBuf+(samps*TOSS_SIZE)); } printf("\n"); FCLOSE(outF1); StopWatch(); return 0; }
int main(int argc,char **argv) { int lines,samps,start_line; /* Number of image lines and samples */ int x,y,ii; /* Counters and the filter frequency indicies */ char *inName, *outName; /* Input filename */ char metaName[256]; /* Name of meta file */ complexFloat *inBuf; /* Input/Output Image Buffers */ complexFloat *fftBuf; /* FFT Buffer for the image */ float *ampBuf,*phsBuf; /* Amplitude and Phase Buffers */ float df, freq[FFT_LEN], f_s; /* Frequency Vector */ FILE *inF,*outF1; /* Input and Output file pointers */ meta_parameters *meta; /* Meta-file data pointer */ /* Usage is shown if the user doesn't give correct number of arguments */ if(argc!=4) { usage(argv[0]); } StartWatch(); /* Get the filename and filter start and end frequencies from the command line */ inName = argv[1]; outName = argv[2]; start_line = atoi(argv[3]); create_name(metaName, inName, ".meta"); /* Get the PRF and number of samples from the meta-file */ meta = meta_read(metaName); lines = FFT_LEN; samps = meta->general->sample_count; f_s = 1/(meta->sar->azimuth_time_per_pixel); printf("Sampling Frequency is %f\n",f_s); /* Compute the FFT length based on the number of lines. Must be a power of 2 */ printf("FFT Length is %d\n",FFT_LEN); cfft1d(FFT_LEN,NULL,0); /* Allocate the memory for all the buffers */ inBuf = (complexFloat *)MALLOC(sizeof(complexFloat)*samps*FFT_LEN); fftBuf = (complexFloat *)MALLOC(sizeof(complexFloat)*FFT_LEN); ampBuf = (float *)MALLOC(sizeof(float)*FFT_LEN); phsBuf = (float *)MALLOC(sizeof(float)*FFT_LEN); df = f_s/FFT_LEN; for(ii=0; ii<FFT_LEN; ii++) freq[ii] = df*ii; /* Open the Complex Image File */ if((inF=FOPEN(inName,"rb"))==NULL) { printf("Complex Image file %s could not be opened\n",inName); exit(EXIT_FAILURE); } /* Zero out all the arrays and begin processing data */ for(ii=0; ii<FFT_LEN; ii++) { ampBuf[ii]=0; phsBuf[ii]=0; } /* Read in the data chunk */ printf("Reading Data Starting at Line %d\n",start_line); get_complexFloat_lines(inF, meta, start_line, FFT_LEN, inBuf); /* Process the each column, take the average at the end */ printf("Performing the FFT\n"); for(x=0; x<samps; x++) { if(x%500 == 0) printf("Processing Column %d\n",x); for(y=0; y<FFT_LEN; y++) { fftBuf[y].real=0; fftBuf[y].imag=0; } for(y=0; y<lines; y++) { fftBuf[y].real=inBuf[y*samps+x].real; fftBuf[y].imag=inBuf[y*samps+x].imag; } cfft1d(FFT_LEN,fftBuf,-1); for (ii=0; ii<FFT_LEN; ii++) { ampBuf[ii] += sqrt(fftBuf[ii].real*fftBuf[ii].real + fftBuf[ii].imag*fftBuf[ii].imag); if(fftBuf[ii].imag!=0.0 || fftBuf[ii].real!=0.0) phsBuf[ii] += atan2(fftBuf[ii].imag, fftBuf[ii].real); } } printf("Finished the FFT\n"); /* Open and write output file */ strcat(outName,".spectra"); if((outF1=FOPEN(outName,"w"))==NULL) { printf("Unable to write output %s\n",outName); exit(EXIT_FAILURE); } for (ii=0; ii<FFT_LEN; ii++) { ampBuf[ii] /= samps; phsBuf[ii] /= samps; fprintf(outF1,"%f %f %f\n",freq[ii],ampBuf[ii],phsBuf[ii]); } /* Close up & leave */ meta_free(meta); FCLOSE(outF1); StopWatch(); return 0; }
/******* amp_corr: Given two patches, p1 containing the echos from ahead of beam center, p2 containing echos from behind beam center; performs an amplitude cross-correlation in range and returns the range offset, in pixels, between these two images. */ double amp_corr(patch *p1,patch *p2,file *f) { int clip=20;/*Remove this from the far-range end of the images*/ int overlap=30;/*Overlap is the maximum shift we ever expect.*/ FILE *fout; int x,y; int fftLen=smallestPow2(p1->n_range); float scale=1.0/fftLen; complexFloat *amp1,*amp2; float *corr; double ret; amp1=(complexFloat *)MALLOC(sizeof(complexFloat)*fftLen); amp2=(complexFloat *)MALLOC(sizeof(complexFloat)*fftLen); corr=(float *)MALLOC(sizeof(float)*(fftLen+overlap)); if (!quietflag) printf(" Performing amplitude correlation.\n"); for (x=0;x<fftLen+overlap;x++) corr[x]=0.0; cfft1d(fftLen,NULL,0); p1->n_range-=clip; p2->n_range-=clip; for (y=f->firstOutputLine;y<f->firstOutputLine+f->n_az_valid;y++) { for (x=0;x<overlap;x++) { amp1[x]=Czero(); amp2[x].r=Cabs(p2->trans[x*p2->n_az+y])*scale; amp2[x].i=0.0; } for (;x<p1->n_range-overlap;x++) { amp1[x].r=Cabs(p1->trans[x*p1->n_az+y])*scale; amp1[x].i=0.0; amp2[x].r=Cabs(p2->trans[x*p2->n_az+y])*scale; amp2[x].i=0.0; } for (;x<p1->n_range;x++) { amp1[x]=Czero(); amp2[x].r=Cabs(p2->trans[x*p2->n_az+y])*scale; amp2[x].i=0.0; } for (;x<fftLen;x++) amp1[x]=amp2[x]=Czero(); cfft1d(fftLen,amp1,-1); cfft1d(fftLen,amp2,-1); for (x=0;x<fftLen;x++) amp2[x]=Cmul(amp2[x],Cconj(amp1[x])); cfft1d(fftLen,amp2,1); for (x=0;x<fftLen;x++) corr[x]+=Cabs(amp2[x]); } fout=FOPEN(f->out_cpx,"w"); for (x=-overlap;x<overlap;x++) { corr[x+fftLen]=corr[(x+fftLen)%fftLen]; if (corr[x+fftLen]<10000000000000000000000.0) /*Is a good value-- print it out*/ fprintf(fout,"%d %f\n",x,corr[x+fftLen]); else/*Must be an infinity or NaN*/ { fprintf(stderr, " WARNING!! Found infinity at offset %d!\n",x); if (logflag) { sprintf(logbuf," WARNING!! Found infinity at offset %d!\n",x); printLog(logbuf); } corr[x+fftLen]=0.0; } } FCLOSE(fout); FREE(amp1); FREE(amp2); ret = dop_findPeak(corr,fftLen-overlap,2*overlap)-fftLen; FREE(corr); return ret; }