Python 物理实验数据处理类

4

Comments

非常无语的,同济大一什么物理理论都没学,需要的高数基础也都没有学过,竟然要我们先学物理实验,而且要处理数据,计算平均值和标准误差什么的,十分麻烦……

上次处理数据弄了个零碎的小程序来,很麻烦,这次就把他统一编为一个模块,方便以后使用……这个模块里面的说有公式依据是同济大学出版社《物理实验教程》第1版第二章的内容。

如何使用这个模块呢?首先,作为一个 Python 模块,肯定要用 Python……

然后我用我第一次做实验的部分数据演示一下:
Screenshot-upsuper@upsuper-netbook: ~-external-tju

直接输入数据,标准格式输出~

最后是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import math
sqrt = math.sqrt
 
def gen_imet(func):
  def retfunc(self, other):
    ret = func(self, other)
    self.ave = ret.ave
    self.u = ret.u
    self.digs = ret.digs
    return self
  return retfunc
 
def get_digs(a, b):
  if a == 0: return b
  elif b == 0: return a
  else: return min(a, b)
 
class PhyStat:
  """
  物理实验数据
 
  PhyStat(ave, u = 0.0, digs = 0)
  ave   表示平均值,如果传入一列数则自动计算平均值及其标准误差
  u     表示标准误差,如果 ave 传入数据列表则此处表示仪器精度
  digs  表示有效数字个数,0 表示不限制
  """
 
  def __init__(self, ave, u = 0.0, digs = 0):
    """
    对于 ave 为数据列表的情况,使用下面公式计算平均值:
    ave = Σx[i] / n
    根据下面公式计算标准误差:
    S = Sqrt(Σ(x[i]-ave)^2 / (n - 1))
    u = Δinst / Sqrt(3)
    U = Sqrt(S^2 + u^2)
    """
    self.digs = digs
 
    if isinstance(ave, tuple) or isinstance(ave, list):
      data = ave
      n = len(data)
      ave = math.fsum(ave) / n
      self.ave = ave
 
      s = 0.0
      for i in data:
        s += (i - ave) ** 2
      s = sqrt(s / (n - 1))
      u /= sqrt(3)
      self.u = sqrt(s ** 2 + u ** 2)
    else:
      self.ave = float(ave)
      self.u = abs(float(u))
 
  def __repr__(self):
    ave = self.ave
    exp = int(math.floor(math.log10(ave)))
    exp10 = 10 ** exp
    ave = ave / exp10
    u = self.u / exp10
    digs = self.digs
    if digs == 0:
      ret = '%f ±%f'
    else:
      ret = '%%.%df ±%%.%df' % (digs, digs)
    if exp:
      ret = '(%s) E %d' % (ret, exp)
    return ret % (ave, u)
 
  __neg__ = lambda self: PhyStat(-self.ave, self.u, self.digs)
  __pos__ = lambda self: self
  __abs__ = lambda self: PhyStat(abs(self.ave), self.u, self.digs)
 
  def __add__(self, other):
    if isinstance(other, PhyStat):
      ave = self.ave + other.ave
      u = sqrt(self.u ** 2 + other.u ** 2)
      digs = get_digs(self.digs, other.digs)
      return PhyStat(ave, u, digs)
    else:
      ave = self.ave + other
      return PhyStat(ave, self.u, self.digs)
 
  __radd__ = __add__
  __sub__ = lambda self, other: self + (-other)
  __rsub__ = lambda self, other: other + (-self)
 
  def __mul__(self, other):
    if isinstance(other, PhyStat):
      a = self.ave
      b = other.ave
      ave = a * b
      u = ave * sqrt((self.u / a) ** 2 + (other.u / b) ** 2)
      digs = get_digs(self.digs, other.digs)
      return PhyStat(ave, u, digs)
    else:
      ave = self.ave * other
      u = self.u * other
      return PhyStat(ave, u, self.digs)
 
  __rmul__ = __mul__
 
  def __div__(self, other):
    if isinstance(other, PhyStat):
      return self * other ** -1
    else:
      return (1.0 / other) * self
 
  __rdiv__ = lambda self, other: other * self ** -1
 
  def __pow__(self, other):
    a = self.ave
    ave = a ** other
    u = abs(other * self.u / a * ave)
    return PhyStat(ave, u, self.digs)
 
  __iadd__ = gen_imet(lambda self, other: self + other)
  __isub__ = gen_imet(lambda self, other: self - other)
  __imul__ = gen_imet(lambda self, other: self * other)
  __idiv__ = gen_imet(lambda self, other: self / other)
  __ipow__ = gen_imet(lambda self, other: self ** other)
 
  __int__ = lambda self: int(self.ave)
  __long__ = lambda self: long(self.ave)
  __float__ = lambda self: self.ave

如果大家发现什么 bug,或者有什么改进建议,欢迎提哈~

4 Responses to “Python 物理实验数据处理类”

  1. ivan Says:
    2009年10月29日 08:39 回复

    可否加一个链接?

  2. hftree Says:
    2010年2月9日 09:53 回复

    建议:
    1)外部数据文件输入,如netcdf hdf格式支持
    2)可以用blade 做界面
    3)matplotlib 等图像输出

    • upsuper Says:
      2010年2月9日 20:37 回复

      您好,感谢您的建议,但我不准备对这一程序做进一步完善。如果您对此有兴趣,可以在此程序发布协议(GPLv3)的约定下自行修改和完善该程序~

Leave a Reply