Ejemplo n.º 1
0
void init_generic(GENERIC_GRADIENT_T *grad, char name[], double amp, double time) 
   {
   if ((ix > 1) && !sglarray) return;
   initGeneric(grad);                            /* initialize generic gradient with defaults */
   grad->amp = amp;                              /* assign gradient amplitude */
   grad->duration  = time;                       /* assign gradient duration */
   grad->maxGrad   = gmax;                       /* assign maximum allowed gradient */               
   strcpy(grad->name,name);                      /* assign waveform name */
   }
Ejemplo n.º 2
0
void trapezoid(GENERIC_GRADIENT_T *grad, char name[], double amp, double time, double moment, int write_flag)
   {
   
   /* check is input values for moment, amplitude, time are set */
   if ((amp == 0) && (time == 0) && (moment == 0)) {
      sgl_abort_message("ERROR gradient %s: All input values to <trapezoid> function are zero",name);
      return;
   }

   initGeneric(grad);                            /* initialize generic gradient with defaults */

   grad->amp       = amp;                        /* assign amplitude */
   grad->duration  = time;                       /* assign duration */
   grad->m0        = moment;                     /* assign moment0 */
   grad->maxGrad   = gmax;                       /* assign maximum allowed gradient */               
   grad->writeToDisk = write_flag;               /* set writeToDisk flag */
   strcpy(grad->name,name);                      /* assign waveform name */

   /* check amplitude */
   if (amp > glim*gmax) {
      sgl_abort_message("ERROR gradient %s: amp too large (%f), reduced to glim*gmax (%f)",
                    name, amp, glim*gmax);
   }
      
   /* evaluate imputs and set correct calcFlag */   
   if ((amp != 0) && (time != 0) && (moment == 0)) {
     grad->calcFlag = MOMENT_FROM_DURATION_AMPLITUDE;
   }
   else if ((amp == 0) && (time != 0) && (moment != 0)) {
     grad->calcFlag = AMPLITUDE_FROM_MOMENT_DURATION;
   }
   else if ((amp != 0) && (time == 0) && (moment != 0)) {
     grad->calcFlag = DURATION_FROM_MOMENT_AMPLITUDE;
   }

   calcGeneric(grad);
   }
Ejemplo n.º 3
0
void calc_readout_rampsamp(READOUT_GRADIENT_T *grad, double *dwell, double *minskip, int *npr) {
  double this_gro, skip, skip_m0, dwint, dw, dwflat;
  double ramp_t, ramp_m0, flat_t, flat_m0, dwell_sum, rt;
  int    npro, np_ramp, np_flat;
  int    pt, pt2;
  GENERIC_GRADIENT_T gg;
  
  /* Calculate gradient amplitude based on FOV and sw */
  this_gro       = sw/grad->gamma/lro;
  grad->amp      = this_gro;

  /* Nominal dwell time is 1/sw */
  dw    = granularity(1/sw,1/epi_grad.ddrsr);
  dwflat = dw;  /* we may later end up with different dw on flat part */
  dwint = dw*grad->amp;   /* Gradient Integral per point */
  npro  = (int) np/2;

  /* Calculate the area that is skipped for phase encoding blip */
  skip    = *minskip;
  if (skip == 0)
    skip = dw + getval("aqtm")-at;                /* Need at least a dwell time at the end */

  skip_m0 = skip*(skip*grad->slewRate)/2;         /* Area of that skipped part */

  /* Calculate the ramp time */
  grad->tramp     = granularity(grad->amp/grad->slewRate,grad->resolution);
  grad->slewRate  = grad->amp/grad->tramp;

  ramp_m0 = grad->tramp*grad->amp/2;
  np_ramp = (int) ((ramp_m0 - skip_m0)/dwint);
  
  /* Check that we even need points on the flat part */
  if (np_ramp >= npro/2) {
    np_ramp = npro/2 - 1;  /* Center two points considered "flat part" */
    
    /* We may not need to go all the way to full gradient
       in order to fit all points on ramp; adjust amplitude */
    ramp_m0 = np_ramp*dwint + skip_m0;
    grad->tramp = granularity(sqrt(2*ramp_m0/grad->slewRate),grad->resolution);
    grad->amp   = grad->tramp * grad->slewRate;

    /* recalculate ramp area and np_ramp */
    ramp_m0 = grad->tramp*grad->amp/2;
    
    /* Now adjust the dwell time necessary on flat part with this amplitude */
    dwflat = granularity(dwint/grad->amp,1/epi_grad.ddrsr);
  }

  np_flat = npro - 2*np_ramp;

  /* How long must the flat part be? */
  grad->duration = granularity((np_flat-1)*dwflat,grad->resolution); 

  /* Due to rounding of gradient duration, 
     we may be able to fit more points on flat part */
  while (grad->duration - (np_flat-1)*dwflat >= 2*dwflat) {
    np_flat += 2;
    np_ramp -= 1;
  }

  /* Now add the ramp times to the total duration */
  grad->duration += 2*grad->tramp; 
  
  /* Use a generic to calculate the actual shape, ie fill in dataPoints */
  initGeneric(&gg);
  gg.amp         = grad->amp;
  gg.duration    = grad->duration;
  gg.tramp       = grad->tramp;
  gg.slewRate    = grad->slewRate;
  gg.calcFlag    = MOMENT_FROM_DURATION_AMPLITUDE_RAMP;
  gg.writeToDisk = FALSE;

  calcGeneric(&gg);

  if (gg.error != ERR_NO_ERROR) {
    printf("Temporary generic gradient: \n");
    displayGeneric(&gg);
    abort_message("Problem calculating RO gradient with ramp sampling");
  }

  grad->m0         = gg.m0;
  grad->m1         = gg.m1;
  grad->m0ref      = grad->m0/2;
  grad->numPoints  = gg.numPoints;
  free(grad->dataPoints); // release original array
  grad->dataPoints = gg.dataPoints;

  /* Recalculate the skipped part with new gradient integral */
  skip_m0 = (grad->m0 - dwint*(np/2-1))/2;
  skip = sqrt(2*skip_m0/grad->slewRate);

  /* Skip rampsampling if gradient is longer than necessary */
  if ((grad->m0-ramp_m0*2) > npro*dwint) {
    warn_message("The gradient is too long, no ramp sampling");
    for (pt = 0; pt < npro; pt++) {
      dwell[pt]  = dwflat;
    }
    *minskip = grad->tramp;
    return;
  }

  /* Calculate where we start acquisition on the ramp */
  /* Do we have extra integral on flat part? */
  flat_m0 = (grad->m0 - 2*ramp_m0) - ((np_flat-1)*dwflat*grad->amp);
  
  /* if yes, then what is the duration of this? */
  if (flat_m0 > 0)
    flat_t = (grad->duration - 2*grad->tramp) / ((np_flat - 1)*dwflat);
  else
    flat_t = 0;

  /* Double-check that gradient is long enough */
  if (flat_m0 < -1e-9)
    abort_message("Gradient integral too small %f vs %f (%f) G/cm*us", 
                   (grad->m0-2*ramp_m0)*1e6,(np_flat-1)*dwint*1e6,flat_m0*1e9);

  /* If extra integral > 2*dwint, we could move a point from each ramp up to the flat */
  if (flat_m0 > 2*dwint)
    warn_message("Gradient flat part longer than necessary with ramp sampling, check gradient calculation\n");


  /**************************************************************************/
  /* Calculate dwell times */
  /**************************************************************************/
  dwell_sum = 0;
  /* Start at top of ramp and walk down ramp */
  pt = np_ramp - 1;
  rt = grad->tramp;  

  /* Top point on ramp first, it may use a bit of time from the flat part */
  if (flat_m0 > 0) {
    ramp_m0 -= (dwint - flat_m0/2);  /* area at ramp at previous point */
    flat_t = (grad->duration - 2*grad->tramp) - ((np_flat - 1)*dwflat); /* extra duration at top */
    flat_t /= 2;  /* divide evenly between both ramps */
  }
  else {
    ramp_m0 -= dwint;  /* area at ramp at previous point */
    flat_t = 0;
  }
  ramp_t    = sqrt(2*ramp_m0/grad->slewRate); /* time at ramp at previous point */
  dwell[pt] = granularity(flat_t + (rt-ramp_t), 1/epi_grad.ddrsr);
  dwell_sum += dwell[pt];

  ramp_t = rt - (dwell[pt] - flat_t); /* correct for rounding of dwell */
  /* Do all the rest of the points on the ramp */
  for(pt = np_ramp-2; pt >= 0; pt--) {  
    rt = ramp_t;       /* remember current time */
    ramp_m0 -= dwint;  /* total area of ramp at previous point */
    if (ramp_m0 <= 0) {
      if (fabs(ramp_m0) > dwint*0.01) abort_message("problem: ramp_m0 negative %f\n",ramp_m0*1000);
      ramp_t = 0;
    }
    else ramp_t  = sqrt(2*ramp_m0/grad->slewRate);  /* time at previous point */
    dwell[pt]  = granularity(rt-ramp_t,1/epi_grad.ddrsr);
    dwell_sum += dwell[pt];

    ramp_t = rt - dwell[pt];
  }       

  skip = ramp_t;
  dwell_sum += skip;

  for (pt = np_ramp; pt < np_ramp+np_flat-1; pt++) {  /* Flat part */
    dwell[pt]  = dwflat;
    dwell_sum += dwflat;
  }

  pt2 = np_ramp-1;
  for (pt = np_ramp+np_flat-1; pt < np_ramp*2 + np_flat - 1; pt++) {
    dwell[pt] = dwell[pt2--];
    dwell_sum += dwell[pt];
  }
  /* Very last point, just set dwell = 1/sw */
  pt = np_ramp*2 + np_flat - 1;
  dwell[pt] = dw;
  dwell_sum += skip;
  
  if (fabs(dwell_sum - grad->duration) > 12.5e-9)
    warn_message("Mismatch in sum of dwells (%.3fus) vs. gradient duration (%.3fus)",
                 dwell_sum*1e6,grad->duration*1e6);


  /* Return values */
  *minskip = skip;
  *npr     = np_ramp;

  if (sgldisplay) {    
    printf("============== DEBUG DWELL  (%d, %d, %d) ===============\n",np_ramp,np_flat,np_ramp);
    dwell_sum = skip;
    for (pt = 0; pt < npro-1; pt++) {
      printf("[%3d] %3.6f\t%3.3f\t%3.6f\n",pt+1,dwell_sum*1e6,dwell[pt]*1e6,(dwell[pt]+dwell_sum)*1e6);
      dwell_sum += dwell[pt];  
    }
    printf("[%3d] %3.6f\t%3.3f\t%3.6f\n",(pt+1),dwell_sum*1e6,0.0,dwell_sum*1e6);pt++;
    printf("[%3d] %3.6f\t%3.3f\t%3.6f\n",pt+1,dwell_sum*1e6,skip*1e6,(skip+dwell_sum)*1e6);
    dwell_sum += skip;

    printf("Did we get a full gradient's worth? %.6f, %.6f\n",grad->duration*1e6,dwell_sum*1e6);
    printf("=======================================================\n");
  }
  
}