Skip to content

Commit cdb303a

Browse files
authored
Merge pull request #6 from UV-CDAT/metrics
done with cdp metrics.
2 parents 3a74406 + a84cf56 commit cdb303a

File tree

4 files changed

+133
-10
lines changed

4 files changed

+133
-10
lines changed

cdp/cdp_metric.py

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,71 @@
55
class CDPMetric(cdp.cdp_tool.CDPTool):
66
__metaclass__ = abc.ABCMeta
77

8-
def __init__(self, var, data1, data2):
9-
self.var = var
10-
self.data1 = data1
11-
self.data2 = data2
8+
def __init__(self, metric_path):
9+
# metric_path: printed when this metric is used.
10+
# Let's users know when a metric is called in the code.
11+
# _values: dictionary of the computed values. This allows for compound metrics.
12+
self._metric_path = metric_path
13+
# get the 'filename' from /path/to/filename.py
14+
name_with_py = self._metric_path.split('/')[-1]
15+
name = name_with_py.split('.')[0]
16+
self._values = {name: self}
1217

13-
def __call__(self):
14-
self.compute()
18+
def __call__(self, *args, **kwargs):
19+
self._show_metric_information()
20+
if self._is_compound():
21+
# Remove the 'CompoundMetric' key from the _values
22+
self._values.pop('CompoundMetric')
23+
# loop through and calculate all of the metrics
24+
for key, value in self._values.items():
25+
# replaces the function with the actual value
26+
self._values[key] = value(*args, **kwargs)
27+
return self._values
28+
else:
29+
return self.compute(*args, **kwargs)
30+
31+
def __add__(self, other):
32+
class CompoundMetric(CDPMetric):
33+
def compute(self):
34+
pass
35+
compound_metric = CompoundMetric('CompoundMetric')
36+
self._add_values_dict_into_first(compound_metric, self)
37+
self._add_values_dict_into_first(compound_metric, other)
38+
return compound_metric
39+
40+
def __sub__(self, other):
41+
class CompoundMetric(CDPMetric):
42+
def compute(self):
43+
pass
44+
if not self._is_compound():
45+
raise TypeError('First operand must be a CompoundMetric')
46+
compound_metric = CompoundMetric('CompoundMetric')
47+
self._add_values_dict_into_first(compound_metric, self)
48+
self._subtract_values_dict_into_first(compound_metric, other)
49+
return compound_metric
50+
51+
def _is_compound(self):
52+
""" Determines if the current metric was a compound metric, one
53+
created with the + operator. """
54+
return len(self._values) > 1
55+
56+
def _add_values_dict_into_first(self, compound_metric, other_metric):
57+
""" Merges the _values dict of two objects of type CDPMetric
58+
into the first. """
59+
for key, value in other_metric._values.items():
60+
compound_metric._values[key] = value
61+
62+
def _subtract_values_dict_into_first(self, compound_metric, other_metric):
63+
""" Removes the elements of the _values dict of the second
64+
object from the first object's _values dict. """
65+
for key in other_metric._values:
66+
if compound_metric._values.pop(key, None) is None:
67+
print "Could not subtract %s metric since it's not in the first operand." % key
68+
69+
def _show_metric_information(self):
70+
""" Displays information about this metric so that a user
71+
can easily identify what metrics are being used. """
72+
print 'Using metric: ' + self._metric_path
1573

1674
@abc.abstractmethod
1775
def compute(self):

cdp/test/test_cdp_metric.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import unittest
2+
import cdp.cdp_metric
3+
4+
5+
class TestCDPMetric(unittest.TestCase):
6+
7+
class Add(cdp.cdp_metric.CDPMetric):
8+
def __init__(self):
9+
metric_path = 'add'
10+
super(TestCDPMetric.Add, self).__init__(metric_path)
11+
12+
def compute(self, a1, a2):
13+
return a1 + a2
14+
15+
class Sub(cdp.cdp_metric.CDPMetric):
16+
def __init__(self):
17+
metric_path = 'sub'
18+
super(TestCDPMetric.Sub, self).__init__(metric_path)
19+
20+
def compute(self, s1, s2):
21+
return s1 - s2
22+
23+
def test_init_metric(self):
24+
try:
25+
sub = self.Sub()
26+
except:
27+
self.fail('Failed to initialize a variable of type Sub, a child type of CDPMetric.')
28+
29+
def test_compute(self):
30+
try:
31+
sub = self.Sub()
32+
result = sub(2, 1)
33+
self.assertEquals(result, 1)
34+
except Exception as err:
35+
self.fail('Failure during call compute(): %s' % err)
36+
37+
def test_add(self):
38+
try:
39+
sub = TestCDPMetric.Sub()
40+
add = TestCDPMetric.Add()
41+
new_metric = sub + add
42+
result = new_metric(2, 1)
43+
self.assertDictEqual(result, {'add':3, 'sub':1})
44+
except Exception as err:
45+
self.fail('Failure during metric addition: %s' % err)
46+
47+
def test_sub(self):
48+
try:
49+
sub = TestCDPMetric.Sub()
50+
add = TestCDPMetric.Add()
51+
compound_metric = sub + add
52+
new_metric = compound_metric - sub
53+
result = new_metric(2, 1)
54+
self.assertDictEqual(result, {'add':3})
55+
except Exception as err:
56+
self.fail('Failure during metric subtraction: %s' % err)
57+
58+
def test_is_compound(self):
59+
sub = TestCDPMetric.Sub()
60+
add = TestCDPMetric.Add()
61+
compound_metric = sub + add
62+
self.assertTrue(compound_metric._is_compound())
63+
64+
if __name__ == '__main__':
65+
unittest.main()

conda/meta.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ about:
44

55
package:
66
name: cdp
7-
version: '1.0.1'
7+
version: '1.0.2'
88

99
source:
10-
git_rev: v1.0.1
10+
git_rev: v1.0.2
1111
git_url: https://github.com/UV-CDAT/CDP.git
1212

1313
requirements:

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
setup(
44
name="cdp",
5-
version="1.0.1",
5+
version="1.0.2",
66
author="Zeshawn Shaheen",
77
author_email="[email protected]",
8-
description="Framework for creating climate diagnostics.",
8+
description="Framework for creating scientific diagnostics.",
99
packages=find_packages(exclude=["*.test", "*.test.*", "test.*", "test"]),
1010
include_package_data=True
1111
)

0 commit comments

Comments
 (0)