/* pulse.cc //for generation of the pulse sequences! Ivana Drobnjak and Mark Jenkinson, FMRIB Image Analysis Group Copyright (C) 2005 University of Oxford */ /* Part of FSL - FMRIB's Software Library http://www.fmrib.ox.ac.uk/fsl fsl@fmrib.ox.ac.uk Developed at FMRIB (Oxford Centre for Functional Magnetic Resonance Imaging of the Brain), Department of Clinical Neurology, Oxford University, Oxford, UK LICENCE FMRIB Software Library, Release 5.0 (c) 2012, The University of Oxford (the "Software") The Software remains the property of the University of Oxford ("the University"). The Software is distributed "AS IS" under this Licence solely for non-commercial use in the hope that it will be useful, but in order that the University as a charitable foundation protects its assets for the benefit of its educational and research purposes, the University makes clear that no condition is made or to be implied, nor is any warranty given or to be implied, as to the accuracy of the Software, or that it will be suitable for any particular purpose or for use under any specific conditions. Furthermore, the University disclaims all responsibility for the use which is made of the Software. It further disclaims any liability for the outcomes arising from using the Software. The Licensee agrees to indemnify the University and hold the University harmless from and against any and all claims, damages and liabilities asserted by third parties (including claims for negligence) which arise directly or indirectly from the use of the Software or the sale of any products based on the Software. No part of the Software may be reproduced, modified, transmitted or transferred in any form or by any means, electronic or mechanical, without the express permission of the University. The permission of the University is not required if the said reproduction, modification, transmission or transference is done without financial return, the conditions of this Licence are imposed upon the receiver of the product, and all original and amended source code is included in any transmitted product. You may be held legally responsible for any copyright infringement that is caused or encouraged by your failure to abide by these terms and conditions. You are not permitted under this Licence to use this Software commercially. Use for which any financial return is received shall be defined as commercial use, and includes (1) integration of all or part of the source code or the Software into a product for sale or license by or on behalf of Licensee to third parties or (2) use of the Software or any derivative of it for research with the final aim of developing software products for sale or license to a third party or (3) use of the Software or any derivative of it for research with the final aim of developing non-software products for sale or license to a third party, or (4) use of the Software to provide any service to an external organisation for which payment is received. If you are interested in using the Software commercially, please contact Isis Innovation Limited ("Isis"), the technology transfer company of the University, to negotiate a licence. Contact details are: innovation@isis.ox.ac.uk quoting reference DE/9564. */ #include #include #include #include #include "libprob.h" #include "newmatap.h" #include "newmatio.h" #include "newimage/newimageall.h" #include "utils/options.h" //#include "possumfns.h" #define _GNU_SOURCE 1 #define POSIX_SOURCE 1 using namespace NEWIMAGE; using namespace NEWMAT; using namespace MISCMATHS; using namespace Utilities; using namespace std; const double gammabar=42.58*1e06;//(in Hz/T) string title="pulse \nCopyright(c) 2003, University of Oxford (Ivana Drobnjak and Mark Jenkinson)"; string examples="pulse -i -o [optional arguments]"; Option verbose(string("-v,--verbose"), false, string("switch on diagnostic messages"), false, no_argument); Option help(string("-h,--help"), false, string("display this message"), false, no_argument); Option opt_object(string("-i,--inp"), string(""), string("4D digital brain, resolution can be any."), true, requires_argument); //INPUT pulse sequence properties Option opt_seq(string("--seq"), string("epi"), string("default=epi (epi OR ge)"), false, requires_argument); Option opt_angle(string("--angle"),90, string("default=90 (flip angle in degrees)"), false,requires_argument); Option opt_numvol(string("--numvol"), 1, string("default=1 (number of volumes)"), false, requires_argument); Option opt_numslc(string("--numslc"),1, string("default=1 (number of slices)"), false,requires_argument); Option opt_slcdir(string("--slcdir"), string("z-"), string("default=z- (x+,x-, y+,y- or z+,or z- slice acquisition direction/orientation)"), false, requires_argument); Option opt_phasedir(string("--phasedir"), string("y+"), string("default=y+ (x+,x-, y+,y- or z+,or z- phase encode direction/orientation)"), false, requires_argument); Option opt_readdir(string("--readdir"), string("x+"), string("default=x+ (x+,x-, y+,y- or z+,or z- read-out direction/orientation) "), false, requires_argument); Option opt_slcthk(string("--slcthk"),0.006, string("default=0.006m (slice thickness)"), false,requires_argument); Option opt_gap(string("--gap"),0, string("default=0m (gap between the slices in m)"), false,requires_argument); Option opt_Nx(string("--nx"), 64, string("default=64 (resolution in x of the output image)"), false,requires_argument); Option opt_Ny(string("--ny"), 64, string("default=64 (resolution in y of the output image)"), false,requires_argument); Option opt_dx(string("--dx"),0.004, string("default=0.004m (image voxel x-dimension)"), false,requires_argument); Option opt_dy(string("--dy"),0.004, string("default=0.004m (image voxel y-dimension) "), false,requires_argument); Option opt_BWrec(string("--bw"),100000, string("default=100000Hz ( receiving bandwidth) "), false,requires_argument); Option opt_TE(string("--te"),0.03, string("default=0.03s (the time from the first RF to the first echo (in epi center of the k-space, in GE it is the center of the first line of the k-space)"), false,requires_argument); Option opt_TR(string("--tr"),3, string("default=3s (the time between the two RF pulses applied on the same part of the object (in epi the acquisition time for the whole k-space in GE time for the first line)"), false,requires_argument); Option opt_TRslc(string("--trslc"),0.12, string("default=0.12s (the time that takes for the acquisition of one slice)"), false,requires_argument); Option opt_maxG(string("--maxG"),0.055, string("default=0.055 T/m (maximum gradient strength) "), false,requires_argument); Option opt_risetime(string("--riset"),0.00022, string("default=0.00022s (time it takes for the gradient to reach its max value) "), false,requires_argument); Option opt_zstart(string("--zstart"),0, string("default=0m (the lowest position in the slice direction in m)"), false,requires_argument); Option opt_cover(string("--cover"),100, string("default=100 (phase partial Fourier coverage in %. min=50 max=100)"), false,requires_argument); //OUTPUT matrix Option opt_pulse(string("-o,--out"), string(""), string("pulse sequence matrix"), true, requires_argument); Option opt_kcoord(string("-k,--kcoord"),false, string("default=no (saving k-space coordinates)"), false, no_argument); int nonoptarg; //////////////////////////////////////////////// double round_ivana(const double x, const int n){ //rounds a number up to n digits of precision double xx,xxx,xxxx,nn; nn=MISCMATHS::pow(10.0f,(double) n); xx=nn*x; if (x>0) xxx=floor((float)xx+0.5); else xxx=ceil(xx-0.5); xxxx=xxx/nn; return xxxx; } ///////////////////////////////////////////////////////////////////////////////// Matrix episequence(const int n,const RowVector zc,const int ns,const double ddz,const int slcdir_int, const int phasedir_int, const int readdir_int,const int resX,const int resY, const int bottom, const int top){ // Input parameters: n = number of volumes, ns = number of slices (per volume) // ddz = slice thickness (m) , zc = coordinate of slice centre (m) //EPISEQUENCE MATRIX INPUTFILE //(1)=time in s,(2)=rf angle,(3)=rf frequency bandwidth df(Hz),(4)=rf center frequency fc(Hz),(5)=readout 1/0 (6)=x gradient(T/m),(7)=y gradient(T/m),(8)=z gradient(T/m) ///////////////////////////////// //SLICE DIRECTION //////////////////////////////// int aa=6; int bb=7; int cc=8; //slc if (abs(slcdir_int)==1) cc=8; if (abs(slcdir_int)==2) cc=7; if (abs(slcdir_int)==3) cc=6; //phase if (abs(phasedir_int)==1) bb=8; if (abs(phasedir_int)==2) bb=7; if (abs(phasedir_int)==3) bb=6; //read if (abs(readdir_int)==1) aa=8; if (abs(readdir_int)==2) aa=7; if (abs(readdir_int)==3) aa=6; int bhelp=0; int simdir=1; int phdir=1; int redir=1; if (slcdir_int<0) { bhelp=ns+1; simdir=-1; } if (phasedir_int<0) { phdir=-1; } if (readdir_int<0) { redir=-1; } ///////////////////////////// //INPUT PARAMETERS //////////////////////////// float angle=opt_angle.value(); float angle_rad=angle*M_PI/180; double bw=(double) (opt_BWrec.value());//BW double TE=(double) (opt_TE.value()); double TR=(double) (opt_TR.value()); double TRslc=(double) (opt_TRslc.value()); if (round_ivana(TRslc,5)*ns>round_ivana(TR,5)){ cout<<"WARNING:TR>=TRslc*numslc and your values TR="<round_ivana(TR,5)){ cout<<"TR and TRline and numslc do not agree"< phantom;//consists of gry,wht,csf,fat,mus,con,gli,skn (in that order) read_volume4D(phantom,opt_object.value()); int Nx=phantom.xsize();double xdim=phantom.xdim()*1e-03; int Ny=phantom.ysize();double ydim=phantom.ydim()*1e-03; int Nz=phantom.zsize();double zdim=phantom.zdim()*1e-03; int Nzz=Nz;double zzdim=zdim; print_volume_info(phantom,"object"); ////////////////////////////////////////////////////////////////// RowVector posx(Nx); RowVector posy(Ny); RowVector posz(Nz); ///////////////////////////////////////////////////////////////////////////// // SET UP COORDINATE SYSTEM WITH THE CENTER IN THE CENTER OF THE OBJECT // ///////////////////////////////////////////////////////////////////////////// double xxx=-(Nx-1)/2.0; for (int m=1;m<=Nx;m++){ posx(m)=xxx*xdim; xxx=xxx+1; } double yyy=-(Ny-1)/2.0; for (int m=1;m<=Ny;m++){ posy(m)=yyy*ydim; yyy=yyy+1; } double zzz=-(Nz-1)/2.0; for (int m=1;m<=Nz;m++){ posz(m)=zzz*zdim; zzz=zzz+1; } write_ascii_matrix(posx,opt_pulse.value()+".posx"); write_ascii_matrix(posy,opt_pulse.value()+".posy"); write_ascii_matrix(posz,opt_pulse.value()+".posz"); //////////////////////////////////////////////////////////////////////// // PULSE SEQUENCE // //////////////////////////////////////////////////////////////////////// int ns=opt_numslc.value(); int n= opt_numvol.value(); double slcthk=opt_slcthk.value();//slcthk (m) int resX=opt_Nx.value(); int resY=opt_Ny.value(); double gap=opt_gap.value(); Matrix pulse; ////////////////////////////////////////////////////////////////////////// // SET UP THE VECTOR OF CENTRES OF SLICES // ////////////////////////////////////////////////////////////////////////// string slcdir=opt_slcdir.value(); string phasedir=opt_phasedir.value(); string readdir=opt_readdir.value(); int slcdir_int=1; int phasedir_int=2; int readdir_int=3; //slc if (slcdir=="x+") slcdir_int=3; if (slcdir=="x-") slcdir_int=-3; if (slcdir=="y+") slcdir_int=2; if (slcdir=="y-") slcdir_int=-2; if (slcdir=="z+") slcdir_int=1; if (slcdir=="z-") slcdir_int=-1; //phase if (phasedir=="x+") phasedir_int=3; if (phasedir=="x-") phasedir_int=-3; if (phasedir=="y+") phasedir_int=2; if (phasedir=="y-") phasedir_int=-2; if (phasedir=="z+") phasedir_int=1; if (phasedir=="z-") phasedir_int=-1; //read if (readdir=="x+") readdir_int=3; if (readdir=="x-") readdir_int=-3; if (readdir=="y+") readdir_int=2; if (readdir=="y-") readdir_int=-2; if (readdir=="z+") readdir_int=1; if (readdir=="z-") readdir_int=-1; if (abs(slcdir_int)==abs(phasedir_int) || abs(slcdir_int)==abs(readdir_int) || abs(readdir_int)==abs(phasedir_int)){ cout<<"WARNING: The same gradients used for different directions in the k-space!!"<poszz(Nzz)){ cout<<"WARNING: the center of your slice excides the size of the object, i.e. ss>poszz(Nzz)"<resY) { cout<<"WARNING: Number of lines below the central k-space line (phase) is too big for the k-space:"<