diffpy/pyfullprof/utilfunction.py
def checkFileExistence(filename):
    """
    check whether a file does exist in the designated location

    filename:  file name
    """
    try:
        cfile = open(filename, 'r')
        cfile.close()
    except IOError, err:
        print "File << %-20s >> Do NOT Exist:  %-30s"% (filename, err)
        return False

    return True
diffpy/pyfullprof/infoclass.py
class FloatInfo(ParameterInfo):
    """FloatInfo desribes a float paramter or a float parameter list.
    
    Data members that are inherited from ParameterInfo:
    
    name, description, default, unit, min, max, minsize, maxsize
    """
    def __init__(self, name, description, default, unit='', min=None, max=None, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        unit        -- the unit of the parameter
        min         -- the minimal value (None means unlimited)
        max         -- the maximal value (None means unlimited)
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        """
        ParameterInfo.__init__(self, name, description, default, unit, min, max, minsize, maxsize)

        return


    def fromStr(self, s):
        """Translate the value from a string or a unicode string.
        
        s    -- a string or a unicode string
        return: a value 
        """
        return self.convert(float(s))
        

    def convert(self, value):
        """Validate the type of the value and convert the value.
        
        value -- a value to be checked
        
        return: the converted value
        raise: ValueError if the value has the wrong type or it is not in the range.
        """
        if not isinstance(value, float) and not isinstance(value, int)\
           and not isinstance(value, long):
            raise ValueError("'%s' expects a'float', but a '%s'=%s is received."%
                            (self.name, type(value), str(value)))
        if ((self.min is not None and value < self.min) or 
            (self.max is not None and value > self.max) ):
            raise ValueError("'%s' receives a value %f out of range (%s, %s)."%
                            (self.name, value, str(self.min), str(self.max)))
                            
        return float(value)
diffpy/pyfullprof/utilfunction.py
def verifyType(value, type, classinstance=None):
    """
    check whether a value is of a certain type

    classinstance   --  an instance of a class has such value
    value           --  a value
    type            --  a built-in data or a class instance
    """
    errortype = False

    if not isinstance(value, type):
        errortype = True

        # an exception for 'float'
        if type == float:
            if isinstance(value, int):
                errortype = False

    if errortype:
        if classinstance is not None:
            estring = classinstance.__class__.__name__
        else:
            estring = ""
        estring += ":  "+str(value)+" is not required type "+str(type)
        raise NotImplementedError(estring)

    return True
diffpy/pyfullprof/infoclass.py
class BoolInfo(ParameterInfo):
    """BoolInfo desribes a bool paramter or a bool parameter list.
    
    Data members that are inherited from ParameterInfo:
    
    name, description, default, minsize, maxsize
    """
    def __init__(self, name, description, default, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        """
        ParameterInfo.__init__(self, name, description, default, minsize=minsize, maxsize=maxsize)
        return


    def fromStr(self, s):
        """Translate the value from a string or a unicode string.
        
        s    -- a string or a unicode string
        return: a value 
        """
        return self.convert(bool(s))
        
        
    def convert(self, value):
        """Validate the type of the value and convert the value.
        
        value -- a value to be checked
        
        return: the converted value
        raise: ValueError if the object has the wrong type
        """
        if not isinstance(value, (numpy.bool_, bool)):
            raise ValueError("'%s' expects an 'bool', but a '%s' is received."%
                            (self.name, type(value)))
        return bool(value)
diffpy/pyfullprof/refine.py
class Refine(BaseClass):
    """
    Refine is a special ensemble container for Constraints and Variables
    """
    ParamDict = {}
    ObjectDict = {}
    ObjectListDict = {
        "Variable":     ObjectInfo("Variable"  , "Variable", 0, None),
    }

    def __init__(self, Parent):
        """
        initialzation
        """
        BaseClass.__init__(self, Parent) 
        self.constraints = []
        return


    def __str__(self):
        """
        print a Refine object;
        override BaseClass.__str__()
        """
        index_num=0
        s  = "+++++++++++++++this is start of Refine++++++++++++++\n"
        s += "Constraints to Refine:\n"
        for constraint in self.constraints:
            if constraint.variable is not None:
                s += ("["+str(index_num)+"]"+str(constraint)+"\n")
                index_num+=1

        s += "\nConstraints NOT to Refine:\n"
        for constraint in self.constraints:
            if constraint.variable is None:
                s += "["+str(index_num)+"]"+str(constraint)+"\n"
                index_num+=1

        s += "\nVariables:\tNumber = " + str(len(self.get("Variable"))) + "\n"
        for variable in self.get("Variable"):
            s += "Name : " + str(variable.get("name")) + "\t\tvalue = " + str(variable.get("value")) + "\n"
            s += "\tconstraints:  + number = " + str(len(variable.constraints)) + "\n"
            for constraint in variable.constraints:
                s += "\t" + constraint.name + "\t\t" + constraint.formula + "\n"
            

        return s
        

    def findVariable(self, name):
        """find a variable by its name 

        name -- the variable name
        
        return: a Variable instance or None
        """
        for object in self.get("Variable"):
            if name == object.get("name"):
                return object

        # Not found
        return None
diffpy/pyfullprof/exception.py
class RietError(RietException):
    """
    rietError is all the standard error usually indicating 
    that there must be something wrong in the python scripts

    Attributes:
    - message:  error message provided from code
    - errortyp: reason for error (standarized)
    """
    def __init__(self, message, errortype="Standard Error", errorId = ""):
        """
        initialization
        """
        RietException.__init__(self, message, errortype, errorId)
        
        return
diffpy/pyfullprof/infoclass.py
class ObjectInfo:
    """ObjectInfo describes a BaseClass object or an object list.
    
    Data member:
    name        -- the name of the parameter
    classtype   -- the base class name of this object
    minsize     -- for an object list, it is the minimal number of objects
    maxsize     -- for an object list, it is the maximal number of objects
    
    The current naming scheme requires that the name of a derived class has to 
    start with the name of its base class. This is used to check the validity.
    """
    def __init__(self, name, classtype, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        classtype   -- the base class name of this object
        minsize     -- for an object list, it is the minimal number of objects
        maxsize     -- for an object list, it is the maximal number of objects
        """
        # check the argument validity
        if minsize is not None and minsize < 0:
            raise ValueError("%s '%s' receives an invalide minsize(%i)."
                            %(self.__class__.__name__, name, minsize))
        if maxsize is not None and maxsize < 0:
            raise ValueError("%s '%s' receives an invalide maxsize(%i)."
                            %(self.__class__.__name__, name, maxsize))
        if minsize is not None and maxsize is not None and minsize > maxsize:
            raise ValueError("%s '%s' receives a minsize(%i) that is greater than the maxsize(%i)."
                            %(self.__class__.__name__, name, minsize, maxsize))
        self.name      = name
        self.classtype = classtype
        self.minsize   = minsize
        self.maxsize   = maxsize
    
        return


    def __str__(self):
        """Form a string representation.
        
        return: a string.
        """
        s =  "name:           " + self.name + "\n"
        s += "type:           " + self.classtype + "\n"
        
        if self.minsize != 1 or self.maxsize != 1:
            # it is a list
            s += "range of size:  (%i,%i)"%(self.minsize, self.maxsize) + "\n"

        return s


    def validate(self, obj):
        """Validate the object type.
        
        obj -- object reference
        raise: ValueError if the object has the wrong type.
        """
        classname = obj.__class__.__name__
        if not classname.startswith(self.classtype):
            raise ValueError("%s '%s' expects a '%s', but a '%s' is received."
                            %(self.__class__.__name__, self.name, self.classtype, classname))
        
        return
diffpy/pyfullprof/infoclass.py
class EnumInfo(ParameterInfo):
    """EnumInfo desribes an enumerate paramter or an enumerate parameter list.
    
    Data members that are inherited from ParameterInfo:
    
    name, description, default, minsize, maxsize
    
    Data members that are new:
    
    rangedict: a dictionary that translate a value to a string
    """
    def __init__(self, name, description, default, rangedict, rangelist=None, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        rangedict   -- a dictionary that translate a value to a string
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        """
        #FIXME: rangelist is not in use, but there are too much hard coded code using this arg.
        # for validate.
        self.rangedict = rangedict
        
        ParameterInfo.__init__(self, name, description, default, minsize=minsize, maxsize=maxsize)
        
        return


    def fromStr(self, s):
        """Translate the value from a string or a unicode string.
        
        s    -- a string or a unicode string
        return: a value 
        """
        return self.convert(int(s))
        

    def convert(self, value):
        """Validate the type of the value and convert the value.
        
        value -- a value to be checked
        
        return: the converted value
        raise: ValueError if the value is not in the list of values
        """
        if not self.rangedict.has_key(value):
            raise ValueError("'%s' can only take a value in '%s', but '%s' is received."%
                            (self.name, str(self.rangedict.keys()),  str(value)))
        
        return value


    def getValueStr(self, value):
        """Get the value name.
        
        return: a string
        """
        return self.rangedict[value]
diffpy/pyfullprof/infoclass.py
class StringInfo(ParameterInfo):
    """StringInfo describes an ascii string parameter or a ascii string parameter list.
    
    Data members that are inherited from FloatInfo:
    
    name, description, default, minsize, maxsize
    
    Data members that are new:
    
    fixlen -- the fixed length measured in bytes
    """
    def __init__(self, name, description, default, fixlen=None, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        """
        # self.fixlen is needed by ParameterInfo.__init__ which calls convert
        self.fixlen = fixlen
        
        ParameterInfo.__init__(self, name, description, default, minsize=minsize, maxsize=maxsize)
        
        return


    def fromStr(self, s):
        """Translate the value from a string or a unicode string.
        
        s    -- a string or a unicode string
        return: a value 
        """
        return self.convert(s)
        

    def convert(self, value):
        """Validate the type of the value and convert the value.
        
        value -- a value to be checked
        
        return: the converted value
        raise: ValueError if the object has the wrong type
        """
        if isinstance(value, unicode):
            # encode using ascii, an error will be thrown in case it is not an ascii.
            value = value.encode()
        elif not isinstance(value, str):
            raise ValueError("'%s' expects a 'str', but a '%s'=%s is received"%
                            (self.name, type(value), repr(value)))


        if self.fixlen and len(value) != self.fixlen:
            raise ValueError("'%s' receives a value '%s' does not match the length."%
                                (self.name, repr(value)) )

        return value
diffpy/pyfullprof/infoclass.py
class RefineInfo(FloatInfo):
    """RefineInfo describes a refinable parameter or a refinable parameter list.
    
    Data members that are inherited from FloatInfo:
    
    name, description, default, unit, min, max, minsize, maxsize

    Data members that are new:
    
    damping
    """
    def __init__(self, name, description, default, damping=0.0, unit='', min=None, max=None, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        unit        -- the unit of the parameter
        min         -- the minimal value (None means unlimited)
        max         -- the maximal value (None means unlimited)
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        damping     -- the damping 
        """
        FloatInfo.__init__(self, name, description, default, unit, min, max, minsize, maxsize)
        self.damping = damping
        return
diffpy/pyfullprof/infoclass.py
class ParameterInfo:
    """ParameterInfo desribes a paramter or a parameter list.
    
    Data member:
    name        -- the name of the parameter
    description -- the detailed description of the parameter
    default     -- the default value for the parameter
    unit        -- the unit of the parameter
    min         -- the minimal value (None means unlimited)
    max         -- the maximal value (None means unlimited)
    minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
    maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
    """
    def __init__(self, name, description, default, unit='', min=None, max=None, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        unit        -- the unit of the parameter
        min         -- the minimal value (None means unlimited)
        max         -- the maximal value (None means unlimited)
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        """
        # check the argument validity
        if minsize is not None and minsize < 0:
            raise ValueError("%s '%s' receives an invalide minsize(%i)."
                            %(self.__class__.__name__, name, minsize))
        if maxsize is not None and maxsize < 0:
            raise ValueError("%s '%s' receives an invalide maxsize(%i)."
                            %(self.__class__.__name__, name, maxsize))
        if minsize is not None and maxsize is not None and minsize > maxsize:
            raise ValueError("%s '%s' receives a minsize(%i) that is greater than the maxsize(%i)."
                            %(self.__class__.__name__, name, minsize, maxsize))
        if min is not None and max is not None and min>max:
            raise ValueError("%s '%s' receives a min(%) that is greater than the max(%s)."
                            %(self.__class__.__name__, name, str(min), str(max)))
                            
        self.name        = name
        self.description = description
        self.unit        = unit
        self.min         = min
        self.max         = max
        self.minsize     = minsize
        self.maxsize     = maxsize

        # convert value in the end.
        self.default     = self.convert(default)

        return


    def __str__(self):
        """Form a string representation.
        
        return: a string
        """
        s =  "name:           " + self.name + "\n"
        s += "description:    " + self.description + "\n"
        s += "type:           " + type(self.default) + "\n"
        s += "default:        " + str(self.default)  + "\n"
        if self.unit:
            s += "unit:           " + self.unit + "\n"
        if self.minsize is not None or self.max is not None:
            # it has min and max value
            s += "range of value: (%s, %s)"%(str(self.minsize), str(self.maxsize)) + "\n"
        if self.minsize != 1 or self.maxsize != 1:
            # it is a list
            s += "range of size:  (%i, %i)"%(self.minsize, self.maxsize) + "\n"
        return s


    def fromStr(self, s):
        """Translate the value from a string or a unicode string.
        
        s    -- a string or a unicode string
        return: a value 
        """
        return s
        

    def convert(self, value):
        """Validate the type of the value and convert the value.
        
        value -- a value to be checked
        
        return: the converted value
        raise: ValueError if the object has the wrong type
        """
        # By default, a parameter can take any value
        return value
diffpy/pyfullprof/infoclass.py
class IntInfo(ParameterInfo):
    """IntInfo desribes an int paramter or an int parameter list.
    
    Data members that are inherited from ParameterInfo:
    
    name, description, default, unit, min, max, minsize, maxsize
    """
    def __init__(self, name, description, default, min=None, max=None, minsize=1, maxsize=1):
        """Initialization.
        
        name        -- the name of the parameter
        description -- the detailed description of the parameter
        default     -- the default value for the parameter
        unit        -- the unit of the parameter
        min         -- the minimal value (None means unlimited)
        max         -- the maximal value (None means unlimited)
        minsize     -- the minimal number of parameters in a parameter list (None means unlimited)
        maxsize     -- the maximal number of parameters in a parameter list (None means unlimited)
        """
        # except for unit, it matches the ParameterInfo arguments, set unit=''
        ParameterInfo.__init__(self, name, description, default, '', min, max, minsize, maxsize)

        return


    def fromStr(self, s):
        """Translate the value from a string or a unicode string.
        
        s    -- a string or a unicode string
        return: a value 
        """
        return self.convert(int(s))
        

    def convert(self, value):
        """Validate the type of the value and convert the value.
        
        value -- a value to be checked
        
        return: the converted value
        raise: ValueError if the object has the wrong type
        """
        if not isinstance(value, int) and not isinstance(value, long):
            raise ValueError("'%s' expects an 'int', but a '%s'=%s is received."%
                            (self.name, type(value), str(value)))
        if ( (self.min is not None and value < self.min) or
             (self.max is not None and value > self.max) ):
            raise ValueError("'%s' receives a value %i out of range (%i, %i)"%
                            (self.name, value, self.min, self.max))
        return int(value)
diffpy/pyfullprof/rietveldclass.py
class RietveldClass(BaseClass):
    """RietveldClass extends BaseClass, and serves as the base class for all
    classes designed for Rietveld refinement.
    
    Data members:
    
    constraints -- a dictionary stores mapping from (name,index) to constarint.
    """
    def __init__(self, parent):
        """Initialization.
        """
        BaseClass.__init__(self, parent)
        self.constraints = {}
        return


    def duplicate(self):
        """
        duplicate self object to a exact copy
        (1) parameter...(copy)
        (2) subclass... (copy)
        (3) container... (copy)

        For Constraint object, only the pattern_range, phase_range and parname are copied;
        No link to Refine is established!

        scenario    --  After duplicate() and the corresponding linking work by Rietveld.set()
                        method 'RietveldClass.linkConstraint()' is always called

        return  --  the new generated twin object
        """
        try:
            newobject = self.__class__(None)
        except TypeError, err:
            errmsg  = "RietveldClass.duplicate():  instantiated as %-20s\n"%(self.__class__.__name__)
            errmsg += str(err)
            raise RietError(errmsg)

        for param_name in self.ParamDict.keys():
            #newobject.__dict__[param_name] = self.__dict__[param_name].duplicate()
            paramobj = self.get(param_name)
            if not isinstance(paramobj, Constraint):
                newobject.set(param_name, paramobj)
            else:
                newobject.set(param_name, paramobj.copy())

        for classtype in self.ObjectDict.keys():
            subobject = self.ObjectDict[classtype].get("name")
            newobject.__dict__[subobject] = self.__dict__[subobject].duplicate(self)

        for classtype in self.ObjectListDict.keys():
            subcontainer = self.ObjectListDict[classtype].get("name")
            newobject.__dict__[subcontainer] = self.__dict__[subcontainer].duplicate(self)

        return newobject


    def extend(self, baseobj):
        """
        extend a base-object to 'self', and replace base-object with 'self' in 
        Rietveld-class hierachy
        baseobj = base object
        """

        def class_in_list(classname, classnamelist):
            """
            identify whether a class_name is one in classnamelist
            class_name can be extended class while the name in classnamelist is base class
            classname -
            classnamelist -
            """
            for basename in classnamelist:
                if classname.count(basename) == 1:
                    return True
            
            return False


        def getClassName(classname, classnamelist):
            """
            if classname is an extended class name, then return the base class name

            class_name can be extended class while the name in classnamelist is base class
            classname -
            classnamelist -
            """
            for basename in classnamelist:
                if classname.count(basename) == 1:
                    return basename
           
            raise RietError, "rietveldclass.extend - getClassName"
            return

        from diffpy.pyfullprof.contribution import Contribution
        if isinstance(baseobj, Contribution):
            errmsg = "Contribution should extend this function because of its dual parent"
            raise RietError(errmsg)

        # 1 check
        if not isinstance(self, baseobj.__class__):
            return False

        # 2 copy
        for name in baseobj.ParamDict.keys():
            self.__dict__[name] = baseobj.__dict__[name]
        
        for name in baseobj.ParamListDict.keys():
            for i in range(len(baseobj.__dict__[name])):
                self.__dict__[name].set(baseobj.__dict__[name].get(i))

        for name in baseobj.ObjectDict.keys():
            self.__dict__[name] = baseobj.__dict__[name]
            # set parent
            self.__dict__[name].parent = self
            self.__dict__[name].parent = self
        
        for name in baseobj.ObjectListDict.keys():
            self.__dict__[name] = baseobj.__dict__[name]
            # set parent
            self.__dict__[name].parent = self
            for objref in self.get(name):
                objref.parent = self

        # 3 find and set parent
        parentobj = baseobj.parent
        self.parent = parentobj

        # 4 replace from the parent class view
        # if baseobj.__class__.__name__ in parentobj.ObjectDict.keys():
        if class_in_list(baseobj.__class__.__name__, parentobj.ObjectDict.keys()):
            classname = getClassName(baseobj.__class__.__name__, parentobj.ObjectDict.keys())
            parentobj.set(classname, self)
        # elif baseobj.__class__.__name__ in parentobj.ObjectListDict.keys():
        elif class_in_list(baseobj.__class__.__name__, parentobj.ObjectListDict.keys()):
            classname = getClassName(baseobj.__class__.__name__, parentobj.ObjectListDict.keys())
            for i,obj in enumerate(parentobj.get(classname)):
                if baseobj == obj:
                    parentobj.set(classname, self, i)
                    break
            else:
                raise RietError("RietveldClass.extend(): Can not find the ")
        else:
            print "base obj:\t" + baseobj.__class__.__name__
            print "parent obj:\t" + str(parentobj.ObjectDict.keys())
            raise RietError("RietveldClass.extend(): Parent Class Cannot Locate Object")

        return True


    def clear(self):
        """Clear myself completely.
        """
        for constraint in self.constraints.values():
            constraint.clear()
            
        self.constraints = {}
        
        
    def getFit(self):
        """Get the owner Fit instance.
        
        return: a Fit instance
        """
        from diffpy.pyfullprof.fit import Fit
        root = self
        while not isinstance(root,  Fit):
            root = root.parent
            if root is None:
                return None
                
        return root


    def set(self, name, value, index=None):
        """Set the value for a member and link constraints.
        
        name  --  a key in ParamDict, ObjectDict or ObjectListDict
        value --  the value/object to be set
        index --  only for ObjectListDict object, to give the location of the object
        """
        BaseClass.set(self, name, value, index)
        #NOTE: linkConstraint is quite useless, becaue if the constraint is set
        #      before a refine is assigned to it, an exception is thrown.
        #      It is only useful when a RietveldClass object is set to another Fit.
        if isinstance(value, RietveldClass) and self.getFit() is not None:
            value.linkConstraint()

        return


    def linkConstraint(self):
        """Link all the constraints to the fit object.
        called after duplicate() when a new-object is added to the Fit regime

        refine:  Refine object 
        """
        from diffpy.pyfullprof.fit import Fit
        if isinstance(self, Fit):
            _fit = self
        else:
            _fit = self.getFit()
        if _fit:
            refine = _fit.get("Refine")
        else:
            # Should not happen, this is checked in the "set" function
            # which is the only one calling this function.
            raise RietError("No Fit is created.")
        
        for constraint in self.constraints.values():
            constraint.refine = refine
            constraint.apply()
        
        for name in self.ObjectDict.keys():
            o = self.__dict__[name]
            if o: # it may be None
                o.linkConstraint()
                        
        for name in self.ObjectListDict.keys():
            for o in self.__dict__[name]._list:
                o.linkConstraint()

        return
    
    
    def _checkNameIndex(self, name, index):
        """check the validity of the name and index passed to set/get/remove constraints
        
        name   -- the parameter name
        index -- the index in the parameter list  
      
        raise: RietError if name or index is not right.
        """  
        if self.ParamDict.has_key(name):
            if index is not None:
                raise RietError('The parameter "%s" is not a list.'%name)
            return
            
        
        if self.ParamListDict.has_key(name):
            if not isinstance(index, int):
                raise RietError('The parameter list needs an int for index, but "%s"=%s is received.' 
                                %(type(index), str(index)))
                                
            return
    
        # otherwise, there is no key.
        raise RietError("Class %s does not have a  parameter or parameter list: %s"%(
                  self.__class__.__name__, name) )
        
        return
        

    def setConstraintByPath(self, path, formula, value=None, damping=None, varIndex=None):
        """Constrain a parameter by path

        path  -- a full path,  e.g., x.y.z[i].a
        formula -- a formula to be applied to the parameter
        value   -- the initial value of the constrained parameter.
        damping -- damping    
        varIndex -- if it is not None, append it to the formula; if the path 
                    corresponds to multiple parameters, varIndex will increase
                    by one for each parameter. 
 
        return: the newly created constraint object
        """
        if path.count('.') > 0:
            try:
                objpath,paramname = path.rsplit('.',1)
            except:
                raise RietError('Invalid format for a parameter name: ' + path)

            objects = self.getByPath(objpath)

            # There are multiple objects
            if isinstance(objects,  list):
                constraints = []
                for i, object in enumerate(objects):
                    _constraints = object.setConstraintByPath(paramname, formula, 
                                                           value, damping, varIndex)
                    # Append results to the result constraint list,
                    # and increase the varIndex accordingly if it is not None.
                    if isinstance(_constraints, list):
                        constraints.extend(_constraints)
                        if varIndex is not None:
                            varIndex += len(_constraints)
                    else:
                        constraints.append(_constraints)
                        if varIndex is not None:
                            varIndex += 1
                return constraints

            # else it is a single object
            return objects.setConstraintByPath(paramname, formula, value, damping, varIndex)

        name, index = self._parseIndex(path)
        
        # If index is a slice, we need set constraint one by one
        if isinstance(index, slice):
            constraints = []
            indices = self._rangeParam(name, index)
            for i in indices:
                if varIndex is not None:
                    _formula = formula+'%i'%(varIndex+i)
                else:
                    _formula = formula
                constraints.append(
                   self.setConstraint(name, _formula, value, damping, index=i))                
            return constraints
                
        
        # else the index is an int or None
        if varIndex is not None:
            formula = formula + '%i'%varIndex
        return self.setConstraint(name, formula, value=value, damping=damping, index=index)


    def setConstraint(self, name, formula, value=None, damping=None, index=None):
        """Constrain a parameter to a formula

        name   -- the parameter name
        formula -- the formula that the parameter to be constrained to
        value   -- the initial value of the constrained parameter.
        damping -- damping       
        index -- the index in the parameter list 
        
        return: the newly created constraint object
        """
        self._checkNameIndex(name, index)
        constraint = Constraint(name,self,formula,value=value,damping=damping, index=index)
        constraint.codeWord=damping
        constraint.realvalue=value
        try:
            oldconstraint = self.constraints[(name, index)]
            oldconstraint.clear()
        except KeyError:
            pass
            
        self.constraints[(name, index)] = constraint
        return constraint
                
    def setConstraint(self, name, formula, tpcowdWord,value=None, damping=None, index=None):
        """Constrain a parameter to a formula

        name   -- the parameter name
        formula -- the formula that the parameter to be constrained to
        value   -- the initial value of the constrained parameter.
        damping -- damping       
        index -- the index in the parameter list 
        
        return: the newly created constraint object
        """
        self._checkNameIndex(name, index)
        constraint = Constraint(name,self,formula,value=value,damping=damping, index=index)
        constraint.codeWord=tpcowdWord
        constraint.realvalue=value
        try:
            oldconstraint = self.constraints[(name, index)]
            oldconstraint.clear()
        except KeyError:
            pass
            
        self.constraints[(name, index)] = constraint
        return constraint
    def getConstraint(self,  name,  index=None):
        """Get a constraint by name.
        
        name -- a parameter name in ParamDict
        index -- the index in the parameter list 
        
        return: a constraint object
        """
        self._checkNameIndex(name, index)
        try:
            return self.constraints[(name, index)]
        except KeyError:
            return None
            
            
    def getConstraintByPath(self, path):
        """Get a constraint by path
        
        path -- a full path,  e.g., x.y.z[i].a
        return: a constraint object
        """
        if path.count('.') > 0:
            try:
                objpath,paramname = path.rsplit('.',1)
            except:
                raise RietError('Invalid format for a parameter name: ' + path)

            objects = self.getByPath(objpath)
            if isinstance(objects,  list):
                constraints = []
                for object in objects:
                    _constraints=object.getConstraintByPath(paramname)
                    if isinstance(_constraints, list):
                        constraints.extend(_constraints)
                    else:
                        constraints.append(_constraints)   
                return constraints
            
            # else it is a single object
            return objects.getConstraintByPath(paramname)

        name, index = self._parseIndex(path)
        
        # If index is a slice, we need get constraint one by one 
        if isinstance(index, slice):
            constraints = []
            indices = self._rangeParam(name, index)
            for i in indices:
                constraints.append(self.getConstraint(name, i))
            return constraints
        
        # else the index is an int or None
        return self.getConstraint(name, index)
        
        
    def removeConstraint(self, name, index=None):
        """Remove a constraint by name.
        
        name -- a parameter name in ParamDict
        index -- the parameter index in the parameter list
        """
        self._checkNameIndex(name, index)
        try:
            constraint = self.constraints[(name, index)]
            constraint.clear()
            
            del self.constraints[(name, index)]
        except KeyError:
            pass
            
        return constraint


Question: import os
import glob
import shutil
        import diffpy.pyfullprof.runfullprof as FpEngine
        import diffpy.pyfullprof.fpoutputfileparsers as FPP     
        import diffpy.pyfullprof.runfullprof as FpEngine
from diffpy.pyfullprof.refine import Refine
from diffpy.pyfullprof.rietveldclass import RietveldClass
from diffpy.pyfullprof.utilfunction import verifyType
from diffpy.pyfullprof.infoclass import ParameterInfo
from diffpy.pyfullprof.infoclass import BoolInfo
from diffpy.pyfullprof.infoclass import EnumInfo
from diffpy.pyfullprof.infoclass import FloatInfo
from diffpy.pyfullprof.infoclass import IntInfo
from diffpy.pyfullprof.infoclass import RefineInfo
from diffpy.pyfullprof.infoclass import StringInfo
from diffpy.pyfullprof.infoclass import ObjectInfo
from diffpy.pyfullprof.utilfunction import checkFileExistence
from diffpy.pyfullprof.exception import RietError
        from diffpy.pyfullprof.pattern import Pattern
        from diffpy.pyfullprof.phase import Phase
        from diffpy.pyfullprof.contribution import Contribution
        """
        initialization: add a new Fit, and create the refine object belonged to this fit object
        """
        RietveldClass.__init__(self, parent)

        # init refine
        refineobj = Refine(None)
        self.set("Refine", refineobj)

        # bank information:  This is for some specific pattern data such as ".gss" with different bank
        self.banklist = []
        
        # internal data
        self.key = ''
        self._param_indices = {}
        self.updateParamIndices(self._param_indices)

        return

    def __str__(self):
        """
        customerized output
        """
        rstring  = ""

        rstring += RietveldClass.__str__(self)

        return rstring


    def getContribution(self, p1, p2):
        """
        get the contribution by pattern and phase
        p1: pattern/phase
        p2: phase/pattern

        return  --  (1) Contribution
                    (2) None if not exist
        """

        phase   = None
        pattern = None
        if isinstance(p1, Pattern) and isinstance(p2, Phase):
            pattern = p1
            phase   = p2
        elif isinstance(p1, Phase) and isinstance(p2, Pattern):
            pattern = p2
            phase   = p1
        else:
            raise NotImplementedError, "fit.getContribution:  p1 and p2 must be phase and pattern or pattern and phase"

        contributionlist = self.get("Contribution")
        for contribution in contributionlist:
            if contribution._ParentPhase == phase and contribution._ParentPattern == pattern:
                return contribution

        # if return will be None, then print out some debugging information
        if 0:
            contributionlist = self.get("Contribution")
            dbmsg  = "pyfullprof.core.Fit.getContribution():  Cannot Find a Matching Contribution!\n"
            dbmsg += "%-20s: Phase -- %-30s   Pattern -- %-30s\n"%("Input", repr(phase), repr(pattern)) 
            counts = 0
            for contribution in contributionlist:
                addrphase   = repr(contribution._ParentPhase)
                addrpattern = repr(contribution._ParentPattern)
                dbmsg += "%-20s: Phase -- %-30s  Pattern -- %-30s\n"%("Contribution "+str(counts), addrphase, addrpattern)
                counts += 1
            print dbmsg
        
        return None


   
    def getParamList(self):
        return self.Refine.constraints

    def updateFit(self, newfit):
        """Update self with the new fit, which is the resultant Fit instance.
        
        newfit --   an instance of Fit
        """
        # update Chi^2
        for paramname in self.ParamDict:
            self.set(paramname, newfit.get(paramname)) 
        for constraint in self.get("Refine").constraints[:]:
            if constraint.on:
                path = constraint.path
                val = newfit.getByPath(path)
                self.setByPath(path, val)
                
                #FIXME: it is a get-around of the engine bug
                newconstraint = newfit.getConstraintByPath(path)
                if newconstraint is not None:
                    constraint.sigma = newconstraint.sigma
                    
        for constraint in self.get("Refine").constraints[:]:
            print "                    %-10s    %-15s    %-15.6f+/- %-11.6f" \
            % ( constraint.name, constraint.varName, constraint.getValue(), 
                constraint.sigma)
        print "\n"
        return


    def validate(self, mode="Refine"):
        """
        validate the parameters, subclass and container to meet the refinement requirement

        Arguments
        - mode  :  string, validate mode, (Refine, Calculate)

        Return  :  Boolean 
        """
        rvalue = RietveldClass.validate(self)
        errmsg = ""

        # I. Synchronization of FulProf Parameter & Check Data File Existence
        for pattern in self.get("Pattern"):

            # 2.1 data file existence
            if mode == "Refine":

Answer:                 exist = checkFileExistence(pattern.get("Datafile"))