|
From: <zk...@us...> - 2010-02-21 20:52:06
|
Revision: 668
http://pyphant.svn.sourceforge.net/pyphant/?rev=668&view=rev
Author: zklaus
Date: 2010-02-21 20:51:58 +0000 (Sun, 21 Feb 2010)
Log Message:
-----------
Merge branch 'master' into svn-trunk
* master:
Module SQLiteWrapper adapted to additional base unit bit.
Conflicts resolved, but merged version still has bugs.
Refacturing: Removed intermediate module PhysicalQuantities, such that class Quantity is directly loaded from module quantities.
Refactoring: Renamed Function isPhysicalUnit to isUnit.
Refacturing: Renamed class PhysicalQuantity to Quantity.
Enh.: Added scenario for testing datetime with uncertainty.
Enh: Demo script readfmf.py accepts command 'parse <FMF-value>'.
Refactured: Function item2value takes a simple string as argument and not a pair of dictionary with associated key.
Refactured: Function item2value takes a simple string as argument and not a pair of dictionary with associated key.
Bugfix: File example.fmf does not specify complex numbers with capital J anymore.
Bugfix: Items are correctly discriminated between complex numbers and quantities of unit Joule.
Defined 1Byte=8Bit.
Enh.: Added binary Units bit and B.
Test for converting value 1EUR to 1USD is only run, if up to date exchange rates have been fetched.
Enh: Added binary units.
Bugfix: Monetary values cannot have prefixes with powers lower than 1000.
Enh.: If fields cannot be reshaped, because they consists of strings. A warning is given.
Modified Paths:
--------------
trunk/doc/demo/example.fmf
trunk/doc/demo/readfmf.py
trunk/src/pyphant/pyphant/core/DataContainer.py
trunk/src/pyphant/pyphant/core/FieldContainer.py
trunk/src/pyphant/pyphant/core/H5FileHandler.py
trunk/src/pyphant/pyphant/core/KnowledgeManager.py
trunk/src/pyphant/pyphant/core/PyTablesPersister.py
trunk/src/pyphant/pyphant/core/SQLiteWrapper.py
trunk/src/pyphant/pyphant/quantities/ParseQuantities.py
trunk/src/pyphant/pyphant/quantities/__init__.py
trunk/src/pyphant/pyphant/tests/TestAutoFocus.py
trunk/src/pyphant/pyphant/tests/TestDataContainer.py
trunk/src/pyphant/pyphant/tests/TestH5FileHandler.py
trunk/src/pyphant/pyphant/tests/TestParseQuantities.py
trunk/src/pyphant/pyphant/tests/TestPyTablesPersister.py
trunk/src/pyphant/pyphant/tests/TestSQLiteWrapper.py
trunk/src/pyphant/pyphant/visualizers/Chart.py
trunk/src/pyphant/pyphant/visualizers/External.py
trunk/src/pyphant/pyphant/visualizers/ImageVisualizer.py
trunk/src/workers/ImageProcessing/ImageProcessing/AutoFocus.py
trunk/src/workers/ImageProcessing/ImageProcessing/DistanceMapper.py
trunk/src/workers/ImageProcessing/ImageProcessing/ImageLoaderWorker.py
trunk/src/workers/ImageProcessing/ImageProcessing/NDImageWorker.py
trunk/src/workers/ImageProcessing/ImageProcessing/SlopeCalculator.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestApplyMask.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestDistanceMapper.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestImageLoader.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestMedianiser.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestSkeletonizeFeature.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestSlopeCalculator.py
trunk/src/workers/ImageProcessing/ImageProcessing/tests/TestThresholdingWorker.py
trunk/src/workers/OSC/OSC/CompareFields.py
trunk/src/workers/OSC/OSC/ComputeFunctional.py
trunk/src/workers/OSC/OSC/ErrorEstimator.py
trunk/src/workers/OSC/OSC/EstimateParameter.py
trunk/src/workers/OSC/OSC/ExtremumFinder.py
trunk/src/workers/OSC/OSC/MRA.py
trunk/src/workers/OSC/OSC/OscAbsorption.py
trunk/src/workers/OSC/OSC/OscCurrent.py
trunk/src/workers/OSC/OSC/OscLoader.py
trunk/src/workers/OSC/OSC/OscVisualisers.py
trunk/src/workers/OSC/OSC/Slicing.py
trunk/src/workers/OSC/OSC/Smoother.py
trunk/src/workers/OSC/OSC/ThicknessModeller.py
trunk/src/workers/OSC/OSC/tests/TestExtremumFinder.py
trunk/src/workers/OSC/OSC/tests/TestMRA.py
trunk/src/workers/OSC/OSC/tests/TestOscAbsorption.py
trunk/src/workers/Statistics/Statistics/tests/TestHistogram.py
trunk/src/workers/fmfile/fmfile/FMFLoader.py
trunk/src/workers/fmfile/fmfile/tests/TestFMFLoader.py
trunk/src/workers/tools/tools/ParameterRun.py
trunk/src/workers/tools/tools/tests/TestEmd5Source.py
Added Paths:
-----------
trunk/src/pyphant/pyphant/tests/TestQuantities.py
Removed Paths:
-------------
trunk/src/pyphant/pyphant/quantities/PhysicalQuantities.py
Property Changed:
----------------
trunk/doc/demo/readfmf.py
Modified: trunk/doc/demo/example.fmf
===================================================================
--- trunk/doc/demo/example.fmf 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/doc/demo/example.fmf 2010-02-21 20:51:58 UTC (rev 668)
@@ -28,10 +28,10 @@
float with Exponential: -1.1E10
list of floats: 1.0, .1, 1e-10, -1.1E10
complex: 1+2j
-Complex: 1+2J
-Complex number with zero real part : 2J
-Complex number with zero imaginary part: 1+0J
-list of complex: 1+2j, 1+2J
+Complex: 1.1+2j
+Complex number with zero real part : 2j
+Complex number with zero imaginary part: 1+0j
+list of complex: 1+2j, 1.1+2j
[Boolean values]
true1: True
true2: true
@@ -101,7 +101,7 @@
[*data: T]
H_2 1 1. 1e1 1+0j nan inf
O_2 2 .2 2E1 2+.1j NaN INF
-O 2 2 .2 2E1 2+.1J NAN Inf
+O 2 2 .2 2E1 2.+2j NAN Inf
[*data definitions: M]
String: S
Complex: C
Modified: trunk/doc/demo/readfmf.py
===================================================================
--- trunk/doc/demo/readfmf.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/doc/demo/readfmf.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,15 +1,61 @@
-import sys
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2008, Rectorate of the University of Freiburg
+# Copyright (c) 2009, Andreas W. Liehr (li...@us...)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of the Freiburg Materials Research Center,
+# University of Freiburg nor the names of its contributors may be used to
+# endorse or promote products derived from this software without specific
+# prior written permission.
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
import logging
+from optparse import OptionParser
+
logging.basicConfig(level=logging.WARNING,
format="%(asctime)s - %(levelname)s:%(name)s:%(thread)d:%(module)s.%(funcName)s(l %(lineno)d):%(message)s")
-from fmfile.FMFLoader import FMFLoader
+from fmfile.FMFLoader import FMFLoader,item2value
-worker = FMFLoader()
-if len(sys.argv) == 1:
+parser = OptionParser(usage="""usage: %prog path2FMFfile
+ %prog parse FMFvalue""")
+
+(options, args) = parser.parse_args()
+if len(args) == 0:
filenames = ['example.fmf']
+elif args[0] in ('parse',u'parse'):
+ value = ' '.join(args[1:])
+ result = item2value(value)
+ print "Value \"%s\" is interpreted as %s:" % (value,type(result))
+ print result
+ from sys import exit
+ exit(0)
else:
- filenames = sys.argv[1:]
+ filenames = args
+
+worker = FMFLoader()
for filename in filenames:
worker.paramFilename.value=filename
result = worker.plugLoadFMF.getResult()
Property changes on: trunk/doc/demo/readfmf.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: trunk/src/pyphant/pyphant/core/DataContainer.py
===================================================================
--- trunk/src/pyphant/pyphant/core/DataContainer.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/core/DataContainer.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2006-2008, Rectorate of the University of Freiburg
+# Copyright (c) 2006-2009, Rectorate of the University of Freiburg
+# Copyright (c) 2009, Andreas W. Liehr (li...@us...)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -70,8 +71,8 @@
import copy, hashlib, threading, numpy, StringIO
import os, platform, datetime, socket, urlparse
-from pyphant.quantities.PhysicalQuantities import (isPhysicalQuantity,
- PhysicalQuantity)
+from pyphant.quantities import (isQuantity,
+ Quantity)
import Helpers
import logging
@@ -195,7 +196,7 @@
\t .data \t- Table of samples stored in a numpy.ndarray.
\t .desc \t- Description numpy.dtype of the ndarray.
-\t .units \t- List of PhysicalQuantities objects denoting the units of
+\t .units \t- List of quantities.objects denoting the units of
\t\t\t the columns.
\t .longname \t- Notation of the data, e.g. 'database query',
\t\t\t which is used for the automatic annotation of charts.
@@ -338,12 +339,12 @@
al.append(('SCColumn', column))
else:
try:
- phq = PhysicalQuantity(e)
+ phq = Quantity(e)
al.append(('PhysQuant', phq))
continue
except:
try:
- number = PhysicalQuantity(e+' m')
+ number = Quantity(e+' m')
al.append(('Number', eval(e)))
continue
except: pass
@@ -594,7 +595,7 @@
<atomar> := <value> <CompareOp> <value>
where <value> is either a SC Column accessed as
"longname" or "shortname" (including the double quotes)
- or a number or a string representing a PhysicalQuantity
+ or a number or a string representing a Quantity
(e.g. 300nm). And <CompareOp> can be ==, !=, <, <=, >, >=.
Then a valid expression <expression> is:
- <atomar>
@@ -613,7 +614,7 @@
- or
If expression is a nested tuple, syntax is as follows:
<value> is either ('SCColumn', FieldContainer instance)
- or ('PhysQuant', PhysicalQuantity instance)
+ or ('PhysQuant', Quantity instance)
or ('Number', int float etc.)
<CompareOp> is in ['==', '!=', ...]
A valid nested tuple <nt> can be:
@@ -661,7 +662,7 @@
rightvalue = None
if left[0] == 'SCColumn' and right[0] == 'SCColumn':
number = right[1].unit/left[1].unit
- if isPhysicalQuantity(number):
+ if isQuantity(number):
raise TypeError(
'Cannot compare "' + left[1].longname + '" to "'
+ right[1].longname + '".'
@@ -670,7 +671,7 @@
rightvalue = right[1].data*number
elif left[0] == 'SCColumn':
number = right[1]/left[1].unit
- if isPhysicalQuantity(number):
+ if isQuantity(number):
raise TypeError(
'Cannot compare "' + left[1].longname
+ '" to ' + str(right[1]) + '".'
@@ -679,7 +680,7 @@
rightvalue = number
elif right[0] == 'SCColumn':
number = left[1]/right[1].unit
- if isPhysicalQuantity(number):
+ if isQuantity(number):
raise TypeError(
"Cannot compare " + str(left[1]) + ' to "'
+ right[1].longname + '".'
Modified: trunk/src/pyphant/pyphant/core/FieldContainer.py
===================================================================
--- trunk/src/pyphant/pyphant/core/FieldContainer.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/core/FieldContainer.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
-# Copyright (c) 2006-2008, Rectorate of the University of Freiburg
+# Copyright (c) 2006-2009, Rectorate of the University of Freiburg
+# Copyright (c) 2009, Andreas W. Liehr (li...@us...)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -59,7 +60,7 @@
import scipy, copy, hashlib, threading, numpy, StringIO
import os, platform, datetime, socket, urlparse
-from pyphant.quantities.PhysicalQuantities import (isPhysicalQuantity, PhysicalQuantity,_prefixes)
+from pyphant.quantities import (isQuantity, Quantity,_prefixes)
from DataContainer import DataContainer, enc, _logger
from types import NoneType
@@ -136,14 +137,14 @@
def slice2ind(arg, dim):
if isinstance(arg, type("")):
- sl = [ "0"+a for a in arg.split(':')] #Hack for PhysicalQuantities, which does not recognize .6 as a number.
+ sl = [ "0"+a for a in arg.split(':')] #Hack for quantities. which does not recognize .6 as a number.
unit = dim.unit
try:
- hi = PhysicalQuantity(sl[1])
+ hi = Quantity(sl[1])
try:
- li = PhysicalQuantity(sl[0])
+ li = Quantity(sl[0])
except:
- li = PhysicalQuantity(float(sl[0]),hi.unit)
+ li = Quantity(float(sl[0]),hi.unit)
try:
li, hi = [ i.inUnitsOf(unit.unit).value/unit.value for i in [li,hi] ]
except TypeError:
@@ -182,7 +183,7 @@
\t\t\t shortname=u"\\Psi",rescale=False)
\t Class describing sampled fields:
\t .data\t\t- Numpy.array representing the sampled field.
-\t .unit\t\t- PhysicalQuantity object denoting the unit of the sampled field.
+\t .unit\t\t- Quantity object denoting the unit of the sampled field.
\t .dimensions\t- List of FieldContainer instances
\t\t\t describing the dimensions of the sampled field.
\t .data \t- Sampled field stored as numpy.array, which is rescaled to reasonable basic units if option rescale is chosen.
@@ -210,10 +211,10 @@
unit = unit.replace('^', '**')
if isinstance(unit, unicode):
unit = unit.encode('utf-8')
- self.unit = PhysicalQuantity(unit)
+ self.unit = Quantity(unit)
except:
try:
- self.unit = PhysicalQuantity("1"+unit)
+ self.unit = Quantity("1"+unit)
except:
self.unit = unit
self.error = error
@@ -244,7 +245,7 @@
dependency = ''
label = u"%s $%s%s$ / %s" % (self.longname.title(), self.shortname, dependency, self.unit)
try:
- if not isPhysicalQuantity(self.unit) and self.unit == 1:
+ if not isQuantity(self.unit) and self.unit == 1:
label = u"%s $%s%s$ / a.u." % (self.longname.title(),self.shortname,dependency)
except:
pass #just a ScientificPython bug
@@ -252,7 +253,7 @@
label=property(_getLabel)
def _getShortLabel(self):
- if not isPhysicalQuantity(self.unit) and self.unit == 1:
+ if not isQuantity(self.unit) and self.unit == 1:
if self.longname == 'index':
label = u"%s $%s$" % (self.longname.title(),self.shortname)
else:
@@ -311,11 +312,11 @@
super(FieldContainer, self).seal(id)
def inUnitsOf(self, other):
- if not isPhysicalQuantity(self.unit):
- if isPhysicalQuantity(other.unit):
+ if not isQuantity(self.unit):
+ if isQuantity(other.unit):
raise ValueError("Incompatible Units: self.unit = <%s>, other.unit = <%s>"%(self.unit, other.unit))
factor = float(self.unit)/float(other.unit)
- elif not isPhysicalQuantity(other.unit):
+ elif not isQuantity(other.unit):
raise ValueError("Incompatible Units: self.unit = <%s>, other.unit = <%s>"%(self.unit, other.unit))
else:
if not self.unit.isCompatible(other.unit.unit):
@@ -329,7 +330,7 @@
return newSelf
def rescale(self):
- if isPhysicalQuantity(self.unit):
+ if isQuantity(self.unit):
oldUnit = self.unit.inBaseUnits()
else:
return
@@ -391,7 +392,7 @@
error = self.error
otherData = other.data
otherError = other.error
- if (isPhysicalQuantity(self.unit) or isPhysicalQuantity(other.unit)):
+ if (isQuantity(self.unit) or isQuantity(other.unit)):
try:
if not (self.unit.inBaseUnits().unit == other.unit.inBaseUnits().unit):
_logger.debug('The units are different.')
@@ -470,8 +471,8 @@
for i in xrange(len(self._dimensions)):
if not self._dimensions[i] == other.dimensions[i]:
return NotImplemented
- if isPhysicalQuantity(self.unit):
- if not isPhysicalQuantity(other.unit):
+ if isQuantity(self.unit):
+ if not isQuantity(other.unit):
return NotImplemented
if not self.unit.isCompatible(other.unit.unit):
return NotImplemented
@@ -481,7 +482,7 @@
else:
data = other.data+(self.data*self.unit.value*self.unit.unit.conversionFactorTo(other.unit.unit))/other.unit.value
unit = other.unit
- elif isPhysicalQuantity(other.unit):
+ elif isQuantity(other.unit):
return NotImplemented
else:
data = (self.data*self.unit) + (other.data*other.unit)
@@ -510,8 +511,8 @@
for i in xrange(len(self._dimensions)):
if not self._dimensions[i] == other.dimensions[i]:
return NotImplemented
- if isPhysicalQuantity(self.unit):
- if not (isPhysicalQuantity(other.unit) and self.unit.isCompatible(other.unit.unit)):
+ if isQuantity(self.unit):
+ if not (isQuantity(other.unit) and self.unit.isCompatible(other.unit.unit)):
return NotImplemented
if self.unit >= other.unit:
data = self.data - (other.data*other.unit.value*other.unit.unit.conversionFactorTo(self.unit.unit))/self.unit.value
@@ -520,7 +521,7 @@
data = ((self.data*self.unit.value*self.unit.unit.conversionFactorTo(other.unit.unit))/other.unit.value) - other.data
unit = other.unit
else:
- if isPhysicalQuantity(other.unit):
+ if isQuantity(other.unit):
return NotImplemented
data = (self.data*self.unit) - (other.data*other.unit)
unit = 1.0
Modified: trunk/src/pyphant/pyphant/core/H5FileHandler.py
===================================================================
--- trunk/src/pyphant/pyphant/core/H5FileHandler.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/core/H5FileHandler.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2006-2008, Rectorate of the University of Freiburg
+# Copyright (c) 2006-2010, Rectorate of the University of Freiburg
+# Copyright (c) 2009-2010, Andreas W. Liehr (li...@us...)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -39,7 +40,7 @@
import tables
from pyphant.core import DataContainer
from tables import StringCol
-from pyphant.quantities.PhysicalQuantities import PhysicalQuantity
+from pyphant.quantities import Quantity
import scipy
import logging
import os
Modified: trunk/src/pyphant/pyphant/core/KnowledgeManager.py
===================================================================
--- trunk/src/pyphant/pyphant/core/KnowledgeManager.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/core/KnowledgeManager.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -392,7 +392,7 @@
use (SQLiteWrapper instance).any_value
or (KM instance).any_value to skip value check
'storage': str types (==)
- 'unit': PhysicalUnit or number or PhysicalQuantity (==, FC only)
+ 'unit': PhysicalUnit or number or Quantity (==, FC only)
'dimensions': list of FC search dicts
(see above definitions, FC only)
'columns': list of FC search dicts (see above definitions, SC only)
@@ -410,7 +410,7 @@
--> [('name1', ), ('name2', ), ...]
Get id and shortname of all FCs that are parametrized by
a time dimension along the primary axis:
- tunit = PhysicalQuantity(1, 's')
+ tunit = Quantity(1, 's')
get_andsearch_result(['id', 'shortname'],
{'type':'field',
'dimensions':[{'unit':tunit}]})
Modified: trunk/src/pyphant/pyphant/core/PyTablesPersister.py
===================================================================
--- trunk/src/pyphant/pyphant/core/PyTablesPersister.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/core/PyTablesPersister.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2006-2008, Rectorate of the University of Freiburg
+# Copyright (c) 2006-2009, Rectorate of the University of Freiburg
+# Copyright (c) 2009, Andreas W. Liehr (li...@us...)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -65,7 +66,7 @@
import sys
from pyphant.core import (CompositeWorker, DataContainer)
from tables import StringCol, Col
-from pyphant.quantities.PhysicalQuantities import PhysicalQuantity
+from pyphant.quantities import Quantity
from ImageProcessing.AutoFocus import FocusSlice # For loading FCs...
import scipy
import logging
Modified: trunk/src/pyphant/pyphant/core/SQLiteWrapper.py
===================================================================
--- trunk/src/pyphant/pyphant/core/SQLiteWrapper.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/core/SQLiteWrapper.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2006-2009, Rectorate of the University of Freiburg
+# Copyright (c) 2006-2010, Rectorate of the University of Freiburg
+# Copyright (c) 2010, Andreas W. Liehr (li...@us...)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -41,17 +42,19 @@
import sqlite3
import time
from pyphant.core.Helpers import (utf82uc, uc2utf8, emd52dict)
-from pyphant.quantities.PhysicalQuantities import (PhysicalQuantity,
- PhysicalUnit)
+from pyphant.quantities import (Quantity,PhysicalUnit,_base_units)
from types import (FloatType, IntType, LongType, StringTypes)
def quantity2powers(quantity):
- if isinstance(quantity, PhysicalQuantity):
- return tuple(quantity.unit.powers)
+ numberOfBaseUnits = len(_base_units)
+ if isinstance(quantity, Quantity):
+ result = tuple(quantity.unit.powers)
+ assert len(result) == numberOfBaseUnits, "Expecting %i base units, but got a tupple of %i unit powers insteat." % (numberOfBaseUnits,len(result))
+ return result
elif isinstance(quantity, (FloatType, IntType, LongType)):
- return (0, ) * 10
+ return (0, ) * numberOfBaseUnits
else:
- raise ValueError("Expected (PhysicalQuantity, FloatType, IntType, "\
+ raise ValueError("Expected (Quantity, FloatType, IntType, "\
"LongType) but got %s instead."\
% (type(quantity), ))
@@ -68,11 +71,11 @@
def quantity2dbase(quantity):
if isinstance(quantity, (FloatType, IntType, LongType)):
return quantity.__repr__()
- elif isinstance(quantity, PhysicalQuantity):
+ elif isinstance(quantity, Quantity):
return "P%s;%s" % (quantity.value.__repr__(),
quantity.getUnitName())
else:
- raise ValueError("Expected (PhysicalQuantity, FloatType, IntType, "\
+ raise ValueError("Expected (Quantity, FloatType, IntType, "\
"LongType) but got %s instead."\
% (type(quantity), ))
@@ -80,7 +83,7 @@
if isinstance(dbase, StringTypes):
if dbase.startswith("P"):
tmp = dbase[1:].split(';')
- return PhysicalQuantity(str2number(tmp[0]), tmp[1])
+ return Quantity(str2number(tmp[0]), tmp[1])
else:
return str2number(dbase)
else:
@@ -273,7 +276,8 @@
('rad', 'INT'),
('sr', 'INT'),
('EUR', 'INT'),
- ('', 'UNIQUE(m, g, s, A, K, mol, cd, rad, sr, EUR)')]
+ ('bit', 'INT'),
+ ('', 'UNIQUE(m, g, s, A, K, mol, cd, rad, sr, EUR,bit)')]
create_table('km_base_units', columns, self.cursor)
#create triggers:
create_trigger('trigger_del_fc', 'DELETE', 'km_fc',
@@ -307,14 +311,14 @@
insert_dict['unit'] = quantity2dbase(summary['unit'])
try:
exe("INSERT OR ABORT INTO km_base_units "\
- "(m, g, s, A, K, mol, cd, rad, sr, EUR) "\
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ "(m, g, s, A, K, mol, cd, rad, sr, EUR, bit) "\
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
quantity2powers(summary['unit']))
l_row_id = self.cursor.lastrowid
except sqlite3.IntegrityError:
exe("SELECT bu_id FROM km_base_units WHERE m=? AND g=? "\
"AND s=? AND A=? AND K=? AND mol=? AND cd=? AND rad=? "\
- "AND sr=? AND EUR=?", quantity2powers(summary['unit']))
+ "AND sr=? AND EUR=? AND bit=?", quantity2powers(summary['unit']))
tmp = self.cursor.fetchone()
assert tmp != None
l_row_id = tmp[0]
@@ -397,17 +401,17 @@
return key
def translate_unit_search(self, value):
- if isinstance(value, PhysicalQuantity):
+ if isinstance(value, Quantity):
value = value.unit.powers
elif isinstance(value, (IntType, LongType, FloatType)):
- value = [0] * 10
+ value = [0] * len(_base_units)
elif isinstance(value, PhysicalUnit):
value = value.powers
else:
raise ValueError(value)
expr = '(bu_id IN (SELECT bu_id FROM km_base_units WHERE '\
'm=? AND g=? AND s=? AND A=? AND K=? AND mol=? '\
- 'AND cd=? AND rad=? AND sr=? AND EUR=?))'
+ 'AND cd=? AND rad=? AND sr=? AND EUR=? AND bit=?))'
return (expr, value, True)
def translate_attr_search(self, value, type):
@@ -539,7 +543,7 @@
use (SQLiteWrapper instance).any_value
or (KM instance).any_value to skip value check
'storage': str types (==)
- 'unit': PhysicalUnit or number or PhysicalQuantity (==, FC only)
+ 'unit': PhysicalUnit or number or Quantity (==, FC only)
'dimensions': list of FC search dicts
(see above definitions, FC only)
'dim_of': str types: emd5 of parent FC (==, FC only)
@@ -559,7 +563,7 @@
--> [('name1', ), ('name2', ), ...]
Get id and shortname of all FCs that are parametrized by
a time dimension along the primary axis:
- tunit = PhysicalQuantity(1, 's')
+ tunit = Quantity(1, 's')
get_andsearch_result(['id', 'shortname'],
{'type':'field',
'dimensions':[{'unit':tunit}]})
Modified: trunk/src/pyphant/pyphant/quantities/ParseQuantities.py
===================================================================
--- trunk/src/pyphant/pyphant/quantities/ParseQuantities.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/quantities/ParseQuantities.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2008, Rectorate of the University of Freiburg
+# Copyright (c) 2008-2009, Rectorate of the University of Freiburg
+# Copyright (c) 2009-2010, Andreas W. Liehr (li...@us...)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -37,10 +38,12 @@
__version__ = "$Revision$"
# $Source$
-from PhysicalQuantities import PhysicalQuantity
import mx.DateTime.ISO
+from pyphant.quantities import Quantity
def str2unit(unit):
+ """The function str2unit returns either a quantity or a float from a given string."""
+ # Prepare conversion to quantity
if unit.startswith('.'):
unit = '0'+unit
elif unit.endswith('%'):
@@ -55,9 +58,10 @@
unit = 1.0
elif not (unit[0].isdigit() or unit[0]=='-'):
unit = '1'+unit
+ # Convert input to quantity or float
try:
unit = unit.replace('^', '**')
- unit = PhysicalQuantity(unit.encode('utf-8'))
+ unit = Quantity(unit.encode('utf-8'))
except:
unit = float(unit)
return unit
@@ -94,9 +98,9 @@
def parseDateTime(value):
"""
>>>parseDateTime('2004-08-21 12:00:00+-12h')
- (PhysicalQuantity(731814.5,'d'), PhysicalQuantity(0.5,'d'))
+ (Quantity(731814.5,'d'), Quantity(0.5,'d'))
>>>parseDateTime('2004-08-21 12:00:00')
- (PhysicalQuantity(731814.5,'d'), None)
+ (Quantity(731814.5,'d'), None)
"""
datetimeWithError = value.split('+-')
if len(datetimeWithError)==2:
@@ -106,4 +110,4 @@
datetime = mx.DateTime.ISO.ParseAny(value)
error = None
days,seconds = datetime.absvalues()
- return (PhysicalQuantity(days,'d')+PhysicalQuantity(seconds,'s'),error)
+ return (Quantity(days,'d')+Quantity(seconds,'s'),error)
Deleted: trunk/src/pyphant/pyphant/quantities/PhysicalQuantities.py
===================================================================
--- trunk/src/pyphant/pyphant/quantities/PhysicalQuantities.py 2010-02-12 16:21:58 UTC (rev 667)
+++ trunk/src/pyphant/pyphant/quantities/PhysicalQuantities.py 2010-02-21 20:51:58 UTC (rev 668)
@@ -1,997 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 1998-2007, Konrad Hinsen <hi...@cn...>
-# Copyright (c) 2008, Rectorate of the University of Freiburg
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# * Neither the name of the Freiburg Materials Research Center,
-# University of Freiburg nor the names of its contributors may be used to
-# endorse or promote products derived from this software without specific
-# prior written permission.
-#
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""
-Quantities with units
-
-based on the module Scientific.Physics.PhysicalQuantities
-written by Conrad Hinsen with contributions from Greg Ward.
-
-This module provides a data type that represents a physical
-quantity together with its unit. It is possible to add and
-subtract these quantities if the units are compatible, and
-a quantity can be converted to another compatible unit.
-Multiplication, subtraction, and raising to integer powers
-is allowed without restriction, and the result will have
-the correct unit. A quantity can be raised to a non-integer
-power only if the result can be represented by integer powers
-of the base units.
-
-The values of physical constants are taken from the 1986
-recommended values from CODATA. Other conversion factors
-(e.g. for British units) come from various sources. I can't
-guarantee for the correctness of all entries in the unit
-table, so use this at your own risk.
-"""
-
-rc = { 'fetchCurrencyRates' : False }
-
-class NumberDict(dict):
-
- """
- Dictionary storing numerical values
-
- Constructor: NumberDict()
-
- An instance of this class acts like an array of number with
- generalized (non-integer) indices. A value of zero is assumed
- for undefined entries. NumberDict instances support addition,
- and subtraction with other NumberDict instances, and multiplication
- and division by scalars.
- """
-
- def __getitem__(self, item):
- try:
- return dict.__getitem__(self, item)
- except KeyError:
- return 0
-
- def __coerce__(self, other):
- if type(other) == type({}):
- other = NumberDict(other)
- return self, other
-
- def __add__(self, other):
- sum_dict = NumberDict()
- for key in self.keys():
- sum_dict[key] = self[key]
- for key in other.keys():
- sum_dict[key] = sum_dict[key] + other[key]
- return sum_dict
-
- def __sub__(self, other):
- sum_dict = NumberDict()
- for key in self.keys():
- sum_dict[key] = self[key]
- for key in other.keys():
- sum_dict[key] = sum_dict[key] - other[key]
- return sum_dict
-
- def __mul__(self, other):
- new = NumberDict()
- for key in self.keys():
- new[key] = other*self[key]
- return new
- __rmul__ = __mul__
-
- def __div__(self, other):
- new = NumberDict()
- for key in self.keys():
- new[key] = self[key]/other
- return new
-
-import numpy.oldnumeric
-def int_sum(a, axis=0):
- return numpy.oldnumeric.add.reduce(a, axis)
-def zeros_st(shape, other):
- return numpy.oldnumeric.zeros(shape, dtype=other.dtype)
-from numpy import ndarray as array_type
-
-
-import re, string
-
-
-# Class definitions
-
-class PhysicalQuantity:
-
- """
- Physical quantity with units
-
- PhysicalQuantity instances allow addition, subtraction,
- multiplication, and division with each other as well as
- multiplication, division, and exponentiation with numbers.
- Addition and subtraction check that the units of the two operands
- are compatible and return the result in the units of the first
- operand. A limited set of mathematical functions (from module
- Numeric) is applicable as well:
-
- - sqrt: equivalent to exponentiation with 0.5.
-
- - sin, cos, tan: applicable only to objects whose unit is
- compatible with 'rad'.
-
- See the documentation of the PhysicalQuantities module for a list
- of the available units.
-
- Here is an example on usage:
-
- >>> from PhysicalQuantities import PhysicalQuantity as p # short hand
- >>> distance1 = p('10 m')
- >>> distance2 = p('10 km')
- >>> total = distance1 + distance2
- >>> total
- PhysicalQuantity(10010.0,'m')
- >>> total.convertToUnit('km')
- >>> total.getValue()
- 10.01
- >>> total.getUnitName()
- 'km'
- >>> total = total.inBaseUnits()
- >>> total
- PhysicalQuantity(10010.0,'m')
- >>>
- >>> t = p(314159., 's')
- >>> # convert to days, hours, minutes, and second:
- >>> t2 = t.inUnitsOf('d','h','min','s')
- >>> t2_print = ' '.join([str(i) for i in t2])
- >>> t2_print
- '3.0 d 15.0 h 15.0 min 59.0 s'
- >>>
- >>> e = p('2.7 Hartree*Nav')
- >>> e.convertToUnit('kcal/mol')
- >>> e
- PhysicalQuantity(1694.2757596034764,'kcal/mol')
- >>> e = e.inBaseUnits()
- >>> str(e)
- '7088849.77818 kg*m**2/s**2/mol'
- >>>
- >>> freeze = p('0 degC')
- >>> freeze = freeze.inUnitsOf ('degF')
- >>> str(freeze)
- '32.0 degF'
- >>>
- """
-
- def __init__(self, *args):
- """
- There are two constructor calling patterns:
-
- 1. PhysicalQuantity(value, unit), where value is any number
- and unit is a string defining the unit
-
- 2. PhysicalQuantity(value_with_unit), where value_with_unit
- is a string that contains both the value and the unit,
- i.e. '1.5 m/s'. This form is provided for more convenient
- interactive use.
-
- @param args: either (value, unit) or (value_with_unit,)
- @type args: (number, C{str}) or (C{str},)
- """
- if len(args) == 2:
- self.value = args[0]
- self.unit = _findUnit(args[1])
- else:
- s = string.strip(args[0])
- match = PhysicalQuantity._number.match(s)
- if match is None:
- raise TypeError('No number found')
- self.value = string.atof(match.group(0))
- self.unit = _findUnit(s[len(match.group(0)):])
-
- _number = re.compile('[+-]?[0-9]+(\\.[0-9]*)?([eE][+-]?[0-9]+)?')
-
- def __str__(self):
- return str(self.value) + ' ' + self.unit.name()
-
- def __repr__(self):
- return (self.__class__.__name__ + '(' + `self.value` + ',' +
- `self.unit.name()` + ')')
-
- def _sum(self, other, sign1, sign2):
- if not isPhysicalQuantity(other):
- raise TypeError('Incompatible types')
- new_value = sign1*self.value + \
- sign2*other.value*other.unit.conversionFactorTo(self.unit)
- return self.__class__(new_value, self.unit)
-
- def __add__(self, other):
- return self._sum(other, 1, 1)
-
- __radd__ = __add__
-
- def __sub__(self, other):
- return self._sum(other, 1, -1)
-
- def __rsub__(self, other):
- return self._sum(other, -1, 1)
-
- def __cmp__(self, other):
- diff = self._sum(other, 1, -1)
- return cmp(diff.value, 0)
-
- def __mul__(self, other):
- if not isPhysicalQuantity(other):
- return self.__class__(self.value*other, self.unit)
- value = self.value*other.value
- unit = self.unit*other.unit
- if unit.isDimensionless():
- return value*unit.factor
- else:
- return self.__class__(value, unit)
-
- __rmul__ = __mul__
-
- def __div__(self, other):
- if not isPhysicalQuantity(other):
- return self.__class__(self.value/other, self.unit)
- value = self.value/other.value
- unit = self.unit/other.unit
- if unit.isDimensionless():
- return value*unit.factor
- else:
- return self.__class__(value, unit)
-
- def __rdiv__(self, other):
- if not isPhysicalQuantity(other):
- return self.__class__(other/self.value, pow(self.unit, -1))
- value = other.value/self.value
- unit = other.unit/self.unit
- if unit.isDimensionless():
- return value*unit.factor
- else:
- return self.__class__(value, unit)
-
- def __pow__(self, other):
- if isPhysicalQuantity(other):
- raise TypeError('Exponents must be dimensionless')
- return self.__class__(pow(self.value, other), pow(self.unit, other))
-
- def __rpow__(self, other):
- raise TypeError('Exponents must be dimensionless')
-
- def __abs__(self):
- return self.__class__(abs(self.value), self.unit)
-
- def __pos__(self):
- return self
-
- def __neg__(self):
- return self.__class__(-self.value, self.unit)
-
- def __nonzero__(self):
- return self.value != 0
-
- def convertToUnit(self, unit):
- """
- Change the unit and adjust the value such that
- the combination is equivalent to the original one. The new unit
- must be compatible with the previous unit of the object.
-
- @param unit: a unit
- @type unit: C{str}
- @raise TypeError: if the unit string is not a know unit or a
- unit incompatible with the current one
- """
- unit = _findUnit(unit)
- self.value = _convertValue (self.value, self.unit, unit)
- self.unit = unit
-
- def inUnitsOf(self, *units):
- """
- Express the quantity in different units. If one unit is
- specified, a new PhysicalQuantity object is returned that
- expresses the quantity in that unit. If several units
- are specified, the return value is a tuple of
- PhysicalObject instances with with one element per unit such
- that the sum of all quantities in the tuple equals the the
- original quantity and all the values except for the last one
- are integers. This is used to convert to irregular unit
- systems like hour/minute/second.
-
- @param units: one or several units
- @type units: C{str} or sequence of C{str}
- @returns: one or more physical quantities
- @rtype: L{PhysicalQuantity} or C{tuple} of L{PhysicalQuantity}
- @raises TypeError: if any of the specified units are not compatible
- with the original unit
- """
- units = map(_findUnit, units)
- if len(units) == 1:
- unit = units[0]
- value = _convertValue (self.value, self.unit, unit)
- return self.__class__(value, unit)
- else:
- units.sort()
- result = []
- value = self.value
- unit = self.unit
- for i in range(len(units)-1,-1,-1):
- value = value*unit.conversionFactorTo(units[i])
- if i == 0:
- rounded = value
- else:
- rounded = _round(value)
- result.append(self.__class__(rounded, units[i]))
- value = value - rounded
- unit = units[i]
- return tuple(result)
-
- # Contributed by Berthold Hoellmann
- def inBaseUnits(self):
- """
- @returns: the same quantity converted to base units,
- i.e. SI units in most cases
- @rtype: L{PhysicalQuantity}
- """
- new_value = self.value * self.unit.factor
- num = ''
- denom = ''
- for i in xrange(9):
- unit = _base_names[i]
- power = self.unit.powers[i]
- if power < 0:
- denom = denom + '/' + unit
- if power < -1:
- denom = denom + '**' + str(-power)
- elif power > 0:
- num = num + '*' + unit
- if power > 1:
- num = num + '**' + str(power)
- if len(num) == 0:
- num = '1'
- else:
- num = num[1:]
- return self.__class__(new_value, num + denom)
-
- def isCompatible (self, unit):
- """
- @param unit: a unit
- @type unit: C{str}
- @returns: C{True} if the specified unit is compatible with the
- one of the quantity
- @rtype: C{bool}
- """
- unit = _findUnit (unit)
- return self.unit.isCompatible (unit)
-
- def getValue(self):
- """Return value (float) of physical quantity (no unit)."""
- return self.value
-
- def getUnitName(self):
- """Return unit (string) of physical quantity."""
- return self.unit.name()
-
- def sqrt(self):
- return pow(self, 0.5)
-
- def sin(self):
- if self.unit.isAngle():
- return numpy.oldnumeric.sin(self.value * \
- self.unit.conversionFactorTo(_unit_table['rad']))
- else:
- raise TypeError('Argument of sin must be an angle')
-
- def cos(self):
- if self.unit.isAngle():
- return numpy.oldnumeric.cos(self.value * \
- self.unit.conversionFactorTo(_unit_table['rad']))
- else:
- raise TypeError('Argument of cos must be an angle')
-
- def tan(self):
- if self.unit.isAngle():
- return numpy.oldnumeric.tan(self.value * \
- self.unit.conversionFactorTo(_unit_table['rad']))
- else:
- raise TypeError('Argument of tan must be an angle')
-
-
-class PhysicalUnit:
-
- """
- Physical unit
-
- A physical unit is defined by a name (possibly composite), a scaling
- factor, and the exponentials of each of the SI base units that enter into
- it. Units can be multiplied, divided, and raised to integer powers.
- """
-
- def __init__(self, names, factor, powers, offset=0):
- """
- @param names: a dictionary mapping each name component to its
- associated integer power (e.g. C{{'m': 1, 's': -1}})
- for M{m/s}). As a shorthand, a string may be passed
- which is assigned an implicit power 1.
- @type names: C{dict} or C{str}
- @param factor: a scaling factor
- @type factor: C{float}
- @param powers: the integer powers for each of the nine base units
- @type powers: C{list} of C{int}
- @param offset: an additive offset to the base unit (used only for
- temperatures)
- @type offset: C{float}
- """
- if type(names) == type(''):
- self.names = NumberDict()
- self.names[names] = 1
- else:
- self.names = names
- self.factor = factor
- self.offset = offset
- self.powers = powers
-
- def __repr__(self):
- return '<PhysicalUnit ' + self.name() + '>'
-
- __str__ = __repr__
-
- def __cmp__(self, other):
- if self.powers != other.powers:
- raise TypeError('Incompatible units')
- return cmp(self.factor, other.factor)
-
- def __mul__(self, other):
- if self.offset != 0 or (isPhysicalUnit (other) and other.offset != 0):
- raise TypeError("cannot multiply units with non-zero offset")
- if isPhysicalUnit(other):
- return PhysicalUnit(self.names+other.names,
- self.factor*other.factor,
- map(lambda a,b: a+b,
- self.powers, other.powers))
- else:
- return PhysicalUnit(self.names+{str(other): 1},
- self.factor*other,
- self.powers,
- self.offset * other)
-
- __rmul__ = __mul__
-
- def __div__(self, other):
- if self.offset != 0 or (isPhysicalUnit (other) and other.offset != 0):
- raise TypeError("cannot divide units with non-zero offset")
- if isPhysicalUnit(other):
- return PhysicalUnit(self.names-other.names,
- self.factor/other.factor,
- map(lambda a,b: a-b,
- self.powers, other.powers))
- else:
- return PhysicalUnit(self.names+{str(other): -1},
- self.factor/other, self.powers)
-
- def __rdiv__(self, other):
- if self.offset != 0 or (isPhysicalUnit (other) and other.offset != 0):
- raise TypeError("cannot divide units with non-zero offset")
- if isPhysicalUnit(other):
- return PhysicalUnit(other.names-self.names,
- other.factor/self.factor,
- map(lambda a,b: a-b,
- other.powers, self.powers))
- else:
- return PhysicalUnit({str(other): 1}-self.names,
- other/self.factor,
- map(lambda x: -x, self.powers))
-
- def __pow__(self, other):
- if self.offset != 0:
- raise TypeError("cannot exponentiate units with non-zero offset")
- if isinstance(other, int):
- return PhysicalUnit(other*self.names, pow(self.factor, other),
- map(lambda x,p=other: x*p, self.powers))
- if isinstance(other, float):
- inv_exp = 1./other
- rounded = int(numpy.oldnumeric.floor(inv_exp+0.5))
- if abs(inv_exp-rounded) < 1.e-10:
- if reduce(lambda a, b: a and b,
- map(lambda x, e=rounded: x%e == 0, self.powers)):
- f = pow(self.factor, other)
- p = map(lambda x,p=rounded: x/p, self.powers)
- if reduce(lambda a, b: a and b,
- map(lambda x, e=rounded: x%e == 0,
- self.names.values())):
- names = self.names/rounded
- else:
- names = NumberDict()
- if f != 1.:
- names[str(f)] = 1
- for i in range(len(p)):
- names[_base_names[i]] = p[i]
- return PhysicalUnit(names, f, p)
- else:
- raise TypeError('Illegal exponent')
- raise TypeError('Only integer and inverse integer exponents allowed')
-
- def conversionFactorTo(self, other):
- """
- @param other: another unit
- @type other: L{PhysicalUnit}
- @returns: the conversion factor from this unit to another unit
- @rtype: C{float}
- @raises TypeError: if the units are not compatible
- """
- if self.powers != other.powers:
- raise TypeError('Incompatible units')
- if self.offset != other.offset and self.factor != other.factor:
- raise TypeError(('Unit conversion (%s to %s) cannot be expressed ' +
- 'as a simple multiplicative factor') % \
- (self.name(), other.name()))
- return self.factor/other.factor
-
- def conversionTupleTo(self, other): # added 1998/09/29 GPW
- """
- @param other: another unit
- @type other: L{PhysicalUnit}
- @returns: the conversion factor and offset from this unit to
- another unit
- @rtype: (C{float}, C{float})
- @raises TypeError: if the units are not compatible
- """
- if self.powers != other.powers:
- raise TypeError('Incompatible units')
-
- # let (s1,d1) be the conversion tuple from 'self' to base units
- # (ie. (x+d1)*s1 converts a value x from 'self' to base units,
- # and (x/s1)-d1 converts x from base to 'self' units)
- # and (s2,d2) be the conversion tuple from 'other' to base units
- # then we want to compute the conversion tuple (S,D) from
- # 'self' to 'other' such that (x+D)*S converts x from 'self'
- # units to 'other' units
- # the formula to convert x from 'self' to 'other' units via the
- # base units is (by definition of the conversion tuples):
- # ( ((x+d1)*s1) / s2 ) - d2
- # = ( (x+d1) * s1/s2) - d2
- # = ( (x+d1) * s1/s2 ) - (d2*s2/s1) * s1/s2
- # = ( (x+d1) - (d1*s2/s1) ) * s1/s2
- # = (x + d1 - d2*s2/s1) * s1/s2
- # thus, D = d1 - d2*s2/s1 and S = s1/s2
- factor = self.factor / other.factor
- offset = self.offset - (other.offset * other.factor / self.factor)
- return (factor, offset)
-
- def isCompatible (self, other): # added 1998/10/01 GPW
- """
- @param other: another unit
- @type other: L{PhysicalUnit}
- @returns: C{True} if the units are compatible, i.e. if the powers of
- the base units are the same
- @rtype: C{bool}
- """
- return self.powers == other.powers
-
- def isDimensionless(self):
- return not reduce(lambda a,b: a or b, self.powers)
-
- def isAngle(self):
- return self.powers[7] == 1 and \
- reduce(lambda a,b: a + b, self.powers) == 1
-
- def setName(self, name):
- self.names = NumberDict()
- self.names[name] = 1
-
- def name(self):
- num = ''
- denom = ''
- for unit in self.names.keys():
- power = self.names[unit]
- if power < 0:
- denom = denom + '/' + unit
- if power < -1:
- denom = denom + '**' + str(-power)
- elif power > 0:
- num = num + '*' + unit
- if power > 1:
- num = num + '**' + str(power)
- if len(num) == 0:
- num = '1'
- else:
- num = num[1:]
- return num + denom
-
-
-# Type checks
-
-def isPhysicalUnit(x):
- """
- @param x: an object
- @type x: any
- @returns: C{True} if x is a L{PhysicalUnit}
- @rtype: C{bool}
- """
- return hasattr(x, 'factor') and hasattr(x, 'powers')
-
-def isPhysicalQuantity(x):
- """
- @param x: an object
- @type x: any
- @returns: C{True} if x is a L{PhysicalQuantity}
- @rtype: C{bool}
- """
- return hasattr(x, 'value') and hasattr(x, 'unit')
-
-
-# Helper functions
-
-def _findUnit(unit):
- from types import StringTypes
- if isinstance(unit, StringTypes):
- name = string.strip(unit)
- unit = eval(name, _unit_table)
- for cruft in ['__builtins__', '__args__']:
- try: del _unit_table[cruft]
- except: pass
-
- if not isPhysicalUnit(unit):
- raise TypeError(str(unit) + ' is not a unit')
- return unit
-
-def _round(x):
- if numpy.oldnumeric.greater(x, 0.):
- return numpy.oldnumeric.floor(x)
- else:
- return numpy.oldnumeric.ceil(x)
-
-
-def _convertValue (value, src_unit, target_unit):
- (factor, offset) = src_unit.conversionTupleTo(target_unit)
- return (value + offset) * factor
-
-
-# SI unit definitions
-
-_base_names = ['m', 'kg', 's', 'A', 'K', 'mol', 'cd', 'rad', 'sr','EUR']
-
-_base_units = [('m', PhysicalUnit('m', 1., [1,0,0,0,0,0,0,0,0,0])),
- ('g', PhysicalUnit('g', 0.001, [0,1,0,0,0,0,0,0,0,0])),
- ('s', PhysicalUnit('s', 1., [0,0,1,0,0,0,0,0,0,0])),
- ('A', PhysicalUnit('A', 1., [0,0,0,1,0,0,0,0,0,0])),
- ('K', PhysicalUnit('K', 1., [0,0,0,0,1,0,0,0,0,0])),
- ('mol', PhysicalUnit('mol', 1., [0,0,0,0,0,1,0,0,0,0])),
- ('cd', PhysicalUnit('cd', 1., [0,0,0,0,0,0,1,0,0,0])),
- ('rad', PhysicalUnit('rad', 1., [0,0,0,0,0,0,0,1,0,0])),
- ('sr', PhysicalUnit('sr', 1., [0,0,0,0,0,0,0,0,1,0])),
- ('EUR', PhysicalUnit('EUR', 1., [0,0,0,0,0,0,0,0,0,1])),
- ]
-
-_prefixes = [('Y', 1.e24),
- ('Z', 1.e21),
- ('E', 1.e18),
- ('P', 1.e15),
- ('T', 1.e12),
- ('G', 1.e9),
- ('M', 1.e6),
- ('k', 1.e3),
- ('h', 1.e2),
- ('da', 1.e1),
- ('d', 1.e-1),
- ('c', 1.e-2),
- ('m', 1.e-3),
- ('mu', 1.e-6),
- ('n', 1.e-9),
- ('p', 1.e-12),
- ('f', 1.e-15),
- ('a', 1.e-18),
- ('z', 1.e-21),
- ('y', 1.e-24),
- ]
-
-_unit_table = {}
-
-for unit in _base_units:
- _unit_table[unit[0]] = unit[1]
-
-_help = []
-
-def _addUnit(name, unit, comment=''):
- if _unit_table.has_key(name):
- raise KeyError, 'Unit ' + name + ' already defined'
- if comment:
- _help.append((name, comment, unit))
- if type(unit) == type(''):
- unit = eval(unit, _unit_table)
- for cruft in ['__builtins__', '__args__']:
- try: del _unit_table[cruft]
- except: pass
- unit.setName(name)
- _unit_table[name] = unit
-
-def _addPrefixed(unit):
- _help.append('Prefixed units for %s:' % unit)
- _prefixed_names = []
- for prefix in _prefixes:
- name = prefix[0] + unit
- _addUnit(name, prefix[1]*_unit_table[unit])
- _prefixed_names.append(name)
- _help.append(', '.join(_prefixed_names))
-
-
-# SI derived units; these automatically get prefixes
-_help.append('SI derived units; these automatically get prefixes:\n' + \
- ', '.join([prefix + ' (%.0E)' % value for prefix, value in _prefixes]) + \
- '\n')
-
-
-_unit_table['kg'] = PhysicalUnit('kg', 1., [0,1,0,0,0,0,0,0,0,0])
-
-_addUnit('Hz', '1/s', 'Hertz')
-_addUnit('N', 'm*kg/s**2', 'Newton')
-_addUnit('Pa', 'N/m**2', 'Pascal')
-_addUnit('J', 'N*m', 'Joule')
-_addUnit('W', 'J/s', 'Watt')
-_addUnit('C', 's*A', 'Coulomb')
-_addUnit('V', 'W/A', 'Volt')
-_addUnit('F', 'C/V', 'Farad')
-_addUnit('ohm', 'V/A', 'Ohm')
-_addUnit('S', 'A/V', 'Siemens')
-_addUnit('Wb', 'V*s', 'Weber')
-_addUnit('T', 'Wb/m**2', 'Tesla')
-_addUnit('H', 'Wb/A', 'Henry')
-_addUnit('lm', 'cd*sr', 'Lumen')
-_addUnit('lx', 'lm/m**2', 'Lux')
-_addUnit('Bq', '1/s', 'Becquerel')
-_addUnit('Gy', 'J/kg', 'Gray')
-_addUnit('Sv', 'J/kg', 'Sievert')
-
-del _unit_table['kg']
-
-for unit in _unit_table.keys():
- _addPrefixed(unit)
-
-# Fundamental constants
-_help.append('Fundamental constants:')
-
-_unit_table['pi'] = numpy.oldnumeric.pi
-_addUnit('c', '299792458.*m/s', 'speed of light')
-_addUnit('mu0', '4.e-7*pi*N/A**2', 'permeability of vacuum')
-_addUnit('eps0', '1/mu0/c**2', 'permittivity of vacuum')
-_addUnit('Grav', '6.67259e-11*m**3/kg/s**2', 'gravitational constant')
-_addUnit('hplanck', '6.6260755e-34*J*s', 'Planck constant')
-_addUnit('hbar', 'hplanck/(2*pi)', 'Planck constant / 2pi')
-_addUnit('e', '1.60217733e-19*C', 'elementary charge')
-_addUnit('me', '9.1093897e-31*kg', 'electron mass')
-_addUnit('mp', '1.6726231e-27*kg', 'proton mass')
-_addUnit('Nav', '6.0221367e23/mol', 'Avogadro number')
-_addUnit('k', '1.380658e-23*J/K', 'Boltzmann constant')
-
-# Time units
-_help.append('Time units:')
-
-_addUnit('min', '60*s', 'minute')
-_addUnit('h', '60*min', 'hour')
-_addUnit('d', '24*h', 'day')
-_addUnit('wk', '7*d', 'week')
-_addUnit('yr', '365.25*d', 'year')
-
-# Length units
-_help.append('Length units:')
-
-_addUnit('inch', '2.54*cm', 'inch')
-_addUnit('ft', '12*inch', 'foot')
-_addUnit('yd', '3*ft', 'yard')
-_addUnit('mi', '5280.*ft', '(British) mile')
-_addUnit('nmi', '1852.*m', 'Nautical mile')
-_addUnit('Ang', '1.e-10*m', 'Angstrom')
-_addUnit('lyr', 'c*yr', 'light year')
-_addUnit('AU'...
[truncated message content] |