New experimetns added
This commit is contained in:
		
							
								
								
									
										176
									
								
								Scripts/EXSY/op_noesy_exp.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								Scripts/EXSY/op_noesy_exp.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | TXEnableDelay = 2e-6 | ||||||
|  | TXEnableValue = 0b0001  # TTL line enabling RF amplifier (bit 0) | ||||||
|  | TXPulseValue  = 0b0010  # TTL line triggering RF pulses  (bit 1) | ||||||
|  | ADCSensitivity = 2	# voltage span for ADC | ||||||
|  |  | ||||||
|  | def experiment(): # 2D NOESY experiment, using States-TPPI technique for quadrature detection in F1  | ||||||
|  |  | ||||||
|  |                   # States-TPPI technique achieves two effects for an indirect dimension F1:  | ||||||
|  |                   # (1) signal frequency discrimination and (2) displacement of the unmodulated  | ||||||
|  |                   # artefact signal from an inconvenient location in the middle of spectrum to the edge. | ||||||
|  |                   # (1) is achieved by recording two data sets at each t1 point - with orthogonal phases  | ||||||
|  |                   # of the preparation pulse and same receiver phase - and storing them in separate memory  | ||||||
|  |                   # locations. These two fid measurements yield one complex data point in F1. | ||||||
|  |                   # (2) by inverting phase of the preparation pulse and the receiver each time when t1 is  | ||||||
|  |                   # incremented (that is for subsequent complex points). Therefore, the artefact signal  | ||||||
|  |                   # becomes modulated at the Nyquist frequency and appears in the spectrum at F1=<3D>SW/2 Hz  | ||||||
|  |                   # instead of 0 Hz, where SW is spectral width. [http://nmrwiki.org] | ||||||
|  |      | ||||||
|  |     # set up acqusition parameters:       | ||||||
|  |     pars = {} | ||||||
|  |     pars['P90'] = 1.65e-6           # 90-degree pulse length (s) | ||||||
|  |     pars['SF'] = 338.7e6            # spectrometer frequency (Hz) | ||||||
|  |     pars['O1'] = -57.0e3            # offset from SF (Hz) | ||||||
|  |     pars['SW'] = 150e3              # spectral width (Hz) | ||||||
|  |     pars['SI1'] = 32                # number of (complex) data points in F1 (2D) | ||||||
|  |     pars['SI2'] = 128               # number of (complex) data points in F2 | ||||||
|  |     pars['D8'] = 100e-6             # mixing time, tm (s) | ||||||
|  |     pars['NS'] = 16                 # number of scans | ||||||
|  |     pars['DS'] = 0                  # number of dummy scans | ||||||
|  |     pars['RD'] = 2.5                # delay between scans (s) | ||||||
|  |     pars['DEAD1'] = 4e-6            # receiver dead time (s)   | ||||||
|  |     pars['PHA'] = 150               # receiver reference phase (degree) | ||||||
|  |     pars['DATADIR'] = '/home/fprak/'    # data directory | ||||||
|  |     pars['OUTFILE'] = 'test'                # output file name | ||||||
|  |      | ||||||
|  |     # specify a variable parameter (optional): | ||||||
|  |     pars['VAR_PAR'] = 'D8'	# variable parameter name (a string)    | ||||||
|  |     start = 10.e-6		# starting value | ||||||
|  |     stop = 1000e-6 		# end value | ||||||
|  |     steps = 3			# number of values | ||||||
|  |     log_scale = True		# log scale flag  | ||||||
|  |     stag_range = False		# staggered range flag | ||||||
|  |      | ||||||
|  |     # check parameters for safety:      | ||||||
|  |     if pars['PHA'] < 0: | ||||||
|  |         pars['PHA'] = 360 + pars['PHA'] | ||||||
|  |          | ||||||
|  |     if pars['P90'] > 20e-6: | ||||||
|  |         raise Exception("Pulse too long!!!")    | ||||||
|  |                           | ||||||
|  |     var_key = pars.get('VAR_PAR') | ||||||
|  |     if var_key == 'P90' and (start > 20e-6 or stop > 20e-6): | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     if pars['NS']%8 != 0: | ||||||
|  |         pars['NS'] = (pars['NS'] / 8 + 1) * 8  | ||||||
|  |         print 'Number of scans changed to', pars['NS'], 'due to phase cycling' | ||||||
|  |          | ||||||
|  |     # start the experiment: | ||||||
|  |     if var_key:  | ||||||
|  |         # this is an arrayed experiment: | ||||||
|  |         if log_scale: | ||||||
|  |             array = log_range(start,stop,steps) | ||||||
|  |         else: | ||||||
|  |             array = lin_range(start,stop,steps)  | ||||||
|  |          | ||||||
|  |         if stag_range: | ||||||
|  |             array = staggered_range(array, size=2) | ||||||
|  |  | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         if var_key == 'D8': | ||||||
|  |             seconds = (sum(array) + (.5*pars['SI1']/pars['SW'] + pars['RD']) * steps) * (pars['NS'] + pars['DS']) * 2*pars['SI1'] | ||||||
|  |         elif var_key == 'RD': | ||||||
|  |             seconds = (sum(array) + (.5*pars['SI1']/pars['SW'] + pars['D8']) * steps) * (pars['NS'] + pars['DS']) * 2*pars['SI1'] | ||||||
|  |         else: | ||||||
|  |             seconds = (.5*pars['SI1']/pars['SW'] + pars['D8'] + pars['RD']) * steps * (pars['NS']+ pars['DS']) * 2*pars['SI1'] | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         # loop for a variable parameter: | ||||||
|  |         for index, pars[var_key] in enumerate(array): | ||||||
|  |             print 'Arrayed experiment for '+var_key+': run = '+str(index+1)+\ | ||||||
|  |                                 ' out of '+str(array.size)+': value = '+str(pars[var_key]) | ||||||
|  |             # loop for accumulation and sampling the indirect dimension F1: | ||||||
|  |             for run in xrange((pars['NS']+pars['DS'])*2*pars['SI1']): | ||||||
|  |                 yield noesyst_experiment(pars, run) | ||||||
|  |             synchronize()  | ||||||
|  |  | ||||||
|  |     else: | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         seconds = (.5*pars['SI1']/pars['SW'] + pars['D8'] + pars['RD']) * (pars['NS']+ pars['DS']) * 2*pars['SI1'] | ||||||
|  |         print 'sec ', seconds | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |        # loop for accumulation and sampling the indirect dimension F1: | ||||||
|  |         for run in xrange((pars['NS']+pars['DS'])*2*pars['SI1']): | ||||||
|  |             yield noesyst_experiment(pars, run) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # the pulse program:  | ||||||
|  |  | ||||||
|  | def noesyst_experiment(pars, run): | ||||||
|  |     e=Experiment() | ||||||
|  |  | ||||||
|  |     dummy_scans = pars.get('DS') | ||||||
|  |     if dummy_scans: | ||||||
|  |         run -= dummy_scans | ||||||
|  |      | ||||||
|  |     # phase lists (M.H.Levitt 'Spin Dynamics', 2nd edition, p.530):  | ||||||
|  |     pars['PH1'] = [  0, 180,   0, 180,   0, 180,   0, 180]	 | ||||||
|  |     pars['PH3'] = [180, 180, 180, 180, 180, 180, 180, 180] | ||||||
|  |     pars['PH4'] = [  0,   0,  90,  90, 180, 180, 270, 270]	 | ||||||
|  |     pars['PH2'] = [  0, 180,  90, 270, 180,   0, 270,  90]    # receiver | ||||||
|  |  | ||||||
|  |     # read in variables: | ||||||
|  |     P90 = pars['P90']  | ||||||
|  |     SF = pars['SF'] | ||||||
|  |     O1 = pars['O1']    | ||||||
|  |     RD = pars['RD'] | ||||||
|  |     DEAD1 = pars['DEAD1'] | ||||||
|  |     D8 = pars['D8'] | ||||||
|  |     NS = pars['NS'] | ||||||
|  |     PH1 = pars['PH1'][run%len(pars['PH1'])] | ||||||
|  |     PH3 = pars['PH3'][run%len(pars['PH3'])] | ||||||
|  |     PH4 = pars['PH4'][run%len(pars['PH4'])] | ||||||
|  |     PH2 = pars['PH2'][run%len(pars['PH2'])]  | ||||||
|  |     PHA = pars['PHA'] | ||||||
|  |          | ||||||
|  |     # F1 sampling parameters: | ||||||
|  |     IN0 = 1./pars['SW']        # t1 increment | ||||||
|  |      | ||||||
|  |     # the States-TPPI bit: | ||||||
|  |     PH1-= (run/(1*NS))%4*90    # PH1 changes by 90-deg. after every 1*NS scans | ||||||
|  |     D0  = (run/(2*NS)) *IN0    # t1 increases by IN0 after every 2*NS scans    | ||||||
|  |      | ||||||
|  |     # F2 sampling parameters: | ||||||
|  |     SI2 = pars['SI2'] | ||||||
|  |     SW2 = pars['SW'] | ||||||
|  |     while SW2 <= 10e6 and SI2 < 256*1024: | ||||||
|  |         SI2 *= 2 | ||||||
|  |         SW2 *= 2 | ||||||
|  |          | ||||||
|  |     # run the pulse sequence:  | ||||||
|  |     e.wait(RD)                                  	# delay between scans | ||||||
|  |     e.set_frequency(SF+O1, phase=PH1) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D0)                                          # incremented delay t1 | ||||||
|  |     e.set_phase(PH3) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D8)                  	              	# mixing time | ||||||
|  |     e.set_phase(PH4) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse | ||||||
|  |     e.set_phase(PHA)                                    # set phase for receiver  | ||||||
|  |     e.wait(DEAD1)                                       # wait for coil ringdown | ||||||
|  |     e.record(SI2, SW2, sensitivity=ADCSensitivity)     	# acquire signal | ||||||
|  |  | ||||||
|  |     # write experiment attributes:   | ||||||
|  |     for key in pars.keys(): | ||||||
|  |         e.set_description(key, pars[key])		# acqusition parameters | ||||||
|  |     e.set_description('run', run)               	# current scan | ||||||
|  |     e.set_description('rec_phase', -PH2)		# current receiver phase | ||||||
|  |  | ||||||
|  |     return e | ||||||
							
								
								
									
										157
									
								
								Scripts/EXSY/op_noesy_res.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								Scripts/EXSY/op_noesy_res.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | from numpy import * | ||||||
|  | from scipy.signal import * | ||||||
|  | from scipy.optimize import * | ||||||
|  | from os import path, rename | ||||||
|  |  | ||||||
|  | def result(): | ||||||
|  |      | ||||||
|  |     measurement = MeasurementResult('Magnetization') | ||||||
|  |  | ||||||
|  |     measurement_range = [0.0, 10e-6] | ||||||
|  |     measurement_ranging = False | ||||||
|  |      | ||||||
|  |     suffix = '' 	# output file name's suffix and... | ||||||
|  |     counter = 0         # counter for arrayed 2D experiments | ||||||
|  |  | ||||||
|  |     # loop over the incoming results:  | ||||||
|  |     for timesignal in results: | ||||||
|  |         if not isinstance(timesignal,ADC_Result):  | ||||||
|  |             continue | ||||||
|  |  | ||||||
|  |         # read experiment parameters: | ||||||
|  |         pars = timesignal.get_description_dictionary() | ||||||
|  |  | ||||||
|  |         # ---------------- digital filter ------------------  | ||||||
|  |               | ||||||
|  |         # get actual sampling rate of timesignal: | ||||||
|  |         sampling_rate = timesignal.get_sampling_rate() | ||||||
|  |  | ||||||
|  |         # get user-defined spectrum width: | ||||||
|  |         spec_width = pars['SW'] | ||||||
|  |          | ||||||
|  |         # specify cutoff frequency, in relative units: | ||||||
|  |         cutoff = spec_width / sampling_rate | ||||||
|  |                  | ||||||
|  |         if cutoff < 1: # otherwise no filter applied | ||||||
|  |  | ||||||
|  |             # number of filter's coefficients: | ||||||
|  |             numtaps = 29 | ||||||
|  |              | ||||||
|  |             # use firwin to create a lowpass FIR filter: | ||||||
|  |             fir_coeff = firwin(numtaps, cutoff) | ||||||
|  |              | ||||||
|  |             # downsize x according to user-defined spectral window: | ||||||
|  |             skip = int(sampling_rate / spec_width) | ||||||
|  |             timesignal.x = timesignal.x[::skip] | ||||||
|  |              | ||||||
|  |             for i in range(2): | ||||||
|  |                 # apply the filter to ith channel: | ||||||
|  |                 timesignal.y[i] = lfilter(fir_coeff, 1.0, timesignal.y[i]) | ||||||
|  |  | ||||||
|  |                 # zeroize first N-1 "corrupted" samples: | ||||||
|  |                 timesignal.y[i][:numtaps-1] = 0.0 | ||||||
|  |  | ||||||
|  |                 # circular left shift of y: | ||||||
|  |                 timesignal.y[i] = roll(timesignal.y[i], -(numtaps-1))     | ||||||
|  |  | ||||||
|  |                 # downsize y to user-defined number of samples (SI): | ||||||
|  |                 timesignal.y[i] = timesignal.y[i][::skip] | ||||||
|  |  | ||||||
|  |             # update the sampling_rate attribute of the signal's: | ||||||
|  |             timesignal.set_sampling_rate(spec_width) | ||||||
|  |  | ||||||
|  |         # ---------------------------------------------------- | ||||||
|  |  | ||||||
|  |         # rotate timesignal according to current receiver's phase: | ||||||
|  |         timesignal.phase(pars['rec_phase']) | ||||||
|  |  | ||||||
|  |         # provide timesignal to the display tab: | ||||||
|  |         data['Current scan'] = timesignal | ||||||
|  |  | ||||||
|  |         # accumulate... | ||||||
|  |         if not locals().get('accu'): | ||||||
|  |             accu = Accumulation() | ||||||
|  |  | ||||||
|  |         # skip dummy scans, if any: | ||||||
|  |         if pars['run'] < 0: continue | ||||||
|  |  | ||||||
|  |         # add up: | ||||||
|  |         accu += timesignal | ||||||
|  |  | ||||||
|  |         # provide accumulation to the display tab: | ||||||
|  |         data['Accumulation'] = accu | ||||||
|  |  | ||||||
|  |         # check whether accumulation is complete: | ||||||
|  |         # ---------------------------------------------------------------------------------------- | ||||||
|  |         # Note that State-TPPI technique implies recording two data sets at each t1 point. | ||||||
|  |         # Cosine-modulated data are stored in record 1 as Re, and sine-modulated data are stored | ||||||
|  |         # in record 2 as Im, totally 2*SI1 records. Henceforth, accu represents one such a record. | ||||||
|  |         # ----------------------------------------------------------------------------------------- | ||||||
|  |         if accu.n == pars['NS']: | ||||||
|  |  | ||||||
|  |             # make a copy: | ||||||
|  |             fid = accu + 0 | ||||||
|  |  | ||||||
|  |             # compute the initial phase of FID: | ||||||
|  |             phi0 = arctan2(fid.y[1][0], fid.y[0][0]) * 180 / pi | ||||||
|  |             if not 'ref' in locals(): ref = phi0    | ||||||
|  |            # print 'phi0 = ', phi0 | ||||||
|  |  | ||||||
|  |             # rotate FID to maximize y[0][0]:      | ||||||
|  |             #echo.phase(-phi0)  | ||||||
|  |  | ||||||
|  |             # check whether it is an arrayed experiment:  | ||||||
|  |             var_key = pars.get('VAR_PAR') | ||||||
|  |             if var_key: | ||||||
|  |                 # get variable parameter's value: | ||||||
|  |                 var_value = pars.get(var_key) | ||||||
|  |                  | ||||||
|  |                 # provide signal recorded with this var_value to the display tab: | ||||||
|  |                 data['Accumulation'+"/"+var_key+"=%e"%(var_value)] = accu                 | ||||||
|  |  | ||||||
|  |                 # measure signal intensity vs. var_value: | ||||||
|  |                 if measurement_ranging == True: | ||||||
|  |                    [start, stop] = accu.get_sampling_rate() * array(measurement_range) | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][int(start):int(stop)])  | ||||||
|  |                     | ||||||
|  |                 else: | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][0:31]) | ||||||
|  |                     | ||||||
|  |                 # provide measurement to the display tab: | ||||||
|  |                 data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  |                 # update the file name suffix: | ||||||
|  |                 counter2D = counter/(2*pars['SI1'])+1 | ||||||
|  |                 suffix = '_' + str(counter2D) | ||||||
|  |                 counter += 1 | ||||||
|  |  | ||||||
|  |             # save accu if required: | ||||||
|  |             outfile = pars.get('OUTFILE') | ||||||
|  |             if outfile:  | ||||||
|  |                 datadir = pars.get('DATADIR') | ||||||
|  |  | ||||||
|  |                 # write raw data in Tecmag format: | ||||||
|  |                 filename = datadir+outfile+suffix+'.tnt' | ||||||
|  |                 accu.write_to_tecmag(filename,\ | ||||||
|  |                                      nrecords=2*pars['SI1'],\ | ||||||
|  |                                      frequency=pars['SW']+pars['O1']) | ||||||
|  |  | ||||||
|  |                # write parameters in a text file: | ||||||
|  |                 filename = datadir+outfile+suffix+'.par'  | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.par') | ||||||
|  |  | ||||||
|  |                 fileobject = open(filename, 'w') | ||||||
|  |                 for key in sorted(pars.iterkeys()): | ||||||
|  |                     if key=='run': continue | ||||||
|  |                     if key=='rec_phase': continue | ||||||
|  |                     fileobject.write('%s%s%s'%(key,'=', pars[key])) | ||||||
|  |                     fileobject.write('\n') | ||||||
|  |                 fileobject.close() | ||||||
|  |  | ||||||
|  |             # reset accumulation: | ||||||
|  |             del accu | ||||||
|  |  | ||||||
|  | pass | ||||||
							
								
								
									
										194
									
								
								Scripts/EXSY_2H/op_exsy2h_exp.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								Scripts/EXSY_2H/op_exsy2h_exp.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | TXEnableDelay = 0.5e-6 | ||||||
|  | TXEnableValue = 0b0001  # TTL line blanking RF amplifier (bit 0) | ||||||
|  | TXPulseValue  = 0b0010  # TTL line triggering RF pulses  (bit 1) | ||||||
|  | ADCSensitivity = 1	# voltage span for ADC | ||||||
|  |  | ||||||
|  | def experiment(): # 2H Exchange Spectroscopy (2H EXSY) experiment [JMR 79, 269-290 (1988)] | ||||||
|  |  | ||||||
|  |                   # Cosine and sine modulated signals are acquired sequentially by switching  | ||||||
|  |                   # between Zeeman order and spin-alignment phase lists. The signals are  | ||||||
|  |                   # processed into a pure absorption mode 2D spectrum according to scheme by | ||||||
|  |                   # [Bluemich, Schmidt, and Spiess, JMR 79, 269-290 (1988)]. Prior to writing | ||||||
|  |                   # in a file (Tecmag), the sine-modulated signal is rotated by 90<39>, thus  | ||||||
|  |                   # enabling 2D processing via a regular States algorithm with NMRnotebook | ||||||
|  |                   # or like NMR software. | ||||||
|  |  | ||||||
|  |   # set up acquisition parameters:          | ||||||
|  |     pars = {} | ||||||
|  |     pars['P90'] = 2.7e-6        # 90<39>-pulse length (s) | ||||||
|  |     pars['SF'] = 46.140e6 	# spectrometer frequency (Hz) | ||||||
|  |     pars['O1'] = 1000		# offset from SF (Hz) | ||||||
|  |     pars['SW'] = 125e3		# spectral window (Hz) | ||||||
|  |     pars['SI1'] = 80            # number of (complex) data points in F1 (2nd dimension) | ||||||
|  |     pars['SI2'] = 1*256         # number of (complex) data points in F2 | ||||||
|  |     pars['D3'] = 10e-6          # position of refocusing 90<39>-pulse, Delta (s) | ||||||
|  |     pars['D4'] = 2e-6           # pre-aquisition delay (s)     | ||||||
|  |     pars['D8'] = 3e-3	  	# mixing time, tm (s) | ||||||
|  |     pars['NS'] = 512		# number of scans | ||||||
|  |     pars['DS'] = 0		# number of dummy scans | ||||||
|  |     pars['RD'] = 0.2		# delay between scans (s) | ||||||
|  |     pars['PHA'] = 65		# receiver reference phase (degree) | ||||||
|  |     pars['DATADIR'] = '/home/mathilda/Desktop/Oleg/temp/'	# data directory | ||||||
|  |     pars['OUTFILE'] = 'dso_320K'			# output file name | ||||||
|  |  | ||||||
|  |   # specify a variable parameter (optional): | ||||||
|  |     pars['VAR_PAR'] = None	# variable parameter's name (a string) | ||||||
|  |     start = 80         	# starting value | ||||||
|  |     stop = 128			# end value | ||||||
|  |     steps = 2			# number of values | ||||||
|  |     log_scale = False		# log scale flag  | ||||||
|  |     stag_range = False		# staggered range flag | ||||||
|  |  | ||||||
|  |   # check parameters for safety: | ||||||
|  |     if pars['PHA'] < 0: | ||||||
|  |         pars['PHA'] = 360 + pars['PHA'] | ||||||
|  |          | ||||||
|  |     if pars['P90'] > 20e-6: | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |                      | ||||||
|  |     # check whether a variable parameter is named:  | ||||||
|  |     var_key = pars.get('VAR_PAR') | ||||||
|  |     if var_key == 'P90' and (start > 20e-6 or stop > 20e-6): | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     if pars['NS']%16 != 0: | ||||||
|  |         pars['NS'] = int(round(pars['NS'] / 32) + 1) * 32  | ||||||
|  |         print 'Number of scans changed to ', pars['NS'], ' due to phase cycling' | ||||||
|  |  | ||||||
|  |     # start the experiment: | ||||||
|  |     if var_key:  | ||||||
|  |         # this is an arrayed experiment: | ||||||
|  |         if log_scale: | ||||||
|  |             array = log_range(start,stop,steps) | ||||||
|  |         else: | ||||||
|  |             array = lin_range(start,stop,steps)  | ||||||
|  |          | ||||||
|  |         if stag_range: | ||||||
|  |             array = staggered_range(array, size = 2) | ||||||
|  |  | ||||||
|  |         # estimate the experiment time: | ||||||
|  |         if var_key == 'D8': | ||||||
|  |             seconds = (sum(array) + (.5*pars['SI1']/pars['SW'] + pars['RD']) * steps) * (pars['NS'] + pars['DS']) * 2*pars['SI1'] | ||||||
|  |         elif var_key == 'RD': | ||||||
|  |             seconds = (sum(array) + (.5*pars['SI1']/pars['SW'] + pars['D8']) * steps) * (pars['NS'] + pars['DS']) * 2*pars['SI1'] | ||||||
|  |         else: | ||||||
|  |             seconds = (.5*pars['SI1']/pars['SW'] + pars['D8'] + pars['RD']) * steps * (pars['NS']+ pars['DS']) * 2*pars['SI1'] | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |         # loop for a variable parameter: | ||||||
|  |         for index, pars[var_key] in enumerate(array): | ||||||
|  |             print 'Arrayed experiment for '+var_key+': run = '+str(index+1)+\ | ||||||
|  |                                 ' out of '+str(array.size)+': value = '+str(pars[var_key]) | ||||||
|  |             # loop for accumulation and sampling the indirect dimension F1: | ||||||
|  |             for run in xrange((pars['NS']+pars['DS'])*2*pars['SI1']): | ||||||
|  |                 yield exsy2h_experiment(pars, run) | ||||||
|  |             synchronize()  | ||||||
|  |  | ||||||
|  |     else: | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         seconds = (.5*pars['SI1']/pars['SW'] + pars['D8'] + pars['RD']) * (pars['NS']+ pars['DS']) * 2*pars['SI1'] | ||||||
|  |         print 'sec ', seconds | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |        # loop for accumulation and sampling the indirect dimension F1: | ||||||
|  |         for run in xrange((pars['NS']+pars['DS'])*2*pars['SI1']): | ||||||
|  |             yield exsy2h_experiment(pars, run) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # the pulse program:  | ||||||
|  |  | ||||||
|  | def exsy2h_experiment(pars, run): | ||||||
|  |     e=Experiment() | ||||||
|  |  | ||||||
|  |     dummy_scans = pars.get('DS') | ||||||
|  |     if dummy_scans: | ||||||
|  |         run -= dummy_scans | ||||||
|  |                         | ||||||
|  |     pars['PROG'] = 'exsy2h_experiment'    | ||||||
|  |          | ||||||
|  |             # 8-step phase cycle (1-21) modifided to deal with T1-recovery and extended for Re/Im imbalance) | ||||||
|  |     pars['PH1'] = [0, 270,   0, 270,   180,  90, 180,  90] # 1st pulse (90<39>) | ||||||
|  |     pars['PH3'] = [0,  90,   0,  90,     0,  90,   0,  90] # 2nd pulse (57.4<EFBFBD>) | ||||||
|  |     pars['PH4'] = [0,   0, 180, 180,   270, 270,  90,  90] # 3rd pulse (57.4<EFBFBD>) | ||||||
|  |     pars['PH5'] = [90, 90,  90,  90,   180, 180, 180, 180] # 4th pulse (90<39>) | ||||||
|  |     pars['PH2'] = [0, 180, 180,   0,    90, 270, 270,  90] # receiver | ||||||
|  |   | ||||||
|  |   # read in variables: | ||||||
|  |     P90 = pars['P90'] | ||||||
|  |     P1  = pars['P90']*(54.7/90) | ||||||
|  |     SF =  pars['SF'] | ||||||
|  |     O1 =  pars['O1']     | ||||||
|  |     RD =  pars['RD'] | ||||||
|  |     D4 =  pars['D4'] | ||||||
|  |     D8 =  pars['D8'] | ||||||
|  |     D3 =  pars['D3'] | ||||||
|  |     NS =  pars['NS'] | ||||||
|  |     PH1 = pars['PH1'][run%len(pars['PH1'])] | ||||||
|  |     PH3 = pars['PH3'][run%len(pars['PH3'])] | ||||||
|  |     PH4 = pars['PH4'][run%len(pars['PH4'])] | ||||||
|  |     PH5 = pars['PH5'][run%len(pars['PH5'])] | ||||||
|  |     PH2 = pars['PH2'][run%len(pars['PH2'])] | ||||||
|  |     PHA = pars['PHA'] | ||||||
|  |   | ||||||
|  |     # this is a part of phase cycling:   | ||||||
|  |     PH5 += (run/len(pars['PH5']))%2*180  | ||||||
|  |     PH1 += (run/len(pars['PH5']))%2*180  | ||||||
|  |     PH2 += (run/len(pars['PH5']))%2*180  | ||||||
|  |      | ||||||
|  |     # F1 sampling parameters: | ||||||
|  |     IN0 = 1./pars['SW'] 	# t1 increment | ||||||
|  |      | ||||||
|  |     # F1 sampling scheme: | ||||||
|  |     PH3+= (run/(1*NS))%4*90     # phases are upgraded after every NS scans | ||||||
|  |     PH4+= (run/(1*NS))%4*90  | ||||||
|  |     D0 =  (run/(2*NS)) *IN0     # t1 is incremented after every 2*NS scans | ||||||
|  |      | ||||||
|  |     # F2 sampling parameters: | ||||||
|  |     SI2 = pars['SI2'] | ||||||
|  |     SW2 = pars['SW'] | ||||||
|  |     while SW2 <= 10e6 and SI2 < 256*1024: | ||||||
|  |         SI2 *= 2 | ||||||
|  |         SW2 *= 2 | ||||||
|  |      | ||||||
|  |    # run the pulse sequence: | ||||||
|  |     e.wait(RD)						# relaxation delay between scans | ||||||
|  |     e.set_frequency(SF+O1, phase=PH1) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)  # 90<39>-pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D0)  	                   	      	# incremented delay, t1 | ||||||
|  |     e.set_phase(PH3) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P1, value=TXEnableValue|TXPulseValue)   # 54.7<EFBFBD>-pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D8)          	                 	# mixing time, tm | ||||||
|  |     e.set_phase(PH4) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P1, value=TXEnableValue|TXPulseValue)	# 54.7<EFBFBD>-pulse | ||||||
|  |  | ||||||
|  |     e.wait(D3)                                          # refocusing delay, Delta | ||||||
|  |      | ||||||
|  |     e.set_phase(PH5) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)  # 90<39>-pulse | ||||||
|  |  | ||||||
|  |     e.wait(TXEnableDelay) | ||||||
|  |     e.set_phase(PHA) | ||||||
|  |     e.wait(D3+D4)               	      	        # pre-aquisition delay | ||||||
|  |     e.record(SI2, SW2, sensitivity=ADCSensitivity)      # acquisition   | ||||||
|  |     | ||||||
|  |    # write experiment parameters: | ||||||
|  |     for key in pars.keys(): | ||||||
|  |         e.set_description(key, pars[key])	# acquisition parameters | ||||||
|  |     e.set_description('run', run)		# current scan | ||||||
|  |     e.set_description('rec_phase', -PH2)	# current receiver phase | ||||||
|  |  | ||||||
|  |     return e | ||||||
							
								
								
									
										170
									
								
								Scripts/EXSY_2H/op_exsy2h_res.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								Scripts/EXSY_2H/op_exsy2h_res.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | from numpy import * | ||||||
|  | from scipy.signal import * | ||||||
|  | from scipy.optimize import * | ||||||
|  | from scipy.fftpack import fft, ifft | ||||||
|  | from os import path, rename | ||||||
|  |  | ||||||
|  | def result(): | ||||||
|  |      | ||||||
|  |     measurement = MeasurementResult('Magnetization') | ||||||
|  |  | ||||||
|  |     measurement_range = [0.0, 10e-6] | ||||||
|  |     measurement_ranging = False | ||||||
|  |      | ||||||
|  |     suffix = '' 	# output file name's suffix and... | ||||||
|  |     counter = 0         # counter for arrayed 2D experiments | ||||||
|  |  #   npts = 0 | ||||||
|  |  | ||||||
|  |     # loop over the incoming results:  | ||||||
|  |     for timesignal in results: | ||||||
|  |         if not isinstance(timesignal,ADC_Result):  | ||||||
|  |             continue | ||||||
|  |  | ||||||
|  |         # read experiment parameters: | ||||||
|  |         pars = timesignal.get_description_dictionary() | ||||||
|  |  | ||||||
|  |         # ---------------- digital filter ------------------  | ||||||
|  |               | ||||||
|  |         # get actual sampling rate of timesignal: | ||||||
|  |         sampling_rate = timesignal.get_sampling_rate() | ||||||
|  |  | ||||||
|  |         # get user-defined spectrum width: | ||||||
|  |         spec_width = pars['SW'] | ||||||
|  |          | ||||||
|  |         # specify cutoff frequency, in relative units: | ||||||
|  |         cutoff = spec_width / sampling_rate | ||||||
|  |                  | ||||||
|  |         if cutoff < 1: # otherwise no filter applied | ||||||
|  |  | ||||||
|  |             # number of filter's coefficients: | ||||||
|  |             numtaps = 29 | ||||||
|  |              | ||||||
|  |             # use firwin to create a lowpass FIR filter: | ||||||
|  |             fir_coeff = firwin(numtaps, cutoff) | ||||||
|  |              | ||||||
|  |             # downsize x according to user-defined spectral window: | ||||||
|  |             skip = int(sampling_rate / spec_width) | ||||||
|  |             timesignal.x = timesignal.x[::skip] | ||||||
|  |              | ||||||
|  |             for i in range(2): | ||||||
|  |                 # apply the filter to ith channel: | ||||||
|  |                 timesignal.y[i] = lfilter(fir_coeff, 1.0, timesignal.y[i]) | ||||||
|  |  | ||||||
|  |                 # zeroize first N-1 "corrupted" samples: | ||||||
|  |                 timesignal.y[i][:numtaps-1] = 0.0 | ||||||
|  |  | ||||||
|  |                 # circular left shift of y: | ||||||
|  |                 timesignal.y[i] = roll(timesignal.y[i], -(numtaps-1))     | ||||||
|  |  | ||||||
|  |                 # downsize y to user-defined number of samples (SI): | ||||||
|  |                 timesignal.y[i] = timesignal.y[i][::skip] | ||||||
|  |  | ||||||
|  |             # update the sampling_rate attribute of the signal's: | ||||||
|  |             timesignal.set_sampling_rate(spec_width) | ||||||
|  |  | ||||||
|  |         # ---------------------------------------------------- | ||||||
|  |  | ||||||
|  |         # rotate timesignal according to current receiver's phase: | ||||||
|  |         timesignal.phase(pars['rec_phase']) | ||||||
|  |  | ||||||
|  |         # provide timesignal to the display tab: | ||||||
|  |         data['Current scan'] = timesignal | ||||||
|  |  | ||||||
|  |         # accumulate... | ||||||
|  |         if not locals().get('accu'): | ||||||
|  |             accu = Accumulation() | ||||||
|  |  | ||||||
|  |         # skip dummy scans, if any: | ||||||
|  |         if pars['run'] < 0: continue | ||||||
|  |  | ||||||
|  |         # add up: | ||||||
|  |         accu += timesignal | ||||||
|  |  | ||||||
|  |         # provide accumulation to the display tab: | ||||||
|  |         data['Accumulation'] = accu | ||||||
|  |  | ||||||
|  |         # check whether accumulation is complete: | ||||||
|  |         # ------------------------------------------------------------------------------------     | ||||||
|  |         # The hypercomplex technique implies recording two data sets for each t1 value. | ||||||
|  |         # One dataset (a cosine-modulated signal) is stored in odd records as Re, while | ||||||
|  | 		# the other dataset (a sine-modulated signal) in even records as Im, totally 2*SI1  | ||||||
|  | 		# records. Henceforth, accu represents one such a record. | ||||||
|  |         # ------------------------------------------------------------------------------------ | ||||||
|  |         if accu.n == pars['NS']: | ||||||
|  |             # compute the initial phase of FID: | ||||||
|  |             phi0 = arctan2(accu.y[1][0], accu.y[0][0]) * 180 / pi | ||||||
|  |             if not 'ref' in locals(): ref = phi0    | ||||||
|  |             print 'phi0 = ', phi0 | ||||||
|  |              | ||||||
|  |             # rotate every other record by 90<39> so that States algorithm is applicable:      | ||||||
|  |             rec = (accu.job_id/accu.n)%(2*pars['SI1']) + 1 | ||||||
|  |             if rec%2 == 0: | ||||||
|  |                 accu.phase(90) | ||||||
|  |                 coeff = 1.5			 | ||||||
|  |                 accu.y[0] *= coeff  # XY-balancing | ||||||
|  |                 accu.y[1] *= coeff    | ||||||
|  | 			 | ||||||
|  |             else: # baseline correction ))))) | ||||||
|  |                 tmp = fft(accu.y[0]+1j*accu.y[1]) | ||||||
|  |                 [start, stop] = len(accu.y[0])*array([0.4, 0.6]) | ||||||
|  |                 tmp -= mean(tmp.real[start:stop])	 | ||||||
|  |                 tmp = ifft(tmp) | ||||||
|  |                 accu.y[0] = tmp.real | ||||||
|  |                 accu.y[1] = tmp.imag        				 | ||||||
|  |                   | ||||||
|  |             # check whether it is an arrayed experiment:  | ||||||
|  |             var_key = pars.get('VAR_PAR') | ||||||
|  |             if var_key: | ||||||
|  |                 # get variable parameter's value: | ||||||
|  |                 var_value = pars.get(var_key) | ||||||
|  |                  | ||||||
|  |                 # provide signal recorded with this var_value to the display tab: | ||||||
|  |                 data['Accumulation'+"/"+var_key+"=%e"%(var_value)] = accu                 | ||||||
|  |  | ||||||
|  |                 # measure signal intensity vs. var_value: | ||||||
|  |                 if measurement_ranging == True: | ||||||
|  |                    [start, stop] = accu.get_sampling_rate() * array(measurement_range) | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][int(start):int(stop)])  | ||||||
|  |                     | ||||||
|  |                 else: | ||||||
|  |                   # measurement[var_value] = sum(accu.y[0][0:31]) | ||||||
|  |                    measurement[var_value+counter*1e-6] = sum(accu.y[0][0:31]) | ||||||
|  |                     | ||||||
|  |                 # provide measurement to the display tab: | ||||||
|  |                 data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  |                 # update the file name suffix: | ||||||
|  |                 counter2D = counter/(2*pars['SI1'])+1 | ||||||
|  |                 suffix = '_' + str(counter2D) | ||||||
|  |                 counter += 1 | ||||||
|  |  | ||||||
|  |             # save accu if required: | ||||||
|  |             outfile = pars.get('OUTFILE') | ||||||
|  |             if outfile:  | ||||||
|  |                 datadir = pars.get('DATADIR') | ||||||
|  |  | ||||||
|  |                 # write raw data in Tecmag format: | ||||||
|  |                 filename = datadir+outfile+suffix+'.tnt' | ||||||
|  |                 accu.write_to_tecmag(filename,\ | ||||||
|  |                                      nrecords=2*pars['SI1'],\ | ||||||
|  |                                      frequency=pars['SW']+pars['O1']) | ||||||
|  |  | ||||||
|  |                # write parameters in a text file: | ||||||
|  |                 filename = datadir+outfile+suffix+'.par'  | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.par') | ||||||
|  |  | ||||||
|  |                 fileobject = open(filename, 'w') | ||||||
|  |                 for key in sorted(pars.iterkeys()): | ||||||
|  |                     if key=='run': continue | ||||||
|  |                     if key=='rec_phase': continue | ||||||
|  |                     fileobject.write('%s%s%s'%(key,'=', pars[key])) | ||||||
|  |                     fileobject.write('\n') | ||||||
|  |                 fileobject.close() | ||||||
|  |  | ||||||
|  |             # reset accumulation: | ||||||
|  |             del accu | ||||||
|  |              | ||||||
|  | pass | ||||||
							
								
								
									
										176
									
								
								Scripts/Spin_Alignment_Four_Pulses/op_spinal4pulses_exp.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								Scripts/Spin_Alignment_Four_Pulses/op_spinal4pulses_exp.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | TXEnableDelay = 1e-6 | ||||||
|  | TXEnableValue = 0b0001  # TTL line blanking RF amplifier (bit 0) | ||||||
|  | TXPulseValue  = 0b0010  # TTL line triggering RF pulses  (bit 1) | ||||||
|  | ADCSensitivity = 1	# voltage span for ADC | ||||||
|  |  | ||||||
|  | def experiment(): # Jeener-Broekaert echo sequence (a.k.a. spin-alignment) | ||||||
|  |  | ||||||
|  |   # set up acquisition parameters:          | ||||||
|  |     pars = {} | ||||||
|  |     pars['P90'] = 4.2e-6	# 90-degree pulse length (s) | ||||||
|  |     pars['SF'] = 46.7e6		# spectrometer frequency (Hz) | ||||||
|  |     pars['O1'] = -30e3	 	# offset from SF (Hz) | ||||||
|  |     pars['SW'] = 10e6    	# spectral window (Hz) | ||||||
|  |     pars['SI'] = 1*1024  	# number of acquisition points | ||||||
|  |     pars['NS'] = 16		# number of scans | ||||||
|  |     pars['DS'] = 0		# number of dummy scans | ||||||
|  |     pars['RD'] = 0.5		# delay between scans (s) | ||||||
|  |     pars['D1'] = 30e-6		# delay after first pulse, or tp (s) | ||||||
|  |     pars['D2'] = 100e-6		# delay after second pulse, or tm (s) | ||||||
|  |     pars['D3'] = 20e-6          # refocusing pulse delay (s) | ||||||
|  |     pars['PHA'] = 30		# receiver reference phase (degree) | ||||||
|  |     pars['DATADIR'] = '/home/fprak/Students/'	# data directory | ||||||
|  |     pars['OUTFILE'] = None			# output file name | ||||||
|  |      | ||||||
|  |   # specify a variable parameter (optional): | ||||||
|  |     pars['VAR_PAR'] = 'D2'	# variable parameter name (a string)    | ||||||
|  |     start = 30e-6		# starting value | ||||||
|  |     stop = 2e-0			# end value | ||||||
|  |     steps = 24			# number of values | ||||||
|  |     log_scale = True		# log scale flag  | ||||||
|  |     stag_range = False		# staggered range flag | ||||||
|  |  | ||||||
|  |   # check parameters for safety: | ||||||
|  |     if pars['PHA'] < 0: | ||||||
|  |         pars['PHA'] = 360 + pars['PHA'] | ||||||
|  |          | ||||||
|  |     if pars['P90'] > 20e-6: | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |                      | ||||||
|  |     # check whether a variable parameter is named:  | ||||||
|  |     var_key = pars.get('VAR_PAR') | ||||||
|  |     if var_key == 'P90' and (start > 20e-6 or stop > 20e-6): | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     if pars['NS']%16 != 0: | ||||||
|  |         pars['NS'] = int(round(pars['NS'] / 16) + 1) * 16  | ||||||
|  |         print 'Number of scans changed to ', pars['NS'], ' due to phase cycling' | ||||||
|  |  | ||||||
|  |     # start the experiment: | ||||||
|  |     if var_key:  | ||||||
|  |         # this is an arrayed experiment: | ||||||
|  |         if log_scale: | ||||||
|  |             array = log_range(start,stop,steps) | ||||||
|  |         else: | ||||||
|  |             array = lin_range(start,stop,steps)  | ||||||
|  |          | ||||||
|  |         if stag_range: | ||||||
|  |             array = staggered_range(array, size = 2) | ||||||
|  |  | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         if var_key == 'D1': | ||||||
|  |             seconds = (sum(array)*2 + (pars['D2'] + pars['RD']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         elif var_key == 'D2': | ||||||
|  |             seconds = (sum(array) + (pars['D1']*2 + pars['RD']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         elif var_key == 'RD': | ||||||
|  |             seconds = (sum(array) + (pars['D1']*2 + pars['D2']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         else: | ||||||
|  |             seconds = (pars['D1']*2 + pars['D2'] + pars['RD']) * steps * (pars['NS']+ pars['DS']) | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |         # loop for a variable parameter: | ||||||
|  |         for index, pars[var_key] in enumerate(array): | ||||||
|  |             print 'Arrayed experiment for '+var_key+': run = '+str(index+1)+\ | ||||||
|  |                              ' out of '+str(array.size)+': value = '+str(pars[var_key]) | ||||||
|  |             # loop for accumulation: | ||||||
|  |             for run in xrange(pars['NS']+pars['DS']): | ||||||
|  |                 yield spinal4pulses_experiment(pars, run) | ||||||
|  |             synchronize() | ||||||
|  |  | ||||||
|  |     else: | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         seconds = (pars['D1']*2 + pars['D2'] + pars['RD']) * (pars['NS']+ pars['DS']) | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |        # loop for accumulation: | ||||||
|  |         for run in xrange(pars['NS']+pars['DS']): | ||||||
|  |             yield spinal4pulses_experiment(pars, run) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # the pulse program:  | ||||||
|  |  | ||||||
|  | def spinal4pulses_experiment(pars, run): | ||||||
|  |     e=Experiment() | ||||||
|  |  | ||||||
|  |     dummy_scans = pars.get('DS') | ||||||
|  |     if dummy_scans: | ||||||
|  |         run -= dummy_scans | ||||||
|  |                         | ||||||
|  |     pars['PROG'] = 'spinal4pulses_experiment'                        | ||||||
|  |                         | ||||||
|  |    # 8-step phase cycle (1-14 modifided to deal with T1-recovery and extended for Re/Im imbalance) | ||||||
|  |     pars['PH1'] = [0,  270,   0, 270,   180,  90, 180,  90] # 1st (90-degree) pulse | ||||||
|  |     pars['PH3'] = [90, 180,  90, 180,    90, 180,  90, 180] # 2nd (90-degree) pulse | ||||||
|  |     pars['PH4'] = [90,  90, 270, 270,     0,   0, 180, 180]  # 3rd (90-degree) pulse | ||||||
|  |     pars['PH5'] = [90,  90,  90,  90,   180, 180, 180, 180]  # 3rd (90-degree) pulse | ||||||
|  |     pars['PH2'] = [0,  180, 180,   0,    90, 270, 270,  90]  # receiver | ||||||
|  |          | ||||||
|  |    # read in variables: | ||||||
|  |     P90 = pars['P90'] | ||||||
|  |     P45 = pars['P90']*0.5 | ||||||
|  |     P1  = pars['P90']*0.5 | ||||||
|  |     SF =  pars['SF'] | ||||||
|  |     O1 =  pars['O1']     | ||||||
|  |     RD =  pars['RD'] | ||||||
|  |     D1 =  pars['D1'] | ||||||
|  |     D2 =  pars['D2'] | ||||||
|  |     D3 =  pars['D3'] | ||||||
|  |     PH1 = pars['PH1'][run%len(pars['PH1'])] | ||||||
|  |     PH3 = pars['PH3'][run%len(pars['PH3'])] | ||||||
|  |     PH4 = pars['PH4'][run%len(pars['PH4'])] | ||||||
|  |     PH5 = pars['PH5'][run%len(pars['PH5'])] | ||||||
|  |     PH2 = pars['PH2'][run%len(pars['PH2'])] | ||||||
|  |     PHA = pars['PHA'] | ||||||
|  |  | ||||||
|  |     if (run/8)%2 != 0: | ||||||
|  |         PH5 += 180    | ||||||
|  |  | ||||||
|  |    # set sampling parameters: | ||||||
|  |     SI = pars['SI'] | ||||||
|  |     SW = pars['SW'] | ||||||
|  |     while SW <= 10e6 and SI < 256*1024: | ||||||
|  |         SI *= 2 | ||||||
|  |         SW *= 2 | ||||||
|  |  | ||||||
|  |    # run the pulse sequence: | ||||||
|  |     e.wait(RD)						# relaxation delay between scans | ||||||
|  |     e.set_frequency(SF+O1, phase=PH1) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D1-P90/2-P45/2-TXEnableDelay)		# 'short tau' | ||||||
|  |     e.set_phase(PH3) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P45, value=TXEnableValue|TXPulseValue)	# 45-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D2-P45/2-P1/2-TXEnableDelay)			# 'long tau' | ||||||
|  |     e.set_phase(PH4) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P1, value=TXEnableValue|TXPulseValue)	# 45-degree pulse | ||||||
|  |  | ||||||
|  |     e.wait(D3-P1/2-P90/2-TXEnableDelay)                 # 'delta' | ||||||
|  |      | ||||||
|  |     e.set_phase(PH5) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse | ||||||
|  |  | ||||||
|  |     e.wait(TXEnableDelay) | ||||||
|  |     e.set_phase(PHA) | ||||||
|  |     e.wait(D3+D1-P90/2-TXEnableDelay)                   # wait for echo | ||||||
|  |     e.record(SI, SW, sensitivity=ADCSensitivity)        # acquisition                                      | ||||||
|  |  | ||||||
|  |    # write experiment parameters: | ||||||
|  |     for key in pars.keys(): | ||||||
|  |         e.set_description(key, pars[key])	# acquisition parameters | ||||||
|  |     e.set_description('run', run)		# current scan | ||||||
|  |     e.set_description('rec_phase', -PH2)	# current receiver phase | ||||||
|  |  | ||||||
|  |     return e | ||||||
							
								
								
									
										210
									
								
								Scripts/Spin_Alignment_Four_Pulses/op_spinal4pulses_res.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								Scripts/Spin_Alignment_Four_Pulses/op_spinal4pulses_res.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | from numpy import * | ||||||
|  | from scipy.signal import * | ||||||
|  | from scipy.optimize import * | ||||||
|  | from os import path, rename | ||||||
|  |  | ||||||
|  | def result(): | ||||||
|  |  | ||||||
|  |     measurement = MeasurementResult('Magnetization') | ||||||
|  |  | ||||||
|  |     measurement_range = [0.0, 10e-6] | ||||||
|  |     measurement_ranging = False | ||||||
|  |  | ||||||
|  |     suffix = '' 	# output file name's suffix and... | ||||||
|  |     counter = 1		# counter for arrayed experiments | ||||||
|  |     var_key = ''	# variable parameter name | ||||||
|  |  | ||||||
|  |     # loop over the incoming results:  | ||||||
|  |     for timesignal in results: | ||||||
|  |         if not isinstance(timesignal,ADC_Result):  | ||||||
|  |             continue | ||||||
|  |  | ||||||
|  |         # read experiment parameters: | ||||||
|  |         pars = timesignal.get_description_dictionary() | ||||||
|  |  | ||||||
|  |         # ---------------- digital filter ------------------  | ||||||
|  |               | ||||||
|  |         # get actual sampling rate of timesignal: | ||||||
|  |         sampling_rate = timesignal.get_sampling_rate() | ||||||
|  |  | ||||||
|  |         # get user-defined spectrum width: | ||||||
|  |         spec_width = pars['SW'] | ||||||
|  |          | ||||||
|  |         # specify cutoff frequency, in relative units: | ||||||
|  |         cutoff = spec_width / sampling_rate | ||||||
|  |                  | ||||||
|  |         if cutoff < 1: # no filter applied otherwise | ||||||
|  |  | ||||||
|  |             # number of filter's coefficients: | ||||||
|  |             numtaps = 29 | ||||||
|  |              | ||||||
|  |             # use firwin to create a lowpass FIR filter: | ||||||
|  |             fir_coeff = firwin(numtaps, cutoff) | ||||||
|  |              | ||||||
|  |             # downsize x according to user-defined spectral window: | ||||||
|  |             skip = int(sampling_rate / spec_width) | ||||||
|  |             timesignal.x = timesignal.x[::skip] | ||||||
|  |              | ||||||
|  |             for i in range(2): | ||||||
|  |                 # apply the filter to ith channel: | ||||||
|  |                 timesignal.y[i] = lfilter(fir_coeff, 1.0, timesignal.y[i]) | ||||||
|  |  | ||||||
|  |                 # zeroize first N-1 "corrupted" samples: | ||||||
|  |                 timesignal.y[i][:numtaps-1] = 0.0 | ||||||
|  |  | ||||||
|  |                 # circular left shift of y: | ||||||
|  |                 timesignal.y[i] = roll(timesignal.y[i], -(numtaps-1))     | ||||||
|  |  | ||||||
|  |                 # downsize y to user-defined number of samples (SI): | ||||||
|  |                 timesignal.y[i] = timesignal.y[i][::skip] | ||||||
|  |  | ||||||
|  |             # update the sampling_rate attribute of the signal's: | ||||||
|  |             timesignal.set_sampling_rate(spec_width) | ||||||
|  |  | ||||||
|  |         # ---------------------------------------------------- | ||||||
|  |  | ||||||
|  |         # rotate timesignal according to current receiver's phase: | ||||||
|  |         timesignal.phase(pars['rec_phase']) | ||||||
|  |  | ||||||
|  |         # provide timesignal to the display tab: | ||||||
|  |         data['Current scan'] = timesignal | ||||||
|  |  | ||||||
|  |         # accumulate... | ||||||
|  |         if not locals().get('accu'): | ||||||
|  |             accu = Accumulation() | ||||||
|  |  | ||||||
|  |         # skip dummy scans, if any: | ||||||
|  |         if pars['run'] < 0: continue | ||||||
|  |  | ||||||
|  |         # add up: | ||||||
|  |         accu += timesignal | ||||||
|  |  | ||||||
|  |         # provide accumulation to the display tab: | ||||||
|  |         data['Accumulation'] = accu | ||||||
|  |  | ||||||
|  |         # check how many scans are done: | ||||||
|  |         if accu.n == pars['NS']: # accumulation is complete | ||||||
|  |  | ||||||
|  |             # make a copy: | ||||||
|  |             echo = accu + 0 | ||||||
|  |  | ||||||
|  |             # compute the initial phase of FID: | ||||||
|  |             phi0 = arctan2(echo.y[1][0], echo.y[0][0]) * 180 / pi | ||||||
|  |             if not 'ref' in locals(): ref = phi0    | ||||||
|  |             print 'phi0 = ', phi0 | ||||||
|  |  | ||||||
|  |             # rotate FID to maximize y[0][0]:      | ||||||
|  |             #echo.phase(-phi0)  | ||||||
|  |  | ||||||
|  |             # do FFT: | ||||||
|  |             echo.exp_window(line_broadening=10) | ||||||
|  |             spectrum = echo.fft(samples=2*pars['SI']) | ||||||
|  |  | ||||||
|  |             # try zero-order phase correction:  | ||||||
|  |             spectrum.phase(-phi0) | ||||||
|  |  | ||||||
|  |             # provide spectrum to the display tab: | ||||||
|  |             data['Spectrum'] = spectrum | ||||||
|  |  | ||||||
|  |             # check whether it is an arrayed experiment:  | ||||||
|  |             var_key = pars.get('VAR_PAR') | ||||||
|  |             if var_key: | ||||||
|  |                 # get variable parameter's value: | ||||||
|  |                 var_value = pars.get(var_key) | ||||||
|  |  | ||||||
|  |                 # provide signal recorded with this var_value to the display tab: | ||||||
|  |                 data['Accumulation'+"/"+var_key+"=%e"%(var_value)] = accu                 | ||||||
|  |  | ||||||
|  |                 # measure signal intensity vs. var_value: | ||||||
|  |                 if measurement_ranging == True: | ||||||
|  |                    [start, stop] = accu.get_sampling_rate() * array(measurement_range) | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][int(start):int(stop)])  | ||||||
|  |                     | ||||||
|  |                 else: | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][0:31]) | ||||||
|  |  | ||||||
|  |                 # provide measurement to the display tab: | ||||||
|  |                 data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  |                 # update the file name suffix: | ||||||
|  |                 suffix = '_' + str(counter) | ||||||
|  |                 counter += 1 | ||||||
|  |  | ||||||
|  |             # save accu if required: | ||||||
|  |             outfile = pars.get('OUTFILE') | ||||||
|  |             if outfile:  | ||||||
|  |                 datadir = pars.get('DATADIR') | ||||||
|  |  | ||||||
|  |                 # write raw data in Simpson format: | ||||||
|  |                 filename = datadir+outfile+suffix+'.dat' | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.dat') | ||||||
|  |                 accu.write_to_simpson(filename) | ||||||
|  |  | ||||||
|  |                 # write raw data in Tecmag format: | ||||||
|  |                 # filename = datadir+outfile+'.tnt' | ||||||
|  |                 # accu.write_to_tecmag(filename, nrecords=20) | ||||||
|  |  | ||||||
|  |                # write parameters in a text file: | ||||||
|  |                 filename = datadir+outfile+suffix+'.par'  | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.par') | ||||||
|  |  | ||||||
|  |                 fileobject = open(filename, 'w') | ||||||
|  |                 for key in sorted(pars.iterkeys()): | ||||||
|  |                     if key=='run': continue | ||||||
|  |                     if key=='rec_phase': continue | ||||||
|  |                     fileobject.write('%s%s%s'%(key,'=', pars[key])) | ||||||
|  |                     fileobject.write('\n') | ||||||
|  |                 fileobject.close() | ||||||
|  |  | ||||||
|  |             # reset accumulation: | ||||||
|  |             del accu | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     if var_key == 'D2': | ||||||
|  |         # KWW fit: | ||||||
|  |         xdata = measurement.get_xdata() | ||||||
|  |         ydata = measurement.get_ydata() | ||||||
|  |         [amplitude, rate, beta] = fitfunc(xdata, ydata) | ||||||
|  |         print '%s%02g' % ('Amplitude = ', amplitude) | ||||||
|  |         print '%s%02g' % ('T2 [s] = ', 1./rate) | ||||||
|  |         print '%s%02g' % ('Beta = ', beta) | ||||||
|  |  | ||||||
|  |         # update display for the fit: | ||||||
|  |         measurement.y = func([amplitude, rate, beta], xdata) | ||||||
|  |         data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  | # the fitting procedure: | ||||||
|  | def fitfunc(xdata, ydata):  | ||||||
|  |  | ||||||
|  |     # initialize variable parameters: | ||||||
|  |     try:  | ||||||
|  |         # solve Az = b: | ||||||
|  |         A = array((ones(xdata.size/2), xdata[0:xdata.size/2]))     | ||||||
|  |         b = log(abs(ydata[0:xdata.size/2]))      | ||||||
|  |         z = linalg.lstsq(transpose(A), b) | ||||||
|  |         amplitude = exp(z[0][0]) | ||||||
|  |         rate = -z[0][1] | ||||||
|  |     except: | ||||||
|  |         amplitude = abs(ydata[0]) | ||||||
|  |         rate = 1./(xdata[-1] - xdata[0]) | ||||||
|  |     beta = 1 | ||||||
|  |     p0 = [amplitude, rate, beta] | ||||||
|  |  | ||||||
|  |     # run least-squares optimization: | ||||||
|  |     plsq = leastsq(residuals, p0, args=(xdata, ydata)) | ||||||
|  |  | ||||||
|  |     return plsq[0] # best-fit parameters | ||||||
|  |  | ||||||
|  | def residuals(p, xdata, ydata): | ||||||
|  |     return ydata - func(p, xdata) | ||||||
|  |  | ||||||
|  | # here is the function to fit: | ||||||
|  | def func(p, xdata): | ||||||
|  |     return p[0]*exp(-(p[1]*xdata)**p[2]) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | pass | ||||||
| @@ -0,0 +1,183 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | TXEnableDelay = 2e-6 | ||||||
|  | TXEnableValue = 0b0001  # TTL line blanking RF amplifier (bit 0) | ||||||
|  | TXPulseValue  = 0b0010  # TTL line triggering RF pulses  (bit 1) | ||||||
|  | ADCSensitivity = 5	# voltage span for ADC | ||||||
|  |  | ||||||
|  | def experiment(): # a diffusion editing sequence with stimulated echo and XY-16 detection | ||||||
|  |  | ||||||
|  |   # set up acqusition parameters: | ||||||
|  |     pars = {} | ||||||
|  |     pars['P90'] = 0.8e-6	# 90-degree pulse length (s) | ||||||
|  |     pars['SF'] = 161.85e6  	# spectrometer frequency (Hz) | ||||||
|  |     pars['O1'] = 0e3		# offset from SF (Hz) | ||||||
|  |     pars['NS'] = 16		# number of scans | ||||||
|  |     pars['DS'] = 0		# number of dummy scans | ||||||
|  |     pars['RD'] = 6		# delay between scans (s) | ||||||
|  |     pars['D1'] = 20e-6		# delay after first STE pulse (s) | ||||||
|  |     pars['D2'] = 30e-6		# delay after second STE pulse (s)  | ||||||
|  |     pars['D4'] = 2.5e-6		# pre-acquisition offset | ||||||
|  |     pars['NECH'] = 128          # number of 180-degree pulses | ||||||
|  |     pars['TAU'] = 50e-6         # half pulse period (s) | ||||||
|  |     pars['PHA'] = -95   	# receiver phase (degree)  | ||||||
|  |     pars['DATADIR'] = '/home/fprak/Desktop/test/'	# data directory | ||||||
|  |     pars['OUTFILE'] = None				# output file name | ||||||
|  |  | ||||||
|  |   # specify a variable parameter (optional): | ||||||
|  |     pars['VAR_PAR'] = 'D2'	# variable parameter name (a string)    | ||||||
|  |     start = 20e-6		# starting value | ||||||
|  |     stop = 3e-1			# end value | ||||||
|  |     steps = 24			# number of values | ||||||
|  |     log_scale = True		# log scale flag  | ||||||
|  |     stag_range = False		# staggered range flag | ||||||
|  |  | ||||||
|  |    # check parameters for safety:  | ||||||
|  |     if pars['PHA'] < 0: | ||||||
|  |         pars['PHA'] = 360 + pars['PHA'] | ||||||
|  |  | ||||||
|  |     if pars['P90'] > 20e-6: | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     # check whether a variable parameter is named:  | ||||||
|  |     var_key = pars.get('VAR_PAR') | ||||||
|  |     if var_key == 'P90' and (start > 20e-6 or stop > 20e-6): | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     if pars['NS']%16 != 0: | ||||||
|  |         pars['NS'] = int(round(pars['NS'] / 16) + 1) * 16  | ||||||
|  |         print 'Number of scans changed to ',pars['NS'],' due to phase cycling' | ||||||
|  |  | ||||||
|  |     # start the experiment: | ||||||
|  |     if var_key:  | ||||||
|  |         # this is an arrayed experiment: | ||||||
|  |         if log_scale: | ||||||
|  |             array = log_range(start,stop,steps) | ||||||
|  |         else: | ||||||
|  |             array = lin_range(start,stop,steps)  | ||||||
|  |  | ||||||
|  |         if stag_range: | ||||||
|  |             array = staggered_range(array, size = 2)  | ||||||
|  |  | ||||||
|  |         # estimate the experiment time: | ||||||
|  |         if var_key == 'D1': | ||||||
|  |             seconds = (sum(array)*2 + (pars['D2'] + pars['RD']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         elif var_key == 'D2': | ||||||
|  |             seconds = (sum(array) + (pars['D1']*2 + pars['RD']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         elif var_key == 'RD': | ||||||
|  |             seconds = (sum(array) + (pars['D1']*2 + pars['D2']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         else: | ||||||
|  |             seconds = (pars['D1']*2 + pars['D2'] + pars['RD']) * steps * (pars['NS']+ pars['DS']) | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |   | ||||||
|  |         # loop for a variable parameter: | ||||||
|  |         for index, pars[var_key] in enumerate(array): | ||||||
|  |             print 'Arrayed experiment for '+var_key+': run = '+str(index+1)+\ | ||||||
|  |                              ' out of '+str(array.size)+': value = '+str(pars[var_key]) | ||||||
|  |             # loop for accumulation: | ||||||
|  |             for run in xrange(pars['NS']+pars['DS']): | ||||||
|  |                 yield ste16_experiment(pars, run) | ||||||
|  |             synchronize()  | ||||||
|  |     else: | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         seconds = (pars['D1']*2 + pars['D2'] + pars['RD']) * (pars['NS']+ pars['DS']) | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |         # loop for accumulation: | ||||||
|  |         for run in xrange(pars['NS']+pars['DS']): | ||||||
|  |             yield ste16_experiment(pars, run)   | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # the pulse program:  | ||||||
|  |  | ||||||
|  | def ste16_experiment(pars, run): | ||||||
|  |     e=Experiment() | ||||||
|  |  | ||||||
|  |     dummy_scans = pars.get('DS') | ||||||
|  |     if dummy_scans: | ||||||
|  |         run -= dummy_scans | ||||||
|  |  | ||||||
|  |     pars['PROG'] = 'ste16_experiment' | ||||||
|  |  | ||||||
|  |     # phase lists [from J. Magn. Reson. 157, 31 (2002)]:  | ||||||
|  |     pars['PH1'] = [0, 180,   0, 180,   0, 180,   0, 180,  90, 270,  90, 270,  90, 270,  90, 270] # 1st 90-degree pulse | ||||||
|  |     pars['PH3'] = [0,   0, 180, 180,   0,   0, 180, 180,   0,   0, 180, 180,   0,   0, 180, 180] # 2nd 90-degree pulse | ||||||
|  |     pars['PH4'] = [0,   0,   0,   0, 180, 180, 180, 180,   0,   0,   0,   0, 180, 180, 180, 180] # 3nd 90-degree pulse | ||||||
|  |     pars['PH5'] = [0,   0,   0,   0,   0,   0,   0,   0, 270, 270, 270, 270, 270, 270, 270, 270] # 180-degree pulses | ||||||
|  |     pars['PH2'] = [0, 180, 180,   0, 180,   0,   0, 180, 270,  90,  90, 270,  90, 270, 270,  90] # receiver  | ||||||
|  |      | ||||||
|  |     # XY-16 phase cycle | ||||||
|  |     pars['PH5_XY16'] = [0,   90,   0,  90,  90,   0,  90,   0, 180, 270, 180, 270, 270, 180, 270, 180]    # XY-16: 180-degree pulses | ||||||
|  |     pars['PH2_XY16'] = [90, 270, 270,  90, 270, 270,  90,  90,  90, 270, 270,  90, 270, 270,  90,  90]    # XY_16: receiver  | ||||||
|  |  | ||||||
|  |     # read in variables: | ||||||
|  |     P90 = pars['P90'] | ||||||
|  |     P180 = pars['P90']*2 | ||||||
|  |     SF =  pars['SF'] | ||||||
|  |     O1 =  pars['O1']     | ||||||
|  |     RD =  pars['RD'] | ||||||
|  |     D1 =  pars['D1'] | ||||||
|  |     D2 =  pars['D2'] | ||||||
|  |     D4 =  pars['D4'] | ||||||
|  |     TAU = pars['TAU'] | ||||||
|  |     NECH = pars['NECH'] | ||||||
|  |     PH1 = pars['PH1'][run%len(pars['PH1'])] | ||||||
|  |     PH3 = pars['PH3'][run%len(pars['PH3'])] | ||||||
|  |     PH4 = pars['PH4'][run%len(pars['PH4'])] | ||||||
|  |     PH5 = pars['PH5'][run%len(pars['PH5'])] | ||||||
|  |     PH2 = pars['PH2'][run%len(pars['PH2'])]  | ||||||
|  |     PH5_XY16 = [x+PH5 for x in pars['PH5_XY16']*(NECH/16)] | ||||||
|  |     PH2_XY16 = [x+PH2 for x in pars['PH2_XY16']*(NECH/16)]    | ||||||
|  |     PHA = pars['PHA']  | ||||||
|  |  | ||||||
|  |     # set sampling parameters: | ||||||
|  |     SI = 128    	# number of echo samples | ||||||
|  |     SW = 20e6   	# sample rate | ||||||
|  |     AQ = (SI+6)/SW	# acquisition window | ||||||
|  | 	 | ||||||
|  |     if TAU < (P90+P180)/2+TXEnableDelay or TAU < (P180+TXEnableDelay+AQ)/2: | ||||||
|  |         raise Exception('pulse period is too short!') | ||||||
|  |  | ||||||
|  |     if 2*TAU < P180+TXEnableDelay+SI/SW: | ||||||
|  |         raise Exception('pulse period too short!') | ||||||
|  |      | ||||||
|  |    # run the pulse sequence:  | ||||||
|  |     e.wait(RD)						# delay between scans | ||||||
|  |     e.set_frequency(SF+O1, phase=PH1) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue) | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 1st 90-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D1-P90/2-TXEnableDelay)			# short delay | ||||||
|  |     e.set_phase(PH3) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 2nd 90-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D2-P90/2-TXEnableDelay)			# long delay | ||||||
|  |     e.set_phase(PH4) | ||||||
|  |  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 3rd 90-degree pulse | ||||||
|  |      | ||||||
|  |     e.wait(D1+TAU-P90/2-TXEnableDelay)			# wait for first echo and tau | ||||||
|  |      | ||||||
|  |     for i in range(NECH): | ||||||
|  |         e.set_phase(PH5_XY16[i])                                     	# set phase for 180-degree pulse   | ||||||
|  |         e.ttl_pulse(TXEnableDelay, value=TXEnableValue)         	# enable RF amplifier | ||||||
|  |         e.ttl_pulse(P180, value=TXEnableValue|TXPulseValue)     	# apply 180-degree pulse | ||||||
|  |         e.set_phase(PHA)	                                       	# set phase for receiver      | ||||||
|  |         e.wait(TAU-(P180+TXEnableDelay+AQ)/2+D4)                   	# pre-acquisition delay | ||||||
|  |         e.record(SI, SW, timelength=AQ, sensitivity=ADCSensitivity)     # echo acquisition | ||||||
|  |         e.wait(TAU-(P180+TXEnableDelay+AQ)/2-D4)                   	# post-acquisition delay  | ||||||
|  |  | ||||||
|  |     # write experiment attributes:   | ||||||
|  |     for key in pars.keys(): | ||||||
|  |         e.set_description(key, pars[key])		# acqusition parameters | ||||||
|  |     e.set_description('run', run)			# current scan | ||||||
|  |     e.set_description('rec_phase', [-1*x for x in PH2_XY16])        # current phase list for data routing | ||||||
|  |  | ||||||
|  |     return e | ||||||
| @@ -0,0 +1,201 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | from numpy import * | ||||||
|  | from scipy.signal import * | ||||||
|  | from scipy.optimize import * | ||||||
|  | from os import path, rename | ||||||
|  |  | ||||||
|  | def result(): | ||||||
|  |  | ||||||
|  |     measurement = MeasurementResult('Magnetization') | ||||||
|  |  | ||||||
|  |     suffix = '' 	# output file name's suffix and... | ||||||
|  |     counter = 1		# counter for arrayed experiments | ||||||
|  |     var_key = ''	# variable parameter name | ||||||
|  |  | ||||||
|  |     # loop over the incoming results:  | ||||||
|  |     for timesignal in results: | ||||||
|  |         if not isinstance(timesignal,ADC_Result):  | ||||||
|  |             continue    | ||||||
|  |  | ||||||
|  |         # read experiment parameters: | ||||||
|  |         pars = timesignal.get_description_dictionary() | ||||||
|  |  | ||||||
|  |         # get number of echoes: | ||||||
|  |         num_echoes = pars['NECH']          | ||||||
|  |          | ||||||
|  |         # get phase list for data routung: | ||||||
|  |         rec_phase = eval(pars['rec_phase']) | ||||||
|  |          | ||||||
|  |         # phase individual echoes in timesignal: | ||||||
|  |         for i in range(num_echoes):  | ||||||
|  |             echo = timesignal.get_result_by_index(i) | ||||||
|  |             echo.phase(rec_phase[i]) | ||||||
|  |              | ||||||
|  |             start = timesignal.index[i][0] | ||||||
|  |             end = timesignal.index[i][1] | ||||||
|  |             for k in range(timesignal.get_number_of_channels()): | ||||||
|  |                 if i%2 == 0: | ||||||
|  |                     timesignal.y[k][start:end+1] = echo.y[k] | ||||||
|  |                 else:   | ||||||
|  |                     timesignal.y[k][start:end+1] = -echo.y[k]    | ||||||
|  |  | ||||||
|  |         # provide timesignal to the display tab: | ||||||
|  |         data['Current scan'] = timesignal | ||||||
|  |  | ||||||
|  |         # accumulate... | ||||||
|  |         if not locals().get('accu'): | ||||||
|  |             accu = Accumulation() | ||||||
|  |  | ||||||
|  |         # skip dummy scans, if any: | ||||||
|  |         if pars['run'] < 0: continue | ||||||
|  |          | ||||||
|  |         # add up: | ||||||
|  |         accu += timesignal | ||||||
|  |                  | ||||||
|  |         # provide accumulation to the display tab: | ||||||
|  |         data['Accumulation'] = accu | ||||||
|  |  | ||||||
|  |         # check how many scans are done: | ||||||
|  |         if accu.n == pars['NS']: # accumulation is complete | ||||||
|  |  | ||||||
|  |             # get number of echoes: | ||||||
|  |             num_echoes = pars['NECH']  | ||||||
|  |  | ||||||
|  |             # downsize accu to one point per echo: | ||||||
|  |             echodecay = accu + 0 | ||||||
|  |             echodecay.x = resize(echodecay.x, int(num_echoes)) | ||||||
|  |             echodecay.y[0] = resize(echodecay.y[0], int(num_echoes)) | ||||||
|  |             echodecay.y[1] = resize(echodecay.y[1], int(num_echoes)) | ||||||
|  |              | ||||||
|  |             # find where first echo exceeds noise: | ||||||
|  | #            if not locals().get('noise'): | ||||||
|  | #                last_echo = accu.get_accu_by_index(num_echoes-1) | ||||||
|  | #                first_echo = accu.get_accu_by_index(0) | ||||||
|  | #                noise = 3*std(last_echo.y[1][:]) | ||||||
|  | #                samples = first_echo.y[0] > noise | ||||||
|  |                  | ||||||
|  |             if not locals().get('noise'): | ||||||
|  |                 echo = accu.get_accu_by_index(0) | ||||||
|  |                 noise = 0.1*max(abs(echo.y[0])) | ||||||
|  |                 samples = abs(echo.y[0]) > noise | ||||||
|  |  | ||||||
|  |             # set echo times and intensities: | ||||||
|  |             for i in range(num_echoes): | ||||||
|  |                 # get ith echo: | ||||||
|  |                 echo = accu.get_accu_by_index(i) | ||||||
|  |                 # set echo time: | ||||||
|  |                 echodecay.x[i] = i*2*pars['TAU'] | ||||||
|  |                 # set echo value: | ||||||
|  |                 echodecay.y[0][i] = sum(echo.y[0][samples])	# the sum of echo points that exceed noise... | ||||||
|  |                 echodecay.y[1][i] = sum(echo.y[1][samples])  | ||||||
|  |                 #echodecay.y[0][i] = sum(echo.y[0])             # or the sum of all echo points... | ||||||
|  |                 #echodecay.y[1][i] = sum(echo.y[1])  | ||||||
|  |                 #echodecay.y[0][i] = echo.y[0][echo.x.size/2]	# or a middle echo point | ||||||
|  |                 #echodecay.y[1][i] = echo.y[1][echo.x.size/2] | ||||||
|  |                  | ||||||
|  |             # compute a signal's phase: | ||||||
|  |             phi0 = arctan2(echodecay.y[1][0], echodecay.y[0][0]) * 180 / pi | ||||||
|  |             if not locals().get('ref'):  ref = phi0  | ||||||
|  |             print 'phi0 = ', phi0  | ||||||
|  |                       | ||||||
|  |             # rotate signal to maximize Re (optional):  | ||||||
|  |             #echodecay.phase(-phi0) | ||||||
|  |  | ||||||
|  |             # provide echo decay to the display tab: | ||||||
|  |             data['Echo Decay'] = echodecay | ||||||
|  |  | ||||||
|  |             # check whether it is an arrayed experiment:  | ||||||
|  |             var_key = pars.get('VAR_PAR') | ||||||
|  |             if var_key: | ||||||
|  |                 # get variable parameter's value: | ||||||
|  |                 var_value = pars.get(var_key) | ||||||
|  |  | ||||||
|  |                 # provide signal recorded with different var_value's to the display tab: | ||||||
|  |                 data['Accumulation'+"/"+var_key+"=%e"%(var_value)] = accu        | ||||||
|  |                 data['Echo Decay'+"/"+var_key+"=%e"%(var_value)] = echodecay | ||||||
|  |  | ||||||
|  |                 # measure signal intensity vs. var_value: | ||||||
|  | #                [amplitude, rate] = fitfunc(echodecay.x, echodecay.y[0]) | ||||||
|  | #                print '%s%02g' % ('Amplitude = ', amplitude) | ||||||
|  | #                print '%s%02g' % ('T2 [s] = ', 1./rate) | ||||||
|  |  | ||||||
|  | #                measurand[var_value] = amplitude | ||||||
|  |                 measurement[var_value] = sum(echodecay.y[0][:]) | ||||||
|  |  | ||||||
|  |                 # provide measurement to the display tab: | ||||||
|  |                 data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  |             # save accu if required:    | ||||||
|  |             outfile = pars.get('OUTFILE') | ||||||
|  |             if outfile:  | ||||||
|  |                 datadir = pars.get('DATADIR') | ||||||
|  |  | ||||||
|  |                 # write raw data in Simpson format: | ||||||
|  |                 filename = datadir+outfile+suffix+'.dat' | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.dat') | ||||||
|  |                 accu.write_to_simpson(filename) | ||||||
|  |  | ||||||
|  |                 # write raw data in Tecmag format: | ||||||
|  |                 # filename = datadir+outfile+'.tnt' | ||||||
|  |                 # accu.write_to_tecmag(filename, nrecords=20) | ||||||
|  |  | ||||||
|  |                # write parameters in a text file: | ||||||
|  |                 filename = datadir+outfile+suffix+'.par'  | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.par') | ||||||
|  |  | ||||||
|  |                 fileobject = open(filename, 'w') | ||||||
|  |                 for key in sorted(pars.iterkeys()): | ||||||
|  |                     if key=='run': continue | ||||||
|  |                     if key=='rec_phase': continue | ||||||
|  |                     fileobject.write('%s%s%s'%(key,'=', pars[key])) | ||||||
|  |                     fileobject.write('\n') | ||||||
|  |                 fileobject.close() | ||||||
|  |  | ||||||
|  |             # reset accumulation: | ||||||
|  |             del accu | ||||||
|  |  | ||||||
|  |     if var_key == 'D2': | ||||||
|  |         # mono-exponential decay fit: | ||||||
|  |         xdata = measurement.get_xdata() | ||||||
|  |         ydata = measurement.get_ydata() | ||||||
|  |         [amplitude, rate] = fitfunc(xdata, ydata) | ||||||
|  |         print '%s%02g' % ('Amplitude = ', amplitude) | ||||||
|  |         print '%s%02g' % ('T2 [s] = ', 1./rate) | ||||||
|  |  | ||||||
|  |         # update display for the fit: | ||||||
|  |         measurement.y = func([amplitude, rate], xdata) | ||||||
|  |         data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  | # the fitting procedure: | ||||||
|  | def fitfunc(xdata, ydata): | ||||||
|  |  | ||||||
|  |     # initialize variable parameters: | ||||||
|  |     try:  | ||||||
|  |         # solve Az = b: | ||||||
|  |         A = array((ones(xdata.size/2), xdata[0:xdata.size/2])) | ||||||
|  |         b = log(abs(ydata[0:xdata.size/2])) | ||||||
|  |         z = linalg.lstsq(transpose(A), b) | ||||||
|  |         amplitude = exp(z[0][0]) | ||||||
|  |         rate = -z[0][1] | ||||||
|  |         print amplitude, 1./rate | ||||||
|  |     except: | ||||||
|  |         amplitude = abs(ydata[0]) | ||||||
|  |         rate = 1./(xdata[-1] - xdata[0]) | ||||||
|  |     p0 = [amplitude, rate] | ||||||
|  |  | ||||||
|  |     # run least-squares optimization: | ||||||
|  |     plsq = leastsq(residuals, p0, args=(xdata, ydata)) | ||||||
|  |  | ||||||
|  |     return plsq[0] # best-fit parameters | ||||||
|  |  | ||||||
|  | def residuals(p, xdata, ydata): | ||||||
|  |     return ydata - func(p, xdata) | ||||||
|  |  | ||||||
|  | # here is the function to fit: | ||||||
|  | def func(p, xdata): | ||||||
|  |     return p[0]*exp(-p[1]*xdata) | ||||||
|  |  | ||||||
|  | pass | ||||||
							
								
								
									
										173
									
								
								Scripts/Zeeman_Order_Four_Pulses/op_zeeman4pulses_exp.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								Scripts/Zeeman_Order_Four_Pulses/op_zeeman4pulses_exp.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | TXEnableDelay = 1e-6 | ||||||
|  | TXEnableValue = 0b0001	# TTL line blanking RF amplifier (bit 0) | ||||||
|  | TXPulseValue  = 0b0010	# TTL line triggering RF pulses  (bit 1) | ||||||
|  | ADCSensitivity = 1	# voltage span for ADC | ||||||
|  |  | ||||||
|  | def experiment(): # Four-pulse STE sequence (Zeeman order) | ||||||
|  |  | ||||||
|  |   # set up acquisition parameters:          | ||||||
|  |     pars = {} | ||||||
|  |     pars['P90'] = 4.2e-6	# 90-degree pulse length (s) | ||||||
|  |     pars['SF'] = 338.7e6 	# spectrometer frequency (Hz) | ||||||
|  |     pars['O1'] = -60e3		# offset from SF (Hz) | ||||||
|  |     pars['SW'] = 10e6		# spectral window (Hz) | ||||||
|  |     pars['SI'] = 1*1024		# number of acquisition points | ||||||
|  |     pars['NS'] = 16		# number of scans | ||||||
|  |     pars['DS'] = 0		# number of dummy scans | ||||||
|  |     pars['RD'] = .5		# delay between scans (s) | ||||||
|  |     pars['D1'] = 30e-6		# delay after first pulse, or 'short tau' (s) | ||||||
|  |     pars['D2'] = 100e-6		# delay after second pulse, or 'long tau' (s) | ||||||
|  |     pars['D3'] = 20e-6          # refocusing pusle delay (s) | ||||||
|  |     pars['PHA'] = 124		# receiver phase (degree) | ||||||
|  |     pars['DATADIR'] = '/home/fprak/Students/'	# data directory | ||||||
|  |     pars['OUTFILE'] = None			# output file name | ||||||
|  |  | ||||||
|  |   # specify a variable parameter (optional): | ||||||
|  |     pars['VAR_PAR'] = 'D2'	# variable parameter name (a string) | ||||||
|  |     start = 30e-6		# starting value | ||||||
|  |     stop = 2e-0			# end value | ||||||
|  |     steps = 24			# number of values | ||||||
|  |     log_scale = True		# log scale flag  | ||||||
|  |     stag_range = False		# staggered range flag | ||||||
|  |  | ||||||
|  |   # check parameters for safety:  | ||||||
|  |     if pars['PHA'] < 0: | ||||||
|  |         pars['PHA'] = 360 + pars['PHA'] | ||||||
|  |  | ||||||
|  |     if pars['P90'] > 20e-6: | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     # check whether a variable parameter is named:  | ||||||
|  |     var_key = pars.get('VAR_PAR') | ||||||
|  |     if var_key == 'P90' and (start > 20e-6 or stop > 20e-6): | ||||||
|  |         raise Exception("Pulse too long!!!") | ||||||
|  |  | ||||||
|  |     if pars['NS']%8 != 0: | ||||||
|  |         pars['NS'] = int(round(pars['NS'] / 8) + 1) * 8  | ||||||
|  |         print 'Number of scans changed to ',pars['NS'],' due to phase cycling' | ||||||
|  |  | ||||||
|  |     # start the experiment: | ||||||
|  |     if var_key: | ||||||
|  |         # this is an arrayed experiment: | ||||||
|  |         if log_scale: | ||||||
|  |             array = log_range(start,stop,steps) | ||||||
|  |         else: | ||||||
|  |             array = lin_range(start,stop,steps) | ||||||
|  |  | ||||||
|  |         if stag_range: | ||||||
|  |             array = staggered_range(array, size = 2) | ||||||
|  |  | ||||||
|  |         # estimate the experiment time: | ||||||
|  |         if var_key == 'D1': | ||||||
|  |             seconds = (sum(array)*2 + (pars['D2'] + pars['RD']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         elif var_key == 'D2': | ||||||
|  |             seconds = (sum(array) + (pars['D1']*2 + pars['RD']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         elif var_key == 'RD': | ||||||
|  |             seconds = (sum(array) + (pars['D1']*2 + pars['D2']) * steps) * (pars['NS'] + pars['DS']) | ||||||
|  |         else: | ||||||
|  |             seconds = (pars['D1']*2 + pars['D2'] + pars['RD']) * steps * (pars['NS']+ pars['DS']) | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |         # loop for a variable parameter: | ||||||
|  |         for index, pars[var_key] in enumerate(array): | ||||||
|  |             print 'Arrayed experiment for '+var_key+': run = '+str(index+1)+\ | ||||||
|  |                              ' out of '+str(array.size)+': value = '+str(pars[var_key]) | ||||||
|  |             # loop for accumulation: | ||||||
|  |             for run in xrange(pars['NS']+pars['DS']): | ||||||
|  |                 yield zeeman4pulses_experiment(pars, run)  | ||||||
|  |             synchronize() | ||||||
|  |     else: | ||||||
|  |        # estimate the experiment time: | ||||||
|  |         seconds = (pars['D1']*2 + pars['D2'] + pars['RD']) * (pars['NS']+ pars['DS']) | ||||||
|  |         m, s = divmod(seconds, 60) | ||||||
|  |         h, m = divmod(m, 60) | ||||||
|  |         print '%s%02d:%02d:%02d' % ('Experiment time estimated: ', h, m, s) | ||||||
|  |  | ||||||
|  |         # loop for accumulation: | ||||||
|  |         for run in xrange(pars['NS']+pars['DS']): | ||||||
|  |             yield zeeman4pulses_experiment(pars, run) | ||||||
|  |  | ||||||
|  | # the pulse program:  | ||||||
|  |  | ||||||
|  | def zeeman4pulses_experiment(pars, run): | ||||||
|  |     e=Experiment() | ||||||
|  |  | ||||||
|  |     dummy_scans = pars.get('DS') | ||||||
|  |     if dummy_scans: | ||||||
|  |         run -= dummy_scans | ||||||
|  |          | ||||||
|  |     pars['PROG'] = 'zeeman4pulses_experiment' | ||||||
|  |      | ||||||
|  |          # ok 8-step phase cycle (1-21 modifided to deal with T1-recovery and extended for Re/Im imbalance) | ||||||
|  |     pars['PH1'] = [0, 270,   0, 270,   180,  90, 180,  90] # 1st (90-degree) pulse | ||||||
|  |     pars['PH3'] = [0,  90,   0,  90,     0,  90,   0,  90] # 2nd (90-degree) pulse | ||||||
|  |     pars['PH4'] = [0,   0, 180, 180,   270, 270,  90,  90]  # 3rd (90-degree) pulse | ||||||
|  |     pars['PH5'] = [90, 90,  90,  90,   180, 180, 180, 180]  # 3rd (90-degree) pulse | ||||||
|  |     pars['PH2'] = [0, 180, 180,   0,    90, 270, 270,  90]  # receiver | ||||||
|  |      | ||||||
|  |   | ||||||
|  |    # read in variables: | ||||||
|  |     P90 = pars['P90'] | ||||||
|  |     SF =  pars['SF'] | ||||||
|  |     O1 =  pars['O1']     | ||||||
|  |     RD =  pars['RD'] | ||||||
|  |     D1 =  pars['D1'] | ||||||
|  |     D2 =  pars['D2'] | ||||||
|  |     D3 =  pars['D3'] | ||||||
|  |     PH1 = pars['PH1'][run%len(pars['PH1'])] | ||||||
|  |     PH3 = pars['PH3'][run%len(pars['PH3'])] | ||||||
|  |     PH4 = pars['PH4'][run%len(pars['PH4'])] | ||||||
|  |     PH5 = pars['PH5'][run%len(pars['PH5'])] | ||||||
|  |     PH2 = pars['PH2'][run%len(pars['PH2'])] | ||||||
|  |     PHA = pars['PHA'] | ||||||
|  |      | ||||||
|  |     if (run/8)%2 != 0: | ||||||
|  |         PH5 += 180   | ||||||
|  |  | ||||||
|  |    # set sampling parameters: | ||||||
|  |     SI = pars['SI'] | ||||||
|  |     SW = pars['SW'] | ||||||
|  |     while SW <= 10e6 and SI < 256*1024: | ||||||
|  |         SI *= 2 | ||||||
|  |         SW *= 2 | ||||||
|  |  | ||||||
|  |     # run the pulse program:  | ||||||
|  |     e.wait(RD)   				        # relaxation delay between scans | ||||||
|  |     e.set_frequency(SF+O1, phase=PH1)          				  | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse  | ||||||
|  |  | ||||||
|  |     e.wait(D1-P90-TXEnableDelay)			# short tau | ||||||
|  |      | ||||||
|  |     e.set_phase(PH3)      				 | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse  | ||||||
|  |     | ||||||
|  |     e.wait(D2-P90-TXEnableDelay)			# long tau | ||||||
|  |      | ||||||
|  |     e.set_phase(PH4)   | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse | ||||||
|  |        | ||||||
|  |     e.wait(D3-P90-TXEnableDelay)                        # echo delay | ||||||
|  |      | ||||||
|  |     e.set_phase(PH5) | ||||||
|  |     e.ttl_pulse(TXEnableDelay, value=TXEnableValue)		 | ||||||
|  |     e.ttl_pulse(P90, value=TXEnableValue|TXPulseValue)	# 90-degree pulse | ||||||
|  |      | ||||||
|  |     e.wait(TXEnableDelay) | ||||||
|  |     e.set_phase(PHA) | ||||||
|  |     e.wait(D3+D1-P90/2-TXEnableDelay)                   # echo delay | ||||||
|  |     e.record(SI, SW, sensitivity=ADCSensitivity)	# acquisition | ||||||
|  |  | ||||||
|  |    # write experiment parameters: | ||||||
|  |     for key in pars.keys(): | ||||||
|  |         e.set_description(key, pars[key])	# acquisition parameters | ||||||
|  |     e.set_description('run', run)		# current scan | ||||||
|  |     e.set_description('rec_phase', -PH2)	# current receiver phase | ||||||
|  |  | ||||||
|  |     return e | ||||||
							
								
								
									
										210
									
								
								Scripts/Zeeman_Order_Four_Pulses/op_zeeman4pulses_res.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								Scripts/Zeeman_Order_Four_Pulses/op_zeeman4pulses_res.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | |||||||
|  | # -*- coding: iso-8859-1 -*- | ||||||
|  |  | ||||||
|  | from numpy import * | ||||||
|  | from scipy.signal import * | ||||||
|  | from scipy.optimize import * | ||||||
|  | from os import path, rename | ||||||
|  |  | ||||||
|  | def result(): | ||||||
|  |  | ||||||
|  |     measurement = MeasurementResult('Magnetization') | ||||||
|  |  | ||||||
|  |     measurement_range = [0.0, 10e-6] | ||||||
|  |     measurement_ranging = False | ||||||
|  |  | ||||||
|  |     suffix = '' 	# output file name's suffix and... | ||||||
|  |     counter = 1		# counter for arrayed experiments | ||||||
|  |     var_key = ''	# variable parameter name | ||||||
|  |  | ||||||
|  |     # loop over the incoming results:  | ||||||
|  |     for timesignal in results: | ||||||
|  |         if not isinstance(timesignal,ADC_Result):  | ||||||
|  |             continue | ||||||
|  |  | ||||||
|  |         # read experiment parameters: | ||||||
|  |         pars = timesignal.get_description_dictionary() | ||||||
|  |  | ||||||
|  |         # ---------------- digital filter ------------------  | ||||||
|  |               | ||||||
|  |         # get actual sampling rate of timesignal: | ||||||
|  |         sampling_rate = timesignal.get_sampling_rate() | ||||||
|  |  | ||||||
|  |         # get user-defined spectrum width: | ||||||
|  |         spec_width = pars['SW'] | ||||||
|  |          | ||||||
|  |         # specify cutoff frequency, in relative units: | ||||||
|  |         cutoff = spec_width / sampling_rate | ||||||
|  |                  | ||||||
|  |         if cutoff < 1: # otherwise no filter applied | ||||||
|  |  | ||||||
|  |             # number of filter's coefficients: | ||||||
|  |             numtaps = 29 | ||||||
|  |              | ||||||
|  |             # use firwin to create a lowpass FIR filter: | ||||||
|  |             fir_coeff = firwin(numtaps, cutoff) | ||||||
|  |              | ||||||
|  |             # downsize x according to user-defined spectral window: | ||||||
|  |             skip = int(sampling_rate / spec_width) | ||||||
|  |             timesignal.x = timesignal.x[::skip] | ||||||
|  |              | ||||||
|  |             for i in range(2): | ||||||
|  |                 # apply the filter to ith channel: | ||||||
|  |                 timesignal.y[i] = lfilter(fir_coeff, 1.0, timesignal.y[i]) | ||||||
|  |  | ||||||
|  |                 # zeroize first N-1 "corrupted" samples: | ||||||
|  |                 timesignal.y[i][:numtaps-1] = 0.0 | ||||||
|  |  | ||||||
|  |                 # circular left shift of y: | ||||||
|  |                 timesignal.y[i] = roll(timesignal.y[i], -(numtaps-1))     | ||||||
|  |  | ||||||
|  |                 # downsize y to user-defined number of samples (SI): | ||||||
|  |                 timesignal.y[i] = timesignal.y[i][::skip] | ||||||
|  |  | ||||||
|  |             # update the sampling_rate attribute of the signal's: | ||||||
|  |             timesignal.set_sampling_rate(spec_width) | ||||||
|  |  | ||||||
|  |         # ---------------------------------------------------- | ||||||
|  |  | ||||||
|  |         # rotate timesignal according to current receiver's phase: | ||||||
|  |         timesignal.phase(pars['rec_phase']) | ||||||
|  |  | ||||||
|  |         # provide timesignal to the display tab: | ||||||
|  |         data['Current scan'] = timesignal | ||||||
|  |  | ||||||
|  |         # accumulate... | ||||||
|  |         if not locals().get('accu'): | ||||||
|  |             accu = Accumulation() | ||||||
|  |  | ||||||
|  |         # skip dummy scans, if any: | ||||||
|  |         if pars['run'] < 0: continue | ||||||
|  |  | ||||||
|  |         # add up: | ||||||
|  |         accu += timesignal | ||||||
|  |  | ||||||
|  |         # provide accumulation to the display tab: | ||||||
|  |         data['Accumulation'] = accu | ||||||
|  |  | ||||||
|  |         # check how many scans are done: | ||||||
|  |         if accu.n == pars['NS']: # accumulation is complete | ||||||
|  |  | ||||||
|  |             # make a copy: | ||||||
|  |             echo = accu + 0 | ||||||
|  |  | ||||||
|  |             # compute the initial phase of FID: | ||||||
|  |             phi0 = arctan2(echo.y[1][0], echo.y[0][0]) * 180 / pi | ||||||
|  |             if not 'ref' in locals(): ref = phi0    | ||||||
|  |             print 'phi0 = ', phi0 | ||||||
|  |  | ||||||
|  |             # rotate FID to maximize y[0][0]:      | ||||||
|  |             #echo.phase(-phi0)  | ||||||
|  |  | ||||||
|  |             # do FFT: | ||||||
|  |             echo.exp_window(line_broadening=10) | ||||||
|  |             spectrum = echo.fft(samples=2*pars['SI']) | ||||||
|  |  | ||||||
|  |             # try zero-order phase correction:  | ||||||
|  |             spectrum.phase(-phi0) | ||||||
|  |  | ||||||
|  |             # provide spectrum to the display tab: | ||||||
|  |             data['Spectrum'] = spectrum | ||||||
|  |  | ||||||
|  |             # check whether it is an arrayed experiment:  | ||||||
|  |             var_key = pars.get('VAR_PAR') | ||||||
|  |             if var_key: | ||||||
|  |                 # get variable parameter's value: | ||||||
|  |                 var_value = pars.get(var_key) | ||||||
|  |                  | ||||||
|  |                 # provide signal recorded with this var_value to the display tab: | ||||||
|  |                 data['Accumulation'+"/"+var_key+"=%e"%(var_value)] = accu                 | ||||||
|  |  | ||||||
|  |                 # measure signal intensity vs. var_value: | ||||||
|  |                 if measurement_ranging == True: | ||||||
|  |                    [start, stop] = accu.get_sampling_rate() * array(measurement_range) | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][int(start):int(stop)])  | ||||||
|  |                     | ||||||
|  |                 else: | ||||||
|  |                    measurement[var_value] = sum(accu.y[0][0:31]) | ||||||
|  |  | ||||||
|  |                 # provide measurement to the display tab: | ||||||
|  |                 data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  |                 # update the file name suffix: | ||||||
|  |                 suffix = '_' + str(counter) | ||||||
|  |                 counter += 1 | ||||||
|  |  | ||||||
|  |             # save accu if required: | ||||||
|  |             outfile = pars.get('OUTFILE') | ||||||
|  |             if outfile:  | ||||||
|  |                 datadir = pars.get('DATADIR') | ||||||
|  |  | ||||||
|  |                 # write raw data in Simpson format: | ||||||
|  |                 filename = datadir+outfile+suffix+'.dat' | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.dat') | ||||||
|  |                 accu.write_to_simpson(filename) | ||||||
|  |  | ||||||
|  |                 # write raw data in Tecmag format: | ||||||
|  |                 # filename = datadir+outfile+'.tnt' | ||||||
|  |                 # accu.write_to_tecmag(filename, nrecords=20) | ||||||
|  |  | ||||||
|  |                # write parameters in a text file: | ||||||
|  |                 filename = datadir+outfile+suffix+'.par'  | ||||||
|  |                 if path.exists(filename): | ||||||
|  |                     rename(filename, datadir+'~'+outfile+suffix+'.par') | ||||||
|  |  | ||||||
|  |                 fileobject = open(filename, 'w') | ||||||
|  |                 for key in sorted(pars.iterkeys()): | ||||||
|  |                     if key=='run': continue | ||||||
|  |                     if key=='rec_phase': continue | ||||||
|  |                     fileobject.write('%s%s%s'%(key,'=', pars[key])) | ||||||
|  |                     fileobject.write('\n') | ||||||
|  |                 fileobject.close() | ||||||
|  |  | ||||||
|  |             # reset accumulation: | ||||||
|  |             del accu | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     if var_key == 'D2': | ||||||
|  |         # KWW fit: | ||||||
|  |         xdata = measurement.get_xdata() | ||||||
|  |         ydata = measurement.get_ydata() | ||||||
|  |         [amplitude, rate, beta] = fitfunc(xdata, ydata) | ||||||
|  |         print '%s%02g' % ('Amplitude = ', amplitude) | ||||||
|  |         print '%s%02g' % ('T2 [s] = ', 1./rate) | ||||||
|  |         print '%s%02g' % ('Beta = ', beta) | ||||||
|  |  | ||||||
|  |         # update display for the fit: | ||||||
|  |         measurement.y = func([amplitude, rate, beta], xdata) | ||||||
|  |         data[measurement.get_title()] = measurement | ||||||
|  |  | ||||||
|  | # the fitting procedure: | ||||||
|  | def fitfunc(xdata, ydata):  | ||||||
|  |  | ||||||
|  |     # initialize variable parameters: | ||||||
|  |     try:  | ||||||
|  |         # solve Az = b: | ||||||
|  |         A = array((ones(xdata.size/2), xdata[0:xdata.size/2]))     | ||||||
|  |         b = log(abs(ydata[0:xdata.size/2]))      | ||||||
|  |         z = linalg.lstsq(transpose(A), b) | ||||||
|  |         amplitude = exp(z[0][0]) | ||||||
|  |         rate = -z[0][1] | ||||||
|  |     except: | ||||||
|  |         amplitude = abs(ydata[0]) | ||||||
|  |         rate = 1./(xdata[-1] - xdata[0]) | ||||||
|  |     beta = 1 | ||||||
|  |     p0 = [amplitude, rate, beta] | ||||||
|  |  | ||||||
|  |     # run least-squares optimization: | ||||||
|  |     plsq = leastsq(residuals, p0, args=(xdata, ydata)) | ||||||
|  |  | ||||||
|  |     return plsq[0] # best-fit parameters | ||||||
|  |  | ||||||
|  | def residuals(p, xdata, ydata): | ||||||
|  |     return ydata - func(p, xdata) | ||||||
|  |  | ||||||
|  | # here is the function to fit: | ||||||
|  | def func(p, xdata): | ||||||
|  |     return p[0]*exp(-(p[1]*xdata)**p[2]) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | pass | ||||||
		Reference in New Issue
	
	Block a user