Source code for symfit.core.argument
import os
import sys
import inspect
from sympy.core.symbol import Symbol
try: # This defines the basestring in both py2/py3.
basestring
except NameError:
basestring = str
[docs]class Argument(Symbol):
"""
Base class for ``symfit`` symbols. This helps make ``symfit`` symbols distinguishable from ``sympy`` symbols.
The ``Argument`` class also makes DRY possible in defining ``Argument``'s: it uses ``inspect`` to read the lhs of the
assignment and uses that as the name for the ``Argument`` is none is explicitly set.
For example::
x = Variable()
print(x.name)
>> 'x'
"""
def __new__(cls, name=None, **assumptions):
assumptions['real'] = True
# Super dirty way? to determine the variable name from the calling line.
if not name or not isinstance(name, basestring):
frame, filename, line_number, function_name, lines, index = inspect.stack()[1]
# Check if the script is running in an exe
# If this is the case, symfit cannot find the vaiable name from the calling line and it will search
# in the exe directory to find the source. Make sure to copy the required source files for this to work.
if getattr(sys, 'frozen', False):
basedir = sys._MEIPASS # Find the exe base dir
fname = os.path.basename(filename)
# Find the source file in the pyinstaller directory
source_file = None
for root, dirs, files in os.walk(basedir):
if fname in files:
source_file = os.path.join(root, fname)
break
if source_file is None:
raise IOError("Source code file not found")
# Get the correct line from the source code
l = 0
with open(source_file, 'r') as fid:
for line in fid:
l+=1
if l == line_number:
lines = line
caller = lines[0].strip()
if '==' in caller:
pass
else:
try:
terms = caller.split('=')
except ValueError:
generated_name = name
else:
generated_name = terms[0].strip() # lhs
return super(Argument, cls).__new__(cls, generated_name, **assumptions)
return super(Argument,cls).__new__(cls, name, **assumptions)
def __init__(self, name=None, **assumptions):
# TODO: A more careful look at Symbol.__init__ is needed! However, it
# seems we don't have to pass anything on to it.
if name is not None:
self.name = name
super(Argument, self).__init__()
[docs]class Parameter(Argument):
""" Parameter objects are used to facilitate bounds on function parameters. """
[docs] def __init__(self, value=1.0, min=None, max=None, fixed=False, name=None, **assumptions):
"""
:param value: Initial guess value.
:param min: Lower bound on the parameter value.
:param max: Upper bound on the parameter value.
:param fixed: Fix the parameter to ``value`` during fitting.
:type fixed: bool
:param name: Name of the Parameter.
:param assumptions: assumptions to pass to ``sympy``.
"""
super(Parameter, self).__init__(name, **assumptions)
self.value = value
self.fixed = fixed
if not self.fixed:
self.min = min
self.max = max
[docs]class Variable(Argument):
""" Variable type."""
pass