Exemple #1
0
void calc_generic(GENERIC_GRADIENT_T *grad, int write_flag, char VJparam_g[], char VJparam_t[])
   {
   double gradamp;

   if ((ix > 1) && !sglarray) return;
   grad->writeToDisk = write_flag;        /* assign writeToDisk flag */
   strcpy(grad->param1,VJparam_g);        /* Assign VNMRJ paramter 1 */
   strcpy(grad->param2,VJparam_t);        /* Assign VNMRJ paramter 2 */

   if (grad->amp > grad->maxGrad) {
     sgl_abort_message("ERROR gradient %s: Crusher amplitude (%.2f) exceeds maximum (%.2f)",
       grad->name,grad->amp,grad->maxGrad);
   }


   if (grad->duration == 0) {
     if (strcmp(grad->param2, ""))  /* The name of the duration is supplied */
       sgl_abort_message("ERROR gradient %s: Duration (%s) is zero",grad->name,grad->param2);
     else
       sgl_abort_message("ERROR gradient %s: Duration is zero",grad->name);
     return;
   }
   
   gradamp = grad->amp;
   if (grad->amp == 0) {
     /* temporarily set it to a non-zero value in order to calculate a shape */
     grad->amp = 1.0/32767.0*gmax;
   }
   
   
   calcGeneric(grad);                     /* calculate and create generic gradient */

   /* reset gradient amplitude */
   if (gradamp == 0) {
     grad->amp = 0;
     grad->m0  = 0;
   }

   if (strcmp(grad->param1, ""))
       putvalue(grad->param1, grad->amp);
   if (strcmp(grad->param2, ""))
       putvalue(grad->param2, grad->duration);
   }
Exemple #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);
   }
Exemple #3
0
/***********************************************************************
*  Function Name: calc_sim_gradient
*  Example:       calc_sim_gradient (GENERIC_GRADIENT_T  *grad0, 
*				    GENERIC_GRADIENT_T  *grad1,
*                                   GENERIC_GRADIENT_T  *grad2, 
*                                   double min_tpe, 
*                                   int write_flag)
*  Purpose:    Blocks up to three gradient
*  Input
*     Formal:  *grad0     - pointer to generic structure
*              *grad0     - pointer to generic structure
*              *grad0     - pointer to generic structure  
*              min_tpe    - minimum duration
*              write_flag - write to disk flag 
*     Private: none
*     Public:  
*  Output
*     Return:  double - duration of blocked greadients
*     Formal:  none
*     Private: none
*     Public:  none
*  Notes:      ONLY works for trapezoidal gradients
***********************************************************************/
double calc_sim_gradient(GENERIC_GRADIENT_T  *grad0, GENERIC_GRADIENT_T  *grad1,
                         GENERIC_GRADIENT_T  *grad2, double min_tpe, int write_flag)
{ 
   int    i;                                /* loop counter */
   int    typesum = 0;                      /* check for gradient type */
   double time    = 0.0;                    /* longest duration of gradient */
   double tramp   = 0.0;                    /* longest ramp time */
   double duration0, duration1, duration2;  /* gradient durations */
   double tramp0, tramp1,tramp2;            /* gradient ramp time */
   double amp0, amp1, amp2;
   GENERIC_GRADIENT_T* grad[3];  /* internal array of structs to allow indexing */

   if ((ix > 1) && !sglarray) return(grad0->duration);
   /* assign input structs to internal array to allow use in for loop ***/
   grad[0] = grad0;
   grad[1] = grad1;
   grad[2] = grad2;

   /* check for  shape -> all gradients need to be trapezoidal */
   for (i=0; i<3; i++) {
     if (grad[i]->shape != TRAPEZOID) {
       displayGeneric(grad[i]);
       sgl_abort_message("ERROR calc_sim_gradient: Gradient %d ('%s') must be trapezoidal",i,grad[i]->name);   
     }
   }
   
   /* find longest gradient duration */
   duration0 = grad[0]->duration - grad[0]->tramp; /* duration of a square gradient with same integral & amplitude */
   duration1 = grad[1]->duration - grad[1]->tramp;
   duration2 = grad[2]->duration - grad[2]->tramp;
  
   time = MAX(MAX(duration0,duration1),duration2);  /* should already be granulated */

	if( trampfixed > 0.0 ) {

		tramp = grad[0]->tramp;

	} else {
		amp0   = (fabs(grad[0]->m0) + fabs(grad[0]->areaOffset))/time;  /* amplitude of square gradient with same integral and duration "time" */
		amp1   = (fabs(grad[1]->m0) + fabs(grad[1]->areaOffset))/time;
		amp2   = (fabs(grad[2]->m0) + fabs(grad[2]->areaOffset))/time;
  
   		tramp0 = amp0/grad[0]->slewRate; /* ramp time with new amplitude */
   		tramp1 = amp1/grad[1]->slewRate;
   		tramp2 = amp2/grad[2]->slewRate;

   		tramp = MAX(MAX(tramp0,tramp1),tramp2);
   		tramp = granularity(tramp,grad[0]->resolution);

	
	}

   /* But use min_tpe as duration, if it is longer */
   time = MAX(time+tramp,granularity(min_tpe,grad[0]->resolution));
    
   /* assign new duration, ramp time, calc flag, and write flag to all 3 */
   grad[0]->duration = grad[1]->duration = grad[2]->duration = time;
   grad[0]->tramp    = grad[1]->tramp    = grad[2]->tramp    = tramp;
   grad[0]->calcFlag = grad[1]->calcFlag = grad[2]->calcFlag = AMPLITUDE_FROM_MOMENT_DURATION_RAMP;

   /* set writeToDisk flag */  
   grad[0]->writeToDisk = grad[1]->writeToDisk = grad[2]->writeToDisk = write_flag;  

   /* Re-calculate gradients */ 
   for (i=0; i<3; i++) {
     switch(grad[i]->type) 
     {
	   case REFOCUS_GRADIENT_TYPE:
         calcRefocus(grad[i]);
         if (strcmp(grad[i]->param1, ""))
           putvalue(grad[i]->param1, grad[i]->amp);
         break;
       case DEPHASE_GRADIENT_TYPE:
         calcDephase(grad[i]);
         if (strcmp(grad[i]->param1, ""))
           putvalue(grad[i]->param1, grad[i]->amp);
         break;
       case PHASE_GRADIENT_TYPE:
         calcPhase(grad[i]);
         if (strcmp(grad[i]->param1, ""))
           putvalue(grad[i]->param1, grad[i]->amp);
         if (strcmp(grad[i]->param2, "")) 
           putvalue(grad[i]->param2, grad[i]->duration);
         break;
       case GENERIC_GRADIENT_TYPE:
         calcGeneric(grad[i]);
         if (strcmp(grad[i]->param1, ""))
           putvalue(grad[i]->param1, grad[i]->amp);
         break;
       default:
         typesum += 1;
     }
   }

   if (typesum >=2) {
     sgl_abort_message("ERROR calc_sim_gradient: 2 or more unspecified gradients as arguments");
   }
   
   /* return longest duration */
   return(time);
   }
Exemple #4
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");
  }
  
}