/* Bloch simulator This code takes in time sequences of gradients and B1 field, and simulates the excitation pattern over a 3 dimensional volume. Originally from DC Noll (5/18/03) Adopted by CY Yip */ #include #include #include #include #define MAXNPNTS 100000 #define MAXFOVXY 128 #define MAXFOVZ 64 #define MAXNSHOTS 16 #define PI 3.14159265358979323846 #define GAM 26751. /*Gyromagnetic ratio?*/ int i,j,k,f,z,tindex; short phrf[MAXNPNTS]; /*Phase of the RF? I guess this guy goes from -1 (corr to -pi) to 1 (corr to pi) */ short magrf[MAXNPNTS]; /*Magnitude of the RF?*/ float b1xar[MAXNPNTS]; /*Real part of B1?*/ float b1yar[MAXNPNTS]; /*Imag part of B1?*/ short gx[MAXNPNTS]; /*Gradients*/ short gy[MAXNPNTS]; short gz[MAXNPNTS]; /*float freqmap[256][256];*/ float m[3], tempm[3]; short mfinal[3*MAXFOVZ*MAXFOVXY*MAXFOVXY*MAXNSHOTS]; float dm[3],dm1[3],dm2[3],dm3[3],dm4[3]; float arf; /*Flip angle thing??*/ FILE *ofile, *fid; char fname[50],outfname[50]; float tfinal,fa; /*gscale is multiplied to the grads*/ int fovf,fovz,sumrf,shotn,nshots,pulsen,npulses; float filescale; int npnts,nzpnts; float deltat,tfinal,dgdtmax,pwgza,pwgz,simfovz; double pnttime, gscale, trfpw; /*changed to double type in MGH, 12/3/08, cy*/ char ifn[50], ofn[50], sfn[50];/*, mfn[50]; */ int nz, nf; /*ny;*/ float fstep,zstep; /*int trfpw;*/ int simnpnts; /*int simfovxy,simfovx,simfovy;*/ int simfovf; bloch(int shind/*So I guess it is shot index?*/) { /* integration by rotational forms */ float cphi, sphi, cpsi, spsi, ct, st; float Bmag, Btrans; float Mx0, My0, Mz0; int pindex,gxyindex; float bx, by, bz; float b1x, b1y, xgrad, ygrad, zgrad; float phi; phi=2.0*PI*((float)(shind)/nshots)*trfpw; /*What's that?*/ for (tindex = 0; tindex< simnpnts; tindex++) { /*Within this shot, there are npnts where rf is defined. tindex goes thru those npnts*/ pindex=tindex+shind*npnts; /*the index in the original time line, not within the shot*/ gxyindex=tindex; /* xgrad=gscale/filescale*(cos(phi)*gx[gxyindex]-sin(phi)*gy[gxyindex]); ygrad=gscale/filescale*(cos(phi)*gy[gxyindex]+sin(phi)*gx[gxyindex]); */ /*Why multiply the gradients by gscale?*/ xgrad=gscale*gx[pindex]/filescale; ygrad=gscale*gy[pindex]/filescale; zgrad=gscale*gz[pindex]/filescale; /* Define B-fields */ bx=(b1xar[pindex])*deltat*GAM; /*dM = M x (B*dt*gamma)*/ by=(b1yar[pindex])*deltat*GAM; /* bz=((xgrad*xstep+ygrad*ystep+zgrad*zstep)*GAM + freqmap[y][x]*2*PI)*deltat; /*freqmap is the field map. Why [y][x]?*/ bz= ((zgrad*zstep)*GAM + 2*PI*fstep)*deltat; /* rotations */ Bmag = sqrt(bx*bx+by*by+bz*bz); /*Magnitude of B field*/ Btrans = sqrt(bx*bx+by*by); /*Mag in the trans plane*/ ct = (Bmag > 0 )? bz/Bmag : 1; /*t is theta, wrt +ve z axis*/ st = sqrt(1.0 - ct*ct); /*sine of t*/ cphi = (Btrans > 0 )? bx/Btrans : 1; /*phi: ang. wrt to +x*/ /* sphi = sqrt(1.0 - cphi*cphi); */ /*Why not?*/ sphi = (Btrans > 0 )? by/Btrans : 0; /*M is normalized. after we we rotate the rotational axis to be aligned with B, how much (angle, psi) does M move? dM/|M| = M/|M| x (gamma*B*dt). |1|*|gam*B*dt|sin(pi/2)=dM |dM|=|gam*B*dt|~=the arc length of the unit circle.*/ cpsi = cos(Bmag); spsi = sin(Bmag); Mx0 = m[0]; My0 = m[1]; Mz0 = m[2]; m[0] = cphi*(ct*(cpsi*(ct*(sphi*My0+cphi*Mx0)-st*Mz0) + spsi*(cphi*My0-sphi*Mx0))+st*(ct*Mz0+st*(sphi*My0+cphi*Mx0))) - sphi*(-spsi*(ct*(sphi*My0+cphi*Mx0)-st*Mz0) + cpsi*(cphi*My0-sphi*Mx0)); m[1] = sphi*(ct*(cpsi*(ct*(sphi*My0+cphi*Mx0)-st*Mz0) + spsi*(cphi*My0-sphi*Mx0))+st*(ct*Mz0+st*(sphi*My0+cphi*Mx0))) + cphi*(-spsi*(ct*(sphi*My0+cphi*Mx0)-st*Mz0) + cpsi*(cphi*My0-sphi*Mx0)); m[2] = ct*(ct*Mz0+st*(sphi*My0+cphi*Mx0)) - st*(cpsi*(ct*(sphi*My0+cphi*Mx0)-st*Mz0) + spsi*(cphi*My0-sphi*Mx0)); } /*But no relaxation considered!*/ return 0; } print_parmeters() { printf("files in=%s, out=%s\n",ifn,ofn);/*,mfn);*/ printf("fa=%f\n",fa); printf("simfovf=%d, simfovz=%f, fovf=%d, fovz=%d\n",simfovf,simfovz,fovf,fovz); printf("tfinal=%f\n",tfinal); printf("pnttime=%1.8f\n",pnttime); printf("npnts=%d\n",npnts); printf("arf=%f\n",arf); printf("nshots=%d\n",nshots); printf("npulses=%d\n",npulses); printf("simnpnts=%d\n",simnpnts); printf("therefore sim time = %1.8f\n",simnpnts*pnttime); return 0; } flip_angle() { float totrf, temprf; totrf=0.; for (i=0;i