コード例 #1
0
    def onclick(self, event):

        if event.button is not self.mousebutton: return

        if event.xdata == None:
            event.xdata = 0
            event.ydata = 0
        self.pts.append((event.xdata, event.ydata))

        try:
            color = self.kwargs['color']
        except KeyError:            color=self.colors[(len(self.pts)-1)\
                              %len(self.colors)] #Colors will cycle
        try:
            fontsize = self.kwargs['fontsize']
        except KeyError:
            fontsize = 14

        l = self.ax.plot([event.xdata], [event.ydata], 'o', color=color)[0]
        self.ax.text(event.xdata,event.ydata,len(self.pts),fontsize=fontsize,\
                     bbox=dict(facecolor='white', alpha=0.25),\
                     horizontalalignment='center',\
                     verticalalignment='bottom')
        plt.draw()

        # Quit the loop if we achieve the desired number of points #
        if self.max_pts and len(self.pts) == self.max_pts:
            event.key = 'quit_for_sure'
            self.onquit(event)

        if self.verbose:
            Logger.write('You are now on point #%i' % (len(self.pts) + 1))
コード例 #2
0
    def __init__(self,
                 mousebutton=1,
                 max_pts=1,
                 ax=None,
                 cbar=None,
                 message=None,
                 verbose=False,
                 **kwargs):

        import time

        self.pts = []
        self.verbose = verbose
        self.kwargs = kwargs

        self.mousebutton = mousebutton
        self.max_pts = max_pts
        self.colors = ['b', 'r', 'g', 'c', 'm', 'y']

        self.cid1 = plt.gcf().canvas.mpl_connect('button_press_event',
                                                 self.onclick)
        self.cid2 = plt.gcf().canvas.mpl_connect('key_press_event',
                                                 self.ondelete)
        self.cid3 = plt.gcf().canvas.mpl_connect('key_press_event',
                                                 self.onquit)
        self.cid4 = plt.gcf().canvas.mpl_connect('key_press_event',
                                                 self.colorlimits)

        if not ax: ax = plt.gca()
        self.ax = ax
        self.cbar = cbar

        if verbose:
            if not message:
                message = 'Please click %s points on the current figure using \
                         mouse button %i.  You may at any time strike the "c" \
                         key to change color limits on an image, or the "delete" \
                         key to remove the last selected point.' % (
                    max_pts, mousebutton)
            Logger.write(message)
            Logger.write('\tYou are now on point #1.')

        plt.gcf().canvas.start_event_loop(timeout=0)
コード例 #3
0
def GenerateCarbonylTips(Ls=numpy.linspace(30,20e3,100),a=30,\
                         wavelength=6e3,taper_angles=[10,20],\
                         geometries=['cone','hyperboloid']):

    skin_depth = .05

    if wavelength is None: freq = 0
    else: freq = a / numpy.float(wavelength)
    Ls = Ls / numpy.float(a)

    for i, geometry in enumerate(geometries):
        for k, taper_angle in enumerate(taper_angles):
            for j, L in enumerate(Ls):

                Logger.write('Currently working on geometry "%s", L/a=%s...' %
                             (geometry, L))
                tip.build_charge_distributions(Nqs=144,Nzs=144,L=L,taper_angle=taper_angle,quadrature='TS',\
                                               geometry=geometry,freq=freq,skin_depth=skin_depth)

                progress = (
                    (i * len(taper_angles) + k) * len(Ls) + j +
                    1) / numpy.float(
                        len(Ls) * len(geometries) * len(taper_angles)) * 100
                Logger.write('\tProgress: %1.1f%%' % progress)

    Logger.write('Done!')
コード例 #4
0
 def polyfit_poles_residues(self,deg=6,zmax=10):
     
     Nterms=self.Ps.shape[1]
     Rs=self.Rs.cslice[:zmax]
     Ps=self.Ps.cslice[:zmax]
     zs=Rs.axes[0]
     
     if self.verbose:
         Logger.write('Finding complex polynomial approximations of degree %i '%deg+\
                      'to the first %i poles and residues, up to a value z/a=%s...'%(Nterms,zmax))
         
     self.Ppolys=[]
     for i in range(Nterms):
         
         Ppoly=numpy.polyfit(zs,Ps[:,i],deg=deg)
         self.Ppolys.append(Ppoly)
     
     self.Rpolys=[]
     for i in range(Nterms):
         
         Rpoly=numpy.polyfit(zs,Rs[:,i],deg=deg)
         self.Rpolys.append(Rpoly)
コード例 #5
0
        gtuples = numpy.vstack((x, g, g)).transpose().tolist()
        btuples = numpy.vstack((x, b, b)).transpose().tolist()
        cdit = {'red': rtuples, 'green': gtuples, 'blue': btuples}

        pyplot.register_cmap(name=cmap_name, data=cdit)

        r = r[::-1]
        g = g[::-1]
        b = b[::-1]
        rtuples_r = numpy.vstack((x, r, r)).transpose().tolist()
        gtuples_r = numpy.vstack((x, g, g)).transpose().tolist()
        btuples_r = numpy.vstack((x, b, b)).transpose().tolist()
        cdit_r = {'red': rtuples_r, 'green': gtuples_r, 'blue': btuples_r}

        pyplot.register_cmap(name=cmap_name + '_r', data=cdit_r)
        Logger.write('Registered colormaps "%s" and "%s_r"...' %
                     ((cmap_name, ) * 2))

# ----- Plotting functions

_color_index_ = 0
all_colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'teal', 'gray', 'navy']


def next_color():

    global _color_index_
    color = all_colors[_color_index_ % len(all_colors)]
    _color_index_ += 1

    return color
コード例 #6
0
 def invert_signal(self,signals,nodes=[(1,0)],Nterms=10,\
                   interpolation='linear',\
                   select_by='continuity',\
                   closest_pole=0,\
                   scaling=10):
     """The inversion is not unique, consequently the selected solution
     will probably be wrong if signal values correspond with 
     "beta" values that are too large (`|beta|~>min{|Poles|}`).
     This can be expected to break at around `|beta|>2`."""
     #Default is to invert signal in contact
     #~10 terms seem required to converge on e.g. SiO2 spectrum,
     #especially on the Re(beta)<0 (low signal) side of phonons
     
     global roots,poly,root_scaling
     
     #global betas,all_roots,pmin,rs,ps,As,Bs,roots,to_minimize
     if self.verbose:
         Logger.write('Inverting `signals` based on the provided `nodes` to obtain consistent beta values...')
     
     if not hasattr(signals,'__len__'): signals=[signals]
     if not isinstance(signals,AWA): signals=AWA(signals)
     
     zs,ws=list(zip(*nodes))
     ws_grid=numpy.array(ws).reshape((len(ws),1)) #last dimension is to broadcast over all `Nterms` equally
     zs=numpy.array(zs)
     
     Rs=self.Rs[:,:Nterms].interpolate_axis(zs,axis=0,kind=interpolation,
                                                    bounds_error=False,extrapolate=True)
     Ps=self.Ps[:,:Nterms].interpolate_axis(zs,axis=0,kind=interpolation,
                                                    bounds_error=False,extrapolate=True)
     
     #`rs` and `ps` can safely remain as arrays for `invres`
     rs=(Rs*ws_grid).flatten()
     ps=Ps.flatten()
     
     k0=numpy.sum(rs/ps).tolist()
     
     #Rescale units so their order of magnitude centers around 1
     rscaling=numpy.exp(-(numpy.log(numpy.abs(rs).max())+\
                         numpy.log(numpy.abs(rs).min()))/2.)
     pscaling=numpy.exp(-(numpy.log(numpy.abs(ps).max())+\
                          numpy.log(numpy.abs(ps).min()))/2.)
     root_scaling=1/pscaling
     #rscaling=1
     #pscaling=1
     if self.verbose:
         Logger.write('\tScaling residues by a factor %1.2e to reduce floating point overflow...'%rscaling)
         Logger.write('\tScaling poles by a factor %1.2e to reduce floating point overflow...'%pscaling)
     rs*=rscaling; ps*=pscaling
     k0*=rscaling/pscaling
     signals=signals*rscaling/pscaling
     
     #highest order first in `Ps` and `Qs`
     #VERY SLOW - about 100ms on practical inversions (~60 terms)
     As,Bs=invres(rs, ps, k=[k0], tol=1e-16, rtype='avg') #tol=1e-16 is the smallest allowable to `unique_roots`..
     
     dtype=numpy.complex128 #Double precision offers noticeable protection against overflow
     As=numpy.array(As,dtype=dtype)
     Bs=numpy.array(Bs,dtype=dtype)
     signals=signals.astype(dtype)
     
     #import time
     
     betas=[]
     for i,signal in enumerate(signals):
         #t1=time.time()
         
         #Root finding `roots` seems to give noisy results when `Bs` has degree >84, with dynamic range ~1e+/-30 in coefficients...
         #Pretty fast - 5-9 ms on practical inversions with rank ~60 companion matrices, <1 ms with ~36 terms
         #@TODO: Root finding chokes on `Nterms=9` (number of eigenfields) and `Nts=12` (number of nodes),
         #       necessary for truly converged S3 on resonant phonons, probably due to
         #       floating point overflow - leading term increases exponentially with
         #       number of terms, leading to huge dynamic range.
         #       Perhaps limited by the double precision of DGEEV.
         #       So, replace with faster / more reliable root finder?
         #       We need 1) speed, 2) ALL roots (or at least the first ~10 smallest)
         poly=As-signal*Bs
         roots=find_roots(poly,scaling=scaling)
         roots=roots[roots.imag>0]
         roots*=root_scaling #since all beta units scaled by `pscaling`, undo that here
         
         #print time.time()-t1
         
         #How should we select the most likely beta among the multiple solutions?
         #1. Avoids large changes in value of beta
         if select_by=='difference' and i>=1:
             if i==1 and self.verbose:
                 Logger.write('\tSelecting remaining roots by minimizing differences with prior...')
             to_minimize=numpy.abs(roots-betas[i-1])
             
         #2. Avoids large changes in slope of beta (best for spectroscopy)
         #Nearly guarantees good beta spectrum, with exception of very loosely sampled SiC spectrum
         #Loosely samples SiO2-magnitude phonons still perfectly fine
         elif select_by=='continuity' and i>=2:
             if i==2 and self.verbose:
                 Logger.write('\tSelecting remaining roots by ensuring continuity with prior...')
             earlier_diff=betas[i-1]-betas[i-2]
             current_diffs=roots-betas[i-1]
             to_minimize=numpy.abs(current_diffs-earlier_diff)
             
         #3. Select specifically which pole we want |beta| to be closest to
         else:
             if i==0 and self.verbose:
                 Logger.write('\tSeeding inversion closest to pole %i...'%closest_pole)
             reordering=numpy.argsort(numpy.abs(roots)) #Order the roots towards increasing beta
             roots=roots[reordering]
             to_minimize=numpy.abs(closest_pole-numpy.arange(len(roots)))
             
         beta=roots[to_minimize==to_minimize.min()].squeeze()
         betas.append(beta)
         if not i%5 and self.verbose:
             Logger.write('\tProgress: %1.2f%%  -  Inverted %i signals of %i.'%\
                                  (((i+1)/numpy.float(len(signals))*100),\
                                   (i+1),len(signals)))
     
     betas=AWA(betas); betas.adopt_axes(signals)
     betas=betas.squeeze()
     if not betas.ndim: betas=betas.tolist()
     
     return betas
コード例 #7
0
 def __init__(self,zs=numpy.logspace(-3,2,400),Nterms_max=20,sort=True,
             *args,**kwargs):
     """For some reason using Nqs>=244, getting higher q-resolution,
     only makes more terms relevant, requiring twice as many terms for
     stability and smoothness in approach curves...
     (although overall """
     
     self.zs=zs
     self.Nterms_max=Nterms_max
     
     #Take a look at current probe geometry
     #Adjust quadrature parameters that assist in yielding smooth residues/poles
     #Pre-determined as good values for Nterms=10
     geometry=tip.LRM.geometric_params['geometry']
     if self.verbose:
         Logger.write('Setting up eigenfield tip model for geometry "%s"...'\
                      %geometry)
     if geometry is 'cone': tip.LRM.quadrature_params['b']=.5
     elif geometry is 'hyperboloid': tip.LRM.quadrature_params['b']=.5
     
     global Rs,Ps
     Rs=[]
     Ps=[]
     for i,z in enumerate(zs):
         
         if i==0: kwargs['reload_signal']=True
         elif i==1: kwargs['reload_signal']=False
         
         d=get_tip_eigenbasis_expansion(z,a=1,*args,**kwargs)
         
         Rrow=d['Rs']
         Prow=d['Ps']
         Rrow[numpy.isnan(Rrow)]=Rrow[numpy.isfinite(Rrow)][-1]
         Prow[numpy.isnan(Prow)]=Prow[numpy.isfinite(Prow)][-1]
         
         Rrow=Rrow[Prow.real>0]
         Prow=Prow[Prow.real>0]
         
         where_unphys_Ps=(Prow.imag>0)
         Prow[where_unphys_Ps]-=1j*Prow[where_unphys_Ps].imag
         
         Prow=Prow[:50]
         Rrow=Rrow[:50]
         
         if i>1 and sort:
             #Ensure continuity with previous poles (could have done residues instead, but this works)
             sorting=numpy.array([numpy.argmin(
                                         numpy.abs((Prow-previous_P)-\
                                                   (previous_P-preprevious_P)))
                                  for previous_P,preprevious_P in zip(previous_Prow,preprevious_Prow)])
             Prow=Prow[sorting]
             Rrow=Rrow[sorting]
         
         Rs.append(Rrow[:Nterms_max])
         Ps.append(Prow[:Nterms_max])
         
         #Make sure to keep a reference to previous set of poles and residues
         if sort:
             previous_Prow=Prow
             previous_Rrow=Rrow
             if i>=1:
                 preprevious_Prow=previous_Prow
                 preprevious_Rrow=previous_Rrow
     
     terms=numpy.arange(Nterms_max)+1
     self.Rs=AWA(Rs,axes=[zs,terms],axis_names=['z/a','Term'])
     self.Ps=AWA(Ps,axes=[zs,terms],axis_names=['z/a','Term'])
     
     ##Remove `nan`s from poles and residues##
     #Best way to remove `nan`s (=huge values) is to replace with largest finite value
     #Largest such value in Rs will be found in ratio to that in Ps, implying that
     #beta in denominator of that term is irrelevant, so term+offset goes to zero anyway..
     
     for j in range(Nterms_max):
         
         Rrow=self.Rs[:,j]; Prow=self.Ps[:,j]
         Rrow[numpy.isnan(Rrow)]=Rrow[numpy.isfinite(Rrow)][-1] #Highest value will be for largest z (end of array)
         Prow[numpy.isnan(Prow)]=Prow[numpy.isfinite(Prow)][-1]
     
     ##Remove any positive imaginary part from poles##
     #These are unphysical and are perhaps a by-product of inaccurate eigenvalues
     #when diagonalizing an almost-singular matrix (i.e. g*Lambda)
     #Just put them on the real line, at least it doesn't seem to hurt anything, at most it's more physical.
     where_unphys_Ps=(self.Ps.imag>0)
     self.Ps[where_unphys_Ps]-=1j*self.Ps[where_unphys_Ps].imag
     
     if self.verbose: Logger.write('\tDone.')
コード例 #8
0
def CompareCarbonylTips(Ls=numpy.linspace(30,20e3,100),a=30,\
                                  wavelength=6e3,amplitude=60,lift=30,\
                                  geometries=['cone','hyperboloid'],\
                                  taper_angles=[20],\
                                  load=True,save=True,demo_file='CarbonylTips.pickle',\
                                  enhancement_index=2):

    carbonyl_freqs = numpy.linspace(1730, 1750, 10)
    normalize_at_freq = numpy.mean(carbonyl_freqs)
    freqs = [a / numpy.float(wavelength)
             ]  #load frequency should be quite close to `sio2_freq`
    Ls = Ls / float(a)
    freq_labels = ['ED']
    skin_depth = .05

    ##################################################
    ## Load or compute Carbonyl measurement metrics ##
    ##################################################
    global d
    d_keys=['max_s3','max_s2',\
            'max_rel_absorption','max_absorption','max_freq',\
            'charges0','charges_q0','Lambda0','enhancement',\
            'signals','norm_signals','DCSD_contact','DCSD_lift',\
            'psf_contact','psf_lift']

    demo_path = os.path.join(root_dir, demo_file)
    if load and os.path.isfile(demo_path):
        Logger.write('Loading lengths data...')
        d = pickle.load(open(demo_path))

    else:
        tip.LRM.load_params['reload_model'] = True
        tip.LRM.geometric_params['skin_depth'] = skin_depth

        d = {}

        for i, geometry in enumerate(geometries):
            for n, taper_angle in enumerate(taper_angles):

                #If geometry is not conical, do not iterate to additional taper angles, these are all the same.
                if geometry not in ['PtSi', 'hyperboloid', 'cone'] and n > 0:
                    break

                tip.LRM.geometric_params['geometry'] = geometry
                tip.LRM.geometric_params['taper_angle'] = taper_angle
                signals_for_geometry = {}

                for j, freq in enumerate(freqs):
                    signals_for_freq = dict([(key, []) for key in d_keys])

                    for k, L in enumerate(Ls):
                        tip.LRM.geometric_params['L'] = int(L)
                        Logger.write(
                            'Currently working on geometry "%s", freq=%s, L/a=%s...'
                            % (geometry, freq, L))

                        #Make sure to calculate on zs all the way up to zmax=2*amplitude+lift
                        carbonyl_vals=tip.LRM(carbonyl_freqs,rp=Carbonyl.reflection_p,Nqs=72,zmin=.1,a=a,amplitude=amplitude+lift/2.,\
                                              normalize_to=mat.Si.reflection_p,normalize_at=normalize_at_freq,load_freq=freq,Nzs=30)

                        ##Get overall signal with approach curve##
                        global carbonyl_sigs
                        carbonyl_sigs = carbonyl_vals['signals'] * numpy.exp(
                            -1j * numpy.angle(
                                carbonyl_vals['norm_signals'].cslice[0]))
                        carbonyl_rel_sigs = carbonyl_vals[
                            'signals'] / carbonyl_vals['norm_signals'].cslice[0]
                        ind = numpy.argmax(carbonyl_rel_sigs.imag.cslice[0]
                                           )  #Find maximum phase in contact

                        signals_for_freq['max_s3'].append(
                            carbonyl_vals['signal_3']
                            [ind])  #Pick out the peak frequency
                        signals_for_freq['max_s2'].append(
                            carbonyl_vals['signal_2']
                            [ind])  #Pick out the peak frequency
                        signals_for_freq['max_rel_absorption'].append(
                            carbonyl_rel_sigs[:, ind].imag.cslice[0]
                        )  #Relative to out-of-contact on reference
                        signals_for_freq['max_absorption'].append(
                            carbonyl_sigs[:, ind].imag.cslice[0]
                        )  #Absolute signal
                        signals_for_freq['max_freq'].append(
                            carbonyl_freqs[ind])
                        signals_for_freq['charges0'].append(
                            tip.LRM.charges0 /
                            (2 * numpy.pi * tip.LRM.charge_radii))
                        signals_for_freq['charges_q0'].append(
                            tip.LRM.charges.cslice[0] /
                            (2 * numpy.pi * tip.LRM.charge_radii))
                        signals_for_freq['Lambda0'].append(tip.LRM.Lambda0)
                        signals_for_freq['enhancement'].append(
                            numpy.abs(2 * tip.LRM.charges0[enhancement_index]))
                        signals_for_freq['signals'].append(
                            carbonyl_sigs[:,
                                          ind])  #Pick out the peak frequency
                        signals_for_freq['norm_signals'].append(
                            carbonyl_vals['norm_signals'])
                        signals_for_freq['DCSD_contact'].append(
                            get_DCSD(carbonyl_sigs[:, ind],
                                     zmin=0.1,
                                     amplitude=60,
                                     lift=0))
                        signals_for_freq['DCSD_lift'].append(
                            get_DCSD(carbonyl_sigs[:, ind],
                                     zmin=0.1,
                                     amplitude=60,
                                     lift=lift))

                        ##Isolate some point-spread functions##
                        rs = numpy.linspace(0, 5, 200).reshape((200, 1))
                        integrand_contact=AWA(tip.LRM.qxs**2*\
                                              special.j0(tip.LRM.qxs*rs)*tip.LRM.get_dipole_moments(tip.LRM.qxs)*\
                                              tip.LRM.wqxs,axes=[rs.squeeze(),tip.LRM.qxs])
                        integrand_contact=integrand_contact.interpolate_axis(numpy.logspace(numpy.log(tip.LRM.qxs.min())/numpy.log(10),\
                                                                                            numpy.log(tip.LRM.qxs.max())/numpy.log(10),1000),\
                                                                       axis=1)
                        psf_contact = numpy.sum(integrand_contact, axis=1)
                        signals_for_freq['psf_contact'].append(
                            AWA(psf_contact,
                                axes=[rs.squeeze()],
                                axis_names=['r/a']))

                        integrand_lift=AWA(tip.LRM.qxs**2*numpy.exp(-tip.LRM.qxs*lift/numpy.float(a))*\
                                           special.j0(tip.LRM.qxs*rs)*tip.LRM.get_dipole_moments(tip.LRM.qxs)*\
                                           tip.LRM.wqxs,axes=[rs.squeeze(),tip.LRM.qxs])
                        integrand_lift=integrand_lift.interpolate_axis(numpy.logspace(numpy.log(tip.LRM.qxs.min())/numpy.log(10),\
                                                                                      numpy.log(tip.LRM.qxs.max())/numpy.log(10),1000),\
                                                                       axis=1)
                        psf_lift = numpy.sum(integrand_lift, axis=1)
                        signals_for_freq['psf_lift'].append(
                            AWA(psf_lift,
                                axes=[rs.squeeze()],
                                axis_names=['r/a']))

                        progress = (i * len(Ls) * len(freqs) + j * len(Ls) +
                                    k + 1) / numpy.float(
                                        len(Ls) * len(freqs) *
                                        len(geometries)) * 100
                        Logger.write('\tProgress: %1.1f%%' % progress)

                    for key in list(signals_for_freq.keys()):
                        if numpy.array(
                                signals_for_freq[key]
                        ).ndim == 2:  #Prepend probe length axis and expand these into AWA's
                            axes = [
                                a * Ls / numpy.float(wavelength),
                                signals_for_freq[key][0].axes[0]
                            ]
                            axis_names = [
                                '$L/\lambda_\mathrm{C=O}$',
                                signals_for_freq[key][0].axis_names[0]
                            ]
                            signals_for_freq[key]=AWA(numpy.array(signals_for_freq[key],dtype=numpy.complex),\
                                                          axes=axes,axis_names=axis_names)
                        else:
                            signals_for_freq[key]=AWA(numpy.array(signals_for_freq[key],dtype=numpy.complex),\
                                                          axes=[a*Ls/numpy.float(wavelength)],\
                                                          axis_names=['$L/\lambda_\mathrm{C=O}$'])

                    signals_for_geometry[freq_labels[j]] = signals_for_freq

                geometry_name = geometry
                if geometry in ['PtSi', 'hyperboloid', 'cone']:
                    geometry_name += str(taper_angle)

                d[geometry_name] = signals_for_geometry

    if not load and save:
        Logger.write('Saving tip comparison data...')
        file = open(demo_path, 'wb')
        pickle.dump(d, file)
        file.close()

    return d