Skip to content

Commit

Permalink
Lots of cell updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
uclatommy committed Apr 9, 2017
1 parent 202a496 commit 6e36295
Show file tree
Hide file tree
Showing 8 changed files with 425 additions and 244 deletions.
85 changes: 83 additions & 2 deletions PyCell/Plugins/PyCell/dataframe_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@
'name': 'Update',
'module': 'PyCell.dataframe_cell',
'categories': ['Data', 'Modify']
},
{
'name': 'Iloc',
'module': 'PyCell.dataframe_cell',
'categories': ['Data', 'Modify']
},
{
'name': 'Loc',
'module': 'PyCell.dataframe_cell',
'categories': ['Data', 'Modify']
}
]

Expand Down Expand Up @@ -460,6 +470,74 @@ def process(self):
return super().process()


class Iloc(Custom):
"""
Create a dataframe subset using the `iloc` function.
:param axis0: Rows to return by position
:type axis0: int, list of int, slice
:param axis1: Columns to return by position
:type axis1: int, list of int, slice
:param data: *Required*. The source data.
:type data: H5
:returns: The requested rows and columns.
:rtype: H5
"""
required = ['data']

def __init__(self):
self.return_msg_ = 'I\'m ready!'
self.inputs = {'axis0': None, 'axis1': None, 'data': None}
self.outputs = {'dataframe': None}

@data_process
def iloc(self, h5):
df = None
if self.inputs['axis1'] is None:
df = h5.df.iloc[self.inputs['axis0']]
else:
df = h5.df.iloc[self.inputs['axis0'], self.inputs['axis1']]
return df

def process(self):
self.outputs['dataframe'] = self.iloc(self.inputs['data'])
return super().process()


class Loc(Custom):
"""
Create a dataframe subset using the `loc` function.
:param axis0: Rows to return by label
:type axis0: label, list of labels
:param axis1: Columns to return by label
:type axis1: label, list of labels
:param data: *Required*. The source data.
:type data: H5
:returns: The requested rows and columns.
:rtype: H5
"""
required = ['data']

def __init__(self):
self.return_msg_ = 'I\'m ready!'
self.inputs = {'axis0': None, 'axis1': None, 'data': None}
self.outputs = {'dataframe': None}

@data_process
def loc(self, h5):
df = None
if self.inputs['axis1'] is None:
df = h5.df.loc[self.inputs['axis0']]
else:
df = h5.df.loc[self.inputs['axis0'], self.inputs['axis1']]
return df

def process(self):
self.outputs['dataframe'] = self.loc(self.inputs['data'])
return super().process()


class Head(Custom):
"""
Creates a new dataframe from the first few rows of the input DataFrame.
Expand All @@ -481,9 +559,12 @@ def __init__(self):
@data_process
def head(self, h5):
# select start and stop params dont work for series for some reason.
df = h5.select(start=0, stop=self.inputs['n'])
stop = self.inputs['n']
if stop is None:
stop = 5
df = h5.select(start=0, stop=stop)
# calling head on df because df might be a series.
return df.head(self.inputs['n'])
return df.head(stop)

def process(self):
self.outputs['dataframe'] = self.head(self.inputs['data'])
Expand Down
90 changes: 58 additions & 32 deletions PyCell/Plugins/PyCell/projection_cell.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
"""
Projection
==========
The projection module produces tensors that are intended to represent your
model's time series results.
"""

from PyCell.custom_cell import Custom
from PyCell import registry
import ast
Expand All @@ -23,39 +30,21 @@
ast.USub: op.neg}


def eval_expr(expr):
"""
>>> eval_expr('2^6')
4
>>> eval_expr('2**6')
64
>>> eval_expr('1 + 2*3**(4^5) / (6 + -7)')
-5.0
"""
return eval_(ast.parse(expr, mode='eval').body)


def eval_(node):
if isinstance(node, ast.Num): # <number>
return node.n
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
return operators[type(node.op)](eval_(node.left), eval_(node.right))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
return operators[type(node.op)](eval_(node.operand))
else:
raise TypeError(node)


class AstColumn(Custom):
"""
AstColumn produces a vector tranformation using t as the input vector and
f(t) as the transformation function. The function f should be an expression
in terms of t, and the t socket should contain a list.
Example:
f(t) = 't**2'
t = [1, 2, 3, 4]
ans = [1, 4, 9, 16]
Example::
>>> a = AstColumn()
>>> a.inputs['f(t)'] = 't**2'
>>> a.inputs['t'] = [1, 2, 3, 4]
>>> a.process()
0
>>> a.outputs['ans']
[1, 4, 9, 16]
"""
inputs = {'f(t)': 't', 't': []}
inflows = ['>>']
Expand All @@ -71,21 +60,58 @@ def return_msg(self):

def process(self):
expr = str(self.inputs['f(t)'])
self.outputs['ans'] = [eval_expr(expr.replace('t', str(t)))
self.outputs['ans'] = [self._eval_expr(expr.replace('t', str(t)))
for t in self.inputs['t']]
return super().process()

def _eval_expr(self, expr):
"""
*Internal*. Evaluates a string math expression.
Example::
>>> _eval_expr('2^6')
4
>>> _eval_expr('2**6')
64
>>> _eval_expr('1 + 2*3**(4^5) / (6 + -7)')
-5.0
"""
return self._eval(ast.parse(expr, mode='eval').body)


def _eval(self, node):
"""
Recursively evaluates a binary syntax tree. Each node is composed of
other nodes, operators, or numbers. When a node is encountered, a
a recursion occurs.
"""
if isinstance(node, ast.Num): # <number>
return node.n
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
return operators[type(node.op)](self._eval(node.left),
self._eval(node.right))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
return operators[type(node.op)](self._eval(node.operand))
else:
raise TypeError(node)


class NumpyColumn(Custom):
"""
NumpyColumn produces a vector tranformation using t as the input vector and
f(t) as the transformation function. The function f should be an expression
in terms of t, and the t socket should contain a list.
Example:
f(t) = 't**2'
t = [1, 2, 3, 4]
ans = [1, 4, 9, 16]
Example::
>>> a = NumpyColumn()
>>> a.inputs['f(t)'] = 't**2'
>>> a.inputs['t'] = [1, 2, 3, 4]
>>> a.process()
0
>>> a.outputs['ans']
array([1, 4, 9, 16])
"""
inputs = {'f(t)': 't', 't': []}
inflows = ['>>']
Expand Down
Loading

0 comments on commit 6e36295

Please sign in to comment.