我正在做一个项目,让用户随着时间的推移跟踪不同的数据类型。基本思想的一部分是用户应该能够使用他们需要的任何单位输入数据。我一直在看两个单位:
http://pypi.python.org/pypi/units/
和数量:
http://pypi.python.org/pypi/quantities/
但是我不确定最好的方法。据我所知,数量更复杂,但包含更好的初始单位列表。
我正在做一个项目,让用户随着时间的推移跟踪不同的数据类型。基本思想的一部分是用户应该能够使用他们需要的任何单位输入数据。我一直在看两个单位:
http://pypi.python.org/pypi/units/
和数量:
http://pypi.python.org/pypi/quantities/
但是我不确定最好的方法。据我所知,数量更复杂,但包含更好的初始单位列表。
我赞赏在科学计算应用程序中使用显式单位。使用明确的单位类似于刷牙。它预先增加了一些乏味,但从长远来看,您获得的类型安全可以节省很多麻烦。比如说,不是将价值 1.25 亿美元的轨道飞行器撞向行星。
您还应该查看这两个其他 python 单位/数量包:
我曾经调查过 Scientific.Physics.PhysicalQuantity。它不能完全满足我的需求,但可能会满足你的需求。从简短的描述中很难说出您需要哪些功能。
我最终编写了我自己的用于单位转换和维度分析的 python 包,但它还没有正确打包以供发布。我们在 Python 绑定中使用我的单位系统,用于我们的 OpenMM 系统,用于 GPU 加速分子力学。您可以在以下位置浏览我的 python 单元代码的 svn 存储库:
最终,我打算将其打包以进行分发。如果你觉得有趣,请告诉我。这可能会促使我尽快将其打包。我在设计 SimTK python 单位系统时一直在寻找的功能包括以下内容:
哪些功能对您很重要?
请注意,quantities
它对温度的支持非常糟糕:
>>> (100 * pq.degC).rescale(pq.degF)
array(179.99999999999997) * degF
>>> (0 * pq.degC).rescale(pq.degF)
array(0.0) * degF
0摄氏度不是0华氏度。他们的框架不支持任何类型的转换,而不仅仅是乘以一个因子。
我很惊讶没有人提到 SymPy。SymPy是一个成熟且维护良好的 Python 符号数学库,也是NumFOCUS 赞助的项目。
它有一个物理模块,其中包含许多有用的类和函数,用于“解决物理问题”。与您最相关的是,我认为它有一个Unit子模块,其中包含您需要的一切;只需阅读优秀的文档。
看起来另一个包也可以做到这一点,由 web2py 成名的 Massimo DiPierro 编写,称为Buckingham。
另外值得注意的是,布赖恩有这样的事情已经有一段时间了。
我想指出一个用于处理单位的单独库:Barril
https://github.com/ESSS/barril
文档位于:https ://barril.readthedocs.io/en/latest/
虽然它确实支持从计算中创建“随机”单位(例如 Pint、unum 等),但它更适合拥有一个单位数据库(该库默认具有该数据库 - 请参阅:https://barril.readthedocs .io/en/latest/units.html和实现:https://github.com/ESSS/barril/blob/master/src/barril/units/posc.py)然后您可以根据相关单位。
它支持的在这方面有很大不同的一件事是处理“无量纲”的单位转换 - 例如 m3/m3 (即:)volume per volume
,然后转换为cm3/m3
并保持维度。
即:品脱:
>>> import pint
>>> ureg = pint.UnitRegistry()
>>> m = ureg.meter
>>> v = 1 \* (m\*3)/(m\*3)
>>> v
<Quantity(1.0, 'dimensionless')>
然后,在那之后(据我所知),如果知道它是 m3/m3,就不可能正确地进行额外的单位转换。
在巴里尔:
>>> from barril.units import Scalar
>>> a = Scalar(3, 'm3/m3')
>>> a.GetValue('cm3/m3')
3000000.0
>>> a.category
'volume per volume'
>>> a.unit
'm3/m3'
并且a.GetValue('m3')
(具有无效值)的东西会给出一个错误,说明转换实际上是无效的。
单位数据库(最初基于 POSC 计量单位字典)更适合石油和天然气领域,但也应该可以在它之外使用。
我认为你应该使用数量,因为数量有一些与之相关的单位。
例如,压力是一个可以输入并转换为不同单位(Pa、psi、atm 等)的量。可能您可以为您的应用程序创建新的数量细节。
我发现单位包比想要的要多。不需要太多代码就可以开始构建自己的函数,这些函数引用了极少数的基本数字。此外,它会强制您进行尺寸分析以防止错误。
def FtoC(Tf):
return (Tf-32)*5/9
def CtoF(Tc):
return 9*Tc/5+32
def CtoK(Tc):
return Tc+273.15
def INCHtoCM(Inch):
return 2.54 * Inch
def CMtoINCH(cm):
return cm / INCHtoCM(1)
def INCHtoMETER(inch):
return .01*INCHtoCM(inch)
def FOOTtoMETER(foot):
return INCHtoMETER(12*foot)
def METERtoINCH(Meter):
return CMtoINCH(100 * Meter)
def METERtoFOOT(Meter):
return METERtoINCH(Meter)/12
def M3toINCH3(M3):
return (METERtoINCH(M3))**3
def INCH3toGALLON(Inch3):
return Inch3 / 231
def M3toGALLON(M3):
return INCH3toGALLON(M3toINCH3(M3))
def KG_M3toLB_GALLON(KGperM3):
return KGtoLBM(KGperM3) / M3toGALLON(1)
def BARtoPASCAL(bar):
return 100000 * bar
def KGtoLBM(kilogram):
return kilogram * 2.20462262185
def LBMtoKG(lbm):
return lbm/KGtoLBM(1)
def NEWTONtoLBF(newton):
return newton * KGtoLBM(1) * METERtoFOOT(1) / STANDARD_GRAVITY_IMPERIAL()
def LBFtoNEWTON(lbf):
return lbf * STANDARD_GRAVITY_IMPERIAL() * LBMtoKG(1) * FOOTtoMETER(1)
def STANDARD_GRAVITY_IMPERIAL():
return 32.174049
def STANDARD_GRAVITY_SI():
return 9.80665
def PASCALtoPSI(pascal):
return pascal * NEWTONtoLBF(1) / METERtoINCH(1)**2
def PSItoPASCAL(psi):
return psi * LBFtoNEWTON(1) / INCHtoMETER(1)**2
然后假设您想绘制 1,3 丁二烯 @44 F 的静压头并使用 PSI 中的仪表,因为您住在美国,但密度表应该是 SI 单位...... ......
# butadiene temperature in Fahrenheit
Tf = 44
# DIPPR105 Equation Parameters (Density in kg/m3, T in K)
# valid in temperature 165 to 424 Kelvin
A=66.9883
B=0.272506
C=425.17
D=0.288139
# array of pressures in psi
Pscale = np.arange(0,5,.1, dtype=float)
Tk = CtoK(FtoC(44))
Density = A / (B**(1+(1-Tk/C)**D)) # KG/M3
Height = [PSItoPASCAL(P) / (Density * STANDARD_GRAVITY_SI()) for P in Pscale]
Height_inch = METERtoINCH(1) * np.array(Height, dtype=np.single)