#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <limits.h>
#include <float.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "snaphu.h"
extern char dumpresults_global;
extern char requestedstop_global;
extern FILE *sp0, *sp1, *sp2, *sp3;
extern nodeT NONTREEARC[1];
extern void (*CalcCost)(void **, long, long, long, long, long,
paramT *, long *, long *);
extern long (*EvalCost)(void **, short **, long, long, long, paramT *);
char dumpresults_global = FALSE;
char requestedstop_global = FALSE;
FILE *sp0 = NULL;
FILE *sp1 = NULL;
FILE *sp2 = NULL;
FILE *sp3 = NULL;
nodeT NONTREEARC[1];
void (*CalcCost)(void **, long, long, long, long, long,
paramT *, long *, long *) = NULL;
long (*EvalCost)(void **, short **, long, long, long, paramT *) = NULL;
int StartTimers(time_t *tstart, double *cputimestart);
int DisplayElapsedTime(time_t tstart, double cputimestart);
int run_main(int argc, char **argv) {
infileT infiles[1];
outfileT outfiles[1];
paramT params[1];
time_t tstart;
double cputimestart;
long linelen, nlines;
StartTimers(&tstart,&cputimestart);
SetStreamPointers();
fprintf(sp1,"\n%s v%s\n",PROGRAMNAME,VERSION);
SetDefaults(infiles,outfiles,params);
ReadConfigFile(DEF_SYSCONFFILE,infiles,outfiles,&linelen,params);
ProcessArgs(argc,argv,infiles,outfiles,&linelen,params);
SetVerboseOut(params);
SetDumpAll(outfiles,params);
nlines=GetNLines(infiles,linelen,params);
CheckParams(infiles,outfiles,linelen,nlines,params);
WriteConfigLogFile(argc,argv,infiles,outfiles,linelen,params);
Unwrap(infiles,outfiles,params,linelen,nlines);
fprintf(sp1,"Program %s done\n",PROGRAMNAME);
DisplayElapsedTime(tstart,cputimestart);
exit(NORMAL_EXIT);
}
int ChildResetStreamPointers(pid_t pid, long tilerow, long tilecol,
paramT *params){
FILE *logfp;
char logfile[MAXSTRLEN], cwd[MAXSTRLEN];
fflush(NULL);
sprintf(logfile,"%s/%s%ld_%ld",params->tiledir,LOGFILEROOT,tilerow,tilecol);
if((logfp=fopen(logfile,"w"))==NULL){
fflush(NULL);
fprintf(sp0,"Unable to open log file %s\nAbort\n",logfile);
exit(ABNORMAL_EXIT);
}
fprintf(logfp,"%s (pid %ld): unwrapping tile at row %ld, column %ld\n\n",
PROGRAMNAME,(long )pid,tilerow,tilecol);
if(getcwd(cwd,MAXSTRLEN)!=NULL){
fprintf(logfp,"Current working directory is %s\n",cwd);
}
if(sp2==stdout || sp2==stderr){
sp2=logfp;
}
if(sp1==stdout || sp1==stderr){
sp1=logfp;
}
if(sp0==stdout || sp0==stderr){
sp0=logfp;
}
if(sp3!=stdout && sp3!=stderr && sp3!=stdin && sp3!=NULL){
fclose(sp3);
}
if((sp3=fopen(NULLFILE,"w"))==NULL){
fflush(NULL);
fprintf(sp0,"Unable to open null file %s\n",NULLFILE);
exit(ABNORMAL_EXIT);
}
return(0);
}
int Unwrap(infileT *infiles, outfileT *outfiles, paramT *params,
long linelen, long nlines){
long optiter, noptiter;
long nexttilerow, nexttilecol, ntilerow, ntilecol, nthreads, nchildren;
long sleepinterval;
tileparamT tileparams[1];
infileT iterinfiles[1];
outfileT iteroutfiles[1];
outfileT tileoutfiles[1];
paramT iterparams[1];
char tileinitfile[MAXSTRLEN];
pid_t pid;
int childstatus;
double tilecputimestart;
time_t tiletstart;
signed char **dotilemask;
memset(tileparams,0,sizeof(tileparamT));
memset(iterinfiles,0,sizeof(infileT));
memset(iteroutfiles,0,sizeof(outfileT));
memset(tileoutfiles,0,sizeof(outfileT));
memset(iterparams,0,sizeof(paramT));
memset(tileinitfile,0,MAXSTRLEN);
if(params->onetilereopt){
noptiter=2;
}else{
noptiter=1;
}
for(optiter=0;optiter<noptiter;optiter++){
memcpy(iterinfiles,infiles,sizeof(infileT));
memcpy(iteroutfiles,outfiles,sizeof(outfileT));
memcpy(iterparams,params,sizeof(paramT));
if(optiter==0){
if(noptiter>1){
SetTileInitOutfile(iteroutfiles->outfile,iterparams->parentpid);
StrNCopy(tileinitfile,iteroutfiles->outfile,MAXSTRLEN);
iteroutfiles->outfileformat=TILEINITFILEFORMAT;
fprintf(sp1,"Starting first-round tile-mode unwrapping\n");
}
}else if(optiter==1){
StrNCopy(iterinfiles->infile,tileinitfile,MAXSTRLEN);
iterinfiles->unwrappedinfileformat=TILEINITFILEFORMAT;
iterparams->unwrapped=TRUE;
iterparams->ntilerow=1;
iterparams->ntilecol=1;
iterparams->rowovrlp=0;
iterparams->colovrlp=0;
fprintf(sp1,"Starting second-round single-tile unwrapping\n");
}else{
fprintf(sp0,"ERROR: illegal optiter value in Unwrap()\n");
exit(ABNORMAL_EXIT);
}
ntilerow=iterparams->ntilerow;
ntilecol=iterparams->ntilecol;
nthreads=iterparams->nthreads;
dumpresults_global=FALSE;
requestedstop_global=FALSE;
if(ntilerow==1 && ntilecol==1){
tileparams->firstrow=iterparams->piecefirstrow;
tileparams->firstcol=iterparams->piecefirstcol;
tileparams->nrow=iterparams->piecenrow;
tileparams->ncol=iterparams->piecencol;
UnwrapTile(iterinfiles,iteroutfiles,iterparams,tileparams,nlines,linelen);
}else{
if(!iterparams->assembleonly){
dotilemask=SetUpDoTileMask(iterinfiles,ntilerow,ntilecol);
MakeTileDir(iterparams,iteroutfiles);
if(nthreads>1){
nexttilerow=0;
nexttilecol=0;
nchildren=0;
sleepinterval=(long )ceil(nlines*linelen
/((double )(ntilerow*ntilecol))
*SECONDSPERPIXEL);
CatchSignals(KillChildrenExit);
while(TRUE){
if(nchildren<nthreads && nexttilerow<ntilerow){
if(dotilemask[nexttilerow][nexttilecol]){
sleep(sleepinterval);
fflush(NULL);
pid=fork();
}else{
pid=iterparams->parentpid;
}
if(pid<0){
fflush(NULL);
fprintf(sp0,"Error while forking\nAbort\n");
kill(0,SIGKILL);
exit(ABNORMAL_EXIT);
}else if(pid==0){
CatchSignals(SignalExit);
StartTimers(&tiletstart,&tilecputimestart);
pid=getpid();
fprintf(sp1,
"Unwrapping tile at row %ld, column %ld (pid %ld)\n",
nexttilerow,nexttilecol,(long )pid);
SetupTile(nlines,linelen,iterparams,tileparams,
iteroutfiles,tileoutfiles,
nexttilerow,nexttilecol);
ChildResetStreamPointers(pid,nexttilerow,nexttilecol,
iterparams);
UnwrapTile(iterinfiles,tileoutfiles,iterparams,tileparams,
nlines,linelen);
DisplayElapsedTime(tiletstart,tilecputimestart);
exit(NORMAL_EXIT);
}
if(++nexttilecol==ntilecol){
nexttilecol=0;
nexttilerow++;
}
if(pid!=iterparams->parentpid){
nchildren++;
}
}else{
pid=wait(&childstatus);
if(!(WIFEXITED(childstatus)) || (WEXITSTATUS(childstatus))!=0){
fflush(NULL);
fprintf(sp0,"Unexpected or abnormal exit of child process %ld\n"
"Abort\n",(long )pid);
signal(SIGTERM,SIG_IGN);
kill(0,SIGTERM);
exit(ABNORMAL_EXIT);
}
if(--nchildren==0){
sleep(sleepinterval);
break;
}
}
}
CatchSignals(SIG_DFL);
}else{
for(nexttilerow=0;nexttilerow<ntilerow;nexttilerow++){
for(nexttilecol=0;nexttilecol<ntilecol;nexttilecol++){
if(dotilemask[nexttilerow][nexttilecol]){
fprintf(sp1,"Unwrapping tile at row %ld, column %ld\n",
nexttilerow,nexttilecol);
SetupTile(nlines,linelen,iterparams,tileparams,
iteroutfiles,tileoutfiles,
nexttilerow,nexttilecol);
UnwrapTile(iterinfiles,tileoutfiles,iterparams,tileparams,
nlines,linelen);
}
}
}
}
Free2DArray((void **)dotilemask,ntilerow);
}
AssembleTiles(iteroutfiles,iterparams,nlines,linelen);
}
if(iterparams->rmtileinit && optiter>0){
unlink(tileinitfile);
}
}
return(0);
}
int UnwrapTile(infileT *infiles, outfileT *outfiles, paramT *params,
tileparamT *tileparams, long nlines, long linelen){
long nrow, ncol, nnoderow, narcrow, n, ngroundarcs, iincrcostfile;
long nflow, ncycle, mostflow, nflowdone;
long candidatelistsize, candidatebagsize;
long isource, nsource;
long nnondecreasedcostiter;
long *nconnectedarr;
int *nnodesperrow, *narcsperrow;
short **flows, **mstcosts;
float **wrappedphase, **unwrappedphase, **mag, **unwrappedest;
incrcostT **incrcosts;
void **costs;
totalcostT totalcost, oldtotalcost, mintotalcost;
nodeT **sourcelist;
nodeT *source, ***apexes;
nodeT **nodes, ground[1];
candidateT *candidatebag, *candidatelist;
signed char **iscandidate;
signed char notfirstloop, allmasked;
bucketT *bkts;
nrow=tileparams->nrow;
ncol=tileparams->ncol;
ReadInputFile(infiles,&mag,&wrappedphase,&flows,linelen,nlines,
params,tileparams);
ReadMagnitude(mag,infiles,linelen,nlines,tileparams);
ReadByteMask(mag,infiles,linelen,nlines,tileparams,params);
allmasked=CheckMagMasking(mag,nrow,ncol);
unwrappedest=NULL;
if(strlen(infiles->estfile)){
ReadUnwrappedEstimateFile(&unwrappedest,infiles,linelen,nlines,
params,tileparams);
FlattenWrappedPhase(wrappedphase,unwrappedest,nrow,ncol);
}
BuildCostArrays(&costs,&mstcosts,mag,wrappedphase,unwrappedest,
linelen,nlines,nrow,ncol,params,tileparams,infiles,outfiles);
if(params->eval){
mostflow=Short2DRowColAbsMax(flows,nrow,ncol);
fprintf(sp1,"Maximum flow on network: %ld\n",mostflow);
totalcost=EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params);
fprintf(sp1,"Total solution cost: %.9g\n",(double )totalcost);
Free2DArray((void **)costs,2*nrow-1);
Free2DArray((void **)mag,nrow);
Free2DArray((void **)wrappedphase,nrow);
Free2DArray((void **)flows,2*nrow-1);
return(1);
}
SetGridNetworkFunctionPointers();
unwrappedphase=NULL;
nodes=NULL;
if(!params->unwrapped){
if(params->initmethod==MSTINIT){
MSTInitFlows(wrappedphase,&flows,mstcosts,nrow,ncol,
&nodes,ground,params->initmaxflow);
}else if(params->initmethod==MCFINIT){
MCFInitFlows(wrappedphase,&flows,mstcosts,nrow,ncol,
params->cs2scalefactor);
}else{
fflush(NULL);
fprintf(sp0,"Illegal initialization method\nAbort\n");
exit(ABNORMAL_EXIT);
}
if(params->initonly || strlen(outfiles->initfile)){
fprintf(sp1,"Integrating phase\n");
unwrappedphase=(float **)Get2DMem(nrow,ncol,
sizeof(float *),sizeof(float));
IntegratePhase(wrappedphase,unwrappedphase,flows,nrow,ncol);
if(unwrappedest!=NULL){
Add2DFloatArrays(unwrappedphase,unwrappedest,nrow,ncol);
}
FlipPhaseArraySign(unwrappedphase,params,nrow,ncol);
if(params->initonly){
fprintf(sp1,"Writing output to file %s\n",outfiles->outfile);
WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles,
nrow,ncol);
Free2DArray((void **)mag,nrow);
Free2DArray((void **)wrappedphase,nrow);
Free2DArray((void **)unwrappedphase,nrow);
if(nodes!=NULL){
Free2DArray((void **)nodes,nrow-1);
}
Free2DArray((void **)flows,2*nrow-1);
return(1);
}else{
fprintf(sp2,"Writing initialization to file %s\n",outfiles->initfile);
WriteOutputFile(mag,unwrappedphase,outfiles->initfile,outfiles,
nrow,ncol);
Free2DArray((void **)unwrappedphase,nrow);
}
}
}
InitNetwork(flows,&ngroundarcs,&ncycle,&nflowdone,&mostflow,&nflow,
&candidatebagsize,&candidatebag,&candidatelistsize,
&candidatelist,&iscandidate,&apexes,&bkts,&iincrcostfile,
&incrcosts,&nodes,ground,&nnoderow,&nnodesperrow,&narcrow,
&narcsperrow,nrow,ncol,¬firstloop,&totalcost,params);
oldtotalcost=totalcost;
mintotalcost=totalcost;
nnondecreasedcostiter=0;
if(params->regrowconncomps){
Free2DArray((void **)apexes,2*nrow-1);
Free2DArray((void **)iscandidate,2*nrow-1);
Free2DArray((void **)nodes,nrow-1);
free(candidatebag);
free(candidatelist);
free(bkts->bucketbase);
GrowConnCompsMask(costs,flows,nrow,ncol,incrcosts,outfiles,params);
Free2DArray((void **)incrcosts,2*nrow-1);
Free2DArray((void **)costs,2*nrow-1);
Free2DArray((void **)mag,nrow);
Free2DArray((void **)wrappedphase,nrow);
Free2DArray((void **)flows,2*nrow-1);
free(nnodesperrow);
free(narcsperrow);
return(1);
}
MaskNodes(nrow,ncol,nodes,ground,mag);
if(params->ntilerow==1 && params->ntilecol==1){
signal(SIGINT,SetDump);
signal(SIGHUP,SetDump);
}
if(!allmasked){
fprintf(sp1,"Running nonlinear network flow optimizer\n");
fprintf(sp1,"Maximum flow on network: %ld\n",mostflow);
fprintf(sp2,"Number of nodes in network: %ld\n",(nrow-1)*(ncol-1)+1);
while(TRUE){
fprintf(sp1,"Flow increment: %ld (Total improvements: %ld)\n",
nflow,ncycle);
SetupIncrFlowCosts(costs,incrcosts,flows,nflow,nrow,narcrow,narcsperrow,
params);
if(params->dumpall && params->ntilerow==1 && params->ntilecol==1){
DumpIncrCostFiles(incrcosts,++iincrcostfile,nflow,nrow,ncol);
}
sourcelist=NULL;
nconnectedarr=NULL;
nsource=SelectSources(nodes,mag,ground,nflow,flows,ngroundarcs,
nrow,ncol,params,&sourcelist,&nconnectedarr);
SetupTreeSolveNetwork(nodes,ground,apexes,iscandidate,
nnoderow,nnodesperrow,narcrow,narcsperrow,
nrow,ncol);
n=0;
for(isource=0;isource<nsource;isource++){
source=sourcelist[isource];
if(source->row==GROUNDROW){
fprintf(sp3,"Source %ld: (edge ground)\n",isource);
}else{
fprintf(sp3,"Source %ld: row, col = %d, %d\n",
isource,source->row,source->col);
}
n+=TreeSolve(nodes,NULL,ground,source,
&candidatelist,&candidatebag,
&candidatelistsize,&candidatebagsize,
bkts,flows,costs,incrcosts,apexes,iscandidate,
ngroundarcs,nflow,mag,wrappedphase,outfiles->outfile,
nnoderow,nnodesperrow,narcrow,narcsperrow,nrow,ncol,
outfiles,nconnectedarr[isource],params);
}
free(sourcelist);
free(nconnectedarr);
fprintf(sp2,"Current solution cost: %.16g\n",
(double )EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params));
fflush(NULL);
if(notfirstloop){
oldtotalcost=totalcost;
totalcost=EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params);
if(totalcost<mintotalcost){
mintotalcost=totalcost;
}
if(totalcost>oldtotalcost || (n>0 && totalcost==oldtotalcost)){
fflush(NULL);
fprintf(sp1,"Caution: Unexpected increase in total cost\n");
}
if(totalcost > mintotalcost){
nnondecreasedcostiter++;
}else{
nnondecreasedcostiter=0;
}
}
ncycle+=n;
if(n<=params->maxnflowcycles){
nflowdone++;
}else{
nflowdone=1;
}
mostflow=MaxNonMaskFlow(flows,mag,nrow,ncol);
if(nnondecreasedcostiter>=2*mostflow){
fflush(NULL);
fprintf(sp0,"WARNING: No overall cost reduction for too many iterations."
" Breaking loop\n");
break;
}
if(nflowdone>=params->maxflow || nflowdone>=mostflow || params->p>=1.0){
break;
}
nflow++;
if(nflow>params->maxflow || nflow>mostflow){
nflow=1;
notfirstloop=TRUE;
}
fprintf(sp2,"Maximum valid flow on network: %ld\n",mostflow);
if(strlen(outfiles->flowfile)){
FlipFlowArraySign(flows,params,nrow,ncol);
Write2DRowColArray((void **)flows,outfiles->flowfile,nrow,ncol,
sizeof(short));
FlipFlowArraySign(flows,params,nrow,ncol);
}
}
}
if(params->ntilerow==1 && params->ntilecol==1){
signal(SIGINT,SIG_DFL);
signal(SIGHUP,SIG_DFL);
}
Free2DArray((void **)apexes,2*nrow-1);
Free2DArray((void **)iscandidate,2*nrow-1);
Free2DArray((void **)nodes,nrow-1);
free(candidatebag);
free(candidatelist);
free(bkts->bucketbase);
if(strlen(outfiles->conncompfile)){
GrowConnCompsMask(costs,flows,nrow,ncol,incrcosts,outfiles,params);
}
if(params->ntilerow!=1 || params->ntilecol!=1){
GrowRegions(costs,flows,nrow,ncol,incrcosts,outfiles,tileparams,params);
}
Free2DArray((void **)incrcosts,2*nrow-1);
totalcost=EvaluateTotalCost(costs,flows,nrow,ncol,NULL,params);
fprintf(sp1,"Maximum flow on network: %ld\n",mostflow);
fprintf(sp1,"Total solution cost: %.9g\n",(double )totalcost);
fprintf(sp1,"Integrating phase\n");
unwrappedphase=(float **)Get2DMem(nrow,ncol,sizeof(float *),sizeof(float));
IntegratePhase(wrappedphase,unwrappedphase,flows,nrow,ncol);
if(unwrappedest!=NULL){
Add2DFloatArrays(unwrappedphase,unwrappedest,nrow,ncol);
}
FlipPhaseArraySign(unwrappedphase,params,nrow,ncol);
fprintf(sp1,"Writing output to file %s\n",outfiles->outfile);
WriteOutputFile(mag,unwrappedphase,outfiles->outfile,outfiles,
nrow,ncol);
Free2DArray((void **)costs,2*nrow-1);
Free2DArray((void **)mag,nrow);
Free2DArray((void **)wrappedphase,nrow);
Free2DArray((void **)unwrappedphase,nrow);
Free2DArray((void **)flows,2*nrow-1);
free(nnodesperrow);
free(narcsperrow);
return(0);
}