Skip to content

Commit db83d82

Browse files
committed
some simplifications in quantity constructors, where attributes have already been initialized by array_finalize
use ._dimensionality instead of .units internally, wherever possible, for performance reasons. Improved import times and unit tests take only 0.6 seconds instead of 2 seconds.
1 parent d1b19e3 commit db83d82

File tree

9 files changed

+84
-147
lines changed

9 files changed

+84
-147
lines changed

.eric4project/quantities.e4q

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE UserProject SYSTEM "UserProject-4.0.dtd">
33
<!-- eric4 user project file for project quantities -->
4-
<!-- Saved: 2009-01-20, 18:13:35 -->
4+
<!-- Saved: 2009-01-21, 13:57:13 -->
55
<!-- Copyright (C) 2009 , -->
66
<UserProject version="4.0">
77
</UserProject>

.eric4project/quantities.e4t

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE Tasks SYSTEM "Tasks-4.2.dtd">
33
<!-- eric4 tasks file for project quantities -->
4-
<!-- Saved: 2009-01-20, 18:13:35 -->
4+
<!-- Saved: 2009-01-21, 13:57:13 -->
55
<Tasks version="4.2">
66
<Task priority="1" completed="False" bugfix="False">
77
<Summary>TODO: move to physical constants</Summary>
@@ -48,40 +48,31 @@
4848
<Linenumber>100</Linenumber>
4949
</Resource>
5050
</Task>
51-
<Task priority="1" completed="False" bugfix="False">
52-
<Summary>TODO: needs uncertainty: http://en.wikipedia.org/wiki/Astronomical_unit</Summary>
53-
<Description></Description>
54-
<Created>2009-01-14, 17:09:35</Created>
55-
<Resource>
56-
<Filename>quantities/units/length.py</Filename>
57-
<Linenumber>111</Linenumber>
58-
</Resource>
59-
</Task>
6051
<Task priority="1" completed="False" bugfix="False">
6152
<Summary>TODO: what is an appropriate value?</Summary>
6253
<Description></Description>
63-
<Created>2009-01-18, 12:40:47</Created>
54+
<Created>2009-01-21, 12:40:34</Created>
6455
<Resource>
65-
<Filename>quantities/uncertainquantity.py</Filename>
66-
<Linenumber>11</Linenumber>
56+
<Filename>quantities/quantity.py</Filename>
57+
<Linenumber>62</Linenumber>
6758
</Resource>
6859
</Task>
6960
<Task priority="1" completed="False" bugfix="False">
70-
<Summary>TODO: what is an appropriate value?</Summary>
61+
<Summary>TODO: do we want this kind of magic?</Summary>
7162
<Description></Description>
72-
<Created>2009-01-20, 18:13:18</Created>
63+
<Created>2009-01-21, 12:40:34</Created>
7364
<Resource>
7465
<Filename>quantities/quantity.py</Filename>
75-
<Linenumber>27</Linenumber>
66+
<Linenumber>379</Linenumber>
7667
</Resource>
7768
</Task>
7869
<Task priority="1" completed="False" bugfix="False">
79-
<Summary>TODO: do we want this kind of magic?</Summary>
70+
<Summary>TODO: what is an appropriate value?</Summary>
8071
<Description></Description>
81-
<Created>2009-01-20, 18:13:18</Created>
72+
<Created>2009-01-21, 13:52:50</Created>
8273
<Resource>
83-
<Filename>quantities/quantity.py</Filename>
84-
<Linenumber>343</Linenumber>
74+
<Filename>quantities/uncertainquantity.py</Filename>
75+
<Linenumber>14</Linenumber>
8576
</Resource>
8677
</Task>
8778
</Tasks>

quantities.e4p

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE Project SYSTEM "Project-4.6.dtd">
33
<!-- eric4 project file for project quantities -->
4-
<!-- Saved: 2009-01-19, 14:46:07 -->
4+
<!-- Saved: 2009-01-21, 13:57:13 -->
55
<!-- Copyright (C) 2009 , -->
66
<Project version="4.6">
77
<Language>en</Language>
@@ -19,7 +19,6 @@
1919
<Source>quantities/units/angle.py</Source>
2020
<Source>quantities/units/electromagnetism.py</Source>
2121
<Source>quantities/units/information.py</Source>
22-
<Source>quantities/units/compound.py</Source>
2322
<Source>quantities/units/acceleration.py</Source>
2423
<Source>quantities/units/viscosity.py</Source>
2524
<Source>quantities/units/radiation.py</Source>
@@ -68,6 +67,7 @@
6867
<Source>quantities/constants/weak.py</Source>
6968
<Source>quantities/constants/astronomy.py</Source>
7069
<Source>quantities/constants/statisticalmechanics.py</Source>
70+
<Source>quantities/units/compound.py</Source>
7171
</Sources>
7272
<Forms>
7373
</Forms>

quantities.egg-info/PKG-INFO

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Metadata-Version: 1.1
22
Name: quantities
3-
Version: 0.1
3+
Version: 0.5a1
44
Summary: Support for physical quantities based on the popular numpy library
55
Home-page: http://packages.python.org/quantities
66
Author: Darren Dale

quantities/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979

8080
from __future__ import absolute_import
8181

82-
__version__ = '0.1(bzr)'
82+
__version__ = '0.5a1'
8383

8484
from .quantity import Quantity
8585
from .uncertainquantity import UncertainQuantity

quantities/dimensionality.py

Lines changed: 29 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,11 @@
1212
from .registry import unit_registry
1313

1414

15-
class Dimensionality(object):
15+
class Dimensionality(dict):
1616

1717
"""
1818
"""
1919

20-
def __init__(self, dict=None):
21-
self.__data = {}
22-
if dict is not None:
23-
self.__data.update(dict)
24-
2520
@property
2621
def simplified(self):
2722
if len(self):
@@ -32,6 +27,14 @@ def simplified(self):
3227
else:
3328
return self
3429

30+
@property
31+
def string(self):
32+
return format_units(self)
33+
34+
@property
35+
def unicode(self):
36+
return format_units_unicode(self)
37+
3538
def __hash__(self):
3639
res = hash(unit_registry['dimensionless'])
3740
for key in sorted(self.keys(), key=operator.attrgetter('format_order')):
@@ -80,127 +83,77 @@ def __isub__(self, other):
8083
return self
8184

8285
def __mul__(self, other):
83-
new = dict(self)
86+
new = Dimensionality(self)
8487
for unit, power in other.iteritems():
8588
try:
8689
new[unit] += power
8790
if new[unit] == 0:
8891
new.pop(unit)
8992
except KeyError:
9093
new[unit] = power
91-
return Dimensionality(new)
94+
return new
9295

9396
def __imul__(self, other):
9497
for unit, power in other.iteritems():
9598
try:
96-
self.__data[unit] += power
97-
if self.__data[unit] == 0:
98-
self.__data.pop(unit)
99+
self[unit] += power
100+
if self[unit] == 0:
101+
self.pop(unit)
99102
except KeyError:
100-
self.__data[unit] = power
103+
self[unit] = power
101104
return self
102105

103106
def __truediv__(self, other):
104-
new = dict(self)
107+
new = Dimensionality(self)
105108
for unit, power in other.iteritems():
106109
try:
107110
new[unit] -= power
108111
if new[unit] == 0:
109112
new.pop(unit)
110113
except KeyError:
111114
new[unit] = -power
112-
return Dimensionality(new)
115+
return new
113116

114117
def __div__(self, other):
115118
return self.__truediv__(other)
116119

117120
def __itruediv__(self, other):
118121
for unit, power in other.iteritems():
119122
try:
120-
self.__data[unit] -= power
121-
if self.__data[unit] == 0:
122-
self.__data.pop(unit)
123+
self[unit] -= power
124+
if self[unit] == 0:
125+
self.pop(unit)
123126
except KeyError:
124-
self.__data[unit] = -power
127+
self[unit] = -power
125128
return self
126129

127130
def __idiv__(self, other):
128131
return self.__itruediv__(other)
129132

130133
def __pow__(self, other):
131134
assert isinstance(other, (int, float))
132-
new = dict(self)
135+
new = Dimensionality(self)
133136
for i in new:
134137
new[i] *= other
135-
return Dimensionality(new)
138+
return new
136139

137140
def __ipow__(self, other):
138141
assert isinstance(other, (int, float))
139-
for i in self.__dict:
140-
self.__dict[i] *= other
142+
for i in self:
143+
self[i] *= other
141144
return self
142145

143146
def __repr__(self):
144-
return self.string()
147+
return self.string
145148

146149
def __str__(self):
147150
if USE_UNICODE:
148-
return self.unicode()
149-
else:
150-
return self.string()
151-
152-
def __cmp__(self, dict):
153-
if isinstance(dict, Dimensionality):
154-
return cmp(self.__data, dict.__data)
151+
return self.unicode
155152
else:
156-
return cmp(self, dict)
157-
158-
def __len__(self):
159-
return len(self.__data)
160-
161-
def __contains__(self, key):
162-
return key in self.__data
153+
return self.string
163154

164155
def __eq__(self, other):
165156
return hash(self) == hash(other)
166157

167-
def __getitem__(self, key):
168-
return self.__data[key]
169-
170-
def __iter__(self):
171-
return self.__data.__iter__()
172-
173158
def copy(self):
174-
return Dimensionality(self.__data.copy())
175-
176-
def keys(self):
177-
return self.__data.keys()
178-
179-
def items(self):
180-
return self.__data.items()
181-
182-
def iteritems(self):
183-
return self.__data.iteritems()
184-
185-
def iterkeys(self):
186-
return self.__data.iterkeys()
187-
188-
def itervalues(self):
189-
return self.__data.itervalues()
190-
191-
def values(self):
192-
return self.__data.values()
193-
194-
def has_key(self, key):
195-
return self.__data.has_key(key)
196-
197-
def get(self, key, failobj=None):
198-
if not self.has_key(key):
199-
return failobj
200-
return self[key]
201-
202-
def string(self):
203-
return format_units(self)
204-
205-
def unicode(self):
206-
return format_units_unicode(self)
159+
return Dimensionality(self)

quantities/quantity.py

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ def validate_unit_quantity(value):
3636

3737
def validate_dimensionality(value):
3838
if isinstance(value, str):
39-
return unit_registry[value].dimensionality.copy()
39+
return unit_registry[value].dimensionality
4040
elif isinstance(value, Quantity):
4141
validate_unit_quantity(value)
42-
return value.dimensionality.copy()
43-
elif isinstance(value, (Dimensionality, dict)):
44-
return value.copy()
42+
return value.dimensionality
43+
elif isinstance(value, Dimensionality):
44+
return value
4545
else:
4646
raise TypeError(
4747
'units must be a quantity, string, or dimensionality, got %s'\
@@ -66,21 +66,15 @@ def __new__(cls, data, units='', dtype=None, copy=True):
6666
if isinstance(data, cls):
6767
if units:
6868
data = data.rescale(units)
69-
if copy or (dtype and data.dtype != dtype):
70-
return data.astype(dtype)
71-
return data
72-
73-
ret = numpy.asarray(data, dtype).view(cls)
74-
if copy:
75-
ret = ret.copy()
76-
77-
ret._dimensionality = validate_dimensionality(units)
69+
return numpy.array(data, dtype=dtype, copy=copy, subok=True)
7870

71+
ret = numpy.array(data, dtype=dtype, copy=copy).view(cls)
72+
ret._dimensionality.update(validate_dimensionality(units))
7973
return ret
8074

8175
@property
8276
def dimensionality(self):
83-
return self._dimensionality
77+
return self._dimensionality.copy()
8478

8579
@property
8680
def magnitude(self):
@@ -142,17 +136,12 @@ def astype(self, dtype=None):
142136
ret = super(Quantity, self).astype(dtype)
143137
# scalar quantities get converted to plain numbers, so we fix this:
144138
if not isinstance(ret, type(self)):
145-
ret = type(self)(ret, self.units)
139+
ret = type(self)(ret, self._dimensionality)
146140

147141
return ret
148142

149-
def __array__(self, dtype=None):
150-
return type(self)(self, dtype, copy=True)
151-
152143
def __array_finalize__(self, obj):
153144
self._dimensionality = getattr(obj, 'dimensionality', Dimensionality())
154-
if self.base is None:
155-
self._dimensionality = self._dimensionality.copy()
156145

157146
# def __array_wrap__(self, obj, context=None):
158147
# """
@@ -368,7 +357,7 @@ def __str__(self):
368357

369358
def __getitem__(self, key):
370359
if isinstance(key, int):
371-
return Quantity(self.magnitude[key], self.units)
360+
return Quantity(self.magnitude[key], self._dimensionality)
372361
else:
373362
return super(Quantity, self).__getitem__(key)
374363

@@ -377,7 +366,7 @@ def __setitem__(self, key, value):
377366
value = Quantity(value)
378367

379368
# TODO: do we want this kind of magic?
380-
self.magnitude[key] = value.rescale(self.units).magnitude
369+
self.magnitude[key] = value.rescale(self._dimensionality).magnitude
381370

382371
def __lt__(self, other):
383372
ss, os = prepare_compatible_units(self, other)
@@ -528,8 +517,8 @@ def clip(self, min=None, max=None, out=None):
528517
)
529518

530519
clipped = self.magnitude.clip(
531-
min.rescale(self.units).magnitude,
532-
max.rescale(self.units).magnitude,
520+
min.rescale(self._dimensionality).magnitude,
521+
max.rescale(self._dimensionality).magnitude,
533522
out
534523
)
535524
return Quantity(clipped, self.dimensionality, copy=False)

0 commit comments

Comments
 (0)