pulsesequence() { /* Internal variable declarations *************************/ /*timing*/ double tr_delay; double te_d1,te_d2,te_d3; /* delays */ double tau1,tau2,tau3; /*voxel crusher multipliers */ double fx,fy,fz; /*localization parameters*/ double freq1,freq2,freq3; double vox1_cr,vox2_cr, vox3_cr; int nDim; double rprof,pprof,sprof; char profile_vox[MAXSTR],profile_ovs[MAXSTR]; double restol, resto_local, csd_ppm; /*phase cycle****/ int counter,noph; char autoph[MAXSTR], pcflag[MAXSTR]; int rf1_phase[64] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}; int rf2_phase[64] = {0,0,0,0,2,2,2,2,1,1,1,1,3,3,3,3,0,0,0,0,2,2,2,2,1,1,1,1,3,3,3,3, 0,0,0,0,2,2,2,2,1,1,1,1,3,3,3,3,0,0,0,0,2,2,2,2,1,1,1,1,3,3,3,3}; int rf3_phase[64] = {0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3, 0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3,0,2,1,3}; /* Initialize paramaters **********************************/ init_mri(); //this gets all the parameters that are defined in acqparms.h, etc get_wsparameters(); get_ovsparameters(); rprof = getval("rprof"); pprof = getval("pprof"); sprof = getval("sprof"); //read the crusher factors that are designed to create grad on the same axis without refoc fx=getval("fx"); fy=getval("fy"); fz=getval("fz"); getstr("profile_vox",profile_vox); getstr("profile_ovs",profile_ovs); /*set voxel sizes for butterfly crushers to 10^6 to set the slice portion to zero ***/ vox1_cr=1000000; vox2_cr=1000000; vox3_cr=1000000; /***** RF power initialize *****/ init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2); init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof2); /***** Initialize gradient structs *****/ trampfixed=trise; //rise time =trise tcrush=granularity(tcrush,GRADIENT_RES); //this is to avoid the granularity errors //if trampfixed is used, rise time needs to be checked if (trise*2>tcrush){ abort_message("tcrush too short. Minimum tcrush = %fms \n",1000*trise*2); } if (gcrush>gmax){ abort_message("gcrush too large. Max gcrush = %f \n",gmax*0.95); } init_slice_butterfly(&vox1_grad,"vox1",vox1,gcrush,tcrush); init_slice_butterfly(&vox2_grad,"vox2",vox2,gcrush,tcrush); init_slice_butterfly(&vox3_grad,"vox3",vox3,gcrush,tcrush); init_slice_butterfly(&vox1_crush,"vox1_crush",vox1_cr,gcrush,tcrush); init_slice_butterfly(&vox2_crush,"vox2_crush",vox2_cr,gcrush,tcrush); init_slice_butterfly(&vox3_crush,"vox3_crush",vox3_cr,gcrush,tcrush); if (profile_vox[0] == 'y') { init_readout_butterfly(&ro_grad,"ro",lro,np,sw,gcrushro,tcrushro); init_readout_refocus(&ror_grad,"ror"); } /***** RF and Gradient calculations *****/ calc_rf(&p1_rf,"tpwr1","tpwr1f"); calc_rf(&p2_rf,"tpwr2","tpwr2f"); calc_slice(&vox1_grad,&p2_rf,WRITE,"gvox1"); calc_slice(&vox2_grad,&p2_rf,WRITE,"gvox2"); calc_slice(&vox3_grad,&p2_rf,WRITE,"gvox3"); calc_slice(&vox1_crush,&p2_rf,WRITE,"vox1_crush"); calc_slice(&vox2_crush,&p2_rf,WRITE,"vox2_crush"); calc_slice(&vox3_crush,&p2_rf,WRITE,"vox3_crush"); if (profile_vox[0] == 'y') { calc_readout(&ro_grad,WRITE,"gro","sw","at"); putvalue("gro",ro_grad.roamp); // RO grad calc_readout_refocus(&ror_grad,&ro_grad,WRITE,"gror"); putvalue("tror",ror_grad.duration); // ROR duration } //set all gradients along a particular direction to zero if profile is needed if (profile_ovs[0]=='y'){ if (rprof==1) { vox1_grad.amp=0; //set slice selection in read direction to none vox3_crush.amp=0; // set corresponding crusher gradients to none } else if(pprof==1) { vox2_grad.amp=0; vox1_crush.amp=0; } else if(sprof==1) { vox3_grad.amp=0; vox2_crush.amp=0; } } /* Optional OVS and Water Suppression */ if (ovs[0] == 'y') create_ovsbands(); if (sat[0] == 'y') create_satbands(); if (ws[0] == 'y') create_watersuppress(); //Read in parameters not defined in acqparms.h and sglHelper nDim=getval("nDim"); restol=getval("restol"); //local frequency offset roff=getval("roff"); //receiver offset csd_ppm=getval("csd_ppm"); //chemical shift displacement factor noph=getval("noph"); getstr("autoph",autoph); getstr("pcflag",pcflag); settable(t3,noph,rf1_phase); settable(t2,noph,rf2_phase); settable(t1,noph,rf3_phase); /* tau1, tau2 and tau3 are sums of all events in TE*/ tau1 = vox1_grad.rfCenterFront+GDELAY+rof2; tau2 = vox1_grad.rfCenterBack + vox1_grad.rfCenterFront+2*(GDELAY+rof2); tau3 = vox3_grad.rfCenterBack+GDELAY+rof2; temin = tau1+5.0*tau2+tau3; if (minte[0] == 'y') { te = temin; putvalue("te",te); } if (te < temin) { abort_message("te too short. Minimum te = %.2f ms\n",temin*1000); } /***** Calculate TE delays *****/ te_d1 = te/12.0 - tau1+GDELAY; te_d2 = te/6.0 - tau2+2*(GDELAY+rof2); te_d3 = te/12.0 - tau3+GDELAY+rof2; //Calculate delta from resto to include local frequency line+ chemical shift offset resto_local=resto-restol; /***** Min TR *****/ trmin = GDELAY + p1 + te + at+rof1+rof2; if (ws[0] == 'y') trmin += wsTime; if (ovs[0] == 'y') trmin += ovsTime; if (sat[0] == 'y') trmin += satTime; if (profile_vox[0] == 'y') trmin += ror_grad.duration + ro_grad.duration - at; if (mintr[0] == 'y') { tr = trmin; // ensure at least 4us between gradient events putvalue("tr",tr); } if ((trmin-tr) > 12.5e-9) { abort_message("TR too short. Minimum TR= %.2fms\n",trmin*1000); } /***** Calculate TR delay *****/ tr_delay = tr - trmin; /* Frequency offsets */ freq1 = poffset(pos1,vox1_grad.ssamp); // First RF pulse freq2 = poffset(pos2,vox2_grad.ssamp); // Second RF pulse freq3 = poffset(pos3,vox3_grad.ssamp); // Third RF pulse freq1=freq1-csd_ppm*sfrq; freq2=freq2-csd_ppm*sfrq; freq3=freq3-csd_ppm*sfrq; /* Frequency offsets */ if (profile_vox[0] == 'y') { /* Shift DDR for pro ************************************/ roff = -poffset(pro,ro_grad.roamp); } /* Put gradient information back into VnmrJ parameters */ putvalue("gvox1",vox1_grad.ssamp); putvalue("gvox2",vox2_grad.ssamp); putvalue("gvox3",vox3_grad.ssamp); putvalue("rgvox1",vox1_grad.tramp); putvalue("rgvox2",vox2_grad.tramp); putvalue("rgvox3",vox3_grad.tramp); sgl_error_check(sglerror); if (ss<0) g_setExpTime(tr*(nt-ss)*arraydim); else g_setExpTime(tr*(nt*arraydim+ss)); /**[2.7] PHASE CYCLING ******************************************************/ assign(zero, oph); counter=(double)nt*(ix-1); if (autoph[0] == 'n') counter=0.0; //only goes through nt, if 'y' goes through nt*array initval(counter,v1); initval(noph,v3); add(v1,ct,v2); modn(v2,v3,v2); /* Full phase cycling requires 64 steps*/ if (pcflag[0] == 'n') { assign(zero,v2); getelem(t1,v2,v10); getelem(t2,v2,v11); getelem(t3,v2,v12); } else { getelem(t1,v2,v10); getelem(t2,v2,v11); getelem(t3,v2,v12); } /*Start of the sequence*/ obsoffset(resto_local); // need it here for water suppression to work delay(GDELAY); rot_angle(vpsi,vphi,vtheta); if (ticks) { xgate(ticks); grad_advance(gpropdelay); delay(4e-6); } /* TTL scope trigger **********************************/ //sp1on(); delay(4e-6); sp1off(); /* Saturation bands ***********************************/ if (ovs[0] == 'y') ovsbands(); if (sat[0] == 'y') satbands(); /* Water suppression **********************************/ if (ws[0] == 'y') watersuppress(); /* Slice selective 90 degree RF pulse *****/ obspower(p1_rf.powerCoarse); obspwrf(p1_rf.powerFine); delay(GDELAY); shaped_pulse(p1pat,p1,zero,rof1,rof2); /* start localization */ obspower(p2_rf.powerCoarse); obspwrf(p2_rf.powerFine); if (nDim > 2.5) { delay(te_d1); //this is at least GDELAY == 4 us obl_shaped3gradient(vox1_grad.name,vox1_crush.name,"",vox1_grad.duration,vox1_grad.amp,fy*vox1_crush.amp,0,NOWAIT); delay(vox1_grad.rfDelayFront); if (profile_ovs[0]=='y'&& rprof==1) freq1=0.0; shapedpulseoffset(p2_rf.pulseName,vox1_grad.rfDuration,v12,rof1,rof2,freq1); delay(vox1_grad.rfDelayBack); delay(te_d2); obl_shaped3gradient (vox1_grad.name,vox1_crush.name,"",vox1_grad.duration,vox1_grad.amp,fy*0.777*vox1_crush.amp,0,NOWAIT); delay(vox1_grad.rfDelayFront); if (profile_ovs[0]=='y'&& rprof==1) freq1=0.0; shapedpulseoffset(p2_rf.pulseName,vox1_grad.rfDuration,v12,rof1,rof2,freq1); delay(vox1_grad.rfDelayBack); delay(te_d2); } if (nDim > 1.5) { //this is 2nd slice selection obl_shaped3gradient("",vox2_grad.name,vox2_crush.name,vox2_grad.duration,0,vox2_grad.amp,fz*vox2_crush.amp,NOWAIT); delay(vox2_grad.rfDelayFront); if (profile_ovs[0]=='y'&& pprof==1) freq2=0.0; shapedpulseoffset(p2_rf.pulseName,vox2_grad.rfDuration,v11,rof1,rof2,freq2); delay(vox2_grad.rfDelayBack); delay(te_d2); obl_shaped3gradient("",vox2_grad.name,vox2_crush.name,vox2_grad.duration,0,vox2_grad.amp,fz*0.777*vox2_crush.amp,NOWAIT); delay(vox2_grad.rfDelayFront); if (profile_ovs[0]=='y'&& pprof==1) freq2=0.0; shapedpulseoffset(p2_rf.pulseName,vox2_grad.rfDuration,v11,rof1,rof2,freq2); delay(vox2_grad.rfDelayBack); delay(te_d2); } if (nDim > 0.5){ //this is 3rd slice selection obl_shaped3gradient(vox3_crush.name,"",vox3_grad.name,vox3_grad.duration,fx*vox3_crush.amp,0,vox3_grad.amp,NOWAIT); delay(vox3_grad.rfDelayFront); if (profile_ovs[0]=='y'&& sprof==1) freq3=0.0; shapedpulseoffset(p2_rf.pulseName,vox3_grad.rfDuration,v10,rof1,rof2,freq3); delay(vox3_grad.rfDelayBack); delay(te_d2); obl_shaped3gradient(vox3_crush.name,"",vox3_grad.name,vox3_grad.duration,fx*vox3_crush.amp,0,vox3_grad.amp,NOWAIT); delay(vox3_grad.rfDelayFront); if (profile_ovs[0]=='y'&& sprof==1) freq3=0.0; shapedpulseoffset(p2_rf.pulseName,vox3_grad.rfDuration,v10,rof1,rof2,freq3); delay(vox3_grad.rfDelayBack); delay(te_d3); } if (profile_vox[0] == 'y') { obl_shapedgradient(ror_grad.name,ror_grad.duration, -rprof*ror_grad.amp,-pprof*ror_grad.amp,-sprof*ror_grad.amp,WAIT); delay(GDELAY); obl_shapedgradient(ro_grad.name,ro_grad.duration, rprof*ro_grad.amp,pprof*ro_grad.amp,sprof*ro_grad.amp,NOWAIT); delay(ro_grad.atDelayFront); startacq(alfa); acquire(np,1.0/sw); delay(ro_grad.atDelayBack); endacq(); } else { startacq(alfa); acquire(np,1.0/sw); endacq(); } delay(tr_delay);
pulsesequence() { /* Internal variable declarations *************************/ int shapelist90,shapelist180,shapelistIR; double nseg; double seqtime,tau1,tau2,tau3, te1_delay,te2_delay,te3_delay, iti_delay, ti_delay, tr_delay; double kzero; double freq90[MAXNSLICE], freq180[MAXNSLICE], freqIR[MAXNSLICE]; /* Real-time variables used in this sequence **************/ int vpe_ctr = v2; // PE loop counter int vpe_mult = v3; // PE multiplier, ranges from -PE/2 to PE/2 int vms_slices = v4; // Number of slices int vms_ctr = v5; // Slice loop counter int vseg = v6; // Number of ETL segments int vseg_ctr = v7; // Segment counter int vetl = v8; // Echo train length int vetl_ctr = v9; // Echo train loop counter int vssc = v10; // Compressed steady-states int vtrimage = v11; // Counts down from nt, trimage delay when 0 int vacquire = v12; // Argument for setacqvar, to skip steady state acquires int vphase180 = v13; // phase of 180 degree refocusing pulse /* Initialize paramaters **********************************/ init_mri(); /* Load external PE table ********************************/ if (strcmp(petable,"n") && strcmp(petable,"N") && strcmp(petable,"")) { loadtable(petable); } else { abort_message("petable undefined"); } seqtime = 0.0; espmin = 0.0; kzero = getval("kzero"); /* RF Power & Bandwidth Calculations **********************/ init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2); init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof2); calc_rf(&p1_rf,"tpwr1","tpwr1f"); calc_rf(&p2_rf,"tpwr2","tpwr2f"); /* Initialize gradient structures *************************/ init_readout_butterfly(&ro_grad,"ro",lro,np,sw,gcrushro,tcrushro); init_readout_refocus(&ror_grad,"ror"); init_phase(&pe_grad,"pe",lpe,nv); init_slice(&ss_grad,"ss",thk); /* NOTE assume same band widths for p1 and p2 */ init_slice_butterfly(&ss2_grad,"ss2",thk,gcrush,tcrush); init_slice_refocus(&ssr_grad,"ssr"); /* Gradient calculations **********************************/ calc_readout(&ro_grad,WRITE,"gro","sw","at"); calc_readout_refocus(&ror_grad,&ro_grad,NOWRITE,"gror"); calc_phase(&pe_grad,WRITE,"gpe","tpe"); calc_slice(&ss_grad,&p1_rf,WRITE,"gss"); calc_slice(&ss2_grad,&p1_rf,WRITE,""); calc_slice_refocus(&ssr_grad,&ss_grad,NOWRITE,"gssr"); /* Equalize refocus and PE gradient durations *************/ calc_sim_gradient(&ror_grad,&null_grad,&ssr_grad,0.0,WRITE); /* Create optional prepulse events ************************/ if (sat[0] == 'y') create_satbands(); if (fsat[0] == 'y') create_fatsat(); if (mt[0] == 'y') create_mtc(); if (ir[0] == 'y') { init_rf(&ir_rf,pipat,pi,flipir,rof1,rof2); calc_rf(&ir_rf,"tpwri","tpwrif"); init_slice_butterfly(&ssi_grad,"ssi",thk,gcrushir,tcrushir); calc_slice(&ssi_grad,&ir_rf,WRITE,"gssi"); } /* Set up frequency offset pulse shape list ********/ offsetlist(pss,ss_grad.ssamp, 0,freq90, ns,seqcon[1]); offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]); offsetlist(pss,ssi_grad.ssamp,0,freqIR, ns,seqcon[1]); shapelist90 = shapelist(p1pat,ss_grad.rfDuration, freq90, ns,0,seqcon[1]); shapelist180 = shapelist(p2pat,ss2_grad.rfDuration,freq180,ns,0,seqcon[1]); shapelistIR = shapelist(pipat,ssi_grad.rfDuration,freqIR, ns,0,seqcon[1]); /* same slice selection gradient and RF pattern used */ if (ss_grad.rfFraction != 0.5) abort_message("ERROR %s: RF pulse must be symmetric (RF fraction = %.2f)", seqfil,ss_grad.rfFraction); if (ro_grad.echoFraction != 1) abort_message("ERROR %s: Echo Fraction must be 1",seqfil); /* Find sum of all events in each half-echo period ********/ tau1 = ss_grad.rfCenterBack + ssr_grad.duration + ss2_grad.rfCenterFront; tau2 = ss2_grad.rfCenterBack + pe_grad.duration + ro_grad.timeToEcho; tau3 = ro_grad.timeFromEcho + pe_grad.duration + ss2_grad.rfCenterFront; espmin = 2*MAX(MAX(tau1,tau2),tau3); // Minimum echo spacing if (minesp[0] == 'y') { esp = espmin + 8e-6; // ensure at least 4us delays in both TE periods putvalue("esp",esp); } else if (((espmin+8e-6)-esp) > 12.5e-9) { abort_message("ERROR %s: Echo spacing too small, minimum is %.2fms\n",seqfil,(espmin+8e-6)*1000); } te1_delay = esp/2.0 - tau1; // Intra-esp delays te2_delay = esp/2.0 - tau2; te3_delay = esp/2.0 - tau3; te = kzero*esp; // Return effective TE putvalue("te",te); /* Minimum TR **************************************/ /* seqtime is total time per slice */ seqtime = 2*4e-6 + ss_grad.rfCenterFront + etl*esp + ro_grad.timeFromEcho + pe_grad.duration + te3_delay; /* Increase TR if any options are selected****************/ if (sat[0] == 'y') seqtime += ns*satTime; if (fsat[0] == 'y') seqtime += ns*fsatTime; if (mt[0] == 'y') seqtime += ns*mtTime; if (ir[0] == 'y') { /* Inter-IR delay */ if (ns > 1) iti_delay = seqtime - ssi_grad.duration; /* it is probably safe to assume that seqtime is always > the pulse widths */ else iti_delay = 0; /* Inversion Recovery */ timin = ssi_grad.rfCenterBack + ss_grad.rfCenterFront; timin += 8e-6; // from sp1on/off and after 90 pulse power setting timin += seqtime*(ns-1) + iti_delay; if (ti < timin + 4e-6) // ensure at least a 4us delay abort_message("%s: ti too short, minimum is %.2fms",seqfil,timin*1000); /* Delay after the last IR pulse */ ti_delay = ti - timin; /* force all slices to be acquired back-to-back, with a single TR delay at end */ trtype = 1; } else { iti_delay = ti_delay = 0; } trmin = ns*(seqtime + 4e-6); if (ir[0] == 'y') { trmin += (4e-6 + ssi_grad.rfCenterFront + ti); } if (mintr[0] == 'y'){ tr = trmin; putvalue("tr",tr); } if ((trmin-tr) > 12.5e-9) { abort_message("TR too short. Minimum TR = %.2fms\n",trmin*1000); } tr_delay = (tr - trmin)/ns; /* Set number of segments for profile or full image **********/ nseg = prep_profile(profile[0],nv/etl,&pe_grad,&per_grad); /* Shift DDR for pro *******************************/ roff = -poffset(pro,ro_grad.roamp); /* Calculate total acquisition time */ g_setExpTime(tr*(nt*nseg*getval("arraydim") + ssc) + trimage*getval("arraydim")); /* Return parameters to VnmrJ */ putvalue("rgss",ss_grad.tramp); //90 slice ramp if (ss2_grad.enableButterfly) { //180 slice ramps putvalue("rcrush",ss2_grad.crusher1RampToCrusherDuration); putvalue("rgss2",ss2_grad.crusher1RampToSsDuration); } else { putvalue("rgss2",ss2_grad.tramp); } if (ro_grad.enableButterfly) { putvalue("rgro",ro_grad.crusher1RampToSsDuration); } else { putvalue("rgro",ro_grad.tramp); //RO ramp } putvalue("tror",ror_grad.duration); //ROR duration putvalue("rgror",ror_grad.tramp); //ROR ramp putvalue("gpe",pe_grad.peamp); //PE max amp putvalue("gss",ss_grad.ssamp); putvalue("gro",ro_grad.roamp); /* PULSE SEQUENCE *************************************/ initval(fabs(ssc),vssc); // Compressed steady-state counter assign(one,vacquire); // real-time acquire flag /* Phase cycle: Alternate 180 phase to cancel residual FID */ mod2(ct,vphase180); // 0101 dbl(vphase180,vphase180); // 0202 add(vphase180,one,vphase180); // 1313 Phase difference from 90 add(vphase180,oph,vphase180); obsoffset(resto); delay(4e-6); initval(nseg,vseg); loop(vseg,vseg_ctr); /* TTL scope trigger **********************************/ sp1on(); delay(4e-6); sp1off(); /* Compressed steady-states: 1st array & transient, all arrays if ssc is negative */ if ((ix > 1) && (ssc > 0)) assign(zero,vssc); sub(vseg_ctr,vssc,vseg_ctr); // vpe_ctr counts up from -ssc assign(zero,vssc); ifzero(vseg_ctr); assign(zero,vacquire); // Start acquiring when vseg_ctr reaches zero endif(vseg_ctr); setacqvar(vacquire); // Turn on acquire when vacquire is zero if (ticks) { xgate(ticks); grad_advance(gpropdelay); delay(4e-6); } if(ir[0] == 'y') { /* IR for all slices prior to data acquisition */ obspower(ir_rf.powerCoarse); obspwrf(ir_rf.powerFine); delay(4e-6); msloop(seqcon[1],ns,vms_slices,vms_ctr); obl_shapedgradient(ssi_grad.name,ssi_grad.duration,0,0,ssi_grad.amp,NOWAIT); delay(ssi_grad.rfDelayFront); shapedpulselist(shapelistIR,ssi_grad.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ssi_grad.rfDelayBack); delay(iti_delay); endmsloop(seqcon[1],vms_ctr); delay(ti_delay); } msloop(seqcon[1],ns,vms_slices,vms_ctr); /* Prepulse options ***********************************/ if (sat[0] == 'y') satbands(); if (fsat[0] == 'y') fatsat(); if (mt[0] == 'y') mtc(); /* 90 degree pulse ************************************/ rotate(); obspower(p1_rf.powerCoarse); obspwrf(p1_rf.powerFine); delay(4e-6); obl_shapedgradient(ss_grad.name,ss_grad.duration,0,0,ss_grad.amp,NOWAIT); delay(ss_grad.rfDelayFront); shapedpulselist(shapelist90,ss_grad.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ss_grad.rfDelayBack); /* Read dephase and Slice refocus *********************/ obl_shapedgradient(ssr_grad.name,ssr_grad.duration,ror_grad.amp,0.0,-ssr_grad.amp,WAIT); /* First half-TE delay ********************************/ obspower(p2_rf.powerCoarse); obspwrf(p2_rf.powerFine); delay(te1_delay); peloop(seqcon[2],etl,vetl,vetl_ctr); mult(vseg_ctr,vetl,vpe_ctr); add(vpe_ctr,vetl_ctr,vpe_ctr); getelem(t1,vpe_ctr,vpe_mult); /* 180 degree pulse *******************************/ /* Note, ss2_grad.amp is max gradient for butterfly shape; flat top = _.ssamp */ obl_shapedgradient(ss2_grad.name,ss2_grad.duration,0,0,ss2_grad.amp,NOWAIT); delay(ss2_grad.rfDelayFront); shapedpulselist(shapelist180,ss2_grad.rfDuration,vphase180,rof1,rof2,seqcon[1],vms_ctr); delay(ss2_grad.rfDelayBack); /* Phase-encode gradient ******************************/ pe_shapedgradient(pe_grad.name,pe_grad.duration,0,0,0,-pe_grad.increment,vpe_mult,WAIT); /* Second half-TE period ******************************/ delay(te2_delay); /* Readout gradient ************************************/ obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT); delay(ro_grad.atDelayFront); /* Acquire data ****************************************/ startacq(alfa); acquire(np,1.0/sw); endacq(); delay(ro_grad.atDelayBack); /* Rewinding phase-encode gradient ********************/ /* Phase encode, refocus, and dephase gradient ******************/ pe_shapedgradient(pe_grad.name,pe_grad.duration,0,0,0,pe_grad.increment,vpe_mult,WAIT); /* Second half-TE delay *******************************/ delay(te3_delay); endpeloop(seqcon[2],vetl_ctr); /* Relaxation delay ***********************************/ if (!trtype) delay(tr_delay); endmsloop(seqcon[1],vms_ctr); if (trtype) delay(ns*tr_delay); endloop(vseg_ctr); /* Inter-image delay **********************************/ sub(ntrt,ct,vtrimage); decr(vtrimage); ifzero(vtrimage); delay(trimage); endif(vtrimage); }
pulsesequence() { /* Internal variable declarations *************************/ double freqEx[MAXNSLICE], freqIR[MAXNSLICE]; double pe_steps,pespoil_amp; double perTime, seqtime, tau1, tauIR=0, te_delay, tr_delay, ti_delay=0; int table, shapeEx, shapeIR=0; char spoilflag[MAXSTR],per_name[MAXSTR]; /* Real-time variables used in this sequence **************/ int vpe_steps = v1; // Number of PE steps int vpe_ctr = v2; // PE loop counter int vms_slices = v3; // Number of slices int vms_ctr = v4; // Slice loop counter int vpe_offset = v5; // PE/2 for non-table offset int vpe_mult = v6; // PE multiplier, ranges from -PE/2 to PE/2 int vper_mult = v7; // PE rewinder multiplier; turn off rewinder when 0 int vssc = v8; // Compressed steady-states int vacquire = v9; // Argument for setacqvar, to skip steady state acquires int vrfspoil_ctr = v10; // RF spoil counter int vrfspoil = v11; // RF spoil multiplier int vtrimage = v12; // Counts down from nt, trimage delay when 0 /* Initialize paramaters **********************************/ get_parameters(); get_ovsparameters(); getstr("spoilflag",spoilflag); /* Check for external PE table ***************************/ table = 0; if (strcmp(petable,"n") && strcmp(petable,"N") && strcmp(petable,"")) { loadtable(petable); table = 1; } /* Set Rcvr/Xmtr phase increments for RF Spoiling ********/ /* Ref: Zur, Y., Magn. Res. Med., 21, 251, (1991) *******/ if (rfspoil[0] == 'y') { rcvrstepsize(rfphase); obsstepsize(rfphase); } /* Initialize gradient structures *************************/ init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2 ); // excitation pulse init_slice(&ss_grad,"ss",thk); // slice select gradient init_slice_refocus(&ssr_grad,"ssr"); // slice refocus gradient init_readout(&ro_grad,"ro",lro,np,sw); // readout gradient init_readout_refocus(&ror_grad,"ror"); // dephase gradient init_phase(&pe_grad,"pe",lpe,nv); // phase encode gradient init_phase(&per_grad,"per",lpe,nv); // phase encode gradient init_generic(&spoil_grad,"spoil",gspoil,tspoil); // spoiler gradient /* RF Calculations ****************************************/ calc_rf(&p1_rf,"tpwr1","tpwr1f"); /* Gradient calculations **********************************/ calc_slice(&ss_grad,&p1_rf,WRITE,"gss"); calc_slice_refocus(&ssr_grad, &ss_grad, NOWRITE,"gssr"); calc_readout(&ro_grad, WRITE, "gro","sw","at"); calc_readout_refocus(&ror_grad, &ro_grad, NOWRITE, "gror"); calc_phase(&pe_grad, NOWRITE, "gpe","tpe"); /* Equalize refocus and PE gradient durations *************/ calc_sim_gradient(&ror_grad, &pe_grad, &ssr_grad,tpemin, WRITE); /* Calculate phase-rewind & spoiler gradients *************/ pespoil_amp = 0.0; perTime = 0.0; if ((perewind[0] == 'y') && (spoilflag[0] == 'n')) { // Rewinder, no spoiler calc_phase(&per_grad,WRITE,"",""); strcpy(per_name,per_grad.name); perTime = per_grad.duration; spoil_grad.amp = 0.0; } else if ((perewind[0] == 'n') && (spoilflag[0] == 'y')) { // Spoiler, no rewinder calc_generic(&spoil_grad,WRITE,"",""); strcpy(per_name,spoil_grad.name); perTime = spoil_grad.duration; pespoil_amp = spoil_grad.amp; // Apply spoiler on PE axis if no rewinder } else if ((perewind[0] == 'y') && (spoilflag[0] == 'y')) { // Rewinder and spoiler calc_phase(&per_grad,NOWRITE,"",""); calc_generic(&spoil_grad,NOWRITE,"",""); calc_sim_gradient(&per_grad,&spoil_grad,&null_grad,0.0,WRITE); strcpy(per_name,per_grad.name); perTime = per_grad.duration; } /* Create optional prepulse events ************************/ if (sat[0] == 'y') create_satbands(); if (fsat[0] == 'y') create_fatsat(); if (mt[0] == 'y') create_mtc(); if (ovs[0] == 'y') { /* Must set up a few voxel specific parameters for create_ovsbands() to function */ vox1_grad.thickness = vox1; vox2_grad.thickness = vox2; vox3_grad.thickness = vox3; vox1_grad.rfBandwidth = vox2_grad.rfBandwidth = vox3_grad.rfBandwidth = p1_rf.bandwidth; create_ovsbands(); } if (ir[0] == 'y') { init_rf(&ir_rf,pipat,pi,flipir,rof2,rof2); calc_rf(&ir_rf,"tpwri","tpwrif"); init_slice_butterfly(&ssi_grad,"ssi",thk,gcrush,tcrush); calc_slice(&ssi_grad,&ir_rf,WRITE,"gssi"); tauIR = ss_grad.duration - ss_grad.rfCenterBack; // Duration of ss_grad before RF center ti_delay = ti - (ssi_grad.rfCenterFront + tauIR); if (ti_delay < 0) { abort_message("TI too short, Minimum TI = %.2fms\n",(ti-ti_delay)*1000); } irTime = 4e-6 + ti + ssi_grad.duration - ssi_grad.rfCenterBack; // Time to add to TR } /* Check that all Gradient calculations are ok ************/ sgl_error_check(sglerror); /* Min TE ******************************************/ tau1 = ss_grad.rfCenterBack + pe_grad.duration + alfa + ro_grad.timeToEcho; temin = tau1 + 4e-6; /* ensure that te_delay is at least 4us */ if (minte[0] == 'y') { te = temin; putvalue("te",te); } if (te < temin) { abort_message("TE too short. Minimum TE= %.2fms\n",temin*1000+0.005); } te_delay = te - tau1; /* Min TR ******************************************/ seqtime = ss_grad.duration + te_delay + pe_grad.duration + ro_grad.duration + perTime + tep + alfa; /* Increase TR if any options are selected ****************/ if (sat[0] == 'y') seqtime += satTime; if (fsat[0] == 'y') seqtime += fsatTime; if (mt[0] == 'y') seqtime += mtTime; if (ovs[0] == 'y') seqtime += ovsTime; if (ir[0] == 'y') { seqtime += irTime; seqtime -= tauIR; /* subtract out ss_grad which was already included in TR */ } trmin = seqtime + 4e-6; /* ensure that tr_delay is at least 4us */ trmin *= ns; if (mintr[0] == 'y') { tr = trmin; putvalue("tr",tr); } if (tr < trmin) { abort_message("TR too short. Minimum TR= %.2fms\n",trmin*1000+0.005); } tr_delay = (tr - seqtime*ns)/ns; /* Set up frequency offset pulse shape list ********/ offsetlist(pss,ss_grad.ssamp,0,freqEx,ns,seqcon[1]); shapeEx = shapelist(p1pat,ss_grad.rfDuration,freqEx,ns,0,seqcon[1]); if (ir[0] == 'y') { offsetlist(pss,ssi_grad.ssamp,0,freqIR,ns,seqcon[1]); shapeIR = shapelist(pipat,ssi_grad.rfDuration,freqIR,ns,0,seqcon[1]); } /* Set pe_steps for profile or full image **********/ pe_steps = prep_profile(profile[0],nv,&pe_grad,&per_grad); initval(pe_steps/2.0,vpe_offset); /* Shift DDR for pro *******************************/ roff = -poffset(pro,ro_grad.roamp); g_setExpTime(tr*(nt*pe_steps*arraydim + ssc)); /* PULSE SEQUENCE *************************************/ status(A); rotate(); obsoffset(resto); delay(4e-6); initval(fabs(ssc),vssc); // Compressed steady-state counter assign(zero,vrfspoil_ctr); // RF spoil phase counter assign(zero,vrfspoil); // RF spoil multiplier assign(one,vacquire); // real-time acquire flag setacqvar(vacquire); // Turn on acquire when vacquire is zero /* Delay all channels except gradient *****************/ sub(ssval,ssctr,v30); add(v30,ct,v30); if (ix == 1) { ifzero(v30); grad_advance(tep); endif(v30); } /* Begin phase-encode loop ****************************/ peloop(seqcon[2],pe_steps,vpe_steps,vpe_ctr); /* Compressed steady-states: 1st array & transient, all arrays if ssc is negative */ if ((ix > 1) && (ssc > 0)) assign(zero,vssc); sub(vpe_ctr,vssc,vpe_ctr); // vpe_ctr counts up from -ssc assign(zero,vssc); if (seqcon[2] == 's') assign(zero,vacquire); // Always acquire for non-compressed loop else { ifzero(vpe_ctr); assign(zero,vacquire); // Start acquiring when vpe_ctr reaches zero endif(vpe_ctr); } /* Set rcvr/xmtr phase for RF spoiling *******************/ if (rfspoil[0] == 'y') { incr(vrfspoil_ctr); // vrfspoil_ctr = 1 2 3 4 5 6 add(vrfspoil,vrfspoil_ctr,vrfspoil); // vrfspoil = 1 3 6 10 15 21 xmtrphase(vrfspoil); rcvrphase(vrfspoil); } /* Read external kspace table if set ******************/ if (table) getelem(t1,vpe_ctr,vpe_mult); else { ifzero(vacquire); sub(vpe_ctr,vpe_offset,vpe_mult); elsenz(vacquire); sub(zero,vpe_offset,vpe_mult); // Hold PE mult at initial value for steady states endif(vacquire); } /* PE rewinder follows PE table; zero if turned off ***/ if (perewind[0] == 'y') assign(vpe_mult,vper_mult); else assign(zero,vper_mult); /* Begin multislice loop ******************************/ msloop(seqcon[1],ns,vms_slices,vms_ctr); triggerSelect(trigger); // Selectable trigger input delay(4e-6); if (ticks) { xgate(ticks); grad_advance(tep); // Gradient propagation delay } /* TTL scope trigger **********************************/ sp1on(); delay(4e-6); sp1off(); /* Prepulse options ***********************************/ if (sat[0] == 'y') satbands(); if (fsat[0] == 'y') fatsat(); if (mt[0] == 'y') mtc(); if (ovs[0] == 'y') {ovsbands(); rotate();} /* Optional IR pulse **********************************/ if (ir[0] == 'y') { obspower(ir_rf.powerCoarse); obspwrf(ir_rf.powerFine); delay(4e-6); obl_shapedgradient(ssi_grad.name,ssi_grad.duration,0,0,ssi_grad.amp,NOWAIT); delay(ssi_grad.rfDelayFront); shapedpulselist(shapeIR,ssi_grad.rfDuration,oph,rof2,rof2,seqcon[1],vms_ctr); delay(ssi_grad.rfDelayBack); delay(ti_delay); } /* Slice select RF pulse ******************************/ obspower(p1_rf.powerCoarse); obspwrf(p1_rf.powerFine); delay(4e-6); obl_shapedgradient(ss_grad.name,ss_grad.duration,0,0,ss_grad.amp,NOWAIT); delay(ss_grad.rfDelayFront); shapedpulselist(shapeEx,ss_grad.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ss_grad.rfDelayBack); /* Phase encode, refocus, and dephase gradient ********/ pe_shapedgradient(pe_grad.name,pe_grad.duration,-ror_grad.amp,0,-ssr_grad.amp, -pe_grad.increment,vpe_mult,WAIT); /* TE delay *******************************************/ delay(te_delay); /* Readout gradient and acquisition ********************/ obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT); delay(ro_grad.atDelayFront); startacq(alfa); acquire(np,1.0/sw); delay(ro_grad.atDelayBack); endacq(); /* Rewind / spoiler gradient *********************************/ if ((perewind[0] == 'y') || (spoilflag[0] == 'y')) { pe_shapedgradient(per_name,perTime,spoil_grad.amp,pespoil_amp,spoil_grad.amp, per_grad.increment,vper_mult,WAIT); } /* Relaxation delay ***********************************/ if (!trtype) delay(tr_delay); endmsloop(seqcon[1],vms_ctr); if (trtype) delay(ns*tr_delay); endpeloop(seqcon[2],vpe_ctr); /* Inter-image delay **********************************/ sub(ntrt,ct,vtrimage); decr(vtrimage); ifzero(vtrimage); delay(trimage); endif(vtrimage); }
pulsesequence() { /* Internal variable declarations *************************/ double freq90[MAXNSLICE],freq180[MAXNSLICE],freqIR[MAXNSLICE]; int shape90=0, shape180=0, shapeIR=0; double te_delay1, te_delay2, tr_delay, ti_delay = 0; double del1=0, del2=0, del3=0, del4=0; double tau1=0, tau2=0, difftime=0, tetime=0; int table=0; /* Diffusion parameters */ #define MAXDIR 1024 /* Will anybody do more than 1024 directions or b-values? */ double roarr[MAXDIR], pearr[MAXDIR], slarr[MAXDIR]; int nbval, /* Total number of bvalues*directions */ nbro, nbpe, nbsl, i; double bro[MAXDIR], bpe[MAXDIR], bsl[MAXDIR], /* b-values along RO, PE, SL */ brs[MAXDIR], brp[MAXDIR], bsp[MAXDIR], /* and the cross-terms */ btrace[MAXDIR], /* and the trace */ max_bval=0, dcrush, dgss2, /* "delta" for crusher and gss2 gradients */ Dro, Dcrush, Dgss2; /* "DELTA" for readout, crusher and gss2 gradients */ /* Real-time variables ************************************/ int vpe_steps = v1; int vpe_ctr = v2; int vms_slices = v3; int vms_ctr = v4; int vpe_offset = v5; int vpe_index = v6; int vph180 = v7; // Phase of 180 pulse int vph2 = v8; // alternate phase of 180 on odd transients /* Initialize paramaters *********************************/ init_mri(); /* Check for external PE table ***************************/ if (strcmp(petable,"n") && strcmp(petable,"N") && strcmp(petable,"")) { loadtable(petable); table = 1; } if ((diff[0] == 'y') && (gcrush < 4)) warn_message("Advisory: set gcrush to higher value to avoid image artifacts"); /* Initialize gradient structures *************************/ init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2); init_rf(&p2_rf,p2pat,p2,flip2,rof2,rof2); init_slice(&ss_grad,"ss",thk); init_slice_butterfly(&ss2_grad,"ss2",thk*1.1,gcrush,tcrush); init_slice_refocus(&ssr_grad,"ssr"); init_readout_butterfly(&ro_grad,"ro",lro,np,sw,gcrushro,tcrushro); init_readout_refocus(&ror_grad,"ror"); init_phase(&pe_grad,"pe",lpe,nv); /* RF Calculations ****************************************/ calc_rf(&p1_rf,"tpwr1","tpwr1f"); calc_rf(&p2_rf,"tpwr2","tpwr2f"); if (p2_rf.header.rfFraction != 0.5) abort_message("RF pulse for refocusing (%s) must be symmetric",p2pat); /* Gradient calculations **********************************/ calc_slice(&ss_grad,&p1_rf,WRITE,"gss"); calc_slice(&ss2_grad,&p2_rf,WRITE,"gss2"); calc_slice_refocus(&ssr_grad, &ss_grad, NOWRITE,"gssr"); calc_readout(&ro_grad, WRITE, "gro","sw","at"); ro_grad.m0ref *= grof; calc_readout_refocus(&ror_grad, &ro_grad, NOWRITE, "gror"); calc_phase(&pe_grad, NOWRITE, "gpe","tpe"); /* Equalize refocus and PE gradient durations *************/ calc_sim_gradient(&ror_grad, &pe_grad, &ssr_grad,0,WRITE); /* Set up diffusion gradient */ if (diff[0] == 'y') { init_generic(&diff_grad,"diff",gdiff,tdelta); calc_generic(&diff_grad,NOWRITE,"",""); /* adjust duration, so tdelta is from start ramp up to start ramp down */ if (ix == 1) diff_grad.duration += diff_grad.tramp; calc_generic(&diff_grad,WRITE,"",""); } /* Min TE *************************************************/ tau1 = ss_grad.rfCenterBack + pe_grad.duration + 4e-6 + ss2_grad.rfCenterFront; tau2 = ss2_grad.rfCenterBack + ror_grad.duration + ro_grad.timeToEcho + alfa; temin = 2*(MAX(tau1,tau2) + 2*4e-6); /* have at least 4us between gradient events */ /* Calculate te_delays with the current TE, then later see how diffusion fits */ if ((minte[0] == 'y') || (te < temin)) { te_delay1 = temin/2 - tau1; te_delay2 = temin/2 - tau2; } else { te_delay1 = te/2 - tau1; te_delay2 = te/2 - tau2; } if (diff[0] =='y') { /* Is tDELTA long enough for RF refocusing gradient? */ if (tDELTA < diff_grad.duration + ss2_grad.duration) abort_message("DELTA too short, increase to %.2fms", (diff_grad.duration + ss2_grad.duration)*1000+0.005); /* Is tDELTA too long for TE dead time? */ difftime = tDELTA + diff_grad.duration; // tDELTA + front & back half diff_grad tetime = ss2_grad.duration + te_delay1 + te_delay2; if (difftime > tetime) { temin += (difftime - tetime); } } /* We now know the minimum TE incl. diffusion */ if (minte[0] == 'y') { te = temin; putvalue("te",ceil(te*1e6)*1e-6); /* round up to nearest us */ } if (te < temin) { if (diff[0] == 'n') { abort_message("TE too short. Minimum TE = %.2fms\n",temin*1000); } else { abort_message("TE too short, increase to %.2fms or reduce DELTA to %.2fms", temin*1000,(tetime-diff_grad.duration)*1000); } } te_delay1 = te/2 - tau1; te_delay2 = te/2 - tau2; /* Set up delays around diffusion gradients */ /* RF1 - del1 - diff - del2 - RF2 - del3 - diff - del4 - ACQ */ if (diff[0] == 'y') { del1 = (tetime - difftime)/2; del4 = del1; del2 = te_delay1 - diff_grad.duration; del3 = te_delay2 - diff_grad.duration; if (del3 < 0.0) { // shift diff block to right del1 += del3; del2 -= del3; del4 -= del3; del3 = 0; } else if (del2 < 0.0) { // shift diff block to left del1 -= del2; del3 -= del2; del4 += del2; del2 = 0; } } else { /* No diffusion */ del1 = 0; del3 = 0; del2 = te_delay1; del4 = te_delay2; } /* Min TR *************************************************/ trmin = (ss_grad.duration - ss_grad.rfCenterBack) + te + ro_grad.timeFromEcho; if (navigator[0] == 'y') trmin += (pe_grad.duration + ro_grad.duration); /* Optional prepulse calculations *************************/ if (sat[0] == 'y') { create_satbands(); trmin += satTime; } if (fsat[0] == 'y') { create_fatsat(); trmin += fsatTime; } if (mt[0] == 'y') { create_mtc(); trmin += mtTime; } if (ir[0] == 'y') { init_rf(&ir_rf,pipat,pi,flipir,rof2,rof2); calc_rf(&ir_rf,"tpwri","tpwrif"); init_slice_butterfly(&ssi_grad,"ssi",thk,gcrushir,tcrushir); calc_slice(&ssi_grad,&ir_rf,WRITE,"gssi"); tau1 = ss_grad.duration - ss_grad.rfCenterBack; /* duration of ss_grad before RF center */ ti_delay = ti - (ssi_grad.rfCenterBack + tau1); if (ti_delay < 0) { abort_message("TI too short, Minimum TI = %.2fms\n",(ti-ti_delay)*1000); } irTime = ti + ssi_grad.duration - ssi_grad.rfCenterBack; /* time to add to TR */ trmin += irTime; trmin -= tau1; /* but subtract out ss_grad which was already included in TR */ } trmin *= ns; if (mintr[0] == 'y'){ tr = trmin + ns*4e-6; putvalue("tr",tr); } if (tr < trmin) { abort_message("TR too short. Minimum TR= %.2fms\n",trmin*1000); } tr_delay = (tr - trmin)/ns > 4e-6 ? (tr - trmin)/ns : 4e-6; /***************************************************/ /* CALCULATE B VALUES ******************************/ if (diff[0] == 'y') { /* Get multiplication factors and make sure they have same # elements */ /* All this is only necessary because putCmd only work for ix==1 */ nbro = (int) getarray("dro",roarr); nbval = nbro; nbpe = (int) getarray("dpe",pearr); if (nbpe > nbval) nbval = nbpe; nbsl = (int) getarray("dsl",slarr); if (nbsl > nbval) nbval = nbsl; if ((nbro != nbval) && (nbro != 1)) abort_message("%s: Number of directions/b-values must be the same for all axes (readout)",seqfil); if ((nbpe != nbval) && (nbpe != 1)) abort_message("%s: Number of directions/b-values must be the same for all axes (phase)",seqfil); if ((nbsl != nbval) && (nbsl != 1)) abort_message("%s: Number of directions/b-values must be the same for all axes (slice)",seqfil); if (nbro == 1) for (i = 1; i < nbval; i++) roarr[i] = roarr[0]; if (nbpe == 1) for (i = 1; i < nbval; i++) pearr[i] = pearr[0]; if (nbsl == 1) for (i = 1; i < nbval; i++) slarr[i] = slarr[0]; } else { nbval = 1; roarr[0] = 0; pearr[0] = 0; slarr[0] = 0; } for (i = 0; i < nbval; i++) { /* Readout */ Dro = ror_grad.duration; bro[i] = bval(gdiff*roarr[i],tdelta,tDELTA); bro[i] += bval(ro_grad.amp,ro_grad.timeToEcho,Dro); /* Slice */ dgss2 = Dgss2 = ss_grad.rfCenterFront; dcrush = tcrush; //"delta" for crusher part of butterfly Dcrush = dcrush + ss_grad.rfDuration; //"DELTA" for crusher bsl[i] = bval(gdiff*slarr[i],tdelta,tDELTA); bsl[i] += bval(gcrush,dcrush,Dcrush); bsl[i] += bval(ss2_grad.ssamp,dgss2,Dgss2); bsl[i] += bval_nested(gdiff*slarr[i],tdelta,tDELTA,gcrush,dcrush,Dcrush); bsl[i] += bval_nested(gdiff*slarr[i],tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2); bsl[i] += bval_nested(gcrush,dcrush,Dcrush,ss2_grad.ssamp,dgss2,Dgss2); /* Phase */ bpe[i] = bval(gdiff*pearr[i],tdelta,tDELTA); /* Readout/Slice Cross-terms */ brs[i] = bval2(gdiff*roarr[i],gdiff*slarr[i],tdelta,tDELTA); brs[i] += bval_cross(gdiff*roarr[i],tdelta,tDELTA,gcrush,dcrush,Dcrush); brs[i] += bval_cross(gdiff*roarr[i],tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2); /* Readout/Phase Cross-terms */ brp[i] = bval2(gdiff*roarr[i],gdiff*pearr[i],tdelta,tDELTA); /* Slice/Phase Cross-terms */ bsp[i] = bval2(gdiff*slarr[i],gdiff*pearr[i],tdelta,tDELTA); bsp[i] += bval_cross(gdiff*pearr[i],tdelta,tDELTA,gcrush,dcrush,Dcrush); bsp[i] += bval_cross(gdiff*pearr[i],tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2); btrace[i] = (bro[i]+bsl[i]+bpe[i]); if (max_bval < btrace[i]) { max_bval = (bro[i]+bsl[i]+bpe[i]); } } /* End for-all-directions */ putarray("bvalrr",bro,nbval); putarray("bvalpp",bpe,nbval); putarray("bvalss",bsl,nbval); putarray("bvalrp",brp,nbval); putarray("bvalrs",brs,nbval); putarray("bvalsp",bsp,nbval); putarray("bvalue",btrace,nbval); putvalue("max_bval",max_bval); /* Generate phase-ramped pulses: 90, 180, and IR */ offsetlist(pss,ss_grad.ssamp,0,freq90,ns,seqcon[1]); shape90 = shapelist(p1pat,ss_grad.rfDuration,freq90,ns,0,seqcon[1]); offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]); shape180 = shapelist(p2pat,ss2_grad.rfDuration,freq180,ns,0,seqcon[1]); if (ir[0] == 'y') { offsetlist(pss,ssi_grad.ssamp,0,freqIR,ns,seqcon[1]); shapeIR = shapelist(pipat,ssi_grad.rfDuration,freqIR,ns,0,seqcon[1]); } /* Set pe_steps for profile or full image **********/ pe_steps = prep_profile(profile[0],nv,&pe_grad,&null_grad); initval(pe_steps/2.0,vpe_offset); sgl_error_check(sglerror); /* Return parameters to VnmrJ */ putvalue("rgss",ss_grad.tramp); //90 slice ramp if (ss2_grad.enableButterfly) { //180 slice ramps putvalue("rcrush",ss2_grad.crusher1RampToCrusherDuration); putvalue("rgss2",ss2_grad.crusher1RampToSsDuration); } else { putvalue("rgss2",ss2_grad.tramp); } if (ro_grad.enableButterfly) { putvalue("rgro",ro_grad.crusher1RampToSsDuration); } else { putvalue("rgro",ro_grad.tramp); //RO ramp } putvalue("tror",ror_grad.duration); //ROR duration putvalue("rgror",ror_grad.tramp); //ROR ramp putvalue("gpe",pe_grad.peamp); //PE max amp putvalue("gss",ss_grad.ssamp); putvalue("gro",ro_grad.roamp); g_setExpTime(tr*(nt*pe_steps*arraydim + ssc)); /* PULSE SEQUENCE *************************************/ rotate(); obsoffset(resto); roff = -poffset(pro,ro_grad.roamp); delay(4e-6); /* Begin phase-encode loop ****************************/ peloop(seqcon[2],pe_steps,vpe_steps,vpe_ctr); /* Read external kspace table if set ******************/ if (table) getelem(t1,vpe_ctr,vpe_index); else sub(vpe_ctr,vpe_offset,vpe_index); settable(t2,2,ph180); // initialize phase tables and variables getelem(t2,vpe_ctr,vph180); add(oph,vph180,vph180); // 180 deg pulse phase alternates +/- 90 from receiver mod2(ct,vph2); dbl(vph2,vph2); add(vph180,vph2,vph180); // Alternate phase for 180 on odd transients /* Begin multislice loop ******************************/ msloop(seqcon[1],ns,vms_slices,vms_ctr); if (ticks) { xgate(ticks); grad_advance(gpropdelay); } /* TTL scope trigger **********************************/ sp1on(); delay(5e-6); sp1off(); /* Prepulses ******************************************/ if (sat[0] == 'y') satbands(); if (fsat[0] == 'y') fatsat(); if (mt[0] == 'y') mtc(); /* Optional IR pulse **********************************/ if (ir[0] == 'y') { obspower(ir_rf.powerCoarse); obspwrf(ir_rf.powerFine); delay(4e-6); obl_shapedgradient(ssi_grad.name,ssi_grad.duration,0,0,ssi_grad.amp,NOWAIT); delay(ssi_grad.rfDelayFront); shapedpulselist(shapeIR,ssi_grad.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ssi_grad.rfDelayBack); delay(ti_delay); } /* Slice select RF pulse ******************************/ obspower(p1_rf.powerCoarse); obspwrf(p1_rf.powerFine); delay(4e-6); obl_shapedgradient(ss_grad.name,ss_grad.duration,0,0,ss_grad.amp,NOWAIT); delay(ss_grad.rfDelayFront); shapedpulselist(shape90,ss_grad.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ss_grad.rfDelayBack); /* Phase encode, refocus, and dephase gradient ********/ pe_shapedgradient(pe_grad.name,pe_grad.duration,0,0,-ssr_grad.amp, pe_grad.increment,vpe_index,WAIT); delay(del1); // delay to start of first diffusion gradient if (diff[0] == 'y') { obl_shapedgradient(diff_grad.name,diff_grad.duration, diff_grad.amp*dro,diff_grad.amp*dpe,diff_grad.amp*dsl,WAIT); } delay(del2); // delay from end of diffusion to slice refocusing /* Refocusing RF pulse ********************************/ obspower(p2_rf.powerCoarse); obspwrf(p2_rf.powerFine); delay(4e-6); obl_shapedgradient(ss2_grad.name,ss2_grad.duration,0,0,ss2_grad.amp,NOWAIT); delay(ss2_grad.rfDelayFront); shapedpulselist(shape180,ss2_grad.rfDuration,vph180,rof2,rof2,seqcon[1],vms_ctr); delay(ss2_grad.rfDelayBack); delay(del3); // delay from slice refocusing to second diffusion gradient if (diff[0] == 'y') { obl_shapedgradient(diff_grad.name,diff_grad.duration, diff_grad.amp*dro,diff_grad.amp*dpe,diff_grad.amp*dsl,WAIT); } delay(del4); // delay from end of diffusion gradient to readout event /* Readout gradient and acquisition ********************/ roff = -poffset(pro,ro_grad.roamp); obl_shapedgradient(ror_grad.name,ror_grad.duration,-ror_grad.amp,0,0,WAIT); obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT); delay(ro_grad.atDelayFront); startacq(alfa); acquire(np,1.0/sw); delay(ro_grad.atDelayBack); endacq(); /* Rewind Phase encoding ******************************/ pe_shapedgradient(pe_grad.name,pe_grad.duration,0,0,0, pe_grad.increment,vpe_index,WAIT); if (navigator[0] == 'y') { roff = -poffset(pro,-ro_grad.roamp); obl_shapedgradient(ro_grad.name,ro_grad.duration,-ro_grad.amp,0,0,NOWAIT); delay(ro_grad.atDelayFront); startacq(alfa); acquire(np,1.0/sw); delay(ro_grad.atDelayBack); endacq(); } /* Relaxation delay ***********************************/ delay(tr_delay); endmsloop(seqcon[1],vms_ctr); endpeloop(seqcon[2],vpe_ctr); }
pulsesequence() { /* Internal variable declarations *********************/ double freq90[MAXNSLICE],freq180[MAXNSLICE]; int shape90,shape180; double minTE, te_delay1, te_delay2, minTR, tr_delay; double tref, te1, te2; int tpwr1f, tpwr2f; /* Real-time variables ****************************/ int vms_slices = v1; int vms_ctr = v2; /* Initialize parameters *************************/ init_mri(); tpwr1f = (int) getval("tpwr1f"); tpwr2f = (int) getval("tpwr2f"); if ((nv > 0) && (profile[0] == 'n')) abort_message("Sorry, this sequence only acquires a profile, check the profile flag"); /* Read RF shape but don't calculate powers *******/ init_rf(&p1_rf,p1pat,p1,-1,rof1,rof2); calc_rf(&p1_rf,"",""); init_rf(&p2_rf,p2pat,p2,-1,rof1,rof1); calc_rf(&p2_rf,"",""); /* Gradient Calculations **************************/ init_slice(&ss_grad,"gss",thk); calc_slice(&ss_grad,&p1_rf,WRITE,"gss"); init_slice_refocus(&ssr_grad, "ssr"); calc_slice_refocus(&ssr_grad, &ss_grad, NOWRITE,"gssr"); init_slice_butterfly(&ss2_grad,"gss2",thk,gcrush,tcrush); calc_slice(&ss2_grad,&p2_rf,WRITE,"gss"); init_readout(&ro_grad,"ro",lro,np,sw); calc_readout(&ro_grad, WRITE, "gro","sw","at"); init_readout_refocus(&ror_grad,"ror"); calc_readout_refocus(&ror_grad, &ro_grad, NOWRITE, "gror"); /* Equalize Refocus Gradients ********************/ tref = calc_sim_gradient(&ror_grad, &ssr_grad, &null_grad, 0, WRITE); /* Min TE ******************************************/ te1 = ss_grad.rfCenterBack + tref + 4e-6 + ss2_grad.rfCenterFront; te2 = ss2_grad.rfCenterBack + alfa + ro_grad.timeToEcho; minTE = 2*(te1 > te2 ? te1 : te2) + 2*4e-6; if (minte[0] == 'y') { te = minTE; putvalue("te",ceil(te*1e6)*1e-6); /* round up to nearest us */ } if (te < minTE) { abort_message("TE too short. Minimum TE= %.2fms\n",minTE*1000); } te_delay1 = te/2 - te1; te_delay2 = te/2 - te2; /* Min TR ******************************************/ minTR = (GDELAY + ss_grad.rfCenterFront + te + ro_grad.timeFromEcho) * ns; if (mintr[0] == 'y') { tr = minTR + 4e-6; putvalue("tr",tr); } if (tr < minTR + 4e-6) { abort_message("TR too short. Minimum TR= %.2fms\n",(minTR + 4e-6)*1000); } tr_delay = (tr - minTR)/ns; if (sglerror) abort_message("Sequence has error(s) and will not execute - See error message(s)!\n"); offsetlist(pss,ss_grad.ssamp,0,freq90,ns,seqcon[1]); offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]); shape90 = shapelist(p1pat,ss_grad.rfDuration,freq90,ns,0,seqcon[1]); shape180 = shapelist(p2pat,ss2_grad.rfDuration,freq180,ns,0,seqcon[1]); /* PULSE SEQUENCE *************************************/ settable(t1,4,phr); getelem(t1,ct,oph); /* receiver phase */ rotate(); obsoffset(resto); delay(GDELAY); /* Begin multislice loop ******************************/ msloop(seqcon[1],ns,vms_slices,vms_ctr); if (ticks) { xgate(ticks); grad_advance(gpropdelay); delay(4e-6); } /* RF pulse *******************************************/ obspower(tpwr1); obspwrf(tpwr1f); delay(GDELAY); obl_shapedgradient(ss_grad.name,ss_grad.duration,0,0,ss_grad.amp,NOWAIT); delay(ss_grad.rfDelayFront); shapedpulselist(shape90,ss_grad.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ss_grad.rfDelayBack); /* Refocusing gradients ******************/ obl_shaped3gradient(ror_grad.name,"",ssr_grad.name, ssr_grad.duration, ror_grad.amp,0,-ssr_grad.amp,WAIT); delay(te_delay1); /* RF pulse *******************************************/ obspower(tpwr2); obspwrf(tpwr2f); delay(GDELAY); obl_shapedgradient(ss2_grad.name,ss2_grad.duration,0,0,ss2_grad.amp,NOWAIT); delay(ss2_grad.rfDelayFront); shapedpulselist(shape90,ss_grad.rfDuration,oph,rof1,rof1,seqcon[1],vms_ctr); delay(ss2_grad.rfDelayBack); delay(te_delay2); /* Readout gradient and acquisition ********************/ obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT); delay(ro_grad.atDelayFront); startacq(alfa); acquire(np,1.0/sw); endacq(); delay(ro_grad.atDelayBack); delay(tr_delay); endmsloop(seqcon[1],vms_ctr); }
pulsesequence() { /* Acquisition variables */ double dw; /* nominal dwell time, = 1/sw */ double aqtm = getval("aqtm"); /* Delay variables */ double tref, te_delay1, te_delay2, tr_delay, ti_delay, del1, del2, del3, del4, del5, /* before and after diffusion gradients */ busy1, busy2, /* time spent on rf pulses etc. in TE periods */ seqtime, invTime; int use_minte; /* RF and receiver frequency variables */ double freq90[MAXNSLICE],freq180[MAXNSLICE],freqIR[MAXNSLICE]; /* frequencies for multi-slice */ int shape90=0, shape180=0, shapeIR=0; /* List ID for RF shapes */ double roff1, roff2, roffn; /* Receiver offsets when FOV is offset along readout */ /* Gradient amplitudes, may vary depending on "image" parameter */ double peramp, perinc, peamp, roamp, roramp; /* diffusion variables */ #define MAXDIR 1024 /* Will anybody do more than 1024 directions or b-values? */ int diff_in_one = 0; double tmp, tmp_ss2; double roarr[MAXDIR], pearr[MAXDIR], slarr[MAXDIR]; int nbval, /* Total number of bvalues*directions */ nbro, nbpe, nbsl; /* bvalues*directions along RO, PE, and SL */ double bro[MAXDIR], bpe[MAXDIR], bsl[MAXDIR], /* b-values along RO, PE, SL */ brs[MAXDIR], brp[MAXDIR], bsp[MAXDIR], /* the cross-terms */ btrace[MAXDIR], /* and the trace */ max_bval=0, dcrush, dgss2, /* "delta" for crusher and gss2 gradients */ Dro, Dcrush, Dgss2; /* "DELTA" for readout, crusher and gss2 gradients */ /* loop variable */ int i; /* Real-time variables used in this sequence **************/ int vms_slices = v3; // Number of slices int vms_ctr = v4; // Slice loop counter int vnseg = v5; // Number of segments int vnseg_ctr = v6; // Segment loop counter int vetl = v7; // Number of choes in readout train int vetl_ctr = v8; // etl loop counter int vblip = v9; // Sign on blips in multi-shot experiment int vssepi = v10; // Number of Gradient Steady States lobes int vssepi_ctr = v11; // Steady State counter int vacquire = v12; // Argument for setacqvar, to skip steady states /******************************************************/ /* VARIABLE INITIALIZATIONS ***************************/ /******************************************************/ get_parameters(); euler_test(); if (tep < 0) { // adjust by reducing gpropdelay by that amount gpropdelay += tep; tep = 0; } setacqmode(WACQ|NZ); // Necessary for variable rate sampling use_minte = (minte[0] == 'y'); /******************************************************/ /* CALCULATIONS ***************************************/ /******************************************************/ if (ix == 1) { /* Calculate RF pulse */ init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2); calc_rf(&p1_rf,"tpwr1","tpwr1f"); /* Calculate gradients: */ init_slice(&ss_grad,"ss",thk); calc_slice(&ss_grad, &p1_rf,WRITE,"gss"); init_slice_refocus(&ssr_grad,"ssr"); calc_slice_refocus(&ssr_grad, &ss_grad, WRITE,"gssr"); if (spinecho[0] == 'y') { init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof1); calc_rf(&p2_rf,"tpwr2","tpwr2f"); init_slice_butterfly(&ss2_grad,"ss2",thk,gcrush,tcrush); calc_slice(&ss2_grad,&p2_rf,WRITE,"gss2"); } else ss2_grad.duration = 0; /* used for diffusion calculations */ init_readout(&epiro_grad,"epiro",lro,np,sw); init_readout_refocus(&ror_grad,"ror"); init_phase(&epipe_grad, "epipe",lpe,nv); init_phase(&per_grad,"per",lpe,nv); init_readout(&nav_grad,"nav",lro,np,sw); init_epi(&epi_grad); if (!strcmp(orient,"oblique")) { if ((phi != 90) || (psi != 90) || (theta != 90)) { /* oblique slice - this should take care of most cases */ epiro_grad.slewRate /= 3; /* = gmax/trise */ epipe_grad.slewRate /= 3; } } calc_epi(&epi_grad,&epiro_grad,&epipe_grad,&ror_grad,&per_grad,&nav_grad,NOWRITE); /* Make sure the slice refocus, readout refocus, and phase dephaser fit in the same duration */ tref = calc_sim_gradient(&ror_grad, &per_grad, &null_grad, getval("tpe"), WRITE); if (sgldisplay) displayEPI(&epi_grad); /* calc_sim_gradient recalculates per_grad, so reset its base amplitude for centric ordering or fractional k-space*/ switch(ky_order[0]) { case 'l': per_grad.amp *= (fract_ky/(epipe_grad.steps/2)); break; case 'c': per_grad.amp = (nseg/2-1)*per_grad.increment; break; } if (ir[0] == 'y') { init_rf(&ir_rf,pipat,pi,flipir,rof1,rof1); calc_rf(&ir_rf,"tpwri","tpwrif"); init_slice_butterfly(&ssi_grad,"ssi",thk,gcrush,tcrush); calc_slice(&ssi_grad,&ir_rf,WRITE,"gssi"); } if (fsat[0] == 'y') { create_fatsat(); } if (diff[0] == 'y') { init_generic(&diff_grad,"diff",gdiff,tdelta); diff_grad.maxGrad = gmax; calc_generic(&diff_grad,NOWRITE,"",""); /* adjust duration, so tdelta is from start ramp up to start ramp down */ if (ix == 1) { diff_grad.duration += diff_grad.tramp; calc_generic(&diff_grad,WRITE,"",""); } } /* Acquire top-down or bottom-up ? */ if (ky_order[1] == 'r') { epipe_grad.amp *= -1; per_grad.amp *= -1; per_grad.increment *= -1; } } /* end gradient setup if ix == 1 */ /* Load table used to determine multi-shot direction */ settable(t2,(int) nseg,epi_grad.table2); /* What is happening in the 2 TE/2 periods (except for diffusion)? */ busy1 = ss_grad.rfCenterBack + ssr_grad.duration; busy2 = tep + nav_grad.duration*(epi_grad.center_echo + 0.5); if (navigator[0] == 'y') busy2 += (tep + nav_grad.duration + per_grad.duration); /* How much extra time do we have in each TE/2 period? */ if (spinecho[0] == 'y') { busy1 += (GDELAY + ss2_grad.rfCenterFront); busy2 += ss2_grad.rfCenterBack; temin = MAX(busy1,busy2)*2; if (use_minte) te = temin; te_delay1 = te/2 - busy1; te_delay2 = te/2 - busy2; if (temin > te) { /* Use min TE and try and catch further violations of min TE */ te_delay1 = temin/2 - busy1; te_delay2 = temin/2 - busy2; } } else { /* Gradient echo */ temin = (busy1 + busy2); if (use_minte) te = temin; te_delay1 = te - temin; te_delay2 = 0; if (temin > te) te_delay1 = 0; } /* Now fill in the diffusion delays: del1 = between 90 and 1st diffusion gradient del2 = after 1st diffusion gradient del3 = before 2nd diffusion gradient when both in same TE/2 period del4 = before 2nd diffusion gradient when in different TE/2 period del5 = before acquisition Ie, the order is: 90 - del1 - diff - del2 - (diff - del3) - 180 - (del4 - diff) - del5 - acq where one and only one of the two options (diff - del3) or (del4 - diff) is used */ if (diff[0] == 'y') { tmp_ss2 = GDELAY + ss2_grad.duration; /* ss2 grad + 4us delay */ del1 = del2 = del3 = del4 = del5 = 0; if (tDELTA < (diff_grad.duration + tmp_ss2)) /* Minimum DELTA */ abort_message("ERROR %s: tDELTA is too short, minimum is %.2fms\n", seqfil,(diff_grad.duration + tmp_ss2)*1000+0.005); if (tDELTA + diff_grad.duration > te_delay1 + tmp_ss2 + te_delay2) { if (!use_minte) { abort_message("ERROR %s: Maximum tDELTA is %.2fms", seqfil,te_delay1 + ss2_grad.duration + te_delay2 - diff_grad.duration); } else { tmp = (tDELTA + diff_grad.duration) - (te_delay1 + tmp_ss2 + te_delay2); if (spinecho[0] == 'y') { te_delay1 += (tmp/2); te_delay2 += (tmp/2); } else te_delay1 += tmp; temin += tmp; } } if (spinecho[0] == 'y') { if (te_delay1 >= (tDELTA + diff_grad.duration)) { /* Put them both in 1st TE/2 period, */ diff_in_one = (diff[0] == 'y'); /* no need to increase temin */ del2 = tDELTA - diff_grad.duration; /* time between diffusion gradients */ del3 = te_delay1 - (tDELTA+diff_grad.duration); /* time after diffusion gradients */ del5 = te_delay2; /* delay in second TE/2 period */ } else { /* put them on each side of the 180 */ diff_in_one = 0; busy1 += diff_grad.duration; busy2 += diff_grad.duration; temin = 2*MAX(busy1,busy2); /* Optimally, the 2nd diff grad is right after the 180 */ del2 = tDELTA - diff_grad.duration - tmp_ss2; /* This is always > 0, or we would have aborted above */ del1 = te_delay1 - (diff_grad.duration + del2); if (del1 < 0) { del1 = 0; /* Place the 1st right after the 90 and push the 2nd out */ del4 = tDELTA - te_delay1 - ss2_grad.duration; } del5 = te_delay2 - (del4 + diff_grad.duration); /* del5 could still be < 0, when te_delay2 < diff_grad.duration */ if (del5 < 0) { del1 += fabs(del5); /* Increase each TE/2 period by abs(del5) */ del5 = 0; } } } else { /* gradient echo */ diff_in_one = (diff[0] == 'y'); del1 = 0; del2 = tDELTA - diff_grad.duration; /* time between diffusion gradients */ del3 = 0; del4 = 0; if (!use_minte) /* user defined TE */ del5 = te_delay1 - (tDELTA + diff_grad.duration); } } /* End of Diffusion block */ else { del1 = te_delay1; del5 = te_delay2; del2 = del3 = del4 = 0; } if (sgldisplay) { text_message("busy1/2, temin = %f, %f, %f",busy1*1e3, busy2*1e3, temin*1e3); text_message("te_delay1/2 = %f, %f",te_delay1*1e3, te_delay2*1e3); text_message("delays 1-5: %.2f, %.2f, %.2f, %.2f, %.2fms\n",del1*1000,del2*1000,del3*1000,del4*1000,del5*1000); } /* Check if TE is long enough */ temin = ceil(temin*1e6)/1e6; /* round to nearest us */ if (use_minte) { te = temin; putvalue("te",te); } else if (temin > te) { abort_message("TE too short, minimum is %.2f ms\n",temin*1000); } if (ir[0] == 'y') { ti_delay = ti - (pi*ssi_grad.rfFraction + rof2 + ssi_grad.rfDelayBack) - (ss_grad.rfDelayFront + rof1 + p1*(1-ss_grad.rfFraction)); if (ti_delay < 0) { abort_message("TI too short, minimum is %.2f ms\n",(ti-ti_delay)*1000); } } else ti_delay = 0; invTime = GDELAY + ssi_grad.duration + ti_delay; /* Minimum TR per slice, w/o options */ seqtime = GDELAY + ss_grad.rfCenterFront // Before TE + te + (epiro_grad.duration - nav_grad.duration*(epi_grad.center_echo+0.5)); // After TE /* Add in time for options outside of TE */ if (ir[0] == 'y') seqtime += invTime; if (fsat[0] == 'y') seqtime += fsatTime; trmin = seqtime + 4e-6; /* ensure a minimum of 4us in tr_delay */ trmin *= ns; if (tr - trmin < 0.0) { abort_message("%s: Requested tr too short. Min tr = %.2f ms\n", seqfil,ceil(trmin*100000)/100.00); } /* spread out multi-slice acquisition over total TR */ tr_delay = (tr - ns*seqtime)/ns; /******************************************************/ /* Return gradient values to VnmrJ interface */ /******************************************************/ putvalue("etl",epi_grad.etl+2*ssepi); putvalue("gro",epiro_grad.amp); putvalue("rgro",epiro_grad.tramp); putvalue("gror",ror_grad.amp); putvalue("tror",ror_grad.duration); putvalue("rgror",ror_grad.tramp); putvalue("gpe",epipe_grad.amp); putvalue("rgpe",epipe_grad.tramp); putvalue("gped",per_grad.amp); putvalue("tped",per_grad.duration); putvalue("rgped",per_grad.tramp); putvalue("gss",ss_grad.amp); putvalue("gss2",ss2_grad.ssamp); putvalue("rgss",ss_grad.tramp); putvalue("gssr",ssr_grad.amp); putvalue("tssr",ssr_grad.duration); putvalue("rgssr",ssr_grad.tramp); putvalue("rgss2",ss2_grad.crusher1RampToSsDuration); putvalue("rgssi",ssi_grad.crusher1RampToSsDuration); putvalue("rgcrush",ssi_grad.crusher1RampToCrusherDuration); putvalue("at_full",epi_grad.duration); putvalue("at_one",nav_grad.duration); putvalue("rcrush",ss2_grad.crusher1RampToCrusherDuration); putvalue("np_ramp",epi_grad.np_ramp); putvalue("np_flat",epi_grad.np_flat); if (diff[0] == 'y') { /* CALCULATE B VALUES */ /* Get multiplication factors and make sure they have same # elements */ /* All this is only necessary because putCmd only work for ix==1 */ nbro = (int) getarray("dro",roarr); nbval = nbro; nbpe = (int) getarray("dpe",pearr); if (nbpe > nbval) nbval = nbpe; nbsl = (int) getarray("dsl",slarr); if (nbsl > nbval) nbval = nbsl; if ((nbro != nbval) && (nbro != 1)) abort_message("%s: Number of directions/b-values must be the same for all axes (readout)",seqfil); if ((nbpe != nbval) && (nbpe != 1)) abort_message("%s: Number of directions/b-values must be the same for all axes (phase)",seqfil); if ((nbsl != nbval) && (nbsl != 1)) abort_message("%s: Number of directions/b-values must be the same for all axes (slice)",seqfil); if (nbro == 1) for (i = 1; i < nbval; i++) roarr[i] = roarr[0]; if (nbpe == 1) for (i = 1; i < nbval; i++) pearr[i] = pearr[0]; if (nbsl == 1) for (i = 1; i < nbval; i++) slarr[i] = slarr[0]; } else { nbval = 1; roarr[0] = 0; pearr[0] = 0; slarr[0] = 0; } for (i = 0; i < nbval; i++) { /* We need to worry about slice gradients & crushers for slice gradients */ /* Everything else is outside diffusion gradients, and thus constant */ /* for all b-values/directions */ /* Readout */ bro[i] = bval(gdiff*roarr[i],tdelta,tDELTA); /* Phase */ bpe[i] = bval(gdiff*pearr[i],tdelta,tDELTA); /* Slice */ dgss2 = p2/2; Dgss2 = dgss2; dcrush = tcrush; Dcrush = dcrush + p2; bsl[i] = bval(gdiff*slarr[i],tdelta,tDELTA); if (spinecho[0] == 'y') { bsl[i] += bval(ss2_grad.ssamp,dgss2,Dgss2); bsl[i] += bval(gcrush,dcrush,Dcrush); bsl[i] += bval_nested(gcrush,dcrush,Dcrush,ss2_grad.ssamp,dgss2,Dgss2); } if (!diff_in_one) { bsl[i] += bval_nested(gdiff*slarr[i],tdelta,tDELTA,gcrush,dcrush,Dcrush); bsl[i] += bval_nested(gdiff*slarr[i],tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2); } /* Readout/Slice Cross-terms */ brs[i] = bval2(gdiff*roarr[i],gdiff*slarr[i],tdelta,tDELTA); if (spinecho[0] == 'y') { brs[i] += bval_cross(gdiff*roarr[i],tdelta,tDELTA,gcrush,dcrush,Dcrush); brs[i] += bval_cross(gdiff*roarr[i],tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2); } /* Readout/Phase Cross-terms */ brp[i] = bval2(gdiff*roarr[i],gdiff*pearr[i],tdelta,tDELTA); /* Slice/Phase Cross-terms */ bsp[i] = bval2(gdiff*slarr[i],gdiff*pearr[i],tdelta,tDELTA); bsp[i] += bval_cross(gdiff*pearr[i],tdelta,tDELTA,gcrush,dcrush,Dcrush); bsp[i] += bval_cross(gdiff*pearr[i],tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2); btrace[i] = (bro[i]+bsl[i]+bpe[i]); if (max_bval < btrace[i]) { max_bval = (bro[i]+bsl[i]+bpe[i]); } } /* End for-all-directions */ putarray("bvalrr",bro,nbval); putarray("bvalpp",bpe,nbval); putarray("bvalss",bsl,nbval); putarray("bvalrp",brp,nbval); putarray("bvalrs",brs,nbval); putarray("bvalsp",bsp,nbval); putarray("bvalue",btrace,nbval); putvalue("max_bval",max_bval); /* Set all gradients depending on whether we do */ /* Use separate variables, because we only initialize & calculate gradients for ix==1 */ peamp = epipe_grad.amp; perinc = per_grad.increment; peramp = per_grad.amp; roamp = epiro_grad.amp; roramp = ror_grad.amp; switch ((int)image) { case 1: /* Real image scan, don't change anything */ break; case 0: /* Normal reference scan */ peamp = 0; perinc = 0; peramp = 0; roamp = epiro_grad.amp; roramp = ror_grad.amp; break; case -1: /* Inverted image scan */ roamp = -epiro_grad.amp; roramp = -ror_grad.amp; break; case -2: /* Inverted reference scan */ peamp = 0; perinc = 0; peramp = 0; roamp = -epiro_grad.amp; roramp = -ror_grad.amp; break; default: break; } /* Generate phase-ramped pulses: 90, 180, and IR */ offsetlist(pss,ss_grad.ssamp,0,freq90,ns,seqcon[1]); shape90 = shapelist(p1pat,ss_grad.rfDuration,freq90,ns,0,seqcon[1]); if (spinecho[0] == 'y') { offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]); shape180 = shapelist(p2pat,ss2_grad.rfDuration,freq180,ns,0,seqcon[1]); } if (ir[0] == 'y') { offsetlist(pss,ssi_grad.ssamp,0,freqIR,ns,seqcon[1]); shapeIR = shapelist(pipat,ssi_grad.rfDuration,freqIR,ns,0,seqcon[1]); } sgl_error_check(sglerror); roff1 = -poffset(pro,epi_grad.amppos); roff2 = -poffset(pro,epi_grad.ampneg); roffn = -poffset(pro,nav_grad.amp); roff1 = -poffset(pro,epi_grad.amppos*roamp/epiro_grad.amp); roff2 = -poffset(pro,epi_grad.ampneg*roamp/epiro_grad.amp); roffn = -poffset(pro,nav_grad.amp); dw = granularity(1/sw,1/epi_grad.ddrsr); /* Total Scan Time */ g_setExpTime(tr*nt*nseg*arraydim); /******************************************************/ /* PULSE SEQUENCE *************************************/ /******************************************************/ rotate(); F_initval(epi_grad.etl/2, vetl); /* vetl is the loop counter in the acquisition loop */ /* that includes both a positive and negative readout lobe */ F_initval(nseg, vnseg); /* NB. F_initval(-ssepi,vssepi); currently gives errors */ initval(-ssepi,vssepi); /* gradient steady state lobes */ obsoffset(resto); delay(GDELAY); ifzero(rtonce); grad_advance(gpropdelay); endif(rtonce); loop(vnseg,vnseg_ctr); /* Loop through segments in segmented EPI */ msloop(seqcon[1],ns,vms_slices,vms_ctr); /* Multislice loop */ assign(vssepi,vssepi_ctr); sp1on(); delay(4e-6); sp1off(); /* Output trigger to look at scope */ if (ticks) { xgate(ticks); grad_advance(gpropdelay); delay(4e-6); } getelem(t2,vnseg_ctr,vblip); /* vblip = t2[vnseg_ctr]; either 1 or -1 for pos/neg blip */ /* Optional FAT SAT */ if (fsat[0] == 'y') { fatsat(); } /* Optional IR + TI delay */ if (ir[0] == 'y') { obspower(ir_rf.powerCoarse); obspwrf(ir_rf.powerFine); delay(GDELAY); obl_shapedgradient(ssi_grad.name,ssi_grad.duration,0.0,0.0,ssi_grad.amp,NOWAIT); delay(ssi_grad.rfDelayBack); shapedpulselist(shapeIR,ssi_grad.rfDuration,oph,rof1,rof1,seqcon[1],vms_ctr); delay(ssi_grad.rfDelayBack); delay(ti_delay); } /* 90 ss degree pulse */ obspower(p1_rf.powerCoarse); obspwrf(p1_rf.powerFine); delay(GDELAY); obl_shapedgradient(ss_grad.name,ss_grad.duration,0.0,0.0,ss_grad.amp,NOWAIT); delay(ss_grad.rfDelayFront); shapedpulselist(shape90,p1_rf.rfDuration,oph,rof1,rof2,seqcon[1],vms_ctr); delay(ss_grad.rfDelayBack); /* Slice refocus */ obl_shapedgradient(ssr_grad.name,ssr_grad.duration,0,0,-ssr_grad.amp,WAIT); delay(del1); if (diff[0] == 'y') obl_shapedgradient(diff_grad.name,diff_grad.duration, diff_grad.amp*dro,diff_grad.amp*dpe,diff_grad.amp*dsl,WAIT); delay(del2); if (diff_in_one) obl_shapedgradient(diff_grad.name,diff_grad.duration, -diff_grad.amp*dro,-diff_grad.amp*dpe,-diff_grad.amp*dsl,WAIT); delay(del3); /* Optional 180 ss degree pulse with crushers */ if (spinecho[0] == 'y') { obspower(p2_rf.powerCoarse); obspwrf(p2_rf.powerFine); delay(GDELAY); obl_shapedgradient(ss2_grad.name,ss2_grad.duration,0.0,0.0,ss2_grad.amp,NOWAIT); delay(ss2_grad.rfDelayFront); shapedpulselist(shape180,ss2_grad.rfDuration,oph,rof1,rof1,seqcon[1],vms_ctr); delay(ss2_grad.rfDelayBack); } delay(del4); if ((diff[0] == 'y') && !diff_in_one) obl_shapedgradient(diff_grad.name,diff_grad.duration, diff_grad.amp*dro,diff_grad.amp*dpe,diff_grad.amp*dsl,WAIT); delay(del5); /* Optional navigator echo */ if (navigator[0] == 'y') { obl_shapedgradient(ror_grad.name,ror_grad.duration,roramp,0,0,WAIT); obl_shapedgradient(nav_grad.name,nav_grad.duration, -nav_grad.amp,0,0,NOWAIT); delay(tep); roff = roffn; /* Set receiver offset for navigator gradient */ delay(epi_grad.skip-alfa); /* ramp up */ startacq(alfa); for(i=0;i<np/2;i++){ sample(dw); delay((epi_grad.dwell[i] - dw)); } sample(aqtm-at); endacq(); delay(epi_grad.skip - dw - (aqtm-at)); /* Phase encode dephaser here if navigator echo was acquired */ var_shapedgradient(per_grad.name,per_grad.duration,0,-peramp,0,perinc,vnseg_ctr,WAIT); } else { var_shapedgradient(per_grad.name,per_grad.duration, -roramp,-peramp,0,perinc,vnseg_ctr,WAIT); } /* Start readout and phase encode gradient waveforms, NOWAIT */ /* If alternating ky-ordering, get polarity on blips from table */ var_shaped3gradient(epiro_grad.name,epipe_grad.name,"", /* patterns */ epiro_grad.duration, /* duration */ roamp,0,0, /* amplitudes */ peamp,vblip, /* step and multiplier */ NOWAIT); /* Don't wait */ delay(tep); /* Acquisition loop */ assign(one,vacquire); // real-time acquire flag nowait_loop(epi_grad.etl/2 + ssepi,vetl,vetl_ctr); ifzero(vssepi_ctr); //vssepi_ctr = -ssepi, -ssepi+1, ..., 0, 1,2,... assign(zero,vacquire); // turn on acquisition after all ss lobes endif(vssepi_ctr); incr(vssepi_ctr); setacqvar(vacquire); // Set acquire flag roff = roff1; /* Set receiver offset for positive gradient */ delay(epi_grad.skip-alfa); /* ramp up */ startacq(alfa); for(i=0;i<np/2;i++){ sample(dw); //dw = 1/sw delay((epi_grad.dwell[i] - dw)); } if (aqtm > at) sample(aqtm-at); endacq(); delay(epi_grad.skip - dw - (aqtm-at)); roff = roff2; /* Set receiver offset for negative gradient */ delay(epi_grad.skip-alfa); startacq(alfa); for(i=0;i<np/2;i++){ sample(dw); delay((epi_grad.dwell[i] - dw)); } if (aqtm > at) sample(aqtm-at); endacq(); delay(epi_grad.skip - dw - (aqtm-at)); nowait_endloop(vetl_ctr); delay(tr_delay); endmsloop(seqcon[1],vms_ctr); /* end multislice loop */ endloop(vnseg_ctr); /* end segments loop */ } /* end pulsesequence */
pulsesequence() { /***** Internal variable declarations *****/ int shapelist1,shapelist2,shapelist3; /* pulse shapes (lists) */ double freq1,freq2,freq3,ws_delta; double rprof,pprof,sprof; double restol, resto_local,csd_ppm; char profile_ovs[MAXSTR]; char profile_vox[MAXSTR]; int wsfirst; //wsfirst makes ws unit to be exececuted first int isis; int counter,noph; char autoph[MAXSTR],pcflag[MAXSTR]; /* sequence timing variables */ double te_delay1, te_delay2, newdelay,tr_delay, tm_delay; double tau1=0, tau2=0; /* Extra crushers */ double gcrushtm,tcrushtm; double ky; double vox3_cr, vox3r_cr; double gcrush_end, tcrush_end; /*extra ws pulse flag*/ char ws_tm[MAXSTR]; double wsflipftm; double tmwstpwr,tmwstpwrf; init_mri(); noph=(int)getval("noph"); isis=(int)getval("isis"); int inv1[32]= {0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3};//excitation pulse int inv2[32]= {0, 0, 1, 1, 2, 2, 3, 3, 0, 0, 1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3, 0, 0, 1, 1, 2, 2, 3, 3, 0, 0}; //refocusing pulse int inv3[32]= {0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3};//inversion pulse int phrec[32]= {0, 2, 2, 0, 2, 0, 0, 2, 0, 2, 2, 0, 2, 0, 0, 2, 1, 3, 3, 1, 3, 1, 1, 3, 1, 3, 3, 1, 3, 1, 1, 3};// rec phase int phrec0[32]= {0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1};// rec phase for non-isis /***** Real-time variables used in this sequence *****/ int vinv1 = v1; // on/off flag first inversion pulse int vms = v5; // dummy shapedpulselist slice counter (= one) get_ovsparameters(); get_wsparameters(); rprof = getval("rprof"); pprof = getval("pprof"); sprof = getval("sprof"); ky=getval("ky"); getstr("autoph",autoph); getstr("pcflag",pcflag); getstr("profile_ovs",profile_ovs); getstr("profile_vox",profile_vox); wsfirst=(int)getval("wsfirst"); restol=getval("restol"); //local frequency offset roff=getval("roff"); //receiver offset csd_ppm=getval("csd_ppm"); //chemical shift displacement factor gcrushtm = getval("gcrushtm"); tcrushtm = getval("tcrushtm"); wsflipftm = getval("wsflipftm"); getstr("ws_tm",ws_tm); ws_delta=getval("ws_delta"); vox3_cr=1000000; /***** RF power calculations *****/ shape_rf(&p1_rf,"p1",p1pat,p1,flip1,rof1,rof2); shape_rf(&p2_rf,"p2",p2pat,p2,flip2,rof1,rof2); shape_rf(&p3_rf,"p3",p3pat,p3,flip3,rof1,rof2); shape_rf(&p4_rf,"p4",p4pat,p4,flip4,rof1,rof2); p4_rf.flipmult=wsflipftm; calc_rf(&p1_rf,"tpwr1","tpwr1f"); calc_rf(&p2_rf,"tpwr2","tpwr2f"); calc_rf(&p3_rf,"tpwr3","tpwr3f"); calc_rf(&p4_rf,"tpwr4","tpwr4f"); // wsfpwrtm=p4_rf.powerFine*wsflipftm; /* ws fine RF power */ trampfixed=trise; //rise time =trise tcrush=granularity(tcrush,GRADIENT_RES); //this is to avoid the granularity errors //if trampfixed is used, rise time needs to be checked if (trise*2>tcrush){ abort_message("tcrush too short. Minimum tcrush = %fms \n",1000*trise*2); } if (gcrush>gmax){ abort_message("gcrush too large. Max gcrush = %f \n",gmax*0.95); } init_slice(&vox1_grad,"vox1",vox1); init_slice(&vox2_grad,"vox2",vox2); init_slice_butterfly(&vox3_crush,"vox3_crush",vox3_cr,gcrush,tcrush); init_slice_butterfly(&vox3r_crush,"vox3r_crush",vox3_cr,gcrush,tcrush); init_slice_butterfly(&vox3_grad,"vox3",vox3,gcrush,tcrush); init_generic(&tmcrush_grad,"tmcrush",gcrushtm,tcrushtm); //crusher grad during tm if (profile_vox[0] == 'y') { init_readout_butterfly(&ro_grad,"ro",lro,np,sw,gcrushro,tcrushro); init_readout_refocus(&ror_grad,"ror"); } /***** Gradient calculations *****/ calc_slice(&vox1_grad,&p1_rf,WRITE,"vox1_grad"); calc_slice(&vox2_grad,&p2_rf,WRITE,"vox2_grad"); calc_slice(&vox3_grad,&p3_rf,NOWRITE,""); calc_slice(&vox3_crush,&p3_rf,WRITE,"vox3_crush"); calc_slice(&vox3r_crush,&p3_rf,NOWRITE,""); vox3r_crush.crusher1Moment0 -= vox2_grad.m0ref; //only now can re-calculate the moment vox3r_crush.crusher1CalcFlag=AMPLITUDE_FROM_MOMENT_DURATION_RAMP; calc_slice(&vox3r_crush,&p3_rf,WRITE,"vox3r_crush"); vox3_grad.crusher2Moment0 *= vox3_grad.m0def/vox3_grad.m0ref*ky; //only now can re-calculate the moment vox3_grad.crusher2CalcFlag=AMPLITUDE_FROM_MOMENT_DURATION_RAMP; calc_slice(&vox3_grad,&p3_rf,WRITE,"vox3_grad"); calc_generic(&tmcrush_grad,WRITE,"",""); if (profile_vox[0] == 'y') { calc_readout(&ro_grad,WRITE,"gro","sw","at"); putvalue("gro",ro_grad.roamp); // RO grad calc_readout_refocus(&ror_grad,&ro_grad,WRITE,"gror"); putvalue("tror",ror_grad.duration); // ROR duration } if (profile_ovs[0]=='y'){ if (rprof==1) { vox1_grad.amp=0; } else if(pprof==1) { vox2_grad.amp=0; } else if(sprof==1) { vox3_grad.amp=0; } } /***** Check nt is a multiple of 2 *****/ if (ix == 1) { if ((int)nt%2 != 0) text_message("WARNING: SPECIAL requires 2 steps. Set nt as a multiple of 2\n"); } /* Optional Outer Volume Suppression */ if (ovs[0] == 'y') create_ovsbands(); if (sat[0] == 'y') create_satbands(); /* Optional Water Suppression */ if (ws[0] == 'y') create_watersuppress(); /***** Set up frequency offset pulse shape list *****/ offsetlist(&pos1,vox1_grad.ssamp,0,&freq1,1,'s'); offsetlist(&pos2,vox2_grad.ssamp,0,&freq2,1,'s'); offsetlist(&pos3,vox3_grad.ssamp,0,&freq3,1,'s'); if (profile_ovs[0]=='y'&& sprof==1) freq3=0.0; if (profile_ovs[0]=='y'&& pprof==1) freq2=0.0; if (profile_ovs[0]=='y'&& rprof==1) freq1=0.0; freq1=freq1-csd_ppm*sfrq; freq2=freq2-csd_ppm*sfrq; freq3=freq3-csd_ppm*sfrq; shapelist1 = shapelist(p1_rf.pulseName,vox1_grad.rfDuration,&freq1,1,vox1_grad.rfFraction,'s'); shapelist2 = shapelist(p2_rf.pulseName,vox2_grad.rfDuration,&freq2,1,vox2_grad.rfFraction,'s'); shapelist3 = shapelist(p3_rf.pulseName,vox3_grad.rfDuration,&freq3,1,vox3_grad.rfFraction,'s'); /* Calculate delta from resto to include local frequency line + chemical shift offset */ resto_local=resto-restol; /* Frequency offsets */ if (profile_vox[0] == 'y') { /* Shift DDR for pro ************************************/ roff = -poffset(pro,ro_grad.roamp); } /* Set tables */ /* Real time variables for inversion pulses */ settable(t1,noph,inv1); settable(t2,noph,inv2); settable(t3,noph,inv3); /* Phase cycle for excitation pulse and receiver */ if (isis!=1) settable(t4,noph,phrec0); else settable(t4,noph,phrec); /* shapedpulselist variable */ assign(one,vms); /* Put gradient information back into VnmrJ parameters */ putvalue("gvox1",vox1_grad.ssamp); putvalue("gvox2",vox2_grad.ssamp); putvalue("gvox3",vox3_grad.ssamp); putvalue("rgvox1",vox1_grad.tramp); putvalue("rgvox2",vox2_grad.tramp); putvalue("rgvox3",vox3_grad.tramp); sgl_error_check(sglerror); if (ss<0) g_setExpTime(trmean*(nt-ss)*arraydim); else g_setExpTime(tr*(ntmean*arraydim+ss)); /* PULSE SEQUENCE *************************************/ /* Real time variables for inversion pulses */ counter=(double)nt*(ix-1); if (autoph[0] == 'n') counter=0.0; initval(counter,v11); initval(noph,v13); //v13=number of phase cycling steps add(v11,ctss,v12); //v12=counter modn(v12,v13,v12); //v12 runs from 1:v13 getelem(t1,v12,v8); /* 90 DEG. SPIN ECHO PULSE */ getelem(t2,v12,v9); /* 180 DEG. SPIN ECHO P. */ getelem(t3,v12,v10); /* ISIS 180 DEG. ADIAB. PULSE */ getelem(t4,v12,oph); /*RCVR PHASE*/ mod2(v12,vinv1); // this controls 1D isis on, off, on, of... up to noph(=32) /****************************************************/ /* Sequence Timing **********************************/ /****************************************************/ /* Min TE ******************************************/ tau1 = vox2_grad.rfCenterBack + vox3_grad.rfCenterFront; tau2 = vox3_grad.rfCenterBack+alfa; temin = 2*(MAX(tau1,tau2) + 4e-6); /* have at least 4us between gradient events */ if (minte[0] == 'y') { te = temin; putvalue("te",te); } else if (te < temin) { abort_message("TE too short. Minimum TE = %.2fms\n",temin*1000); } te_delay1 = te/2 - tau1; te_delay2 = te/2 - tau2; printf("te delay1 is %f", te_delay1); printf("te delay2 is %f", te_delay2); /***************************************************/ /* Min TM ******************************************/ if (ws_tm[0] == 'y') { tau1 = vox1_grad.rfCenterBack + rof1+rof2+p4_rf.rfDuration+tmcrush_grad.duration + 4e-6 + vox2_grad.rfCenterFront; } else tau1 = vox1_grad.rfCenterBack + rof2+tmcrush_grad.duration + 4e-6 + vox2_grad.rfCenterFront; tmmin = tau1 + 4e-6; /* have at least 4us between gradient events */ if (mintm[0] == 'y') { tm = tmmin; putvalue("tm",tm); } else if (tm < tmmin) { abort_message("TM too short. Minimum TM = %.2fms\n",tmmin*1000); } tm_delay = (tm - tau1); /* Relaxation delay ***********************************/ /***** Min TR *****/ trmin = vox1_grad.rfCenterFront + tm + te+alfa + at + 20e-6; if (profile_vox[0] == 'y') trmin += ror_grad.duration + ro_grad.duration - at; if (ws[0] == 'y') trmin += wsTime; if (ovs[0] == 'y') trmin += ovsTime; if (sat[0] == 'y') trmin += satTime; if (mintr[0] == 'y') { tr = trmin; putCmd("setvalue('tr',%f,'current')\n",tr); } if ((trmin-tr) > 12.5e-9) { abort_message("tr too short. Minimum tr = %.2f ms\n",(trmin)*1000); } /***** Calculate TR delay *****/ tr_delay = tr - trmin; /**Sequence Begin**/ status(A); obsoffset(resto_local); delay(4e-6); set_rotation_matrix(vpsi,vphi,vtheta); if (ticks > 0) { xgate(ticks); grad_advance(gpropdelay); delay(4e-6); } /* TTL scope trigger **********************************/ sp1on(); delay(4e-6); sp1off(); /* Saturation bands ***********************************/ if (ovs[0] == 'y') ovsbands(); if (sat[0] == 'y') satbands(); /* Post OVS water suppression *************************/ if (ws[0] == 'y') watersuppress(); /* First inversion pulse *****/ if (isis >= 1){ /*for the ISIS pulse on,off,on,off... or on,on,on,on... */ obspower(p1_rf.powerCoarse); obspwrf(p1_rf.powerFine); delay(4e-6); if (isis == 1) /* for ISIS on,off,on,off,... */{ ifzero(vinv1); obl_shapedgradient(vox1_grad.name,vox1_grad.duration,vox1_grad.amp,0,0,NOWAIT); delay(vox1_grad.rfDelayFront); shapedpulselist(shapelist1,vox1_grad.rfDuration,v10,rof1,rof2,'s',vms); delay(vox1_grad.rfDelayBack); elsenz(vinv1); obl_shapedgradient(vox1_grad.name,vox1_grad.duration,vox1_grad.amp,0,0,WAIT); endif(vinv1); } else { /* for ISIS on,on,on,on...*/ obl_shapedgradient(vox1_grad.name,vox1_grad.duration,vox1_grad.amp,0,0,NOWAIT); delay(vox1_grad.rfDelayFront); shapedpulselist(shapelist1,vox1_grad.rfDuration,v10,rof1,rof2,'s',vms); delay(vox1_grad.rfDelayBack); } } else delay(vox1_grad.duration); //this is for isis off,off,off,off /* tm delay before excitation pulse *****/ /* Optional TM water suppression ***********************/ if (ws_tm[0] == 'y') { if (wsrf[0]=='y') { obspower(p4_rf.powerCoarse); obspwrf(p4_rf.powerFine); delay(4e-6); shapedpulseoffset(p4_rf.pulseName,p4_rf.rfDuration,zero,rof1,rof2,ws_delta); } else delay(p4_rf.rfDuration+rof1+rof2); } //end of ws_tm='y' condition delay(tm_delay); /* TM Gradient crusher ********************************/ obl_shapedgradient(tmcrush_grad.name,tmcrush_grad.duration,0,0,tmcrush_grad.amp,WAIT); /* 90 degree excitation pulse *****/ obspower(p2_rf.powerCoarse); obspwrf(p2_rf.powerFine); delay(4e-6); obl_shapedgradient(vox2_grad.name,vox2_grad.duration,0,vox2_grad.amp,0,NOWAIT); delay(vox2_grad.rfDelayFront); shapedpulselist(shapelist2,vox2_grad.rfDuration,v8,rof1,rof2,'s',vms); delay(vox2_grad.rfDelayBack); delay(te_delay1); /* 180 degree pulse ********************************/ obspower(p3_rf.powerCoarse); obspwrf(p3_rf.powerFine); delay(4e-6); obl_shaped3gradient (vox3_crush.name,vox3r_crush.name,vox3_grad.name,vox3_grad.duration,vox3_crush.amp,vox3r_crush.amp,vox3_grad.amp,NOWAIT); delay(vox3_grad.rfDelayFront); shapedpulselist(shapelist3,vox3_grad.rfDuration,v9,rof1,rof2,'s',vms); delay(vox3_grad.rfDelayBack); delay(te_delay2); //acquisition starts if (profile_vox[0] == 'y') { obl_shapedgradient(ror_grad.name,ror_grad.duration, -rprof*ror_grad.amp,-pprof*ror_grad.amp,-sprof*ror_grad.amp,WAIT); delay(4e-6); obl_shapedgradient(ro_grad.name,ro_grad.duration, rprof*ro_grad.amp,pprof*ro_grad.amp,sprof*ro_grad.amp,NOWAIT); delay(ro_grad.atDelayFront); startacq(alfa); acquire(np,1.0/sw); delay(ro_grad.atDelayBack); endacq(); } else { startacq(alfa); acquire(np,1.0/sw); endacq(); } delay(tr_delay); }