diff --git a/pymodelfit/__init__.py b/pymodelfit/__init__.py index 322b4ff..4c8059d 100644 --- a/pymodelfit/__init__.py +++ b/pymodelfit/__init__.py @@ -25,5 +25,9 @@ ('' if _bugfix is None else ('.'+str(_bugfix))) + \ ('' if _release else 'dev') -from core import * -from builtins import * #do this to register all the builtins +try: + from core import * + from builtins import * #do this to register all the builtins +except: + from .core import * + from .builtins import * #do this to register all the builtins diff --git a/pymodelfit/builtins.py b/pymodelfit/builtins.py index f269d88..c05f448 100644 --- a/pymodelfit/builtins.py +++ b/pymodelfit/builtins.py @@ -21,8 +21,12 @@ import numpy as np #from core import * #includes pi -from core import ParametricModel,FunctionModel,FunctionModel1DAuto, \ - DatacentricModel1DAuto,FunctionModel2DScalarAuto,register_model +try: + from core import ParametricModel,FunctionModel,FunctionModel1DAuto, \ + DatacentricModel1DAuto,FunctionModel2DScalarAuto,register_model +except: + from .core import ParametricModel,FunctionModel,FunctionModel1DAuto, \ + DatacentricModel1DAuto,FunctionModel2DScalarAuto,register_model from math import e,pi from abc import abstractmethod @@ -1630,7 +1634,11 @@ def plot3d(self,data=np.array([(-1,1),(-1,1),(-1,1)]),n=10, M.mesh(x,y,self([x,y]),**kwargs) if showdata: - from operator import isMappingType + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) if isMappingType(showdata): M.points3d(*data,**showdata) else: @@ -1638,7 +1646,7 @@ def plot3d(self,data=np.array([(-1,1),(-1,1),(-1,1)]),n=10, #register everything in this module from inspect import isclass -for o in locals().values(): +for o in list(locals().values()): if isclass(o) and not o.__name__.startswith('_') and issubclass(o,ParametricModel): if 'FunctionModel' not in o.__name__ and 'CompositeModel' not in o.__name__: register_model(o) diff --git a/pymodelfit/core.py b/pymodelfit/core.py index c291135..30d348c 100644 --- a/pymodelfit/core.py +++ b/pymodelfit/core.py @@ -24,8 +24,12 @@ """ from __future__ import division,with_statement +from collections import Sequence from math import pi import numpy as np +import sys +import collections + try: #requires Python 2.6 from abc import ABCMeta @@ -36,6 +40,26 @@ abstractproperty = property ABCMeta = type +try: + dict.iteritems +except AttributeError: + # Python 3 + basestring = str + + def itervalues(d): + return iter(d.values()) + + def iteritems(d): + return iter(d.items()) +else: + # Python 2 + def itervalues(d): + return d.itervalues() + + def iteritems(d): + return d.iteritems() + + class ModelTypeError(Exception): """ This exception indicates a problem with the value of the input @@ -111,7 +135,8 @@ def _setData(self,val): else: ws = np.array(val[2],copy=False) self._data = (ind,outd,ws) - except TypeError,e: + except TypeError: + e = sys.exc_info()[1] e.args = ('invalid type for model data',) raise data = property(_getData,_setData,doc=""" @@ -331,7 +356,8 @@ def __call__(cls,*args,**kwargs): objkwargs=dict([(k,kwargs.pop(k)) for k in kwargs.keys() if k not in cls._pars]) try: obj = super(AutoParamsMeta,AutoParamsMeta).__call__(cls,**objkwargs) #object __init__ is called here - except TypeError,e: + except TypeError: + e = sys.exc_info()[1] if len(e.args)>0 and 'object.__new__() takes no parameters' == e.args[0]: raise TypeError('invalid parameter in model constructor:'+str(objkwargs.keys())) else: @@ -591,7 +617,12 @@ def fitData(self,x=None,y=None,fixedpars='auto',weights=None,savedata=True, .. seealso:: :meth:`getMCMC` """ from scipy import optimize as opt - from operator import isMappingType + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) + from functools import partial self._fitchi2 = None #clear saved chi-squared if it exists @@ -656,7 +687,11 @@ def fitData(self,x=None,y=None,fixedpars='auto',weights=None,savedata=True, res = fitter(x,y,fixedpars=fixedpars,weights=weights,**kwargs) #ensure that res is at least a tuple with parameters in elem 0 - from operator import isSequenceType + try: + from operator import isSequenceType + except: + def isSequenceType(obj): + return isinstance(obj, Sequence) if len(res)==0 or not isSequenceType(res[0]): res = (res,) @@ -1136,7 +1171,11 @@ def getMCMC(self,x,y,priors={},datamodel=None): """ import pymc - from operator import isSequenceType + try: + from operator import isSequenceType + except: + def isSequenceType(obj): + return isinstance(obj, Sequence) from inspect import getargspec from types import MethodType @@ -1572,9 +1611,9 @@ def inv(self,yval,*args,**kwargs): f = method if kwargs.pop('abs',False): - g = lambda(x):np.abs(self(x)-yval) + g = lambda x:np.abs(self(x)-yval) else: - g = lambda(x):self(x)-yval + g = lambda x:self(x)-yval return f(g,*args,**kwargs) @@ -1783,7 +1822,12 @@ def plot(self,lower=None,upper=None,n=100,clf=True,logplot='',data='auto', `zorder` to 0. """ - from operator import isMappingType + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) + from .utils import mpl_context with mpl_context(clf=clf) as plt: @@ -2516,7 +2560,11 @@ def __init__(self,models,extraparams=None,outputcontraction=None, linear interpolation, this takes the closest value. """ - from operator import isMappingType + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) if len(models)==2 and isMappingType(models[1]): modtype = get_model_class(models[0]) @@ -3208,7 +3256,11 @@ def plot(self,datarange=None,nx=100,ny=100,clf=True,cb=True,data='auto', :except ValueError: if data is not present and `datarange` is None """ - from operator import isMappingType + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) from .utils import mpl_context with mpl_context(clf=clf) as plt: @@ -3284,7 +3336,11 @@ def plot3d(self,datarange=None,nx=100,ny=100,clf=True,cb=True,data='auto',**kwar See :meth:`plot` for meaning of the arguments """ from enthought.mayavi import mlab as M - from operator import isMappingType + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) if data == 'auto': if self.data: @@ -3778,7 +3834,9 @@ def get_model_instance(model,baseclass=None,nvarparams=1,**kwargs): return cls(*args,**kwargs) -def list_models(include=None,exclude=None,baseclass=None,showabstract=False): +def list_models( + include=None, exclude=None, baseclass=None, showabstract=False +): """ Lists the registered model objects in the package, possibly subject to constraints. @@ -3808,17 +3866,23 @@ def list_models(include=None,exclude=None,baseclass=None,showabstract=False): See the :func:`register_model` docstring for examples. """ - from operator import isSequenceType - from inspect import isclass,isabstract + try: + from operator import isSequenceType + except: + def isSequenceType(obj): + return isinstance(obj, Sequence) + from inspect import isclass, isabstract - res = [k for k,c in __model_registry.iteritems() - if (baseclass is None or issubclass(c,baseclass)) - if (showabstract or not isabstract(c))] + res = [ + k for k, c in iteritems(__model_registry) + if (baseclass is None or issubclass(c, baseclass)) + if (showabstract or not isabstract(c)) + ] if include is not None: if exclude is not None: raise TypeError("can't specify both included models and excluded models") - if isinstance(include,basestring): + if isinstance(include, basestring): include = include.split(',') elif not isSequenceType(include): include = [include] diff --git a/pymodelfit/fitgui.py b/pymodelfit/fitgui.py index c0be124..6a8fe52 100644 --- a/pymodelfit/fitgui.py +++ b/pymodelfit/fitgui.py @@ -18,7 +18,11 @@ #TODO: change single select to click-to-do-action from __future__ import division,with_statement +from collections import Sequence import numpy as np +import sys +import collections + try: #this is the old-style import - below is for traits 4.x from enthought.traits.api import HasTraits,Instance,Int,Float,Bool,Button, \ Event,Property,on_trait_change,Array,List, \ @@ -175,8 +179,17 @@ def _updatetraitparams_fired(self): setattr(self,p,getattr(m,p)) self.paramchange = True - def _fitdata_fired(self,new): - from operator import isSequenceType,isMappingType + def _fitdata_fired(self, new): + try: + from operator import isSequenceType + except: + def isSequenceType(obj): + return isinstance(obj, Sequence) + try: + from operator import isMappingType + except: + def isMappingType(x): + return isinstance(x, collections.Mapping) if self.model is not None: if isSequenceType(new) and len(new) == 2: @@ -208,8 +221,8 @@ def _fitdata_fired(self,new): self.model.fitData(**kw) self.updatetraitparams = True self.lastfitfailure = None - except Exception,e: - self.lastfitfailure = e + except Exception: + self.lastfitfailure = sys.exc_info()[1] def _get_modelname(self): if self.model is None: @@ -1060,4 +1073,4 @@ def fit_data(*args,**kwargs): if res: return fg.getModelObject() else: - return None \ No newline at end of file + return None diff --git a/setup.py b/setup.py index b4e4073..fca942e 100755 --- a/setup.py +++ b/setup.py @@ -3,9 +3,23 @@ from __future__ import division,with_statement from glob import glob -from distribute_setup import use_setuptools -use_setuptools() -from setuptools import setup,find_packages +#from distribute_setup import use_setuptools +#use_setuptools() +#from setuptools import setup,find_packages +try: + import pkg_resources + try: + pkg_resources.require("setuptools>=0.6c5") + except pkg_resources.VersionConflict: + from ez_setup import use_setuptools + use_setuptools(version="0.6c5") + from setuptools import setup, Command,find_packages + _have_setuptools = True +except ImportError: + # no setuptools installed + from distutils.core import setup, Command,find_packages + _have_setuptools = False + from distutils.command.build_py import build_py as du_build_py from pymodelfit import version as versionstr @@ -53,5 +67,6 @@ def finalize_options(self): license = 'Apache License 2.0', url='http:http://packages.python.org/PyModelFit/', long_description=descrip, - cmdclass = cmdclassd + cmdclass = cmdclassd, + use_2to3=True ) diff --git a/tests/test_models.py b/tests/test_models.py index 266921f..4c3546f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -2,7 +2,8 @@ from __future__ import division,with_statement import numpy as np from nose import tools -from pymodelfit import core,builtins +from pymodelfit import core, builtins + def test_1d_model_funcs(): for modname in core.list_models(baseclass=core.FunctionModel1D): @@ -13,36 +14,59 @@ def test_1d_model_funcs(): if core.get_model_class(modname).isVarnumModel(): #just try it w/ 3 variable arguments w/ default values mod = cls(3,) - mod = core.get_model_instance(modname,nvarparams=3) + mod = core.get_model_instance(modname, nvarparams=3) else: mod = cls() mod = core.get_model_instance(modname) if mod.rangehint is None: x1 = 0 - x2 = 01 + x2 = 1 else: - x1,x2 = mod.rangehint + x1, x2 = mod.rangehint - avgval = mod((x1+x2)/2) #single value output - rangevals = mod(np.linspace(x1,x2,12)[1:-1]) #array output - - assert np.all(np.isfinite(avgval)),'Non-finite value encountered for model '+modname - assert np.all(np.isfinite(rangevals)),'Non-finite value encountered for model '+modname + avgval = mod((x1+x2)/2) # single value output + rangevals = mod(np.linspace(x1, x2, 12)[1:-1]) # array output + assert np.all( + np.isfinite(avgval) + ), 'Non-finite value encountered for model ' + modname + + assert np.all( + np.isfinite(rangevals) + ), 'Non-finite value encountered for model ' + modname + + def test_scale_off(): - m1 = core.scale_and_offset_model(builtins.LinearModel(2.5,1),scaleval=3,offsetval=-2.1) + m1 = core.scale_and_offset_model( + builtins.LinearModel(2.5, 1), scaleval=3, offsetval=-2.1 + ) shouldval = 8.4 - tools.assert_almost_equal(m1(1),shouldval,msg='Scale and Offset of model not giving correct answer: %g,%g'%(m1(1),shouldval)) + tools.assert_almost_equal( + m1(1), shouldval, + msg='Scale and Offset of model not giving correct answer: %g,%g' % ( + m1(1), shouldval) + ) - m2 = core.offset_model(builtins.PowerLawModel(1.2,3),offsetval=2) + m2 = core.offset_model(builtins.PowerLawModel(1.2, 3), offsetval=2) shouldval = 1.2*2**3+2 - tools.assert_almost_equal(m2(2),shouldval,msg='Offset of model not giving correct answer: %g,%g'%(m2(2),shouldval)) + tools.assert_almost_equal( + m2(2), shouldval, + msg='Offset of model not giving correct answer: %g,%g' % ( + m2(2), shouldval) + ) - m3 = core.scale_model(builtins.PolynomialModel(3,c0=0,c1=2.1,c2=-3.5),scaleval=1.3) + m3 = core.scale_model( + builtins.PolynomialModel(3, c0=0, c1=2.1, c2=-3.5), scaleval=1.3 + ) shouldval = 1.3*(2.1*3-3.5*3**2) - tools.assert_almost_equal(m3(3),shouldval,msg='Scale of model not giving correct answer: %g,%g'%(m3(3),shouldval)) - + tools.assert_almost_equal( + m3(3), shouldval, + msg='Scale of model not giving correct answer: %g,%g' % ( + m3(3), shouldval) + ) + + if __name__ == '__main__': import nose nose.main()