def rare_standalone( init_gpa=False, # Starts the gpa nScans=1, # NEX larmorFreq=3.08, # MHz, Larmor frequency rfExAmp=0.3, # a.u., rf excitation pulse amplitude rfReAmp=0.3, # a.u., rf refocusing pulse amplitude rfExTime=35, # us, rf excitation pulse time rfReTime=70, # us, rf refocusing pulse time echoSpacing=10, # ms, time between echoes preExTime=0., # ms, Time from preexcitation pulse to inversion pulse inversionTime=0., # ms, Inversion recovery time repetitionTime=200., # ms, TR fov=np.array([140., 150., 180.]), # mm, FOV along readout, phase and slice dfov=np.array([0., 0., 0.]), # mm, displacement of fov center nPoints=np.array([140, 80, 10]), # Number of points along readout, phase and slice etl=10, # Echo train length acqTime=4, # ms, acquisition time axes=np.array([2, 1, 0]), # 0->x, 1->y and 2->z defined as [rd,ph,sl] axesEnable=np.array([1, 1, 1]), # 1-> Enable, 0-> Disable sweepMode=1, # 0->k2k (T2), 1->02k (T1), 2->k20 (T2), 3->Niquist modulated (T2) rdGradTime=5, # ms, readout gradient time rdDephTime=2, # ms, readout dephasing time phGradTime=1, # ms, phase and slice dephasing time rdPreemphasis=1.00, # readout dephasing gradient is multiplied by this factor drfPhase=0, # degrees, phase of the excitation pulse dummyPulses=1, # number of dummy pulses for T1 stabilization shimming=np.array([-70, -90., 10]), # a.u.*1e4, shimming along the X,Y and Z axes parFourierFraction=1.0 # fraction of acquired k-space along phase direction ): freqCal = 1 # rawData fields rawData = {} # Conversion of variables to non-multiplied units larmorFreq = larmorFreq * 1e6 rfExTime = rfExTime * 1e-6 rfReTime = rfReTime * 1e-6 fov = np.array(fov) * 1e-3 dfov = np.array(dfov) * 1e-3 echoSpacing = echoSpacing * 1e-3 acqTime = acqTime * 1e-3 shimming = shimming * 1e-4 repetitionTime = repetitionTime * 1e-3 preExTime = preExTime * 1e-3 inversionTime = inversionTime * 1e-3 rdGradTime = rdGradTime * 1e-3 rdDephTime = rdDephTime * 1e-3 phGradTime = phGradTime * 1e-3 # Inputs for rawData rawData['seqName'] = 'RareBatches_Standalone' rawData['nScans'] = nScans rawData['larmorFreq'] = larmorFreq # Larmor frequency rawData['rfExAmp'] = rfExAmp # rf excitation pulse amplitude rawData['rfReAmp'] = rfReAmp # rf refocusing pulse amplitude rawData['rfExTime'] = rfExTime # rf excitation pulse time rawData['rfReTime'] = rfReTime # rf refocusing pulse time rawData['echoSpacing'] = echoSpacing # time between echoes rawData['preExTime'] = preExTime rawData['inversionTime'] = inversionTime # Inversion recovery time rawData['repetitionTime'] = repetitionTime # TR rawData['fov'] = fov # FOV along readout, phase and slice rawData['dfov'] = dfov # Displacement of fov center rawData[ 'nPoints'] = nPoints # Number of points along readout, phase and slice rawData['etl'] = etl # Echo train length rawData['acqTime'] = acqTime # Acquisition time rawData[ 'axesOrientation'] = axes # 0->x, 1->y and 2->z defined as [rd,ph,sl] rawData['axesEnable'] = axesEnable # 1-> Enable, 0-> Disable rawData[ 'sweepMode'] = sweepMode # 0->k2k (T2), 1->02k (T1), 2->k20 (T2), 3->Niquist modulated (T2) rawData['rdPreemphasis'] = rdPreemphasis rawData['drfPhase'] = drfPhase rawData['dummyPulses'] = dummyPulses # Dummy pulses for T1 stabilization rawData['parFourierFraction'] = parFourierFraction rawData['rdDephTime'] = rdDephTime rawData['shimming'] = shimming # Miscellaneous larmorFreq = larmorFreq * 1e-6 gradRiseTime = 400e-6 # Estimated gradient rise time gSteps = int(gradRiseTime * 1e6 / 5) * 0 + 1 addRdPoints = 10 # Initial rd points to avoid artifact at the begining of rd randFactor = 0e-3 # Random amplitude to add to the phase gradients if rfReAmp == 0: rfReAmp = rfExAmp if rfReTime == 0: rfReTime = 2 * rfExTime resolution = fov / nPoints rawData['resolution'] = resolution rawData['gradRiseTime'] = gradRiseTime rawData['randFactor'] = randFactor rawData['addRdPoints'] = addRdPoints # Matrix size nRD = nPoints[0] + 2 * addRdPoints nPH = nPoints[1] * axesEnable[1] + (1 - axesEnable[1]) nSL = nPoints[2] * axesEnable[2] + (1 - axesEnable[2]) # ETL if nPH = 1 if etl > nPH: etl = nPH # parAcqLines in case parAcqLines = 0 parAcqLines = int(int(nPoints[2] * parFourierFraction) - nPoints[2] / 2) rawData['partialAcquisition'] = parAcqLines # BW BW = nPoints[0] / acqTime * 1e-6 BWov = BW * hw.oversamplingFactor samplingPeriod = 1 / BWov rawData['bw'] = BW rawData['samplingPeriod'] = samplingPeriod # Readout gradient time if rdGradTime > 0 and rdGradTime < acqTime: rdGradTime = acqTime rawData['rdGradTime'] = rdGradTime # Phase and slice de- and re-phasing time if phGradTime == 0 or phGradTime > echoSpacing / 2 - rfExTime / 2 - rfReTime / 2 - 2 * gradRiseTime: phGradTime = echoSpacing / 2 - rfExTime / 2 - rfReTime / 2 - 2 * gradRiseTime rawData['phGradTime'] = phGradTime # Max gradient amplitude rdGradAmplitude = nPoints[0] / (hw.gammaB * fov[0] * acqTime) * axesEnable[0] phGradAmplitude = nPH / (2 * hw.gammaB * fov[1] * (phGradTime + gradRiseTime)) * axesEnable[1] slGradAmplitude = nSL / (2 * hw.gammaB * fov[2] * (phGradTime + gradRiseTime)) * axesEnable[2] rawData['rdGradAmplitude'] = rdGradAmplitude rawData['phGradAmplitude'] = phGradAmplitude rawData['slGradAmplitude'] = slGradAmplitude # Readout dephasing amplitude rdDephAmplitude = 0.5 * rdGradAmplitude * (gradRiseTime + rdGradTime) / ( gradRiseTime + rdDephTime) rawData['rdDephAmplitude'] = rdDephAmplitude # Phase and slice gradient vector phGradients = np.linspace(-phGradAmplitude, phGradAmplitude, num=nPH, endpoint=False) slGradients = np.linspace(-slGradAmplitude, slGradAmplitude, num=nSL, endpoint=False) # Now fix the number of slices to partailly acquired k-space nSL = (int(nPoints[2] / 2) + parAcqLines) * axesEnable[2] + (1 - axesEnable[2]) # Add random displacemnt to phase encoding lines for ii in range(nPH): if ii < np.ceil(nPH / 2 - nPH / 20) or ii > np.ceil(nPH / 2 + nPH / 20): phGradients[ii] = phGradients[ii] + randFactor * np.random.randn() kPH = hw.gammaB * phGradients * (gradRiseTime + phGradTime) rawData['phGradients'] = phGradients rawData['slGradients'] = slGradients # Set phase vector to given sweep mode ind = mri.getIndex(etl, nPH, sweepMode) rawData['sweepOrder'] = ind phGradients = phGradients[ind] def createSequence(): phIndex = 0 nRepetitions = int(nPH / etl + dummyPulses) scanTime = 20e3 + nRepetitions * repetitionTime rawData['batchTime'] = scanTime * 1e-6 if rdGradTime == 0: # Check if readout gradient is dc or pulsed dc = True else: dc = False # Set shimming mri.iniSequence(expt, 20, shimming) for repeIndex in range(nRepetitions): # Initialize time tEx = 20e3 + repetitionTime * repeIndex + inversionTime + preExTime # First I do a noise measurement. if repeIndex == 0: t0 = tEx - preExTime - inversionTime - 4 * acqTime mri.rxGate(expt, t0, acqTime + 2 * addRdPoints / BW) # Pre-excitation pulse if repeIndex >= dummyPulses and preExTime != 0: t0 = tEx - preExTime - inversionTime - rfExTime / 2 - hw.blkTime mri.rfRecPulse(expt, t0, rfExTime, rfExAmp / 90 * 90, 0) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, preExTime * 0.5, -0.005, gSteps, axes[0], shimming) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, preExTime * 0.5, -0.005, gSteps, axes[1], shimming) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, preExTime * 0.5, -0.005, gSteps, axes[2], shimming) # Inversion pulse if repeIndex >= dummyPulses and inversionTime != 0: t0 = tEx - inversionTime - rfReTime / 2 - hw.blkTime mri.rfRecPulse(expt, t0, rfReTime, rfReAmp / 180 * 180, 0) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, inversionTime * 0.5, 0.005, gSteps, axes[0], shimming) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, inversionTime * 0.5, 0.005, gSteps, axes[1], shimming) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, inversionTime * 0.5, 0.005, gSteps, axes[2], shimming) # DC gradient if desired if (repeIndex == 0 or repeIndex >= dummyPulses) and dc == True: t0 = tEx - 10e3 mri.gradTrap(expt, t0, gradRiseTime, 10e3 + echoSpacing * (etl + 1), rdGradAmplitude, gSteps, axes[0], shimming) # Excitation pulse t0 = tEx - hw.blkTime - rfExTime / 2 mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, drfPhase) # Dephasing readout t0 = tEx + rfExTime / 2 - hw.gradDelay if (repeIndex == 0 or repeIndex >= dummyPulses) and dc == False: mri.gradTrap(expt, t0, gradRiseTime, rdDephTime, rdDephAmplitude * rdPreemphasis, gSteps, axes[0], shimming) # Echo train for echoIndex in range(etl): tEcho = tEx + echoSpacing * (echoIndex + 1) # Refocusing pulse t0 = tEcho - echoSpacing / 2 - rfReTime / 2 - hw.blkTime mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, drfPhase + np.pi / 2) # Dephasing phase and slice gradients if repeIndex >= dummyPulses: # This is to account for dummy pulses t0 = tEcho - echoSpacing / 2 + rfReTime / 2 - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, phGradTime, phGradients[phIndex], gSteps, axes[1], shimming) mri.gradTrap(expt, t0, gradRiseTime, phGradTime, slGradients[slIndex], gSteps, axes[2], shimming) # Readout gradient if (repeIndex == 0 or repeIndex >= dummyPulses ) and dc == False: # This is to account for dummy pulses t0 = tEcho - rdGradTime / 2 - gradRiseTime - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, rdGradTime, rdGradAmplitude, gSteps, axes[0], shimming) # Rx gate if (repeIndex == 0 or repeIndex >= dummyPulses): t0 = tEcho - acqTime / 2 - addRdPoints / BW mri.rxGate(expt, t0, acqTime + 2 * addRdPoints / BW) # Rephasing phase and slice gradients t0 = tEcho + acqTime / 2 + addRdPoints / BW - hw.gradDelay if (echoIndex < etl - 1 and repeIndex >= dummyPulses): mri.gradTrap(expt, t0, gradRiseTime, phGradTime, -phGradients[phIndex], gSteps, axes[1], shimming) mri.gradTrap(expt, t0, gradRiseTime, phGradTime, -slGradients[slIndex], gSteps, axes[2], shimming) elif (echoIndex == etl - 1 and repeIndex >= dummyPulses): mri.gradTrap(expt, t0, gradRiseTime, phGradTime, +phGradients[phIndex], gSteps, axes[1], shimming) mri.gradTrap(expt, t0, gradRiseTime, phGradTime, +slGradients[slIndex], gSteps, axes[2], shimming) # Update the phase and slice gradient if repeIndex >= dummyPulses: phIndex += 1 if repeIndex == nRepetitions - 1: mri.endSequence(expt, scanTime) # Changing time parameters to us rfExTime = rfExTime * 1e6 rfReTime = rfReTime * 1e6 echoSpacing = echoSpacing * 1e6 repetitionTime = repetitionTime * 1e6 gradRiseTime = gradRiseTime * 1e6 phGradTime = phGradTime * 1e6 rdGradTime = rdGradTime * 1e6 rdDephTime = rdDephTime * 1e6 inversionTime = inversionTime * 1e6 preExTime = preExTime * 1e6 # Calibrate frequency if freqCal == 1: mri.freqCalibration(rawData, bw=0.05) mri.freqCalibration(rawData, bw=0.005) larmorFreq = rawData['larmorFreq'] * 1e-6 drfPhase = rawData['drfPhase'] # Run the experiment dataFull = [] dummyData = [] overData = [] noise = [] for slIndex in range(nSL): expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] BW = 1 / samplingPeriod / hw.oversamplingFactor acqTime = nPoints[0] / BW # us createSequence() for ii in range(nScans): print("Scan %s, slice %s ..." % (ii + 1, slIndex + 1)) rxd, msgs = expt.run() rxd['rx0'] = rxd[ 'rx0'] * 13.788 # Here I normalize to get the result in mV # Get noise data noise = np.concatenate( (noise, rxd['rx0'][0:nRD * hw.oversamplingFactor]), axis=0) rxd['rx0'] = rxd['rx0'][nRD * hw.oversamplingFactor::] # Get data if dummyPulses > 0: dummyData = np.concatenate( (dummyData, rxd['rx0'][0:nRD * etl * hw.oversamplingFactor]), axis=0) overData = np.concatenate( (overData, rxd['rx0'][nRD * etl * hw.oversamplingFactor::]), axis=0) else: overData = np.concatenate((overData, rxd['rx0']), axis=0) expt.__del__() print('Scans done!') rawData['noiseData'] = noise rawData['overData'] = overData # Fix the echo position using oversampled data if dummyPulses > 0: dummyData = np.reshape( dummyData, (nSL * nScans, etl, nRD * hw.oversamplingFactor)) dummyData = np.average(dummyData, axis=0) rawData['dummyData'] = dummyData overData = np.reshape( overData, (nScans * nSL, int(nPH / etl), etl, nRD * hw.oversamplingFactor)) for ii in range(nScans * nSL): overData[ii, :, :, :] = mri.fixEchoPosition( dummyData, overData[ii, :, :, :]) overData = np.squeeze( np.reshape(overData, (1, nRD * hw.oversamplingFactor * nPH * nSL * nScans))) # Generate dataFull dataFull = sig.decimate(overData, hw.oversamplingFactor, ftype='fir', zero_phase=True) # Get index for krd = 0 # Average data dataProv = np.reshape(dataFull, (nSL, nScans, nRD * nPH)) dataProv = np.average(dataProv, axis=1) # Reorganize the data acording to sweep mode dataProv = np.reshape(dataProv, (nSL, nPH, nRD)) dataTemp = dataProv * 0 for ii in range(nPH): dataTemp[:, ind[ii], :] = dataProv[:, ii, :] dataProv = dataTemp # Check where is krd = 0 dataProv = dataProv[int(nPoints[2] / 2), int(nPH / 2), :] indkrd0 = np.argmax(np.abs(dataProv)) if indkrd0 < nRD / 2 - addRdPoints or indkrd0 > nRD / 2 + addRdPoints: indkrd0 = int(nRD / 2) # indkrd0 = int(nRD/2) # Get individual images dataFull = np.reshape(dataFull, (nSL, nScans, nPH, nRD)) dataFull = dataFull[:, :, :, indkrd0 - int(nPoints[0] / 2):indkrd0 + int(nPoints[0] / 2)] dataTemp = dataFull * 0 for ii in range(nPH): dataTemp[:, :, ind[ii], :] = dataFull[:, :, ii, :] dataFull = dataTemp imgFull = dataFull * 0 for ii in range(nScans): imgFull[:, ii, :, :] = np.fft.ifftshift( np.fft.ifftn(np.fft.ifftshift(np.squeeze(dataFull[:, ii, :, :])))) rawData['dataFull'] = dataFull rawData['imgFull'] = imgFull # Average data data = np.average(dataFull, axis=1) # Do zero padding dataTemp = np.zeros((nPoints[2], nPoints[1], nPoints[0])) dataTemp = dataTemp + 1j * dataTemp dataTemp[0:nSL, :, :] = data data = np.reshape(dataTemp, (1, nPoints[0] * nPoints[1] * nPoints[2])) # Fix the position of the sample according to dfov kMax = np.array(nPoints) / (2 * np.array(fov)) * np.array(axesEnable) kRD = np.linspace(-kMax[0], kMax[0], num=nPoints[0], endpoint=False) # kPH = np.linspace(-kMax[1],kMax[1],num=nPoints[1],endpoint=False) kSL = np.linspace(-kMax[2], kMax[2], num=nPoints[2], endpoint=False) kPH = kPH[::-1] kPH, kSL, kRD = np.meshgrid(kPH, kSL, kRD) kRD = np.reshape(kRD, (1, nPoints[0] * nPoints[1] * nPoints[2])) kPH = np.reshape(kPH, (1, nPoints[0] * nPoints[1] * nPoints[2])) kSL = np.reshape(kSL, (1, nPoints[0] * nPoints[1] * nPoints[2])) dPhase = np.exp(-2 * np.pi * 1j * (dfov[0] * kRD + dfov[1] * kPH + dfov[2] * kSL)) data = np.reshape(data * dPhase, (nPoints[2], nPoints[1], nPoints[0])) rawData['kSpace3D'] = data img = np.fft.ifftshift(np.fft.ifftn(np.fft.ifftshift(data))) rawData['image3D'] = img data = np.reshape(data, (1, nPoints[0] * nPoints[1] * nPoints[2])) # Create sampled data kRD = np.reshape(kRD, (nPoints[0] * nPoints[1] * nPoints[2], 1)) kPH = np.reshape(kPH, (nPoints[0] * nPoints[1] * nPoints[2], 1)) kSL = np.reshape(kSL, (nPoints[0] * nPoints[1] * nPoints[2], 1)) data = np.reshape(data, (nPoints[0] * nPoints[1] * nPoints[2], 1)) rawData['kMax'] = kMax rawData['sampled'] = np.concatenate((kRD, kPH, kSL, data), axis=1) data = np.reshape(data, (nPoints[2], nPoints[1], nPoints[0])) # Save data mri.saveRawData(rawData) # Plot data for 1D case if (nPH == 1 and nSL == 1): # Plot k-space plt.figure(3) dataPlot = data[0, 0, :] plt.subplot(1, 2, 1) if axesEnable[0] == 0: tVector = np.linspace( -acqTime / 2, acqTime / 2, num=nPoints[0], endpoint=False) * 1e-3 sMax = np.max(np.abs(dataPlot)) indMax = np.argmax(np.abs(dataPlot)) timeMax = tVector[indMax] sMax3 = sMax / 3 dataPlot3 = np.abs(np.abs(dataPlot) - sMax3) indMin = np.argmin(dataPlot3) timeMin = tVector[indMin] T2 = np.abs(timeMax - timeMin) plt.plot(tVector, np.abs(dataPlot)) plt.plot(tVector, np.real(dataPlot)) plt.plot(tVector, np.imag(dataPlot)) plt.xlabel('t (ms)') plt.ylabel('Signal (mV)') print("T2 = %s us" % (T2)) plt.title(rawData['fileName']) plt.legend(['Abs', 'Real', 'Imag']) else: plt.plot(kRD[:, 0], np.abs(dataPlot)) plt.yscale('log') plt.xlabel('krd (mm^-1)') plt.ylabel('Signal (mV)') echoTime = np.argmax(np.abs(dataPlot)) echoTime = kRD[echoTime, 0] print("Echo position = %s mm^{-1}" % round(echoTime, 1)) plt.title(rawData['fileName']) # Plot image plt.subplot(122) img = img[0, 0, :] if axesEnable[0] == 0: xAxis = np.linspace( -BW / 2, BW / 2, num=nPoints[0], endpoint=False) * 1e3 plt.plot(xAxis, np.abs(img), '.') plt.xlabel('Frequency (kHz)') plt.ylabel('Density (a.u.)') print("Smax = %s mV" % (np.max(np.abs(img)))) plt.title(rawData['fileName']) else: xAxis = np.linspace(-fov[0] / 2 * 1e2, fov[0] / 2 * 1e2, num=nPoints[0], endpoint=False) plt.plot(xAxis, np.abs(img)) plt.xlabel('Position RD (cm)') plt.ylabel('Density (a.u.)') plt.title(rawData['fileName']) else: # Plot k-space plt.figure(3) dataPlot = data[round(nSL / 2), :, :] plt.subplot(131) plt.imshow(np.log(np.abs(dataPlot)), cmap='gray') plt.axis('off') # Plot image if sweepMode == 3: imgPlot = img[round(nSL / 2), round(nPH / 4):round(3 * nPH / 4), :] else: imgPlot = img[round(nSL / 2), :, :] plt.subplot(132) plt.imshow(np.abs(imgPlot), cmap='gray') plt.axis('off') plt.title(rawData['fileName']) plt.subplot(133) plt.imshow(np.angle(imgPlot), cmap='gray') plt.axis('off') # plot full image if nSL > 1: plt.figure(4) img2d = np.zeros((nPoints[1], nPoints[0] * nPoints[2])) img2d = img2d + 1j * img2d for ii in range(nPoints[2]): img2d[:, ii * nPoints[0]:(ii + 1) * nPoints[0]] = img[ii, :, :] plt.imshow(np.abs(img2d), cmap='gray') plt.axis('off') plt.title(rawData['fileName']) plt.show()
def rabiflopStandalone( init_gpa=False, larmorFreq=3.07953, rfExAmp=0.4, rfExPhase=0, rfExTimeIni=6, rfExTimeEnd=60, nExTime=20, nReadout=100, tAdq=4 * 1e3, tEcho=40 * 1e3, tRepetition=500 * 1e3, plotSeq=0, pulseShape='Rec', # 'Rec' for square pulse shape, 'Sinc' for sinc pulse shape method='Time', # 'Amp' -> rfReAmp=2*rfExAmp, 'Time' -> rfReTime=2*rfReTime shimming=[-70, -90, 10]): # Miscellaneous deadTime = 400 # us, time between excitation and first acquisition shimming = np.array(shimming) * 1e-4 # Inputs for rawData rawData = {} rawData['seqName'] = 'RabiFlops' rawData['larmorFreq'] = larmorFreq # Larmor frequency rawData['rfExAmp'] = rfExAmp # rf excitation pulse amplitude rawData['rfExTimeIni'] = rfExTimeIni # rf excitation pulse time rawData['rfExTimeEnd'] = rfExTimeEnd # rf refocusing pulse time rawData['nExTime'] = nExTime rawData['echoSpacing'] = tEcho # time between echoes rawData['repetitionTime'] = tRepetition # TR rawData['nReadout'] = nReadout rawData['tAdq'] = tAdq rawData['pulseShape'] = pulseShape rawData['shimming'] = shimming rawData['deadTime'] = deadTime * 1e-6 # Excitation times rfExTime = np.linspace(rfExTimeIni, rfExTimeEnd, nExTime, endpoint=True) # Refocusing amplitude and time if method == 'Time': rfReAmp = rfExAmp rfReTime = 2 * rfExTime elif method == 'Amp': rfReAmp = 2 * rfExAmp rfReTime = rfExTime rawData['rfReAmp'] = rfReAmp rawData['rfReTime'] = rfReTime # SPECIFIC FUNCTIONS #################################################################################### def plotData(data, rfExTime, tAdqReal): plt.figure(1) colors = cm.rainbow(np.linspace(0, 0.8, len(rfExTime))) for indexExTime in range(nExTime): tPlot = np.linspace( -tAdqReal / 2, tAdqReal / 2, nReadout, endpoint='True') * 1e-3 leg = 'Time = ' + str(np.round(rfExTime[indexExTime])) + 'us' plt.plot(tPlot[5:], np.abs(data[indexExTime, 5:]), label=leg, color=colors[indexExTime]) # plt.plot(tPlot[5:], np.real(data[indexExTime, 5:])) # plt.plot(tPlot[5:], np.imag(data[indexExTime, 5:])) plt.xlabel('t(ms)') plt.ylabel('A(mV)') plt.legend() def getRabiFlopData(data, rfExTime, tAdqReal): for indexExTime in range(nExTime): if indexExTime == 0: maxEchoes = np.max(np.abs(data[indexExTime, 5:])) else: maxEchoes = np.append(maxEchoes, np.max(np.abs(data[indexExTime, 5:]))) rabiFlopData = np.transpose(np.array([rfExTime, maxEchoes])) return rabiFlopData def plotRabiFlop(rabiFlopData, name): plt.figure(2) plt.plot(rabiFlopData[:, 0], rabiFlopData[:, 1]) plt.xlabel('t(us)') plt.ylabel('A(mV)') titleRF = 'RF Amp = ' + str(np.real(rfExAmp)) + '; ' + name plt.title(titleRF) return rabiFlopData # SEQUENCE ############################################################################################ def createSequence(): # Set shimming mri.iniSequence(expt, 20, shimming) # Initialize time tEx = 20e3 # Excitation pulse t0 = tEx - hw.blkTime - rfExTime[indexExTime] / 2 if pulseShape == 'Rec': mri.rfRecPulse(expt, t0, rfExTime[indexExTime], rfExAmp, rfExPhase * np.pi / 180) elif pulseShape == 'Sinc': mri.rfSincPulse(expt, t0, rfExTime[indexExTime], 7, rfExAmp, rfExPhase * np.pi / 180) # First acquisition t0 = tEx + rfExTime[indexExTime] / 2 + deadTime mri.rxGate(expt, t0, tAcq) # Refocusing pulse t0 = tEx + tEcho / 2 - rfReTime[indexExTime] / 2 - hw.blkTime if pulseShape == 'Rec': mri.rfRecPulse(expt, t0, rfReTime[indexExTime], rfReAmp, np.pi / 2) elif pulseShape == 'Sinc': mri.rfSincPulse(expt, t0, rfReTime[indexExTime], 7, rfReAmp, np.pi / 2) # Second acquisition t0 = tEx + tEcho - tAcq / 2 mri.rxGate(expt, t0, tAcq) # End sequence mri.endSequence(expt, tRepetition) # INIT EXPERIMENT dataAll = [] for indexExTime in range(nExTime): BW = nReadout / tAdq BWov = BW * hw.oversamplingFactor samplingPeriod = 1 / BWov expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] BW = 1 / samplingPeriod / hw.oversamplingFactor tAcq = nReadout / BW rawData['bw'] = BW createSequence() if plotSeq == 0: print(indexExTime, '.- Running...') rxd, msgs = expt.run() expt.__del__() print(' End') data = sig.decimate(rxd['rx0'] * 13.788, hw.oversamplingFactor, ftype='fir', zero_phase=True) dataAll = np.concatenate((dataAll, data), axis=0) rawData['dataFull'] = dataAll elif plotSeq == 1: expt.plot_sequence() plt.show() expt.__del__() if plotSeq == 1: expt.plot_sequence() plt.show() expt.__del__() elif plotSeq == 0: data = np.reshape(dataAll, (nExTime, 2, nReadout)) dataFID = np.squeeze(data[:, 0, :]) dataEcho = np.squeeze(data[:, 1, :]) plotData(dataEcho, rfExTime, tAcq) rabiFlopData = getRabiFlopData(dataEcho, rfExTime, tAcq) rawData['rabiFlopData'] = rabiFlopData mri.saveRawData(rawData) plotRabiFlop(rabiFlopData, rawData['fileName']) plt.show()
def fasttrStandalone( init_gpa= False, larmorFreq = 3.07968, # MHz rfExAmp = 0.3, rfReAmp = 0.6, rfExTime = 30, # us rfReTime = 60, # us acqTime = 4, # ms echoTime = 20, # ms repetitionTime =0.8, # s nRepetitions = 2, # number of samples nRD=50, plotSeq =0, shimming=[-70, -90, 10]): shimming = np.array(shimming)*1e-4 if rfReTime is None: rfReTime = 2*rfExTime rfExTime = rfExTime*1e-6 rfReTime = rfReTime*1e-6 acqTime = acqTime*1e-3 echoTime = echoTime*1e-3 rawData = {} rawData['seqName'] = 'fastTR' rawData['larmorFreq'] = larmorFreq*1e6 rawData['rfExAmp'] = rfExAmp rawData['rfReAmp'] = rfReAmp rawData['rfExTime'] = rfExTime rawData['rfRetime'] = rfReTime rawData['repetitionTime'] = repetitionTime rawData['nRepetitions'] = nRepetitions rawData['acqTime'] = acqTime rawData['nRD'] = nRD rawData['echoTime'] = echoTime # Miscellaneous gradRiseTime = 200 # us crusherTime = 1000 # us gSteps = int(gradRiseTime/5) axes = np.array([0, 1, 2]) rawData['gradRiseTime'] = gradRiseTime rawData['gSteps'] = gSteps # Bandwidth and sampling rate bw = nRD/acqTime*1e-6 # MHz bwov = bw*hw.oversamplingFactor samplingPeriod = 1/bwov def createSequence(): # Set shimming mri.iniSequence(expt, 20, shimming) for repeIndex in range(nRepetitions): # Initialize time tEx = 20e3+repetitionTime*repeIndex # Excitation pulse t0 = tEx-hw.blkTime-rfExTime/2 mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, 0) # # Rx gating # t0 = tEx+rfExTime/2+hw.deadTime # mri.rxGate(expt, t0, acqTime) # Crusher gradient t0 = tEx+echoTime/2-crusherTime/2-gradRiseTime-hw.gradDelay-43 mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[0], shimming) mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[1], shimming) mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[2], shimming) # Refocusing pulse t0 = tEx+echoTime/2-rfReTime/2-hw.blkTime mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, np.pi/2) # Rx gating t0 = tEx+echoTime-acqTime/2 mri.rxGate(expt, t0, acqTime) # End sequence mri.endSequence(expt, scanTime) # Time variables in us rfExTime *= 1e6 rfReTime *= 1e6 repetitionTime *= 1e6 echoTime *= 1e6 scanTime = nRepetitions*repetitionTime # us expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] # us bw = 1/samplingPeriod/hw.oversamplingFactor # MHz acqTime = nRD/bw # us rawData['samplingPeriod'] = samplingPeriod*1e-6 rawData['bw'] = bw*1e6 createSequence() # Representar Secuencia o tomar los datos. data = [] nn = 1 if plotSeq==1: expt.plot_sequence() plt.show() expt.__del__() elif plotSeq==0: print('Running...') for repe in range(nn): rxd, msgs = expt.run() data = np.concatenate((data, rxd['rx0']*13.788), axis=0) if nn>1: time.sleep(20) expt.__del__() print('Ready!') data = sig.decimate(data, hw.oversamplingFactor, ftype='fir', zero_phase=True) data = np.reshape(data, (nn, nRD*2)) data = np.average(data, axis=0) rawData['fullData'] = data dataIndiv = np.reshape(np.abs(data), (nRepetitions, nRD)) print('End') # Save data mri.saveRawData(rawData) # Plots plt.figure(1) plt.plot(dataIndiv[0, :]) plt.plot(dataIndiv[1, :]) plt.xlabel('Time (a.u.)') plt.ylabel('Signal (mV)') plt.legend('First echo', 'Second echo') plt.title(rawData['fileName']) ratio = dataIndiv[0, int(nRD/2)]/dataIndiv[1, int(nRD/2)] print('Signal ratio = ', ratio) plt.show()
def haste(self, plotSeq): init_gpa = False # Starts the gpa nScans = self.nScans # NEX larmorFreq = self.larmorFreq # MHz, Larmor frequency rfExAmp = self.rfExAmp # a.u., rf excitation pulse amplitude rfReAmp = self.rfReAmp # a.u., rf refocusing pulse amplitude rfExTime = self.rfExTime # us, rf excitation pulse time rfReTime = self.rfReTime # us, rf refocusing pulse time rfEnvelope = self.rfEnvelope # 'Rec' -> square pulse, 'Sinc' -> sinc pulse echoSpacing = self.echoSpacing # ms, time between echoes inversionTime = self.inversionTime # ms, Inversion recovery time repetitionTime = self.repetitionTime # ms, TR fov = np.array(self.fov) # mm, FOV along readout, phase and slice dfov = np.array(self.dfov) # mm, displacement of fov center nPoints = np.array( self.nPoints) # Number of points along readout, phase and slice acqTime = self.acqTime # ms, acquisition time axes = np.array(self.axes) # 0->x, 1->y and 2->z defined as [rd,ph,sl] axesEnable = self.axesEnable # 1-> Enable, 0-> Disable sweepMode = self.sweepMode # 0->k2k (T2), 1->02k (T1), 2->k20 (T2), 3->Niquist modulated (T2) rdGradTime = self.rdGradTime # ms, readout gradient time rdDephTime = self.rdDephTime # ms, readout dephasing time phGradTime = self.phGradTime # ms, phase and slice dephasing time rdPreemphasis = self.rdPreemphasis # readout dephasing gradient is multiplied by this factor ssPreemphasis = self.ssPreemphasis # slice rephasing gradient is multiplied by this factor crusherDelay = self.crusherDelay # delay of the crusher gradient drfPhase = self.drfPhase # degrees, phase of the excitation pulse dummyPulses = self.dummyPulses # number of dummy pulses for T1 stabilization shimming = self.shimming # a.u.*1e4, shimming along the X,Y and Z axes parFourierFraction = self.parFourierFraction # fraction of acquired k-space along phase direction freqCal = True demo = False # rawData fields rawData = {} # Conversion of variables to non-multiplied units larmorFreq = larmorFreq * 1e6 rfExTime = rfExTime * 1e-6 rfReTime = rfReTime * 1e-6 fov = np.array(fov) * 1e-3 dfov = np.array(dfov) * 1e-3 echoSpacing = echoSpacing * 1e-3 acqTime = acqTime * 1e-3 shimming = np.array(shimming) * 1e-4 repetitionTime = repetitionTime * 1e-3 inversionTime = inversionTime * 1e-3 rdGradTime = rdGradTime * 1e-3 rdDephTime = rdDephTime * 1e-3 phGradTime = phGradTime * 1e-3 crusherDelay = crusherDelay * 1e-6 # Inputs for rawData rawData['seqName'] = 'HASTE' rawData['nScans'] = nScans rawData['larmorFreq'] = larmorFreq # Larmor frequency rawData['rfExAmp'] = rfExAmp # rf excitation pulse amplitude rawData['rfReAmp'] = rfReAmp # rf refocusing pulse amplitude rawData['rfExTime'] = rfExTime # rf excitation pulse time rawData['rfReTime'] = rfReTime # rf refocusing pulse time rawData['rfEnvelope'] = rfEnvelope rawData['echoSpacing'] = echoSpacing # time between echoes rawData['inversionTime'] = inversionTime # Inversion recovery time rawData['repetitionTime'] = repetitionTime # TR rawData['fov'] = fov # FOV along readout, phase and slice rawData['dfov'] = dfov # Displacement of fov center rawData[ 'nPoints'] = nPoints # Number of points along readout, phase and slice rawData['acqTime'] = acqTime # Acquisition time rawData[ 'axesOrientation'] = axes # 0->x, 1->y and 2->z defined as [rd,ph,sl] rawData['axesEnable'] = axesEnable # 1-> Enable, 0-> Disable rawData[ 'sweepMode'] = sweepMode # 0->k2k (T2), 1->02k (T1), 2->k20 (T2), 3->Niquist modulated (T2) rawData['rdPreemphasis'] = rdPreemphasis rawData['ssPreemphasis'] = ssPreemphasis rawData['drfPhase'] = drfPhase rawData['dummyPulses'] = dummyPulses # Dummy pulses for T1 stabilization rawData['partialFourierFraction'] = parFourierFraction rawData['rdDephTime'] = rdDephTime rawData['crusherDelay'] = crusherDelay rawData['shimming'] = shimming # Miscellaneous slThickness = fov[2] rfSincLobes = 7 # Number of lobes for sinc rf excitation, BW = rfSincLobes/rfTime larmorFreq = larmorFreq * 1e-6 gradRiseTime = 200e-6 # Estimated gradient rise time gSteps = int(gradRiseTime * 1e6 / 5) addRdPoints = 10 # Initial rd points to avoid artifact at the begining of rd if rfReAmp == 0: rfReAmp = 2 * rfExAmp if rfReTime == 0: rfReTime = rfExTime resolution = fov / nPoints rawData['resolution'] = resolution rawData['gradRiseTime'] = gradRiseTime rawData['addRdPoints'] = addRdPoints # Matrix size nRD = nPoints[0] + 2 * addRdPoints nPH = nPoints[1] * axesEnable[1] + (1 - axesEnable[1]) # parAcqLines nPHreal = int(nPoints[1] * parFourierFraction) parAcqLines = int(nPHreal - nPoints[1] / 2) rawData['parAcqLines'] = parAcqLines print(parAcqLines) del nPHreal # BW BW = nPoints[0] / acqTime * 1e-6 BWov = BW * hw.oversamplingFactor samplingPeriod = 1 / BWov rawData['samplingPeriod'] = samplingPeriod # Readout gradient time if rdGradTime < acqTime: rdGradTime = acqTime rawData['rdGradTime'] = rdGradTime # Phase de- and re-phasing time if phGradTime == 0 or phGradTime > echoSpacing / 2 - rfExTime / 2 - rfReTime / 2 - 2 * gradRiseTime: phGradTime = echoSpacing / 2 - rfExTime / 2 - rfReTime / 2 - 2 * gradRiseTime rawData['phGradTime'] = phGradTime # Slice selection dephasing gradient time ssDephGradTime = (rfExTime - gradRiseTime) / 2 rawData['ssDephGradTime'] = ssDephGradTime # Max redaout and phase gradient amplitude rdGradAmplitude = nPoints[0] / (hw.gammaB * fov[0] * acqTime) * axesEnable[0] phGradAmplitude = nPH / (2 * hw.gammaB * fov[1] * (phGradTime + gradRiseTime)) * axesEnable[1] rawData['rdGradAmplitude'] = rdGradAmplitude rawData['phGradAmplitude'] = phGradAmplitude # Slice selection gradient if rfEnvelope == 'Sinc': ssGradAmplitude = rfSincLobes / (hw.gammaB * slThickness * rfExTime) * axesEnable[2] elif rfEnvelope == 'Rec': ssGradAmplitude = 1 / (hw.gammaB * slThickness * rfExTime) * axesEnable[2] rawData['ssGradAmplitude'] = ssGradAmplitude # Readout dephasing amplitude rdDephAmplitude = 0.5 * rdGradAmplitude * (gradRiseTime + rdGradTime) / ( gradRiseTime + rdDephTime) rawData['rdDephAmplitude'] = rdDephAmplitude # Phase gradient vector phGradients = np.linspace(-phGradAmplitude, phGradAmplitude, num=nPH, endpoint=False) # Get phase indexes for the given sweep mode ind = mri.getIndex(2 * parAcqLines, 2 * parAcqLines, sweepMode) ind = ind - parAcqLines + int(nPH / 2) ind = np.int32( np.concatenate((ind, np.linspace(int(nPH / 2) - parAcqLines - 1, -1, num=int(nPH / 2) - parAcqLines, endpoint=False)), axis=0)) rawData['sweepOrder'] = ind # Now fix the number of phases to partailly acquired k-space nPH = (int(nPoints[1] / 2) + parAcqLines) * axesEnable[1] + (1 - axesEnable[1]) phGradients = phGradients[0:nPH] phGradients = phGradients[ind] rawData['phGradients'] = phGradients def createSequenceDemo(): nRepetitions = int(1 + dummyPulses) scanTime = 20e3 + nRepetitions * repetitionTime rawData['scanTime'] = scanTime * 1e-6 acqPoints = 0 data = [] for repeIndex in range(nRepetitions): for echoIndex in range(nPH): if (repeIndex == 0 or repeIndex >= dummyPulses): acqPoints += nRD * hw.oversamplingFactor data = np.concatenate( (data, np.random.randn(nRD * hw.oversamplingFactor) + 1j * np.random.randn(nRD * hw.oversamplingFactor)), axis=0) return data, acqPoints def createSequence(): nRepetitions = int(1 + dummyPulses) scanTime = 20e3 + nRepetitions * repetitionTime rawData['scanTime'] = scanTime * 1e-6 print('Scan Time = ', (scanTime * 1e-6), 's') if rdGradTime == 0: # Check if readout gradient is dc or pulsed dc = True else: dc = False # Set shimming mri.iniSequence(expt, 20, shimming) for repeIndex in range(nRepetitions): # Initialize time tEx = 20e3 + repetitionTime * repeIndex + inversionTime # Inversion pulse if repeIndex >= dummyPulses and inversionTime != 0: t0 = tEx - inversionTime - rfReTime / 2 - hw.blkTime mri.rfRecPulse(expt, t0, rfReTime, rfReAmp / 180 * 180, 0) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, inversionTime * 0.5, 0.005, gSteps, axes[0], shimming) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, inversionTime * 0.5, 0.005, gSteps, axes[1], shimming) mri.gradTrap(expt, t0 + hw.blkTime + rfReTime, gradRiseTime, inversionTime * 0.5, 0.005, gSteps, axes[2], shimming) # DC radout gradient if desired if (repeIndex == 0 or repeIndex >= dummyPulses) and dc == True: t0 = tEx - rfExTime / 2 - gradRiseTime - hw.gradDelay mri.gradTrap(expt, t0, echoSpacing * (nPH + 1), rdGradAmplitude, axes[0]) # Slice selection gradient dephasing if (slThickness != 0 and repeIndex >= dummyPulses): t0 = tEx - rfExTime / 2 - gradRiseTime - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, rfExTime, ssGradAmplitude, gSteps, axes[2], shimming) # Excitation pulse t0 = tEx - hw.blkTime - rfExTime / 2 if rfEnvelope == 'Rec': mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, drfPhase * np.pi / 180) elif rfEnvelope == 'Sinc': mri.rfSincPulse(expt, t0, rfExTime, rfSincLobes, rfExAmp, drfPhase * np.pi / 180) # Slice selection gradient rephasing if (slThickness != 0 and repeIndex >= dummyPulses): t0 = tEx + rfExTime / 2 + gradRiseTime - hw.gradDelay if rfEnvelope == 'Rec': mri.gradTrap(expt, t0, gradRiseTime, 0., -ssGradAmplitude * ssPreemphasis, gSteps, axes[2], shimming) elif rfEnvelope == 'Sinc': mri.gradTrap(expt, t0, gradRiseTime, ssDephGradTime, -ssGradAmplitude * ssPreemphasis, gSteps, axes[2], shimming) # Dephasing readout t0 = tEx + rfExTime / 2 - hw.gradDelay if (repeIndex == 0 or repeIndex >= dummyPulses) and dc == False: mri.gradTrap(expt, t0, gradRiseTime, rdDephTime, rdDephAmplitude * rdPreemphasis, gSteps, axes[0], shimming) # Echo train for echoIndex in range(nPH): tEcho = tEx + echoSpacing * (echoIndex + 1) # Crusher gradient if repeIndex >= dummyPulses: t0 = tEcho - echoSpacing / 2 - rfReTime / 2 - gradRiseTime - hw.gradDelay - crusherDelay mri.gradTrap(expt, t0, gradRiseTime, rfReTime + 2 * crusherDelay, ssGradAmplitude, gSteps, axes[2], shimming) # Refocusing pulse t0 = tEcho - echoSpacing / 2 - rfReTime / 2 - hw.blkTime if rfEnvelope == 'Rec': mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, np.pi / 2 + drfPhase * np.pi / 180) if rfEnvelope == 'Sinc': mri.rfSincPulse(expt, t0, rfReTime, rfSincLobes, rfReAmp, np.pi / 2 + drfPhase * np.pi / 180) # Dephasing phase gradient t0 = tEcho - echoSpacing / 2 + rfReTime / 2 - hw.gradDelay if repeIndex >= dummyPulses: # This is to account for dummy pulses mri.gradTrap(expt, t0, gradRiseTime, phGradTime, phGradients[echoIndex], gSteps, axes[1], shimming) # Readout gradient t0 = tEcho - rdGradTime / 2 - gradRiseTime - hw.gradDelay if (repeIndex == 0 or repeIndex >= dummyPulses ) and dc == False: # This is to account for dummy pulses mri.gradTrap(expt, t0, gradRiseTime, rdGradTime, rdGradAmplitude, gSteps, axes[0], shimming) # Rx gate if (repeIndex == 0 or repeIndex >= dummyPulses): t0 = tEcho - acqTime / 2 - addRdPoints / BW mri.rxGate(expt, t0, acqTime + 2 * addRdPoints / BW) # Rephasing phase and slice gradients t0 = tEcho + acqTime / 2 + addRdPoints / BW - hw.gradDelay if (echoIndex < nPH - 1 and repeIndex >= dummyPulses): mri.gradTrap(expt, t0, gradRiseTime, phGradTime, -phGradients[echoIndex], gSteps, axes[1], shimming) elif (echoIndex == nPH - 1 and repeIndex >= dummyPulses): mri.gradTrap(expt, t0, gradRiseTime, phGradTime, +phGradients[echoIndex], gSteps, axes[1], shimming) if repeIndex == nRepetitions - 1: mri.endSequence(expt, scanTime) # Changing time parameters to us rfExTime = rfExTime * 1e6 rfReTime = rfReTime * 1e6 echoSpacing = echoSpacing * 1e6 repetitionTime = repetitionTime * 1e6 gradRiseTime = gradRiseTime * 1e6 phGradTime = phGradTime * 1e6 rdGradTime = rdGradTime * 1e6 rdDephTime = rdDephTime * 1e6 inversionTime = inversionTime * 1e6 crusherDelay = crusherDelay * 1e6 ssDephGradTime = ssDephGradTime * 1e6 # Calibrate frequency if not demo and freqCal and (not plotSeq): mri.freqCalibration(rawData, bw=0.05) mri.freqCalibration(rawData, bw=0.005) larmorFreq = rawData['larmorFreq'] * 1e-6 # Create full sequence if not demo: expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] BW = 1 / samplingPeriod / hw.oversamplingFactor acqTime = nPoints[0] / BW # us createSequence() # Run the experiment dataFull = [] dummyData = [] overData = [] for ii in range(nScans): if plotSeq: expt.plot_sequence() plt.show() break else: print("Scan %s ..." % (ii + 1)) if not demo: rxd, msgs = expt.run() rxd['rx0'] = rxd[ 'rx0'] * 13.788 # Here I normalize to get the result in mV else: data, acqPoints = createSequenceDemo() # Get data if not demo: if dummyPulses > 0: dummyData = np.concatenate( (dummyData, rxd['rx0'][0:nRD * nPH * hw.oversamplingFactor]), axis=0) overData = np.concatenate( (overData, rxd['rx0'][nRD * nPH * hw.oversamplingFactor::]), axis=0) else: overData = np.concatenate((overData, rxd['rx0']), axis=0) else: if dummyPulses > 0: dummyData = np.concatenate( (dummyData, data[0:nRD * nPH * hw.oversamplingFactor]), axis=0) overData = np.concatenate( (overData, data[nRD * nPH * hw.oversamplingFactor::]), axis=0) else: overData = np.concatenate((overData, data), axis=0) if not demo: expt.__del__() print('Scans done!') rawData['overData'] = overData # Fix the echo position using oversampled data if dummyPulses > 0: dummyData = np.reshape(dummyData, (nScans, nPH, nRD * hw.oversamplingFactor)) dummyData = np.average(dummyData, axis=0) rawData['dummyData'] = dummyData overData = np.reshape(overData, (nScans, 1, nPH, nRD * hw.oversamplingFactor)) for ii in range(nScans): overData[ii, :, :, :] = mri.fixEchoPosition( dummyData, overData[ii, :, :, :]) # Generate dataFull overData = np.squeeze( np.reshape(overData, (1, nRD * hw.oversamplingFactor * nPH * nScans))) dataFull = sig.decimate(overData, hw.oversamplingFactor, ftype='fir', zero_phase=True) # Get index for krd = 0 # Average data dataProv = np.reshape(dataFull, (nScans, nRD * nPH)) dataProv = np.average(dataProv, axis=0) # Reorganize the data acording to sweep mode dataProv = np.reshape(dataProv, (nPH, nRD)) dataTemp = dataProv * 0 for ii in range(nPH): dataTemp[ind[ii], :] = dataProv[ii, :] dataProv = dataTemp # Check where is krd = 0 dataProv = dataProv[int(nPoints[1] / 2), :] indkrd0 = np.argmax(np.abs(dataProv)) if indkrd0 < nRD / 2 - addRdPoints or indkrd0 > nRD / 2 + addRdPoints: indkrd0 = int(nRD / 2) # Get individual images dataFull = np.reshape(dataFull, (nScans, nPH, nRD)) dataFull = dataFull[:, :, indkrd0 - int(nPoints[0] / 2):indkrd0 + int(nPoints[0] / 2)] dataTemp = dataFull * 0 for ii in range(nPH): dataTemp[:, ind[ii], :] = dataFull[:, ii, :] dataFull = dataTemp imgFull = dataFull * 0 for ii in range(nScans): imgFull[ii, :, :] = np.fft.ifftshift( np.fft.ifftn(np.fft.ifftshift(dataFull[ii, :, :]))) rawData['dataFull'] = dataFull rawData['imgFull'] = imgFull # Average data data = np.average(dataFull, axis=0) data = np.reshape(data, (nPH, nPoints[0])) # Do zero padding dataTemp = np.zeros((nPoints[1], nPoints[0])) dataTemp = dataTemp + 1j * dataTemp dataTemp[0:nPH, :] = data data = np.reshape(dataTemp, (1, nPoints[0] * nPoints[1])) # Fix the position of the sample according to dfov kMax = np.array(nPoints) / (2 * np.array(fov)) * np.array(axesEnable) kRD = np.linspace(-kMax[0], kMax[0], num=nPoints[0], endpoint=False) kPH = np.linspace(-kMax[1], kMax[1], num=nPoints[1], endpoint=False) kPH, kRD = np.meshgrid(kPH, kRD) kRD = np.reshape(kRD, (1, nPoints[0] * nPoints[1])) kPH = np.reshape(kPH, (1, nPoints[0] * nPoints[1])) dPhase = np.exp(-2 * np.pi * 1j * (dfov[0] * kRD + dfov[1] * kPH)) data = np.reshape(data * dPhase, (nPoints[1], nPoints[0])) rawData['kSpace3D'] = data img = np.fft.ifftshift(np.fft.ifftn(np.fft.ifftshift(data))) rawData['image3D'] = img data = np.reshape(data, (1, nPoints[0] * nPoints[1])) # Create sampled data kRD = np.reshape(kRD, (nPoints[0] * nPoints[1], 1)) kPH = np.reshape(kPH, (nPoints[0] * nPoints[1], 1)) data = np.reshape(data, (nPoints[0] * nPoints[1], 1)) rawData['kMax'] = kMax rawData['sampled'] = np.concatenate((kRD, kPH, data), axis=1) data = np.reshape(data, -1) # Save data mri.saveRawData(rawData) return rawData, msgs, data, BW
def rabiflopStandalone( init_gpa= False, larmorFreq = 3.0806, # MHz rfExAmp = 0.4, # a.u. rfReAmp = 0.8, # a.u. rfExTime = 22, # us rfReTime = 22, # us nPoints = 100, acqTime = 18, # ms echoTime = 20, # ms repetitionTime = 1000, # ms plotSeq = 0, # 0 to run sequence, 1 to plot sequence pulseShape = 'Rec', # 'Rec' for square pulse shape, 'Sinc' for sinc pulse shape shimming0 = [-77.5, -70, 7.5], nShimming = 10, # number of samples to sweep in each gradient direction dShimming = [2.5, 2.5, 2.5] # shimming step in each direction ): freqCal = 0 plt.ion() # Miscellaneous deadTime = 400 # us, time between excitation and first acquisition shimming0 = np.array(shimming0)*1e-4 # Varibales to fundamental units larmorFreq *= 1e6 rfExTime *= 1e-6 rfReTime *= 1e-6 acqTime *= 1e-3 echoTime *= 1e-3 repetitionTime *= 1e-3 # Inputs for rawData rawData={} rawData['seqName'] = 'ShimmingCal' rawData['larmorFreq'] = larmorFreq # Larmor frequency rawData['rfExAmp'] = rfExAmp # rf excitation pulse amplitude rawData['rfReAmp'] = rfReAmp rawData['rfExTime'] = rfExTime rawData['rfReTime'] = rfReTime rawData['nPoints'] = nPoints rawData['acqTime'] = acqTime rawData['echoTime'] = echoTime rawData['repetitionTime'] = repetitionTime rawData['pulseShape'] = pulseShape rawData['deadTime'] = deadTime*1e-6 rawData['shimming0'] = shimming0 rawData['nShimming'] = nShimming rawData['dShimming'] = dShimming rawData['shimming'] = shimming0 rawData['addRdPoints'] = 10 # Shimming vectors dsx = nShimming*dShimming[0]*1e-4 dsy = nShimming*dShimming[1]*1e-4 dsz = nShimming*dShimming[2]*1e-4 sxVector = np.linspace(shimming0[0]-dsx/2, shimming0[0]+dsx/2, num=nShimming, endpoint=False) syVector = np.linspace(shimming0[1]-dsy/2, shimming0[1]+dsy/2, num=nShimming, endpoint=False) szVector = np.linspace(shimming0[2]-dsz/2, shimming0[2]+dsz/2, num=nShimming, endpoint=False) # Bandwidth bw = nPoints/acqTime*1e-6 # MHz bwov = bw*hw.oversamplingFactor # MHz samplingPeriod = 1/bwov # us rawData['bw'] = bw rawData['samplingPeriod'] = samplingPeriod fVector = np.linspace(-bw/2, bw/2, num=nPoints, endpoint=False) # Time variables in us and MHz larmorFreq *=1e-6 rfExTime *=1e6 rfReTime *=1e6 echoTime *=1e6 repetitionTime *=1e6 acqTime *=1e6 # SEQUENCE ############################################################################################ def createSequence(shimming): # Set shimming mri.iniSequence(expt, 20, shimming) # Initialize time tEx = 20e3 # Excitation pulse t0 = tEx-hw.blkTime-rfExTime/2 if pulseShape=='Rec': mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, 0) elif pulseShape=='Sinc': mri.rfSincPulse(expt, t0, rfExTime, 7, rfExAmp, 0) # Refocusing pulse t0 = tEx+echoTime/2-rfReTime/2-hw.blkTime if pulseShape=='Rec': mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, np.pi/2) elif pulseShape=='Sinc': mri.rfSincPulse(expt, t0, rfReTime, 7, rfReAmp, np.pi/2) # Acquisition window t0 = tEx+echoTime-acqTime/2 mri.rxGate(expt, t0, acqTime) # End sequence mri.endSequence(expt, repetitionTime) # Calibrate frequency if freqCal==1: mri.freqCalibration(rawData, bw=0.05) mri.freqCalibration(rawData, bw=0.005) larmorFreq = rawData['larmorFreq']*1e-6 # INIT EXPERIMENT dataAll = [] gx = [] gy = [] gz = [] ppmx = [] ppmy = [] ppmz = [] # shimming for Gx for sx in sxVector: shimming = np.array([sx, shimming0[1], shimming0[2]]) expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] bw = 1/samplingPeriod/hw.oversamplingFactor acqTime = nPoints/bw rawData['bw'] = bw createSequence(shimming) if plotSeq==1: expt.plot_sequence() plt.show(block=False) expt.__del__() elif plotSeq==0: print(shimming*1e4, '.- Running...') rxd, msgs = expt.run() expt.__del__() data = sig.decimate(rxd['rx0']*13.788, hw.oversamplingFactor, ftype='fir', zero_phase=True) fwhm, max = getPeakProperties(fVector, data) gx = np.concatenate((gx, np.array([max])), axis=0) ppmx = np.concatenate((ppmx, np.array([fwhm/larmorFreq*1e6])), axis=0) dataAll = np.concatenate((dataAll, data), axis=0) # Plots plt.figure(1) plt.plot(sx*1e4, max, 'b.') plt.figure(2) plt.plot(sx*1e4, fwhm/larmorFreq*1e6, 'b.') plt.show(block=False) plt.pause(0.05) idx = np.argmax(gx) sxOpt = sxVector[idx] # shimming for Gy for sy in syVector: shimming = np.array([sxOpt, sy, shimming0[2]]) expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] bw = 1/samplingPeriod/hw.oversamplingFactor acqTime = nPoints/bw rawData['bw'] = bw createSequence(shimming) if plotSeq==1: expt.plot_sequence() plt.show(block=False) expt.__del__() elif plotSeq==0: print(shimming*1e4, '.- Running...') rxd, msgs = expt.run() expt.__del__() data = sig.decimate(rxd['rx0']*13.788, hw.oversamplingFactor, ftype='fir', zero_phase=True) fwhm, max = getPeakProperties(fVector, data) gy = np.concatenate((gy, np.array([max])), axis=0) ppmy = np.concatenate((ppmy, np.array([fwhm/larmorFreq*1e6])), axis=0) dataAll = np.concatenate((dataAll, data), axis=0) plt.figure(1) plt.plot(sy*1e4, max, 'g.') plt.figure(2) plt.plot(sy*1e4, fwhm/larmorFreq*1e6, 'g.') plt.show(block=False) plt.pause(0.05) idx = np.argmax(gy) syOpt = syVector[idx] # shimming for Gz for sz in szVector: shimming = np.array([sxOpt, syOpt, sz]) expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] bw = 1/samplingPeriod/hw.oversamplingFactor acqTime = nPoints/bw rawData['bw'] = bw createSequence(shimming) if plotSeq==1: expt.plot_sequence() plt.show(block=False) expt.__del__() elif plotSeq==0: print(shimming*1e4, '.- Running...') rxd, msgs = expt.run() expt.__del__() data = sig.decimate(rxd['rx0']*13.788, hw.oversamplingFactor, ftype='fir', zero_phase=True) fwhm, max = getPeakProperties(fVector, data) gz = np.concatenate((gz, np.array([max])), axis=0) ppmz = np.concatenate((ppmz, np.array([fwhm/larmorFreq*1e6])), axis=0) dataAll = np.concatenate((dataAll, data), axis=0) plt.figure(1) plt.plot(sz*1e4, max, 'r.') plt.figure(2) plt.plot(sz*1e4, fwhm/larmorFreq*1e6, 'r.') plt.show(block=False) plt.pause(0.05) idx = np.argmax(gz) szOpt = szVector[idx] rawData['shimming'] = np.array([sxOpt, syOpt, szOpt]) # Get the values for the optimal case shimming = np.array([sxOpt, syOpt, szOpt]) # expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) # samplingPeriod = expt.get_rx_ts()[0] # bw = 1/samplingPeriod/hw.oversamplingFactor # acqTime = nPoints/bw # rawData['bw'] = bw # createSequence(shimming) # if plotSeq==1: # expt.plot_sequence() # plt.show(block=False) # expt.__del__() # elif plotSeq==0: # print(shimming*1e4, '.- Running...') # rxd, msgs = expt.run() # expt.__del__() # data = sig.decimate(rxd['rx0']*13.788, hw.oversamplingFactor, ftype='fir', zero_phase=True) # fwhm, max = getPeakProperties(fVector, data) # plt.figure(1) # plt.plot(0, max, 'k.') # plt.figure(2) # plt.plot(0, fwhm/larmorFreq*1e6, 'k.') # plt.show(block=False) # plt.pause(0.05) # Save data mri.saveRawData(rawData) plt.figure(3) plt.plot(sxVector*1e4, gx, 'b.', syVector*1e4, gy, 'g.', szVector*1e4, gz, 'r.') plt.title(rawData['fileName']) plt.xlabel('Shimming (a.u.)') plt.ylabel('FFT peak amplitude (a.u.)') plt.legend(['x Axis', 'y Axis', 'z Axis']) plt.figure(4) plt.plot(sxVector*1e4, ppmx, 'b.', syVector*1e4, ppmy, 'g.', szVector*1e4, ppmz, 'r.') plt.title(rawData['fileName']) plt.xlabel('Shimming (a.u.)') plt.ylabel('Homogeneity (ppm)') plt.legend(['x Axis', 'y Axis', 'z Axis']) print('Best shimming = ', shimming*1e4) plt.show(block=True)
def saturationrecoveryStandalone( init_gpa=False, larmorFreq=3.077, # MHz rfExAmp=0.4, rfReAmp=0.4, rfExTime=20, # us rfReTime=20, # us acqTime=4, # ms echoTime=20, # ms repetitionTime=5, # s tSatIni=0.01, # s tSatFin=0.9, # s nRepetitions=1, # number of samples nRD=100, plotSeq=0, shimming=[-70, -90, 10]): shimming = np.array(shimming) * 1e-4 if rfReTime is None: rfReTime = 2 * rfExTime rfExTime = rfExTime * 1e-6 rfReTime = rfReTime * 1e-6 acqTime = acqTime * 1e-3 echoTime = echoTime * 1e-3 rawData = {} rawData['seqName'] = 'inversionRecovery' rawData['larmorFreq'] = larmorFreq * 1e6 rawData['rfExAmp'] = rfExAmp rawData['rfReAmp'] = rfReAmp rawData['rfExTime'] = rfExTime rawData['rfRetime'] = rfReTime rawData['repetitionTime'] = repetitionTime rawData['tSatIni'] = tSatIni rawData['tSatFin'] = tSatFin rawData['nRepetitions'] = nRepetitions rawData['acqTime'] = acqTime rawData['nRD'] = nRD rawData['echoTime'] = echoTime # Miscellaneous gradRiseTime = 200 # us crusherTime = 1000 # us gSteps = int(gradRiseTime / 5) axes = np.array([0, 1, 2]) rawData['gradRiseTime'] = gradRiseTime rawData['gSteps'] = gSteps # Bandwidth and sampling rate bw = nRD / acqTime * 1e-6 # MHz bwov = bw * hw.oversamplingFactor samplingPeriod = 1 / bwov tSat = np.geomspace(tSatIni, tSatFin, nRepetitions) rawData['tSat'] = tSat def createSequence(): # Set shimming mri.iniSequence(expt, 20, shimming) for repeIndex in range(nRepetitions): # Initialize time tEx = 20e3 + np.max(tSat) + repetitionTime * repeIndex # Inversion time for current iteration inversionTime = tSat[repeIndex] # Crusher gradient for inversion rf pulse # t0 = tEx-inversionTime-crusherTime/2-gradRiseTime-hw.gradDelay-50 # mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[0], shimming) # mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[1], shimming) # mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[2], shimming) # Saturation pulse t0 = tEx - inversionTime - hw.blkTime - rfReTime / 2 mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, 0) # Spoiler gradients to destroy residual transversal signal detected for ultrashort inversion times # mri.gradTrap(expt, t0+hw.blkTime+rfReTime, gradRiseTime, inversionTime*0.5, 0.005, gSteps, axes[0], shimming) # mri.gradTrap(expt, t0+hw.blkTime+rfReTime, gradRiseTime, inversionTime*0.5, 0.005, gSteps, axes[1], shimming) # mri.gradTrap(expt, t0+hw.blkTime+rfReTime, gradRiseTime, inversionTime*0.5, 0.005, gSteps, axes[2], shimming) # Excitation pulse t0 = tEx - hw.blkTime - rfExTime / 2 mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, 0) # # Rx gating # t0 = tEx+rfExTime/2+hw.deadTime # mri.rxGate(expt, t0, acqTime) # Crusher gradient t0 = tEx + echoTime / 2 - crusherTime / 2 - gradRiseTime - hw.gradDelay - 50 mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[0], shimming) mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[1], shimming) mri.gradTrap(expt, t0, gradRiseTime, crusherTime, 0.005, gSteps, axes[2], shimming) # Refocusing pulse t0 = tEx + echoTime / 2 - rfReTime / 2 - hw.blkTime mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, np.pi / 2) # Rx gating t0 = tEx + echoTime - acqTime / 2 mri.rxGate(expt, t0, acqTime) # End sequence mri.endSequence(expt, scanTime) # Time variables in us rfExTime *= 1e6 rfReTime *= 1e6 repetitionTime *= 1e6 echoTime *= 1e6 tSat *= 1e6 scanTime = nRepetitions * repetitionTime # us expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] # us bw = 1 / samplingPeriod / hw.oversamplingFactor # MHz acqTime = nRD / bw # us rawData['samplingPeriod'] = samplingPeriod * 1e-6 rawData['bw'] = bw * 1e6 createSequence() # Representar Secuencia o tomar los datos. tSat1 = np.geomspace(tSatIni, tSatFin, nRepetitions) tSat2 = np.geomspace(tSatIni, tSatFin, 10 * nRepetitions) if plotSeq == 1: expt.plot_sequence() plt.show() expt.__del__() elif plotSeq == 0: print('Running...') rxd, msgs = expt.run() print('End') data = rxd['rx0'] * 13.788 expt.__del__() data = sig.decimate(data, hw.oversamplingFactor, ftype='fir', zero_phase=True) rawData['fullData'] = data dataIndiv = np.reshape(data, (nRepetitions, nRD)) dataIndiv = np.real( dataIndiv[:, int(nRD / 2)] * np.exp(-1j * (np.angle(dataIndiv[0, int(nRD / 2)]) + np.pi))) results = np.transpose(np.array([tSat1, dataIndiv / np.max(dataIndiv)])) # results = np.transpose(np.array([tSat1, dataIndiv])) rawData['signalVsTime'] = results plt.figure(1) plt.plot(np.abs(data)) plt.show() # For 1 component fitData1, xxx = curve_fit(func1, results[:, 0], results[:, 1]) print('For one component:') print('mA', round(fitData1[0], 1)) print('T1', round(fitData1[1] * 1e3), ' ms') rawData['T11'] = fitData1[1] * 1e3 rawData['M1'] = fitData1[0] # For 2 components fitData2, xxx = curve_fit(func2, results[:, 0], results[:, 1], p0=(1, 0.1, 0.5, 0.05), bounds=(0., 5.)) print('For two components:') print('Ma', round(fitData2[0], 1)) print('Mb', round(fitData2[2], 1)) print('T1a', round(fitData2[1] * 1e3), ' ms') print('T1b', round(fitData2[3] * 1e3), ' ms') rawData['T12'] = [fitData2[1], fitData2[3]] rawData['M2'] = [fitData2[0], fitData2[2]] # For 3 components fitData3, xxx = curve_fit(func3, results[:, 0], results[:, 1], p0=(1, 0.1, 0.5, 0.05, 1, 0.01), bounds=(0., 5.)) print('For three components:') print('Ma', round(fitData3[0], 1), ' ms') print('Mb', round(fitData3[2], 1), ' ms') print('Mc', round(fitData3[4], 1), ' ms') print('T1a', round(fitData3[1] * 1e3), ' ms') print('T1b', round(fitData3[3] * 1e3), ' ms') print('T1c', round(fitData3[5] * 1e3), ' ms') rawData['T13'] = [fitData3[1], fitData3[3], fitData3[5]] rawData['M3'] = [fitData3[0], fitData3[2], fitData3[4]] # Save data mri.saveRawData(rawData) # Plots plt.figure(2, figsize=(5, 5)) plt.plot(results[:, 0], results[:, 1], 'o') plt.plot(tSat2, func1(tSat2, *fitData1)) plt.plot(tSat2, func2(tSat2, *fitData2)) plt.plot(tSat2, func3(tSat2, *fitData3)) plt.title(rawData['fileName']) plt.xscale('log') plt.xlabel('t(s)') plt.ylabel('Signal (mV)') plt.legend([ 'Experimental', 'Fitting 1 component', 'Fitting 2 components', 'Fitting 3 components' ]) plt.title(rawData['fileName']) plt.show()
def rabiflopStandalone( init_gpa=False, larmorFreq=3.0806, # MHz rfExAmp=0.4, # a.u. rfReAmp=0.8, # a.u. rfExTime=22, # us rfReTime=22, # us nPoints=100, acqTime=18, # ms echoTime=20, # ms repetitionTime=1000, # ms plotSeq=0, # 0 to run sequence, 1 to plot sequence pulseShape='Rec', # 'Rec' for square pulse shape, 'Sinc' for sinc pulse shape shimming0=[-0, -0, 0], nShimming=10, # number of samples to sweep in each gradient direction dShimming=[10, 10, 10] # shimming step in each direction ): freqCal = 1 plt.ion() # Miscellaneous deadTime = 400 # us, time between excitation and first acquisition shimming0 = np.array(shimming0) * 1e-4 dShimming = np.array(dShimming) * 1e-4 # Varibales to fundamental units larmorFreq *= 1e6 rfExTime *= 1e-6 rfReTime *= 1e-6 acqTime *= 1e-3 echoTime *= 1e-3 repetitionTime *= 1e-3 # Inputs for rawData rawData = {} rawData['seqName'] = 'ShimmingCal' rawData['larmorFreq'] = larmorFreq # Larmor frequency rawData['rfExAmp'] = rfExAmp # rf excitation pulse amplitude rawData['rfReAmp'] = rfReAmp rawData['rfExTime'] = rfExTime rawData['rfReTime'] = rfReTime rawData['nPoints'] = nPoints rawData['acqTime'] = acqTime rawData['echoTime'] = echoTime rawData['repetitionTime'] = repetitionTime rawData['pulseShape'] = pulseShape rawData['deadTime'] = deadTime * 1e-6 rawData['shimming0'] = shimming0 rawData['nShimming'] = nShimming rawData['dShimming'] = dShimming rawData['shimming'] = shimming0 rawData['addRdPoints'] = 10 # Bandwidth bw = nPoints / acqTime * 1e-6 # MHz bwov = bw * hw.oversamplingFactor # MHz samplingPeriod = 1 / bwov # us rawData['bw'] = bw rawData['samplingPeriod'] = samplingPeriod fVector = np.linspace(-bw / 2, bw / 2, num=nPoints, endpoint=False) # Time variables in us and MHz larmorFreq *= 1e-6 rfExTime *= 1e6 rfReTime *= 1e6 echoTime *= 1e6 repetitionTime *= 1e6 acqTime *= 1e6 # SEQUENCE ############################################################################################ def createSequence(expt, shimming): # Set shimming mri.iniSequence(expt, 20, shimming) # Initialize time tEx = 20e3 # Excitation pulse t0 = tEx - hw.blkTime - rfExTime / 2 if pulseShape == 'Rec': mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, 0) elif pulseShape == 'Sinc': mri.rfSincPulse(expt, t0, rfExTime, 7, rfExAmp, 0) # Refocusing pulse t0 = tEx + echoTime / 2 - rfReTime / 2 - hw.blkTime if pulseShape == 'Rec': mri.rfRecPulse(expt, t0, rfReTime, rfReAmp, np.pi / 2) elif pulseShape == 'Sinc': mri.rfSincPulse(expt, t0, rfReTime, 7, rfReAmp, np.pi / 2) # Acquisition window t0 = tEx + echoTime - acqTime / 2 mri.rxGate(expt, t0, acqTime) # End sequence mri.endSequence(expt, repetitionTime) def runExperiment(shimmingExp, samplingRate): expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingRate, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] bw = 1 / samplingPeriod / hw.oversamplingFactor acqTime = nPoints / bw rawData['acqTime'] = acqTime rawData['bw'] = bw createSequence(expt, shimmingExp) print(shimmingExp * 1e4, '.- Running...') rxd, msgs = expt.run() expt.__del__() data = sig.decimate(rxd['rx0'] * 13.788, hw.oversamplingFactor, ftype='fir', zero_phase=True) return (data) def sweepAxis(axis): # First two samples to determine the sweep direction shimmingA = shimming0 * 1 shimmingB = shimming0 * 1 shimmingB[axis] = shimming0[axis] + dShimming[axis] dataA = runExperiment(shimmingA, samplingPeriod) fwhmA, maxA = getPeakProperties(fVector, dataA) print('Peak amplitude = ', maxA) print('Homogeneity = ', fwhmA / larmorFreq * 1e6, ' ppm \n') dataB = runExperiment(shimmingB, samplingPeriod) fwhmB, maxB = getPeakProperties(fVector, dataB) print('Peak amplitude = ', maxB) print('Homogeneity = ', fwhmB / larmorFreq * 1e6, ' ppm \n') if maxB < maxA: dShimming[axis] = -dShimming[axis] maxP = maxB maxB = maxA maxA = maxP shimmingP = shimmingB shimmingB = shimmingA shimmingA = shimmingP del maxP, shimmingP # Sweep axis until the max start to goes down while maxB > maxA: fwhmA = fwhmB maxA = maxB shimmingA = shimmingB * 1 shimmingB[axis] += dShimming[axis] dataB = runExperiment(shimmingB, samplingPeriod) fwhmB, maxB = getPeakProperties(fVector, dataB) print('Peak amplitude = ', maxB) print('Homogeneity = ', fwhmB / larmorFreq * 1e6, ' ppm \n˘') print('Axis ', axis, ' optimized!') # Return fwhm and max values return (fwhmA, maxA, shimmingA) # Calibrate frequency if freqCal == 1: mri.freqCalibration(rawData, bw=0.05) mri.freqCalibration(rawData, bw=0.005) larmorFreq = rawData['larmorFreq'] * 1e-6 for nSweep in range(3): for axis in range(3): fwhmOpt, maxOpt, shimmingOpt = sweepAxis(axis) shimming0 = shimmingOpt dShimming /= 2 # Save data mri.saveRawData(rawData) # plt.figure(3) # plt.plot(sxVector*1e4, gx, 'b.', # syVector*1e4, gy, 'g.', # szVector*1e4, gz, 'r.') # plt.title(rawData['fileName']) # plt.xlabel('Shimming (a.u.)') # plt.ylabel('FFT peak amplitude (a.u.)') # plt.legend(['x Axis', 'y Axis', 'z Axis']) # plt.figure(4) # plt.plot(sxVector*1e4, ppmx, 'b.', # syVector*1e4, ppmy, 'g.', # szVector*1e4, ppmz, 'r.') # plt.title(rawData['fileName']) # plt.xlabel('Shimming (a.u.)') # plt.ylabel('Homogeneity (ppm)') # plt.legend(['x Axis', 'y Axis', 'z Axis']) print('Best shimming = ', shimming0 * 1e4) plt.show(block=True)
def gre3d(self, plotSeq): init_gpa = False, # Starts the gpa nScans = self.nScans # NEX larmorFreq = self.larmorFreq # MHz, Larmor frequency rfExAmp = self.rfExAmp # a.u. rf excitation pulse amplitude rfExTime = self.rfExTime # us, rf excitation pulse time echoTime = self.echoTime # ms, TE repetitionTime = self.repetitionTime # ms, TR fov = self.fov # mm, FOV along readout, phase and slice dfov = self.dfov # mm, Displacement of fov center nPoints = self.nPoints # Number of points along readout, phase and slice acqTime = self.acqTime # ms, Acquisition time axes = self.axes # 0->x, 1->y and 2->z defined as [rd,ph,sl] rdGradTime = self.rdGradTime # ms, readout rephasing gradient time dephGradTime = self.dephGradTime # ms, Phase and slice dephasing time dummyPulses = self.dummyPulses # Dummy pulses for T1 stabilization shimming = self.shimming # a.u.*1e4, Shimming along the X,Y and Z axes parFourierFraction = self.parFourierFractionSl # fraction of acquired k-space along phase direction spoiler = self.spoiler # set 1 or 0 if you want or do not want to apply spoiler gradients freqCal = False demo = False # rawData fields rawData = {} # Conversion of variables to non-multiplied units larmorFreq = larmorFreq * 1e6 rfExTime = rfExTime * 1e-6 fov = np.array(fov) * 1e-3 dfov = np.array(dfov) * 1e-3 echoTime = echoTime * 1e-3 acqTime = acqTime * 1e-3 shimming = np.array(shimming) * 1e-4 nPoints = np.array(nPoints) repetitionTime = repetitionTime * 1e-3 rdGradTime = rdGradTime * 1e-3 dephGradTime = dephGradTime * 1e-3 # Inputs for rawData rawData['seqName'] = self.seq rawData['nScans'] = nScans rawData['larmorFreq'] = larmorFreq # Larmor frequency rawData['rfExAmp'] = rfExAmp # rf excitation pulse amplitude rawData['rfExTime'] = rfExTime # rf excitation pulse time rawData['echoTime'] = echoTime # time between echoes rawData['repetitionTime'] = repetitionTime # TR rawData['fov'] = fov # FOV along readout, phase and slice rawData['dfov'] = dfov # Displacement of fov center rawData[ 'nPoints'] = nPoints # Number of points along readout, phase and slice rawData['acqTime'] = acqTime # Acquisition time rawData[ 'axesOrientation'] = axes # 0->x, 1->y and 2->z defined as [rd,ph,sl] rawData['rdGradTime'] = rdGradTime rawData['dephGradTime'] = dephGradTime rawData['dummyPulses'] = dummyPulses # Dummy pulses for T1 stabilization rawData['shimming'] = shimming rawData['partialFourierFraction'] = parFourierFraction rawData['spoiler'] = spoiler # Miscellaneous larmorFreq = larmorFreq * 1e-6 gradRiseTime = 100e-6 # Estimated gradient rise time gSteps = int(gradRiseTime * 1e6 / 5) * 0 + 1 addRdPoints = 5 # Initial rd points to avoid artifact at the begining of rd resolution = fov / nPoints randFactor = 0. axesEnable = np.array([1, 1, 1]) for ii in range(3): if nPoints[ii] == 1: axesEnable[ii] = 0 if fov[0] > 1 and nPoints[1] == 1: axesEnable[0] = 0 rawData['randFactor'] = randFactor rawData['resolution'] = resolution rawData['gradRiseTime'] = gradRiseTime rawData['addRdPoints'] = addRdPoints # Matrix size nRD = nPoints[0] + 2 * addRdPoints nPH = nPoints[1] nSL = nPoints[2] # parAcqLines nSLreal = int(nPoints[2] * parFourierFraction) parAcqLines = int(nSLreal - nPoints[2] / 2) rawData['parAcqLines'] = parAcqLines del nSLreal # BW BW = nPoints[0] / acqTime * 1e-6 BWov = BW * hw.oversamplingFactor samplingPeriod = 1 / BWov rawData['samplingPeriod'] = samplingPeriod # Check if dephasing grad time is ok maxDephGradTime = echoTime - (rfExTime + rdGradTime) - 3 * gradRiseTime if dephGradTime == 0 or dephGradTime > maxDephGradTime: dephGradTime = maxDephGradTime # Max gradient amplitude rdGradAmplitude = nPoints[0] / (hw.gammaB * fov[0] * acqTime) rdDephAmplitude = -rdGradAmplitude * (rdGradTime + gradRiseTime) / ( 2 * (dephGradTime + gradRiseTime)) phGradAmplitude = nPH / (2 * hw.gammaB * fov[1] * (dephGradTime + gradRiseTime)) * axesEnable[1] slGradAmplitude = nSL / (2 * hw.gammaB * fov[2] * (dephGradTime + gradRiseTime)) * axesEnable[2] rawData['rdGradAmplitude'] = rdGradAmplitude rawData['rdDephAmplitude'] = rdDephAmplitude rawData['phGradAmplitude'] = phGradAmplitude rawData['slGradAmplitude'] = slGradAmplitude # Phase and slice gradient vector phGradients = np.linspace(-phGradAmplitude, phGradAmplitude, num=nPH, endpoint=False) slGradients = np.linspace(-slGradAmplitude, slGradAmplitude, num=nSL, endpoint=False) # Now fix the number of slices to partailly acquired k-space if nPoints[2] == 1: nSL = 1 else: nSL = int(nPoints[2] / 2) + parAcqLines nRepetitions = nPH * nSL # Add random displacemnt to phase encoding lines for ii in range(nPH): if ii < np.ceil(nPH / 2 - nPH / 20) or ii > np.ceil(nPH / 2 + nPH / 20): phGradients[ii] = phGradients[ii] + randFactor * np.random.randn() kPH = hw.gammaB * phGradients * (gradRiseTime + dephGradTime) rawData['phGradients'] = phGradients rawData['slGradients'] = slGradients # Changing time parameters to us rfExTime = rfExTime * 1e6 echoTime = echoTime * 1e6 repetitionTime = repetitionTime * 1e6 gradRiseTime = gradRiseTime * 1e6 dephGradTime = dephGradTime * 1e6 rdGradTime = rdGradTime * 1e6 scanTime = nRepetitions * repetitionTime rawData['scanTime'] = scanTime * nSL * 1e-6 # Create demo def createSequenceDemo(phIndex=0, slIndex=0, repeIndexGlobal=0): repeIndex = 0 acqPoints = 0 orders = 0 data = [] if (dummyPulses > 0 and nRD * 3 > hw.maxRdPoints) or ( dummyPulses == 0 and nRD * 2 > hw.maxRdPoints): print( 'ERROR: Too many acquired points or orders to the red pitaya.') return () while acqPoints + nRD <= hw.maxRdPoints and orders <= hw.maxOrders and repeIndexGlobal < nRepetitions: # First I do a noise measurement if repeIndex == 0: acqPoints += nRD data = np.concatenate( (data, np.random.randn(nRD * hw.oversamplingFactor)), axis=0) # Dephasing readout, phase and slice if (repeIndex == 0 or repeIndex >= dummyPulses): orders = orders + gSteps * 2 if repeIndex >= dummyPulses: orders = orders + gSteps * 4 # Rephasing readout gradient if (repeIndex == 0 or repeIndex >= dummyPulses): orders = orders + gSteps * 2 # Rx gate if (repeIndex == 0 or repeIndex >= dummyPulses): acqPoints += nRD data = np.concatenate( (data, np.random.randn(nRD * hw.oversamplingFactor)), axis=0) # Spoiler if (repeIndex == 0 or repeIndex >= dummyPulses): orders = orders + gSteps * 2 if repeIndex >= dummyPulses: orders = orders + gSteps * 4 # Update the phase and slice gradient if repeIndex >= dummyPulses: if phIndex == nPH - 1: phIndex = 0 slIndex += 1 else: phIndex += 1 if repeIndex >= dummyPulses: repeIndexGlobal += 1 # Update the global repeIndex repeIndex += 1 # Update the repeIndex after the ETL # Return the output variables return (phIndex, slIndex, repeIndexGlobal, acqPoints, data) # Create sequence instructions def createSequence(phIndex=0, slIndex=0, repeIndexGlobal=0, rewrite=True): repeIndex = 0 acqPoints = 0 orders = 0 # check in case of dummy pulse filling the cache if (dummyPulses > 0 and nRD * 3 > hw.maxRdPoints) or ( dummyPulses == 0 and nRD * 2 > hw.maxRdPoints): print( 'ERROR: Too many acquired points or orders to the red pitaya.') return () # Set shimming mri.iniSequence(expt, 20, shimming, rewrite=rewrite) # Run sequence batch while acqPoints + nRD <= hw.maxRdPoints and orders <= hw.maxOrders and repeIndexGlobal < nRepetitions: # Initialize time tEx = 20e3 + repetitionTime * repeIndex # First I do a noise measurement if repeIndex == 0: t0 = tEx - 4 * acqTime mri.rxGate(expt, t0, acqTime + 2 * addRdPoints / BW) acqPoints += nRD # Excitation pulse t0 = tEx - hw.blkTime - rfExTime / 2 mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, 0.) # Dephasing readout, phase and slice if (repeIndex == 0 or repeIndex >= dummyPulses): t0 = tEx + rfExTime / 2 - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, dephGradTime, rdDephAmplitude, gSteps, axes[0], shimming) orders = orders + gSteps * 2 if repeIndex >= dummyPulses: t0 = tEx + rfExTime / 2 - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, dephGradTime, phGradients[phIndex], gSteps, axes[1], shimming) mri.gradTrap(expt, t0, gradRiseTime, dephGradTime, slGradients[slIndex], gSteps, axes[2], shimming) orders = orders + gSteps * 4 # Rephasing readout gradient if (repeIndex == 0 or repeIndex >= dummyPulses): t0 = tEx + echoTime - rdGradTime / 2 - gradRiseTime - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, rdGradTime, rdGradAmplitude, gSteps, axes[0], shimming) orders = orders + gSteps * 2 # Rx gate if (repeIndex == 0 or repeIndex >= dummyPulses): t0 = tEx + echoTime - acqTime / 2 - addRdPoints / BW mri.rxGate(expt, t0, acqTime + 2 * addRdPoints / BW) acqPoints += nRD # Spoiler if spoiler: t0 = tEx + echoTime + rdGradTime / 2 + gradRiseTime - hw.gradDelay mri.gradTrap(expt, t0, gradRiseTime, dephGradTime, -rdDephAmplitude, gSteps, axes[0], shimming) orders = orders + gSteps * 2 # Update the phase and slice gradient if repeIndex >= dummyPulses: if phIndex == nPH - 1: phIndex = 0 slIndex += 1 else: phIndex += 1 if repeIndex >= dummyPulses: repeIndexGlobal += 1 # Update the global repeIndex repeIndex += 1 # Update the repeIndex after the ETL # Turn off the gradients after the end of the batch mri.endSequence(expt, repeIndex * repetitionTime) # Return the output variables return (phIndex, slIndex, repeIndexGlobal, acqPoints) # Calibrate frequency if (not demo) and freqCal and (not plotSeq): mri.freqCalibration(rawData, bw=0.05) mri.freqCalibration(rawData, bw=0.005) larmorFreq = rawData['larmorFreq'] * 1e-6 drfPhase = rawData['drfPhase'] # Initialize the experiment dataFull = [] dummyData = [] overData = [] noise = [] nBatches = 0 repeIndexArray = np.array([0]) repeIndexGlobal = repeIndexArray[0] phIndex = 0 slIndex = 0 acqPointsPerBatch = [] while repeIndexGlobal < nRepetitions: nBatches += 1 if not demo: expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] BW = 1 / samplingPeriod / hw.oversamplingFactor acqTime = nPoints[0] / BW # us phIndex, slIndex, repeIndexGlobal, aa = createSequence( phIndex=phIndex, slIndex=slIndex, repeIndexGlobal=repeIndexGlobal, rewrite=False) repeIndexArray = np.concatenate( (repeIndexArray, np.array([repeIndexGlobal - 1])), axis=0) acqPointsPerBatch.append(aa) expt.plot_sequence() else: phIndex, slIndex, repeIndexGlobal, aa, dataA = createSequenceDemo( phIndex=phIndex, slIndex=slIndex, repeIndexGlobal=repeIndexGlobal) repeIndexArray = np.concatenate( (repeIndexArray, np.array([repeIndexGlobal - 1])), axis=0) acqPointsPerBatch.append(aa) for ii in range(nScans): print('Batch ', nBatches, ', Scan ', ii, ' runing...') if not demo: if plotSeq == 1: # What is the meaning of plotSeq?? print('Ploting sequence...') expt.plot_sequence() plt.show() expt.__del__() break else: rxd, msgs = expt.run() rxd['rx0'] = rxd[ 'rx0'] * 13.788 # Here I normalize to get the result in mV # Get noise data noise = np.concatenate( (noise, rxd['rx0'][0:nRD * hw.oversamplingFactor]), axis=0) rxd['rx0'] = rxd['rx0'][nRD * hw.oversamplingFactor::] # Get data if dummyPulses > 0: dummyData = np.concatenate( (dummyData, rxd['rx0'][0:nRD * hw.oversamplingFactor]), axis=0) overData = np.concatenate( (overData, rxd['rx0'][nRD * hw.oversamplingFactor::]), axis=0) else: overData = np.concatenate((overData, rxd['rx0']), axis=0) else: data = dataA noise = np.concatenate( (noise, data[0:nRD * hw.oversamplingFactor]), axis=0) data = data[nRD * hw.oversamplingFactor::] # Get data if dummyPulses > 0: dummyData = np.concatenate( (dummyData, data[0:nRD * hw.oversamplingFactor]), axis=0) overData = np.concatenate( (overData, data[nRD * hw.oversamplingFactor::]), axis=0) else: overData = np.concatenate((overData, data), axis=0) if not demo: expt.__del__() if plotSeq == 1: break del aa if not plotSeq: acqPointsPerBatch = (acqPointsPerBatch - nRD * (dummyPulses > 0) - nRD) * nScans print('Scans done!') rawData['noiseData'] = noise rawData['overData'] = overData # Fix the echo position using oversampled data if dummyPulses > 0: dummyData = np.reshape( dummyData, (nBatches * nScans, 1, nRD * hw.oversamplingFactor)) dummyData = np.average(dummyData, axis=0) rawData['dummyData'] = dummyData overData = np.reshape(overData, (-1, 1, nRD * hw.oversamplingFactor)) overData = mri.fixEchoPosition(dummyData, overData) overData = np.reshape(overData, -1) # Generate dataFull dataFull = sig.decimate(overData, hw.oversamplingFactor, ftype='fir', zero_phase=True) if nBatches > 1: dataFullA = dataFull[0:sum(acqPointsPerBatch[0:-1])] dataFullB = dataFull[sum(acqPointsPerBatch[0:-1])::] # Reorganize dataFull dataProv = np.zeros([nScans, nSL * nPH * nRD]) dataProv = dataProv + 1j * dataProv dataFull = np.reshape(dataFull, (nBatches, nScans, -1, nRD)) if nBatches > 1: dataFullA = np.reshape(dataFullA, (nBatches - 1, nScans, -1, nRD)) dataFullB = np.reshape(dataFullB, (1, nScans, -1, nRD)) for scan in range(nScans): if nBatches > 1: dataProv[ii, :] = np.concatenate( (np.reshape(dataFullA[:, ii, :, :], -1), np.reshape(dataFullB[:, ii, :, :], -1)), axis=0) else: dataProv[ii, :] = np.reshape(dataFull[:, ii, :, :], -1) dataFull = np.reshape(dataProv, -1) # Get index for krd = 0 # Average data dataProv = np.reshape(dataFull, (nScans, nRD * nPH * nSL)) dataProv = np.average(dataProv, axis=0) dataProv = np.reshape(dataProv, (nSL, nPH, nRD)) # Check where is krd = 0 dataProv = dataProv[int(nPoints[2] / 2), int(nPH / 2), :] indkrd0 = np.argmax(np.abs(dataProv)) if indkrd0 < nRD / 2 - addRdPoints or indkrd0 > nRD / 2 + addRdPoints: indkrd0 = int(nRD / 2) # Get individual images dataFull = np.reshape(dataFull, (nScans, nSL, nPH, nRD)) dataFull = dataFull[:, :, :, indkrd0 - int(nPoints[0] / 2):indkrd0 + int(nPoints[0] / 2)] imgFull = dataFull * 0 for ii in range(nScans): imgFull[ii, :, :, :] = np.fft.ifftshift( np.fft.ifftn(np.fft.ifftshift(dataFull[ii, :, :, :]))) rawData['dataFull'] = dataFull rawData['imgFull'] = imgFull # Average data data = np.average(dataFull, axis=0) data = np.reshape(data, (nSL, nPH, nPoints[0])) # Do zero padding dataTemp = np.zeros((nPoints[2], nPoints[1], nPoints[0])) dataTemp = dataTemp + 1j * dataTemp dataTemp[0:nSL, :, :] = data data = np.reshape(dataTemp, (1, nPoints[0] * nPoints[1] * nPoints[2])) # Fix the position of the sample according to dfov kMax = np.array(nPoints) / (2 * np.array(fov)) * np.array(axesEnable) kRD = np.linspace(-kMax[0], kMax[0], num=nPoints[0], endpoint=False) # kPH = np.linspace(-kMax[1],kMax[1],num=nPoints[1],endpoint=False) kSL = np.linspace(-kMax[2], kMax[2], num=nPoints[2], endpoint=False) kPH = kPH[::-1] kPH, kSL, kRD = np.meshgrid(kPH, kSL, kRD) kRD = np.reshape(kRD, (1, nPoints[0] * nPoints[1] * nPoints[2])) kPH = np.reshape(kPH, (1, nPoints[0] * nPoints[1] * nPoints[2])) kSL = np.reshape(kSL, (1, nPoints[0] * nPoints[1] * nPoints[2])) dPhase = np.exp(-2 * np.pi * 1j * (dfov[0] * kRD + dfov[1] * kPH + dfov[2] * kSL)) data = np.reshape(data * dPhase, (nPoints[2], nPoints[1], nPoints[0])) rawData['kSpace3D'] = data img = np.fft.ifftshift(np.fft.ifftn(np.fft.ifftshift(data))) rawData['image3D'] = img data = np.reshape(data, (1, nPoints[0] * nPoints[1] * nPoints[2])) # Create sampled data kRD = np.reshape(kRD, (nPoints[0] * nPoints[1] * nPoints[2], 1)) kPH = np.reshape(kPH, (nPoints[0] * nPoints[1] * nPoints[2], 1)) kSL = np.reshape(kSL, (nPoints[0] * nPoints[1] * nPoints[2], 1)) data = np.reshape(data, (nPoints[0] * nPoints[1] * nPoints[2], 1)) rawData['kMax'] = kMax rawData['sampled'] = np.concatenate((kRD, kPH, kSL, data), axis=1) data = np.reshape(data, (nPoints[2], nPoints[1], nPoints[0])) # Save data mri.saveRawData(rawData) # Reshape to 0 dimensional data = np.reshape(data, -1) return rawData, msgs, data, BW
def fasttrStandalone( init_gpa=False, larmorFreq=3.07, # MHz # rfExAmp = 0.2, # RF amplitude in a.u. rfExAmp=0.2, rfExTime=10000, # us repetitionTime=0.1, # s nRepetitions=1): # number of samples # Inputs in fundamental units rfExTime = rfExTime * 1e-6 rawData = {} rawData['seqName'] = 'autoTuning' rawData['larmorFreq'] = larmorFreq * 1e6 rawData['rfExAmp'] = rfExAmp rawData['rfExTime'] = rfExTime rawData['repetitionTime'] = repetitionTime rawData['nRepetitions'] = nRepetitions # Miscellaneous shimming = np.array([0, 0, 0]) plt.ion() # Bandwidth and sampling rate bw = 0.06 # MHz bwov = bw * hw.oversamplingFactor samplingPeriod = 1 / bwov #******************************************************* def createSequence(): # Set shimming mri.iniSequence(expt, 20, shimming) t0 = 20 mri.rfRecPulse(expt, t0, rfExTime, rfExAmp, 0) # End sequence mri.endSequence(expt, rfExTime + 40) #******************************************************* #******************************************************* def ardToVolt(x): # Convert arduino inputs (in ascii format) to voltage (0 to 5 V) y = 0 for ii in range(len(x) - 2): y = y + (x[-3 - ii] - 48) * 10**ii return np.double(y / 1023 * 5) #******************************************************* # Time variables in us rfExTime *= 1e6 # Create all possible states states = np.array([0, 1]) nCapacitors = 10 nStates = 2**nCapacitors c2, c1, c3, c4, c5, c6, c7, c8, c9, c10 = np.meshgrid( states, states, states, states, states, states, states, states, states, states) c1 = np.reshape(c1, (nStates, 1)) c2 = np.reshape(c2, (nStates, 1)) c3 = np.reshape(c3, (nStates, 1)) c4 = np.reshape(c4, (nStates, 1)) c5 = np.reshape(c5, (nStates, 1)) c6 = np.reshape(c6, (nStates, 1)) c7 = np.reshape(c7, (nStates, 1)) c8 = np.reshape(c8, (nStates, 1)) c9 = np.reshape(c9, (nStates, 1)) c10 = np.reshape(c10, (nStates, 1)) states = np.concatenate((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10), axis=1) # Convert states to strings strStates = [] for ii in range(nStates): currentState = "" for jj in range(nCapacitors): currentState = currentState + str(states[ii, jj]) strStates.append(currentState) # Create experiment arduino = serial.Serial(port='/dev/ttyACM1', baudrate=9600, timeout=1.5) expt = ex.Experiment(lo_freq=larmorFreq, rx_t=samplingPeriod, init_gpa=init_gpa, gpa_fhdo_offset_time=(1 / 0.2 / 3.1)) samplingPeriod = expt.get_rx_ts()[0] # us bw = 1 / samplingPeriod / hw.oversamplingFactor # MHz createSequence() voltage = [] # Initialize the experiment with a few runs arduino.write(bytes(strStates[0], 'utf-8')) expt.run() data = arduino.readline() arduino.write(bytes(strStates[0], 'utf-8')) expt.run() data = arduino.readline() # Initialize figure plt.figure(1) plt.plot(0, 0, 'b.') plt.ylabel('Voltage (V)') plt.xlabel('Iteration') plt.xlim([0, nStates]) plt.show(block=False) plt.pause(0.01) # Sweep all states count = 0 t0 = time.time() for state in strStates: arduino.write(bytes( state, 'utf-8')) # Send current state through serial port to arduino. time.sleep(0.02) expt.run() # Run experiment data = arduino.readline( ) # After experiment is finished, read data stored in serial port voltage.append( ardToVolt(data)) # Convert data from (0-1023) to (0-5 V) print('Progress: %.2f %%, Voltage = %.3f V' % (count / nStates * 100, voltage[-1])) # Plots plt.plot(count, voltage[-1], 'b.') plt.show(block=False) plt.pause(0.01) # Delay to next repetition (Current version of RFPA needs 10% duty cycle) time.sleep(repetitionTime) count += 1 t1 = time.time() expt.__del__() print('Ready!') rawData['voltage'] = voltage rawData['states'] = strStates print('Elapsed time: %.0f s' % (t1 - t0)) # Get best state idx = np.argmin(voltage) arduino.write(bytes(strStates[idx], 'utf-8')) print('Best state: ', strStates[idx]) rawData['optState'] = strStates[idx] plt.plot(idx, voltage[idx], 'r.') # Save data mri.saveRawData(rawData) plt.title(rawData['fileName']) # Plots plt.show(block=True)