예제 #1
0
	def linear_phys(self,vf,dt):
		"""Adds linear ramp to waveform, starts at current last 
			value and goes to 'vf' in 'dt'"""
		
		if self.lastPhys == None:
			msg = "The last physics value is not available\n for this waveform."
			msg = msg + "\n\nProgram will be stopped."
			errormsg.box('wfm.linear_phys :: ' + self.name, msg)
			exit(1)
		
		print "...linear_phys last physical value is = %f" % self.lastPhys
		
		v0 = self.lastPhys
		
		#One could also obtain v0 via conversion, but it is not recommended		
		#v0=physics.cnv(self.name+"Phys",self.last())
		
		if dt == 0.0:
			self.y[ self.y.size -1] = physics.cnv(self.name,vf)
			return

			
		N = int(math.floor(dt/self.ss))

		hashbase = ''
		hashbase = hashbase + self.name
		hashbase = hashbase + '%.8f' % vf
		hashbase = hashbase + '%.8f' % v0
		hashbase = hashbase + '%.8f' % N
		hashbase = hashbase + '%.8f' % dt
		hashbase = hashbase + rawcalibdat( self.name ) 
		
		ramphash = seqconf.ramps_dir() + 'linearPhys_' \
			           + hashlib.md5( hashbase ).hexdigest()
	
		if not os.path.exists(ramphash) or True:
				print '...Making new linearPhys ramp for ' + self.name
				
				x = numpy.linspace( v0 + (vf-v0)/N , vf , N )
				ramp = physics.cnv( self.name, x )
				
				#yramp= numpy.array([cnv(self.name,v0 + 1.0*(vf-v0)*(i+1)/N) for i in range(N)])
				
				#if ( numpy.absolute( yramp - ramp ) > 0.0001 ).any():
				#	print "NOT EQUAL!"
				#else:
				#	print "EQUAL!"
					
					
				#ramp.tofile(ramphash,sep=',',format="%.4f")
				
				
		else:
				print '...Recycling previously calculated linearPhys ramp for '  + self.name
				ramp =  numpy.fromfile(ramphash,sep=',')	

		self.y=numpy.append(self.y, ramp)
		self.lastPhys = vf
		
		return
예제 #2
0
	def follow(self, bfield, detuning):
		### Levitation voltage:
		###
		### Vlev = slope * I + offset
		###
		### wherer I is the current on the bias coils
		### slope and offset have been calibrated and are set below:
		
		slope = 0.0971
		offset = -2.7232
		
		if self.ss != bfield.ss:
			msg = "ERROR in HFIMG wave:  step size does not match the bfield ramp!"
			print msg
			errormsg.box('hfimg_wave.follow', msg)
			exit(1)
		
		print "...Setting ANALOGHFIMG to follow bfield ramp"
		
		bfieldV = numpy.copy(bfield.y)
		bfieldG = physics.inv( 'bfield', bfieldV)* 6.8
		
		hfimg0 = -1.*(100.0 + 163.7 - 1.414*bfieldG)
		
		self.y = physics.cnv( 'analogimg', hfimg0 - detuning)
		
		return hfimg0[-1]
예제 #3
0
    def linear_phys(self, vf, dt):
        """Adds linear ramp to waveform, starts at current last 
			value and goes to 'vf' in 'dt'"""

        if self.lastPhys == None:
            msg = "The last physics value is not available\n for this waveform."
            msg = msg + "\n\nProgram will be stopped."
            errormsg.box('wfm.linear_phys :: ' + self.name, msg)
            exit(1)

        print "...linear_phys last physical value is = %f" % self.lastPhys

        v0 = self.lastPhys

        #One could also obtain v0 via conversion, but it is not recommended
        #v0=physics.cnv(self.name+"Phys",self.last())

        if dt == 0.0:
            self.y[self.y.size - 1] = physics.cnv(self.name, vf)
            return

        N = int(math.floor(dt / self.ss))

        hashbase = ''
        hashbase = hashbase + self.name
        hashbase = hashbase + '%.8f' % vf
        hashbase = hashbase + '%.8f' % v0
        hashbase = hashbase + '%.8f' % N
        hashbase = hashbase + '%.8f' % dt
        hashbase = hashbase + rawcalibdat(self.name)

        ramphash = seqconf.ramps_dir() + 'linearPhys_' \
                    + hashlib.md5( hashbase ).hexdigest()

        if not os.path.exists(ramphash) or True:
            print '...Making new linearPhys ramp for ' + self.name

            x = numpy.linspace(v0 + (vf - v0) / N, vf, N)
            ramp = physics.cnv(self.name, x)

            #yramp= numpy.array([cnv(self.name,v0 + 1.0*(vf-v0)*(i+1)/N) for i in range(N)])

            #if ( numpy.absolute( yramp - ramp ) > 0.0001 ).any():
            #	print "NOT EQUAL!"
            #else:
            #	print "EQUAL!"

            #ramp.tofile(ramphash,sep=',',format="%.4f")

        else:
            print '...Recycling previously calculated linearPhys ramp for ' + self.name
            ramp = numpy.fromfile(ramphash, sep=',')

        self.y = numpy.append(self.y, ramp)
        self.lastPhys = vf

        return
예제 #4
0
 def cnv(self, ch, val,errorshow = 1):
     if ch not in self.fs.keys():
         
         print "Channels with defined conversions: "
         pprint.pprint(self.fs.keys())
         if errorshow:
             errormsg.box('CONVERSION : ' + ch, 'No conversion defined for this channel')
         raise ValueError("No conversion has been defined for channel = %s" % ch )
         return None
         
     out = self.fs[ch](  self.cnvcalib[ch]( val) )
     return self.check( ch, val, out)[0]
예제 #5
0
    def cnv(self, ch, val, errorshow=1):
        if ch not in self.fs.keys():

            print "Channels with defined conversions: "
            pprint.pprint(self.fs.keys())
            if errorshow:
                errormsg.box('CONVERSION : ' + ch,
                             'No conversion defined for this channel')
            raise ValueError(
                "No conversion has been defined for channel = %s" % ch)
            return None

        out = self.fs[ch](self.cnvcalib[ch](val))
        return self.check(ch, val, out)[0]
예제 #6
0
    def cnvcalib(self, phys):
        # odt phys to volt conversion
        # max odt power = 10.0
        
        volt = b+m1*kink1 + m2*(kink2-kink1) + m3*(phys-kink2) if phys > kink2 else \
                b+m1*kink1 + m2*(phys-kink1) if phys > kink1 else b+m1*phys

        if volt >10:
            volt=10.	
            if self.GT10warning==False:
                errormsg.box('OdtpowConvert','Odtpow conversion has resulted in a value greater than 10 Volts!'\
                                        +' \n\nResult will be coerced and this warning will not be shown again')
                self.GT10warning=True
        if volt <0.:
            volt=0.
            if self.LT0warning==False:
                errormsg.box('OdtpowConvert','Odtpow conversion has resulted in a value less than 0 Volts!' \
                                        + '\n\nResult will be coerced and this warning will not be shown again')
                self.LT0warning=True                    
                    
        return volt
예제 #7
0
    def cnvcalib(self, phys):
        # odt phys to volt conversion
        # max odt power = 10.0

        volt = b+m1*kink1 + m2*(kink2-kink1) + m3*(phys-kink2) if phys > kink2 else \
                b+m1*kink1 + m2*(phys-kink1) if phys > kink1 else b+m1*phys

        if volt > 10:
            volt = 10.
            if self.GT10warning == False:
                errormsg.box('OdtpowConvert','Odtpow conversion has resulted in a value greater than 10 Volts!'\
                                        +' \n\nResult will be coerced and this warning will not be shown again')
                self.GT10warning = True
        if volt < 0.:
            volt = 0.
            if self.LT0warning == False:
                errormsg.box('OdtpowConvert','Odtpow conversion has resulted in a value less than 0 Volts!' \
                                        + '\n\nResult will be coerced and this warning will not be shown again')
                self.LT0warning = True

        return volt
예제 #8
0
	def follow(self, bfield):
		### Levitation voltage:
		###
		### Vlev = slope * I + offset
		###
		### wherer I is the current on the bias coils
		### slope and offset have been calibrated and are set below:
		
		## These numbers are now store in physics.py
		## slope = 0.0971
		## offset = -2.7232
		
		if self.ss != bfield.ss:
			msg = "ERROR in GRADIENT wave:  step size does not match the bfield ramp!"
			print msg
			errormsg.box('gradient_wave.follow', msg)
			exit(1)
		
		print "...Setting GRADIENT to follow bfield ramp"
		
		bfieldV = numpy.copy(bfield.y)
		bfieldA = physics.inv( 'bfield', bfieldV)
		#~ self.y = slope * bfieldA + offset
		self.y= np.array([physics.cnv( 'gradientfield', bA) for bA in bfieldA])
예제 #9
0
    def _check_bounds(self, x_new):
        """Check the inputs for being in the bounds of the interpolated data.

        Parameters
        ----------
        x_new : array

        Returns
        -------
        out_of_bounds : bool array
            The mask on x_new of values that are out of the bounds.
        """

        # If self.bounds_error is True, we raise an error if any x_new values
        # fall outside the range of x.  Otherwise, we return an array indicating
        # which values are outside the boundary region.
        below_bounds = x_new < self.x[0]
        above_bounds = x_new > self.x[-1]
        
        # !! Could provide more information about which values are out of bounds
        if self.bounds_error and below_bounds.any():
            out_of_bounds_below = None
              
            msg = "The following values are below the interpolation range: "

            if x_new.ndim < 1:
                out_of_bounds_below = x_new
                msg = msg + '\n\t' + str(out_of_bounds_below) 
            else:
                out_of_bounds_below  = x_new[ np.where( x_new < self.x[0] ) ]
                msg = msg + '\n\t' + str(out_of_bounds_below) 
            
            print msg 
              
            errormsg.box('INTERPOLATION :: ' + self.name, msg)

            raise ValueError("A value in x_new is below the interpolation "
                "range.")
                
                
        if self.bounds_error and above_bounds.any():
            out_of_bounds_above = None
              
            msg = "The following values are above the interpolation range: "

            if x_new.ndim < 1:
                out_of_bounds_above = x_new
                msg = msg + '\n\t' + str(out_of_bounds_above) 
            else:
                out_of_bounds_above  = x_new[ np.where( x_new < self.x[0] ) ]
                msg = msg + '\n\t' + str(out_of_bounds_above) 
            
            print msg 
              
            errormsg.box('INTERPOLATION :: ' + self.name, msg)

            raise ValueError("A value in x_new is above the interpolation "
                "range.")
            

        # !! Should we emit a warning if some values are out of bounds?
        # !! matlab does not.
        out_of_bounds = logical_or(below_bounds, above_bounds)
        return out_of_bounds
예제 #10
0
def dimple_to_lattice(s,cpowend):
    
    print "----- LATTICE LOADING RAMPS -----"

    # Find out which is the longest of the ramps we are dealing with:
    maxX =max( [xdomain(DL.latticeV0)[1] ,\
         xdomain(DL.irpow)[1],\
         xdomain(DL.grpow1)[1],\
         xdomain(DL.grpow2)[1],\
         xdomain(DL.grpow3)[1],\
         xdomain(DL.a_s)[1]] )
    print "Largest x value = %.3f ms\n" %  maxX
   
    # We define the times for which all functions will be evaluated
    # MIN TIME TO DO DIGITAL EXTENSION
    DIGEXTENSION = 2050.
    if DL.image >= DIGEXTENSION:
        Xendtime = DIGEXTENSION
    else:
        Xendtime = DL.image

    Nnew = int(math.floor( Xendtime / DL.ss) )  
    Xnew = numpy.arange( Xendtime/Nnew, DL.image, Xendtime/Nnew ) 
    print "X array defined from dt:"
    print "DL.ss =", DL.ss
    print "x0  = ",Xnew[0]
    print "xf  = ",Xnew[-1]
    print "xdt = ",Xnew[1]-Xnew[0]
    print "%d samples" % Nnew
    print 'x shape = ', Xnew.shape
    
    # Define how we want to ramp up the lattice depth
    v0_ramp, xy_v0, v0set =  interpolate_ramp( DL.latticeV0)
    v0  = v0_ramp(Xnew)
                        
    
    
    ###########################################
    #### AXIS DEFINITIONS FOR PLOTS ###
    ###########################################    
    
    fig = plt.figure( figsize=(4.5*1.05,8.*1.1))
    ax0 = fig.add_axes( [0.18,0.76,0.76,0.20]) 
    ax2 = fig.add_axes( [0.18,0.645,0.76,0.11])
    ax3 = fig.add_axes( [0.18,0.53,0.76,0.11])
    ax1 = fig.add_axes( [0.18,0.415,0.76,0.11])
    ax5 = fig.add_axes( [0.18,0.30,0.76,0.11])
    ax4 = fig.add_axes( [0.18,0.185,0.76,0.11])
    ax6 = fig.add_axes( [0.18,0.07,0.76,0.11])

    allax = [ax0, ax1, ax2, ax3, ax4, ax5, ax6]
    for ax in allax:
        ax.axvline( DL.image, linewidth = 1., color='black', alpha=0.6)
    
    lw=1.5
    labelx=-0.12
    legsz =8.
    
    xymew=0.5
    xyms=9
    
    
    ax0.plot( Xnew, v0, 'b', lw=2.5, label='Lattice depth')
    ax0.plot(xy_v0[:,0],xy_v0[:,1], 'x', color='blue', ms=5.)
    ax0.plot(v0set[:,0],v0set[:,1], '.', mew=xymew, ms=xyms, color='blue')
    
    
    ###########################################
    #### USER DEFINED RAMPS: IR, GR, and U ###
    ###########################################      
    
    # Define how we want to ramp up the IR power
    if DIMPLE.allirpow > 0.:
      ir_offset = DIMPLE.allirpow
    else:
      ir_offset = DIMPLE.ir1pow2
    ir_ramp, xy_ir, ir =  interpolate_ramp( DL.irpow, yoffset=ir_offset)
    
    dt_ir = numpy.amax( ir[:,0]) - numpy.amin( ir[:,0])
    N_ir = int(math.floor( dt_ir / DL.ss ))
    x_ir = numpy.arange( dt_ir/N_ir, dt_ir, dt_ir/N_ir)
    
    y_ir = ir_ramp(Xnew)
    
    if v0.size > y_ir.size:
        y_ir = numpy.append(y_ir, (v0.size-y_ir.size)*[y_ir[-1]])
    elif v0.size < y_ir.size:
        y_ir = y_ir[0:v0.size]
        
    if v0.size != y_ir.size:
        msg = "IRPOW ERROR: number of samples in IR ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
        
   
    alpha_clip_range = 0.1 
    if (v0 > y_ir+ alpha_clip_range).any():
        msg = "IRPOW ERROR:  not enough power to get desired lattice depth"
        print msg
        bad = numpy.where( v0 > y_ir + alpha_clip_range)
        timefail =  int(bad[0][0])*float(DL.ss)
        msg = msg + "\nFirst bad sample = %d out of %d" % (bad[0][0], v0.size)
        msg = msg + "\n  t = %f " %  timefail
        msg = msg + "\n v0 = %f " %   v0[ bad[0][0] ]
        msg = msg + "\n ir = %f " % y_ir[ bad[0][0] ]
        print v0[bad[0][0]]
        print y_ir[bad[0][0]]
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
    
    ax0.plot(xy_ir[:,0],xy_ir[:,1], 'x', color='darkorange', ms=5.)
    ax0.plot(ir[:,0],ir[:,1], '.', mew=xymew, ms=xyms, color='darkorange')
    ax0.plot(Xnew, y_ir, lw=lw, color='darkorange',label='irpow')
    
    
    # Define how we want to ramp up the GR power
    grwfms = {}
    splmrkr = ['x','+','d']
    ptsmrkr = ['^','s','p']
    for i,grramp in enumerate([(DL.grpow1,DIMPLE.gr1pow2), (DL.grpow2,DIMPLE.gr2pow2), (DL.grpow3,DIMPLE.gr3pow2)]):
      ramppts = grramp[0]
      ramp0 = grramp[1] 

      print 'gr'+'%d'%i +' offset = %f' % ramp0

      gr_ramp, xy_gr, gr =  interpolate_ramp( ramppts, yoffset=ramp0)
    
      dt_gr = numpy.amax( gr[:,0]) - numpy.amin( gr[:,0])
      N_gr = int(math.floor( dt_gr / DL.ss ))
      x_gr = numpy.arange( dt_gr/N_gr, dt_gr, dt_gr/N_gr)
    
      y_gr = gr_ramp(Xnew)
      if DL.signal == 0:
          y_gr = y_gr / 2.0
    
      if v0.size > y_gr.size:
          y_gr = numpy.append(y_gr, (v0.size-y_gr.size)*[y_gr[-1]])
      elif v0.size < y_gr.size:
          y_gr = y_gr[0:v0.size]
        
      if v0.size != y_gr.size:
          msg = "GRPOW ERROR: number of samples in GR ramp and V0 ramp does not match!"
          errormsg.box('LATTICE LOADING ERROR',msg)
          exit(1)

      grwfms[ 'greenpow' + '%1d' % (i+1) ] = y_gr 

      ax0.plot(xy_gr[:,0],xy_gr[:,1], marker= splmrkr[i] ,mec='green', mfc='None', ms=3.)
      ax0.plot(gr[:,0],gr[:,1], marker=ptsmrkr[i], mew=xymew, ms=xyms/2., mfc='None', mec='green')#, label='grpow dat')
      ax0.plot(Xnew, y_gr, lw=lw, color='green', label='grpow')

    for grch in grwfms.keys():
      print grch, " = ", grwfms[grch].shape
    
    ax0.set_xlim(left=-10., right= ax0.get_xlim()[1]*1.1)   
    plt.setp( ax0.get_xticklabels(), visible=False)
    ylim = ax0.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax0.set_ylim( ylim[0]-extra, ylim[1]+extra )
    ax0.grid(True)
    ax0.set_ylabel('$E_{r}$',size=16, labelpad=0)
    ax0.yaxis.set_label_coords(labelx, 0.5)
    ax0.set_title('Lattice Loading')
    ax0.legend(loc='best',numpoints=1,prop={'size':legsz*0.8})
    
    
    # Define how we want to ramp up the scattering length (control our losses)
    a_s_ramp, xy_a_s, a_s =  interpolate_ramp( DL.a_s)
    
    
    dt_a_s = numpy.amax( a_s[:,0]) - numpy.amin( a_s[:,0])
    N_a_s = int(math.floor( dt_a_s / DL.ss ))
    x_a_s = numpy.arange( dt_a_s/N_a_s, dt_a_s, dt_a_s/N_a_s)
    y_a_s = a_s_ramp(Xnew)

   
    
    if v0.size > y_a_s.size:
        y_a_s = numpy.append(y_a_s, (v0.size-y_a_s.size)*[y_a_s[-1]])
    elif v0.size < y_a_s.size:
        y_a_s = y_a_s[0:v0.size]
        
    if v0.size != y_a_s.size:
        msg = "a_s ERROR: number of samples in a_s ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
    
    
    
    ax1.plot(xy_a_s[:,0],xy_a_s[:,1]/100., 'x', color='#C10087', ms=5.)
    ax1.plot(a_s[:,0],a_s[:,1]/100., '.', mew=xymew, ms=xyms, color='#C10087')
    ax1.plot(Xnew, y_a_s/100., lw=lw, color='#C10087', label=r'$a_s\mathrm{(100 a_{0})}$')
    ax1.set_ylabel(r'$a_s\mathrm{(100 a_{0})}$',size=16, labelpad=0)
    ax1.yaxis.set_label_coords(labelx, 0.5)

    
    ax1.set_xlim( ax0.get_xlim()) 
    ylim = ax1.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax1.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax1.get_xticklabels(), visible=False)
    ax1.grid(True)
    ax1.legend(loc='best',numpoints=1,prop={'size':legsz})
    

    #######################################################################
    #### CALCULATED RAMPS:  ALPHA, TUNNELING, SCATTERING LENGTH, BFIELD ###
    #######################################################################
    
    alpha = (v0/y_ir)**2.
    
    alpha_advance = 100.
    N_adv = int(math.floor( alpha_advance / DL.ss))
    
    alpha  = alpha.clip(0.,1.)
    alpha_desired = numpy.copy(alpha)
    
    if N_adv < v0.size:
        alpha = alpha[N_adv:]
        alpha = numpy.append(alpha, (v0.size-alpha.size)*[alpha[-1]])
    else:
        alpha = numpy.array( v0.size*[alpha[-1]] )
    
    #alpha = alpha.clip(0., 1.)
    
    ax2.plot( Xnew, alpha, lw=lw, color='saddlebrown', label='alpha adv')
    ax2.plot( Xnew, alpha_desired,':', lw=lw, color='saddlebrown', label='alpha')
    
    ax2.set_xlim( ax0.get_xlim()) 
    ax2.set_ylim(-0.05,1.05)
    plt.setp( ax2.get_xticklabels(), visible=False)
    ax2.grid()
    ax2.set_ylabel('$\\alpha$',size=16, labelpad=0)
    ax2.yaxis.set_label_coords(labelx, 0.5)
    
    ax2.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    tunneling_Er  = physics.inv('t_to_V0', v0)
    tunneling_kHz = tunneling_Er * 29.2
    
    ax3.plot( Xnew, tunneling_kHz, lw=lw, color='red', label='$t$ (kHz)')

    
    ax3.set_xlim( ax0.get_xlim()) 
    ylim = ax3.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax3.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax3.get_xticklabels(), visible=False)
    ax3.grid(True)
    ax3.set_ylabel(r'$t\,\mathrm{(kHz)}$',size=16, labelpad=0)
    ax3.yaxis.set_label_coords(labelx, 0.5)
    ax3.legend(loc='best',numpoints=1,prop={'size':legsz})

    
    wannierF = physics.inv('wF_to_V0', v0)
     
    bohrRadius = 5.29e-11 #meters
    lattice_spacing = 1.064e-6 / 2. #meters
    
    bfieldG = physics.cnv('as_to_B', y_a_s)
    print 
    print "The last value of the scattering length ramp is:"
    print 'a_s =', y_a_s[-1]
    print 'B   =', bfieldG[-1]
    print 
    
    U_over_t = y_a_s * bohrRadius / lattice_spacing * wannierF / tunneling_Er
    
    
    
    
    ax4.plot( Xnew, U_over_t, lw=lw, color='k', label=r'$U/t$')
    
    ax4.set_xlim( ax0.get_xlim()) 
    ylim = ax4.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax4.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax4.get_xticklabels(), visible=False)
    ax4.grid(True)
    ax4.set_ylabel(r'$U/t$',size=16, labelpad=0)
    ax4.yaxis.set_label_coords(labelx, 0.5)
    
    ax4.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    ax5.plot( Xnew, bfieldG, lw=lw, color='purple', label='$B$ (G)')
    
    ax5.set_xlim( ax0.get_xlim()) 
    ylim = ax5.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax5.set_ylim( ylim[0]-extra, ylim[1]+extra )
    ax5.grid(True)
    plt.setp( ax5.get_xticklabels(), visible=False)
    ax5.set_ylabel(r'$B\,\mathrm{(G)}$',size=16, labelpad=0)
    ax5.yaxis.set_label_coords(labelx, 0.5)
    
    
    ax5.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    ax6.plot( Xnew, (tunneling_Er / U_over_t), lw=lw, color='#25D500', label=r'$t^{2}/U\,(E_{r)}$')
    #ax6.set_yscale('log')
    
    ax6.set_xlim( ax0.get_xlim()) 
    ylim = ax6.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax6.set_ylim( ylim[0]*0.5, ylim[1] )
    ax6.grid(True)
    ax6.set_ylabel(r'$t^{2}/U\,(E_{r)}$',size=16, labelpad=0)
    ax6.yaxis.set_label_coords(labelx, 0.5)
    
    
    ax6.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    ax6.set_xlabel('time (ms)')

    figfile = seqconf.seqtxtout().split('.')[0]+'_latticeRamp.png'    
    plt.savefig(figfile , dpi=120 )
    
    #Save all ramps to a txt file for later plotting. 
    datfile = seqconf.seqtxtout().split('.')[0]+'_latticeRamp.dat'
    allRamps = numpy.transpose(numpy.vstack((Xnew, v0, y_ir, grwfms['greenpow1'], y_a_s, alpha, alpha_desired, \
                                    tunneling_kHz, U_over_t, bfieldG)))
    header = '# Column index'
    header = header + '\n#\t0\t' + 'time(ms)'
    header = header + '\n#\t1\t' + 'Lattice Depth (Er)'
    header = header + '\n#\t2\t' + 'Ir power (Er)'
    header = header + '\n#\t3\t' + 'GR power (Er)'
    header = header + '\n#\t4\t' + 'a_s (a0)'
    header = header + '\n#\t5\t' + 'alpha - advance'
    header = header + '\n#\t6\t' + 'alpha - desired'
    header = header + '\n#\t7\t' + 'tunneling (kHz)'
    header = header + '\n#\t8\t' + 'U/t'
    header = header + '\n#\t9\t' + 'bfield (Gauss)'
    header = header + '\n'
    
    numpy.savetxt( datfile, allRamps)
    
    with open(datfile, 'w') as f:
        X = numpy.asarray( allRamps )
        f.write(bytes(header))
        
        format = '%.6e'
        ncol = X.shape[1]
        format = [format ,] *ncol
        format = ' '.join(format)
        
        newline = '\n'
        for row in X:
            f.write(numpy.compat.asbytes(format % tuple(row) + newline))

    
    shutil.copyfile( figfile,  seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png')
    shutil.copyfile( datfile,  seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.dat')
    #plt.savefig( seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png', dpi=120)
    
    
    #################################
    #### APPEND RAMPS TO SEQUENCE ###
    #################################
    
    wfms=[]

    if DL.signal == 0:
          print " LOCK VALUE FOR SIGNAL / NOSIGNAL "
          print " before = ", DL.lock_Er
          DL.lock_Er = DL.lock_Er / 1.8
          print " after  = \n", DL.lock_Er
    
    for ch in ['ir1pow','ir2pow','ir3pow']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        w.y = physics.cnv( ch, y_ir )
        if DL.lock:
            endval = w.y[-1]
            w.insertlin_cnv(DL.lock_Er, DL.lock_dtUP, DL.lock_t0 )
        elif DL.lightassist_lock:
            endval = w.y[-1]
            w.linear(DL.lightassist_lockpowIR, DL.lightassist_lockdtUP)
            w.appendhold( DL.lightassist_t0 + DL.lightassistdt )
            if DL.endvalIR >= 0.:
                w.linear(  DL.endvalIR, DL.lightassist_lockdtDOWN)
            else:
                w.linear(  None, DL.lightassist_lockdtDOWN, volt=endval)
        wfms.append(w)
        
    for ch in ['greenpow1','greenpow2','greenpow3']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        
        correction = DIMPLE.__dict__['gr'+n+'correct']
        
        w.y = physics.cnv( ch, correction * grwfms[ch] )
        if DL.lightassist_lock:
            endval = w.y[-1]
            w.linear(DL.lightassist_lockpowGR, DL.lightassist_lockdtUP)
            w.appendhold( DL.lightassist_t0 + DL.lightassistdt )
            if DL.endvalGR >= 0.:
                w.linear(  DL.endvalGR, DL.lightassist_lockdtDOWN)
            else:
                w.linear(  None, DL.lightassist_lockdtDOWN, volt=endval)
        wfms.append(w)
     

    for ch in ['lcr1','lcr2','lcr3']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        force = DL.__dict__['force_'+ch]
        if force >= 0 and force <=1:
            print "...Forcing LCR%s = %f during lattice ramp" % (n,force)
            w.y = physics.cnv( ch, numpy.array( alpha.size*[force] )  )
        elif DL.signal == 0:
            print "...Forcing LCR%s = 0. so that it does NOT rotate to LATTICE" % n 
            w.y = physics.cnv( ch, numpy.array( alpha.size*[0.0] )  )
        else:
            w.y = physics.cnv( ch, alpha )
        wfms.append(w)
    

    
    bfieldA = bfieldG/6.8
    
    ##ADD field
    bfield = wfm.wave('bfield', 0.0, DL.ss)
    bfield.y = physics.cnv( 'bfield', bfieldA)
    print "The last value of the bfield voltage is =", bfield.y[-1]
    print 
    wfms.append(bfield)
    
    
    ##ADD gradient field
    gradient = gradient_wave('gradientfield', 0.0, DL.ss,volt = 0.0)
    gradient.follow(bfield)
    wfms.append(gradient)
   
    
    buffer = 40.
    s.wait(buffer)
    
    
    #~ odtpow = odt.odt_wave('odtpow', cpowend, DL.ss)
    #~ if DIMPLE.odt_t0 > buffer :
        #~ odtpow.appendhold( DIMPLE.odt_t0 - buffer)
    #~ if DIMPLE.odt_pow < 0.:
        #~ odtpow.appendhold( DIMPLE.odt_dt)
    #~ else:
        #~ odtpow.tanhRise( DIMPLE.odt_pow, DIMPLE.odt_dt, DIMPLE.odt_tau, DIMPLE.odt_shift)    
        
    #~ if numpy.absolute(DIMPLE.odt_pow) < 0.0001:
        #~ s.wait( odtpow.dt() )
        #~ s.digichg('odtttl',0)
        #~ s.wait(-odtpow.dt() )
    
    #~ wfms.append(odtpow)
        
    
    # RF sweep
    if DL.rf == 1:   
        rfmod  = wfm.wave('rfmod', 0., DL.ss)
        rfmod.appendhold( bfield.dt() + DL.rftime )
        rfmod.linear( DL.rfvoltf, DL.rfpulsedt)
        wfms.append(rfmod)


    if DL.round_trip == 1:
        bindex = 0  # Calculate detunings using starting field
    else: 
        bindex = -1 # Calculate detunings using field at the end of ramps

    bfieldG = physics.inv( 'bfield', bfield.y[bindex]) * 6.8
    hfimg0 = -1.*(100.0 + 163.7 - 1.414*bfieldG)
   
    # Find bindex for braggkill time 
    bindex_BK =  math.floor(-DL.braggkilltime / bfield.ss)
    bfieldG_BK = physics.inv( 'bfield', bfield.y[-1-bindex_BK]) * 6.8
    hfimg0_BK =  -1.*(100.0 + 163.7 - 1.414*bfieldG_BK) 
    DL.braggkill_hfimg = hfimg0_BK - DL.braggkill_hfimg
    print "\n...Braggkill hfimg modification:\n"
    print "\tNEW braggkill_hfimg = %.2f MHz" % DL.braggkill_hfimg

    # Find bindex for bragg2kill time 
    bindex_B2K =  math.floor(-DL.bragg2killtime / bfield.ss)
    bfieldG_B2K = physics.inv( 'bfield', bfield.y[-1-bindex_B2K]) * 6.8
    hfimg0_B2K =  -1.*(100.0 + 163.7 - 1.414*bfieldG_B2K) 
    DL.bragg2kill_hfimg1 = hfimg0_B2K - DL.bragg2kill_hfimg1
    DL.bragg2kill_hfimg2 = hfimg0_B2K - DL.bragg2kill_hfimg2
    print "\n...Bragg2kill hfimg modification:\n"
    print "\tNEW brag2gkill_hfimg1 = %.2f MHz" % DL.bragg2kill_hfimg1
    print "\tNEW brag2gkill_hfimg2 = %.2f MHz" % DL.bragg2kill_hfimg2
    
    
    print "\n...ANDOR:hfimg and hfimg0 will be modified  in report\n"
    print "\tNEW  ANDOR:hfimg  = %.2f MHz" % ( hfimg0 - DL.imgdet)
    print "\tNEW  ANDOR:hfimg0 = %.2f MHz\n" %  hfimg0
    gen.save_to_report('ANDOR','hfimg', hfimg0 - DL.imgdet)
    gen.save_to_report('ANDOR','hfimg0', hfimg0)
    
    newANDORhfimg = hfimg0 - DL.imgdet

    # THIS DEFINES THE TIME IT TAKES THE OFFSET LOCK TO SWITCH TO
    # A NEW SETPOINT
    hfimgdelay = 50. #ms
        
    # Kill hfimg
    if DL.probekill ==1 or DL.braggkill ==1 or  DL.bragg2kill==1 or DL.lightassist or DL.lightassist_lock:
        analogimg = wfm.wave('analogimg', newANDORhfimg, DL.ss)
        
        if DL.probekill == 1:
            if (-DL.probekilltime+hfimgdelay) < DL.image:
                analogimg.appendhold( bfield.dt() + DL.probekilltime - hfimgdelay)
                analogimg.linear( DL.probekill_hfimg , 0.0)
                analogimg.appendhold( hfimgdelay + DL.probekilldt + 3*DL.ss)
        
        elif DL.braggkill == 1:
            print "Setting up analogimg for braggkill"
            if (-DL.braggkilltime+hfimgdelay) < DL.image:
                analogimg.appendhold( bfield.dt() + DL.braggkilltime - hfimgdelay)
                analogimg.linear( DL.braggkill_hfimg , 0.0)
                analogimg.appendhold( hfimgdelay + DL.braggkilldt + 3*DL.ss)
 
        elif DL.bragg2kill == 1:
            print "Setting up analogimg for bragg2kill"
            if (-DL.bragg2killtime+hfimgdelay) < DL.image:
                # This sets up the detuning for the first pulse
                analogimg.appendhold( bfield.dt() + DL.bragg2killtime - hfimgdelay)
                analogimg.linear( DL.bragg2kill_hfimg1 , 0.0)
                analogimg.appendhold( hfimgdelay + DL.bragg2killdt + 3*DL.ss)
 
                # Then set up the detuning for the second pulse
                analogimg.linear( DL.bragg2kill_hfimg2 , 0.0)
                analogimg.appendhold( hfimgdelay + DL.bragg2killdt + 3*DL.ss)
                
            
        
        elif DL.lightassist == 1 or DL.lightassist_lock:
            analogimg.appendhold( bfield.dt()  - hfimgdelay)
            analogimg.linear( DL.lightassist_hfimg , 0.0)
            duration = DL.lightassist_lockdtUP + DL.lightassist_t0 + DL.lightassistdt + DL.lightassist_lockdtDOWN
            analogimg.appendhold( hfimgdelay + duration + 3*DL.ss)
            
        analogimg.linear( newANDORhfimg, 0.)
        analogimg.extend(10)
        wfms.append(analogimg)
    
        

    
    #analogimg = bfieldwfm.hfimg_wave('analogimg', ANDOR.hfimg, DL.ss)
    #andorhfimg0 = analogimg.follow(bfield, DL.imgdet)
    #wfms.append(analogimg)
    

    # If we are doing round trip END, then mirror all the ramps 
    # before adding them to the sequence
    if DL.round_trip == 1:
        if DL.round_trip_type == 1:
            maxdt = 0.
            maxi = -1
            for i,w in enumerate(wfms):
                if w.dt() > maxdt:
                    maxdt = w.dt()
                    maxi = i
    
            maxdt = maxdt + DL.wait_at_top / 2. 
    
            for w in wfms:
                w.extend(maxdt)
                if 'lcr' in w.name:
                    yvals = w.y
                    
                    #Get the reverse of the alpha desired array
                    alpha_mirror = numpy.copy(alpha_desired[::-1])
                    
                    #Add the wait at top part so that it has same length as yvals
                    if alpha_mirror.size > yvals.size:
                        print "Error making mirror ramp for LCR."
                        print "Program will exit."
                        exit(1)
                    alpha_mirror = numpy.append( (yvals.size - alpha_mirror.size)*[ alpha_mirror[0] ], alpha_mirror )
                    
                                   
                    #This is how much the mirror ramp will be advanced
                    N_adv = int(math.floor( DL.lcr_mirror_advance / DL.ss))
                    
                    if N_adv < alpha_mirror.size:
                        alpha_mirror = alpha_mirror[N_adv:]
                        alpha_mirror = numpy.append(alpha_mirror, (yvals.size-alpha_mirror.size)*[alpha_mirror[-1]])
                    else:
                        alpha_mirror = numpy.array( yvals.size*[alpha_mirror[-1]] )
                    
                    
                    
                    w.y = numpy.concatenate((yvals,physics.cnv( w.name, alpha_mirror )))
                else:
                    w.mirror()
                w.appendhold( DL.wait_at_end)
            
        
    
    N_adv = int(math.floor( alpha_advance / DL.ss))
    
    alpha_desired = numpy.copy(alpha)
    
    
    for wavefm in wfms:
        print "%s dt = %f" % (wavefm.name, wavefm.dt())
   
     
    
    duration = s.analogwfm_add(DL.ss,wfms)
    
    if DL.image < DIGEXTENSION:
        s.wait(duration)
    else:
        print "...DL.image = %f  >= %.2f  Digital seq extension will be used." % (DL.image, DIGEXTENSION)
        s.wait( DL.image )
        
    
    ### Prepare the parts of the ramps that are going to be used to mock
    ### the conditions for the noatoms shot
    ### 1. get dt = [noatoms] ms from the end of the lattice ramps.
    if 'manta' in DL.camera:
        noatomsdt = MANTA.noatoms
    else:
        noatomsdt = ANDOR.noatoms
    noatomswfms = []
    for wavefm in wfms:
        cp = copy.deepcopy( wavefm ) 
        cp.idnum = time.time()*100
        cp.retain_last( DL.bgRetainDT )
        noatomswfms.append( cp ) 
    
        
        
    
    
    
    ### Figure out when to turn interlock back on, using alpha information
    #~ if duration > DL.t0 + DL.dt:
        #~ s.wait(-DL.lattice_interlock_time)
        #~ if DL.use_lattice_interlock == 1:
            #~ s.digichg('latticeinterlockbypass',0)
        #~ else:
            #~ s.digichg('latticeinterlockbypass',1)
        #~ s.wait( DL.lattice_interlock_time)
        
        
    #########################################
    ## OTHER TTL EVENTS: probekill, braggkill, rf, quick2
    #########################################
    # Braggkill
    if DL.braggkill == 1:
        print "Using Bragg Kill"
        s.wait( DL.braggkilltime)
        s = manta.OpenShutterBragg(s,DL.shutterdelay)
        s.digichg('bragg',1)
        s.wait( DL.braggkilldt)
        s.digichg('brshutter',1) # to close shutter
        s.digichg('bragg',0)
        
        s.wait( -DL.braggkilldt)
        s.wait( -DL.braggkilltime )

    if DL.bragg2kill == 1:
        print "Using Bragg 2 Kill"
        tcur = s.tcur 
        s.wait( DL.bragg2killtime )
        s = manta.OpenShutterBragg(s,DL.shutterdelay)
        s.digichg('bragg',1)
        s.wait( DL.bragg2killdt)
        s.digichg('brshutter',1) # to close shutter
        s.digichg('bragg',0)
  
        s.wait( hfimgdelay + 3*DL.ss )
        s = manta.OpenShutterBragg(s,DL.shutterdelay)
        s.digichg('bragg',1)
        s.wait( DL.bragg2killdt)
        s.digichg('brshutter',1) # to close shutter
        s.digichg('bragg',0)

        # Revert to current time after pulses have been added in the past
        s.tcur = tcur

        
       
        
         

    # Probe Kill
    if DL.probekill == 1:
        s.wait(DL.probekilltime)
        
        s.wait(-10)
        s.digichg('prshutter',0)
        s.wait(10)
        s.digichg('probe',1)
        s.wait(DL.probekilldt)
        s.digichg('probe',0)

        s.digichg('prshutter',1)
        s.wait(-DL.probekilltime)


    # Pulse RF
    if DL.rf == 1:
        s.wait(DL.rftime)
        s.digichg('rfttl',1)
        s.wait(DL.rfpulsedt)
        s.digichg('rfttl',0)
        s.wait(-DL.rfpulsedt)
        s.wait(-DL.rftime)
        



    # QUICK2
    if DL.quick2 == 1:
        s.wait( DL.quick2time)
        s.digichg('quick2',1)
        s.wait(-DL.quick2time)
        

    # Light-assisted collisions
    if DL.lightassist == 1 or DL.lightassist_lock:
        s.wait( -DL.lightassist_lockdtUP -DL.lightassist_t0 -DL.lightassistdt -DL.lightassist_lockdtDOWN - 3*DL.ss)
        
        s.wait(DL.lightassist_lockdtUP + DL.lightassist_t0)
        s.wait(-10)
        s.digichg('prshutter',0)
        s.wait(10)
        s.digichg('probe', DL.lightassist)
        s.wait(DL.lightassistdt)
        s.digichg('probe',0)

        s.digichg('prshutter',1)
        s.wait(DL.lightassist_lockdtDOWN)
        s.wait(3*DL.ss)
        # After the collisions happen we still need to wait some time 
        # for the probe frequency to come back to the desired value
        s.wait(hfimgdelay)


    #########################################
    ## GO BACK IN TIME IF DOING ROUND-TRIP START
    #########################################
    if DL.round_trip == 1:
        if DL.round_trip_type == 0:
            s.wait( -DL.image )
            s.stop_analog()


    #########################################
    ## TURN GREEN OFF BEFORE PICTURES
    #########################################
    if DL.greenoff == 1:
      s.wait( DL.greenoff_t0 ) 
      s.digichg('greenttl1', 0)
      s.digichg('greenttl2', 0)
      s.digichg('greenttl3', 0)
      s.wait(-DL.greenoff_t0 ) 


    
    #########################################
    ## LATTICE LOCK WITH POSSIBILITY OF RF
    #########################################
    bufferdt = 5.0
    lastIR = y_ir[-1]
   
    lockwfms=[]
    if DL.locksmooth == 1 and DL.lock == 0:
        s.wait(bufferdt)
        for ch in ['ir1pow','ir2pow','ir3pow']:
            n = filter( str.isdigit, ch)[0]
            w = wfm.wave(ch, lastIR, DL.lockss)  #Start value will be overrriden
            w.tanhRise( DL.lock_Er, DL.lock_dtUP, 0.4,0.2)
            lockwfms.append(w)
        print "...LOCKING LATTICE TO %f Er" % DL.lock_Er
        print "...lastIR = %.4f" % lastIR
        duration = s.analogwfm_add(DL.lockss,lockwfms)
        print "...duration = %.2f" % duration
        s.wait(duration)
        #~ if DL.lockrf:
            #~ s.digichg('rfttl',1)
            #~ s.wait(DL.rfpulsedt)
            #~ s.digichg('rfttl',0)
        #~ s.wait(0.036)
    #else:
    #    s.wait(bufferdt)
  
    lockwfmscopy = []
    for wavefm in lockwfms:
        cp = copy.deepcopy( wavefm ) 
        cp.idnum = time.time()*100 + 1e3*numpy.random.randint(0,1e8)
        lockwfmscopy.append( cp ) 
        
    
    #########################################
    ## IMAGING AT LOW FIELD
    #########################################
    if DL.lowfieldimg == 1:
        s.wait(DL.lowfieldimg_t0)
        s.digichg('field',0)
        s.wait(-DL.lowfieldimg_t0)
    
    
    #########################################
    ## TTL RELEASE FROM ODT and LATTICE
    #########################################
    #INDICATE WHICH CHANNELS ARE TO BE CONSIDERED FOR THE BACKGROUND
    bg = ['odtttl','irttl1','irttl2','irttl3','greenttl1','greenttl2','greenttl3']
    bgdictPRETOF={}
    for ch in bg:
        bgdictPRETOF[ch] = s.digistatus(ch)
    bgdictPRETOF['tof'] = DL.tof
    print "\nChannel status for pictures: PRE-TOF"
    print bgdictPRETOF
    print
        
    #RELEASE FROM LATTICE
    if DL.tof <= 0.:
        s.wait(1.0+ANDOR.exp)
    s.digichg('greenttl1',0)
    s.digichg('greenttl2',0)
    s.digichg('greenttl3',0)
    s.digichg('irttl1',0)
    s.digichg('irttl2',0)
    s.digichg('irttl3',0)
    #RELEASE FROM IR TRAP
    s.digichg('odtttl',0)
    if DL.tof <= 0.:
        s.wait(-1.0+ANDOR.exp)

    print "TIME WHEN RELEASED FROM LATTICE = ",s.tcur
    s.wait(DL.tof)
    
    return s, noatomswfms, lockwfmscopy, bgdictPRETOF
예제 #11
0
    def _check_bounds(self, x_new):
        """Check the inputs for being in the bounds of the interpolated data.

        Parameters
        ----------
        x_new : array

        Returns
        -------
        out_of_bounds : bool array
            The mask on x_new of values that are out of the bounds.
        """

        # If self.bounds_error is True, we raise an error if any x_new values
        # fall outside the range of x.  Otherwise, we return an array indicating
        # which values are outside the boundary region.
        below_bounds = x_new < self.x[0]
        above_bounds = x_new > self.x[-1]

        
        # !! Could provide more information about which values are out of bounds
        if self.bounds_error and below_bounds.any():
            out_of_bounds_below = None
              
            msg = "Interpolation range = (%.4g,%.4g)\n" % (self.x[0], self.x[-1] )
            msg += "The following values are below the interpolation range: "

            if x_new.ndim < 1:
                out_of_bounds_below = x_new
                msg = msg + '\n\t' + str(out_of_bounds_below) 
            else:
                out_of_bounds_below  = x_new[ np.where( x_new < self.x[0] ) ]
                msg = msg + '\n\t' + str(out_of_bounds_below) 
            
            print msg 
              
            errormsg.box('INTERPOLATION :: ' + self.name, msg)

            raise ValueError("A value in x_new is below the interpolation "
                "range.")
                
                
        if self.bounds_error and above_bounds.any():
            out_of_bounds_above = None

            msg = "Interpolation range = (%.4g,%.4g)\n" % (self.x[0], self.x[-1] )
            msg += "The following values are above the interpolation range: "

            if x_new.ndim < 1:
                out_of_bounds_above = x_new
                msg = msg + '\n\t' + str(out_of_bounds_above) 
            else:
                out_of_bounds_above  = x_new[ np.where( x_new > self.x[-1] ) ]
                msg = msg + '\n\t' + str(out_of_bounds_above) 
            
            #print msg 
              
            errormsg.box('INTERPOLATION :: ' + self.name, msg)

            raise ValueError("A value in x_new is above the interpolation "
                "range.")
            

        # !! Should we emit a warning if some values are out of bounds?
        # !! matlab does not.
        out_of_bounds = logical_or(below_bounds, above_bounds)
        return out_of_bounds
예제 #12
0
def dimple_to_lattice(s, cpowend):

    print "----- LATTICE LOADING RAMPS -----"

    dt = DL.dt
    N0 = 0

    N = int(math.floor(dt / DL.ss))
    x = numpy.arange(dt / N, dt, dt / N)

    print "%d samples" % N
    print x.shape

    # Define how we want to ramp up the lattice depth
    v0_ramp, xy_v0, v0set = interpolate_ramp(DL.latticeV0)
    v0 = v0_ramp(x)

    NH = int(math.floor(DL.dthold / DL.ss))

    v0 = numpy.concatenate((numpy.zeros(N0), v0, numpy.array(NH * [v0[-1]])))

    x_v0 = numpy.arange(v0.size)
    x_v0 = x_v0 * DL.ss

    # Number of samples to keep
    NS = int(math.floor(DL.image / DL.ss))
    if NS > v0.size and DL.image < 2500.:
        x_v0 = numpy.append(x_v0, (NS - v0.size) * [x_v0[-1]])
        v0 = numpy.append(v0, (NS - v0.size) * [v0[-1]])

    else:
        x_v0 = x_v0[:NS]
        v0 = v0[:NS]

    ###########################################
    #### AXIS DEFINITIONS FOR PLOTS ###
    ###########################################

    fig = plt.figure(figsize=(4.5 * 1.05, 8. * 1.1))
    ax0 = fig.add_axes([0.18, 0.76, 0.76, 0.20])
    ax2 = fig.add_axes([0.18, 0.645, 0.76, 0.11])
    ax3 = fig.add_axes([0.18, 0.53, 0.76, 0.11])
    ax1 = fig.add_axes([0.18, 0.415, 0.76, 0.11])
    ax5 = fig.add_axes([0.18, 0.30, 0.76, 0.11])
    ax4 = fig.add_axes([0.18, 0.185, 0.76, 0.11])
    ax6 = fig.add_axes([0.18, 0.07, 0.76, 0.11])

    lw = 1.5
    labelx = -0.12
    legsz = 8.

    xymew = 0.5
    xyms = 9

    ax0.plot(x_v0, v0, 'b', lw=2.5, label='Lattice depth')
    ax0.plot(xy_v0[:, 0], xy_v0[:, 1], 'x', color='blue', ms=5.)
    ax0.plot(v0set[:, 0], v0set[:, 1], '.', mew=xymew, ms=xyms, color='blue')

    ###########################################
    #### USER DEFINED RAMPS: IR, GR, and U ###
    ###########################################

    # Define how we want to ramp up the IR power
    if DIMPLE.allirpow > 0.:
        ir_offset = DIMPLE.allirpow
    else:
        ir_offset = DIMPLE.ir1pow2
    ir_ramp, xy_ir, ir = interpolate_ramp(DL.irpow, yoffset=ir_offset)

    dt_ir = numpy.amax(ir[:, 0]) - numpy.amin(ir[:, 0])
    N_ir = int(math.floor(dt_ir / DL.ss))
    x_ir = numpy.arange(dt_ir / N_ir, dt_ir, dt_ir / N_ir)

    #y_ir = ir_spline(x_ir)
    y_ir = ir_ramp(x_ir)

    if v0.size > y_ir.size:
        y_ir = numpy.append(y_ir, (v0.size - y_ir.size) * [y_ir[-1]])
    elif v0.size < y_ir.size:
        y_ir = y_ir[0:v0.size]

    if v0.size != y_ir.size:
        msg = "IRPOW ERROR: number of samples in IR ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR', msg)
        exit(1)

    alpha_clip_range = 0.1
    if (v0 > y_ir + alpha_clip_range).any():
        msg = "IRPOW ERROR:  not enough power to get desired lattice depth"
        print msg
        bad = numpy.where(v0 > y_ir + alpha_clip_range)
        timefail = int(bad[0][0]) * float(DL.ss)
        msg = msg + "\nFirst bad sample = %d out of %d" % (bad[0][0], v0.size)
        msg = msg + "\n  t = %f " % timefail
        msg = msg + "\n v0 = %f " % v0[bad[0][0]]
        msg = msg + "\n ir = %f " % y_ir[bad[0][0]]
        print v0[bad[0][0]]
        print y_ir[bad[0][0]]
        errormsg.box('LATTICE LOADING ERROR', msg)
        exit(1)

    ax0.plot(xy_ir[:, 0], xy_ir[:, 1], 'x', color='darkorange', ms=5.)
    ax0.plot(ir[:, 0], ir[:, 1], '.', mew=xymew, ms=xyms, color='darkorange')
    ax0.plot(x_v0, y_ir, lw=lw, color='darkorange', label='irpow')

    # Define how we want to ramp up the GR power
    grwfms = {}
    splmrkr = ['x', '+', 'd']
    ptsmrkr = ['^', 's', 'p']
    for i, grramp in enumerate([(DL.grpow1, DIMPLE.gr1pow2),
                                (DL.grpow2, DIMPLE.gr2pow2),
                                (DL.grpow3, DIMPLE.gr3pow2)]):
        ramppts = grramp[0]
        ramp0 = grramp[1]

        print 'gr' + '%d' % i + ' offset = %f' % ramp0

        gr_ramp, xy_gr, gr = interpolate_ramp(ramppts, yoffset=ramp0)

        dt_gr = numpy.amax(gr[:, 0]) - numpy.amin(gr[:, 0])
        N_gr = int(math.floor(dt_gr / DL.ss))
        x_gr = numpy.arange(dt_gr / N_gr, dt_gr, dt_gr / N_gr)

        y_gr = gr_ramp(x_gr)

        if v0.size > y_gr.size:
            y_gr = numpy.append(y_gr, (v0.size - y_gr.size) * [y_gr[-1]])
        elif v0.size < y_gr.size:
            y_gr = y_gr[0:v0.size]

        if v0.size != y_gr.size:
            msg = "GRPOW ERROR: number of samples in GR ramp and V0 ramp does not match!"
            errormsg.box('LATTICE LOADING ERROR', msg)
            exit(1)

        grwfms['greenpow' + '%1d' % (i + 1)] = y_gr

        ax0.plot(xy_gr[:, 0],
                 xy_gr[:, 1],
                 marker=splmrkr[i],
                 mec='green',
                 mfc='None',
                 ms=3.)
        ax0.plot(gr[:, 0],
                 gr[:, 1],
                 marker=ptsmrkr[i],
                 mew=xymew,
                 ms=xyms / 2.,
                 mfc='None',
                 mec='green')  #, label='grpow dat')
        ax0.plot(x_v0, y_gr, lw=lw, color='green', label='grpow')

    for grch in grwfms.keys():
        print grch, " = ", grwfms[grch].shape

    ax0.set_xlim(left=-10., right=ax0.get_xlim()[1] * 1.1)
    plt.setp(ax0.get_xticklabels(), visible=False)
    ylim = ax0.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax0.set_ylim(ylim[0] - extra, ylim[1] + extra)
    ax0.grid(True)
    ax0.set_ylabel('$E_{r}$', size=16, labelpad=0)
    ax0.yaxis.set_label_coords(labelx, 0.5)
    ax0.set_title('Lattice Loading')
    ax0.legend(loc='best', numpoints=1, prop={'size': legsz * 0.8})

    # Define how we want to ramp up the scattering length (control our losses)
    a_s_ramp, xy_a_s, a_s = interpolate_ramp(DL.a_s)

    dt_a_s = numpy.amax(a_s[:, 0]) - numpy.amin(a_s[:, 0])
    N_a_s = int(math.floor(dt_a_s / DL.ss))
    x_a_s = numpy.arange(dt_a_s / N_a_s, dt_a_s, dt_a_s / N_a_s)
    y_a_s = a_s_ramp(x_a_s)

    if v0.size > y_a_s.size:
        y_a_s = numpy.append(y_a_s, (v0.size - y_a_s.size) * [y_a_s[-1]])
    elif v0.size < y_a_s.size:
        y_a_s = y_a_s[0:v0.size]

    if v0.size != y_a_s.size:
        msg = "a_s ERROR: number of samples in a_s ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR', msg)
        exit(1)

    ax1.plot(xy_a_s[:, 0], xy_a_s[:, 1] / 100., 'x', color='#C10087', ms=5.)
    ax1.plot(a_s[:, 0],
             a_s[:, 1] / 100.,
             '.',
             mew=xymew,
             ms=xyms,
             color='#C10087')
    ax1.plot(x_v0,
             y_a_s / 100.,
             lw=lw,
             color='#C10087',
             label=r'$a_s\mathrm{(100 a_{0})}$')
    ax1.set_ylabel(r'$a_s\mathrm{(100 a_{0})}$', size=16, labelpad=0)
    ax1.yaxis.set_label_coords(labelx, 0.5)

    ax1.set_xlim(ax0.get_xlim())
    ylim = ax1.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax1.set_ylim(ylim[0] - extra, ylim[1] + extra)
    plt.setp(ax1.get_xticklabels(), visible=False)
    ax1.grid(True)
    ax1.legend(loc='best', numpoints=1, prop={'size': legsz})

    #######################################################################
    #### CALCULATED RAMPS:  ALPHA, TUNNELING, SCATTERING LENGTH, BFIELD ###
    #######################################################################

    alpha = (v0 / y_ir)**2.

    alpha_advance = 100.
    N_adv = int(math.floor(alpha_advance / DL.ss))

    alpha = alpha.clip(0., 1.)
    alpha_desired = numpy.copy(alpha)

    if N_adv < v0.size:
        alpha = alpha[N_adv:]
        alpha = numpy.append(alpha, (v0.size - alpha.size) * [alpha[-1]])
    else:
        alpha = numpy.array(v0.size * [alpha[-1]])

    #alpha = alpha.clip(0., 1.)

    ax2.plot(x_v0, alpha, lw=lw, color='saddlebrown', label='alpha adv')
    ax2.plot(x_v0,
             alpha_desired,
             ':',
             lw=lw,
             color='saddlebrown',
             label='alpha')

    ax2.set_xlim(ax0.get_xlim())
    ax2.set_ylim(-0.05, 1.05)
    plt.setp(ax2.get_xticklabels(), visible=False)
    ax2.grid()
    ax2.set_ylabel('$\\alpha$', size=16, labelpad=0)
    ax2.yaxis.set_label_coords(labelx, 0.5)

    ax2.legend(loc='best', numpoints=1, prop={'size': legsz})

    tunneling_Er = physics.inv('t_to_V0', v0)
    tunneling_kHz = tunneling_Er * 29.2

    ax3.plot(x_v0, tunneling_kHz, lw=lw, color='red', label='$t$ (kHz)')

    ax3.set_xlim(ax0.get_xlim())
    ylim = ax3.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax3.set_ylim(ylim[0] - extra, ylim[1] + extra)
    plt.setp(ax3.get_xticklabels(), visible=False)
    ax3.grid(True)
    ax3.set_ylabel(r'$t\,\mathrm{(kHz)}$', size=16, labelpad=0)
    ax3.yaxis.set_label_coords(labelx, 0.5)
    ax3.legend(loc='best', numpoints=1, prop={'size': legsz})

    wannierF = physics.inv('wF_to_V0', v0)

    bohrRadius = 5.29e-11  #meters
    lattice_spacing = 1.064e-6 / 2.  #meters

    bfieldG = physics.cnv('as_to_B', y_a_s)

    U_over_t = y_a_s * bohrRadius / lattice_spacing * wannierF / tunneling_Er

    ax4.plot(x_v0, U_over_t, lw=lw, color='k', label=r'$U/t$')

    ax4.set_xlim(ax0.get_xlim())
    ylim = ax4.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax4.set_ylim(ylim[0] - extra, ylim[1] + extra)
    plt.setp(ax4.get_xticklabels(), visible=False)
    ax4.grid(True)
    ax4.set_ylabel(r'$U/t$', size=16, labelpad=0)
    ax4.yaxis.set_label_coords(labelx, 0.5)

    ax4.legend(loc='best', numpoints=1, prop={'size': legsz})

    ax5.plot(x_v0, bfieldG, lw=lw, color='purple', label='$B$ (G)')

    ax5.set_xlim(ax0.get_xlim())
    ylim = ax5.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax5.set_ylim(ylim[0] - extra, ylim[1] + extra)
    ax5.grid(True)
    plt.setp(ax5.get_xticklabels(), visible=False)
    ax5.set_ylabel(r'$B\,\mathrm{(G)}$', size=16, labelpad=0)
    ax5.yaxis.set_label_coords(labelx, 0.5)

    ax5.legend(loc='best', numpoints=1, prop={'size': legsz})

    ax6.plot(x_v0, (tunneling_Er / U_over_t),
             lw=lw,
             color='#25D500',
             label=r'$t^{2}/U\,(E_{r)}$')
    #ax6.set_yscale('log')

    ax6.set_xlim(ax0.get_xlim())
    ylim = ax6.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax6.set_ylim(ylim[0] * 0.5, ylim[1])
    ax6.grid(True)
    ax6.set_ylabel(r'$t^{2}/U\,(E_{r)}$', size=16, labelpad=0)
    ax6.yaxis.set_label_coords(labelx, 0.5)

    ax6.legend(loc='best', numpoints=1, prop={'size': legsz})

    ax6.set_xlabel('time (ms)')

    figfile = seqconf.seqtxtout().split('.')[0] + '_latticeRamp.png'
    plt.savefig(figfile, dpi=120)

    #Save all ramps to a txt file for later plotting.
    datfile = seqconf.seqtxtout().split('.')[0] + '_latticeRamp.dat'
    allRamps = numpy.transpose(numpy.vstack((x_v0, v0, y_ir, grwfms['greenpow1'], y_a_s, alpha, alpha_desired, \
                                    tunneling_kHz, U_over_t, bfieldG)))
    header = '# Column index'
    header = header + '\n#\t0\t' + 'time(ms)'
    header = header + '\n#\t1\t' + 'Lattice Depth (Er)'
    header = header + '\n#\t2\t' + 'Ir power (Er)'
    header = header + '\n#\t3\t' + 'GR power (Er)'
    header = header + '\n#\t4\t' + 'a_s (a0)'
    header = header + '\n#\t5\t' + 'alpha - advance'
    header = header + '\n#\t6\t' + 'alpha - desired'
    header = header + '\n#\t7\t' + 'tunneling (kHz)'
    header = header + '\n#\t8\t' + 'U/t'
    header = header + '\n#\t9\t' + 'bfield (Gauss)'
    header = header + '\n'

    numpy.savetxt(datfile, allRamps)

    with open(datfile, 'w') as f:
        X = numpy.asarray(allRamps)
        f.write(bytes(header))

        format = '%.6e'
        ncol = X.shape[1]
        format = [
            format,
        ] * ncol
        format = ' '.join(format)

        newline = '\n'
        for row in X:
            f.write(numpy.compat.asbytes(format % tuple(row) + newline))

    shutil.copyfile(
        figfile,
        seqconf.savedir() + 'expseq' + seqconf.runnumber() +
        '_latticeRamp.png')
    shutil.copyfile(
        datfile,
        seqconf.savedir() + 'expseq' + seqconf.runnumber() +
        '_latticeRamp.dat')
    #plt.savefig( seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png', dpi=120)

    #################################
    #### APPEND RAMPS TO SEQUENCE ###
    #################################

    wfms = []

    for ch in ['ir1pow', 'ir2pow', 'ir3pow']:
        n = filter(str.isdigit, ch)[0]
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        w.y = physics.cnv(ch, y_ir)
        wfms.append(w)

    for ch in ['greenpow1', 'greenpow2', 'greenpow3']:
        n = filter(str.isdigit, ch)[0]
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden

        correction = DIMPLE.__dict__['gr' + n + 'correct']

        w.y = physics.cnv(ch, correction * grwfms[ch])
        wfms.append(w)

    for ch in ['lcr1', 'lcr2', 'lcr3']:
        n = filter(str.isdigit, ch)[0]
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        force = DL.__dict__['force_' + ch]
        if force >= 0 and force <= 1:
            print "...Forcing LCR%s = %f during lattice ramp" % (n, force)
            w.y = physics.cnv(ch, numpy.array(alpha.size * [force]))
        else:
            w.y = physics.cnv(ch, alpha)
        wfms.append(w)

    bfieldA = bfieldG / 6.8

    ##ADD field
    bfield = wfm.wave('bfield', 0.0, DL.ss)
    bfield.y = physics.cnv('bfield', bfieldA)
    wfms.append(bfield)

    ##ADD gradient field
    gradient = gradient_wave('gradientfield', 0.0, DL.ss, volt=0.0)
    gradient.follow(bfield)
    wfms.append(gradient)

    # RF sweep
    if DL.rf == 1:
        rfmod = wfm.wave('rfmod', 0., DL.ss)
        rfmod.appendhold(bfield.dt() + DL.rftime)
        rfmod.linear(DL.rfvoltf, DL.rfpulsedt)
        wfms.append(rfmod)

    #Take care of imaging frequencies, including various kill experiments
    bfieldG = physics.inv('bfield', bfield.y[-1]) * 6.8
    hfimg0 = -1. * (100.0 + 163.7 - 1.414 * bfieldG)

    print "...ANDOR:hfimg and hfimg0 will be modified  in report\n"
    print "\tNEW  ANDOR:hfimg  = %.2f MHz" % (hfimg0 - DL.imgdet)
    print "\tNEW  ANDOR:hfimg0 = %.2f MHz\n" % hfimg0
    gen.save_to_report('ANDOR', 'hfimg', hfimg0 - DL.imgdet)
    gen.save_to_report('ANDOR', 'hfimg0', hfimg0)
    newANDORhfimg = hfimg0 - DL.imgdet

    # Kill hfimg
    if DL.probekill == 1 or DL.braggkill == 1 or DL.lightassist or DL.lightassist_lock:
        hfimgdelay = 50.  #ms
        analogimg = wfm.wave('analogimg', newANDORhfimg, DL.ss)

        if DL.probekill == 1:
            if (-DL.probekilltime + hfimgdelay) < DL.image:
                analogimg.appendhold(bfield.dt() + DL.probekilltime -
                                     hfimgdelay)
                analogimg.linear(DL.probekill_hfimg, 0.0)
                analogimg.appendhold(hfimgdelay + DL.probekilldt + 3 * DL.ss)

        elif DL.braggkill == 1:
            if (-DL.braggkilltime + hfimgdelay) < DL.image:
                analogimg.appendhold(bfield.dt() + DL.braggkilltime -
                                     hfimgdelay)
                analogimg.linear(DL.braggkill_hfimg, 0.0)
                analogimg.appendhold(hfimgdelay + DL.braggkilldt + 3 * DL.ss)

        #elif DL.lightassist == 1 or DL.lightassist_lock:
        #    analogimg.appendhold( bfield.dt()  - hfimgdelay)
        #    analogimg.linear( DL.lightassist_hfimg , 0.0)
        #    duration = DL.lightassist_lockdtUP + DL.lightassist_t0 + DL.lightassistdt + DL.lightassist_lockdtDOWN
        #    analogimg.appendhold( hfimgdelay + duration + 3*DL.ss)

        analogimg.linear(newANDORhfimg, 0.)
        analogimg.extend(10)
        wfms.append(analogimg)

    #analogimg = bfieldwfm.hfimg_wave('analogimg', ANDOR.hfimg, DL.ss)
    #andorhfimg0 = analogimg.follow(bfield, DL.imgdet)
    #wfms.append(analogimg)

    # If we are doing round trip END, then mirror all the ramps
    # before adding them to the sequence
    if DL.round_trip == 1:
        if DL.round_trip_type == 1:
            maxdt = 0.
            maxi = -1
            for i, w in enumerate(wfms):
                if w.dt() > maxdt:
                    maxdt = w.dt()
                    maxi = i

            maxdt = maxdt + DL.wait_at_top / 2.

            for w in wfms:
                w.extend(maxdt)
                if 'lcr' in w.name:
                    yvals = w.y

                    #Get the reverse of the alpha desired array
                    alpha_mirror = numpy.copy(alpha_desired[::-1])

                    #Add the wait at top part so that it has same length as yvals
                    if alpha_mirror.size > yvals.size:
                        print "Error making mirror ramp for LCR."
                        print "Program will exit."
                        exit(1)
                    alpha_mirror = numpy.append(
                        (yvals.size - alpha_mirror.size) * [alpha_mirror[0]],
                        alpha_mirror)

                    #This is how much the mirror ramp will be advanced
                    N_adv = int(math.floor(DL.lcr_mirror_advance / DL.ss))

                    if N_adv < alpha_mirror.size:
                        alpha_mirror = alpha_mirror[N_adv:]
                        alpha_mirror = numpy.append(
                            alpha_mirror, (yvals.size - alpha_mirror.size) *
                            [alpha_mirror[-1]])
                    else:
                        alpha_mirror = numpy.array(yvals.size *
                                                   [alpha_mirror[-1]])

                    w.y = numpy.concatenate(
                        (yvals, physics.cnv(w.name, alpha_mirror)))
                else:
                    w.mirror()
                w.appendhold(DL.wait_at_end)

    N_adv = int(math.floor(alpha_advance / DL.ss))

    alpha_desired = numpy.copy(alpha)

    for wavefm in wfms:
        print "%s dt = %f" % (wavefm.name, wavefm.dt())

    #Wait the buffer for the lattice loading ramps before adding them
    bufferdt = 20.
    s.wait(bufferdt)
    #Add lattice wfms
    duration = s.analogwfm_add(DL.ss, wfms)

    if DL.image < 2500.:
        s.wait(duration)
    else:
        print "...DL.image = %f  >= 2500.  Digital seq extension will be used." % DL.image
        s.wait(DL.image)

    #Here give some buffer time to do lock, RF etc.
    #It has to be minimum 5.0 ms

    ### Figure out when to turn interlock back on, using alpha information
    #~ if duration > DL.t0 + DL.dt:
    #~ s.wait(-DL.lattice_interlock_time)
    #~ if DL.use_lattice_interlock == 1:
    #~ s.digichg('latticeinterlockbypass',0)
    #~ else:
    #~ s.digichg('latticeinterlockbypass',1)
    #~ s.wait( DL.lattice_interlock_time)

    return s, y_ir[-1]
예제 #13
0
    def __init__(self,file_path = '' '''seqconf.seqtxtout()'''):
        
        
        """Initialize the class  """
        
        self.file_path = file_path
        
        self.folder, self.filename = os.path.split(self.file_path)
        #print self.folder, self.filename
        self.seq = open(self.file_path,'rU').readlines()
        #~ print [self.seq[-1]]
        self.analog_waveforms_position = []

        for position, str in enumerate(self.seq[1:]):	
    
            if (str == '#'+endofline): 

                self.analog_waveforms_position.append(position+1) # Plus one since we start from seq[1]
        #~ print self.analog_waveforms_position
        """Parse Digital Waveforms"""

        self.digi_step = float(self.seq[1].split(" ")[1])

        self.digi_channels = self.seq[2].replace(' ','').split('!')

        self.digi_channels.pop(-1) # get rid of the final '\n'

        self.digi_data = [ [] for i in self.digi_channels]
            
        for i in self.seq[3:(self.analog_waveforms_position[0])]:
            
            self.digi_temp = i.replace(' ','').split('!')
            
            self.digi_temp.pop(-1) # get rid of the final '\n'
            
            for index, j in enumerate(self.digi_temp):
                
                self.digi_data[index].append(float(j))

        self.digi_time = self.digi_data.pop(0)

        self.digi_channels.pop(0) # get rid of the time(ms)
        
        """Parse Analog Waveforms"""
        
        self.analog_time0 = []
        
        self.analog_step = []
        
        self.analog_channels = []
        
        self.analog_data = []
        
        self.analog_time = []
        
        for i in range(len(self.analog_waveforms_position)-1):

            self.analog_temp = self.seq[(self.analog_waveforms_position[i]+2):(self.analog_waveforms_position[i+1])]

            self.analog_time0.append(float(self.analog_temp.pop(0).split("\t")[1].replace(endofline,'')))


            self.analog_step.append(float(self.analog_temp.pop(0).split("\t")[1].replace(endofline,'')))

            self.analog_channels.append([])

            self.analog_data.append([])
            
            self.analog_time.append([])

            for index, analog in enumerate(self.analog_temp):
                
                analog.replace(endofline,'')

                if ( index % 2 ) == 0:
                    
                    self.analog_channels[i].append(analog.replace(endofline,''))
                    
                else:
                    
                    self.analog_data[i].append( [ float(j) for j in analog.replace(' ','').split(',') ] )

                    
            self.analog_time[i] = list(np.arange(0, len(self.analog_data[i][0]), 1)*self.analog_step[i]  + self.analog_time0[i])
            if len(self.analog_time[i]) % 2 != 0 :
                err =  "\n WARNING:\n\n%s\n\nwaveform has an odd number of samples : %d" % (self.analog_channels[i], len(self.analog_time[i]))
                err = err +  "\n\nA DAQmx error will occur if you try to run this on labview"
                print err
                errormsg.box("INVALID WAVEFORM ERROR", err ) 
예제 #14
0
def dimple_to_lattice(s,cpowend):
    
    print "----- LATTICE LOADING RAMPS -----"
    
    dt = DL.dt
    tau = DL.tau
    shift = DL.shift
    
    N0 = 0
    
    N = int(math.floor( dt/ DL.ss))
    x = numpy.arange(dt/N, dt, dt/N)
    tau = tau*dt
    shift = dt/2. + shift*dt/2.
    
    # Define how we want to ramp up the lattice depth
    v0_ramp, xy_v0, v0set =  interpolate_ramp( DL.latticeV0)
    
    
    v0  = v0_ramp(x)
    
    #v0 = 0. + DL.latticeV0 * ( (1+numpy.tanh((x-shift)/tau)) - (1+numpy.tanh((-shift)/tau)) )\
    #                    / ( (1+numpy.tanh((dt-shift)/tau)) - (1+numpy.tanh((-shift)/tau)) )
                        
    NH = int(math.floor( DL.dthold/ DL.ss))
    
    v0 = numpy.concatenate(( numpy.zeros(N0), v0, numpy.array(NH*[v0[-1]])  ))
    
    x_v0 = numpy.arange( v0.size )
    x_v0 = x_v0*DL.ss
    
    # Number of samples to keep
    NS = int(math.floor( DL.image / DL.ss))
    if NS > v0.size:
        x_v0 = numpy.append(x_v0, (NS-v0.size)*[x_v0[-1]])
        v0 = numpy.append(v0, (NS-v0.size)*[v0[-1]])
        
    else:
        x_v0 = x_v0[:NS]
        v0 = v0[:NS]
    
    ###########################################
    #### AXIS DEFINITIONS FOR PLOTS ###
    ###########################################    
    
    fig = plt.figure( figsize=(4.5*1.05,8.*1.1))
    ax0 = fig.add_axes( [0.18,0.76,0.76,0.20]) 
    ax2 = fig.add_axes( [0.18,0.645,0.76,0.11])
    ax3 = fig.add_axes( [0.18,0.53,0.76,0.11])
    ax1 = fig.add_axes( [0.18,0.415,0.76,0.11])
    ax5 = fig.add_axes( [0.18,0.30,0.76,0.11])
    ax4 = fig.add_axes( [0.18,0.185,0.76,0.11])
    ax6 = fig.add_axes( [0.18,0.07,0.76,0.11])
    
    lw=1.5
    labelx=-0.12
    legsz =8.
    
    xymew=0.5
    xyms=9

    ax0.plot( x_v0, v0, 'b', lw=2.5, label='Lattice depth')
    ax0.plot(xy_v0[:,0],xy_v0[:,1], 'x', color='blue', ms=5.)
    ax0.plot(v0set[:,0],v0set[:,1], '.', mew=xymew, ms=xyms, color='blue')
    
    
    ###########################################
    #### USER DEFINED RAMPS: IR, GR, and U ###
    ###########################################      
    
    # Define how we want to ramp up the IR power
    ir_ramp, xy_ir, ir =  interpolate_ramp( DL.irpow, yoffset=DIMPLE.ir1pow)
    
    dt_ir = numpy.amax( ir[:,0]) - numpy.amin( ir[:,0])
    N_ir = int(math.floor( dt_ir / DL.ss ))
    x_ir = numpy.arange( dt_ir/N_ir, dt_ir, dt_ir/N_ir)
    
    #y_ir = ir_spline(x_ir) 
    y_ir = ir_ramp(x_ir)
    
    if v0.size > y_ir.size:
        y_ir = numpy.append(y_ir, (v0.size-y_ir.size)*[y_ir[-1]])
    elif v0.size < y_ir.size:
        y_ir = y_ir[0:v0.size]
        
    if v0.size != y_ir.size:
        msg = "IRPOW ERROR: number of samples in IR ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
        
    
    if (v0 > y_ir).any():
        msg = "IRPOW ERROR:  not enough power to get desired lattice depth"
        print msg
        bad = numpy.where( v0 > y_ir)
        msg = msg + "\nFirst bad sample = %d out of %d" % (bad[0][0], v0.size)
        msg = msg + "\n v0 = %f " %   v0[ bad[0][0] ]
        msg = msg + "\n ir = %f " % y_ir[ bad[0][0] ]
        print v0[bad[0][0]]
        print y_ir[bad[0][0]]
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
    
    ax0.plot(xy_ir[:,0],xy_ir[:,1], 'x', color='darkorange', ms=5.)
    ax0.plot(ir[:,0],ir[:,1], '.', mew=xymew, ms=xyms, color='darkorange')
    ax0.plot(x_v0, y_ir, lw=lw, color='darkorange',label='irpow')
    
    
    # Define how we want to ramp up the GR power
    gr_ramp, xy_gr, gr =  interpolate_ramp( DL.grpow, yoffset=DIMPLE.gr1pow)
    
    dt_gr = numpy.amax( gr[:,0]) - numpy.amin( gr[:,0])
    N_gr = int(math.floor( dt_gr / DL.ss ))
    x_gr = numpy.arange( dt_gr/N_gr, dt_gr, dt_gr/N_gr)
    
    y_gr = gr_ramp(x_gr) 
    
    if v0.size > y_gr.size:
        y_gr = numpy.append(y_gr, (v0.size-y_gr.size)*[y_gr[-1]])
    elif v0.size < y_gr.size:
        y_gr = y_gr[0:v0.size]
        
    if v0.size != y_gr.size:
        msg = "GRPOW ERROR: number of samples in GR ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)


    ax0.plot(xy_gr[:,0],xy_gr[:,1], 'x', color='green', ms=5.)
    ax0.plot(gr[:,0],gr[:,1],'.', mew=xymew, ms=xyms, color='green')#, label='grpow dat')
    ax0.plot(x_v0, y_gr, lw=lw, color='green', label='grpow')
    
    ax0.set_xlim(left=-10., right= ax0.get_xlim()[1]*1.1)   
    plt.setp( ax0.get_xticklabels(), visible=False)
    ylim = ax0.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax0.set_ylim( ylim[0]-extra, ylim[1]+extra )
    ax0.grid(True)
    ax0.set_ylabel('$E_{r}$',size=16, labelpad=0)
    ax0.yaxis.set_label_coords(labelx, 0.5)
    ax0.set_title('Lattice Loading')
    ax0.legend(loc='best',numpoints=1,prop={'size':legsz*0.8})
    
    
    # Define how we want to ramp up the scattering length (control our losses)
    a_s_ramp, xy_a_s, a_s =  interpolate_ramp( DL.a_s)
    
    
    dt_a_s = numpy.amax( a_s[:,0]) - numpy.amin( a_s[:,0])
    N_a_s = int(math.floor( dt_a_s / DL.ss ))
    x_a_s = numpy.arange( dt_a_s/N_a_s, dt_a_s, dt_a_s/N_a_s)
    y_a_s = a_s_ramp(x_a_s)
    
    if v0.size > y_a_s.size:
        y_a_s = numpy.append(y_a_s, (v0.size-y_a_s.size)*[y_a_s[-1]])
    elif v0.size < y_a_s.size:
        y_a_s = y_a_s[0:v0.size]
        
    if v0.size != y_a_s.size:
        msg = "a_s ERROR: number of samples in a_s ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
    
    
    
    ax1.plot(xy_a_s[:,0],xy_a_s[:,1]/100., 'x', color='#C10087', ms=5.)
    ax1.plot(a_s[:,0],a_s[:,1]/100., '.', mew=xymew, ms=xyms, color='#C10087')
    ax1.plot(x_v0, y_a_s/100., lw=lw, color='#C10087', label=r'$a_s\mathrm{(100 a_{0})}$')
    ax1.set_ylabel(r'$a_s\mathrm{(100 a_{0})}$',size=16, labelpad=0)
    ax1.yaxis.set_label_coords(labelx, 0.5)

    
    ax1.set_xlim( ax0.get_xlim()) 
    ylim = ax1.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax1.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax1.get_xticklabels(), visible=False)
    ax1.grid(True)
    ax1.legend(loc='best',numpoints=1,prop={'size':legsz})
    

    #######################################################################
    #### CALCULATED RAMPS:  ALPHA, TUNNELING, SCATTERING LENGTH, BFIELD ###
    #######################################################################
    
    alpha = (v0/y_ir)**2.
    
    alpha_advance = 100.
    N_adv = int(math.floor( alpha_advance / DL.ss))
    
    alpha_desired = numpy.copy(alpha)
    
    if N_adv < v0.size:
        alpha = alpha[N_adv:]
        alpha = numpy.append(alpha, (v0.size-alpha.size)*[alpha[-1]])
    else:
        alpha = numpy.array( v0.size*[alpha[-1]] )
    
    
    
    ax2.plot( x_v0, alpha, lw=lw, color='saddlebrown', label='alpha adv')
    ax2.plot( x_v0, alpha_desired,':', lw=lw, color='saddlebrown', label='alpha')
    
    ax2.set_xlim( ax0.get_xlim()) 
    ax2.set_ylim(-0.05,1.05)
    plt.setp( ax2.get_xticklabels(), visible=False)
    ax2.grid()
    ax2.set_ylabel('$\\alpha$',size=16, labelpad=0)
    ax2.yaxis.set_label_coords(labelx, 0.5)
    
    ax2.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    tunneling_Er  = physics.inv('t_to_V0', v0)
    tunneling_kHz = tunneling_Er * 29.2
    
    ax3.plot( x_v0, tunneling_kHz, lw=lw, color='red', label='$t$ (kHz)')
    
    ax3.set_xlim( ax0.get_xlim()) 
    ylim = ax3.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax3.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax3.get_xticklabels(), visible=False)
    ax3.grid(True)
    ax3.set_ylabel(r'$t\,\mathrm{(kHz)}$',size=16, labelpad=0)
    ax3.yaxis.set_label_coords(labelx, 0.5)
    ax3.legend(loc='best',numpoints=1,prop={'size':legsz})

    
    wannierF = physics.inv('wF_to_V0', v0)
     
    bohrRadius = 5.29e-11 #meters
    lattice_spacing = 1.064e-6 / 2. #meters
    
    bfieldG = physics.cnv('as_to_B', y_a_s)
    
    U_over_t = y_a_s * bohrRadius / lattice_spacing * wannierF / tunneling_Er
    
    
    
    
    ax4.plot( x_v0, U_over_t, lw=lw, color='k', label=r'$U/t$')
    
    ax4.set_xlim( ax0.get_xlim()) 
    ylim = ax4.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax4.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax4.get_xticklabels(), visible=False)
    ax4.grid(True)
    ax4.set_ylabel(r'$U/t$',size=16, labelpad=0)
    ax4.yaxis.set_label_coords(labelx, 0.5)
    
    ax4.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    ax5.plot( x_v0, bfieldG, lw=lw, color='purple', label='$B$ (G)')
    
    ax5.set_xlim( ax0.get_xlim()) 
    ylim = ax5.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax5.set_ylim( ylim[0]-extra, ylim[1]+extra )
    ax5.grid(True)
    plt.setp( ax5.get_xticklabels(), visible=False)
    ax5.set_ylabel(r'$B\,\mathrm{(G)}$',size=16, labelpad=0)
    ax5.yaxis.set_label_coords(labelx, 0.5)
    
    
    ax5.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    ax6.plot( x_v0, (tunneling_Er / U_over_t), lw=lw, color='#25D500', label=r'$t^{2}/U\,(E_{r)}$')
    #ax6.set_yscale('log')
    
    ax6.set_xlim( ax0.get_xlim()) 
    ylim = ax6.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax6.set_ylim( ylim[0]*0.5, ylim[1] )
    ax6.grid(True)
    ax6.set_ylabel(r'$t^{2}/U\,(E_{r)}$',size=16, labelpad=0)
    ax6.yaxis.set_label_coords(labelx, 0.5)
    
    
    ax6.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    ax6.set_xlabel('time (ms)')

    figfile = seqconf.seqtxtout().split('.')[0]+'_latticeRamp.png'    
    plt.savefig(figfile , dpi=120 )
    
    #Save all ramps to a txt file for later plotting. 
    datfile = seqconf.seqtxtout().split('.')[0]+'_latticeRamp.dat'
    allRamps = numpy.transpose(numpy.vstack((x_v0, v0, y_ir, y_gr, y_a_s, alpha, alpha_desired, \
                                    tunneling_kHz, U_over_t, bfieldG)))
    header = '# Column index'
    header = header + '\n#\t0\t' + 'time(ms)'
    header = header + '\n#\t1\t' + 'Lattice Depth (Er)'
    header = header + '\n#\t2\t' + 'Ir power (Er)'
    header = header + '\n#\t3\t' + 'GR power (Er)'
    header = header + '\n#\t4\t' + 'a_s (a0)'
    header = header + '\n#\t5\t' + 'alpha - advance'
    header = header + '\n#\t6\t' + 'alpha - desired'
    header = header + '\n#\t7\t' + 'tunneling (kHz)'
    header = header + '\n#\t8\t' + 'U/t'
    header = header + '\n#\t9\t' + 'bfield (Gauss)'
    header = header + '\n'
    
    numpy.savetxt( datfile, allRamps)
    
    with open(datfile, 'w') as f:
        X = numpy.asarray( allRamps )
        f.write(bytes(header))
        
        format = '%.6e'
        ncol = X.shape[1]
        format = [format ,] *ncol
        format = ' '.join(format)
        
        newline = '\n'
        for row in X:
            f.write(numpy.compat.asbytes(format % tuple(row) + newline))

    
    shutil.copyfile( figfile,  seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png')
    #plt.savefig( seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png', dpi=120)
    
    
    #################################
    #### APPEND RAMPS TO SEQUENCE ###
    #################################
    
    wfms=[]
    
    for ch in ['ir1pow','ir2pow','ir3pow']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        w.y = physics.cnv( ch, y_ir )
        if DL.lock:
            endval = w.y[-1]
            w.insertlin_cnv(DL.lock_Er, DL.lock_dtUP, DL.lock_t0 )
            if DL.camera == 'manta' or DL.camera == 'both':
                w.appendhold( MANTA.exp + 1.0 ) 
                w.insertlin( endval, 0., 0.)
                w.appendhold( MANTA.noatoms - MANTA.exp - 1.0)
                w.insertlin_cnv(DL.lock_Er, DL.lock_dtUP, DL.lock_t0 )
        elif DL.lightassist_lock:
            endval = w.y[-1]
            w.linear(DL.lightassist_lockpowIR, DL.lightassist_lockdtUP)
            w.appendhold( DL.lightassist_t0 + DL.lightassistdt )
            if DL.endvalIR >= 0.:
                w.linear(  DL.endvalIR, DL.lightassist_lockdtDOWN)
            else:
                w.linear(  None, DL.lightassist_lockdtDOWN, volt=endval)
        wfms.append(w)
        
    for ch in ['greenpow1','greenpow2','greenpow3']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        w.y = physics.cnv( ch, y_gr )
        if DL.lightassist_lock:
            endval = w.y[-1]
            w.linear(DL.lightassist_lockpowGR, DL.lightassist_lockdtUP)
            w.appendhold( DL.lightassist_t0 + DL.lightassistdt )
            if DL.endvalGR >= 0.:
                w.linear(  DL.endvalGR, DL.lightassist_lockdtDOWN)
            else:
                w.linear(  None, DL.lightassist_lockdtDOWN, volt=endval)
        wfms.append(w)
        
    for ch in ['lcr1','lcr2','lcr3']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        force = DL.__dict__['force_'+ch]
        if force >= 0 and force <=1:
            print "...Forcing LCR%s = %f during lattice ramp" % (n,force)
            w.y = physics.cnv( ch, numpy.array( alpha.size*[force] )  )
        else:
            w.y = physics.cnv( ch, alpha )
        wfms.append(w)
    

    
    bfieldA = bfieldG/6.8
    
    ##ADD field
    bfield = wfm.wave('bfield', 0.0, DL.ss)
    bfield.y = physics.cnv( 'bfield', bfieldA)
    wfms.append(bfield)
    
    
    ##ADD gradient field
    gradient = gradient_wave('gradientfield', 0.0, DL.ss,volt = 0.0)
    gradient.follow(bfield)
    wfms.append(gradient)
    
    
    buffer = 20.
    s.wait(buffer)
    
    
    #~ odtpow = odt.odt_wave('odtpow', cpowend, DL.ss)
    #~ if DIMPLE.odt_t0 > buffer :
        #~ odtpow.appendhold( DIMPLE.odt_t0 - buffer)
    #~ if DIMPLE.odt_pow < 0.:
        #~ odtpow.appendhold( DIMPLE.odt_dt)
    #~ else:
        #~ odtpow.tanhRise( DIMPLE.odt_pow, DIMPLE.odt_dt, DIMPLE.odt_tau, DIMPLE.odt_shift)    
        
    #~ if numpy.absolute(DIMPLE.odt_pow) < 0.0001:
        #~ s.wait( odtpow.dt() )
        #~ s.digichg('odtttl',0)
        #~ s.wait(-odtpow.dt() )
    
    #~ wfms.append(odtpow)
        
    
    # RF sweep
    if DL.rf == 1:   
        rfmod  = wfm.wave('rfmod', 0., DL.ss)
        rfmod.appendhold( bfield.dt() + DL.rftime )
        rfmod.linear( DL.rfvoltf, DL.rfpulsedt)
        wfms.append(rfmod)


    bfieldG = physics.inv( 'bfield', bfield.y[-1]) * 6.8
    hfimg0 = -1.*(100.0 + 163.7 - 1.414*bfieldG)
    
    print "...ANDOR:hfimg and hfimg0 will be modified  in report\n"
    print "\tNEW  ANDOR:hfimg  = %.2f MHz" % ( hfimg0 - DL.imgdet)
    print "\tNEW  ANDOR:hfimg0 = %.2f MHz\n" %  hfimg0
    gen.save_to_report('ANDOR','hfimg', hfimg0 - DL.imgdet)
    gen.save_to_report('ANDOR','hfimg0', hfimg0)
    
    newANDORhfimg = hfimg0 - DL.imgdet
        
    # Kill hfimg
    if DL.probekill ==1 or DL.braggkill ==1 or DL.lightassist or DL.lightassist_lock:
        hfimgdelay = 50. #ms
        analogimg = wfm.wave('analogimg', newANDORhfimg, DL.ss)
        
        if DL.probekill == 1:
            if (-DL.probekilltime+hfimgdelay) < DL.image:
                analogimg.appendhold( bfield.dt() + DL.probekilltime - hfimgdelay)
                analogimg.linear( DL.probekill_hfimg , 0.0)
                analogimg.appendhold( hfimgdelay + DL.probekilldt + 3*DL.ss)
        
        elif DL.braggkill == 1:
            if (-DL.braggkilltime+hfimgdelay) < DL.image:
                analogimg.appendhold( bfield.dt() + DL.braggkilltime - hfimgdelay)
                analogimg.linear( DL.braggkill_hfimg , 0.0)
                analogimg.appendhold( hfimgdelay + DL.braggkilldt + 3*DL.ss)
        
        elif DL.lightassist == 1 or DL.lightassist_lock:
            analogimg.appendhold( bfield.dt()  - hfimgdelay)
            analogimg.linear( DL.lightassist_hfimg , 0.0)
            duration = DL.lightassist_lockdtUP + DL.lightassist_t0 + DL.lightassistdt + DL.lightassist_lockdtDOWN
            analogimg.appendhold( hfimgdelay + duration + 3*DL.ss)
            
        analogimg.linear( newANDORhfimg, 0.)
        analogimg.extend(10)
        wfms.append(analogimg)
    
        

    
    #analogimg = bfieldwfm.hfimg_wave('analogimg', ANDOR.hfimg, DL.ss)
    #andorhfimg0 = analogimg.follow(bfield, DL.imgdet)
    #wfms.append(analogimg)
    

    # If we are doing round trip END, then mirror all the ramps 
    # before adding them to the sequence
    if DL.round_trip == 1:
        if DL.round_trip_type == 1:
            maxdt = 0.
            maxi = -1
            for i,w in enumerate(wfms):
                if w.dt() > maxdt:
                    maxdt = w.dt()
                    maxi = i
    
            maxdt = maxdt + DL.wait_at_top
    
            for w in wfms:
                w.extend(maxdt)
                if 'lcr' in w.name:
                    yvals = w.y
                    
                    alpha_mirror = numpy.copy(alpha_desired[::-1])
                    
                    N_adv = int(math.floor( DL.lcr_mirror_advance / DL.ss))
                    
                    if N_adv < v0.size:
                        alpha_mirror = alpha_mirror[N_adv:]
                        alpha_mirror = numpy.append(alpha_mirror, (yvals.size-alpha_mirror.size)*[alpha_mirror[-1]])
                    else:
                        alpha_mirror = numpy.array( yvals.size*[alpha_mirror[-1]] )
                    
                    
                    
                    w.y = numpy.concatenate((yvals,physics.cnv( w.name, alpha_mirror )))
                else:
                    w.mirror()
                w.appendhold( DL.wait_at_end)
            
        
    
    N_adv = int(math.floor( alpha_advance / DL.ss))
    
    alpha_desired = numpy.copy(alpha)
    
    
    
    
    duration = s.analogwfm_add(DL.ss,wfms)
    
        
    s.wait( duration )
    
    if DL.lock:
        if DL.camera == 'manta' or DL.camera == 'both':
            s.wait( - MANTA.noatoms)
    
    
    ### Figure out when to turn interlock back on, using alpha information
    #~ if duration > DL.t0 + DL.dt:
        #~ s.wait(-DL.lattice_interlock_time)
        #~ if DL.use_lattice_interlock == 1:
            #~ s.digichg('latticeinterlockbypass',0)
        #~ else:
            #~ s.digichg('latticeinterlockbypass',1)
        #~ s.wait( DL.lattice_interlock_time)
    
    
    return s 
def dimple_to_lattice(s,cpowend):
    
    print "----- LATTICE LOADING RAMPS -----"
    
    dt = DL.dt
    N0 = 0
    
    N = int(math.floor( dt/ DL.ss))
    x = numpy.arange(dt/N, dt, dt/N)

    print "%d samples" % N
    print x.shape
    
    # Define how we want to ramp up the lattice depth
    v0_ramp, xy_v0, v0set =  interpolate_ramp( DL.latticeV0)
    v0  = v0_ramp(x)
                        
    NH = int(math.floor( DL.dthold/ DL.ss))
    
    v0 = numpy.concatenate(( numpy.zeros(N0), v0, numpy.array(NH*[v0[-1]])  ))
    
    x_v0 = numpy.arange( v0.size )
    x_v0 = x_v0*DL.ss
    
    # Number of samples to keep
    NS = int(math.floor( DL.image / DL.ss))
    if NS > v0.size and DL.image < 2500.:
        x_v0 = numpy.append(x_v0, (NS-v0.size)*[x_v0[-1]])
        v0 = numpy.append(v0, (NS-v0.size)*[v0[-1]])
        
    else:
        x_v0 = x_v0[:NS]
        v0 = v0[:NS]
    
    ###########################################
    #### AXIS DEFINITIONS FOR PLOTS ###
    ###########################################    
    
    fig = plt.figure( figsize=(4.5*1.05,8.*1.1))
    ax0 = fig.add_axes( [0.18,0.76,0.76,0.20]) 
    ax2 = fig.add_axes( [0.18,0.645,0.76,0.11])
    ax3 = fig.add_axes( [0.18,0.53,0.76,0.11])
    ax1 = fig.add_axes( [0.18,0.415,0.76,0.11])
    ax5 = fig.add_axes( [0.18,0.30,0.76,0.11])
    ax4 = fig.add_axes( [0.18,0.185,0.76,0.11])
    ax6 = fig.add_axes( [0.18,0.07,0.76,0.11])
    
    lw=1.5
    labelx=-0.12
    legsz =8.
    
    xymew=0.5
    xyms=9

    ax0.plot( x_v0, v0, 'b', lw=2.5, label='Lattice depth')
    ax0.plot(xy_v0[:,0],xy_v0[:,1], 'x', color='blue', ms=5.)
    ax0.plot(v0set[:,0],v0set[:,1], '.', mew=xymew, ms=xyms, color='blue')
    
    
    ###########################################
    #### USER DEFINED RAMPS: IR, GR, and U ###
    ###########################################      
    
    # Define how we want to ramp up the IR power
    if DIMPLE.allirpow > 0.:
      ir_offset = DIMPLE.allirpow
    else:
      ir_offset = DIMPLE.ir1pow2
    ir_ramp, xy_ir, ir =  interpolate_ramp( DL.irpow, yoffset=ir_offset)
    
    dt_ir = numpy.amax( ir[:,0]) - numpy.amin( ir[:,0])
    N_ir = int(math.floor( dt_ir / DL.ss ))
    x_ir = numpy.arange( dt_ir/N_ir, dt_ir, dt_ir/N_ir)
    
    #y_ir = ir_spline(x_ir) 
    y_ir = ir_ramp(x_ir)
    
    if v0.size > y_ir.size:
        y_ir = numpy.append(y_ir, (v0.size-y_ir.size)*[y_ir[-1]])
    elif v0.size < y_ir.size:
        y_ir = y_ir[0:v0.size]
        
    if v0.size != y_ir.size:
        msg = "IRPOW ERROR: number of samples in IR ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
        
   
    alpha_clip_range = 0.1 
    if (v0 > y_ir+ alpha_clip_range).any():
        msg = "IRPOW ERROR:  not enough power to get desired lattice depth"
        print msg
        bad = numpy.where( v0 > y_ir + alpha_clip_range)
        timefail =  int(bad[0][0])*float(DL.ss)
        msg = msg + "\nFirst bad sample = %d out of %d" % (bad[0][0], v0.size)
        msg = msg + "\n  t = %f " %  timefail
        msg = msg + "\n v0 = %f " %   v0[ bad[0][0] ]
        msg = msg + "\n ir = %f " % y_ir[ bad[0][0] ]
        print v0[bad[0][0]]
        print y_ir[bad[0][0]]
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
    
    ax0.plot(xy_ir[:,0],xy_ir[:,1], 'x', color='darkorange', ms=5.)
    ax0.plot(ir[:,0],ir[:,1], '.', mew=xymew, ms=xyms, color='darkorange')
    ax0.plot(x_v0, y_ir, lw=lw, color='darkorange',label='irpow')
    
    
    # Define how we want to ramp up the GR power
    grwfms = {}
    splmrkr = ['x','+','d']
    ptsmrkr = ['^','s','p']
    for i,grramp in enumerate([(DL.grpow1,DIMPLE.gr1pow2), (DL.grpow2,DIMPLE.gr2pow2), (DL.grpow3,DIMPLE.gr3pow2)]):
      ramppts = grramp[0]
      ramp0 = grramp[1] 

      print 'gr'+'%d'%i +' offset = %f' % ramp0

      gr_ramp, xy_gr, gr =  interpolate_ramp( ramppts, yoffset=ramp0)
    
      dt_gr = numpy.amax( gr[:,0]) - numpy.amin( gr[:,0])
      N_gr = int(math.floor( dt_gr / DL.ss ))
      x_gr = numpy.arange( dt_gr/N_gr, dt_gr, dt_gr/N_gr)
    
      y_gr = gr_ramp(x_gr)
    
      if v0.size > y_gr.size:
          y_gr = numpy.append(y_gr, (v0.size-y_gr.size)*[y_gr[-1]])
      elif v0.size < y_gr.size:
          y_gr = y_gr[0:v0.size]
        
      if v0.size != y_gr.size:
          msg = "GRPOW ERROR: number of samples in GR ramp and V0 ramp does not match!"
          errormsg.box('LATTICE LOADING ERROR',msg)
          exit(1)

      grwfms[ 'greenpow' + '%1d' % (i+1) ] = y_gr 

      ax0.plot(xy_gr[:,0],xy_gr[:,1], marker= splmrkr[i] ,mec='green', mfc='None', ms=3.)
      ax0.plot(gr[:,0],gr[:,1], marker=ptsmrkr[i], mew=xymew, ms=xyms/2., mfc='None', mec='green')#, label='grpow dat')
      ax0.plot(x_v0, y_gr, lw=lw, color='green', label='grpow')

    for grch in grwfms.keys():
      print grch, " = ", grwfms[grch].shape
    
    ax0.set_xlim(left=-10., right= ax0.get_xlim()[1]*1.1)   
    plt.setp( ax0.get_xticklabels(), visible=False)
    ylim = ax0.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax0.set_ylim( ylim[0]-extra, ylim[1]+extra )
    ax0.grid(True)
    ax0.set_ylabel('$E_{r}$',size=16, labelpad=0)
    ax0.yaxis.set_label_coords(labelx, 0.5)
    ax0.set_title('Lattice Loading')
    ax0.legend(loc='best',numpoints=1,prop={'size':legsz*0.8})
    
    
    # Define how we want to ramp up the scattering length (control our losses)
    a_s_ramp, xy_a_s, a_s =  interpolate_ramp( DL.a_s)
    
    
    dt_a_s = numpy.amax( a_s[:,0]) - numpy.amin( a_s[:,0])
    N_a_s = int(math.floor( dt_a_s / DL.ss ))
    x_a_s = numpy.arange( dt_a_s/N_a_s, dt_a_s, dt_a_s/N_a_s)
    y_a_s = a_s_ramp(x_a_s)
    
    if v0.size > y_a_s.size:
        y_a_s = numpy.append(y_a_s, (v0.size-y_a_s.size)*[y_a_s[-1]])
    elif v0.size < y_a_s.size:
        y_a_s = y_a_s[0:v0.size]
        
    if v0.size != y_a_s.size:
        msg = "a_s ERROR: number of samples in a_s ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR',msg)
        exit(1)
    
    
    
    ax1.plot(xy_a_s[:,0],xy_a_s[:,1]/100., 'x', color='#C10087', ms=5.)
    ax1.plot(a_s[:,0],a_s[:,1]/100., '.', mew=xymew, ms=xyms, color='#C10087')
    ax1.plot(x_v0, y_a_s/100., lw=lw, color='#C10087', label=r'$a_s\mathrm{(100 a_{0})}$')
    ax1.set_ylabel(r'$a_s\mathrm{(100 a_{0})}$',size=16, labelpad=0)
    ax1.yaxis.set_label_coords(labelx, 0.5)

    
    ax1.set_xlim( ax0.get_xlim()) 
    ylim = ax1.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax1.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax1.get_xticklabels(), visible=False)
    ax1.grid(True)
    ax1.legend(loc='best',numpoints=1,prop={'size':legsz})
    

    #######################################################################
    #### CALCULATED RAMPS:  ALPHA, TUNNELING, SCATTERING LENGTH, BFIELD ###
    #######################################################################
    
    alpha = (v0/y_ir)**2.
    
    alpha_advance = 100.
    N_adv = int(math.floor( alpha_advance / DL.ss))
    
    alpha  = alpha.clip(0.,1.)
    alpha_desired = numpy.copy(alpha)
    
    if N_adv < v0.size:
        alpha = alpha[N_adv:]
        alpha = numpy.append(alpha, (v0.size-alpha.size)*[alpha[-1]])
    else:
        alpha = numpy.array( v0.size*[alpha[-1]] )
    
    #alpha = alpha.clip(0., 1.)
    
    ax2.plot( x_v0, alpha, lw=lw, color='saddlebrown', label='alpha adv')
    ax2.plot( x_v0, alpha_desired,':', lw=lw, color='saddlebrown', label='alpha')
    
    ax2.set_xlim( ax0.get_xlim()) 
    ax2.set_ylim(-0.05,1.05)
    plt.setp( ax2.get_xticklabels(), visible=False)
    ax2.grid()
    ax2.set_ylabel('$\\alpha$',size=16, labelpad=0)
    ax2.yaxis.set_label_coords(labelx, 0.5)
    
    ax2.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    tunneling_Er  = physics.inv('t_to_V0', v0)
    tunneling_kHz = tunneling_Er * 29.2
    
    ax3.plot( x_v0, tunneling_kHz, lw=lw, color='red', label='$t$ (kHz)')
    
    ax3.set_xlim( ax0.get_xlim()) 
    ylim = ax3.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax3.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax3.get_xticklabels(), visible=False)
    ax3.grid(True)
    ax3.set_ylabel(r'$t\,\mathrm{(kHz)}$',size=16, labelpad=0)
    ax3.yaxis.set_label_coords(labelx, 0.5)
    ax3.legend(loc='best',numpoints=1,prop={'size':legsz})

    
    wannierF = physics.inv('wF_to_V0', v0)
     
    bohrRadius = 5.29e-11 #meters
    lattice_spacing = 1.064e-6 / 2. #meters
    
    bfieldG = physics.cnv('as_to_B', y_a_s)
    
    U_over_t = y_a_s * bohrRadius / lattice_spacing * wannierF / tunneling_Er
    
    
    
    
    ax4.plot( x_v0, U_over_t, lw=lw, color='k', label=r'$U/t$')
    
    ax4.set_xlim( ax0.get_xlim()) 
    ylim = ax4.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax4.set_ylim( ylim[0]-extra, ylim[1]+extra )
    plt.setp( ax4.get_xticklabels(), visible=False)
    ax4.grid(True)
    ax4.set_ylabel(r'$U/t$',size=16, labelpad=0)
    ax4.yaxis.set_label_coords(labelx, 0.5)
    
    ax4.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    ax5.plot( x_v0, bfieldG, lw=lw, color='purple', label='$B$ (G)')
    
    ax5.set_xlim( ax0.get_xlim()) 
    ylim = ax5.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax5.set_ylim( ylim[0]-extra, ylim[1]+extra )
    ax5.grid(True)
    plt.setp( ax5.get_xticklabels(), visible=False)
    ax5.set_ylabel(r'$B\,\mathrm{(G)}$',size=16, labelpad=0)
    ax5.yaxis.set_label_coords(labelx, 0.5)
    
    
    ax5.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    
    ax6.plot( x_v0, (tunneling_Er / U_over_t), lw=lw, color='#25D500', label=r'$t^{2}/U\,(E_{r)}$')
    #ax6.set_yscale('log')
    
    ax6.set_xlim( ax0.get_xlim()) 
    ylim = ax6.get_ylim()
    extra = (ylim[1]-ylim[0])*0.1
    ax6.set_ylim( ylim[0]*0.5, ylim[1] )
    ax6.grid(True)
    ax6.set_ylabel(r'$t^{2}/U\,(E_{r)}$',size=16, labelpad=0)
    ax6.yaxis.set_label_coords(labelx, 0.5)
    
    
    ax6.legend(loc='best',numpoints=1,prop={'size':legsz})
    
    ax6.set_xlabel('time (ms)')

    figfile = seqconf.seqtxtout().split('.')[0]+'_latticeRamp.png'    
    plt.savefig(figfile , dpi=120 )
    
    #Save all ramps to a txt file for later plotting. 
    datfile = seqconf.seqtxtout().split('.')[0]+'_latticeRamp.dat'
    allRamps = numpy.transpose(numpy.vstack((x_v0, v0, y_ir, grwfms['greenpow1'], y_a_s, alpha, alpha_desired, \
                                    tunneling_kHz, U_over_t, bfieldG)))
    header = '# Column index'
    header = header + '\n#\t0\t' + 'time(ms)'
    header = header + '\n#\t1\t' + 'Lattice Depth (Er)'
    header = header + '\n#\t2\t' + 'Ir power (Er)'
    header = header + '\n#\t3\t' + 'GR power (Er)'
    header = header + '\n#\t4\t' + 'a_s (a0)'
    header = header + '\n#\t5\t' + 'alpha - advance'
    header = header + '\n#\t6\t' + 'alpha - desired'
    header = header + '\n#\t7\t' + 'tunneling (kHz)'
    header = header + '\n#\t8\t' + 'U/t'
    header = header + '\n#\t9\t' + 'bfield (Gauss)'
    header = header + '\n'
    
    numpy.savetxt( datfile, allRamps)
    
    with open(datfile, 'w') as f:
        X = numpy.asarray( allRamps )
        f.write(bytes(header))
        
        format = '%.6e'
        ncol = X.shape[1]
        format = [format ,] *ncol
        format = ' '.join(format)
        
        newline = '\n'
        for row in X:
            f.write(numpy.compat.asbytes(format % tuple(row) + newline))

    
    shutil.copyfile( figfile,  seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png')
    shutil.copyfile( datfile,  seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.dat')
    #plt.savefig( seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png', dpi=120)
    
    
    #################################
    #### APPEND RAMPS TO SEQUENCE ###
    #################################
    
    wfms=[]
    
    for ch in ['ir1pow','ir2pow','ir3pow']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        w.y = physics.cnv( ch, y_ir )
        wfms.append(w)
        
    for ch in ['greenpow1','greenpow2','greenpow3']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        
        correction = DIMPLE.__dict__['gr'+n+'correct']
        
        w.y = physics.cnv( ch, correction * grwfms[ch] )
        wfms.append(w)

    for ch in ['lcr1','lcr2','lcr3']:
        n = filter( str.isdigit, ch)[0] 
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        force = DL.__dict__['force_'+ch]
        if force >= 0 and force <=1:
            print "...Forcing LCR%s = %f during lattice ramp" % (n,force)
            w.y = physics.cnv( ch, numpy.array( alpha.size*[force] )  )
        else:
            w.y = physics.cnv( ch, alpha )
        wfms.append(w)
    
    bfieldA = bfieldG/6.8
    
    ##ADD field
    bfield = wfm.wave('bfield', 0.0, DL.ss)
    bfield.y = physics.cnv( 'bfield', bfieldA)
    wfms.append(bfield)
    
    ##ADD gradient field
    gradient = gradient_wave('gradientfield', 0.0, DL.ss,volt = 0.0)
    gradient.follow(bfield)
    wfms.append(gradient)
     
    
    # RF sweep
    if DL.rf == 1:   
        rfmod  = wfm.wave('rfmod', 0., DL.ss)
        rfmod.appendhold( bfield.dt() + DL.rftime )
        rfmod.linear( DL.rfvoltf, DL.rfpulsedt)
        wfms.append(rfmod)

    
    #Take care of imaging frequencies, including various kill experiments
    bfieldG = physics.inv( 'bfield', bfield.y[-1]) * 6.8
    hfimg0 = -1.*(100.0 + 163.7 - 1.414*bfieldG)
    
    print "...ANDOR:hfimg and hfimg0 will be modified  in report\n"
    print "\tNEW  ANDOR:hfimg  = %.2f MHz" % ( hfimg0 - DL.imgdet)
    print "\tNEW  ANDOR:hfimg0 = %.2f MHz\n" %  hfimg0
    gen.save_to_report('ANDOR','hfimg', hfimg0 - DL.imgdet)
    gen.save_to_report('ANDOR','hfimg0', hfimg0)
    newANDORhfimg = hfimg0 - DL.imgdet
        
    # Kill hfimg
    if DL.probekill ==1 or DL.braggkill ==1 or DL.lightassist or DL.lightassist_lock:
        hfimgdelay = 50. #ms
        analogimg = wfm.wave('analogimg', newANDORhfimg, DL.ss)
        
        if DL.probekill == 1:
            if (-DL.probekilltime+hfimgdelay) < DL.image:
                analogimg.appendhold( bfield.dt() + DL.probekilltime - hfimgdelay)
                analogimg.linear( DL.probekill_hfimg , 0.0)
                analogimg.appendhold( hfimgdelay + DL.probekilldt + 3*DL.ss)
        
        elif DL.braggkill == 1:
            if (-DL.braggkilltime+hfimgdelay) < DL.image:
                analogimg.appendhold( bfield.dt() + DL.braggkilltime - hfimgdelay)
                analogimg.linear( DL.braggkill_hfimg , 0.0)
                analogimg.appendhold( hfimgdelay + DL.braggkilldt + 3*DL.ss)
        
        #elif DL.lightassist == 1 or DL.lightassist_lock:
        #    analogimg.appendhold( bfield.dt()  - hfimgdelay)
        #    analogimg.linear( DL.lightassist_hfimg , 0.0)
        #    duration = DL.lightassist_lockdtUP + DL.lightassist_t0 + DL.lightassistdt + DL.lightassist_lockdtDOWN
        #    analogimg.appendhold( hfimgdelay + duration + 3*DL.ss)
            
        analogimg.linear( newANDORhfimg, 0.)
        analogimg.extend(10)
        wfms.append(analogimg)
    
        

    
    #analogimg = bfieldwfm.hfimg_wave('analogimg', ANDOR.hfimg, DL.ss)
    #andorhfimg0 = analogimg.follow(bfield, DL.imgdet)
    #wfms.append(analogimg)
    

    # If we are doing round trip END, then mirror all the ramps 
    # before adding them to the sequence
    if DL.round_trip == 1:
        if DL.round_trip_type == 1:
            maxdt = 0.
            maxi = -1
            for i,w in enumerate(wfms):
                if w.dt() > maxdt:
                    maxdt = w.dt()
                    maxi = i
    
            maxdt = maxdt + DL.wait_at_top / 2. 
    
            for w in wfms:
                w.extend(maxdt)
                if 'lcr' in w.name:
                    yvals = w.y
                    
                    #Get the reverse of the alpha desired array
                    alpha_mirror = numpy.copy(alpha_desired[::-1])
                    
                    #Add the wait at top part so that it has same length as yvals
                    if alpha_mirror.size > yvals.size:
                        print "Error making mirror ramp for LCR."
                        print "Program will exit."
                        exit(1)
                    alpha_mirror = numpy.append( (yvals.size - alpha_mirror.size)*[ alpha_mirror[0] ], alpha_mirror )
                    
                                   
                    #This is how much the mirror ramp will be advanced
                    N_adv = int(math.floor( DL.lcr_mirror_advance / DL.ss))
                    
                    if N_adv < alpha_mirror.size:
                        alpha_mirror = alpha_mirror[N_adv:]
                        alpha_mirror = numpy.append(alpha_mirror, (yvals.size-alpha_mirror.size)*[alpha_mirror[-1]])
                    else:
                        alpha_mirror = numpy.array( yvals.size*[alpha_mirror[-1]] )
                    
                    
                    
                    w.y = numpy.concatenate((yvals,physics.cnv( w.name, alpha_mirror )))
                else:
                    w.mirror()
                w.appendhold( DL.wait_at_end)
            
        
    
    N_adv = int(math.floor( alpha_advance / DL.ss))
    
    alpha_desired = numpy.copy(alpha)
    
    
    for wavefm in wfms:
        print "%s dt = %f" % (wavefm.name, wavefm.dt())
   
     
    #Wait the buffer for the lattice loading ramps before adding them
    bufferdt = 20.
    s.wait(bufferdt)
    #Add lattice wfms
    duration = s.analogwfm_add(DL.ss,wfms)
    
    
    if DL.image < 2500.:
        s.wait(duration)
    else:
        print "...DL.image = %f  >= 2500.  Digital seq extension will be used." % DL.image
        s.wait( DL.image )

    #Here give some buffer time to do lock, RF etc. 
    #It has to be minimum 5.0 ms 
    
    
    ### Figure out when to turn interlock back on, using alpha information
    #~ if duration > DL.t0 + DL.dt:
        #~ s.wait(-DL.lattice_interlock_time)
        #~ if DL.use_lattice_interlock == 1:
            #~ s.digichg('latticeinterlockbypass',0)
        #~ else:
            #~ s.digichg('latticeinterlockbypass',1)
        #~ s.wait( DL.lattice_interlock_time)
    
    
    return s, y_ir[-1]  
예제 #16
0
    def check(self, ch, phys, volt):

        physa = np.asarray(phys)
        volta = np.asarray(volt)

        #Give a little room for rounding errors
        #and some wiggle room for the physical limits
        physMin = self.physlims[ch][0] - 0.000001
        physMax = self.physlims[ch][1] + 0.000001

        physMin = physMin - (physMax - physMin) * 0.015
        physMax = physMax + (physMax - physMin) * 0.015

        voltMin = self.voltlims[ch][0] - 0.000001
        voltMax = self.voltlims[ch][1] + 0.000001

        #print type(val)
        #print type(out)

        below_bound_phys = physa < physMin
        above_bound_phys = physa > physMax

        below_bound_volt = volta < voltMin
        above_bound_volt = volta > voltMax

        if below_bound_phys.any() or above_bound_phys.any():
            print "phys =", physa
            print "physMin,PhysMax =", physMin, physMax
            out_of_bounds_phys = None

            print "Error in conversion of %s with length = %d" % (type(physa),
                                                                  len(physa))

            msg = "Physical limits [%f,%f]\n" % (physMin, physMax)
            msg += "The following values are outside the physical limits:"

            if physa.ndim < 1:
                out_of_bounds_phys = physa
                msg = msg + '\n\t' + str(out_of_bounds_phys)
            else:
                out_of_bounds_phys = np.concatenate(
                    (physa[np.where(physa < physMin)],
                     physa[np.where(physa > physMax)]))
                msg = msg + '\n\t' + str(out_of_bounds_phys)

            print msg

            errormsg.box('CONVERSION CHECK:: ' + ch, msg)

            raise ValueError("A value is outside the physics range.  ch = %s" %
                             ch)

        if below_bound_volt.any() or above_bound_volt.any():

            out_of_bounds_volt = None

            msg = "Voltage limits [%f,%f]\n" % (voltMin, voltMax)
            msg += "The following values are outside the voltage limits:"

            if volta.ndim < 1:
                out_of_bounds_volt = volta
                msg = msg + '\n\t' + str(out_of_bounds_volt)
            else:
                out_of_bounds_volt = np.concatenate(
                    (volta[np.where(volta < voltMin)],
                     volta[np.where(volta > voltMax)]))
                msg = msg + '\n\t' + str(out_of_bounds_volt)

            print msg

            errormsg.box('CONVERSION CHECK :: ' + ch, msg)

            raise ValueError("A value is outside the voltage range. ch = %s" %
                             ch)

        return (volt, phys)
예제 #17
0
    def __init__(self):

        ### This dictionaries define the functions used for conversion
        self.fs = {}
        self.gs = {}
        self.cnvcalib = {}
        self.invcalib = {}
        self.physlims = {}
        self.voltlims = {}

        ### The for loop below takes care of all the channels that
        ### are associated with a calibration file
        dats = glob.glob(lab + 'software/apparatus3/convert/data/*.dat')

        for d in dats:
            table = np.loadtxt(d, usecols=(1, 0))

            ydat = table[:, 1]  # voltages
            xdat = table[:, 0]  # calibrated quantity

            ch = os.path.splitext(os.path.split(d)[1])[0]

            try:
                f = pwlinterpolate.interp1d(xdat, ydat, name=ch)
                g = pwlinterpolate.interp1d(ydat, xdat, name=ch)

            except ValueError as e:
                print e
                print "Could not define piecewiwse linear interpolation function for : \n\t%s" % d
                exit(1)

            self.fs[ch] = f
            self.gs[ch] = g

            if ch == 'trapdet':
                ### IN    :  MHz detuning at atoms
                ### CALIB :  Double-pass AOM frequency
                shift = -1.1
                self.cnvcalib[ch] = lambda val: (val + shift + 120. + 120.
                                                 ) / 2.
                self.invcalib[ch] = lambda val: 2 * val - shift - 120 - 120.
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([2.0, 8.0])

            elif ch == 'repdet':
                ### IN    :  MHz detuning at atoms
                ### CALIB :  Double-pass AOM frequency
                shift = -1.1
                self.cnvcalib[ch] = lambda val: (val + shift + 228.2 - 80.0 +
                                                 120.) / 2.
                self.invcalib[
                    ch] = lambda val: 2 * val - shift - 228.2 + 80.0 - 120.
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([2.0, 8.0])

            elif ch == 'motpow':
                ### IN    :  Isat/beam at atoms
                ### CALIB :  Power measured by MOT TA monitor
                w0 = 0.86  # beam waist
                ta = 1.682  # power lost to TA sidebands
                op = 1.37  # power loss in MOT optics
                self.cnvcalib[ch] = lambda val: op * ta * 6 * val * 5.1 * (
                    3.14 * w0 * w0) / 2.
                self.invcalib[ch] = lambda val: 2 * val / op / ta / 6 / 5.1 / (
                    3.14 * w0 * w0)
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0.1, 10.])

            elif ch == 'trappow' or ch == 'reppow':
                ### IN    :  power injected to TA
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0., 10.])

            elif ch == 'bfield':
                ### IN    :  current measured on power supply
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0., 9.0])

            elif ch == 'uvdet':
                ### IN    :  UV detuning in MHz
                ### CALIB :  Double-pass AOM frequency
                self.cnvcalib[ch] = lambda val: (val + 130.17) / 2.0
                self.invcalib[ch] = lambda val: val * 2.0 - 130.17
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([2.744, 4.744])

            elif ch == 'uvpow':
                ### IN    :  power measured after 75 um pinhole
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0., 7.0])

            elif ch == 'uv1freq':
                ### IN    :  Frequency of uvaom1 in MHz
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0., 10.0])

            elif ch == 'analogimg':
                ### IN    :  Frequency of offset lock beat signal MHz
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0., 10.0])

            elif ch == 'lcr1' or ch == 'lcr2' or ch == 'lcr3':
                ### IN    :  Lattice ratio:  1=lattice  0=dimple
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch](np.array(
                    [np.amin(xdat), np.amax(xdat)]))
                self.voltlims[ch] = np.array([0., 10.0])

            else:
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = None
                self.voltlims[ch] = None

        ### Channels that are NOT associated with calibration files are
        ### defined below

        chs = ['uvpow2', 'ipganalog', 'rfmod']
        for ch in chs:
            self.cnvcalib[ch] = lambda val: val
            self.invcalib[ch] = lambda val: val
            self.fs[ch] = lambda x: x
            self.gs[ch] = lambda x: x
            self.physlims[ch] = np.array([0., 10.])
            self.voltlims[ch] = np.array([0., 10.])

        latticechs = [
            'ir1pow', 'ir2pow', 'ir3pow', 'greenpow1', 'greenpow2', 'greenpow3'
        ]
        for ch in latticechs:
            ### CALIB : power in mW
            ### FS : PD voltag
            l = lattice_ch(ch, w0d[ch], m1d[ch], V0d[ch], ErMaxd[ch],
                           VMaxd[ch], VMinServod[ch])
            self.cnvcalib[ch] = l.cnvcalib
            self.fs[ch] = l.f
            self.invcalib[ch] = l.invcalib
            self.gs[ch] = l.g
            self.physlims[ch] = l.physlims()
            self.voltlims[ch] = l.voltlims()

        ### ODTPOW
        o = odtpow_ch()
        ch = 'odtpow'
        self.cnvcalib[ch] = np.vectorize(o.cnvcalib)
        self.fs[ch] = o.f
        self.invcalib[ch] = np.vectorize(o.invcalib)
        self.gs[ch] = o.g
        self.physlims[ch] = o.physlims()
        self.voltlims[ch] = o.voltlims()

        ###Gradient field gradientfield
        ### Gradient
        gradientslope = 0.0971
        gradientoffset = -2.7232
        ch = 'gradientfield'
        gradientfield = gradient_ch(ch, gradientslope, gradientoffset)
        self.cnvcalib[ch] = np.vectorize(gradientfield.cnvcalib)
        self.fs[ch] = gradientfield.f
        self.invcalib[ch] = np.vectorize(gradientfield.invcalib)
        self.gs[ch] = gradientfield.g
        self.physlims[ch] = gradientfield.physlims()
        self.voltlims[ch] = gradientfield.voltlims()

        ### TUNNELING / WANNIERFACTOR to LATTICE DEPTH
        tANDu = ['t_to_V0', 'wF_to_V0']
        for ch in tANDu:
            ### CALIB : unity
            ### FS : interpolation
            if 't_' in ch:
                table = np.loadtxt(physpath + 'tANDU.dat', usecols=(1, 0))
            elif 'wF_' in ch:
                table = np.loadtxt(physpath + 'tANDU.dat', usecols=(2, 0))
            else:
                msg = 'ERROR initializing physics.py conversion ch = %s' % ch
                errormsg.box('PHYSICS.PY', msg)
                exit(1)

            ydat = table[:, 1]  # lattice depths
            xdat = table[:, 0]  # tunneling / wFactor

            try:
                f = pwlinterpolate.interp1d(xdat, ydat, name=ch)
                g = pwlinterpolate.interp1d(ydat, xdat, name=ch)

            except ValueError as e:
                print e
                print "Could not define piecewiwse linear nterpolation function for : \n\t%s" % d
                exit(1)

            self.fs[ch] = f
            self.gs[ch] = g

            self.cnvcalib[ch] = lambda val: val
            self.invcalib[ch] = lambda val: val
            self.physlims[ch] = self.invcalib[ch](np.array(
                [np.amin(xdat), np.amax(xdat)]))
            # Max Er for t, U calculation
            maxEr = 81.
            self.voltlims[ch] = np.array([0., maxEr])

        ### SCATTERING LENGTH to BFIELD
        ch = 'as_to_B'
        ### CALIB : unity
        ### FS : interpolation
        #Use latest data from Jochim group
        table = np.loadtxt(physpath + 'ajochim_truncated.dat', usecols=(1, 0))

        ydat = table[:, 1]  # bfield (Gauss)
        xdat = table[:, 0]  # scattering length (a0)

        try:
            f = pwlinterpolate.interp1d(xdat, ydat, name=ch)
            g = pwlinterpolate.interp1d(ydat, xdat, name=ch)

        except ValueError as e:
            print e
            print "Could not define piecewiwse linear nterpolation function for : \n\t%s" % d
            exit(1)

        self.fs[ch] = f
        self.gs[ch] = g

        self.cnvcalib[ch] = lambda val: val
        self.invcalib[ch] = lambda val: val
        self.physlims[ch] = np.array([np.amin(xdat), np.amax(xdat)])
        self.voltlims[ch] = np.array([np.amin(ydat), np.amax(ydat)])
예제 #18
0
    def __init__(self, file_path='' '''seqconf.seqtxtout()'''):
        """Initialize the class  """

        self.file_path = file_path

        self.folder, self.filename = os.path.split(self.file_path)
        #print self.folder, self.filename
        self.seq = open(self.file_path, 'rU').readlines()
        #~ print [self.seq[-1]]
        self.analog_waveforms_position = []

        for position, str in enumerate(self.seq[1:]):

            if (str == '#' + endofline):

                self.analog_waveforms_position.append(
                    position + 1)  # Plus one since we start from seq[1]
        #~ print self.analog_waveforms_position
        """Parse Digital Waveforms"""

        self.digi_step = float(self.seq[1].split(" ")[1])

        self.digi_channels = self.seq[2].replace(' ', '').split('!')

        self.digi_channels.pop(-1)  # get rid of the final '\n'

        self.digi_data = [[] for i in self.digi_channels]

        for i in self.seq[3:(self.analog_waveforms_position[0])]:

            self.digi_temp = i.replace(' ', '').split('!')

            self.digi_temp.pop(-1)  # get rid of the final '\n'

            for index, j in enumerate(self.digi_temp):

                self.digi_data[index].append(float(j))

        self.digi_time = self.digi_data.pop(0)

        self.digi_channels.pop(0)  # get rid of the time(ms)
        """Parse Analog Waveforms"""

        self.analog_time0 = []

        self.analog_step = []

        self.analog_channels = []

        self.analog_data = []

        self.analog_time = []

        for i in range(len(self.analog_waveforms_position) - 1):

            self.analog_temp = self.seq[(
                self.analog_waveforms_position[i] +
                2):(self.analog_waveforms_position[i + 1])]

            self.analog_time0.append(
                float(
                    self.analog_temp.pop(0).split("\t")[1].replace(
                        endofline, '')))

            self.analog_step.append(
                float(
                    self.analog_temp.pop(0).split("\t")[1].replace(
                        endofline, '')))

            self.analog_channels.append([])

            self.analog_data.append([])

            self.analog_time.append([])

            for index, analog in enumerate(self.analog_temp):

                analog.replace(endofline, '')

                if (index % 2) == 0:

                    self.analog_channels[i].append(
                        analog.replace(endofline, ''))

                else:

                    self.analog_data[i].append(
                        [float(j) for j in analog.replace(' ', '').split(',')])

            self.analog_time[i] = list(
                np.arange(0, len(self.analog_data[i][0]), 1) *
                self.analog_step[i] + self.analog_time0[i])
            if len(self.analog_time[i]) % 2 != 0:
                err = "\n WARNING:\n\n%s\n\nwaveform has an odd number of samples : %d" % (
                    self.analog_channels[i], len(self.analog_time[i]))
                err = err + "\n\nA DAQmx error will occur if you try to run this on labview"
                print err
                errormsg.box("INVALID WAVEFORM ERROR", err)
예제 #19
0
def dimple_to_lattice(s, cpowend):

    print "----- LATTICE LOADING RAMPS -----"

    # Find out which is the longest of the ramps we are dealing with:
    maxX =max( [xdomain(DL.latticeV0)[1] ,\
         xdomain(DL.irpow)[1],\
         xdomain(DL.grpow1)[1],\
         xdomain(DL.grpow2)[1],\
         xdomain(DL.grpow3)[1],\
         xdomain(DL.a_s)[1]] )
    print "Largest x value = %.3f ms\n" % maxX

    # We define the times for which all functions will be evaluated
    # MIN TIME TO DO DIGITAL EXTENSION
    DIGEXTENSION = 2050.
    if DL.image >= DIGEXTENSION:
        Xendtime = DIGEXTENSION
    else:
        Xendtime = DL.image

    Nnew = int(math.floor(Xendtime / DL.ss))
    Xnew = numpy.arange(Xendtime / Nnew, DL.image, Xendtime / Nnew)
    print "X array defined from dt:"
    print "DL.ss =", DL.ss
    print "x0  = ", Xnew[0]
    print "xf  = ", Xnew[-1]
    print "xdt = ", Xnew[1] - Xnew[0]
    print "%d samples" % Nnew
    print 'x shape = ', Xnew.shape

    # Define how we want to ramp up the lattice depth
    v0_ramp, xy_v0, v0set = interpolate_ramp(DL.latticeV0)
    v0 = v0_ramp(Xnew)

    ###########################################
    #### AXIS DEFINITIONS FOR PLOTS ###
    ###########################################

    fig = plt.figure(figsize=(4.5 * 1.05, 8. * 1.1))
    ax0 = fig.add_axes([0.18, 0.76, 0.76, 0.20])
    ax2 = fig.add_axes([0.18, 0.645, 0.76, 0.11])
    ax3 = fig.add_axes([0.18, 0.53, 0.76, 0.11])
    ax1 = fig.add_axes([0.18, 0.415, 0.76, 0.11])
    ax5 = fig.add_axes([0.18, 0.30, 0.76, 0.11])
    ax4 = fig.add_axes([0.18, 0.185, 0.76, 0.11])
    ax6 = fig.add_axes([0.18, 0.07, 0.76, 0.11])

    allax = [ax0, ax1, ax2, ax3, ax4, ax5, ax6]
    for ax in allax:
        ax.axvline(DL.image, linewidth=1., color='black', alpha=0.6)

    lw = 1.5
    labelx = -0.12
    legsz = 8.

    xymew = 0.5
    xyms = 9

    ax0.plot(Xnew, v0, 'b', lw=2.5, label='Lattice depth')
    ax0.plot(xy_v0[:, 0], xy_v0[:, 1], 'x', color='blue', ms=5.)
    ax0.plot(v0set[:, 0], v0set[:, 1], '.', mew=xymew, ms=xyms, color='blue')

    ###########################################
    #### USER DEFINED RAMPS: IR, GR, and U ###
    ###########################################

    # Define how we want to ramp up the IR power
    if DIMPLE.allirpow > 0.:
        ir_offset = DIMPLE.allirpow
    else:
        ir_offset = DIMPLE.ir1pow2
    ir_ramp, xy_ir, ir = interpolate_ramp(DL.irpow, yoffset=ir_offset)

    dt_ir = numpy.amax(ir[:, 0]) - numpy.amin(ir[:, 0])
    N_ir = int(math.floor(dt_ir / DL.ss))
    x_ir = numpy.arange(dt_ir / N_ir, dt_ir, dt_ir / N_ir)

    y_ir = ir_ramp(Xnew)

    if v0.size > y_ir.size:
        y_ir = numpy.append(y_ir, (v0.size - y_ir.size) * [y_ir[-1]])
    elif v0.size < y_ir.size:
        y_ir = y_ir[0:v0.size]

    if v0.size != y_ir.size:
        msg = "IRPOW ERROR: number of samples in IR ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR', msg)
        exit(1)

    alpha_clip_range = 0.1
    if (v0 > y_ir + alpha_clip_range).any():
        msg = "IRPOW ERROR:  not enough power to get desired lattice depth"
        print msg
        bad = numpy.where(v0 > y_ir + alpha_clip_range)
        timefail = int(bad[0][0]) * float(DL.ss)
        msg = msg + "\nFirst bad sample = %d out of %d" % (bad[0][0], v0.size)
        msg = msg + "\n  t = %f " % timefail
        msg = msg + "\n v0 = %f " % v0[bad[0][0]]
        msg = msg + "\n ir = %f " % y_ir[bad[0][0]]
        print v0[bad[0][0]]
        print y_ir[bad[0][0]]
        errormsg.box('LATTICE LOADING ERROR', msg)
        exit(1)

    ax0.plot(xy_ir[:, 0], xy_ir[:, 1], 'x', color='darkorange', ms=5.)
    ax0.plot(ir[:, 0], ir[:, 1], '.', mew=xymew, ms=xyms, color='darkorange')
    ax0.plot(Xnew, y_ir, lw=lw, color='darkorange', label='irpow')

    # Define how we want to ramp up the GR power
    grwfms = {}
    splmrkr = ['x', '+', 'd']
    ptsmrkr = ['^', 's', 'p']
    for i, grramp in enumerate([(DL.grpow1, DIMPLE.gr1pow2),
                                (DL.grpow2, DIMPLE.gr2pow2),
                                (DL.grpow3, DIMPLE.gr3pow2)]):
        ramppts = grramp[0]
        ramp0 = grramp[1]

        print 'gr' + '%d' % i + ' offset = %f' % ramp0

        gr_ramp, xy_gr, gr = interpolate_ramp(ramppts, yoffset=ramp0)

        dt_gr = numpy.amax(gr[:, 0]) - numpy.amin(gr[:, 0])
        N_gr = int(math.floor(dt_gr / DL.ss))
        x_gr = numpy.arange(dt_gr / N_gr, dt_gr, dt_gr / N_gr)

        y_gr = gr_ramp(Xnew)
        if DL.signal == 0:
            y_gr = y_gr / 2.0

        if v0.size > y_gr.size:
            y_gr = numpy.append(y_gr, (v0.size - y_gr.size) * [y_gr[-1]])
        elif v0.size < y_gr.size:
            y_gr = y_gr[0:v0.size]

        if v0.size != y_gr.size:
            msg = "GRPOW ERROR: number of samples in GR ramp and V0 ramp does not match!"
            errormsg.box('LATTICE LOADING ERROR', msg)
            exit(1)

        grwfms['greenpow' + '%1d' % (i + 1)] = y_gr

        ax0.plot(xy_gr[:, 0],
                 xy_gr[:, 1],
                 marker=splmrkr[i],
                 mec='green',
                 mfc='None',
                 ms=3.)
        ax0.plot(gr[:, 0],
                 gr[:, 1],
                 marker=ptsmrkr[i],
                 mew=xymew,
                 ms=xyms / 2.,
                 mfc='None',
                 mec='green')  #, label='grpow dat')
        ax0.plot(Xnew, y_gr, lw=lw, color='green', label='grpow')

    for grch in grwfms.keys():
        print grch, " = ", grwfms[grch].shape

    ax0.set_xlim(left=-10., right=ax0.get_xlim()[1] * 1.1)
    plt.setp(ax0.get_xticklabels(), visible=False)
    ylim = ax0.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax0.set_ylim(ylim[0] - extra, ylim[1] + extra)
    ax0.grid(True)
    ax0.set_ylabel('$E_{r}$', size=16, labelpad=0)
    ax0.yaxis.set_label_coords(labelx, 0.5)
    ax0.set_title('Lattice Loading')
    ax0.legend(loc='best', numpoints=1, prop={'size': legsz * 0.8})

    # Define how we want to ramp up the scattering length (control our losses)
    a_s_ramp, xy_a_s, a_s = interpolate_ramp(DL.a_s)

    dt_a_s = numpy.amax(a_s[:, 0]) - numpy.amin(a_s[:, 0])
    N_a_s = int(math.floor(dt_a_s / DL.ss))
    x_a_s = numpy.arange(dt_a_s / N_a_s, dt_a_s, dt_a_s / N_a_s)
    y_a_s = a_s_ramp(Xnew)

    if v0.size > y_a_s.size:
        y_a_s = numpy.append(y_a_s, (v0.size - y_a_s.size) * [y_a_s[-1]])
    elif v0.size < y_a_s.size:
        y_a_s = y_a_s[0:v0.size]

    if v0.size != y_a_s.size:
        msg = "a_s ERROR: number of samples in a_s ramp and V0 ramp does not match!"
        errormsg.box('LATTICE LOADING ERROR', msg)
        exit(1)

    ax1.plot(xy_a_s[:, 0], xy_a_s[:, 1] / 100., 'x', color='#C10087', ms=5.)
    ax1.plot(a_s[:, 0],
             a_s[:, 1] / 100.,
             '.',
             mew=xymew,
             ms=xyms,
             color='#C10087')
    ax1.plot(Xnew,
             y_a_s / 100.,
             lw=lw,
             color='#C10087',
             label=r'$a_s\mathrm{(100 a_{0})}$')
    ax1.set_ylabel(r'$a_s\mathrm{(100 a_{0})}$', size=16, labelpad=0)
    ax1.yaxis.set_label_coords(labelx, 0.5)

    ax1.set_xlim(ax0.get_xlim())
    ylim = ax1.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax1.set_ylim(ylim[0] - extra, ylim[1] + extra)
    plt.setp(ax1.get_xticklabels(), visible=False)
    ax1.grid(True)
    ax1.legend(loc='best', numpoints=1, prop={'size': legsz})

    #######################################################################
    #### CALCULATED RAMPS:  ALPHA, TUNNELING, SCATTERING LENGTH, BFIELD ###
    #######################################################################

    alpha = (v0 / y_ir)**2.

    alpha_advance = 100.
    N_adv = int(math.floor(alpha_advance / DL.ss))

    alpha = alpha.clip(0., 1.)
    alpha_desired = numpy.copy(alpha)

    if N_adv < v0.size:
        alpha = alpha[N_adv:]
        alpha = numpy.append(alpha, (v0.size - alpha.size) * [alpha[-1]])
    else:
        alpha = numpy.array(v0.size * [alpha[-1]])

    #alpha = alpha.clip(0., 1.)

    ax2.plot(Xnew, alpha, lw=lw, color='saddlebrown', label='alpha adv')
    ax2.plot(Xnew,
             alpha_desired,
             ':',
             lw=lw,
             color='saddlebrown',
             label='alpha')

    ax2.set_xlim(ax0.get_xlim())
    ax2.set_ylim(-0.05, 1.05)
    plt.setp(ax2.get_xticklabels(), visible=False)
    ax2.grid()
    ax2.set_ylabel('$\\alpha$', size=16, labelpad=0)
    ax2.yaxis.set_label_coords(labelx, 0.5)

    ax2.legend(loc='best', numpoints=1, prop={'size': legsz})

    tunneling_Er = physics.inv('t_to_V0', v0)
    tunneling_kHz = tunneling_Er * 29.2

    ax3.plot(Xnew, tunneling_kHz, lw=lw, color='red', label='$t$ (kHz)')

    ax3.set_xlim(ax0.get_xlim())
    ylim = ax3.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax3.set_ylim(ylim[0] - extra, ylim[1] + extra)
    plt.setp(ax3.get_xticklabels(), visible=False)
    ax3.grid(True)
    ax3.set_ylabel(r'$t\,\mathrm{(kHz)}$', size=16, labelpad=0)
    ax3.yaxis.set_label_coords(labelx, 0.5)
    ax3.legend(loc='best', numpoints=1, prop={'size': legsz})

    wannierF = physics.inv('wF_to_V0', v0)

    bohrRadius = 5.29e-11  #meters
    lattice_spacing = 1.064e-6 / 2.  #meters

    bfieldG = physics.cnv('as_to_B', y_a_s)
    print
    print "The last value of the scattering length ramp is:"
    print 'a_s =', y_a_s[-1]
    print 'B   =', bfieldG[-1]
    print

    U_over_t = y_a_s * bohrRadius / lattice_spacing * wannierF / tunneling_Er

    ax4.plot(Xnew, U_over_t, lw=lw, color='k', label=r'$U/t$')

    ax4.set_xlim(ax0.get_xlim())
    ylim = ax4.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax4.set_ylim(ylim[0] - extra, ylim[1] + extra)
    plt.setp(ax4.get_xticklabels(), visible=False)
    ax4.grid(True)
    ax4.set_ylabel(r'$U/t$', size=16, labelpad=0)
    ax4.yaxis.set_label_coords(labelx, 0.5)

    ax4.legend(loc='best', numpoints=1, prop={'size': legsz})

    ax5.plot(Xnew, bfieldG, lw=lw, color='purple', label='$B$ (G)')

    ax5.set_xlim(ax0.get_xlim())
    ylim = ax5.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax5.set_ylim(ylim[0] - extra, ylim[1] + extra)
    ax5.grid(True)
    plt.setp(ax5.get_xticklabels(), visible=False)
    ax5.set_ylabel(r'$B\,\mathrm{(G)}$', size=16, labelpad=0)
    ax5.yaxis.set_label_coords(labelx, 0.5)

    ax5.legend(loc='best', numpoints=1, prop={'size': legsz})

    ax6.plot(Xnew, (tunneling_Er / U_over_t),
             lw=lw,
             color='#25D500',
             label=r'$t^{2}/U\,(E_{r)}$')
    #ax6.set_yscale('log')

    ax6.set_xlim(ax0.get_xlim())
    ylim = ax6.get_ylim()
    extra = (ylim[1] - ylim[0]) * 0.1
    ax6.set_ylim(ylim[0] * 0.5, ylim[1])
    ax6.grid(True)
    ax6.set_ylabel(r'$t^{2}/U\,(E_{r)}$', size=16, labelpad=0)
    ax6.yaxis.set_label_coords(labelx, 0.5)

    ax6.legend(loc='best', numpoints=1, prop={'size': legsz})

    ax6.set_xlabel('time (ms)')

    figfile = seqconf.seqtxtout().split('.')[0] + '_latticeRamp.png'
    plt.savefig(figfile, dpi=120)

    #Save all ramps to a txt file for later plotting.
    datfile = seqconf.seqtxtout().split('.')[0] + '_latticeRamp.dat'
    allRamps = numpy.transpose(numpy.vstack((Xnew, v0, y_ir, grwfms['greenpow1'], y_a_s, alpha, alpha_desired, \
                                    tunneling_kHz, U_over_t, bfieldG)))
    header = '# Column index'
    header = header + '\n#\t0\t' + 'time(ms)'
    header = header + '\n#\t1\t' + 'Lattice Depth (Er)'
    header = header + '\n#\t2\t' + 'Ir power (Er)'
    header = header + '\n#\t3\t' + 'GR power (Er)'
    header = header + '\n#\t4\t' + 'a_s (a0)'
    header = header + '\n#\t5\t' + 'alpha - advance'
    header = header + '\n#\t6\t' + 'alpha - desired'
    header = header + '\n#\t7\t' + 'tunneling (kHz)'
    header = header + '\n#\t8\t' + 'U/t'
    header = header + '\n#\t9\t' + 'bfield (Gauss)'
    header = header + '\n'

    numpy.savetxt(datfile, allRamps)

    with open(datfile, 'w') as f:
        X = numpy.asarray(allRamps)
        f.write(bytes(header))

        format = '%.6e'
        ncol = X.shape[1]
        format = [
            format,
        ] * ncol
        format = ' '.join(format)

        newline = '\n'
        for row in X:
            f.write(numpy.compat.asbytes(format % tuple(row) + newline))

    shutil.copyfile(
        figfile,
        seqconf.savedir() + 'expseq' + seqconf.runnumber() +
        '_latticeRamp.png')
    shutil.copyfile(
        datfile,
        seqconf.savedir() + 'expseq' + seqconf.runnumber() +
        '_latticeRamp.dat')
    #plt.savefig( seqconf.savedir() + 'expseq' + seqconf.runnumber() + '_latticeRamp.png', dpi=120)

    #################################
    #### APPEND RAMPS TO SEQUENCE ###
    #################################

    wfms = []

    if DL.signal == 0:
        print " LOCK VALUE FOR SIGNAL / NOSIGNAL "
        print " before = ", DL.lock_Er
        DL.lock_Er = DL.lock_Er / 1.8
        print " after  = \n", DL.lock_Er

    for ch in ['ir1pow', 'ir2pow', 'ir3pow']:
        n = filter(str.isdigit, ch)[0]
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        w.y = physics.cnv(ch, y_ir)
        if DL.lock:
            endval = w.y[-1]
            w.insertlin_cnv(DL.lock_Er, DL.lock_dtUP, DL.lock_t0)
        elif DL.lightassist_lock:
            endval = w.y[-1]
            w.linear(DL.lightassist_lockpowIR, DL.lightassist_lockdtUP)
            w.appendhold(DL.lightassist_t0 + DL.lightassistdt)
            if DL.endvalIR >= 0.:
                w.linear(DL.endvalIR, DL.lightassist_lockdtDOWN)
            else:
                w.linear(None, DL.lightassist_lockdtDOWN, volt=endval)
        wfms.append(w)

    for ch in ['greenpow1', 'greenpow2', 'greenpow3']:
        n = filter(str.isdigit, ch)[0]
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden

        correction = DIMPLE.__dict__['gr' + n + 'correct']

        w.y = physics.cnv(ch, correction * grwfms[ch])
        if DL.lightassist_lock:
            endval = w.y[-1]
            w.linear(DL.lightassist_lockpowGR, DL.lightassist_lockdtUP)
            w.appendhold(DL.lightassist_t0 + DL.lightassistdt)
            if DL.endvalGR >= 0.:
                w.linear(DL.endvalGR, DL.lightassist_lockdtDOWN)
            else:
                w.linear(None, DL.lightassist_lockdtDOWN, volt=endval)
        wfms.append(w)

    for ch in ['lcr1', 'lcr2', 'lcr3']:
        n = filter(str.isdigit, ch)[0]
        w = wfm.wave(ch, 0.0, DL.ss)  #Start value will be overrriden
        force = DL.__dict__['force_' + ch]
        if force >= 0 and force <= 1:
            print "...Forcing LCR%s = %f during lattice ramp" % (n, force)
            w.y = physics.cnv(ch, numpy.array(alpha.size * [force]))
        elif DL.signal == 0:
            print "...Forcing LCR%s = 0. so that it does NOT rotate to LATTICE" % n
            w.y = physics.cnv(ch, numpy.array(alpha.size * [0.0]))
        else:
            w.y = physics.cnv(ch, alpha)
        wfms.append(w)

    bfieldA = bfieldG / 6.8

    ##ADD field
    bfield = wfm.wave('bfield', 0.0, DL.ss)
    bfield.y = physics.cnv('bfield', bfieldA)
    print "The last value of the bfield voltage is =", bfield.y[-1]
    print
    wfms.append(bfield)

    ##ADD gradient field
    gradient = gradient_wave('gradientfield', 0.0, DL.ss, volt=0.0)
    gradient.follow(bfield)
    wfms.append(gradient)

    buffer = 40.
    s.wait(buffer)

    #~ odtpow = odt.odt_wave('odtpow', cpowend, DL.ss)
    #~ if DIMPLE.odt_t0 > buffer :
    #~ odtpow.appendhold( DIMPLE.odt_t0 - buffer)
    #~ if DIMPLE.odt_pow < 0.:
    #~ odtpow.appendhold( DIMPLE.odt_dt)
    #~ else:
    #~ odtpow.tanhRise( DIMPLE.odt_pow, DIMPLE.odt_dt, DIMPLE.odt_tau, DIMPLE.odt_shift)

    #~ if numpy.absolute(DIMPLE.odt_pow) < 0.0001:
    #~ s.wait( odtpow.dt() )
    #~ s.digichg('odtttl',0)
    #~ s.wait(-odtpow.dt() )

    #~ wfms.append(odtpow)

    # RF sweep
    if DL.rf == 1:
        rfmod = wfm.wave('rfmod', 0., DL.ss)
        rfmod.appendhold(bfield.dt() + DL.rftime)
        rfmod.linear(DL.rfvoltf, DL.rfpulsedt)
        wfms.append(rfmod)

    if DL.round_trip == 1:
        bindex = 0  # Calculate detunings using starting field
    else:
        bindex = -1  # Calculate detunings using field at the end of ramps

    bfieldG = physics.inv('bfield', bfield.y[bindex]) * 6.8
    hfimg0 = -1. * (100.0 + 163.7 - 1.414 * bfieldG)

    # Find bindex for braggkill time
    bindex_BK = math.floor(-DL.braggkilltime / bfield.ss)
    bfieldG_BK = physics.inv('bfield', bfield.y[-1 - bindex_BK]) * 6.8
    hfimg0_BK = -1. * (100.0 + 163.7 - 1.414 * bfieldG_BK)
    DL.braggkill_hfimg = hfimg0_BK - DL.braggkill_hfimg
    print "\n...Braggkill hfimg modification:\n"
    print "\tNEW braggkill_hfimg = %.2f MHz" % DL.braggkill_hfimg

    # Find bindex for bragg2kill time
    bindex_B2K = math.floor(-DL.bragg2killtime / bfield.ss)
    bfieldG_B2K = physics.inv('bfield', bfield.y[-1 - bindex_B2K]) * 6.8
    hfimg0_B2K = -1. * (100.0 + 163.7 - 1.414 * bfieldG_B2K)
    DL.bragg2kill_hfimg1 = hfimg0_B2K - DL.bragg2kill_hfimg1
    DL.bragg2kill_hfimg2 = hfimg0_B2K - DL.bragg2kill_hfimg2
    print "\n...Bragg2kill hfimg modification:\n"
    print "\tNEW brag2gkill_hfimg1 = %.2f MHz" % DL.bragg2kill_hfimg1
    print "\tNEW brag2gkill_hfimg2 = %.2f MHz" % DL.bragg2kill_hfimg2

    print "\n...ANDOR:hfimg and hfimg0 will be modified  in report\n"
    print "\tNEW  ANDOR:hfimg  = %.2f MHz" % (hfimg0 - DL.imgdet)
    print "\tNEW  ANDOR:hfimg0 = %.2f MHz\n" % hfimg0
    gen.save_to_report('ANDOR', 'hfimg', hfimg0 - DL.imgdet)
    gen.save_to_report('ANDOR', 'hfimg0', hfimg0)

    newANDORhfimg = hfimg0 - DL.imgdet

    # THIS DEFINES THE TIME IT TAKES THE OFFSET LOCK TO SWITCH TO
    # A NEW SETPOINT
    hfimgdelay = 50.  #ms

    # Kill hfimg
    if DL.probekill == 1 or DL.braggkill == 1 or DL.bragg2kill == 1 or DL.lightassist or DL.lightassist_lock:
        analogimg = wfm.wave('analogimg', newANDORhfimg, DL.ss)

        if DL.probekill == 1:
            if (-DL.probekilltime + hfimgdelay) < DL.image:
                analogimg.appendhold(bfield.dt() + DL.probekilltime -
                                     hfimgdelay)
                analogimg.linear(DL.probekill_hfimg, 0.0)
                analogimg.appendhold(hfimgdelay + DL.probekilldt + 3 * DL.ss)

        elif DL.braggkill == 1:
            print "Setting up analogimg for braggkill"
            if (-DL.braggkilltime + hfimgdelay) < DL.image:
                analogimg.appendhold(bfield.dt() + DL.braggkilltime -
                                     hfimgdelay)
                analogimg.linear(DL.braggkill_hfimg, 0.0)
                analogimg.appendhold(hfimgdelay + DL.braggkilldt + 3 * DL.ss)

        elif DL.bragg2kill == 1:
            print "Setting up analogimg for bragg2kill"
            if (-DL.bragg2killtime + hfimgdelay) < DL.image:
                # This sets up the detuning for the first pulse
                analogimg.appendhold(bfield.dt() + DL.bragg2killtime -
                                     hfimgdelay)
                analogimg.linear(DL.bragg2kill_hfimg1, 0.0)
                analogimg.appendhold(hfimgdelay + DL.bragg2killdt + 3 * DL.ss)

                # Then set up the detuning for the second pulse
                analogimg.linear(DL.bragg2kill_hfimg2, 0.0)
                analogimg.appendhold(hfimgdelay + DL.bragg2killdt + 3 * DL.ss)

        elif DL.lightassist == 1 or DL.lightassist_lock:
            analogimg.appendhold(bfield.dt() - hfimgdelay)
            analogimg.linear(DL.lightassist_hfimg, 0.0)
            duration = DL.lightassist_lockdtUP + DL.lightassist_t0 + DL.lightassistdt + DL.lightassist_lockdtDOWN
            analogimg.appendhold(hfimgdelay + duration + 3 * DL.ss)

        analogimg.linear(newANDORhfimg, 0.)
        analogimg.extend(10)
        wfms.append(analogimg)

    #analogimg = bfieldwfm.hfimg_wave('analogimg', ANDOR.hfimg, DL.ss)
    #andorhfimg0 = analogimg.follow(bfield, DL.imgdet)
    #wfms.append(analogimg)

    # If we are doing round trip END, then mirror all the ramps
    # before adding them to the sequence
    if DL.round_trip == 1:
        if DL.round_trip_type == 1:
            maxdt = 0.
            maxi = -1
            for i, w in enumerate(wfms):
                if w.dt() > maxdt:
                    maxdt = w.dt()
                    maxi = i

            maxdt = maxdt + DL.wait_at_top / 2.

            for w in wfms:
                w.extend(maxdt)
                if 'lcr' in w.name:
                    yvals = w.y

                    #Get the reverse of the alpha desired array
                    alpha_mirror = numpy.copy(alpha_desired[::-1])

                    #Add the wait at top part so that it has same length as yvals
                    if alpha_mirror.size > yvals.size:
                        print "Error making mirror ramp for LCR."
                        print "Program will exit."
                        exit(1)
                    alpha_mirror = numpy.append(
                        (yvals.size - alpha_mirror.size) * [alpha_mirror[0]],
                        alpha_mirror)

                    #This is how much the mirror ramp will be advanced
                    N_adv = int(math.floor(DL.lcr_mirror_advance / DL.ss))

                    if N_adv < alpha_mirror.size:
                        alpha_mirror = alpha_mirror[N_adv:]
                        alpha_mirror = numpy.append(
                            alpha_mirror, (yvals.size - alpha_mirror.size) *
                            [alpha_mirror[-1]])
                    else:
                        alpha_mirror = numpy.array(yvals.size *
                                                   [alpha_mirror[-1]])

                    w.y = numpy.concatenate(
                        (yvals, physics.cnv(w.name, alpha_mirror)))
                else:
                    w.mirror()
                w.appendhold(DL.wait_at_end)

    N_adv = int(math.floor(alpha_advance / DL.ss))

    alpha_desired = numpy.copy(alpha)

    for wavefm in wfms:
        print "%s dt = %f" % (wavefm.name, wavefm.dt())

    duration = s.analogwfm_add(DL.ss, wfms)

    if DL.image < DIGEXTENSION:
        s.wait(duration)
    else:
        print "...DL.image = %f  >= %.2f  Digital seq extension will be used." % (
            DL.image, DIGEXTENSION)
        s.wait(DL.image)

    ### Prepare the parts of the ramps that are going to be used to mock
    ### the conditions for the noatoms shot
    ### 1. get dt = [noatoms] ms from the end of the lattice ramps.
    if 'manta' in DL.camera:
        noatomsdt = MANTA.noatoms
    else:
        noatomsdt = ANDOR.noatoms
    noatomswfms = []
    for wavefm in wfms:
        cp = copy.deepcopy(wavefm)
        cp.idnum = time.time() * 100
        cp.retain_last(DL.bgRetainDT)
        noatomswfms.append(cp)

    ### Figure out when to turn interlock back on, using alpha information
    #~ if duration > DL.t0 + DL.dt:
    #~ s.wait(-DL.lattice_interlock_time)
    #~ if DL.use_lattice_interlock == 1:
    #~ s.digichg('latticeinterlockbypass',0)
    #~ else:
    #~ s.digichg('latticeinterlockbypass',1)
    #~ s.wait( DL.lattice_interlock_time)

    #########################################
    ## OTHER TTL EVENTS: probekill, braggkill, rf, quick2
    #########################################
    # Braggkill
    if DL.braggkill == 1:
        print "Using Bragg Kill"
        s.wait(DL.braggkilltime)
        s = manta.OpenShutterBragg(s, DL.shutterdelay)
        s.digichg('bragg', 1)
        s.wait(DL.braggkilldt)
        s.digichg('brshutter', 1)  # to close shutter
        s.digichg('bragg', 0)

        s.wait(-DL.braggkilldt)
        s.wait(-DL.braggkilltime)

    if DL.bragg2kill == 1:
        print "Using Bragg 2 Kill"
        tcur = s.tcur
        s.wait(DL.bragg2killtime)
        s = manta.OpenShutterBragg(s, DL.shutterdelay)
        s.digichg('bragg', 1)
        s.wait(DL.bragg2killdt)
        s.digichg('brshutter', 1)  # to close shutter
        s.digichg('bragg', 0)

        s.wait(hfimgdelay + 3 * DL.ss)
        s = manta.OpenShutterBragg(s, DL.shutterdelay)
        s.digichg('bragg', 1)
        s.wait(DL.bragg2killdt)
        s.digichg('brshutter', 1)  # to close shutter
        s.digichg('bragg', 0)

        # Revert to current time after pulses have been added in the past
        s.tcur = tcur

    # Probe Kill
    if DL.probekill == 1:
        s.wait(DL.probekilltime)

        s.wait(-10)
        s.digichg('prshutter', 0)
        s.wait(10)
        s.digichg('probe', 1)
        s.wait(DL.probekilldt)
        s.digichg('probe', 0)

        s.digichg('prshutter', 1)
        s.wait(-DL.probekilltime)

    # Pulse RF
    if DL.rf == 1:
        s.wait(DL.rftime)
        s.digichg('rfttl', 1)
        s.wait(DL.rfpulsedt)
        s.digichg('rfttl', 0)
        s.wait(-DL.rfpulsedt)
        s.wait(-DL.rftime)

    # QUICK2
    if DL.quick2 == 1:
        s.wait(DL.quick2time)
        s.digichg('quick2', 1)
        s.wait(-DL.quick2time)

    # Light-assisted collisions
    if DL.lightassist == 1 or DL.lightassist_lock:
        s.wait(-DL.lightassist_lockdtUP - DL.lightassist_t0 -
               DL.lightassistdt - DL.lightassist_lockdtDOWN - 3 * DL.ss)

        s.wait(DL.lightassist_lockdtUP + DL.lightassist_t0)
        s.wait(-10)
        s.digichg('prshutter', 0)
        s.wait(10)
        s.digichg('probe', DL.lightassist)
        s.wait(DL.lightassistdt)
        s.digichg('probe', 0)

        s.digichg('prshutter', 1)
        s.wait(DL.lightassist_lockdtDOWN)
        s.wait(3 * DL.ss)
        # After the collisions happen we still need to wait some time
        # for the probe frequency to come back to the desired value
        s.wait(hfimgdelay)

    #########################################
    ## GO BACK IN TIME IF DOING ROUND-TRIP START
    #########################################
    if DL.round_trip == 1:
        if DL.round_trip_type == 0:
            s.wait(-DL.image)
            s.stop_analog()

    #########################################
    ## TURN GREEN OFF BEFORE PICTURES
    #########################################
    if DL.greenoff == 1:
        s.wait(DL.greenoff_t0)
        s.digichg('greenttl1', 0)
        s.digichg('greenttl2', 0)
        s.digichg('greenttl3', 0)
        s.wait(-DL.greenoff_t0)

    #########################################
    ## LATTICE LOCK WITH POSSIBILITY OF RF
    #########################################
    bufferdt = 5.0
    lastIR = y_ir[-1]

    lockwfms = []
    if DL.locksmooth == 1 and DL.lock == 0:
        s.wait(bufferdt)
        for ch in ['ir1pow', 'ir2pow', 'ir3pow']:
            n = filter(str.isdigit, ch)[0]
            w = wfm.wave(ch, lastIR,
                         DL.lockss)  #Start value will be overrriden
            w.tanhRise(DL.lock_Er, DL.lock_dtUP, 0.4, 0.2)
            lockwfms.append(w)
        print "...LOCKING LATTICE TO %f Er" % DL.lock_Er
        print "...lastIR = %.4f" % lastIR
        duration = s.analogwfm_add(DL.lockss, lockwfms)
        print "...duration = %.2f" % duration
        s.wait(duration)
        #~ if DL.lockrf:
        #~ s.digichg('rfttl',1)
        #~ s.wait(DL.rfpulsedt)
        #~ s.digichg('rfttl',0)
        #~ s.wait(0.036)
    #else:
    #    s.wait(bufferdt)

    lockwfmscopy = []
    for wavefm in lockwfms:
        cp = copy.deepcopy(wavefm)
        cp.idnum = time.time() * 100 + 1e3 * numpy.random.randint(0, 1e8)
        lockwfmscopy.append(cp)

    #########################################
    ## IMAGING AT LOW FIELD
    #########################################
    if DL.lowfieldimg == 1:
        s.wait(DL.lowfieldimg_t0)
        s.digichg('field', 0)
        s.wait(-DL.lowfieldimg_t0)

    #########################################
    ## TTL RELEASE FROM ODT and LATTICE
    #########################################
    #INDICATE WHICH CHANNELS ARE TO BE CONSIDERED FOR THE BACKGROUND
    bg = [
        'odtttl', 'irttl1', 'irttl2', 'irttl3', 'greenttl1', 'greenttl2',
        'greenttl3'
    ]
    bgdictPRETOF = {}
    for ch in bg:
        bgdictPRETOF[ch] = s.digistatus(ch)
    bgdictPRETOF['tof'] = DL.tof
    print "\nChannel status for pictures: PRE-TOF"
    print bgdictPRETOF
    print

    #RELEASE FROM LATTICE
    if DL.tof <= 0.:
        s.wait(1.0 + ANDOR.exp)
    s.digichg('greenttl1', 0)
    s.digichg('greenttl2', 0)
    s.digichg('greenttl3', 0)
    s.digichg('irttl1', 0)
    s.digichg('irttl2', 0)
    s.digichg('irttl3', 0)
    #RELEASE FROM IR TRAP
    s.digichg('odtttl', 0)
    if DL.tof <= 0.:
        s.wait(-1.0 + ANDOR.exp)

    print "TIME WHEN RELEASED FROM LATTICE = ", s.tcur
    s.wait(DL.tof)

    return s, noatomswfms, lockwfmscopy, bgdictPRETOF
예제 #20
0
    def __init__(self):
        
        ### This dictionaries define the functions used for conversion 
        self.fs={}
        self.gs={}
        self.cnvcalib={}
        self.invcalib={}
        self.physlims={}
        self.voltlims={}
        
        
        
        ### The for loop below takes care of all the channels that 
        ### are associated with a calibration file 
        dats = glob.glob(lab + 'software/apparatus3/convert/data/*.dat')

        for d in dats:
            table = np.loadtxt(d, usecols  = (1,0))
            
            ydat = table[:,1]  # voltages
            xdat = table[:,0] # calibrated quantity
            
            ch =  os.path.splitext( os.path.split(d)[1] )[0]
            
            try:
                f = pwlinterpolate.interp1d( xdat, ydat , name = ch)
                g = pwlinterpolate.interp1d( ydat, xdat , name = ch)
                
            except ValueError as e:
                print e
                print "Could not define piecewiwse linear nterpolation function for : \n\t%s" % d
                exit(1)
            
            self.fs[ch] = f
            self.gs[ch] = g
            
            
            if ch == 'trapdet':
                ### IN    :  MHz detuning at atoms
                ### CALIB :  Double-pass AOM frequency
                shift = -1.1
                self.cnvcalib[ch] = lambda val: (val+shift+120.+120.)/2. 
                self.invcalib[ch] = lambda val: 2*val -shift -120 - 120. 
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([2.0, 8.0])
                
            elif ch == 'repdet':
                ### IN    :  MHz detuning at atoms
                ### CALIB :  Double-pass AOM frequency
                shift = -1.1
                self.cnvcalib[ch] = lambda val: (val+shift+228.2 -80.0 + 120.)/2. 
                self.invcalib[ch] = lambda val: 2*val -shift -228.2 + 80.0 - 120.
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([2.0, 8.0])
                
            elif ch == 'motpow':
                ### IN    :  Isat/beam at atoms
                ### CALIB :  Power measured by MOT TA monitor
                w0 = 0.86  # beam waist
                ta = 1.682 # power lost to TA sidebands
                op = 1.37  # power loss in MOT optics
                self.cnvcalib[ch] = lambda val: op*ta*6*val*5.1*(3.14*w0*w0)/2.
                self.invcalib[ch] = lambda val: 2*val/op/ta/6/5.1/(3.14*w0*w0) 
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0.1, 10.])

            elif ch == 'trappow' or ch == 'reppow':
                ### IN    :  power injected to TA
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0., 10.])
                

            elif ch == 'bfield':
                ### IN    :  current measured on power supply
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0., 9.0])
                
            elif ch == 'uvdet':
                ### IN    :  UV detuning in MHz
                ### CALIB :  Double-pass AOM frequency
                self.cnvcalib[ch] = lambda val: (val + 130.17)/2.0
                self.invcalib[ch] = lambda val: val*2.0 - 130.17
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([2.744, 4.744])
                
            elif ch == 'uvpow':
                ### IN    :  power measured after 75 um pinhole
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0., 7.0])
        
            elif ch == 'uv1freq':
                ### IN    :  Frequency of uvaom1 in MHz
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0., 10.0])

            elif ch == 'analogimg':
                ### IN    :  Frequency of offset lock beat signal MHz
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0., 10.0])
                
            elif ch == 'lcr1' or ch == 'lcr2' or ch == 'lcr3':
                ### IN    :  Lattice ratio:  1=lattice  0=dimple
                ### CALIB :  same as IN
                self.cnvcalib[ch] = lambda val: val
                self.invcalib[ch] = lambda val: val
                self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
                self.voltlims[ch] = np.array([0., 10.0])
                
            else:
                self.cnvcalib[ch] = lambda val:val
                self.invcalib[ch] = lambda val:val
                self.physlims[ch] = None
                self.voltlims[ch] = None
             
             
        
        ### Channels that are NOT associated with calibration files are 
        ### defined below 

        chs = ['uvpow2', 'ipganalog', 'rfmod'] 
        for ch in chs:
            self.cnvcalib[ch] = lambda val: val
            self.invcalib[ch] = lambda val: val
            self.fs[ch] = lambda x: x 
            self.gs[ch] = lambda x: x
            self.physlims[ch] = np.array([0., 10.])
            self.voltlims[ch] = np.array([0., 10.])
        
        
        latticechs = ['ir1pow', 'ir2pow', 'ir3pow','greenpow1', 'greenpow2', 'greenpow3' ]
        for ch in latticechs:
            ### CALIB : power in mW 
            ### FS : PD voltag
            l = lattice_ch( ch, w0d[ch], m1d[ch], V0d[ch], ErMaxd[ch], VMaxd[ch], VMinServod[ch])
            self.cnvcalib[ch] = l.cnvcalib
            self.fs[ch] = l.f
            self.invcalib[ch] = l.invcalib
            self.gs[ch] = l.g
            self.physlims[ch] = l.physlims()
            self.voltlims[ch] = l.voltlims()
            
        ### ODTPOW
        o = odtpow_ch() 
        ch = 'odtpow'
        self.cnvcalib[ch] = np.vectorize(o.cnvcalib)
        self.fs[ch] = o.f
        self.invcalib[ch] = np.vectorize(o.invcalib)
        self.gs[ch] = o.g
        self.physlims[ch] = o.physlims()
        self.voltlims[ch] = o.voltlims()    
        
        ###Gradient field gradientfield
        ### Gradient 
        gradientslope =  0.0971
        gradientoffset =  -2.7232
        ch = 'gradientfield'
        gradientfield = gradient_ch(ch,gradientslope,gradientoffset ) 
        self.cnvcalib[ch] = np.vectorize(gradientfield.cnvcalib)
        self.fs[ch] = gradientfield.f
        self.invcalib[ch] = np.vectorize(gradientfield.invcalib)
        self.gs[ch] = gradientfield.g
        self.physlims[ch] = gradientfield.physlims()
        self.voltlims[ch] = gradientfield.voltlims()


        ### TUNNELING / WANNIERFACTOR to LATTICE DEPTH
        tANDu = ['t_to_V0','wF_to_V0']
        for ch in tANDu:
            ### CALIB : unity
            ### FS : interpolation
            if 't_' in ch:
                table = np.loadtxt(physpath+'tANDU.dat', usecols  = (1,0))
            elif 'wF_' in ch:
                table = np.loadtxt(physpath+'tANDU.dat', usecols  = (2,0))
            else:
                msg = 'ERROR initializing physics.py conversion ch = %s' % ch
                errormsg.box('PHYSICS.PY', msg)
                exit(1)
            
            ydat = table[:,1] # lattice depths
            xdat = table[:,0] # tunneling / wFactor
            
            try:
                f = pwlinterpolate.interp1d( xdat, ydat , name = ch)
                g = pwlinterpolate.interp1d( ydat, xdat , name = ch)
                
            except ValueError as e:
                print e
                print "Could not define piecewiwse linear nterpolation function for : \n\t%s" % d
                exit(1)
 
            self.fs[ch] = f
            self.gs[ch] = g
           
            self.cnvcalib[ch] = lambda val: val
            self.invcalib[ch] = lambda val: val
            self.physlims[ch] = self.invcalib[ch]( np.array( [ np.amin(xdat), np.amax(xdat) ] ) ) 
            self.voltlims[ch] = np.array([0., 56.])

        ### SCATTERING LENGTH to BFIELD 
        ch = 'as_to_B' 
        ### CALIB : unity
        ### FS : interpolation
        #Use latest data from Jochim group
        table = np.loadtxt(physpath+'ajochim_truncated.dat', usecols  = (1,0))

        ydat = table[:,1] # bfield (Gauss)
        xdat = table[:,0] # scattering length (a0)
        
        try:
            f = pwlinterpolate.interp1d( xdat, ydat , name = ch)
            g = pwlinterpolate.interp1d( ydat, xdat , name = ch)
            
        except ValueError as e:
            print e
            print "Could not define piecewiwse linear nterpolation function for : \n\t%s" % d
            exit(1)

        self.fs[ch] = f
        self.gs[ch] = g

        self.cnvcalib[ch] = lambda val: val
        self.invcalib[ch] = lambda val: val
        self.physlims[ch] = np.array( [ np.amin(xdat), np.amax(xdat) ] ) 
        self.voltlims[ch] = np.array( [ np.amin(ydat), np.amax(ydat) ] )
예제 #21
0
    def __init__(self,file_path = '' '''seqconf.seqtxtout()'''):
        """Initialize the class  """

        #Open sequence txt file        
        self.file_path = file_path
        self.folder, self.filename = os.path.split(self.file_path)
        self.seq = open(self.file_path,'rU').readlines()

        #Find the line numbers that mark start of analog waveform outputs
        self.analog_waveforms_position = []
        for position, line in enumerate(self.seq[1:]):	
            if (line == '#'+endofline): 
                self.analog_waveforms_position.append(position+1) # Plus one since we start from seq[1]

        """Parse Digital Waveforms"""
        self.digi_step = float(self.seq[1].split(" ")[1])

        self.digi_channels = self.seq[2].replace(' ','').split('!')
        self.digi_channels.pop(-1) # get rid of the final '\n'

        self.digi_data = [ [] for i in self.digi_channels]

        #Iterate through lines in the digital section and get the data
        digitalSection = self.seq[3:(self.analog_waveforms_position[0])]
        for i in digitalSection:
            self.digi_temp = i.replace(' ','').split('!')
            self.digi_temp.pop(-1) # get rid of the final '\n'
            
            for index, j in enumerate(self.digi_temp):
                self.digi_data[index].append(float(j))

        #The first column corresponds to the time values
        self.digi_time = self.digi_data.pop(0)
        self.digi_channels.pop(0) # get rid of the time(ms)
       
 
        """Parse Analog Waveforms"""
        self.analog_time0 = []
        self.analog_step = []
        self.analog_channels = []
        self.analog_data = []
        self.analog_time = []

        #Iterate over the waveforms, populating the above arrays        
        for i in range(len(self.analog_waveforms_position)-1):

            #Get TIME and STEP
            self.analog_temp = self.seq[(self.analog_waveforms_position[i]+2):(self.analog_waveforms_position[i+1])]
            self.analog_time0.append(float(self.analog_temp.pop(0).split("\t")[1].replace(endofline,'')))
            self.analog_step.append(float(self.analog_temp.pop(0).split("\t")[1].replace(endofline,'')))

            #Get CHANNELS, TIMEDATA, and VOLTAGEDATA
            self.analog_channels.append([])
            self.analog_data.append([])
            self.analog_time.append([])

            #Iterate over CHANNELS in WAVEFORM
            for index, analog in enumerate(self.analog_temp):
                analog.replace(endofline,'')
                if ( index % 2 ) == 0:
                    self.analog_channels[i].append(analog.replace(endofline,''))
                else:
                    self.analog_data[i].append( [ float(j) for j in analog.replace(' ','').split(',') ] )

            #All CHANNELS in WAVEFORM have the same TIMEDATA
            #Here it is calculated using the initial TIME and the STEP        
            self.analog_time[i] = list(np.arange(0, len(self.analog_data[i][0]), 1)*self.analog_step[i]  + self.analog_time0[i])
            if len(self.analog_time[i]) % 2 != 0 :
                err =  "\n WARNING:\n\n%s\n\nwaveform has an odd number of samples : %d" % (self.analog_channels[i], len(self.analog_time[i]))
                err = err +  "\n\nA DAQmx error will occur if you try to run this on labview"
                print err
                errormsg.box("INVALID WAVEFORM ERROR", err ) 


        #Collect information for each channel into two dictionaries
        self.flatwfms = {} 	#  just has the waveform data
        self.wfms = {} 	#  has the waveform data, along with an index that
			#  indicates which wfmout did this data belong to

        #the keys of the dictionary are the channel names
        #the values of the dictionary are an array with all the waveform outs for that channel

        for w, wfmouts in enumerate(self.analog_channels):

           for c, ch in enumerate(wfmouts):

             #The 2d-array called data represents the waveform:
             data = np.transpose(np.array(  [ self.analog_time[w], self.analog_data[w][c] ]  ))

             #chdat has two elements : [ data, index of wfm to which data corresponds ] 
             chdat =  [data,  w]

             #Populate the flatwfms and wfms dictionaries
             if ch not in self.wfms.keys():
               self.wfms[ch] = [chdat]
               self.flatwfms[ch] = data
             else:
               self.wfms[ch].append(chdat)
               self.flatwfms[ch] = np.concatenate( [self.flatwfms[ch],data], axis=0 )


        #The flatwfms dictionary is used to populate flat arrays
        #which contain all output information for each channel
        #This flat arrays are the ones used for plotting
        self.flat_analog_chs = []
        self.flat_analog_times = []
        self.flat_analog_data = []
        for i in self.flatwfms.keys(): 
           self.flat_analog_chs.append(i)
           self.flat_analog_times.append( self.flatwfms[i][:,0] )
           self.flat_analog_data.append( self.flatwfms[i][:,1] )
예제 #22
0
    def check( self, ch , phys, volt ):
        
        physa = np.asarray(phys)
        volta = np.asarray(volt)
        
        #Give a little room for rounding errors 
        #and some wiggle room for the physical limits
        physMin = self.physlims[ch][0] - 0.000001
        physMax = self.physlims[ch][1] + 0.000001
        
        
        physMin = physMin - (physMax-physMin)*0.015
        physMax = physMax + (physMax-physMin)*0.015
        

        voltMin = self.voltlims[ch][0] - 0.000001
        voltMax = self.voltlims[ch][1] + 0.000001
        
        #print type(val)
        #print type(out)
        
        below_bound_phys = physa < physMin
        above_bound_phys = physa > physMax
        
        below_bound_volt = volta < voltMin
        above_bound_volt = volta > voltMax
        
        if below_bound_phys.any() or above_bound_phys.any():
            print "phys =", physa
            print "physMin,PhysMax =",physMin,physMax
            out_of_bounds_phys = None
            
            print "Error in conversion of %s with length = %d" % ( type(physa), len(physa) )
              
            msg = "Physical limits [%f,%f]\n" % (physMin, physMax)
            msg += "The following values are outside the physical limits:"
            
            if physa.ndim < 1:
                out_of_bounds_phys = physa
                msg = msg + '\n\t' + str(out_of_bounds_phys) 
            else:
                out_of_bounds_phys  =  np.concatenate( (physa[ np.where( physa < physMin ) ],physa[np.where( physa > physMax)] ))
                msg = msg + '\n\t' + str(out_of_bounds_phys) 
            
            print msg 
              
            errormsg.box('CONVERSION CHECK:: ' + ch, msg)

            raise ValueError("A value is outside the physics range.  ch = %s" % ch)

        if below_bound_volt.any() or above_bound_volt.any():

            
            out_of_bounds_volt = None
            
            msg = "Voltage limits [%f,%f]\n" % (voltMin, voltMax)  
            msg += "The following values are outside the voltage limits:"

            if volta.ndim < 1:
                out_of_bounds_volt = volta
                msg = msg + '\n\t' + str(out_of_bounds_volt) 
            else:
                out_of_bounds_volt  =  np.concatenate( (volta[ np.where( volta < voltMin ) ], volta[np.where( volta > voltMax)]))
                msg = msg + '\n\t' + str(out_of_bounds_volt) 
            
            print msg 
              
            errormsg.box('CONVERSION CHECK :: ' + ch, msg)

            raise ValueError("A value is outside the voltage range. ch = %s" % ch)
                
                
        return (volt, phys)