示例#1
0
文件: gtest.c 项目: timburrow/ovj3
pulsesequence()
{
  double  seqtime,tr_delay,sign1,sign2;

  sign1 = getval("sign1");                  // first gradient multiplier, -1 to 1
  sign2 = getval("sign2");                  // second gradient multiplier, -1 to 1

  /* Initialize paramaters **********************************/
  init_mri();

  /* Gradient calculations **********************************/
  init_generic(&spoil_grad,"gtest",gspoil,tspoil);
  calc_generic(&spoil_grad,WRITE,"","");

  seqtime = 2*(tspoil + d2) + at;
  tr_delay = tr - seqtime;
  if (tr_delay < 0.0)
    abort_message("gradtest: TR too short, minimum TR = %6.1f msec",1000*seqtime);

  /* PULSE SEQUENCE *************************************/
  rotate();                                 // Initialize default orientation
  sp1on(); delay(4e-6); sp1off();           // TTL scope trigger

  obl_shapedgradient(spoil_grad.name,spoil_grad.duration,sign1*gspoil,0,0,WAIT);
  delay(d2);
  obl_shapedgradient(spoil_grad.name,spoil_grad.duration,sign2*gspoil,0,0,WAIT);
  delay(d2);
  delay(tr_delay);
}
示例#2
0
void pulsesequence()
{
   double pd, seqtime;
   double n,r,bigtau;
   double restol, resto_local;

   init_mri();

   restol=getval("restol");   //local frequency offset
   roff=getval("roff");       //receiver offset

   init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2);   /* hard pulse */
   calc_rf(&p1_rf,"tpwr1","tpwr1f");
   init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof2);   /* hard pulse */
   calc_rf(&p2_rf,"tpwr2","tpwr2f");

/* calculate 'big tau' values */
   bigtau = getval("bigtau");
   n =  bigtau/(2.0*d2);
   n = (double)((int)((n/2.0) + 0.5)) * 2.0;
   initval(n,v3);

   seqtime = at+p1+rof1+rof2;
   seqtime += 2*d2+p2+rof1+rof2;  /* cpmg pulse and delay */
   
   pd = tr - seqtime;  /* predelay based on tr */
   if (pd <= 0.0) {
      abort_message("%s: Requested tr too short.  Min tr = %f ms",seqfil,seqtime*1e3);
    }

   resto_local=resto-restol; 

   status(A);
   delay(pd);
   xgate(ticks);
   
/* calculate exact delay and phases */

   r = d2-p2/2.0-rof2;   /* correct delay for pulse width */
   mod2(oph,v2);   /* 0,1,0,1 */
   incr(v2);   /* 1,2,1,2 = y,y,-y,-y */

   obsoffset(resto_local); 
   obspower(p1_rf.powerCoarse);
   obspwrf(p1_rf.powerFine);
   rgpulse(p1,oph,rof1,rof2);  /* 90deg */
   obspower(p2_rf.powerCoarse);
   obspwrf(p2_rf.powerFine);
   starthardloop(v3);
      delay(r);
      rgpulse(p2,v2,rof1,rof2);   /* 180deg pulse */
      delay(r);
   endhardloop();
   startacq(alfa);
   acquire(np,1.0/sw);
   endacq();
}
示例#3
0
pulsesequence()
{
   double pd, seqtime;
   double minte,ted1,ted2;
   double restol, resto_local;

   int  vph180     = v2;  /* Phase of 180 pulse */
   init_mri();              /****needed ****/

   restol=getval("restol");   //local frequency offset
   roff=getval("roff");       //receiver offset

   init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2);   /* hard pulse */
   calc_rf(&p1_rf,"tpwr1","tpwr1f");
   init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof2);   /* hard pulse */
   calc_rf(&p2_rf,"tpwr2","tpwr2f");

   seqtime = at+(p1/2.0)+rof1+d2;

   pd = tr - seqtime;  /* predelay based on tr */
   if (pd <= 0.0) {
      abort_message("%s: Requested tr too short.  Min tr = %f ms",seqfil,seqtime*1e3);
    }
   minte = p1/2.0 + p2 + 2*rof2 + rof1;
   if(d2 > 0) {
     if(d2 < minte+4e-6) 
       abort_message("%s: TE too short. Min te = %f ms",seqfil,minte*1e3);
   }
   ted1 = d2/2 - p1/2 - p2/2 + rof2 + rof1;
   ted2 = d2/2 - p2/2 + rof2;
   resto_local=resto-restol; 

   status(A);
   xgate(ticks);
   delay(pd);

   /* --- observe period --- */
   obsoffset(resto_local);
   obspower(p1_rf.powerCoarse);
   obspwrf(p1_rf.powerFine);
   shapedpulse(p1pat,p1,oph,rof1,rof2);
   /* if d2=0 no 180 pulse applied */
   if (d2 > 0) {
     obspower(p2_rf.powerCoarse);
     obspwrf(p2_rf.powerFine);   
     settable(t2,2,ph180);        /* initialize phase tables and variables */
     getelem(t2,ct,v6);  /* 180 deg pulse phase alternates +/- 90 off the rcvr */
     add(oph,v6,vph180);      /* oph=zero */
     delay(ted1);
     shapedpulse(p2pat,p2,vph180,rof1,rof2);
     delay(ted2);
   }
   startacq(alfa);
   acquire(np,1.0/sw);
   endacq();
}
示例#4
0
pulsesequence()
{
  double sign,currentlimit,RMScurrentlimit,dutycycle;
  int calcpower;

  /* Initialize paramaters **********************************/
  init_mri();
  calcpower=(int)getval("calcpower");
  dutycycle=getval("dutycycle");
  currentlimit=getval("currentlimit");
  RMScurrentlimit=getval("RMScurrentlimit");

  if (gspoil>0.0) sign = 1.0;
  else sign = -1.0;

  init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2);
  if (calcpower) calc_rf(&p1_rf,"tpwr1","tpwr1f");

  if (tspoil>0.0) {
    gspoil = sqrt(dutycycle/100.0)*gmax*RMScurrentlimit/currentlimit;
    init_generic(&spoil_grad,"spoil",gspoil,tspoil);
    spoil_grad.rollOut=FALSE;
    calc_generic(&spoil_grad,WRITE,"gspoil","tspoil");
  }

  xgate(ticks);

  rotate();

  status(A);
  mod4(ct,oph);
  delay(d1);

  /* TTL scope trigger **********************************/       
  sp1on(); delay(4e-6); sp1off();

  if (calcpower) {
    obspower(p1_rf.powerCoarse);
    obspwrf(p1_rf.powerFine);
  } 
  else obspower(tpwr1);
  delay(4e-6);

  if (tspoil>0.0) {
    obl_shapedgradient(spoil_grad.name,spoil_grad.duration,0,0,spoil_grad.amp*sign,WAIT);
    delay(d2);
  }

  shapedpulse(p1pat,p1,ct,rof1,rof2);

  startacq(alfa);
  acquire(np,1.0/sw);
  endacq();
		
}
示例#5
0
文件: adcpuls.c 项目: timburrow/ovj3
pulsesequence()
{
   double pd, seqtime;
   double mintDELTA,ted1,ted2,gf;
   double restol, resto_local;

   init_mri();              /****needed ****/

   restol=getval("restol");   //local frequency offset
   roff=getval("roff");       //receiver offset

   init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2);   /* hard pulse */
   calc_rf(&p1_rf,"tpwr1","tpwr1f");
   init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof2);   /* hard pulse */
   calc_rf(&p2_rf,"tpwr2","tpwr2f");

   gf=1.0;
   if(diff[0] == 'n') gf=0;
   int  vph180     = v2;  /* Phase of 180 pulse */

   mintDELTA = tdelta + trise + rof1 + p2 + rof2;
   if(tDELTA <= mintDELTA) {
       abort_message("%s: tDELTA too short. Min tDELTA = %f ms",seqfil,mintDELTA*1e3);
   }
   ted1 = tDELTA - tdelta + trise + p2 + rof1 + rof2;
   te = p1/2 + rof2 + tdelta + trise + ted1 + rof1 + p2/2;   /* first half-te */
   ted2 = te - p2/2 - rof2 - tdelta - trise;
   if((ted1 <= 0)||(ted2 <= 0) ) {
       abort_message("%s: tDELTA too short. Min tDELTA = %f ms",seqfil,mintDELTA*1e3);
   }
   te = te*2.0;
   putvalue("te",te);
   seqtime = at+(p1/2.0)+rof1+te;
   pd = tr - seqtime;  /* predelay based on tr */
   if (pd <= 0.0) {
      abort_message("%s: Requested tr too short.  Min tr = %f ms",seqfil,seqtime*1e3);
   }

   resto_local=resto-restol; 

   status(A);
   rotate();
   delay(pd);
   xgate(ticks);

   /* --- observe period --- */
   obsoffset(resto_local); 
   obspower(p1_rf.powerCoarse);
   obspwrf(p1_rf.powerFine);
   shapedpulse(p1pat,p1,oph,rof1,rof2);

   obl_gradient(0,0,gdiff*gf);   /* x,y,z gradients selected via orient */
   delay(tdelta);
   zero_all_gradients();
   delay(trise);
   delay(ted1);
     
   obspower(p2_rf.powerCoarse);
   obspwrf(p2_rf.powerFine);   
   settable(t2,2,ph180);        /* initialize phase tables and variables */
   getelem(t2,ct,v6);  /* 180 deg pulse phase alternates +/- 90 off the rcvr */
   add(oph,v6,vph180);      /* oph=zero */
   shapedpulse(p2pat,p2,vph180,rof1,rof2);

   obl_gradient(0,0,gdiff);   /* x,y,z gradients selected via orient */
   delay(tdelta);
   zero_all_gradients();
   delay(trise);
   delay(ted2);
   startacq(alfa);
   acquire(np,1.0/sw);
   endacq();
}
示例#6
0
文件: flair.c 项目: timburrow/ovj3
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);
}
示例#7
0
文件: tssfp.c 项目: timburrow/ovj3
pulsesequence()
{
	/* declaration of SGL kernel structures */
	SGL_KERNEL_INFO_T read, phase, slice, ss_pre, ss_post;


	/* declaration of internal variables */
	double freqlist[MAXNSLICE];
	double pe_steps;
	int shapelist1, table;
	double xtime, grad_duration, ror_pad,rod_pad;
	double temp_tr;

	double readAmp, phaseAmp, sliceAmp;
	double tepad, tepad2, temin2, htrmin, delayToRF, delayRFToAcq, delayAcqToRF;
	double rof_pad, delRof;

	double sliceRephTrim, sliceDephTrim;
	double readRephTrim, readDephTrim;

	int rfPhase[2] = {0,2};
	
	/* declaration of realtime 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  vss        = v7;
	int  vssc       = v8;
	int  vacquire   = v9;
	int  vphase	= v10;
	
	settable(t2,2,rfPhase);

	/* setup phase encoding order */
	table = set_pe_order();

	init_mri();

	if( (sliceRephTrim = getvalnwarn("sliceRephTrim")) == 0.0 ) {
		sliceRephTrim = 1.0;
	}	
	
	if( (sliceDephTrim = getvalnwarn("sliceDephTrim")) == 0.0 ) {
		sliceDephTrim = 1.0;
	}	

	if( (readRephTrim = getvalnwarn("readRephTrim")) == 0.0 ) {
		readRephTrim = 1.0;
	}	
	
	if( (readDephTrim = getvalnwarn("readDephTrim")) == 0.0 ) {
		readDephTrim = 1.0;
	}	

	shape_rf( &p1_rf, "p1", p1pat, p1, flip1, rof1, rof2 );	// excitation pulse

	init_slice( &ss_grad, "ss", thk );					// slice gradient
	init_slice_refocus( &ssr_grad, "ssr" );				// slice refocus
	init_slice_refocus( &ssd_grad, "ssd" );				// slice refocus

	init_readout( &ro_grad, "ro", lro, np, sw );		// read gradient
	init_readout_refocus( &ror_grad, "ror" );			// read dephase
	init_readout_refocus( &rod_grad, "ror" );			// read dephase

	init_phase( &pe_grad, "pe", lpe, nv );				// phase gradient

	ss_grad.maxGrad = gmax * 0.57;
	ssr_grad.maxGrad = gmax * 0.57;
	ssd_grad.maxGrad = gmax * 0.57;
	ro_grad.maxGrad = gmax * 0.57;
	ror_grad.maxGrad = gmax * 0.57;
	rod_grad.maxGrad = gmax * 0.57;
	pe_grad.maxGrad = glimpe < 0.57? gmax*glimpe : gmax * 0.57;

	/* calculate the RF pulses, gradient pulses and their interdependencies */
	calc_rf( &p1_rf, "tpwr1", "tpwr1f" );
	calc_slice( &ss_grad, &p1_rf, NOWRITE, "gss" );

	ssr_grad.amp = ss_grad.amp;	
	ssr_grad.gmult = sliceRephTrim;
	ssr_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE;
	calc_slice_refocus( &ssr_grad, &ss_grad, NOWRITE, "gssr" );
	ssd_grad.amp = ss_grad.amp;	
	ssd_grad.gmult = sliceDephTrim; 
	ssd_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE;
	calc_slice_dephase( &ssd_grad, &ss_grad, NOWRITE, "gssd" ); 
	
	calc_readout( &ro_grad, NOWRITE, "gro", "sw", "at" );

	ror_grad.amp = ro_grad.amp;	
	ror_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE;

	rod_grad.amp = ro_grad.amp;	
	rod_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE;

	ror_grad.gmult = readRephTrim;
	calc_readout_refocus( &ror_grad, &ro_grad, NOWRITE, "gror" );
	rod_grad.gmult = readDephTrim;
	calc_readout_rephase( &rod_grad, &ro_grad, NOWRITE, "grod" );

	calc_phase( &pe_grad, NOWRITE, "gpe", "tpe" );

	/* work out the position of the markers */
	/* markerA */
	/* ss_grad.rfDelayFront indicates the starting point of the
	   RF pulse measured from the start of the slice gradient
       ( rof1:pulse length:rof2 ) */	

	double granulatedRFDelayFront = granularity( ss_grad.rfDelayFront, GRADIENT_RES );
	if( granulatedRFDelayFront > ss_grad.rfDelayFront ) {
		granulatedRFDelayFront -= GRADIENT_RES;
	}

	/* ss_grad.rfDelayBack indicates the end point of the
	   RF pulse measured to the end of the slice gradient
       ( rof1:pulse length:rof2 ) */	

	double granulatedRFDelayBack = granularity( ss_grad.rfDelayBack, GRADIENT_RES );
	if( granulatedRFDelayBack > ss_grad.rfDelayBack ) {
		granulatedRFDelayBack -= GRADIENT_RES;
	}
	
	double granulatedRFDelay = granulatedRFDelayFront < granulatedRFDelayBack ? granulatedRFDelayFront : granulatedRFDelayBack;

	double markerADelay = granulatedRFDelay;

	/* read and phase gradients can overlap the start or end of the slice gradient by max of granulatedRFDElay */

	double granulatedATDelayFront = granularity(ro_grad.atDelayFront, GRADIENT_RES);
	if( granulatedATDelayFront > ro_grad.atDelayFront ) {
		granulatedATDelayFront -= GRADIENT_RES;
	}
	double granulatedATDelayBack = granularity(ro_grad.atDelayBack, GRADIENT_RES);
	if( granulatedATDelayBack > ro_grad.atDelayBack ) {
		granulatedATDelayBack -= GRADIENT_RES;
	}
	double granulatedATDelay = granulatedATDelayFront < granulatedATDelayBack ? granulatedATDelayFront : granulatedATDelayBack;

	/* longest gradient between RF pulse and acquire dominates */

	xtime = ssr_grad.duration + granulatedRFDelay;
	xtime = xtime > ssd_grad.duration + granulatedRFDelay ? xtime : ssd_grad.duration + granulatedRFDelay;
	xtime = xtime > ror_grad.duration + granulatedATDelay ? xtime : ror_grad.duration + granulatedATDelay;
	xtime = xtime > rod_grad.duration + granulatedATDelay ? xtime : rod_grad.duration + granulatedATDelay;
	xtime = xtime > pe_grad.duration ? xtime : pe_grad.duration;

	ror_pad = xtime - ror_grad.duration - granulatedATDelay;
	rod_pad = xtime - rod_grad.duration - granulatedATDelay;

	/* make a gradient list */
	start_kernel( &sk );
	add_gradient( (void*)&ss_grad,  "slice",    	SLICE, START_TIME,	"",         0.0,	PRESERVE );
	add_gradient( (void*)&ssr_grad, "sliceReph", 	SLICE, BEHIND,		"slice",    0.0,	INVERT );
	add_gradient( (void*)&ror_grad, "readDeph", 	READ,  BEHIND,		"slice",   -granulatedRFDelay + ror_pad, INVERT );
	add_gradient( (void*)&ro_grad,  "read",     	READ,  BEHIND,		"readDeph", 0.0,	PRESERVE );	
	add_gradient( (void*)&pe_grad,  "phase",    	PHASE, SAME_START,	"readDeph", 0.0,	PRESERVE );
	add_gradient( (void*)&rod_grad, "readReph", 	READ,  BEHIND,		"read",     0.0,	INVERT );
	add_gradient( (void*)&pe_grad,  "rewind",		PHASE, SAME_END,	"readReph", 0.0, INVERT );
	add_gradient( (void*)&ss_grad,	"nextSlice",	SLICE, BEHIND,		"readReph", rod_pad - granulatedRFDelay, PRESERVE );
	add_gradient( (void*)&ssd_grad,	"sliceDeph",	SLICE, BEFORE,		"nextSlice",    0, INVERT );

	add_marker( "markerA", SAME_START, "slice", granulatedRFDelay );
	add_marker( "markerB", SAME_START, "nextSlice", granulatedRFDelay );

	/* get the minimum echo time */
	temin = get_timing( FROM_RF_CENTER_OF, "slice", TO_ECHO_OF, "read" );
	temin2 = get_timing( FROM_ECHO_OF, "read", TO_RF_CENTER_OF, "nextSlice" );
	
	htrmin = MAX( temin, temin2 );
	
	if( minte[0] == 'y' ){
		te = htrmin;
	}
	
	tepad = granularity( te - temin, GRADIENT_RES );
	tepad2 = granularity( te - temin2, GRADIENT_RES );

	te = temin + tepad;	
	putCmd("setvalue('te', %f, 'current')\n", te );

	if( tepad>0.0 )		change_timing( "readDeph", tepad );
	if( tepad2>0.0 )	change_timing( "nextSlice", tepad2 );

	tr = get_timing( FROM_START_OF, "slice", TO_START_OF, "nextSlice" );
	putvalue("tr", tr );

	delayRFToAcq = get_timing( FROM_RF_PULSE_OF, "slice", TO_ACQ_OF, "read" );
	delayAcqToRF = get_timing( FROM_ACQ_OF, "read", TO_RF_PULSE_OF, "nextSlice" );

	set_comp_info( &ss_pre, "ss_pre" );
	write_comp_grads_snippet( NULL, NULL, &ss_pre, "START_OF_KERNEL", "markerA" );

	set_comp_info( &read, "ro" );
	set_comp_info( &phase, "pe" );
	set_comp_info( &slice, "ss" );
	write_comp_grads_snippet( &read, &phase, &slice, "markerA", "markerB" );

	set_comp_info( &ss_post, "ss_post" );
	write_comp_grads_snippet( NULL, NULL, &ss_post, "markerB", "END_OF_KERNEL" );

	/* Set up frequency offset pulse shape list ********/   	
	offsetlist(pss,ss_grad.ssamp,0,freqlist,ns,seqcon[1]);
	shapelist1 = shapelist(p1_rf.pulseName,ss_grad.rfDuration,freqlist,ns,ss_grad.rfFraction, seqcon[1]);

	/* Set pe_steps for profile or full image **********/   	
	pe_steps = prep_profile(profile[0],nv,&pe_grad,&pe_grad);/* profile[0] is n y or r */
	F_initval(pe_steps/2.0,vpe_offset);

	g_setExpTime(trmean*(ntmean*pe_steps*arraydim + (1+fabs(ssc))*arraydim));

	/* Shift DDR for pro *******************************/   	
	roff = -poffset(pro,ro_grad.roamp);

	/* PULSE SEQUENCE */
	status( A );
	rotate();
        triggerSelect(trigger);
	obsoffset( resto );
	delay( GRADIENT_RES );
	initval( 1+fabs( ssc ), vss );
	
	obspower( p1_rf.powerCoarse );
	obspwrf( p1_rf.powerFine );
	delay( GRADIENT_RES );

	assign(one,vacquire);         // real-time acquire flag
	setacqvar(vacquire);          // Turn on acquire when vacquire is zero 
					
	obl_shapedgradient(ss_pre.name,ss_pre.dur,0,0,ss_pre.amp,NOWAIT);		
	sp1on();
	delay(GRADIENT_RES);
	sp1off();
	delay(ss_pre.dur-GRADIENT_RES );
	msloop( seqcon[1], ns, vms_slices, vms_ctr );
		
		assign(vss,vssc);

		peloop( seqcon[2], pe_steps, vpe_steps, vpe_ctr );

			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);
			}
		
			if (table)
				getelem(t1,vpe_ctr,vpe_index);
			else {
				ifzero(vacquire);
					sub(vpe_ctr,vpe_offset,vpe_index);
				elsenz(vacquire);
					sub(zero,vpe_offset,vpe_index);
				endif(vacquire);
			}		
			
			pe_shaped3gradient( read.name, phase.name, slice.name,
								read.dur, read.amp, 0, slice.amp,
								-pe_grad.increment, vpe_index, NOWAIT );
			delay(ss_grad.rfDelayFront - granulatedRFDelay);
			shapedpulselist( shapelist1, ss_grad.rfDuration, oph, rof1, rof2, seqcon[1], vms_ctr );

			delay( delayRFToAcq - alfa );
			startacq(alfa);
			acquire( np, 1/ro_grad.bandwidth );
			endacq();
			delay( delayAcqToRF - ss_grad.rfDelayFront + granulatedRFDelay - GRADIENT_RES );
			sp1on();
			delay(GRADIENT_RES);
			sp1off();
			
		endpeloop( seqcon[2], vpe_ctr ); 

	endmsloop( seqcon[1], vms_ctr );

	obl_shapedgradient(ss_post.name,ss_post.dur,0,0,ss_post.amp,WAIT);
}
示例#8
0
文件: laser.c 项目: timburrow/ovj3
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);
示例#9
0
pulsesequence()
{
  /* Internal variable declarations *********************/
  double  freq90[MAXNSLICE],freq180[MAXNSLICE];
  double  te_delay1,te_delay2,tr_delay,tau1,tau2,thk2fact,te_delay3=0.0,te_delay4=0.0,navTime=0.0;
  double  crushm0,pem0,gcrushr,gcrushp,gcrushs,pecrush;
  double  refsign=1,crushsign=1,navsign=1;
  int     shape90,shape180,table=0,sepRefocus;
  char    slprofile[MAXSTR];

  /* sequence dependent diffusion variables */
  double Gro,Gss;          // "gdiff" for readout/readout refocus and slice/slice refocus
  double dgro,dgss;        // "delta" for readout/readout refocus and slice/slice refocus
  double Dgro,Dgss;        // "DELTA" for readout/readout refocus and slice/slice refocus
  double dcrush,dgss2;     // "delta" for crusher and gss2 gradients
  double Dcrush,Dgss2;     // "DELTA" for crusher and gss2 gradients

  int    i;

  /* 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  vph180     = v7;    // Phase of 180 pulse
  int  vph2       = v8;    // alternate phase of 180 on odd transients
  int  vssc       = v9;    // Compressed steady-states
  int  vtrimage   = v10;   // Counts down from nt, trimage delay when 0
  int  vacquire   = v11;   // Argument for setacqvar, to skip steady state acquires
  int  vtrigblock = v12;   // Number of slices per trigger block

  /*  Initialize paramaters *****************************/
  init_mri();

  thk2fact=getval("thk2fact");
  pecrush=getval("pecrush");
  sepRefocus=getvalnwarn("sepRefocus");
  getstrnwarn("slprofile",slprofile);

  /*  Check for external PE table ***********************/
  init_tablepar("pelist");          // Initialize pelist parameter
  if (strcmp(petable,"n") && strcmp(petable,"N") && strcmp(petable,"")) {
    loadtable(petable);
    writetabletopar(t1,"pelist");   // Write t1 table to pelist parameter
    table = 1;
  }

  /* RF Power & Bandwidth Calculations ******************/
  shape_rf(&p1_rf,"p1",p1pat,p1,flip1,rof1,rof2);
  shape_rf(&p2_rf,"p2",p2pat,p2,flip2,rof1,rof2);
  calc_rf(&p1_rf,"tpwr1","tpwr1f");
  calc_rf(&p2_rf,"tpwr2","tpwr2f");

  /* Initialize gradient structures *********************/
  init_slice(&ss_grad,"ss",thk);
  init_slice(&ss2_grad,"ss2",thk*thk2fact);
  init_dephase(&crush_grad,"crush");
  init_slice_refocus(&ssr_grad,"ssr");
  if (FP_LT(tcrushro,alfa)) tcrushro=alfa;
  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_generic(&spoil_grad,"spoil",gspoil,tspoil);

  /* Gradient calculations ******************************/
  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");
  calc_slice(&ss_grad,&p1_rf,WRITE,"gss");
  calc_slice(&ss2_grad,&p2_rf,WRITE,"gss2");
  calc_slice_refocus(&ssr_grad,&ss_grad,WRITE,"gssr");
  calc_generic(&spoil_grad,WRITE,"","");

  /* Make sure crushing in PE dimension does not refocus signal from 180 */
  crushm0=fabs(gcrush*tcrush);
  pem0=0.0; gcrushp=0.0;
  if (pecrush) pem0=pe_grad.m0;
  calc_dephase(&crush_grad,WRITE,crushm0+pem0,"","");
  gcrushr = crush_grad.amp*crushm0/crush_grad.m0;
  if (pecrush) gcrushp = crush_grad.amp;
  gcrushs = crush_grad.amp*crushm0/crush_grad.m0;

  /* Allow phase encode and read dephase to be separated from slice refocus */
  if (sepRefocus) {
    /* Equalize read dephase and PE gradient durations */
    calc_sim_gradient(&ror_grad,&pe_grad,&null_grad,0,WRITE);
    crushsign=-1;
  } else {
    if (slprofile[0] == 'y') {
      /* Combined slice refocusing and read dephasing,
         reverse gradient sign if ror > ssr integral */
      refsign = (ss_grad.m0ref > ro_grad.m0ref) ? 1.0 : -1.0;
      ss_grad.m0ref -= ro_grad.m0ref;
      calc_slice_refocus(&ssr_grad,&ss_grad,NOWRITE,"gssr");
    }
    /* Equalize both refocus and PE gradient durations */
    calc_sim_gradient(&ror_grad,&pe_grad,&ssr_grad,0,WRITE);
  }

  /* Create optional prepulse events ********************/
  if (fsat[0] == 'y') create_fatsat();
  if (sat[0] == 'y')  create_satbands();
  if (mt[0] == 'y')   create_mtc();
  if (ir[0] == 'y')   create_inversion_recovery();
  if (diff[0] == 'y') init_diffusion(&diffusion,&diff_grad,"diff",gdiff,tdelta);

  sgl_error_check(sglerror);

  /* Min TE *********************************************/
  te = granularity(te,2*GRADIENT_RES);
  /* tau1, tau2 are the sum of events in each half echo period */
  /* tau1, tau2 include a GRADIENT_RES as this is minimum delay time */
  tau1 = ss_grad.rfCenterBack + ssr_grad.duration + crush_grad.duration + ss2_grad.rfCenterFront + 2*GRADIENT_RES;
  tau2 = ss2_grad.rfCenterBack + crush_grad.duration + ro_grad.timeToEcho + GRADIENT_RES;
  if (sepRefocus) tau2 += ror_grad.duration;
  temin = 2*MAX(tau1,tau2);

  /* Diffusion ******************************************/
  if (diff[0] == 'y') {
    /* granulate tDELTA */
    tDELTA = granularity(tDELTA,GRADIENT_RES);
    /* taudiff is the duration of events between diffusion gradients */
    taudiff = ss2_grad.duration + 2*crush_grad.duration + GRADIENT_RES;
    /* set minimum diffusion structure requirements for gradient echo: taudiff, tDELTA, te and minte[0] */
    set_diffusion(&diffusion,taudiff,tDELTA,te,minte[0]);
    /* set additional diffusion structure requirements for spin echo: tau1 and tau2 */
    set_diffusion_se(&diffusion,tau1,tau2);
    /* calculate the diffusion structure delays.
       address &temin is required in order to update temin accordingly */
    calc_diffTime(&diffusion,&temin);
  }

  /* TE delays ******************************************/
  if (minte[0] == 'y') {
    te = temin;
    putvalue("te",te);
  }
  if (FP_LT(te,temin)) {
    abort_message("TE too short, minimum TE = %.3f ms\n",temin*1000);
  }
  te_delay1 = te/2 - tau1 + GRADIENT_RES;
  te_delay2 = te/2 - tau2 + GRADIENT_RES;

  if (navigator[0] == 'y') {
    /* tau1, tau2 are the sum of events in each half echo period */
    tau1 = ro_grad.timeFromEcho + pe_grad.duration + crush_grad.duration + ss2_grad.rfCenterFront;
    tau2 = ss2_grad.rfCenterBack + crush_grad.duration + ro_grad.timeToEcho;
    if (FP_GT(tau1,tau2)) {
      te_delay3 = GRADIENT_RES;
      te_delay4 = tau1-tau2+GRADIENT_RES;
    } else {
      te_delay3 = tau2-tau1+GRADIENT_RES;
      te_delay4 = GRADIENT_RES;
    }
    navTime = te_delay3 + ss2_grad.duration + 2*crush_grad.duration + ro_grad.duration + te_delay4 + 2*GRADIENT_RES;
  }

  /* Check nsblock, the number of slices blocked together
     (used for triggering and/or inversion recovery) */
  check_nsblock();

  /* Min TR *********************************************/   	
  trmin = ss_grad.rfCenterFront  + te + ro_grad.timeFromEcho + pe_grad.duration + 2*GRADIENT_RES;

  /* Increase TR if any options are selected ************/
  if (spoilflag[0] == 'y') trmin += spoil_grad.duration;
  if (navigator[0] == 'y') trmin += navTime;
  if (sat[0] == 'y')       trmin += satTime;
  if (fsat[0] == 'y')      trmin += fsatTime;
  if (mt[0] == 'y')        trmin += mtTime;
  if (ticks > 0)           trmin += GRADIENT_RES;

  /* Adjust for all slices ******************************/
  trmin *= ns;

  /* Inversion recovery *********************************/
  if (ir[0] == 'y') {
    /* tauti is the additional time beyond IR component to be included in ti */
    /* satTime, fsatTime and mtTime all included as those modules will be after IR */
    tauti = satTime + fsatTime + mtTime + GRADIENT_RES + ss_grad.rfCenterFront;
    /* calc_irTime checks ti and returns the time of all IR components */
    trmin += calc_irTime(tauti,trmin,mintr[0],tr,&trtype);
  }

  if (mintr[0] == 'y') {
    tr = trmin;
    putvalue("tr",tr);
  }
  if (FP_LT(tr,trmin)) {
    abort_message("TR too short, minimum TR = %.3f ms\n",trmin*1000);
  }

  /* TR delay *******************************************/
  tr_delay = granularity((tr-trmin)/ns,GRADIENT_RES);

  /* Calculate B values *********************************/
  if (ix == 1) {
    /* Calculate bvalues according to main diffusion gradients */
    calc_bvalues(&diffusion,"dro","dpe","dsl");
    /* Add components from additional diffusion encoding imaging gradients peculiar to this sequence */
    /* Initialize variables */
    dgro = 0.5*(ror_grad.duration+ro_grad.timeToEcho);
    Gro = ro_grad.m0ref/dgro; Dgro = dgro;
    if (!sepRefocus) Dgro = te-ss_grad.rfCenterBack-ro_grad.timeToEcho;
    dgss = 0.5*(ss_grad.rfCenterBack+ssr_grad.duration);
    Gss = ss_grad.m0ref/dgss; Dgss = dgss;
    dgss2 = ss2_grad.duration/2; Dgss2 = dgss2;
    dcrush = crush_grad.duration-crush_grad.tramp; Dcrush = crush_grad.duration+ss2_grad.duration;
    for (i = 0; i < diffusion.nbval; i++)  {
      /* set droval, dpeval and dslval */
      set_dvalues(&diffusion,&droval,&dpeval,&dslval,i);
      /* Readout */
      diffusion.bro[i] += bval(Gro,dgro,Dgro);
      diffusion.bro[i] += bval(crushsign*gcrushr,dcrush,Dcrush);
      diffusion.bro[i] += bval_nested(gdiff*droval,tdelta,tDELTA,crushsign*gcrushr,dcrush,Dcrush);
      if (!sepRefocus) {
        diffusion.bro[i] += bval_nested(Gro,dgro,Dgro,gdiff*droval,tdelta,tDELTA);
        diffusion.bro[i] += bval_nested(Gro,dgro,Dgro,crushsign*gcrushr,dcrush,Dcrush);
      }
      /* Phase */
      if (pecrush) {
        diffusion.bpe[i] += bval(gcrushp,dcrush,Dcrush);
        diffusion.bpe[i] += bval_nested(gdiff*dpeval,tdelta,tDELTA,gcrushp,dcrush,Dcrush);
      }
      /* Slice */
      diffusion.bsl[i] += bval(Gss,dgss,Dgss);
      diffusion.bsl[i] += bval(gcrushs,dcrush,Dcrush);
      diffusion.bsl[i] += bval(ss2_grad.ssamp,dgss2,Dgss2);
      diffusion.bsl[i] += bval_nested(gdiff*dslval,tdelta,tDELTA,gcrushs,dcrush,Dcrush);
      diffusion.bsl[i] += bval_nested(gdiff*dslval,tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2);
      diffusion.bsl[i] += bval_nested(gcrushs,dcrush,Dcrush,ss2_grad.ssamp,dgss2,Dgss2);
      /* Readout/Phase Cross-terms */
      diffusion.brp[i] += bval_cross(gdiff*dpeval,tdelta,tDELTA,crushsign*gcrushr,dcrush,Dcrush);
      diffusion.brp[i] += bval_cross(gdiff*dpeval,tdelta,tDELTA,crushsign*gcrushr,dcrush,Dcrush);
      if (pecrush) diffusion.brp[i] += bval_cross(gdiff*droval,tdelta,tDELTA,gcrushp,dcrush,Dcrush);
      if (!sepRefocus) {
        diffusion.brp[i] += bval_cross(Gro,dgro,Dgro,gdiff*dpeval,tdelta,tDELTA);
        if (pecrush) diffusion.brp[i] += bval_cross(Gro,dgro,Dgro,gcrushp,dcrush,Dcrush);
      }
      /* Readout/Slice Cross-terms */
      diffusion.brs[i] += bval2(crushsign*gcrushr,gcrushs,dcrush,Dcrush);
      diffusion.brs[i] += bval_cross(gdiff*droval,tdelta,tDELTA,gcrushs,dcrush,Dcrush);
      diffusion.brs[i] += bval_cross(gdiff*dslval,tdelta,tDELTA,crushsign*gcrushr,dcrush,Dcrush);
      diffusion.brs[i] += bval_cross(gdiff*droval,tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2);
      if (!sepRefocus) {
        diffusion.brs[i] += bval_cross(Gro,dgro,Dgro,gdiff*dslval,tdelta,tDELTA);
        diffusion.brs[i] += bval_cross(Gro,dgro,Dgro,gcrushs,dcrush,Dcrush);
        diffusion.brs[i] += bval_cross(Gro,dgro,Dgro,ss2_grad.ssamp,dgss2,Dgss2);
      }
      /* Slice/Phase Cross-terms */
      diffusion.bsp[i] += bval_cross(gdiff*dpeval,tdelta,tDELTA,gcrushs,dcrush,Dcrush);
      diffusion.bsp[i] += bval_cross(gdiff*dpeval,tdelta,tDELTA,ss2_grad.ssamp,dgss2,Dgss2);
      if (pecrush) { 
        diffusion.bsp[i] += bval2(gcrushs,gcrushp,dcrush,Dcrush);
        diffusion.bsp[i] += bval_cross(gdiff*dslval,tdelta,tDELTA,gcrushp,dcrush,Dcrush);
        diffusion.bsp[i] += bval_cross(gcrushp,dcrush,Dcrush,ss2_grad.ssamp,dgss2,Dgss2);
      }
    }  /* End for-all-directions */
    /* Write the values */
    write_bvalues(&diffusion,"bval","bvalue","max_bval");
  }

  /* Generate phase-ramped pulses ***********************/
  offsetlist(pss,ss_grad.ssamp,0,freq90,ns,seqcon[1]);
  offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]);
  shape90 = shapelist(p1_rf.pulseName,ss_grad.rfDuration,freq90,ns,ss_grad.rfFraction,seqcon[1]);
  shape180 = shapelist(p2_rf.pulseName,ss2_grad.rfDuration,freq180,ns,ss2_grad.rfFraction,seqcon[1]);

  /* Set pe_steps for profile or full image *************/   	
  pe_steps = prep_profile(profile[0],nv,&pe_grad,&null_grad);
  F_initval(pe_steps/2.0,vpe_offset);

  /* Shift DDR for pro **********************************/
  roff = -poffset(pro,ro_grad.roamp);

  /* Adjust experiment time for VnmrJ *******************/
  if (ssc<0) {
    if (seqcon[2] == 'c') g_setExpTime(trmean*(ntmean*pe_steps*arraydim - ssc*arraydim));
    else g_setExpTime(trmean*(ntmean*pe_steps*arraydim - ssc*pe_steps*arraydim));
  }
  else g_setExpTime(trmean*ntmean*pe_steps*arraydim + tr*ssc);

  /* Slice profile **************************************/
  if (slprofile[0] == 'y' && !sepRefocus) ror_grad.amp = 0;

  /* Set phase cycle table ******************************/
  if (sepRefocus) settable(t2,1,ph180); // Phase encode is just before readout
  else settable(t2,2,ph180);

  /* PULSE SEQUENCE *************************************/
  status(A);                          // Set status A
  rotate();                           // Set gradient rotation according to psi, phi and theta
  triggerSelect(trigger);             // Select trigger input 1/2/3
  obsoffset(resto);                   // Set spectrometer frequency
  delay(GRADIENT_RES);                // Delay for frequency setting
  initval(fabs(ssc),vssc);            // Compressed steady-state counter
  if (seqcon[2]=='s') assign(zero,vssc); // Zero for standard peloop
  assign(one,vacquire);               // real-time acquire flag
  setacqvar(vacquire);                // Turn on acquire when vacquire is zero 

  /* trigger */
  if (ticks > 0) F_initval((double)nsblock,vtrigblock);

  /* Begin phase-encode loop ****************************/       
  peloop(seqcon[2],pe_steps,vpe_steps,vpe_ctr);

    if (trtype) delay(ns*tr_delay);   // relaxation delay

    /* 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);
    }

    /* 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);
    }

    /* Phase cycle ****************************************/       
    getelem(t2,vpe_ctr,vph180);             // For phase encoding with slice rephase
    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 (!trtype) delay(tr_delay);         // Relaxation delay

      if (ticks > 0) {
        modn(vms_ctr,vtrigblock,vtest);
        ifzero(vtest);                      // if the beginning of an trigger block
          xgate(ticks);
          grad_advance(gpropdelay);
          delay(GRADIENT_RES);
        elsenz(vtest);
          delay(GRADIENT_RES);
        endif(vtest);
      }

      sp1on(); delay(GRADIENT_RES); sp1off();     // Scope trigger

      /* Prepulse options ***********************************/
      if (ir[0] == 'y')   inversion_recovery();
      if (sat[0] == 'y')  satbands();
      if (fsat[0] == 'y') fatsat();
      if (mt[0] == 'y')   mtc();

      /* Slice select RF pulse ******************************/ 
      obspower(p1_rf.powerCoarse);
      obspwrf(p1_rf.powerFine);
      delay(GRADIENT_RES);
      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);

      /* Slice refocus gradient *****************************/
      if (sepRefocus) 
        obl_shapedgradient(ssr_grad.name,ssr_grad.duration,0,0,-ssr_grad.amp,WAIT);
      else
        /* Include phase encode and readout dephase gradient if refocus gradients not separated */
        pe_shapedgradient(pe_grad.name,pe_grad.duration,ror_grad.amp,0,-ssr_grad.amp*refsign,pe_grad.increment,vpe_mult,WAIT);

      if (diff[0] == 'y') {
        delay(diffusion.d1);
        diffusion_dephase(&diffusion,dro,dpe,dsl);
        delay(diffusion.d2);
      } 
      else 
        delay(te_delay1);

      /* Refocusing RF pulse ********************************/ 
      obspower(p2_rf.powerCoarse);
      obspwrf(p2_rf.powerFine);
      delay(GRADIENT_RES);
      obl_shapedgradient(crush_grad.name,crush_grad.duration,crushsign*gcrushr,gcrushp,gcrushs,WAIT);
      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);
      obl_shapedgradient(crush_grad.name,crush_grad.duration,crushsign*gcrushr,gcrushp,gcrushs,WAIT);

      if (diff[0] == 'y') {
        delay(diffusion.d3);
        diffusion_rephase(&diffusion,dro,dpe,dsl);
        delay(diffusion.d4);
      } 
      else 
        delay(te_delay2);

      /* Readout dephase, phase encode & readout gradients **/
      roff = -poffset(pro,ro_grad.roamp);  // incase inverted navigator is acquired
      if (slprofile[0] == 'y') {
        /* Readout gradient only if refocus gradients not separated */
        if (sepRefocus)
          obl_shapedgradient(ror_grad.name,ror_grad.duration,0,0,-ror_grad.amp,WAIT);
        obl_shapedgradient(ro_grad.name,ro_grad.duration,0,0,ro_grad.amp,NOWAIT);
      } else {
        /* Readout gradient only if refocus gradients not separated */
        if (sepRefocus) 
          pe_shapedgradient(pe_grad.name,pe_grad.duration,-ror_grad.amp,0,0,-pe_grad.increment,vpe_mult,WAIT);
        obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT);
      }

      /* Acquisition ****************************************/
      delay(ro_grad.atDelayFront-alfa);
      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_mult,WAIT);

      /* Navigator acquisition ******************************/
      if (navigator[0] == 'y') {
        delay(te_delay3);
        obl_shapedgradient(crush_grad.name,crush_grad.duration,-crushsign*gcrushr,0,-gcrushs,WAIT);
        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);
        obl_shapedgradient(crush_grad.name,crush_grad.duration,-crushsign*gcrushr,0,-gcrushs,WAIT);
        delay(te_delay4);
        obl_shapedgradient(ro_grad.name,ro_grad.duration,navsign*ro_grad.amp,0,0,NOWAIT);
        delay(ro_grad.atDelayFront-alfa);
        startacq(alfa);
        acquire(np,1.0/sw);
        delay(ro_grad.atDelayBack);
        endacq();
      }

      if (spoilflag[0] == 'y') {
        obl_shapedgradient(spoil_grad.name,spoil_grad.duration,navsign*spoil_grad.amp,0,spoil_grad.amp,WAIT);
      }

    endmsloop(seqcon[1],vms_ctr);

  endpeloop(seqcon[2],vpe_ctr);

  /* Inter-image delay **********************************/
  sub(ntrt,ct,vtrimage);
  decr(vtrimage);
  ifzero(vtrimage);
    delay(trimage);
  endif(vtrimage);

  /* Duty cycle *****************************************/
  calc_grad_duty(tr);

}
示例#10
0
pulsesequence()
{
  /* Internal variable declarations *************************/
  double  freqEx[MAXNSLICE];
  double  maxgradtime,spoilMoment,perTime,tau1,te_delay,tr_delay;
  double  te2=0.0,te3=0.0,te2min,te3min,tau2,tau3,te2_delay,te3_delay=0;
  char    minte2[MAXSTR],minte3[MAXSTR],spoilflag[MAXSTR];
  int     sepSliceRephase,sepReadRephase=0,readrev,table,shapeEx;
  int     i;

  /* 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
  int  vne          = v13;     // Number of echoes
  int  vne_ctr      = v14;     // Echo loop counter
  int  vneindex     = v15;     // Echo index, odd or even
  int  vnelast      = v16;     // Check for last echo
  int  vtrigblock   = v17;     // Number of slices per trigger block

  /* Initialize paramaters **********************************/
  init_mri();

  getstr("spoilflag",spoilflag);
  te2=getval("te2");
  te3=getval("te3");
  getstr("minte2",minte2);
  getstr("minte3",minte3);
  readrev=(int)getval("readrev");

  /*  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 *************************/
  shape_rf(&p1_rf,"p1",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
  ro_grad.pad1=alfa; ro_grad.pad2=alfa;
  init_readout_refocus(&ror_grad,"ror");             // dephase gradient
  init_phase(&pe_grad,"pe",lpe,nv);                  // phase encode gradient
  init_dephase(&spoil_grad,"spoil");                 // optimized spoiler
  init_dephase(&ref_grad,"ref");                     // readout rephase

  /* 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,WRITE,"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");
  calc_dephase(&ref_grad,WRITE,ro_grad.m0,"","");

  spoilMoment = ro_grad.acqTime*ro_grad.roamp;   // Optimal spoiling is at*gro for 2pi per pixel
  spoilMoment -= ro_grad.m0def;                  // Subtract partial spoiling from back half of readout
  calc_dephase(&spoil_grad,WRITE,spoilMoment,"gspoil","tspoil");

  /* Is TE long enough for separate slice refocus? ******/
  maxgradtime = MAX(ror_grad.duration,pe_grad.duration);
  if (spoilflag[0] == 'y')
    maxgradtime = MAX(maxgradtime,spoil_grad.duration);
  tau1 = ss_grad.rfCenterBack + ssr_grad.duration + maxgradtime + ro_grad.timeToEcho + GRADIENT_RES;

  /* Equalize refocus and PE gradient durations *********/
  if ((te >= tau1) && (minte[0] != 'y')) {
    sepSliceRephase = 1;                         // Set flag for separate slice rephase
    calc_sim_gradient(&ror_grad,&pe_grad,&spoil_grad,tpemin,WRITE);
  } else {
    sepSliceRephase = 0;
    calc_sim_gradient(&ror_grad,&pe_grad,&ssr_grad,tpemin,WRITE);
    calc_sim_gradient(&ror_grad,&spoil_grad,&null_grad,tpemin,NOWRITE);
  }

  perTime = 0.0;
  if ((perewind[0] == 'y') || (spoilflag[0] == 'y'))
    perTime = spoil_grad.duration;
  if (spoilflag[0] == 'n')
    spoil_grad.amp = 0.0;

  /* 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')   create_inversion_recovery();

  /* Set up frequency offset pulse shape list ********/   	
  offsetlist(pss,ss_grad.ssamp,0,freqEx,ns,seqcon[1]);
  shapeEx = shapelist(p1_rf.pulseName,ss_grad.rfDuration,freqEx,ns,ss_grad.rfFraction,seqcon[1]);
  
  /* Check that all Gradient calculations are ok ************/
  sgl_error_check(sglerror);

  /* Min TE ******************************************/
  tau1 = ss_grad.rfCenterBack + pe_grad.duration + ro_grad.timeToEcho;
  tau1 += (sepSliceRephase) ? ssr_grad.duration : 0.0;   // Add slice refocusing if separate event

  temin = tau1 + GRADIENT_RES;  /* ensure that te_delay is at least GRADIENT_RES */
  te = granularity(te,GRADIENT_RES);
  if (minte[0] == 'y') {
    te = temin;
    putvalue("te",te);
  }
  if (FP_LT(te,temin)) {
    abort_message("TE too short.  Minimum TE= %.3fms\n",temin*1000);   
  }
  te_delay = te - tau1;

  /* Min TE2 *****************************************/
  tau2 = (readrev) ? 2*ro_grad.timeFromEcho : ro_grad.duration+ref_grad.duration;
  te2min = tau2 + GRADIENT_RES;
  te2 = granularity(te2,GRADIENT_RES);
  if (minte2[0] == 'y') {
    te2 = te2min;
    putvalue("te2",te2);
  }
  if (FP_LT(te2,te2min)) {
    abort_message("TE2 too short.  Minimum TE2= %.3fms\n",te2min*1000);
  }

  if (readrev) te2_delay = te2 - tau2;
  else {
    tau2 = ro_grad.duration + 3*ror_grad.duration;
    if (te2 >= tau2) {
      sepReadRephase = 1; // Set flag for separate read rephase
      te2_delay = te2 - ro_grad.duration - 2*ror_grad.duration;
    } else {
      sepReadRephase = 0;
      if (te2 > te2min+GRADIENT_RES) {
        ref_grad.duration = granularity(te2-ro_grad.duration-2*GRADIENT_RES,GRADIENT_RES);
        ref_grad.calcFlag = AMPLITUDE_FROM_MOMENT_DURATION;
        calc_dephase(&ref_grad,WRITE,ro_grad.m0,"","");
      }
      te2_delay = te2 - ro_grad.duration - ref_grad.duration;
    }
  }

  /* Min TE3 *****************************************/
  if (readrev) {  
    tau3 = 2*ro_grad.timeToEcho;
    te3min = tau3 + GRADIENT_RES;
    te3 = granularity(te3,GRADIENT_RES);
    if (minte3[0] == 'y') {
      te3 = te3min;
      putvalue("te3",te3);
    }
    if (FP_LT(te3,te3min)) {
      abort_message("TE3 too short.  Minimum TE3= %.3fms\n",te3min*1000);
    }
    te3_delay = te3 - tau3;
  }

  /* Now set the TE array accordingly */
  putCmd("TE = 0"); /* Re-initialize TE */
  putCmd("TE[1] = %f",te*1000);
  if (readrev) {
    for (i=1;i<ne;i++) {
      if (i%2 == 0) putCmd("TE[%d] = TE[%d]+%f",i+1,i,te3*1000);
      else putCmd("TE[%d] = TE[%d]+%f",i+1,i,te2*1000);
    }
  } else {
    for (i=1;i<ne;i++) putCmd("TE[%d] = TE[%d]+%f",i+1,i,te2*1000);
  }

  /* Check nsblock, the number of slices blocked together
     (used for triggering and/or inversion recovery) */
  check_nsblock();

  /* Min TR ******************************************/
  trmin  = ss_grad.duration + te_delay + pe_grad.duration + ne*ro_grad.duration + perTime + 2*GRADIENT_RES;
  trmin += (sepSliceRephase) ? ssr_grad.duration : 0.0;   // Add slice refocusing if separate event
  if (readrev) trmin += (ne/2)*te2_delay + ((ne-1)/2)*te3_delay;
  else trmin += (sepReadRephase) ? (ne-1)*(te2_delay+2*ror_grad.duration) : (ne-1)*(te2_delay+ref_grad.duration);

  /* Increase TR if any options are selected *********/
  if (sat[0] == 'y')  trmin += satTime;
  if (fsat[0] == 'y') trmin += fsatTime;
  if (mt[0] == 'y')   trmin += mtTime;
  if (ticks > 0) trmin += GRADIENT_RES;

  /* Adjust for all slices ***************************/
  trmin *= ns;

  /* Inversion recovery *********************************/
  if (ir[0] == 'y') {
    /* tauti is the additional time beyond IR component to be included in ti */
    /* satTime, fsatTime and mtTime all included as those modules will be after IR */
    tauti = satTime + fsatTime + mtTime + GRADIENT_RES + ss_grad.rfCenterFront;
    /* calc_irTime checks ti and returns the time of all IR components */
    trmin += calc_irTime(tauti,trmin,mintr[0],tr,&trtype);
  }

  if (mintr[0] == 'y') {
    tr = trmin;
    putvalue("tr",tr);
  }
  if (FP_LT(tr,trmin)) {
    abort_message("TR too short.  Minimum TR = %.3fms\n",trmin*1000);
  }

  /* Calculate tr delay */
  tr_delay = granularity((tr-trmin)/ns,GRADIENT_RES);

  /* Set pe_steps for profile or full image **********/   	
  pe_steps = prep_profile(profile[0],nv,&pe_grad,&per_grad);
  F_initval(pe_steps/2.0,vpe_offset);

  /* Shift DDR for pro *******************************/   	
  roff = -poffset(pro,ro_grad.roamp);

  /* Adjust experiment time for VnmrJ *********************/
  if (ssc<0) {
    if (seqcon[2] == 'c') g_setExpTime(trmean*(ntmean*pe_steps*arraydim - ssc*arraydim));
    else g_setExpTime(trmean*(ntmean*pe_steps*arraydim - ssc*pe_steps*arraydim));
  }
  else g_setExpTime(trmean*ntmean*pe_steps*arraydim + tr*ssc);

  /* PULSE SEQUENCE ***************************************/
  status(A);
  rotate();
  triggerSelect(trigger);       // Select trigger input 1/2/3
  obsoffset(resto);
  delay(GRADIENT_RES);
  initval(fabs(ssc),vssc);      // Compressed steady-state counter
  if (seqcon[2]=='s') assign(zero,vssc); // Zero for standard peloop
  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 

  /* trigger */
  if (ticks > 0) F_initval((double)nsblock,vtrigblock);

  /* Begin phase-encode loop ****************************/       
  peloop(seqcon[2],pe_steps,vpe_steps,vpe_ctr);

    if (trtype) delay(ns*tr_delay);   // relaxation delay

    /* 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);

      if (!trtype) delay(tr_delay);   // Relaxation delay

      if (ticks > 0) {
        modn(vms_ctr,vtrigblock,vtest);
        ifzero(vtest);                // if the beginning of an trigger block
          xgate(ticks);
          grad_advance(gpropdelay);
          delay(GRADIENT_RES);
        elsenz(vtest);
          delay(GRADIENT_RES);
        endif(vtest);
      }

      /* TTL scope trigger **********************************/       
      sp1on(); delay(GRADIENT_RES); sp1off();

      /* Prepulse options ***********************************/       
      if (ir[0] == 'y')   inversion_recovery();
      if (sat[0] == 'y')  satbands();
      if (fsat[0] == 'y') fatsat();
      if (mt[0] == 'y')   mtc();

      /* Slice select RF pulse ******************************/ 
      obspower(p1_rf.powerCoarse);
      obspwrf(p1_rf.powerFine);
      delay(GRADIENT_RES);
      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 ********/
      if (sepSliceRephase) {                // separate slice refocus gradient
        obl_shapedgradient(ssr_grad.name,ssr_grad.duration,0,0,-ssr_grad.amp,WAIT);
        delay(te_delay);                    // delay between slab refocus and pe
        pe_shapedgradient(pe_grad.name,pe_grad.duration,-ror_grad.amp,0,0,
            -pe_grad.increment,vpe_mult,WAIT);
      } else {
        pe_shapedgradient(pe_grad.name,pe_grad.duration,-ror_grad.amp,0,-ssr_grad.amp,
            -pe_grad.increment,vpe_mult,WAIT);
        delay(te_delay);                    // delay after refocus/pe
      }

      F_initval(ne,vne);
      loop(vne,vne_ctr);

        if (readrev) {
          mod2(vne_ctr,vneindex);
          ifzero(vneindex);
            /* Shift DDR for pro *******************************/
            roff = -poffset(pro,ro_grad.roamp);
            /* Readout gradient ********************************/
            obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT);
            delay(ro_grad.atDelayFront-alfa);
            /* Acquisition ***************************************/
            startacq(alfa);
            acquire(np,1.0/sw);
            delay(ro_grad.atDelayBack);
            endacq();
            sub(vne,vne_ctr,vnelast);
            sub(vnelast,one,vnelast);
            ifzero(vnelast);
            elsenz(vnelast);
              delay(te2_delay);
            endif(vnelast);
          elsenz(vneindex);
            /* Shift DDR for pro *******************************/
            roff = -poffset(pro,-ro_grad.roamp);
            /* Readout gradient ********************************/
            obl_shapedgradient(ro_grad.name,ro_grad.duration,-ro_grad.amp,0,0,NOWAIT);
            delay(ro_grad.atDelayFront-alfa);
            /* Acquisition ***************************************/
            startacq(alfa);
            acquire(np,1.0/sw);
            delay(ro_grad.atDelayBack);
            endacq();
            sub(vne,vne_ctr,vnelast);
            sub(vnelast,one,vnelast);
            ifzero(vnelast);
            elsenz(vnelast);
              delay(te3_delay);
            endif(vnelast);
          endif(vneindex);
        } else {
          /* Shift DDR for pro *******************************/
          roff = -poffset(pro,ro_grad.roamp);
          /* Readout gradient ********************************/
          obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp,0,0,NOWAIT);
          delay(ro_grad.atDelayFront-alfa);
          /* Acquisition ***************************************/
          startacq(alfa);
          acquire(np,1.0/sw);
          delay(ro_grad.atDelayBack);
          endacq();
	  sub(vne,vne_ctr,vnelast);
	  sub(vnelast,one,vnelast);
	  ifzero(vnelast);
	  elsenz(vnelast);
            if (sepReadRephase) {
              obl_shapedgradient(ror_grad.name,ror_grad.duration,-ror_grad.amp,0,0,WAIT);
              delay(te2_delay);
              obl_shapedgradient(ror_grad.name,ror_grad.duration,-ror_grad.amp,0,0,WAIT);
            } else {
              obl_shapedgradient(ref_grad.name,ref_grad.duration,-ref_grad.amp,0,0,WAIT);
              delay(te2_delay);
            }
	  endif(vnelast);
        }

      endloop(vne_ctr);

      /* Rewind / spoiler gradient **************************/
      if ((perewind[0] == 'y') || (spoilflag[0] == 'y')) {
        pe_shapedgradient(pe_grad.name,pe_grad.duration,spoil_grad.amp,0,0,pe_grad.increment,vper_mult,WAIT);
      }

    endmsloop(seqcon[1],vms_ctr);

  endpeloop(seqcon[2],vpe_ctr);

  /* Inter-image delay **********************************/
  sub(ntrt,ct,vtrimage);
  decr(vtrimage);
  ifzero(vtrimage);
    delay(trimage);
  endif(vtrimage);
}
示例#11
0
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);
}
示例#12
0
文件: ge3dshim.c 项目: timburrow/ovj3
pulsesequence()
{
  /* Internal variable declarations *************************/ 
  double  freqEx[MAXNSLICE];
  double  pespoil_amp,spoilMoment,maxgradtime,pe2_offsetamp=0.0,nvblock;
  double  tetime,te_delay,tr_delay,perTime;
  int     table=0,shapeEx=0,sepSliceRephase=0,image,blocknvs;
  char    spoilflag[MAXSTR],perName[MAXSTR],slab[MAXSTR];

  /* Real-time variables used in this sequence **************/
  int  vpe_steps    = v1;      // Number of PE steps
  int  vpe_ctr      = v2;      // PE loop counter
  int  vpe_offset   = v3;      // PE/2 for non-table offset
  int  vpe_mult     = v4;      // PE multiplier, ranges from -PE/2 to PE/2
  int  vper_mult    = v5;      // PE rewinder multiplier; turn off rewinder when 0
  int  vpe2_steps   = v6;      // Number of PE2 steps
  int  vpe2_ctr     = v7;      // PE2 loop counter
  int  vpe2_mult    = v8;      // PE2 multiplier
  int  vpe2_offset  = v9;      // PE2/2 for non-table offset
  int  vpe2r_mult   = v10;     // PE2 rewinder multiplier
  int  vtrigblock   = v11;     // Number of PE steps per trigger block
  int  vpe          = v12;     // Current PE step out of total PE*PE2 steps

  /*  Initialize paramaters *********************************/
  init_mri();
  getstr("spoilflag",spoilflag);                                     
  getstr("slab",slab);
  image = getval("image");
  blocknvs = (int)getval("blocknvs");
  nvblock = getval("nvblock");
  if (!blocknvs) nvblock=1;    // If blocked PEs for trigger not selected nvblock=1

  trmin = 0.0;
  temin = 0.0;

  /*  Check for external PE table ***************************/
  if (strcmp(petable,"n") && strcmp(petable,"N") && strcmp(petable,"")) {
    loadtable(petable);
    table = 1;
  }

  if (ns > 1)  abort_message("No of slices must be set to one");   

  /* RF Calculations ****************************************/
  init_rf(&p1_rf,p1pat,p1,flip1,rof1,rof2);   /* hard pulse */
  init_rf(&p2_rf,p2pat,p2,flip2,rof1,rof2);   /* soft pulse */
  calc_rf(&p1_rf,"tpwr1","tpwr1f");
  calc_rf(&p2_rf,"tpwr2","tpwr2f");

  /* Gradient calculations **********************************/
  if (slab[0] == 'y') {
    init_slice(&ss_grad,"ss",thk);
    init_slice_refocus(&ssr_grad,"ssr");
    calc_slice(&ss_grad,&p2_rf,WRITE,"gss");
    calc_slice_refocus(&ssr_grad,&ss_grad,WRITE,"gssr");
  }
  if (FP_GT(tcrushro,0.0))
    init_readout_butterfly(&ro_grad,"ro",lro,np,sw,gcrushro,tcrushro);
  else
    init_readout(&ro_grad,"ro",lro,np,sw);
  init_readout_refocus(&ror_grad,"ror");
  calc_readout(&ro_grad,WRITE,"gro","sw","at");
  ro_grad.m0ref *= grof;
  calc_readout_refocus(&ror_grad,&ro_grad,NOWRITE,"gror");
  init_phase(&pe_grad,"pe",lpe,nv);
  init_phase(&pe2_grad,"pe2",lpe2,nv2);
  calc_phase(&pe_grad,NOWRITE,"gpe","tpe");
  if (!blocknvs) nvblock=1;
  calc_phase(&pe2_grad,NOWRITE,"gpe2","");

  if (spoilflag[0] == 'y') {                         // Calculate spoil grad if spoiling is turned on
    init_dephase(&spoil_grad,"spoil");               // Optimized spoiler
    spoilMoment = ro_grad.acqTime*ro_grad.roamp;     // Optimal spoiling is at*gro for 2pi per pixel
    spoilMoment -= ro_grad.m0def;                    // Subtract partial spoiling from back half of readout
    calc_dephase(&spoil_grad,WRITE,spoilMoment,"gspoil","tspoil");
  }

  /* Is TE long enough for separate slab refocus? ***********/
  maxgradtime = MAX(ror_grad.duration,MAX(pe_grad.duration,pe2_grad.duration));
  if (spoilflag[0] == 'y')
    maxgradtime = MAX(maxgradtime,spoil_grad.duration);
  tetime = maxgradtime + alfa + ro_grad.timeToEcho + 4e-6;
  if (slab[0] == 'y') {
    tetime += ss_grad.rfCenterBack + ssr_grad.duration;
    if ((te >= tetime) && (minte[0] != 'y')) {
      sepSliceRephase = 1;                                 // Set flag for separate slice rephase
    } else {
      pe2_grad.areaOffset = ss_grad.m0ref;                 // Add slab refocus on pe2 axis
      calc_phase(&pe2_grad,NOWRITE,"gpe2","");             // Recalculate pe2 to include slab refocus
    }
  }
 
  /* Equalize refocus and PE gradient durations *************/
  pespoil_amp = 0.0;
  perTime = 0.0;
  if ((perewind[0] == 'y') && (spoilflag[0] == 'y')) {   // All four must be single shape
    if (ror_grad.duration > spoil_grad.duration) {       // calc_sim first with ror
      calc_sim_gradient(&pe_grad,&pe2_grad,&ror_grad,tpemin,WRITE);
      calc_sim_gradient(&ror_grad,&spoil_grad,&null_grad,tpemin,NOWRITE);
    } else {                                             // calc_sim first with spoil
      calc_sim_gradient(&pe_grad,&pe2_grad,&spoil_grad,tpemin,WRITE);
      calc_sim_gradient(&ror_grad,&spoil_grad,&null_grad,tpemin,NOWRITE);
    }
    strcpy(perName,pe_grad.name);
    perTime = pe_grad.duration;
    putvalue("tspoil",perTime);
    putvalue("gspoil",spoil_grad.amp);
  } else {                      // post-acquire shape will be either pe or spoil, but not both
    calc_sim_gradient(&ror_grad,&pe_grad,&pe2_grad,tpemin,WRITE);
    if ((perewind[0] == 'y') && (spoilflag[0] == 'n')) {     // Rewinder, no spoiler
      strcpy(perName,pe_grad.name);
      perTime = pe_grad.duration;
      spoil_grad.amp = 0.0;
      putvalue("tpe",perTime);
    } else if ((perewind[0] == 'n') && (spoilflag[0] == 'y')) {  // Spoiler, no rewinder
      strcpy(perName,spoil_grad.name);
      perTime = spoil_grad.duration;
      pespoil_amp = spoil_grad.amp;      // Apply spoiler on PE & PE2 axis if no rewinder
    }
  }

  if (slab[0] == 'y') pe2_offsetamp = sepSliceRephase ? 0.0 : pe2_grad.offsetamp;  // pe2 slab refocus

  /* Create optional prepulse events ************************/
  if (sat[0] == 'y')  create_satbands();
  if (fsat[0] == 'y') create_fatsat();

  sgl_error_check(sglerror);                               // Check for any SGL errors
  
  /* Min TE ******************************************/
  tetime = pe_grad.duration + alfa + ro_grad.timeToEcho;
  if (slab[0] == 'y') {
    tetime += ss_grad.rfCenterBack;
    tetime += (sepSliceRephase) ? ssr_grad.duration : 0.0;   // Add slice refocusing if separate event
  }
  else if (ws[0] == 'y')
    tetime += p2/2.0 + rof2;	/* soft pulse */
  else
    tetime += p1/2.0 + rof2;	/* hard pulse */
  temin = tetime + 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 - tetime;

  /* Min TR ******************************************/   	
  trmin  = te_delay + pe_grad.duration + ro_grad.duration + perTime;
  if (slab[0] == 'y') {
    trmin += ss_grad.duration;
    trmin += (sepSliceRephase) ? ssr_grad.duration : 0.0;   // Add slice refocusing if separate event
  }
  else if (ws[0] == 'y')
    trmin += p2 +rof1 + rof2;	/* soft pulse */
  else
    trmin += p1 +rof1 + rof2;	/* hard pulse */
  trmin += 8e-6;

  /* Increase TR if any options are selected *********/
  if (sat[0] == 'y')  trmin += satTime;
  if (fsat[0] == 'y') trmin += fsatTime;
  if (ticks > 0) trmin += 4e-6;

  if (mintr[0] == 'y') {
    tr = trmin;
    putvalue("tr",tr);
  }
  if (FP_LT(tr,trmin)) {
    abort_message("TR too short.  Minimum TR = %.2fms\n",trmin*1000+0.005);
  }

  /* Calculate tr delay */
  tr_delay = granularity(tr-trmin,GRADIENT_RES);

  if(slab[0] == 'y') {
    /* Generate phase-ramped pulses: 90 */
    offsetlist(pss,ss_grad.ssamp,0,freqEx,ns,seqcon[1]);
    shapeEx = shapelist(p1pat,ss_grad.rfDuration,freqEx,ns,ss_grad.rfFraction,seqcon[1]);
  }

  /* Set pe_steps for profile or full image **********/   	
  pe_steps = prep_profile(profile[0],nv,&pe_grad,&null_grad);
  F_initval(pe_steps/2.0,vpe_offset);

  pe2_steps = prep_profile(profile[1],nv2,&pe2_grad,&null_grad);
  F_initval(pe2_steps/2.0,vpe2_offset);

  assign(zero,oph);

  /* Shift DDR for pro *******************************/   	
  roff = -poffset(pro,ro_grad.roamp);

  /* Adjust experiment time for VnmrJ *******************/
  g_setExpTime(tr*(nt*pe_steps*pe2_steps));

  /* PULSE SEQUENCE *************************************/
  status(A);
  rotate();
  triggerSelect(trigger);       // Select trigger input 1/2/3
  obsoffset(resto);
  delay(4e-6);

  /* trigger */
  if (ticks > 0) F_initval((double)nvblock,vtrigblock);

  /* Begin phase-encode loop ****************************/       
  peloop2(seqcon[3],pe2_steps,vpe2_steps,vpe2_ctr);

    peloop(seqcon[2],pe_steps,vpe_steps,vpe_ctr);

      delay(tr_delay);   // relaxation delay

      sub(vpe_ctr,vpe_offset,vpe_mult);
      sub(vpe2_ctr,vpe2_offset,vpe2_mult);

      mult(vpe2_ctr,vpe_steps,vpe);
      add(vpe_ctr,vpe,vpe);

      /* PE rewinder follows PE table; zero if turned off ***/       
      if (perewind[0] == 'y') {
        assign(vpe_mult,vper_mult);
        assign(vpe2_mult,vpe2r_mult);
      }
      else {
        assign(zero,vper_mult);
        assign(zero,vpe2r_mult);
      }

      if (ticks > 0) {
        modn(vpe,vtrigblock,vtest);
        ifzero(vtest);                // if the beginning of an trigger block
          xgate(ticks);
          grad_advance(gpropdelay);
          delay(4e-6);
        elsenz(vtest);
          delay(4e-6);
        endif(vtest);
      }

      sp1on(); delay(4e-6); sp1off(); // Scope trigger

      /* Prepulse options ***********************************/
      if (sat[0] == 'y')  satbands();
      if (fsat[0] == 'y') fatsat();

      if (slab[0] == 'y') {
        obspower(p2_rf.powerCoarse);
        obspwrf(p2_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,zero,rof1,rof2,seqcon[1],zero);
	delay(ss_grad.rfDelayBack);
        if (sepSliceRephase) {
          obl_shapedgradient(ssr_grad.name,ssr_grad.duration,0,0,-ssr_grad.amp,WAIT);
          delay(te_delay + tau);   /* tau is current B0 encoding delay */
        }
      } else {
        obspower(p1_rf.powerCoarse);
        obspwrf(p1_rf.powerFine);
        delay(4e-6);
        if (ws[0] == 'y')
          shapedpulse(p2pat,p2,zero,rof1,rof2);   /* soft CS pulse */
        else
          shapedpulse(p1pat,p1,zero,rof1,rof2);   /* hard pulse */
        delay(te_delay + tau);   /* tau is current B0 encoding delay */
      }        

      pe2_shapedgradient(pe_grad.name,pe_grad.duration,-ror_grad.amp*image,0,-pe2_offsetamp,
          -pe_grad.increment,-pe2_grad.increment,vpe_mult,vpe2_mult,WAIT);

      if ((slab[0] == 'y') && !sepSliceRephase) delay(te_delay + tau);   /* tau is current B0 encoding delay */

      /* Readout gradient and acquisition ********************/
      obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.amp*image,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')) {
        pe2_shapedgradient(perName,perTime,spoil_grad.amp,pespoil_amp,pespoil_amp,
          pe_grad.increment,pe2_grad.increment,vper_mult,vpe2r_mult,WAIT);
      }  

    endpeloop(seqcon[2],vpe_ctr);

  endpeloop(seqcon[3],vpe2_ctr);

}
示例#13
0
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);
}
示例#14
0
void pulsesequence() {
  /* Internal variable declarations *********************/
  int    shapelist90,shapelist180,shapelistte=0;
  double kzero,thk2fact,thk3fact;
  double te1=0.0,te1_delay,te2_delay,te3_delay,tr_delay,te_delay1=0.0,te_delay2=0.0;
  double crushm0,pem0,gcrushr,gcrushp,gcrushs;
  double freq90[MAXNSLICE],freq180[MAXNSLICE],freqte[MAXNSLICE];
  char   autocrush[MAXSTR];

  /* Phase encode variables */
  FILE  *fp;
  int    tab[4096],petab[4096],odd,seg0,tabscheme;
  char   tabname[MAXSTR],tabfile[MAXSTR];
  int    i,j,k;

  /* Diffusion variables */
  double Gro,Gss;          // "gdiff" for readout/readout refocus and slice/slice refocus
  double dgro,Dgro;        // delta and DELTA for readout dephase & readout
  double dgss,Dgss;        // delta and DELTA for excitation ss
  double dgss3,Dgss3;      // delta and DELTA for spin echo prep ss
  double dcrush3,Dcrush3;  // delta and DELTA for spin echo prep crusher
  double dgss2,Dgss2;      // delta and DELTA for refocus ss
  double dcrush2,Dcrush2;  // delta and DELTA for refocus crusher

  /* 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  vpe2_steps  = v10;  // Number of PE2 steps
  int  vpe2_ctr    = v11;  // PE2 loop counter
  int  vpe2_mult   = v12;  // PE2 multiplier
  int  vpe2_offset = v13;  // PE2/2 for non-table offset
  int  vssc        = v14;  // Compressed steady-states
  int  vtrimage    = v15;  // Counts down from nt, trimage delay when 0
  int  vacquire    = v16;  // Argument for setacqvar, to skip steady state acquires
  int  vphase180   = v17;  // phase of 180 degree refocusing pulse
  int  vtrigblock  = v18;  // Number of slices per trigger block

  /* Initialize paramaters ******************************/
  init_mri();

  kzero = getval("kzero");
  getstr("autocrush",autocrush);
  tabscheme = getval("tabscheme");
  getstr("spoilflag",spoilflag);

  /* Allow ROxPE2 projection ****************************/
  if (profile[0] == 'y' && profile[1] == 'n') {
    etl=1; kzero=1; nv=nv2;
  } else {
    /* Check kzero is valid *****************************/
    if (kzero<1) kzero=1; if (kzero>etl) kzero=etl;
    putCmd("kzero = %d",(int)kzero); 
  }

  /* Set petable name and full path *********************/
  sprintf(tabname,"fse%d_%d_%d",(int)nv,(int)etl,(int)kzero);
  putCmd("petable = '%s'",tabname);
  strcpy(tabfile,userdir);
  strcat(tabfile,"/tablib/");
  strcat(tabfile,tabname);

  /* Generate phase encode table ************************/
  if (tabscheme) { /* New scheme */
    /* Calculate PE table for kzero=1 */
    seg0=nseg/2;
    for (j=0;j<seg0;j++) {
      for (i=0;i<etl/2;i++) tab[j*(int)etl+i] = i*nseg+seg0-j;
      for (i=1;i<=etl/2;i++) tab[(j+1)*(int)etl-i] = tab[j*(int)etl]-i*nseg;
    }
    for (j=seg0;j<nseg;j++) {
      for (i=0;i<=etl/2;i++) tab[j*(int)etl+i] = i*nseg+seg0-j;
      for (i=1;i<etl/2;i++) tab[(j+1)*(int)etl-i] = tab[j*(int)etl]-i*nseg;
    }
    /* Adjust for kzero */
    for (i=0;i<nseg;i++) { 
      k=i*etl;
      for (j=0;j<kzero-1;j++) petab[k+j]=tab[k+(int)etl-(int)kzero+j+1];
      for (j=kzero-1;j<etl;j++) petab[k+j]=tab[k+j-(int)kzero+1];
    }
  } else { /* Original scheme */
    /* Calculate PE table for kzero=1 */
    odd=(int)nseg%2; seg0=nseg/2+odd;
    k=0; for (i=0;i<etl;i++) for (j=seg0-odd*i%2-1;j>=0;j--) tab[j*(int)etl+i] = k--;
    k=1; for (i=0;i<etl;i++) for (j=seg0-odd*i%2;j<nseg;j++) tab[j*(int)etl+i] = k++;
    /* Adjust for kzero */
    for (i=0;i<nseg;i++) { 
      k=i*etl;
      for (j=0;j<kzero-1;j++) petab[k+j]=tab[k+(int)etl-j-1];
      for (j=kzero-1;j<etl;j++) petab[k+j]=tab[k+j-(int)kzero+1];
    }
  }
  /* Set petable name and full path *********************/
  sprintf(tabname,"fse%d_%d_%d",(int)nv,(int)etl,(int)kzero);
  putCmd("petable = '%s'",tabname);
  strcpy(tabfile,userdir);
  strcat(tabfile,"/tablib/");
  strcat(tabfile,tabname);
  /* Write to tabfile ***********************************/
  fp=fopen(tabfile,"w");
  fprintf(fp,"t1 =");
  for (i=0;i<nseg;i++) { 
    fprintf(fp,"\n");
    for (j=0;j<etl;j++) fprintf(fp,"%3d\t",petab[i*(int)etl+j]);
  }
  fclose(fp);

  /* Set pelist to contain table order ******************/
  putCmd("pelist = 0"); /* Re-initialize pelist */
  for (i=0;i<nseg*etl;i++) putCmd("pelist[%d] = %d",i+1,petab[i]);

  /* Avoid gradient slew rate errors */
  for (i=0;i<nseg*etl;i++) if (abs(petab[i]) > nv/2) petab[i]=0;

  /* Set phase encode table *****************************/
  settable(t1,(int)etl*nseg,petab);

  /* RF Power & Bandwidth Calculations ******************/
  shape_rf(&p1_rf,"p1",p1pat,p1,flip1,rof1,rof2);
  shape_rf(&p2_rf,"p2",p2pat,p2,flip2,rof1,rof2);
  calc_rf(&p1_rf,"tpwr1","tpwr1f");
  calc_rf(&p2_rf,"tpwr2","tpwr2f");

  /* Calculate thk2fact to ensure gss=gss2 for the choice of p1 and p2 
     so that the sequence remains robust in the absence of correct
     balancing of slice select and slice refocus gradients */
  thk2fact=p2_rf.bandwidth/p1_rf.bandwidth;
  putvalue("thk2fact",thk2fact);
  
  /* Initialize gradient structures *********************/
  init_readout(&ro_grad,"ro",lro,np,sw);
  ro_grad.pad1=alfa; ro_grad.pad2=alfa;
  init_readout_refocus(&ror_grad,"ror");
  init_phase(&pe_grad,"pe",lpe,nv);
  init_phase(&pe2_grad,"pe2",lpe2,nv2);
  init_slice(&ss_grad,"ss",thk);
  init_slice(&ss2_grad,"ss2",thk*thk2fact);
  init_slice_refocus(&ssr_grad,"ssr");
  init_dephase(&crush_grad,"crush");

  /* Gradient calculations ******************************/
  calc_readout(&ro_grad,WRITE,"gro","sw","at");
  calc_readout_refocus(&ror_grad,&ro_grad,WRITE,"gror");
  calc_phase(&pe_grad,NOWRITE,"","");
  calc_phase(&pe2_grad,NOWRITE,"","");
  calc_slice(&ss_grad,&p1_rf,WRITE,"gss");
  calc_slice(&ss2_grad,&p2_rf,WRITE,"");
  calc_slice_refocus(&ssr_grad,&ss_grad,WRITE,"gssr");

  /* Equalize refocus gradient durations ****************/
  calc_sim_gradient(&ror_grad,&null_grad,&ssr_grad,0.0,WRITE);

  /* Equalize PE gradient durations *********************/
  calc_sim_gradient(&pe_grad,&pe2_grad,&null_grad,0.0,WRITE);

  /* Set crushing gradient moment ***********************/
  crushm0=fabs(gcrush*tcrush);

  if (spoilflag[0] == 'y') {
    init_generic(&spoil_grad,"spoil",gspoil,tspoil);
    calc_generic(&spoil_grad,WRITE,"gspoil","tspoil");
  }

  /* 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')   create_inversion_recovery();
  if (diff[0] == 'y') init_diffusion(&diffusion,&diff_grad,"diff",gdiff,tdelta);

  if (diff[0] == 'y') { /* Diffusion encoding is during spin echo preparation */
    spinecho[0]='y';
    putCmd("spinecho='y'");
  }

  if (spinecho[0] == 'y') { /* spin echo preparation */
    shape_rf(&p3_rf,"p3",p3pat,p3,flip3,rof1,rof2);
    calc_rf(&p3_rf,"tpwr3","tpwr3f");
    /* Calculate thk3fact to ensure gss=gss2=gss3 for the choice of  
       p1, p2 and p3 so that the sequence remains robust in the absence
       of correct balancing of slice select and slice refocus gradients */
    thk3fact=p3_rf.bandwidth/p1_rf.bandwidth;
    putvalue("thk3fact",thk3fact);
    init_slice(&ss3_grad,"ss3",thk*thk3fact);
    calc_slice(&ss3_grad,&p3_rf,WRITE,"");
    putvalue("gss3",ss3_grad.ssamp);
    offsetlist(pss,ss3_grad.ssamp,0,freqte,ns,seqcon[1]);
    shapelistte = shapelist(p3_rf.pulseName,ss3_grad.rfDuration,freqte,ns,ss3_grad.rfFraction,seqcon[1]);
    /* Automatically set crushers to avoid unwanted echoes */
    if (autocrush[0] == 'y') {
      if (crushm0 < 0.6*ro_grad.m0) crushm0=0.6*ro_grad.m0;
    }
  }

  /* Make sure crushing in PE dimensions does not refocus signal from 180 */
  pem0 = (pe_grad.m0 > pe2_grad.m0) ? pe_grad.m0 : pe2_grad.m0;
  calc_dephase(&crush_grad,WRITE,crushm0+pem0,"","");
  gcrushr = crush_grad.amp*crushm0/crush_grad.m0;
  gcrushp = crush_grad.amp*(crushm0+pe_grad.m0)/crush_grad.m0;
  gcrushs = crush_grad.amp*(crushm0+pe2_grad.m0)/crush_grad.m0;

  sgl_error_check(sglerror);

  /* Set up frequency offset pulse shape list ***********/
  offsetlist(pss,ss_grad.amp,0,freq90,ns,seqcon[1]);
  offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]);
  shapelist90 = shapelist(p1_rf.pulseName,ss_grad.rfDuration,freq90,ns,ss_grad.rfFraction,seqcon[1]);
  shapelist180 = shapelist(p2_rf.pulseName,ss2_grad.rfDuration,freq180,ns,ss2_grad.rfFraction,seqcon[1]);

  /* To ensure proper overlap spin and stimulated echoes ensure that the
     middle of the refocusing RF pulse is the centre of the pulse and that
     echoes are formed in the centre of the acquisition window */
  if (ss2_grad.rfFraction != 0.5)
    abort_message(
      "ERROR %s: Refocusing RF pulse must be symmetric (RF fraction = %.2f)",
      seqfil,ss2_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 ****/
  esp = granularity(esp,2*GRADIENT_RES);
  tau1 = ss_grad.rfCenterBack + ssr_grad.duration + crush_grad.duration + ss2_grad.rfCenterFront + GRADIENT_RES;
  tau2 = ss2_grad.rfCenterBack + crush_grad.duration + pe_grad.duration + ro_grad.timeToEcho + GRADIENT_RES; 
  tau3 = ro_grad.timeFromEcho + pe_grad.duration + crush_grad.duration + ss2_grad.rfCenterFront + GRADIENT_RES;
  espmin  = 2*MAX(MAX(tau1,tau2),tau3);       // Minimum echo spacing

  if (minesp[0] == 'y') {
    esp = espmin;
    putvalue("esp",esp);
  }
  if (FP_LT(esp,espmin)) {
    abort_message("ERROR %s: Echo spacing too small, minimum is %.3fms\n",seqfil,espmin*1000);
  }
  te1_delay = esp/2.0 - tau1 + GRADIENT_RES;  // Intra-esp delays
  te2_delay = esp/2.0 - tau2 + GRADIENT_RES;
  te3_delay = esp/2.0 - tau3 + GRADIENT_RES;

  /* Spin echo preparation ******************************/
  if (spinecho[0] == 'y') {
    te = granularity(te,2*GRADIENT_RES);
    te1 = te-kzero*esp;
    tau1 = ss_grad.rfCenterBack + ssr_grad.duration + crush_grad.duration + ss3_grad.duration/2.0 + GRADIENT_RES;
    tau2 = ss3_grad.duration/2.0 + crush_grad.duration + GRADIENT_RES;
    temin = 2*MAX(tau1,tau2);
    /* Diffusion */
    if (diff[0] == 'y') {
      /* granulate tDELTA */
      tDELTA = granularity(tDELTA,GRADIENT_RES);
      /* taudiff is the duration of events between diffusion gradients */
      taudiff = ss3_grad.duration + 2*crush_grad.duration;
      /* set minimum diffusion structure requirements for gradient echo: taudiff, tDELTA, te and minte[0] */
      set_diffusion(&diffusion,taudiff,tDELTA,te1,minte[0]);
      /* set additional diffusion structure requirements for spin echo: tau1 and tau2 */
      set_diffusion_se(&diffusion,tau1,tau2);
      /* calculate the diffusion structure delays.
         address &temin is required in order to update temin accordingly */
      calc_diffTime(&diffusion,&temin);
    }
    /* TE delays */
    if (minte[0] == 'y') {
      te1 = temin;
      te = te1+kzero*esp;
      putvalue("te",te);
    }
    te_delay1 = te1/2 - tau1 + GRADIENT_RES;
    te_delay2 = te1/2 - tau2 + GRADIENT_RES;
    if (FP_LT(te,temin+kzero*esp)) {
      abort_message("ERROR %s: TE too short, minimum TE = %.3f ms\n",seqfil,temin*1000);
    }
  }

  else
    putvalue("te",kzero*esp);       // Return effective TE

  /* Check nsblock, the number of slices blocked together
     (used for triggering and/or inversion recovery) */
  check_nsblock();

  /* Calculate B values *********************************/
  if (ix==1) {
    /* Calculate bvalues according to main diffusion gradients */
    calc_bvalues(&diffusion,"dro","dpe","dsl");
    /* Add components from additional diffusion encoding imaging gradients peculiar to this sequence */
    /* Initialize variables */
    dgro = 0.5*(ror_grad.duration+ro_grad.timeToEcho);        // readout dephase & readout delta
    Gro = ro_grad.m0ref/dgro;                                 // readout dephase & readout gradient strength
    Dgro = dgro+2*crush_grad.duration+ss2_grad.duration+te2_delay+pe_grad.duration; // readout dephase & readout DELTA
    dgss = 0.5*(ss_grad.rfCenterBack+ssr_grad.duration);      // slice & slice refocus delta
    Gss = ss_grad.m0ref/dgss;                                 // slice & slice refocus gradient strength
    Dgss = dgss;                                              // slice & slice refocus DELTA
    dgss2 = (ss2_grad.duration-ss2_grad.tramp)/2.0;           // refocus slice select delta
    Dgss2 = dgss2;                                            // refocus slice select DELTA
    dcrush2 = crush_grad.duration-crush_grad.tramp;           // refocus crusher delta
    Dcrush2 = crush_grad.duration+ss2_grad.duration;          // refocus crusher DELTA
    dcrush3 = crush_grad.duration-crush_grad.tramp;           // spin echo prep crusher delta
    Dcrush3 = crush_grad.duration+ss3_grad.duration;          // spin echo prep crusher DELTA
    dgss3 = (ss3_grad.duration-ss3_grad.tramp)/2.0;           // spin echo prep slice select delta
    Dgss3 = dgss3;                                            // spin echo prep slice select DELTA
    for (i = 0; i < diffusion.nbval; i++)  {
      /* set droval, dpeval and dslval */
      set_dvalues(&diffusion,&droval,&dpeval,&dslval,i);
      /* Readout */
      diffusion.bro[i] += bval(Gro,dgro,Dgro);
      diffusion.bro[i] += bval(gcrushr,dcrush2,Dcrush2);
      diffusion.bro[i] += bval_nested(Gro,dgro,Dgro,gcrushr,dcrush2,Dcrush2);
      /* Phase */
      diffusion.bpe[i] += bval(gcrushp,dcrush2,Dcrush2);
      /* Slice */
      diffusion.bsl[i] += bval(Gss,dgss,Dgss);
      diffusion.bsl[i] += bval(gcrushs,dcrush2,Dcrush2);
      diffusion.bsl[i] += bval(ss2_grad.ssamp,dgss2,Dgss2);
      diffusion.bsl[i] += bval_nested(gcrushs,dcrush2,Dcrush2,ss2_grad.ssamp,dgss2,Dgss2);
      /* Readout/Phase Cross-terms */
      diffusion.brp[i] += bval2(gcrushr,gcrushp,dcrush2,Dcrush2);
      /* Readout/Slice Cross-terms */
      diffusion.brs[i] += bval_cross(Gro,dgro,Dgro,gcrushs,dcrush2,Dcrush2);
      diffusion.brs[i] += bval_cross(Gro,dgro,Dgro,ss2_grad.ssamp,dgss2,Dgss2);
      diffusion.brs[i] += bval2(gcrushr,gcrushs,dcrush2,Dcrush2);
      diffusion.brs[i] += bval_cross(gcrushr,dcrush2,Dcrush2,ss2_grad.ssamp,dgss2,Dgss2);
      /* Slice/Phase Cross-terms */
      diffusion.bsp[i] += bval2(gcrushs,gcrushp,dcrush2,Dcrush2);
      diffusion.bsp[i] += bval_cross(gcrushp,dcrush2,Dcrush2,ss2_grad.ssamp,dgss2,Dgss2);
      if (spinecho[0] == 'y') {
        /* Readout */
        diffusion.bro[i] += bval(crush_grad.amp,dcrush3,Dcrush3);  
        diffusion.bro[i] += bval_nested(gdiff*droval,tdelta,tDELTA,crush_grad.amp,dcrush3,Dcrush3);
        /* Slice */
        diffusion.bsl[i] += bval(ss3_grad.amp,dgss3,Dgss3);
        diffusion.bsl[i] += bval_nested(gdiff*dslval,tdelta,tDELTA,ss3_grad.ssamp,dgss3,Dgss3);
        /* Readout/Slice Cross-terms */
        diffusion.brs[i] += bval_cross(gdiff*dslval,tdelta,tDELTA,crush_grad.amp,dcrush3,Dcrush3);
        diffusion.brs[i] += bval_cross(gdiff*droval,tdelta,tDELTA,ss3_grad.amp,dgss3,Dgss3);
        diffusion.brs[i] += bval_cross(crush_grad.amp,dcrush3,Dcrush3,ss3_grad.amp,dgss3,Dgss3);
        /* Readout/Phase Cross-terms */
        diffusion.brp[i] += bval_cross(gdiff*dpeval,tdelta,tDELTA,crush_grad.amp,dcrush3,Dcrush3);
        /* Slice/Phase Cross-terms */
        diffusion.bsp[i] += bval_cross(gdiff*dpeval,tdelta,tDELTA,ss3_grad.amp,dgss3,Dgss3);
      }
    }  /* End for-all-directions */
    /* Write the values */
    write_bvalues(&diffusion,"bval","bvalue","max_bval");
  }

  /* Minimum TR *****************************************/
  trmin =  ss_grad.rfCenterFront + etl*esp + ro_grad.timeFromEcho + pe_grad.duration + te3_delay + 2*GRADIENT_RES;
  if (spoilflag[0] == 'y') trmin += spoil_grad.duration;

  /* Increase TR if any options are selected ************/
  if (sat[0] == 'y')  trmin += satTime;
  if (fsat[0] == 'y') trmin += fsatTime;
  if (mt[0] == 'y')   trmin += mtTime;
  if (spinecho[0] == 'y')   trmin += te1;
  if (ticks > 0) trmin += GRADIENT_RES;

  /* Adjust for all slices ******************************/
  trmin *= ns;

  /* Inversion recovery *********************************/
  if (ir[0] == 'y') {
    /* tauti is the additional time beyond IR component to be included in ti */
    /* satTime, fsatTime and mtTime all included as those modules will be after IR */
    tauti = satTime + fsatTime + mtTime + GRADIENT_RES + ss_grad.rfCenterFront;
    /* calc_irTime checks ti and returns the time of all IR components */
    trmin += calc_irTime(tauti,trmin,mintr[0],tr,&trtype);
  }

  if (mintr[0] == 'y') {
    tr = trmin;
    putvalue("tr",tr);
  }
  if (FP_LT(tr,trmin)) {
    abort_message("ERROR %s: TR too short, minimum TR = %.3fms\n",seqfil,trmin*1000);
  }

  /* Calculate tr delay *********************************/
  tr_delay = granularity((tr-trmin)/ns,GRADIENT_RES);

  /* Set number of segments for profile or full image ***/
  nseg = prep_profile(profile[0],nseg,&pe_grad,&null_grad);

  pe2_steps = prep_profile(profile[1],nv2,&pe2_grad,&null_grad);
  F_initval(pe2_steps/2.0,vpe2_offset);

  /* Shift DDR for pro **********************************/
  roff = -poffset(pro,ro_grad.roamp);

  /* Adjust experiment time for VnmrJ *******************/
  if (ssc<0) {
    if (seqcon[2] == 's' && seqcon[3]=='s') g_setExpTime(trmean*ntmean*arraydim - ssc*arraydim);
    else if (seqcon[2]=='s') g_setExpTime(trmean*nseg*(ntmean*pe2_steps*arraydim - ssc*arraydim));
    else if (seqcon[3]=='s') g_setExpTime(trmean*pe2_steps*(ntmean*nseg*arraydim - ssc*arraydim));
    else g_setExpTime(trmean*(ntmean*pe_steps*pe2_steps*arraydim - ssc*arraydim));
  }
  else g_setExpTime(trmean*ntmean*nseg*pe2_steps*arraydim + tr*ssc);

  /* PULSE SEQUENCE *************************************/
  status(A);                          // Set status A
  rotate();                           // Set gradient rotation according to psi, phi and theta
  triggerSelect(trigger);             // Select trigger input 1/2/3
  obsoffset(resto);                   // Set spectrometer frequency
  delay(GRADIENT_RES);                // Delay for frequency setting

  initval(fabs(ssc),vssc);            // Compressed steady-state counter
  if (seqcon[2]=='s' && seqcon[3]=='s') assign(zero,vssc); // Zero for standard peloop and pe2loop
  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);

  /* trigger */
  if (ticks > 0) F_initval((double)nsblock,vtrigblock);

  /* Begin phase-encode loop ****************************/       
  peloop2(seqcon[3],pe2_steps,vpe2_steps,vpe2_ctr);

    /* Begin phase-encode loop ****************************/
    peloop(seqcon[2],nseg,vseg,vseg_ctr);

      if (trtype) delay(ns*tr_delay);   // relaxation delay

      /* Compressed steady-states: 1st array & transient, all arrays if ssc is negative */
      if ((ix > 1) && (ssc > 0))
	assign(zero,vssc);
      if (seqcon[2] == 'c')
        sub(vseg_ctr,vssc,vseg_ctr);    // vseg_ctr counts up from -ssc
      else if (seqcon[3] == 'c')
        sub(vpe2_ctr,vssc,vpe2_ctr);    // vpe2_ctr counts up from -ssc
      assign(zero,vssc);
      if (seqcon[2] == 's' && seqcon[3]=='s')
	assign(zero,vacquire);          // Always acquire for non-compressed loop
      else {
        if (seqcon[2] == 'c') {
	  ifzero(vseg_ctr);
            assign(zero,vacquire);      // Start acquiring when vseg_ctr reaches zero
	  endif(vseg_ctr);
        }
        else if (seqcon[3] == 'c') {
	  ifzero(vpe2_ctr);
            assign(zero,vacquire);      // Start acquiring when vpe2_ctr reaches zero
	  endif(vpe2_ctr);
        }
      }
      setacqvar(vacquire);              // Turn on acquire when vacquire is zero

      /* Use standard encoding order for 2nd PE dimension */
      ifzero(vacquire);
        sub(vpe2_ctr,vpe2_offset,vpe2_mult);
      elsenz(vacquire);
        sub(zero,vpe2_offset,vpe2_mult);
      endif(vacquire);

      msloop(seqcon[1],ns,vms_slices,vms_ctr);

        if (!trtype) delay(tr_delay);   // Relaxation delay

        if (ticks > 0) {
          modn(vms_ctr,vtrigblock,vtest);
          ifzero(vtest);                // if the beginning of an trigger block
            xgate(ticks);
            grad_advance(gpropdelay);
            delay(GRADIENT_RES);
          elsenz(vtest);
            delay(GRADIENT_RES);
          endif(vtest);
        }

        sp1on(); delay(GRADIENT_RES); sp1off(); // Scope trigger

        /* Prepulse options ***********************************/
        if (ir[0] == 'y')   inversion_recovery();
        if (sat[0] == 'y')  satbands();
        if (fsat[0] == 'y') fatsat();
        if (mt[0] == 'y')   mtc();

        /* 90 degree pulse ************************************/         
        obspower(p1_rf.powerCoarse);
        obspwrf(p1_rf.powerFine);
        delay(GRADIENT_RES);
        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);

        /* Spin echo preparation ******************************/
        if (spinecho[0] == 'y') {
          obl_shapedgradient(ssr_grad.name,ssr_grad.duration,0.0,0.0,-ssr_grad.amp,WAIT);
          if (diff[0] == 'y') {
            delay(diffusion.d1);
            diffusion_dephase(&diffusion,dro,dpe,dsl);
            delay(diffusion.d2);
          }
          else
            delay(te_delay1);
          obspower(p3_rf.powerCoarse);
          obspwrf(p3_rf.powerFine);
          obl_shapedgradient(crush_grad.name,crush_grad.duration,crush_grad.amp,0.0,0.0,WAIT);
          obl_shapedgradient(ss3_grad.name,ss3_grad.duration,0,0,ss3_grad.amp,NOWAIT);
          delay(ss3_grad.rfDelayFront);
          shapedpulselist(shapelistte,ss3_grad.rfDuration,vphase180,rof1,rof2,seqcon[1],vms_ctr);
          delay(ss3_grad.rfDelayBack);
          obl_shapedgradient(crush_grad.name,crush_grad.duration,crush_grad.amp,0.0,0.0,WAIT);
          if (diff[0] == 'y') {
            delay(diffusion.d3);
            diffusion_rephase(&diffusion,dro,dpe,dsl);
            delay(diffusion.d4);
          }
          else
            delay(te_delay2);
          delay(ss_grad.duration/2.0);
          delay(te1_delay);
          obspower(p2_rf.powerCoarse);
          obspwrf(p2_rf.powerFine);
          obl_shapedgradient(ror_grad.name,ror_grad.duration,ror_grad.amp,0.0,0.0,WAIT);
        }

        else {
          /* 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);
        }
	
        F_initval(etl,vetl);
        loop(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 *********************************/
          obl_shapedgradient(crush_grad.name,crush_grad.duration,gcrushr,gcrushp,gcrushs,WAIT);
          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);   
          obl_shapedgradient(crush_grad.name,crush_grad.duration,gcrushr,gcrushp,gcrushs,WAIT);

          /* Second half-TE period ****************************/
          delay(te2_delay);
	 
          /* Phase-encode gradient ****************************/
          pe2_shapedgradient(pe_grad.name,pe_grad.duration,0,0,0,-pe_grad.increment,-pe2_grad.increment,vpe_mult,vpe2_mult,WAIT);

          /* Readout gradient *********************************/
          obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.roamp,0,0,NOWAIT);
          delay(ro_grad.atDelayFront-alfa);

          /* Acquire data *************************************/
          startacq(alfa);
          acquire(np,1.0/sw);
          endacq();

          delay(ro_grad.atDelayBack);

          /* Rewinding phase-encode gradient ******************/
          pe2_shapedgradient(pe_grad.name,pe_grad.duration,0,0,0,pe_grad.increment,pe2_grad.increment,vpe_mult,vpe2_mult,WAIT);

          /* Second half-TE delay *****************************/
          delay(te3_delay);

        endloop(vetl_ctr);

        if (spoilflag[0] == 'y') 
          obl_shapedgradient(spoil_grad.name,spoil_grad.duration,spoil_grad.amp,spoil_grad.amp,spoil_grad.amp,WAIT);

      endmsloop(seqcon[1],vms_ctr);

    endpeloop(seqcon[2],vseg_ctr);

  endpeloop(seqcon[3],vpe2_ctr);

  /* Inter-image delay **********************************/
  sub(ntrt,ct,vtrimage);
  decr(vtrimage);
  ifzero(vtrimage);
    delay(trimage);
  endif(vtrimage);
}
示例#15
0
  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);

}
示例#16
0
文件: mems.c 项目: timburrow/ovj3
pulsesequence() {
  /* Internal variable declarations *************************/
  int     shapelist90,shapelist180;
  int     table = 0;
  double  tau1,tau2,tau3,te1_delay,te2_delay,te3_delay,tr_delay;
  double  freq90[MAXNSLICE],freq180[MAXNSLICE];
  double  thk2fact,crush_step,neby2,crush_ind;
  int     suppressSTE,*crushtab;
  char    crushmod[MAXSTR];
  int     i;

  /* Real-time variables used in this sequence **************/
  int  vpe_steps  = v1;    // Number of PE steps
  int  vpe_ctr    = v2;    // PE loop counter
  int  vpe_mult   = v3;    // PE multiplier, ranges from -PE/2 to PE/2
  int  vpe_offset = v4;    // PE/2 for non-table offset
  int  vms_slices = v5;    // Number of slices
  int  vms_ctr    = v6;    // Slice loop counter
  int  vne        = v7;    // Number of echoes
  int  vne_ctr    = v8;    // Echo loop counter
  int  vssc       = v9;    // Compressed steady-states
  int  vtrimage   = v10;   // Counts down from nt, trimage delay when 0
  int  vacquire   = v11;   // Argument for setacqvar, to skip steady state acquires
  int  vphase90   = v12;   // Phase of 90 degree excitation pulse
  int  vphase180  = v13;   // Phase of 180 degree refocusing pulse
  int  vphindex   = v14;   // Phase cycle index
  int  vneindex   = v15;   // Echo index, odd or even
  int  vcrush     = v16;   // Crusher modulation
  int  vtrigblock = v17;   // Number of slices per trigger block

  /* Initialize paramaters **********************************/
  init_mri();

  getstr("crushmod",crushmod);
  suppressSTE=getval("suppressSTE");

  /*  Load external PE table ********************************/
  if (strcmp(petable,"n") && strcmp(petable,"N") && strcmp(petable,"")) {
    loadtable(petable);
    table = 1;
  }

  /* RF Power & Bandwidth Calculations **********************/
  shape_rf(&p1_rf,"p1",p1pat,p1,flip1,rof1,rof2);
  shape_rf(&p2_rf,"p2",p2pat,p2,flip2,rof1,rof2);
  calc_rf(&p1_rf,"tpwr1","tpwr1f");
  calc_rf(&p2_rf,"tpwr2","tpwr2f");

  /* Calculate thk2fact to ensure gss=gss2 for the choice of p1 and p2 
     so that the sequence remains robust in the absence of correct
     balancing of slice select and slice refocus gradients */
  thk2fact=p2_rf.bandwidth/p1_rf.bandwidth;
  putvalue("thk2fact",thk2fact);
  
  /* Initialize gradient structures *************************/
  init_readout(&ro_grad,"ro",lro,np,sw); 
  ro_grad.pad1=alfa; ro_grad.pad2=alfa;
  init_readout_refocus(&ror_grad,"ror");
  init_phase(&pe_grad,"pe",lpe,nv);
  init_slice(&ss_grad,"ss",thk);
  init_slice(&ss2_grad,"ss2",thk*thk2fact);
  init_slice_refocus(&ssr_grad,"ssr");
  init_generic(&crush_grad,"crush",gcrush,tcrush);

  /* 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,&p2_rf,WRITE,"");
  calc_slice_refocus(&ssr_grad,&ss_grad,NOWRITE,"gssr");
  calc_generic(&crush_grad,WRITE,"","");

  /* Equalize slice 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')   create_inversion_recovery();

  sgl_error_check(sglerror);

  /* Set up frequency offset pulse shape list ********/
  offsetlist(pss,ss_grad.amp,0,freq90,ns,seqcon[1]);
  offsetlist(pss,ss2_grad.ssamp,0,freq180,ns,seqcon[1]);
  shapelist90 = shapelist(p1_rf.pulseName,ss_grad.rfDuration,freq90,ns,ss_grad.rfFraction,seqcon[1]);
  shapelist180 = shapelist(p2_rf.pulseName,ss2_grad.rfDuration,freq180,ns,ss2_grad.rfFraction,seqcon[1]);

  /* To ensure proper overlap spin and stimulated echoes ensure that the
     middle of the refocusing RF pulse is the centre of the pulse and that
     echoes are formed in the centre of the acquisition window */
  if (ss2_grad.rfFraction != 0.5)
    abort_message("ERROR %s: Refocusing RF pulse must be symmetric (RF fraction = %.2f)",
      seqfil,ss2_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 + crush_grad.duration + ss2_grad.rfCenterFront;
  tau2 = ss2_grad.rfCenterBack + pe_grad.duration  + crush_grad.duration + ro_grad.timeToEcho; 
  tau3 = ro_grad.timeFromEcho  + pe_grad.duration  + crush_grad.duration + ss2_grad.rfCenterFront;

  espmin  = 2*MAX(MAX(tau1,tau2),tau3);   // Minimum echo spacing
  espmin += 2*GRADIENT_RES; // Ensure that each delay is at least GRADIENT_RES

  te = granularity(te,2*GRADIENT_RES);
  if (minesp[0] == 'y') {
    te = espmin;
    putvalue("te",te);
  }
  if (FP_LT(te,espmin)) {
    abort_message("ERROR %s: Echo time too small, minimum is %.3fms\n",seqfil,espmin*1000);
  }
  te1_delay = te/2.0 - tau1;    // Intra-esp delays
  te2_delay = te/2.0 - tau2;
  te3_delay = te/2.0 - tau3;

  /* Now set the TE processing array accordingly */
  putCmd("TE = 0"); /* Re-initialize TE */
  for (i=0;i<ne;i++) putCmd("TE[%d] = %f",i+1,te*1000*(i+1));

  /* Check nsblock, the number of slices blocked together
     (used for triggering and/or inversion recovery) */
  check_nsblock();

  /* Minimum TR **************************************/
  trmin = ss_grad.rfCenterFront + ne*te + ro_grad.timeFromEcho + pe_grad.duration + te3_delay + 2*GRADIENT_RES;

  /* Increase TR if any options are selected *********/
  if (sat[0] == 'y')  trmin += satTime;
  if (fsat[0] == 'y') trmin += fsatTime;
  if (mt[0] == 'y')   trmin += mtTime;
  if (ticks > 0) trmin += GRADIENT_RES;

  /* Adjust for all slices ***************************/
  trmin *= ns;

  /* Inversion recovery *********************************/
  if (ir[0] == 'y') {
    /* tauti is the additional time beyond IR component to be included in ti */
    /* satTime, fsatTime and mtTime all included as those modules will be after IR */
    tauti = satTime + fsatTime + mtTime + GRADIENT_RES + ss_grad.rfCenterFront;
    /* calc_irTime checks ti and returns the time of all IR components */
    trmin += calc_irTime(tauti,trmin,mintr[0],tr,&trtype);
  }

  if (mintr[0] == 'y') {
    tr = trmin;
    putvalue("tr",tr);
  }
  if (FP_LT(tr,trmin)) {
    abort_message("ERROR %s: TR too short, minimum TR is %.3fms\n",seqfil,trmin*1000);
  }

  /* Calculate tr delay */
  tr_delay = granularity((tr-trmin)/ns,GRADIENT_RES);

  /* Set pe_steps for profile or full image **********/
  pe_steps = prep_profile(profile[0],nv,&pe_grad,&per_grad);
  F_initval(pe_steps/2.0,vpe_offset);

  /* Shift DDR for pro ************************************/
  roff = -poffset(pro,ro_grad.roamp);

  /* Adjust experiment time for VnmrJ *********************/
  if (ssc<0) {
    if (seqcon[2] == 'c') g_setExpTime(trmean*(ntmean*pe_steps*arraydim - ssc*arraydim));
    else g_setExpTime(trmean*(ntmean*pe_steps*arraydim - ssc*pe_steps*arraydim));
  }
  else g_setExpTime(trmean*ntmean*pe_steps*arraydim + tr*ssc);

  /* Set phase cycle tables */
  if (suppressSTE) {
    if ((int)nt%2 == 1)
      abort_message("STE suppression requires a 2 step phase cycle.  Set nt as a multiple of 2\n");
    settable(t2,4,phref1s);
    settable(t3,4,phref2s);
    settable(t4,4,phrec1s);
    settable(t5,4,phrec2s);
  } else {
    settable(t2,4,phref1);
    settable(t3,4,phref2);
    settable(t4,4,phrec1);
    settable(t5,4,phrec2);
  }

  /* Set crusher table */
  crushtab=malloc((int)ne*sizeof(int));
  neby2=ceil(ne/2.0 - US); // US to handle precision errors
  crush_step=gcrush/neby2;
  for (i=0; i<ne; i++) {
    crush_ind = (1.0-2.0*(i%2))*(neby2-floor(i/2));
    crushtab[i] = (int)(crush_ind);
  }
  settable(t6,(int)ne,crushtab);

  /* PULSE SEQUENCE ***************************************/
  status(A);
  rotate();
  triggerSelect(trigger);       // Select trigger input 1/2/3
  obsoffset(resto);
  delay(GRADIENT_RES);
  initval(fabs(ssc),vssc);      // Compressed steady-state counter
  if (seqcon[2]=='s') assign(zero,vssc); // Zero for standard peloop
  assign(one,vacquire);         // real-time acquire flag
  setacqvar(vacquire);          // Turn on acquire when vacquire is zero

  /* Phase for excitation pulse */
  assign(zero,vphase90);

  /* trigger */
  if (ticks > 0) F_initval((double)nsblock,vtrigblock);
    
  /* Begin phase-encode loop ****************************/
  peloop(seqcon[2],pe_steps,vpe_steps,vpe_ctr);

    if (trtype) delay(ns*tr_delay);   // relaxation delay

    /* 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);
    }

    /* 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);
    }

    msloop(seqcon[1],ns,vms_slices,vms_ctr);

      if (!trtype) delay(tr_delay);   // Relaxation delay

      if (ticks > 0) {
        modn(vms_ctr,vtrigblock,vtest);
        ifzero(vtest);                // if the beginning of an trigger block
          xgate(ticks);
          grad_advance(gpropdelay);
          delay(GRADIENT_RES);
        elsenz(vtest);
          delay(GRADIENT_RES);
        endif(vtest);
      }

      sp1on(); delay(GRADIENT_RES); sp1off(); // Scope trigger

      /* Prepulse options ***********************************/
      if (ir[0] == 'y')   inversion_recovery();
      if (sat[0] == 'y')  satbands();
      if (fsat[0] == 'y') fatsat();
      if (mt[0] == 'y')   mtc();

      /* 90 degree pulse ************************************/         
      obspower(p1_rf.powerCoarse);
      obspwrf(p1_rf.powerFine);
      delay(GRADIENT_RES);
      obl_shapedgradient(ss_grad.name,ss_grad.duration,0,0,ss_grad.amp,NOWAIT);   
      delay(ss_grad.rfDelayFront);
      shapedpulselist(shapelist90,ss_grad.rfDuration,vphase90,rof1,rof2,seqcon[1],vms_ctr);
      delay(ss_grad.rfDelayBack);

      /* 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);
	
      F_initval(ne,vne);
      loop(vne,vne_ctr);

        /* Phase cycle for refocusing pulse and receiver */
        mod4(ct,vphindex);
        mod2(vne_ctr,vneindex);
        ifzero(vneindex);
          getelem(t2,vphindex,vphase180);
          getelem(t4,vphindex,oph);
        elsenz(vneindex);
          getelem(t3,vphindex,vphase180);
          getelem(t5,vphindex,oph);
        endif(vneindex);

        /* Crusher gradient modulation */
        assign(one,vcrush);
        if (crushmod[0] == 'y') {
          assign(zero,vcrush);
          ifzero(vneindex);
            add(vcrush,one,vcrush);
          elsenz(vneindex);
            sub(vcrush,one,vcrush);
          endif(vneindex);
        }
        if (crushmod[0] == 'p') {
          getelem(t6,vne_ctr,vcrush);
          crush_grad.amp=crush_step;
        }

        /* 180 degree pulse *******************************/
        if (crushmod[0] == 'y' || crushmod[0] == 'p')
          var3_shapedgradient(crush_grad.name,crush_grad.duration,0.0,0.0,0.0,0.0,0.0,crush_grad.amp,zero,zero,vcrush,WAIT);
        else
          obl_shapedgradient(crush_grad.name,crush_grad.duration,crush_grad.amp,0,crush_grad.amp,WAIT);
        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);
        if (crushmod[0] == 'y' || crushmod[0] == 'p')
          var3_shapedgradient(crush_grad.name,crush_grad.duration,0.0,0.0,0.0,0.0,0.0,crush_grad.amp,zero,zero,vcrush,WAIT);
        else
          obl_shapedgradient(crush_grad.name,crush_grad.duration,crush_grad.amp,0,crush_grad.amp,WAIT);

        /* Second half-TE period ******************************/
	delay(te2_delay);
	 
        /* Phase-encode gradient ******************************/
        pe_shapedgradient(pe_grad.name,pe_grad.duration,0,0,0,-pe_grad.increment,vpe_mult,WAIT);

        /* Readout gradient ************************************/
        obl_shapedgradient(ro_grad.name,ro_grad.duration,ro_grad.roamp,0,0,NOWAIT);
        delay(ro_grad.atDelayFront-alfa);

        /* Acquire data ****************************************/
        startacq(alfa);
        acquire(np,1.0/sw);
        endacq();

        delay(ro_grad.atDelayBack);

        /* Rewinding phase-encode 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);

      endloop(vne_ctr);

    endmsloop(seqcon[1],vms_ctr);

  endpeloop(seqcon[2],vpe_ctr);

  /* Inter-image delay **********************************/
  sub(ntrt,ct,vtrimage);
  decr(vtrimage);
  ifzero(vtrimage);
    delay(trimage);
  endif(vtrimage);
}