void mcx_validate_config(Config *cfg){ int i,gates,idx1d; if(!cfg->issrcfrom0){ cfg->srcpos.x--;cfg->srcpos.y--;cfg->srcpos.z--; /*convert to C index, grid center*/ } if(cfg->tstart>cfg->tend || cfg->tstep==0.f){ mexErrMsgTxt("incorrect time gate settings"); } if(ABS(cfg->srcdir.x*cfg->srcdir.x+cfg->srcdir.y*cfg->srcdir.y+cfg->srcdir.z*cfg->srcdir.z - 1.f)>1e-5) mexErrMsgTxt("field 'srcdir' must be a unitary vector"); if(cfg->steps.x==0.f || cfg->steps.y==0.f || cfg->steps.z==0.f) mexErrMsgTxt("field 'steps' can not have zero elements"); if(cfg->tend<=cfg->tstart) mexErrMsgTxt("field 'tend' must be greater than field 'tstart'"); gates=(int)((cfg->tend-cfg->tstart)/cfg->tstep+0.5); if(cfg->maxgate>gates) cfg->maxgate=gates; if(cfg->sradius>0.f){ cfg->crop0.x=MAX((int)(cfg->srcpos.x-cfg->sradius),0); cfg->crop0.y=MAX((int)(cfg->srcpos.y-cfg->sradius),0); cfg->crop0.z=MAX((int)(cfg->srcpos.z-cfg->sradius),0); cfg->crop1.x=MIN((int)(cfg->srcpos.x+cfg->sradius),cfg->dim.x-1); cfg->crop1.y=MIN((int)(cfg->srcpos.y+cfg->sradius),cfg->dim.y-1); cfg->crop1.z=MIN((int)(cfg->srcpos.z+cfg->sradius),cfg->dim.z-1); }else if(cfg->sradius==0.f){ memset(&(cfg->crop0),0,sizeof(uint3)); memset(&(cfg->crop1),0,sizeof(uint3)); } if(cfg->medianum==0) mexErrMsgTxt("you must define the 'prop' field in the input structure"); if(cfg->dim.x==0||cfg->dim.y==0||cfg->dim.z==0) mexErrMsgTxt("the 'vol' field in the input structure can not be empty"); if(cfg->steps.x!=1.f && cfg->unitinmm==1.f){ cfg->unitinmm=cfg->steps.x; cfg->steps.x=1.f;cfg->steps.y=1.f;cfg->steps.z=1.f; } if(cfg->unitinmm!=1.f){ for(i=1;i<cfg->medianum;i++){ cfg->prop[i].mus*=cfg->unitinmm; cfg->prop[i].mua*=cfg->unitinmm; } } if(cfg->issavedet && cfg->detnum==0) cfg->issavedet=0; for(i=0;i<cfg->detnum;i++){ if(!cfg->issrcfrom0){ cfg->detpos[i].x--;cfg->detpos[i].y--;cfg->detpos[i].z--; /*convert to C index*/ } } if(1){ cfg->isrowmajor=0; /*matlab is always col-major*/ if(cfg->isrowmajor){ /*from here on, the array is always col-major*/ mcx_convertrow2col(&(cfg->vol), &(cfg->dim)); cfg->isrowmajor=0; } if(cfg->issavedet) mcx_maskdet(cfg); if(cfg->srcpos.x<0.f || cfg->srcpos.y<0.f || cfg->srcpos.z<0.f || cfg->srcpos.x>=cfg->dim.x || cfg->srcpos.y>=cfg->dim.y || cfg->srcpos.z>=cfg->dim.z) mexErrMsgTxt("source position is outside of the volume"); idx1d=(int)(int(cfg->srcpos.z)*cfg->dim.y*cfg->dim.x+int(cfg->srcpos.y)*cfg->dim.x+int(cfg->srcpos.x)); /* if the specified source position is outside the domain, move the source along the initial vector until it hit the domain */ if(cfg->vol && cfg->vol[idx1d]==0){ printf("source (%f %f %f) is located outside the domain, vol[%d]=%d\n", cfg->srcpos.x,cfg->srcpos.y,cfg->srcpos.z,idx1d,cfg->vol[idx1d]); while(cfg->vol[idx1d]==0){ cfg->srcpos.x+=cfg->srcdir.x; cfg->srcpos.y+=cfg->srcdir.y; cfg->srcpos.z+=cfg->srcdir.z; if(cfg->srcpos.x<0.f || cfg->srcpos.y<0.f || cfg->srcpos.z<0.f || cfg->srcpos.x>=cfg->dim.x || cfg->srcpos.y>=cfg->dim.y || cfg->srcpos.z>=cfg->dim.z) mcx_error(-4,"searching non-zero voxel failed along the incident vector",__FILE__,__LINE__); idx1d=(int)(int(cfg->srcpos.z)*cfg->dim.y*cfg->dim.x+int(cfg->srcpos.y)*cfg->dim.x+int(cfg->srcpos.x)); } printf("fixing source position to (%f %f %f)\n",cfg->srcpos.x,cfg->srcpos.y,cfg->srcpos.z); } } cfg->his.maxmedia=cfg->medianum-1; /*skip medium 0*/ cfg->his.detnum=cfg->detnum; cfg->his.colcount=cfg->medianum+1; /*column count=maxmedia+2*/ }
void mcx_loadconfig(FILE *in, Config *cfg){ int i,idx1d; unsigned int gates,itmp; char filename[MAX_PATH_LENGTH]={0}, comment[MAX_PATH_LENGTH],*comm; if(in==stdin) fprintf(stdout,"Please specify the total number of photons: [1000000]\n\t"); MCX_ASSERT(fscanf(in,"%d", &(i) )==1); if(cfg->nphoton==0) cfg->nphoton=i; comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%d\nPlease specify the random number generator seed: [1234567]\n\t",cfg->nphoton); MCX_ASSERT(fscanf(in,"%d", &(cfg->seed) )==1); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%d\nPlease specify the position of the source: [10 10 5]\n\t",cfg->seed); MCX_ASSERT(fscanf(in,"%f %f %f", &(cfg->srcpos.x),&(cfg->srcpos.y),&(cfg->srcpos.z) )==3); comm=fgets(comment,MAX_PATH_LENGTH,in); if(cfg->issrcfrom0==0 && comm!=NULL && sscanf(comm,"%u",&itmp)==1) cfg->issrcfrom0=itmp; if(in==stdin) fprintf(stdout,"%f %f %f\nPlease specify the normal direction of the source fiber: [0 0 1]\n\t", cfg->srcpos.x,cfg->srcpos.y,cfg->srcpos.z); if(!cfg->issrcfrom0){ cfg->srcpos.x--;cfg->srcpos.y--;cfg->srcpos.z--; /*convert to C index, grid center*/ } MCX_ASSERT(fscanf(in,"%f %f %f", &(cfg->srcdir.x),&(cfg->srcdir.y),&(cfg->srcdir.z) )==3); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %f %f\nPlease specify the time gates in seconds (start end and step) [0.0 1e-9 1e-10]\n\t", cfg->srcdir.x,cfg->srcdir.y,cfg->srcdir.z); MCX_ASSERT(fscanf(in,"%f %f %f", &(cfg->tstart),&(cfg->tend),&(cfg->tstep) )==3); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %f %f\nPlease specify the path to the volume binary file:\n\t", cfg->tstart,cfg->tend,cfg->tstep); if(cfg->tstart>cfg->tend || cfg->tstep==0.f){ mcx_error(-9,"incorrect time gate settings",__FILE__,__LINE__); } gates=(unsigned int)((cfg->tend-cfg->tstart)/cfg->tstep+0.5); if(cfg->maxgate>gates) cfg->maxgate=gates; MCX_ASSERT(fscanf(in,"%s", filename)==1); if(cfg->rootpath[0]){ #ifdef WIN32 sprintf(comment,"%s\\%s",cfg->rootpath,filename); #else sprintf(comment,"%s/%s",cfg->rootpath,filename); #endif strncpy(filename,comment,MAX_PATH_LENGTH); } comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%s\nPlease specify the x voxel size (in mm), x dimension, min and max x-index [1.0 100 1 100]:\n\t",filename); MCX_ASSERT(fscanf(in,"%f %u %u %u", &(cfg->steps.x),&(cfg->dim.x),&(cfg->crop0.x),&(cfg->crop1.x))==4); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %u %u %u\nPlease specify the y voxel size (in mm), y dimension, min and max y-index [1.0 100 1 100]:\n\t", cfg->steps.x,cfg->dim.x,cfg->crop0.x,cfg->crop1.x); MCX_ASSERT(fscanf(in,"%f %u %u %u", &(cfg->steps.y),&(cfg->dim.y),&(cfg->crop0.y),&(cfg->crop1.y))==4); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %u %u %u\nPlease specify the z voxel size (in mm), z dimension, min and max z-index [1.0 100 1 100]:\n\t", cfg->steps.y,cfg->dim.y,cfg->crop0.y,cfg->crop1.y); MCX_ASSERT(fscanf(in,"%f %u %u %u", &(cfg->steps.z),&(cfg->dim.z),&(cfg->crop0.z),&(cfg->crop1.z))==4); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %u %u %u\nPlease specify the total types of media:\n\t", cfg->steps.z,cfg->dim.z,cfg->crop0.z,cfg->crop1.z); MCX_ASSERT(fscanf(in,"%u", &(cfg->medianum))==1); cfg->medianum++; comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%d\n",cfg->medianum); cfg->prop=(Medium*)malloc(sizeof(Medium)*cfg->medianum); cfg->prop[0].mua=0.f; /*property 0 is already air*/ cfg->prop[0].mus=0.f; cfg->prop[0].g=0.f; cfg->prop[0].n=1.f; for(i=1;i<(int)cfg->medianum;i++){ if(in==stdin) fprintf(stdout,"Please define medium #%d: mus(1/mm), anisotropy, mua(1/mm) and refractive index: [1.01 0.01 0.04 1.37]\n\t",i); MCX_ASSERT(fscanf(in, "%f %f %f %f", &(cfg->prop[i].mus),&(cfg->prop[i].g),&(cfg->prop[i].mua),&(cfg->prop[i].n))==4); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %f %f %f\n",cfg->prop[i].mus,cfg->prop[i].g,cfg->prop[i].mua,cfg->prop[i].n); } if(in==stdin) fprintf(stdout,"Please specify the total number of detectors and fiber diameter (in mm):\n\t"); MCX_ASSERT(fscanf(in,"%u %f", &(cfg->detnum), &(cfg->detradius))==2); comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%d %f\n",cfg->detnum,cfg->detradius); cfg->detpos=(float4*)malloc(sizeof(float4)*cfg->detnum); if(cfg->issavedet && cfg->detnum==0) cfg->issavedet=0; for(i=0;i<(int)cfg->detnum;i++){ if(in==stdin) fprintf(stdout,"Please define detector #%d: x,y,z (in mm): [5 5 5 1]\n\t",i); MCX_ASSERT(fscanf(in, "%f %f %f", &(cfg->detpos[i].x),&(cfg->detpos[i].y),&(cfg->detpos[i].z))==3); cfg->detpos[i].w=cfg->detradius*cfg->detradius; if(!cfg->issrcfrom0){ cfg->detpos[i].x--;cfg->detpos[i].y--;cfg->detpos[i].z--; /*convert to C index*/ } comm=fgets(comment,MAX_PATH_LENGTH,in); if(in==stdin) fprintf(stdout,"%f %f %f\n",cfg->detpos[i].x,cfg->detpos[i].y,cfg->detpos[i].z); } if(filename[0]){ mcx_loadvolume(filename,cfg); if(cfg->isrowmajor){ /*from here on, the array is always col-major*/ mcx_convertrow2col(&(cfg->vol), &(cfg->dim)); cfg->isrowmajor=0; } if(cfg->issavedet) mcx_maskdet(cfg); if(cfg->srcpos.x<0.f || cfg->srcpos.y<0.f || cfg->srcpos.z<0.f || cfg->srcpos.x>=cfg->dim.x || cfg->srcpos.y>=cfg->dim.y || cfg->srcpos.z>=cfg->dim.z) mcx_error(-4,"source position is outside of the volume",__FILE__,__LINE__); idx1d=((int)floor(cfg->srcpos.z)*cfg->dim.y*cfg->dim.x+(int)floor(cfg->srcpos.y)*cfg->dim.x+(int)floor(cfg->srcpos.x)); /* if the specified source position is outside the domain, move the source along the initial vector until it hit the domain */ if(cfg->vol && cfg->vol[idx1d]==0){ printf("source (%f %f %f) is located outside the domain, vol[%d]=%d\n", cfg->srcpos.x,cfg->srcpos.y,cfg->srcpos.z,idx1d,cfg->vol[idx1d]); while(cfg->vol[idx1d]==0){ cfg->srcpos.x+=cfg->srcdir.x; cfg->srcpos.y+=cfg->srcdir.y; cfg->srcpos.z+=cfg->srcdir.z; printf("fixing source position to (%f %f %f)\n",cfg->srcpos.x,cfg->srcpos.y,cfg->srcpos.z); idx1d=cfg->isrowmajor?(int)(floor(cfg->srcpos.x)*cfg->dim.y*cfg->dim.z+floor(cfg->srcpos.y)*cfg->dim.z+floor(cfg->srcpos.z)):\ (int)(floor(cfg->srcpos.z)*cfg->dim.y*cfg->dim.x+floor(cfg->srcpos.y)*cfg->dim.x+floor(cfg->srcpos.x)); } } }else{ mcx_error(-4,"one must specify a binary volume file in order to run the simulation",__FILE__,__LINE__); } }
void mcx_validate_config(Config *cfg){ int i,gates,idx1d; if(!cfg->issrcfrom0){ cfg->srcpos.x--;cfg->srcpos.y--;cfg->srcpos.z--; /*convert to C index, grid center*/ } if(cfg->tstart>cfg->tend || cfg->tstep==0.f){ mexErrMsgTxt("incorrect time gate settings"); } if(ABS(cfg->srcdir.x*cfg->srcdir.x+cfg->srcdir.y*cfg->srcdir.y+cfg->srcdir.z*cfg->srcdir.z - 1.f)>1e-5) mexErrMsgTxt("field 'srcdir' must be a unitary vector"); if(cfg->steps.x==0.f || cfg->steps.y==0.f || cfg->steps.z==0.f) mexErrMsgTxt("field 'steps' can not have zero elements"); if(cfg->tend<=cfg->tstart) mexErrMsgTxt("field 'tend' must be greater than field 'tstart'"); gates=(int)((cfg->tend-cfg->tstart)/cfg->tstep+0.5); if(cfg->maxgate>gates) cfg->maxgate=gates; if(cfg->sradius>0.f){ cfg->crop0.x=MAX((int)(cfg->srcpos.x-cfg->sradius),0); cfg->crop0.y=MAX((int)(cfg->srcpos.y-cfg->sradius),0); cfg->crop0.z=MAX((int)(cfg->srcpos.z-cfg->sradius),0); cfg->crop1.x=MIN((int)(cfg->srcpos.x+cfg->sradius),cfg->dim.x-1); cfg->crop1.y=MIN((int)(cfg->srcpos.y+cfg->sradius),cfg->dim.y-1); cfg->crop1.z=MIN((int)(cfg->srcpos.z+cfg->sradius),cfg->dim.z-1); }else if(cfg->sradius==0.f){ memset(&(cfg->crop0),0,sizeof(uint3)); memset(&(cfg->crop1),0,sizeof(uint3)); }else{ /* if -R is followed by a negative radius, mcx uses crop0/crop1 to set the cachebox */ if(!cfg->issrcfrom0){ cfg->crop0.x--;cfg->crop0.y--;cfg->crop0.z--; /*convert to C index*/ cfg->crop1.x--;cfg->crop1.y--;cfg->crop1.z--; } } if(cfg->medianum==0) mexErrMsgTxt("you must define the 'prop' field in the input structure"); if(cfg->dim.x==0||cfg->dim.y==0||cfg->dim.z==0) mexErrMsgTxt("the 'vol' field in the input structure can not be empty"); if(cfg->srctype==MCX_SRC_PATTERN && cfg->srcpattern==NULL) mexErrMsgTxt("the 'srcpattern' field can not be empty when your 'srctype' is 'pattern'"); if(cfg->steps.x!=1.f && cfg->unitinmm==1.f) cfg->unitinmm=cfg->steps.x; if(cfg->unitinmm!=1.f){ cfg->steps.x=cfg->unitinmm; cfg->steps.y=cfg->unitinmm; cfg->steps.z=cfg->unitinmm; for(i=1;i<cfg->medianum;i++){ cfg->prop[i].mus*=cfg->unitinmm; cfg->prop[i].mua*=cfg->unitinmm; } } if(cfg->issavedet && cfg->detnum==0) cfg->issavedet=0; if(cfg->seed<0 && cfg->seed!=SEED_FROM_FILE) cfg->seed=time(NULL); if(cfg->outputtype==otJacobian && cfg->seed!=SEED_FROM_FILE) mexErrMsgTxt("Jacobian output is only valid in the reply mode. Please define cfg.seed"); for(i=0;i<cfg->detnum;i++){ if(!cfg->issrcfrom0){ cfg->detpos[i].x--;cfg->detpos[i].y--;cfg->detpos[i].z--; /*convert to C index*/ } } if(1){ cfg->isrowmajor=0; /*matlab is always col-major*/ if(cfg->isrowmajor){ /*from here on, the array is always col-major*/ mcx_convertrow2col(&(cfg->vol), &(cfg->dim)); cfg->isrowmajor=0; } if(cfg->issavedet) mcx_maskdet(cfg); if(cfg->seed==SEED_FROM_FILE){ if(cfg->respin>1){ cfg->respin=1; fprintf(stderr,"Warning: respin is disabled in the replay mode\n"); } } } cfg->his.maxmedia=cfg->medianum-1; /*skip medium 0*/ cfg->his.detnum=cfg->detnum; cfg->his.colcount=cfg->medianum+1; /*column count=maxmedia+2*/ mcx_replay_prep(cfg); }