Rearranging util codes. Added meshUtils.closestPoints

This commit is contained in:
rowanc1
2014-04-23 12:11:36 -07:00
parent fb2bc30d96
commit a36f4d76bb
6 changed files with 329 additions and 322 deletions
+4 -2
View File
@@ -7,18 +7,20 @@ import warnings
DEFAULTS = {'direct':'scipy', 'iter':'scipy', 'triangular':'fortran', 'diagonal':'python'}
OPTIONS = {'direct':['scipy'], 'iter':['scipy'], 'triangular':['python'], 'diagonal':['python']}
HELP = []
try:
import Utils.TriSolve as TriSolve
OPTIONS['triangular'].append('fortran')
except Exception, e:
print 'Warning: Python backend is being used for solver. Run setup.py from the command line.'
HELP += ['Warning: Python backend is being used for solver. Run setup.py from the command line.']
DEFAULTS['triangular'] = 'python'
try:
import mumps
OPTIONS['direct'].append('mumps')
except Exception, e:
print 'Warning: mumps solver not available.'
HELP += ['Warning: mumps solver not available.']
class Solver(object):
"""
+114
View File
@@ -0,0 +1,114 @@
import types
import time
import numpy as np
from functools import wraps
class Counter(object):
"""
Counter allows anything that calls it to record iterations and
timings in a simple way.
Also has plotting functions that allow quick recalls of data.
If you want to use this, import *count* or *timeIt* and use them as decorators on class methods.
::
class MyClass(object):
def __init__(self, url):
self.counter = Counter()
@count
def MyMethod(self):
pass
@timeIt
def MySecondMethod(self):
pass
c = MyClass('blah')
for i in range(100): c.MyMethod()
for i in range(300): c.MySecondMethod()
c.counter.summary()
"""
def __init__(self):
self._countList = {}
self._timeList = {}
def count(self, prop):
"""
Increases the count of the property.
"""
assert type(prop) is str, 'The property must be a string.'
if prop not in self._countList:
self._countList[prop] = 0
self._countList[prop] += 1
def countTic(self, prop):
"""
Times a property call, this is the init call.
"""
assert type(prop) is str, 'The property must be a string.'
if prop not in self._timeList:
self._timeList[prop] = []
self._timeList[prop].append(-time.time())
def countToc(self, prop):
"""
Times a property call, this is the end call.
"""
assert type(prop) is str, 'The property must be a string.'
assert prop in self._timeList, 'The property must already be in the dictionary.'
self._timeList[prop][-1] += time.time()
def summary(self):
"""
Provides a text summary of the current counters and timers.
"""
print 'Counters:'
for prop in sorted(self._countList):
print " {0:<40}: {1:8d}".format(prop,self._countList[prop])
print '\nTimes:'+' '*40+'mean sum'
for prop in sorted(self._timeList):
l = len(self._timeList[prop])
a = np.array(self._timeList[prop])
print " {0:<40}: {1:4.2e}, {2:4.2e}, {3:4d}x".format(prop,a.mean(),a.sum(),l)
def count(f):
@wraps(f)
def wrapper(self,*args,**kwargs):
counter = getattr(self,'counter',None)
if type(counter) is Counter: counter.count(self.__class__.__name__+'.'+f.__name__)
out = f(self,*args,**kwargs)
return out
return wrapper
def timeIt(f):
@wraps(f)
def wrapper(self,*args,**kwargs):
counter = getattr(self,'counter',None)
if type(counter) is Counter: counter.countTic(self.__class__.__name__+'.'+f.__name__)
out = f(self,*args,**kwargs)
if type(counter) is Counter: counter.countToc(self.__class__.__name__+'.'+f.__name__)
return out
return wrapper
if __name__ == '__main__':
class MyClass(object):
def __init__(self, url):
self.counter = Counter()
@count
def MyMethod(self):
pass
@timeIt
def MySecondMethod(self):
pass
c = MyClass('blah')
for i in range(100): c.MyMethod()
for i in range(300): c.MySecondMethod()
c.counter.summary()
+3 -303
View File
@@ -1,310 +1,10 @@
from matutils import *
from meshutils import exampleLrmGrid, meshTensors, points2nodes, writeUBCTensorMesh, writeUBCTensorModel, readUBCTensorMesh, readUBCTensorModel
from codeutils import *
from meshutils import exampleLrmGrid, meshTensors, closestPoints, writeUBCTensorMesh, writeUBCTensorModel
from lrmutils import volTetra, faceInfo, indexCube
from interputils import interpmat
from ipythonutils import easyAnimate as animate
from CounterUtils import *
import ModelBuilder
import SolverUtils
import types
import time
import numpy as np
from functools import wraps
class SimPEGMetaClass(type):
def __new__(cls, name, bases, attrs):
return super(SimPEGMetaClass, cls).__new__(cls, name, bases, attrs)
def hook(obj, method, name=None, overwrite=False, silent=False):
"""
This dynamically binds a method to the instance of the class.
If name is None, the name of the method is used.
"""
if name is None:
name = method.__name__
if name == '<lambda>':
raise Exception('Must provide name to hook lambda functions.')
if not hasattr(obj,name) or overwrite:
setattr(obj, name, types.MethodType( method, obj ))
if getattr(obj,'debug',False):
print 'Method '+name+' was added to class.'
elif not silent or getattr(obj,'debug',False):
print 'Method '+name+' was not overwritten.'
def setKwargs(obj, **kwargs):
"""Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist."""
for attr in kwargs:
if hasattr(obj, attr):
setattr(obj, attr, kwargs[attr])
else:
raise Exception('%s attr is not recognized' % attr)
hook(obj,hook, silent=True)
hook(obj,setKwargs, silent=True)
def printTitles(obj, printers, name='Print Titles', pad=''):
titles = ''
widths = 0
for printer in printers:
titles += ('{:^%i}'%printer['width']).format(printer['title']) + ''
widths += printer['width']
print pad + "{0} {1} {0}".format('='*((widths-1-len(name))/2), name)
print pad + titles
print pad + "%s" % '-'*widths
def printLine(obj, printers, pad=''):
values = ''
for printer in printers:
values += ('{:^%i}'%printer['width']).format(printer['format'] % printer['value'](obj))
print pad + values
def checkStoppers(obj, stoppers):
# check stopping rules
optimal = []
critical = []
for stopper in stoppers:
l = stopper['left'](obj)
r = stopper['right'](obj)
if stopper['stopType'] == 'optimal':
optimal.append(l <= r)
if stopper['stopType'] == 'critical':
critical.append(l <= r)
if obj.debug: print 'checkStoppers.optimal: ', optimal
if obj.debug: print 'checkStoppers.critical: ', critical
return (len(optimal)>0 and all(optimal)) | (len(critical)>0 and any(critical))
def printStoppers(obj, stoppers, pad='', stop='STOP!', done='DONE!'):
print pad + "%s%s%s" % ('-'*25,stop,'-'*25)
for stopper in stoppers:
l = stopper['left'](obj)
r = stopper['right'](obj)
print pad + stopper['str'] % (l<=r,l,r)
print pad + "%s%s%s" % ('-'*25,done,'-'*25)
def callHooks(match, mainFirst=False):
"""
Use this to wrap a funciton::
@callHooks('doEndIteration')
def doEndIteration(self):
pass
This will call everything named _doEndIteration* at the beginning of the function call.
By default the master method (doEndIteration) is run after all of the sub methods (_doEndIteration*).
This can be reversed by adding the mainFirst=True kwarg.
"""
def callHooksWrap(f):
@wraps(f)
def wrapper(self,*args,**kwargs):
if not mainFirst:
for method in [posible for posible in dir(self) if ('_'+match) in posible]:
if getattr(self,'debug',False): print (match+' is calling self.'+method)
getattr(self,method)(*args, **kwargs)
return f(self,*args,**kwargs)
else:
out = f(self,*args,**kwargs)
for method in [posible for posible in dir(self) if ('_'+match) in posible]:
if getattr(self,'debug',False): print (match+' is calling self.'+method)
getattr(self,method)(*args, **kwargs)
return out
extra = """
If you have things that also need to run in the method %s, you can create a method::
def _%s*(self, ... ):
pass
Where the * can be any string. If present, _%s* will be called at the start of the default %s call.
You may also completely overwrite this function.
""" % (match, match, match, match)
doc = wrapper.__doc__
wrapper.__doc__ = ('' if doc is None else doc) + extra
return wrapper
return callHooksWrap
def dependentProperty(name, value, children, doc):
def fget(self): return getattr(self,name,value)
def fset(self, val):
if isScalar(val) and getattr(self,name,value) == val:
return # it is the same!
for child in children:
if hasattr(self, child):
delattr(self, child)
setattr(self, name, val)
return property(fget=fget, fset=fset, doc=doc)
def asArray_N_x_Dim(pts, dim):
if type(pts) == list:
pts = np.array(pts)
assert type(pts) == np.ndarray, "pts must be a numpy array"
if dim > 1:
pts = np.atleast_2d(pts)
elif len(pts.shape) == 1:
pts = pts[:,np.newaxis]
assert pts.shape[1] == dim, "pts must be a column vector of shape (nPts, %d) not (%d, %d)" % ((dim,)+pts.shape)
return pts
def requires(var):
"""
Use this to wrap a funciton::
@requires('prob')
def dpred(self):
pass
This wrapper will ensure that a problem has been bound to the data.
If a problem is not bound an Exception will be raised, and an nice error message printed.
"""
def requiresVar(f):
if var is 'prob':
extra = """
.. note::
To use survey.%s(), SimPEG requires that a problem be bound to the survey.
If a problem has not been bound, an Exception will be raised.
To bind a problem to the Data object::
survey.pair(myProblem)
""" % f.__name__
else:
extra = """
To use *%s* method, SimPEG requires that the %s be specified.
""" % (f.__name__, var)
@wraps(f)
def requiresVarWrapper(self,*args,**kwargs):
if getattr(self, var, None) is None:
raise Exception(extra)
return f(self,*args,**kwargs)
doc = requiresVarWrapper.__doc__
requiresVarWrapper.__doc__ = ('' if doc is None else doc) + extra
return requiresVarWrapper
return requiresVar
class Counter(object):
"""
Counter allows anything that calls it to record iterations and
timings in a simple way.
Also has plotting functions that allow quick recalls of data.
If you want to use this, import *count* or *timeIt* and use them as decorators on class methods.
::
class MyClass(object):
def __init__(self, url):
self.counter = Counter()
@count
def MyMethod(self):
pass
@timeIt
def MySecondMethod(self):
pass
c = MyClass('blah')
for i in range(100): c.MyMethod()
for i in range(300): c.MySecondMethod()
c.counter.summary()
"""
def __init__(self):
self._countList = {}
self._timeList = {}
def count(self, prop):
"""
Increases the count of the property.
"""
assert type(prop) is str, 'The property must be a string.'
if prop not in self._countList:
self._countList[prop] = 0
self._countList[prop] += 1
def countTic(self, prop):
"""
Times a property call, this is the init call.
"""
assert type(prop) is str, 'The property must be a string.'
if prop not in self._timeList:
self._timeList[prop] = []
self._timeList[prop].append(-time.time())
def countToc(self, prop):
"""
Times a property call, this is the end call.
"""
assert type(prop) is str, 'The property must be a string.'
assert prop in self._timeList, 'The property must already be in the dictionary.'
self._timeList[prop][-1] += time.time()
def summary(self):
"""
Provides a text summary of the current counters and timers.
"""
print 'Counters:'
for prop in sorted(self._countList):
print " {0:<40}: {1:8d}".format(prop,self._countList[prop])
print '\nTimes:'+' '*40+'mean sum'
for prop in sorted(self._timeList):
l = len(self._timeList[prop])
a = np.array(self._timeList[prop])
print " {0:<40}: {1:4.2e}, {2:4.2e}, {3:4d}x".format(prop,a.mean(),a.sum(),l)
def count(f):
@wraps(f)
def wrapper(self,*args,**kwargs):
counter = getattr(self,'counter',None)
if type(counter) is Counter: counter.count(self.__class__.__name__+'.'+f.__name__)
out = f(self,*args,**kwargs)
return out
return wrapper
def timeIt(f):
@wraps(f)
def wrapper(self,*args,**kwargs):
counter = getattr(self,'counter',None)
if type(counter) is Counter: counter.countTic(self.__class__.__name__+'.'+f.__name__)
out = f(self,*args,**kwargs)
if type(counter) is Counter: counter.countToc(self.__class__.__name__+'.'+f.__name__)
return out
return wrapper
if __name__ == '__main__':
class MyClass(object):
def __init__(self, url):
self.counter = Counter()
@count
def MyMethod(self):
pass
@timeIt
def MySecondMethod(self):
pass
c = MyClass('blah')
for i in range(100): c.MyMethod()
for i in range(300): c.MySecondMethod()
c.counter.summary()
+199
View File
@@ -0,0 +1,199 @@
import types
import time
import numpy as np
from functools import wraps
class SimPEGMetaClass(type):
def __new__(cls, name, bases, attrs):
return super(SimPEGMetaClass, cls).__new__(cls, name, bases, attrs)
def hook(obj, method, name=None, overwrite=False, silent=False):
"""
This dynamically binds a method to the instance of the class.
If name is None, the name of the method is used.
"""
if name is None:
name = method.__name__
if name == '<lambda>':
raise Exception('Must provide name to hook lambda functions.')
if not hasattr(obj,name) or overwrite:
setattr(obj, name, types.MethodType( method, obj ))
if getattr(obj,'debug',False):
print 'Method '+name+' was added to class.'
elif not silent or getattr(obj,'debug',False):
print 'Method '+name+' was not overwritten.'
def setKwargs(obj, **kwargs):
"""Sets key word arguments (kwargs) that are present in the object, throw an error if they don't exist."""
for attr in kwargs:
if hasattr(obj, attr):
setattr(obj, attr, kwargs[attr])
else:
raise Exception('%s attr is not recognized' % attr)
hook(obj,hook, silent=True)
hook(obj,setKwargs, silent=True)
def printTitles(obj, printers, name='Print Titles', pad=''):
titles = ''
widths = 0
for printer in printers:
titles += ('{:^%i}'%printer['width']).format(printer['title']) + ''
widths += printer['width']
print pad + "{0} {1} {0}".format('='*((widths-1-len(name))/2), name)
print pad + titles
print pad + "%s" % '-'*widths
def printLine(obj, printers, pad=''):
values = ''
for printer in printers:
values += ('{:^%i}'%printer['width']).format(printer['format'] % printer['value'](obj))
print pad + values
def checkStoppers(obj, stoppers):
# check stopping rules
optimal = []
critical = []
for stopper in stoppers:
l = stopper['left'](obj)
r = stopper['right'](obj)
if stopper['stopType'] == 'optimal':
optimal.append(l <= r)
if stopper['stopType'] == 'critical':
critical.append(l <= r)
if obj.debug: print 'checkStoppers.optimal: ', optimal
if obj.debug: print 'checkStoppers.critical: ', critical
return (len(optimal)>0 and all(optimal)) | (len(critical)>0 and any(critical))
def printStoppers(obj, stoppers, pad='', stop='STOP!', done='DONE!'):
print pad + "%s%s%s" % ('-'*25,stop,'-'*25)
for stopper in stoppers:
l = stopper['left'](obj)
r = stopper['right'](obj)
print pad + stopper['str'] % (l<=r,l,r)
print pad + "%s%s%s" % ('-'*25,done,'-'*25)
def callHooks(match, mainFirst=False):
"""
Use this to wrap a funciton::
@callHooks('doEndIteration')
def doEndIteration(self):
pass
This will call everything named _doEndIteration* at the beginning of the function call.
By default the master method (doEndIteration) is run after all of the sub methods (_doEndIteration*).
This can be reversed by adding the mainFirst=True kwarg.
"""
def callHooksWrap(f):
@wraps(f)
def wrapper(self,*args,**kwargs):
if not mainFirst:
for method in [posible for posible in dir(self) if ('_'+match) in posible]:
if getattr(self,'debug',False): print (match+' is calling self.'+method)
getattr(self,method)(*args, **kwargs)
return f(self,*args,**kwargs)
else:
out = f(self,*args,**kwargs)
for method in [posible for posible in dir(self) if ('_'+match) in posible]:
if getattr(self,'debug',False): print (match+' is calling self.'+method)
getattr(self,method)(*args, **kwargs)
return out
extra = """
If you have things that also need to run in the method %s, you can create a method::
def _%s*(self, ... ):
pass
Where the * can be any string. If present, _%s* will be called at the start of the default %s call.
You may also completely overwrite this function.
""" % (match, match, match, match)
doc = wrapper.__doc__
wrapper.__doc__ = ('' if doc is None else doc) + extra
return wrapper
return callHooksWrap
def dependentProperty(name, value, children, doc):
def fget(self): return getattr(self,name,value)
def fset(self, val):
if isScalar(val) and getattr(self,name,value) == val:
return # it is the same!
for child in children:
if hasattr(self, child):
delattr(self, child)
setattr(self, name, val)
return property(fget=fget, fset=fset, doc=doc)
def isScalar(f):
scalarTypes = [float, int, long, np.float_, np.int_]
if type(f) in scalarTypes:
return True
elif type(f) == np.ndarray and f.size == 1 and type(f[0]) in scalarTypes:
return True
return False
def asArray_N_x_Dim(pts, dim):
if type(pts) == list:
pts = np.array(pts)
assert type(pts) == np.ndarray, "pts must be a numpy array"
if dim > 1:
pts = np.atleast_2d(pts)
elif len(pts.shape) == 1:
pts = pts[:,np.newaxis]
assert pts.shape[1] == dim, "pts must be a column vector of shape (nPts, %d) not (%d, %d)" % ((dim,)+pts.shape)
return pts
def requires(var):
"""
Use this to wrap a funciton::
@requires('prob')
def dpred(self):
pass
This wrapper will ensure that a problem has been bound to the data.
If a problem is not bound an Exception will be raised, and an nice error message printed.
"""
def requiresVar(f):
if var is 'prob':
extra = """
.. note::
To use survey.%s(), SimPEG requires that a problem be bound to the survey.
If a problem has not been bound, an Exception will be raised.
To bind a problem to the Data object::
survey.pair(myProblem)
""" % f.__name__
else:
extra = """
To use *%s* method, SimPEG requires that the %s be specified.
""" % (f.__name__, var)
@wraps(f)
def requiresVarWrapper(self,*args,**kwargs):
if getattr(self, var, None) is None:
raise Exception(extra)
return f(self,*args,**kwargs)
doc = requiresVarWrapper.__doc__
requiresVarWrapper.__doc__ = ('' if doc is None else doc) + extra
return requiresVarWrapper
return requiresVar
+1 -8
View File
@@ -1,15 +1,8 @@
import numpy as np
import scipy.sparse as sp
from codeutils import isScalar
def isScalar(f):
scalarTypes = [float, int, long, np.float_, np.int_]
if type(f) in scalarTypes:
return True
elif type(f) == np.ndarray and f.size == 1 and type(f[0]) in scalarTypes:
return True
return False
def mkvc(x, numDims=1):
"""Creates a vector with the number of dimension specified
+8 -9
View File
@@ -1,6 +1,7 @@
import numpy as np
from scipy import sparse as sp
from matutils import mkvc, ndgrid, sub2ind, sdiag
from codeutils import asArray_N_x_Dim
def exampleLrmGrid(nC, exType):
assert type(nC) == list, "nC must be a list containing the number of nodes"
@@ -52,25 +53,23 @@ def meshTensors(*args):
return list(tensors) if len(tensors) > 1 else tensors[0]
def points2nodes(mesh, pts):
def closestPoints(mesh, pts, gridLoc='CC'):
"""
Move a list of the nearest nodes to a set of points
Move a list of points to the closest points on a grid.
:param simpeg.Mesh.TensorMesh mesh: The mesh
:param simpeg.Mesh.BaseMesh mesh: The mesh
:param numpy.ndarray pts: Points to move
:param string gridLoc: ['CC', 'N', 'Fx', 'Fy', 'Fz', 'Ex', 'Ex', 'Ey', 'Ez']
:rtype: numpy.ndarray
:return: nodeInds
"""
pts = np.atleast_2d(pts)
assert mesh._meshType in ['TENSOR', 'CYL']
assert pts.shape[1] == mesh.dim
pts = asArray_N_x_Dim(pts, mesh.dim)
grid = getattr(mesh, 'grid' + gridLoc)
nodeInds = np.empty(pts.shape[0], dtype=int)
for i, pt in enumerate(pts):
nodeInds[i] = ((np.tile(pt, (mesh.gridN.shape[0],1)) - mesh.gridN)**2).sum(axis=1).argmin()
nodeInds[i] = ((np.tile(pt, (grid.shape[0],1)) - grid)**2).sum(axis=1).argmin()
return nodeInds