用python进行Step函数分析

用python进行Step函数分析,python,matplotlib,graph,Python,Matplotlib,Graph,关于这个问题,我一直在思考一些想法,但我想我会咨询在线社区,看看是否有人有更好的选择 所以我有像这样的阶梯函数图: 用这个,我想计算台阶之间的y位移 正如我们所看到的,这些台阶并不是完全水平的,而是在上升之前取一个小范围的y值 因此,问题是: (1) 取每个“级别”的平均y值的“正确”方法是什么(如果有)?我不确定我应该在哪里使用作为每个级别上的最左侧点和最右侧点-因此我可以取这些点之间的值并将其平均,然后获得每个级别的“平均值”,希望这有意义。正如人们所看到的,它们在x轴上的位移并不都相

关于这个问题,我一直在思考一些想法,但我想我会咨询在线社区,看看是否有人有更好的选择

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

用这个,我想计算台阶之间的y位移

正如我们所看到的,这些台阶并不是完全水平的,而是在上升之前取一个小范围的y值

因此,问题是:

(1) 取每个“级别”的平均y值的“正确”方法是什么(如果有)?我不确定我应该在哪里使用作为每个级别上的最左侧点和最右侧点-因此我可以取这些点之间的值并将其平均,然后获得每个级别的“平均值”,希望这有意义。正如人们所看到的,它们在x轴上的位移并不都相同。最终的目标是得到水平之间的y位移,一旦我有了每个“水平”的“平均”值,就不需要计算差了

我可能在考虑取曲线的导数,看看每一层的最左边和最右边的点在哪里等于零,但我不确定它是否有效,因为每一层也包含(dy/dx=0)的点,所以我可以使用一些细节

谢谢:)哦,这必须在Python中完成——不仅仅是这些图形,还有许多具有类似样式的图形,因此代码必须足够通用,以处理其他类似step的图形

图1的日期文件:

图2的数据文件:

图3的数据文件:

散点图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()

假设您的数据是晶体表面的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])  

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

第三个曲线图显示了相同的数据,如果旋转这些曲线,使所有坡度都是水平的

如何完成(交互式滑块)显示在第四个图中,这是旋转数据的柱状图。您只需移动滑块(旋转数据),直到直方图具有最大清晰度(所有最大值都具有最小宽度)。 我不是用一个函数而是用一个简单的
autofocus
例程手动(滑块)完成的,最大化相邻值之间的绝对差值之和是可以使用的

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

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


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

这里的第二步是直方图的自动调平。我定义了一个函数
focus
,它告诉我直方图是怎样的
sharp
,然后我使用该函数来找到给出最清晰直方图的角度。然后我选择这个角度,对直方图设置阈值,并找到每个直方图峰值的重心。这些位置之间的区别在于步骤。如果这些数字是以米为单位的,那么台阶大约是4埃

事实证明,同样的想法也可以用于二维原子力显微镜(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)
来自未来进口部的

从ipywidgets导入*
将numpy作为np导入
将matplotlib.pyplot导入为p
%matplotlib内联
def旋转数据(x,y,a):
cosa=np.cos(a)
sina=np.sin(a)
x=x*cosa-y*sina
y=x*sina+y*cosa
返回x,y
data=np.loadtxt('plot3.txt')
data=data.T
x、 y=数据[0],数据[1]
def旋转检查(a2):
x2,y2=旋转数据(x,y,a2)
VAL,边缘=np.直方图(y2,箱=230)
焦点=np.sqrt(np.sum((np.diff(VAL))**2))
返回焦点
焦点=[]
amin,amax,astep=-0.01,0.01,0.0001
对于np.arange中的i(amin、amax、astep):
focus.append(rotateAndCheck(i))
fig=p.figure(num=None,figsize=(18,16),dpi=80,facecolor='w',edgecolor='k')
p、 小批(311)
p、 绘图(焦点“.-”)
nm=np.argmax(焦点)
角度=amin+astep*nm
p、 小批(312)
x2,y2=旋转数据(x,y,角度)
VAL,边,u=p.hist(y2,箱子=230)
#现在门槛
p、 小批(313)
VAL[VAL0:
istart=i
#打印“istart:”,istart
如果VAL[i]>0且VAL[i+1]==0:
istop=i
#打印'istop',istop
sum=np.sum(VAL[istart:istop+1])
c=质量中心(VAL[istart:istop+1])[0]
标高=边[istart]+c*三角形
levels.append(level)
#打印i,求和
打印“级别:”,级别
打印
打印“步骤:”,np.diff(级别)
输出:

@roadrunner66倾斜与否有关系吗?水平之间的差异将是相同的y位移?我相信你的解决方案应该是你试图理解的物理现实的模型。例如,你想先旋转图形以与x和y对齐,还是当前坐标系是你需要的?如果步骤是非常周期性的,FFT可能是测试周期性的一种方法。导数允许您通过设置偏移量来消除倾斜,这样大多数点都会像您提到的那样平均为零。否。如果您将图形倾斜为近似水平,则在
y轴
中不会有
步骤
。因此需要定义步骤,我想你的意思是,图形倾斜的方式类似于楼梯,如第二个图形。是的,我明白你的意思。在这种情况下,是的,我现在使用的坐标系非常重要。这些“倾斜”图形在台阶之间的y位移就是我想要的。我