使用python进行步骤函数分析

时间:2016-03-30 23:29:52

标签: python matplotlib graph

我一直在围绕这个问题提出一些想法,但我想我会咨询在线社区,看看有没有更好的选择。

所以我有这样的阶梯式函数图:

step-1 graph

step-2 graph

step-3 graph

有了这个,我想计算步骤之间的y位移。

正如人们可以看到步骤不是完全水平的,而是在加紧之前取小范围的y值。

所以问题是:

(1)采用每个'水平'的平均y值的'正确'方式(如果有的话)是什么?我不确定我应该使用哪个位置作为我最左边的点和最右边的点 - 所以我可以取这些点之间的值并平均它们,然后达到每个级别的“平均值”,希望这样做感。正如人们可以看到的那样,它们并不都是x中的相同位移。最终目标是在各级之间获得y位移,一旦我得到每个“级别”的“平均”值,就可以获得差异。

我可能正在考虑获取曲线的导数,并在每个级别上看到我的左右点最多等于零的位置,但我不确定它是否会起作用,因为每个级别也包含点(dy) / dx = 0) - 所以我可以使用一些见解。

谢谢:)哦 - 这必须在Python中完成 - 它不仅仅是这些图形,而且它们中的很多都具有相似的样式,因此代码必须足够通用以处理其他类似步骤的图形。

图1的日期文件:http://textuploader.com/5nwsh

图2的数据文件:http://textuploader.com/5nwsv

图3的数据文件:http://textuploader.com/5nwsj

Scatter Plot Python代码:

import numpy as np
import matplotlib.pyplot as plt
import pylab as pl


data=np.loadtxt('data-file')
x= data[:,0]
y=data[:,1]


pl.plot(data[:,0],data[:,1],'r')

pl.xlabel('x')
pl.ylabel('y')
plt.show()

2 个答案:

答案 0 :(得分:2)

假设您的数据是水晶表面的AFM测量值(以m为单位的所有单位),并且您希望得到晶体的台阶高度。以下内容将帮助您实现这一目标。

from __future__ import division
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as p
%matplotlib inline

def rotatedata(x,y,a):
    cosa=np.cos(a)
    sina=np.sin(a)
    x = x*cosa-y*sina
    y = x*sina+y*cosa
    return x,y

data=np.loadtxt('plot3.txt')
data=data.T
x,y=data[0],data[1]

def workit(a2):
    fig=p.figure(num=None, figsize=(18, 16), dpi= 80, facecolor='w', edgecolor='k')
    p.subplot(511) # , aspect='equal')
    p.plot(x,y)

    #what is the slope? 
    m,b = np.polyfit(x, y, 1)

    x1,y1=rotatedata(x,y, -np.arctan(m) )  # rotate data to have flat surface, 
                                           # interesting for surface roughness
    p.subplot(512 )
    p.plot(x1,y1)

    x2,y2=rotatedata(x,y, a2)    # rotate data to 'sharpen' histogram
    p.subplot(513 )
    p.plot(x2,y2)

    p.subplot(514)
    p.hist(y2,bins=130)        

    y3=np.diff(y2)
    p.subplot(515 )
    p.plot(y3)

    return HTML()

interact(workit,a2=[-0.002,0.002,0.00001])  

enter image description here

第一个图是您的原始数据。在第二个图中,我删除了数据的斜率,以显示如果您关心计算表面粗糙度将使用的数据。

如果第三个图旋转使得所有斜率都是水平的,则第三个图显示相同的数据。

如何完成此操作(交互式滑块)显示在第4个图中,该图是旋转数据的直方图。您可以简单地移动滑块(旋转数据),直到直方图具有最大锐度(所有最大值都是最小宽度)。 我手动(滑块)没有使用函数而是简单的autofocus例程,最大化相邻值之间的绝对差值之和可以使用。

在最后一个图中,我显示了一阶导数(现在是多余的,但水平区域的平均斜率应该以零为中心作为复核)。

晶体层的宽度(您要求的台阶高度)现在由直方图中的最大值的距离给出。

我将每个步骤的实际确定作为练习(例如,直方图的阈值,然后计算每个峰值的重心,然后获得相邻峰值重心的差异)。

答案 1 :(得分:1)

这里的第二步是自动调平直方图。我定义了一个函数focus,它告诉我直方图是如何sharp然后我使用该函数来找到给出最清晰直方图的角度。然后我选择该角度,对直方图进行阈值并找到每个直方图峰值的重心。这些位置之间的差异是步骤。如果数字以米为单位,则步长约为4埃。

事实证明,相同的想法可以用于2D水平AFM或白光干涉仪数据,并且非常精确地确定不仅是晶体的台阶高度,而且是纳米级涂层或蚀刻深度的台阶高度。

from __future__ import division
from ipywidgets import *
import numpy as np
import matplotlib.pyplot as p
%matplotlib inline

def rotatedata(x,y,a):
    cosa=np.cos(a)
    sina=np.sin(a)
    x = x*cosa-y*sina
    y = x*sina+y*cosa
    return x,y


data=np.loadtxt('plot3.txt')
data=data.T
x,y=data[0],data[1]

def rotateAndCheck(a2):
    x2,y2=rotatedata(x,y, a2) 
    vals,edges=np.histogram(y2,bins=230)
    focus=np.sqrt(np.sum((np.diff(vals))**2))
    return focus

focus=[]
amin,amax,astep=-0.01,0.01,0.0001
for i in np.arange(amin,amax,astep):
    focus.append(rotateAndCheck(i))


fig=p.figure(num=None, figsize=(18, 16), dpi= 80, facecolor='w', edgecolor='k')


p.subplot(311)    

p.plot(focus,'.-')
nm=np.argmax(focus)
angle=amin+astep*nm


p.subplot(312)
x2,y2=rotatedata(x,y, angle) 
vals,edges,_=p.hist(y2,bins=230)


#now threshold
p.subplot(313)
vals[vals<3]=0
#print len(edges),len(vals)
deltaedge=edges[1]-edges[0]
#print deltaedge
#p.bar(edges[:-1],vals,0.05e-10)
p.bar(np.arange(len(vals)),vals,0.05e-10)
p.show()

# now you go through the histogram from left to right, identify each group and compute the center of gravity for each group
# this could get trickier if the bin size is not well chosen.

from scipy.ndimage.measurements import center_of_mass
levels=[]

for i in range(1,len(edges)-2):
    if  vals[i-1]==0 and vals[i]>0:
        istart=i
        #print 'istart: ',istart
    if  vals[i]>0 and vals[i+1]==0:
        istop=i
        #print 'istop', istop
        sum=np.sum(vals[istart:istop+1])
        c= center_of_mass(vals[istart:istop+1])[0] 
        level= edges[istart]+c*deltaedge
        levels.append(level)

        #print i, sum

print 'levels: ',levels        
print
print 'steps: ' ,np.diff(levels)

输出: enter image description here