/************************************************************************* snaphu utility function source file Written by Curtis W. Chen Copyright 2002 Board of Trustees, Leland Stanford Jr. University Please see the supporting documentation for terms of use. No warranty. *************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "snaphu.h" /* function: IsTrue() * ------------------ * Returns TRUE if the string input is any of TRUE, True, true, 1, * y, Y, yes, YES */ int IsTrue(char *str){ if(!strcmp(str,"TRUE") || !strcmp(str,"true") || !strcmp(str,"True") || !strcmp(str,"1") || !strcmp(str,"y") || !strcmp(str,"Y") || !strcmp(str,"yes") || !strcmp(str,"YES") || !strcmp(str,"Yes")){ return(TRUE); }else{ return(FALSE); } } /* function: IsFalse() * ------------------ * Returns FALSE if the string input is any of FALSE, False, false, * 0, n, N, no, NO */ int IsFalse(char *str){ if(!strcmp(str,"FALSE") || !strcmp(str,"false") || !strcmp(str,"False") || !strcmp(str,"0") || !strcmp(str,"n") || !strcmp(str,"N") || !strcmp(str,"no") || !strcmp(str,"NO") || !strcmp(str,"No")){ return(TRUE); }else{ return(FALSE); } } /* function: SetBoolenaSignedChar() * -------------------------------- * Sets the value of a signed character based on the string argument passed. * Returns TRUE if the string was not a valid value, FALSE otherwise. */ signed char SetBooleanSignedChar(signed char *boolptr, char *str){ if(IsTrue(str)){ (*boolptr)=TRUE; return(FALSE); }else if(IsFalse(str)){ (*boolptr)=FALSE; return(FALSE); } return(TRUE); } /* function: ModDiff() * ------------------- * Computes floating point difference between two numbers. * f1 and f2 should be between [0,2pi). The result is the * modulo difference between (-pi,pi]. Assumes that * PI and TWOPI have been defined. */ double ModDiff(double f1, double f2){ double f3; f3=f1-f2; if(f3>PI){ f3-=TWOPI; }else if(f3<=-PI){ f3+=TWOPI; } return(f3); } /* function: WrapPhase() * --------------------- * Makes sure the passed float array is properly wrapped into the [0,2pi) * interval. */ void WrapPhase(float **wrappedphase, long nrow, long ncol){ long row, col; for(row=0;row=0.5){ dpsi[row][col]-=1.0; }else if(dpsi[row][col]<-0.5){ dpsi[row][col]+=1.0; } } } paddpsi=MirrorPad(dpsi,nrow,ncol-1,(kperpdpsi-1)/2,(kpardpsi-1)/2); if(paddpsi==dpsi){ fprintf(sp0,"Wrapped-gradient averaging box too large " "for input array size\nAbort\n"); exit(ABNORMAL_EXIT); } BoxCarAvg(avgdpsi,paddpsi,nrow,ncol-1,kperpdpsi,kpardpsi); Free2DArray((void **)paddpsi,nrow+kperpdpsi-1); } /* function: CalcWrappedAzDiffs() * --------------------------------- * Computes an array of wrapped phase differences in range (across rows). * Input wrapped phase array should be in radians. Output is in cycles. */ void CalcWrappedAzDiffs(float **dpsi, float **avgdpsi, float **wrappedphase, long kperpdpsi, long kpardpsi, long nrow, long ncol){ long row, col; float **paddpsi; for(row=0;row=0.5){ dpsi[row][col]-=1.0; }else if(dpsi[row][col]<-0.5){ dpsi[row][col]+=1.0; } } } paddpsi=MirrorPad(dpsi,nrow-1,ncol,(kpardpsi-1)/2,(kperpdpsi-1)/2); if(paddpsi==dpsi){ fprintf(sp0,"Wrapped-gradient averaging box too large " "for input array size\nAbort\n"); exit(ABNORMAL_EXIT); } BoxCarAvg(avgdpsi,paddpsi,nrow-1,ncol,kpardpsi,kperpdpsi); Free2DArray((void **)paddpsi,nrow-1+kpardpsi-1); } /* function: CycleResidue() * ------------------------ * Computes the cycle array of a phase 2D phase array. Input arrays * should be type float ** and signed char ** with memory pre-allocated. * Numbers of rows and columns in phase array should be passed. * Residue array will then have size nrow-1 x ncol-1. Residues will * always be -1, 0, or 1 if wrapped phase is passed in. */ void CycleResidue(float **phase, signed char **residue, int nrow, int ncol){ int row, col; float **rowdiff, **coldiff; rowdiff=(float **)Get2DMem(nrow-1,ncol,sizeof(float *),sizeof(float)); coldiff=(float **)Get2DMem(nrow,ncol-1,sizeof(float *),sizeof(float)); for(row=0;rowflipphasesign){ for(row=0;rowflipphasesign){ for(row=0;row<2*nrow-1;row++){ if(rowmaxval){ maxval=labs(arr[row][col]); } } } for(row=nrow-1;row<2*nrow-1;row++){ for(col=0;colmaxval){ maxval=labs(arr[row][col]); } } } return(maxval); } /* function: LinInterp1D() * ----------------------- * Given an array of floats, interpolates at the specified noninteger * index. Returns first or last array value if index is out of bounds. */ float LinInterp1D(float *arr, double index, long nelem){ long intpart; double fracpart; intpart=(long )floor(index); fracpart=index-intpart; if(intpart<0){ return(arr[0]); }else if(intpart>=nelem-1){ return(arr[nelem-1]); }else{ return(((1-fracpart)*arr[intpart]+fracpart*arr[intpart+1])/2.0); } } /* function: LinInterp2D() * ----------------------- * Given a 2-D array of floats, interpolates at the specified noninteger * indices. Returns first or last array values if index is out of bounds. */ float LinInterp2D(float **arr, double rowind, double colind , long nrow, long ncol){ long rowintpart; double rowfracpart; rowintpart=(long )floor(rowind); rowfracpart=rowind-rowintpart; if(rowintpart<0){ return(LinInterp1D(arr[0],colind,ncol)); }else if(rowintpart>=nrow-1){ return(LinInterp1D(arr[nrow-1],colind,ncol)); }else{ return(((1-rowfracpart)*LinInterp1D(arr[rowintpart],colind,ncol) +rowfracpart*LinInterp1D(arr[rowintpart+1],colind,ncol))/2.0); } } /* function: Despeckle() * --------------------- * Filters magnitude/power data with adaptive geometric filter to get rid of * speckle. Allocates 2D memory for ei. Does not square before averaging. */ void Despeckle(float **mag, float ***ei, long nrow, long ncol){ float **intensity; double ratio, ratiomax, wfull, wstick, w[NARMS+1]; long row, col, i, j, k, Irow, Icol; short jmin[5]={2,2,0,1,2}; short jmax[5]={2,3,4,3,2}; enum{ C=0, T, B, R, L, TR, BL, TL, BR}; /* get memory for output array */ if(*ei==NULL){ (*ei)=(float **)Get2DMem(nrow,ncol,sizeof(float *),sizeof(float)); } /* pad magnitude and place into new array (don't touch original data) */ intensity=MirrorPad(mag,nrow,ncol,ARMLEN,ARMLEN); if(intensity==mag){ fprintf(sp0,"Despeckling box size too large for input array size\n" "Abort\n"); exit(ABNORMAL_EXIT); } /* do the filtering */ for(row=0;rowratiomax){ ratiomax=ratio; (*ei)[row][col]=wstick; } } } } } /* free memory */ Free2DArray((void **)intensity,nrow+2*ARMLEN); } /* function: MirrorPad() * --------------------- * Returns pointer to 2D array where passed array is in center and * edges are padded by mirror reflections. If the pad dimensions are * too large for the array size, a pointer to the original array is * returned. */ float **MirrorPad(float **array1, long nrow, long ncol, long krow, long kcol){ long row, col; float **array2; /* get memory */ array2=(float **)Get2DMem(nrow+2*krow,ncol+2*kcol, sizeof(float *),sizeof(float)); /* center array1 in new array */ for(row=0;rownrow || kcol>ncol){ return(array1); } /* mirror reflect edges */ for(row=0;row=HUGE_VAL || tempdouble<=-HUGE_VAL){ return(TRUE); }else{ *d=tempdouble; return(FALSE); } } /* function: StringToLong() * ------------------------ * Uses strtol to convert a string to a base-10 long, but also does error * checking. If any part of the string is not converted, the function does * not make the assignment and returns TRUE. Otherwise, returns FALSE. */ int StringToLong(char *str, long *l){ long templong; char *endp; endp=str; templong=strtol(str,&endp,10); if(strlen(endp) || templong==LONG_MAX || templong==LONG_MIN){ return(TRUE); }else{ *l=templong; return(FALSE); } } /* function: CatchSignals() * ------------------------ * Traps common signals that by default cause the program to abort. * Sets (pointer to function) Handler as the signal handler for all. * Note that SIGKILL usually cannot be caught. No return value. */ void CatchSignals(void (*SigHandler)(int)){ signal(SIGHUP,SigHandler); signal(SIGINT,SigHandler); signal(SIGQUIT,SigHandler); signal(SIGILL,SigHandler); signal(SIGABRT,SigHandler); signal(SIGFPE,SigHandler); signal(SIGSEGV,SigHandler); signal(SIGPIPE,SigHandler); signal(SIGALRM,SigHandler); signal(SIGTERM,SigHandler); signal(SIGBUS,SigHandler); } /* function: SetDump() * ------------------- * Set the global variable dumpresults_global to TRUE if SIGINT or SIGHUP * signals recieved. Also sets requestedstop_global if SIGINT signal * received. This function should only be called via signal() when * a signal is caught. */ void SetDump(int signum){ if(signum==SIGINT){ /* exit if we receive another interrupt */ signal(SIGINT,exit); /* print nice message and set global variables so program knows to exit */ fprintf(sp0,"\n\nSIGINT signal caught. Please wait for graceful exit\n"); fprintf(sp0,"(One more interrupt signal halts job)\n"); dumpresults_global=TRUE; requestedstop_global=TRUE; }else if(signum==SIGHUP){ /* make sure the hangup signal doesn't revert to default behavior */ signal(SIGHUP,SetDump); /* print a nice message, and set the dump variable */ fprintf(sp0,"\n\nSIGHUP signal caught. Dumping results\n"); dumpresults_global=TRUE; }else{ fprintf(sp0,"WARNING: Invalid signal (%d) passed to signal handler\n", signum); } } /* function: KillChildrenExit() * ---------------------------- * Signal handler that sends a KILL signal to all processes in the group * so that children exit when parent exits. */ void KillChildrenExit(int signum){ fprintf(sp0,"Parent received signal %d\nKilling children and exiting\n", signum); fflush(NULL); signal(SIGTERM,SIG_IGN); kill(0,SIGTERM); exit(ABNORMAL_EXIT); } /* function: SignalExit() * ---------------------- * Signal hanlder that prints message about the signal received, then exits. */ void SignalExit(int signum){ signal(SIGTERM,SIG_IGN); fprintf(sp0,"Exiting with status %d on signal %d\n",ABNORMAL_EXIT,signum); fflush(NULL); exit(ABNORMAL_EXIT); } /* function: StartTimers() * ----------------------- * Starts the wall clock and CPU timers for use in conjunction with * DisplayElapsedTime(). */ void StartTimers(time_t *tstart, double *cputimestart){ struct rusage usagebuf; *tstart=time(NULL); *cputimestart=-1.0; if(!getrusage(RUSAGE_SELF,&usagebuf)){ *cputimestart=(double )(usagebuf.ru_utime.tv_sec +(usagebuf.ru_utime.tv_usec/(double )1000000) +usagebuf.ru_stime.tv_sec +(usagebuf.ru_stime.tv_usec/(double )1000000)); if(!getrusage(RUSAGE_CHILDREN,&usagebuf)){ *cputimestart+=(double )(usagebuf.ru_utime.tv_sec +(usagebuf.ru_utime.tv_usec/(double )1000000) +usagebuf.ru_stime.tv_sec +(usagebuf.ru_stime.tv_usec/(double )1000000)); } } } /* function: DisplayElapsedTime() * ------------------------------ * Displays the elapsed wall clock and CPU times for the process and its * children. Times should be initialized at the start of the program with * StartTimers(). The code is written to show the total processor time * for the parent process and all of its children, but whether or not * this is actually done depends on the implementation of the system time * functions. */ void DisplayElapsedTime(time_t tstart, double cputimestart){ double cputime, walltime, seconds; long hours, minutes; time_t tstop; struct rusage usagebuf; cputime=-1.0; if(!getrusage(RUSAGE_CHILDREN,&usagebuf)){ cputime=(double )(usagebuf.ru_utime.tv_sec +(usagebuf.ru_utime.tv_usec/(double )1000000) +usagebuf.ru_stime.tv_sec +(usagebuf.ru_stime.tv_usec/(double )1000000)); if(!getrusage(RUSAGE_SELF,&usagebuf)){ cputime+=(double )(usagebuf.ru_utime.tv_sec +(usagebuf.ru_utime.tv_usec/(double )1000000) +usagebuf.ru_stime.tv_sec +(usagebuf.ru_stime.tv_usec/(double )1000000)); } } tstop=time(NULL); if(cputime>0 && cputimestart>=0){ cputime-=cputimestart; hours=(long )floor(cputime/3600); minutes=(long )floor((cputime-3600*hours)/60); seconds=cputime-3600*hours-60*minutes; fprintf(sp1,"Elapsed processor time: %ld:%02ld:%05.2f\n", hours,minutes,seconds); } if(tstart>0 && tstop>0){ walltime=tstop-tstart; hours=(long )floor(walltime/3600); minutes=(long )floor((walltime-3600*hours)/60); seconds=walltime-3600*hours-60*minutes; fprintf(sp1,"Elapsed wall clock time: %ld:%02ld:%02ld\n", hours,minutes,(long )seconds); } } /* function: LongCompare() * ----------------------- * Compares two long integers. For use with qsort(). */ int LongCompare(const void *c1, const void *c2){ return((*((long *)c1))-(*((long *)c2))); }