def readout_pulse(self):    
        # Readout Window - DO NOT CHANGE!

        self.read = pulses.hard_pulse((self.dw*self.SI),self.samp_rate) # square pulse
        tb.readwin.set_data(self.read) # update flow graph
        delay = self.fudge+self.p90/2+self.TE-self.dw*self.SI/2 # position readout window
        tb.set_readout_delay(int(delay*self.samp_rate)) # update flow graph
 def readout_pulse(self):
     # Readout Window
     self.readout_length = round(float(self.samp_rate) / self.BW * self.SI)
     self.readout_time = self.readout_length / self.samp_rate
     self.read = pulses.hard_pulse(self.readout_time, self.samp_rate)
     tb.readwin.set_data(self.read)  # update pulse in flowgraph
     delay = self.fudge + self.p90 / 2 + self.TE - (self.readout_time / 2)
     tb.set_readout_delay(int(delay * self.samp_rate))  # update pulse delay
 def p180_hard_pulse(self):
     # Refocusing Pulse
     self.ref = self.power_auc / self.p180 * pulses.hard_pulse(
         self.p180, self.samp_rate)
     tb.ref_pulse.set_data(self.ref)  # update pulse in flowgraph
     # update pulse delay
     delay = self.p90 / 2 + self.TE / 2 - self.p180 / 2
     tb.set_ref_delay(int(delay * self.samp_rate))
    def p90_hard_pulse(self):

        # Excitation Pulse
        self.ex = pulses.hard_pulse(self.p90,
                                    self.samp_rate) * self.power_auc / self.p90
        tb.ex_pulse.set_data(self.ex)
        delay = self.fudge  # update pulse in flowgraph
        tb.set_ex_delay(int(delay * self.samp_rate))  # update pulse delay
    def set_readgrad(self):

        # READOUT GRADIENT SET FROM CONFIG FILE SETTINGS - DO NOT CHANGE
    
        self.read_amp = 10./(self.samp_rate*self.dw*np.sqrt(2))*1./(self.dw*self.FOV[self.readdir]*4258*self.Grad_str[self.readdir])
        self.pre_amp = -self.prephasor_fudge*(self.SI*self.dw/2+self.dead)*self.read_amp/self.pre_dur
        
        # create prephasor data
        grad_pre = self.pre_amp*pulses.hard_pulse(self.pre_dur,self.samp_rate)
        # create readout gradient data
        grad_read = self.read_amp*pulses.hard_pulse(self.dw*self.SI+self.dead,self.samp_rate)
        
        length = int(self.samp_rate*(self.fudge+self.p90/2+self.TE+self.SI*self.dw/2))
        self.readgrad = np.ravel(np.zeros([length,1],float))
        
        p_start = int((4*self.fudge+self.p90)*self.samp_rate)
        r_start = int(self.samp_rate*(-self.dead+self.fudge+self.p90/2+self.TE-self.SI*self.dw/2))
        
        self.readgrad[p_start:p_start+size(grad_pre)] = grad_pre
        self.readgrad[r_start:r_start+grad_read.size] = grad_read
                          
        # Set data and delays based on desired gradient directions
        if (self.readdir == x):
            # X Gradient
            self.xgrad = self.readgrad
            tb.Gx.set_data(self.xgrad)
            tb.Gx.set_amps(1,0,1,1)
            tb.set_Gx_delay(0)
        elif (self.readdir == y):
            # Y Gradient
            self.ygrad = self.readgrad
            tb.Gy.set_data(self.ygrad)
            tb.Gy.set_amps(1,0,1,1)
            tb.set_Gy_delay(0)
        elif (self.readdir == z):
            # Z Gradient
            self.zgrad = self.readgrad
            tb.Gz.set_data(self.zgrad)
            tb.Gz.set_amps(1,0,1,1)
            tb.set_Gz_delay(0)
        else:
            print repr(direction) + " is not a valid option for Direction"
 def set_slicegrad(self):
 
 	# SET WHEN SLICE GRADIENT SHOULD START -- SHOULD BE SAME TIME OR SLIGHTLY BEFORE EX PULSE
 	start = int(self.fudge*self.samp_rate)
 
 	# IF YOU DO NOT WANT A SLICE GRADIENT, SET SLICEAMP TO 0
 	self.sliceamp = -self.TBW/(self.p90*4258*self.Grad_str[self.slicedir]*self.slice_thick)
 
 	# SLICE GRADIENT CONSTRUCTED FROM CONFIG FILE SETTINGS -- DO NOT CHANGE BELOW
 
     slicegrad1 = self.sliceamp*pulses.hard_pulse(self.p90+self.fudge,self.samp_rate)
     slicegrad2 = self.rephase_fudge*-self.p90*self.sliceamp/self.rewinder_length*pulses.hard_pulse(self.rewinder_length,self.samp_rate)
     rewind_start = int((4*self.fudge+self.p90)*self.samp_rate)
                     
     length = int(self.samp_rate*(self.fudge+self.p90/2+self.TE+self.SI*self.dw/2))
     self.slicegrad = np.ravel(np.zeros([length,1],float))
     
     self.slicegrad[start:start+size(slicegrad1)] = np.transpose(slicegrad1)
     self.slicegrad[rewind_start:rewind_start+size(slicegrad2)] = np.transpose(slicegrad2)
             
     # set data, delays, and phase steps for desired gradient directions
     if (self.slicedir == x):
         # X Gradient
         self.xgrad = self.slicegrad
         tb.Gx.set_data(self.xgrad)
         tb.Gx.set_amps(1,0,1,1)
         tb.set_Gx_delay(0)
     elif (self.slicedir == y):
         # Y Gradient
         self.ygrad = self.slicegrad
         tb.Gy.set_data(self.ygrad)
         tb.Gy.set_amps(1,0,1,1)
         tb.set_Gy_delay(0)
     elif (self.slicedir == z):
         # Z Gradient
         self.zgrad = self.slicegrad
         tb.Gz.set_data(self.zgrad)
         tb.Gz.set_amps(1,0,1,1)
         tb.set_Gz_delay(0)
     else:
         print repr(self.slicedir) + " is not a valid option for Direction"
class params(object):
    def __init__(self):
        # set some default definitions
        global x
        x=0
        global y
        y=1
        global z
        z=2
        
        f = open('config_file.txt', 'r') # CHANGE TO APPROPRIATE CONFIG FILE
        foo = {}
        for line in f:
            k, v = line.strip().split('=')
            foo[k.strip()] = float(v.strip())

        f.close()
        
        self.__dict__.update(foo)
        self.fudge = 5*1./self.samp_rate
        self.samp_rate = tb.samp_rate
        
        self.NPE = int(self.NPE)
        
        self.FOV = [0,0,0]
        self.FOV[x] = self.FOVx #mm
        self.FOV[z] = self.FOVy #mm
        self.FOV[y] = self.FOVz #mm
        
        self.dead = 100e-6
           
        try:
            # Importing Calibration data
            info = open('cal.pkl', 'rb')
            calinfo = pickle.load(info)
            info.close()
            
            self.offset = (calinfo["offset"])
            self.power_auc = (calinfo["auc"])
            print "UPDATED CENTER FREQUENCY OFFSET AND POWER AUC FROM CALIBRATION FILE"
        except:
            print "power calibration has not been run"
            
        try:
            info = open('Gcal.pkl', 'rb')
            calinfo = pickle.load(info)
            info.close()
            
            self.Grad_str = calinfo["Grad_str"]
            print "UPDATED GRADIENT STRENGTHS FROM CALIBRATION FILE"
        except:
            print "Gradient calibration has not been run"
        
        self.readdir = int(self.readdir)
        self.phasedir = int(self.phasedir)
        self.slicedir = int(self.slicedir)
                
        self.phase_namp = self.NPE
        
        self.nav = int(self.nav)
        
        length = int(self.samp_rate*(self.fudge+self.p90/2+self.TE+self.SI*self.dw/2))
        self.xgrad = ravel(zeros([length,1],float))
        self.ygrad = ravel(zeros([length,1],float))
        self.zgrad = ravel(zeros([length,1],float))
        
        self.rephase_fudge = 1.
        self.prephasor_fudge = 1.
        
    def ex_pulse(self):
    
        # CREATE RF PULSE
        #----------------------------------------------------------------
        self.ex = # PULSE GOES HERE!... pulse area should equal 1
        amp = self.power_auc*self.samp_rate # calculate amp from calibration
        
        # IF MORE THAN ONE PULSE IN RF, YOU MUST CONSTRUCT IT YOURSELF
        
        delay = # SET WHEN PULSE SHOULD START! add self.fudge to center in TXE window
        #----------------------------------------------------------------
        
        self.ex = self.ex*amp # set area under curve for 90 pulse
        tb.ex_pulse.set_data(self.ex)  # update pulse in flowgraph
        
        tb.set_ex_delay(int(delay*self.samp_rate)) # update pulse delay in flowgraph

        # handle RF chopping
        if (self.ischopped == 1):
            tb.ex_pulse.set_amps(1,-2,2,self.nav)
        else:
            tb.ex_pulse.set_amps(1,0,1,1)
    
    def readout_pulse(self):    
        # Readout Window - DO NOT CHANGE!

        self.read = pulses.hard_pulse((self.dw*self.SI),self.samp_rate) # square pulse
        tb.readwin.set_data(self.read) # update flow graph
        delay = self.fudge+self.p90/2+self.TE-self.dw*self.SI/2 # position readout window
        tb.set_readout_delay(int(delay*self.samp_rate)) # update flow graph
        
           
    def set_readgrad(self):

        # READOUT GRADIENT SET FROM CONFIG FILE SETTINGS - DO NOT CHANGE
    
        self.read_amp = 10./(self.samp_rate*self.dw*np.sqrt(2))*1./(self.dw*self.FOV[self.readdir]*4258*self.Grad_str[self.readdir])
        self.pre_amp = -self.prephasor_fudge*(self.SI*self.dw/2+self.dead)*self.read_amp/self.pre_dur
        
        # create prephasor data
        grad_pre = self.pre_amp*pulses.hard_pulse(self.pre_dur,self.samp_rate)
        # create readout gradient data
        grad_read = self.read_amp*pulses.hard_pulse(self.dw*self.SI+self.dead,self.samp_rate)
        
        length = int(self.samp_rate*(self.fudge+self.p90/2+self.TE+self.SI*self.dw/2))
        self.readgrad = np.ravel(np.zeros([length,1],float))
        
        p_start = int((4*self.fudge+self.p90)*self.samp_rate)
        r_start = int(self.samp_rate*(-self.dead+self.fudge+self.p90/2+self.TE-self.SI*self.dw/2))
        
        self.readgrad[p_start:p_start+size(grad_pre)] = grad_pre
        self.readgrad[r_start:r_start+grad_read.size] = grad_read
                          
        # Set data and delays based on desired gradient directions
        if (self.readdir == x):
            # X Gradient
            self.xgrad = self.readgrad
            tb.Gx.set_data(self.xgrad)
            tb.Gx.set_amps(1,0,1,1)
            tb.set_Gx_delay(0)
        elif (self.readdir == y):
            # Y Gradient
            self.ygrad = self.readgrad
            tb.Gy.set_data(self.ygrad)
            tb.Gy.set_amps(1,0,1,1)
            tb.set_Gy_delay(0)
        elif (self.readdir == z):
            # Z Gradient
            self.zgrad = self.readgrad
            tb.Gz.set_data(self.zgrad)
            tb.Gz.set_amps(1,0,1,1)
            tb.set_Gz_delay(0)
        else:
            print repr(direction) + " is not a valid option for Direction"
        
        
        
    def set_phasegrad(self):
		
		# SET WHEN PHASE ENCODE SHOULD START -- DEFAULT IS 4 FUDGE LENGTHS AFTER EX PULSE
		start = int((4*self.fudge+self.p90)*self.samp_rate)

        # PHASE ENCODE GRADIENT CONSTRUCTED FROM CONFIG FILE SETTINGS - DO NOT CHANGE BELOW
    
        self.phase_step =  1./(4258*self.Grad_str[self.phasedir]*self.phase_dur*self.FOV[self.phasedir])
        self.phase_amp = -self.phase_step*self.NPE/2
        
        phasegrad = pulses.hard_pulse(self.phase_dur,self.samp_rate) # create general shape
        
        length = int(self.samp_rate*(self.fudge+self.p90/2+self.TE+self.SI*self.dw/2))
        self.phasegrad = np.ravel(np.zeros([length,1],float))
        
        self.phasegrad[start:start+size(phasegrad)] = phasegrad
        
        # set data, delays, and phase steps for desired gradient directions
        if (self.phasedir == x):
            # X Gradient
            self.xgrad = self.phasegrad
            tb.Gx.set_data(self.xgrad)
            tb.Gx.set_amps(self.phase_amp,self.phase_step,self.NPE,self.nav)
            tb.set_Gx_delay(0)
        elif (self.phasedir == y):
            # Y Gradient
            self.ygrad = self.phasegrad
            tb.Gy.set_data(self.ygrad)
            tb.Gy.set_amps(self.phase_amp,self.phase_step,self.NPE,self.nav)
            tb.set_Gy_delay(0)
        elif (self.phasedir == z):
            # Z Gradient
            self.zgrad = self.phasegrad
            tb.Gz.set_data(self.zgrad)
            tb.Gz.set_amps(self.phase_amp,self.phase_step,self.NPE,self.nav)
            tb.set_Gz_delay(0)
        else:
            print repr(self.phasedir) + " is not a valid option for Direction"