Пример #1
0
 def set_center(self, center):
     """
     Sets center value.
     
     :Parameters:
        #. center (dict): The center value dictionary. Must have a single key and this can only be 'fixed' or 'indexes'.
           If key is fixed, value must be a list or a numpy.array of a point coordinates such as [X,Y,Z]
           If key is indexes, value must be a list or a numpy array of indexes.
     """
     assert isinstance(center, dict), LOGGER.error("center must be a dictionary")
     assert len(center) == 1, LOGGER.error("center must have a single key")       
     key = center.keys()[0]
     val = center[key]
     assert isinstance(val, (list,set,tuple,np.ndarray)), LOGGER.error("center value must be a list")
     if isinstance(val, np.ndarray):
         assert len(val.shape) == 1, LOGGER.error("center value must have a single dimension")
     assert len(val)>0, LOGGER.error("center value must be a non-zero list.")
     for v in val:
         assert is_number(v), LOGGER.error("center value item must be numbers") 
     if key == "fixed":
         self.__mustCompute = False
         assert len(val) == 3, LOGGER.error("fixed center must have exactly 3 elements corresponding to X,Y and Z coordinates of the center point.")
         val = np.array([FLOAT_TYPE(v) for v in val], dtype=FLOAT_TYPE)
     elif key == "indexes":
         self.__mustCompute = True
         for v in val:
             assert is_integer(v), LOGGER.error("indexes center items be integers")
         val =  np.array([INT_TYPE(v) for v in val], dtype=INT_TYPE)
         for v in val:
             assert v>=0, LOGGER.error("indexes center items be positive integers")            
     else:
         self.__mustCompute = None
         raise Exception(LOGGER.error("center key must be either 'fixed' or 'indexes'"))        
     # set center
     self.__center = {key:val}
Пример #2
0
 def compute_chi_square(self, data):
     """ 
     Compute the chi square of data not satisfying constraint conditions. 
     
     :Parameters:
         #. data (numpy.array): The constraint value data to compute chiSquare.
         
     :Returns:
         #. chiSquare (number): The calculated chiSquare multiplied by the contribution factor of the constraint.
     """
     # compute difference
     chiSquare = 0.0
     number = 0
     for k, val in data.items():
         if val < PRECISION:
             continue
         number += 1
         el1, el2 = k.split("intermd_")[1].split("-")
         dist = self.__pairsDistance[el1][el2]
         diff = dist-val
         assert diff>0 , LOGGER.error("difference must be positive. %.6f is found for val:%.6f and minimumDistance: %.6f. Try recomputing constraint data using 'compute_data' method"%(diff, val, dist))
         assert diff<=dist, LOGGER.error("difference must be smaller than minimum distance. %.6f is found for val:%.6f and minimumDistance: %.6f .Try recomputing constraint data using 'compute_data' method"%(diff, val, dist))
         # normalize to make it between 0 and 1
         chiSquare += (diff/dist)**2
     # normalize
     #if number:
     #    chiSquare /= number
     return FLOAT_TYPE(chiSquare)
Пример #3
0
 def _set_fitted_scale_factor_value(self, scaleFactor):
     """
     This method is a scaleFactor value without any validity checking.
     Meant to be used internally only.
     """
     if self.__scaleFactor != scaleFactor:
         LOGGER.info("Experimental constraint '%s' scale factor updated from %.6f to %.6f" %(self.__class__.__name__, self.__scaleFactor, scaleFactor))
         self.__scaleFactor = scaleFactor
 def export(self, fname, format='%12.5f', delimiter=' ', comments='# '):
     """
     Export pair distribution constraint.
     
     :Parameters:
         #. fname (path): full file name and path.
         #. format (string): string format to export the data.
            format is as follows (%[flag]width[.precision]specifier)
         #. delimiter (string): String or character separating columns.
         #. comments (string): String that will be prepended to the header.
     """
     # get constraint value
     output = self.get_constraint_value()
     if not len(output):
         LOGGER.warn("%s constraint data are not computed." %
                     (self.__class__.__name__))
         return
     # start creating header and data
     header = [
         "distances",
     ]
     data = [
         self.experimentalDistances,
     ]
     # add all intra data
     for key, val in output.items():
         if "inter" in key:
             continue
         header.append(key.replace(" ", "_"))
         data.append(val)
     # add all inter data
     for key, val in output.items():
         if "intra" in key:
             continue
         header.append(key.replace(" ", "_"))
         data.append(val)
     # add total
     header.append("total")
     data.append(output["pcf"])
     if self.windowFunction is not None:
         header.append("total_no_window")
         data.append(output["pcf_total"])
     if self._shapeArray is not None:
         header.append("shape_function")
         data.append(self._shapeArray)
     # add experimental data
     header.append("experimental")
     data.append(self.experimentalPDF)
     # create array and export
     data = np.transpose(data).astype(float)
     # save
     np.savetxt(fname=fname,
                X=data,
                fmt=format,
                delimiter=delimiter,
                header=" ".join(header),
                comments=comments)
Пример #5
0
 def _runtime_initialize(self):
     """
     Automatically sets the selector order at the engine runtime.
     """
     assert self.engine is not None, LOGGER.error("engine must be set prior to calling _runtime_initialize")
     if self.__order is None:
         self.__order = np.array(range(len(self.engine.groups)), dtype=INT_TYPE)
         self.__initialize_selector__()
     else:
         assert max(self.__order) < len(self.engine.groups), LOGGER.error("Groups in engine are modified, must re-set GroupSelector order using set_order method")
 def set_weighting(self, weighting):
     """
     Sets elements weighting. It must a valid entry of pdbParser atoms database
     
     :Parameters:
         #. weighting (string): The elements weighting.
     """
     assert is_element_property(weighting),LOGGER.error( "weighting is not a valid pdbParser atoms database entry")
     assert weighting != "atomicFormFactor", LOGGER.error("atomicFormFactor weighting is not allowed")
     self.__weighting = weighting
Пример #7
0
 def _runtime_initialize(self):
     """   
     Automatically check the groups weight
     """
     assert self.engine is not None, LOGGER.error(
         "engine must be set prior to calling _runtime_initialize")
     if len(self._selectionScheme) != len(self.engine.groups):
         raise LOGGER.error(
             "Groups are modified, must set GroupSelector weights using set_weights method"
         )
Пример #8
0
 def set_angle(self, angle):
     """
     Sets the tolerance maximum angle.
     
     :Parameters:
         #. angle (number): The maximum tolerance angle in degrees between a generated translation vector and the pre-defined axis.        
     """
     assert is_number(angle), LOGGER.error("angle must be numbers")
     assert angle > 0, LOGGER.error("angle must be positive")
     assert angle <= 360, LOGGER.error("angle must be smaller than 360")
     self.__angle = FLOAT_TYPE(angle) * PI / FLOAT_TYPE(180.)
Пример #9
0
 def _set_maximum_standard_error(self, maximumStandardError):
     """ Sets the maximum standard error. Use carefully, it's not meant to be used externally.
     maximum squared deviation is what is used to compute the ratio and compare to thresholdRatio.
     """
     if (maximumStandardError is not None) and maximumStandardError:
         assert is_number(maximumStandardError), LOGGER.error("maximumStandardError must be a number.")
         maximumStandardError = FLOAT_TYPE(maximumStandardError)
         assert maximumStandardError>0, LOGGER.error("maximumStandardError must be a positive.")
     self.__maximumStandardError = maximumStandardError
     # dump to repository
     self._dump_to_repository({'_QuasiRigidConstraint__maximumStandardError': self.__maximumStandardError})
Пример #10
0
 def set_angle(self, angle):
     """
     Sets the tolerance maximum angle.
     
     :Parameters:
         #. angle (number): The maximum tolerance angle in degrees between a generated translation vector and the pre-defined axis.        
     """
     assert is_number(angle), LOGGER.error("angle must be numbers")
     assert angle>0, LOGGER.error("angle must be positive")
     assert angle<=360, LOGGER.error("angle must be smaller than 360")
     self.__angle = FLOAT_TYPE(angle)*PI/FLOAT_TYPE(180.)
Пример #11
0
 def set_variance_squared(self, value):
     """
     Sets constraint's variance squared that is used in the computation of the total engine chi square.
     
     :Parameters:
         #. value (number): Any positive non zero number.
     """
     assert is_number(value), LOGGER.error("accepted value must be convertible to a number")
     value = float(value)
     assert value>0 , LOGGER.error("Variance must be positive non zero number.")
     self.__varianceSquared = value
 def get_constraint_original_value(self):
     """
     Compute all partial Pair Distribution Functions (PDFs). 
     
     :Returns:
         #. PDFs (dictionary): The PDFs dictionnary, where keys are the element wise intra and inter molecular PDFs and values are the computed PDFs.
     """
     if self.originalData is None:
         LOGGER.warn("originalData must be computed first using 'compute_data' method.")
         return {}
     return self._get_constraint_value(self.originalData)
Пример #13
0
 def set_amplitude(self, amplitude):
     """
     Sets maximum translation vector allowed amplitude.
     
     :Parameters:
         #. amplitude (number): the maximum allowed translation vector amplitude.
     """
     assert is_number(amplitude), LOGGER.error("Translation amplitude must be a number")
     amplitude = float(amplitude)
     assert amplitude>0, LOGGER.error("Translation amplitude must be bigger than 0")
     self.__amplitude = FLOAT_TYPE(amplitude)
Пример #14
0
 def set_default_minimum_distance(self, defaultMinDistance):
     """ 
     Sets the default intermolecular minimum distance. 
     
     :Parameters:
         #. defaultMinDistance (number): The default minimum distance.
     """
     assert is_number(defaultMinDistance), LOGGER.error("defaultMinDistance must be a number")
     defaultMinDistance = FLOAT_TYPE(defaultMinDistance)
     assert defaultMinDistance>=0, LOGGER.error("defaultMinDistance must be positive")
     self.__defaultMinDistance = defaultMinDistance
Пример #15
0
 def set_amplitude(self, amplitude):
     """
     Sets maximum allowed agitation rotation angle amplitude in degrees of left and right atoms separately and transforms it to rad.
     
     :Parameters:
         #. amplitude (number):  The maximum agitation angle amplitude in degrees of left and right atoms separately.
     """
     assert is_number(amplitude), LOGGER.error("Agitation angle amplitude must be a number")
     amplitude = float(amplitude)
     assert amplitude>0, LOGGER.error("Agitation angle amplitude must be bigger than 0")
     assert amplitude<=90, LOGGER.error("Agitation angle amplitude must be smaller than 90")
     self.__amplitude = FLOAT_TYPE(amplitude*PI/180.)
    def get_constraint_value(self):
        """
        Get constraint's data dictionary value.

        :Returns:
            #. data (dictionary): Constraint's data dictionary.
        """
        if self.data is None:
            LOGGER.warn(
                "data must be computed first using 'compute_data' method.")
            return {}
        return self._get_constraint_value(self.data)
 def get_constraint_value(self):
     """
     Compute all partial Pair Distribution Functions (PDFs). 
     
     :Returns:
         #. PDFs (dictionary): The PDFs dictionnary, where keys are the element wise intra and inter molecular PDFs and values are the computed PDFs.
     """
     if self.data is None:
         LOGGER.warn(
             "data must be computed first using 'compute_data' method.")
         return {}
     return self._get_constraint_value(self.data)
Пример #18
0
 def set_amplitude(self, amplitude):
     """
     Sets maximum translation vector allowed amplitude.
     
     :Parameters:
         #. amplitude (number): the maximum allowed translation vector amplitude.
     """
     assert is_number(amplitude), LOGGER.error(
         "Translation amplitude must be a number")
     amplitude = float(amplitude)
     assert amplitude > 0, LOGGER.error(
         "Translation amplitude must be bigger than 0")
     self.__amplitude = FLOAT_TYPE(amplitude)
Пример #19
0
 def set_bias_factor(self, biasFactor):
     """
     Set the biasing factor.
 
     :Parameters:
         #. biasFactor (Number): The biasing factor of every group when a step get accepted.
            Must be a positive number.
     """
     assert is_number(biasFactor), LOGGER.error(
         "biasFactor must be a number")
     biasFactor = FLOAT_TYPE(biasFactor)
     assert biasFactor >= 0, LOGGER.error("biasFactor must be positive")
     self.__biasFactor = biasFactor
Пример #20
0
 def set_maximum_offset_angle(self, maximumOffsetAngle):
     """
     Sets the maximum offset angle allowed.
     
     :Parameters:
         #. maximumOffsetAngle (number): The maximum offset angle in degrees between groupAxis and orientationAxis in degrees.
     """
     assert is_number(maximumOffsetAngle), LOGGER.error("maximumOffsetAngle must be a number")
     maximumOffsetAngle = float(maximumOffsetAngle)
     assert maximumOffsetAngle>0, LOGGER.error("maximumOffsetAngle must be bigger than 0 deg.")
     assert maximumOffsetAngle<180, LOGGER.error("maximumOffsetAngle must be smaller than 180 deg.")
     # convert to radian and store amplitude
     self.__maximumOffsetAngle = FLOAT_TYPE(PI*maximumOffsetAngle/180.)
Пример #21
0
 def set_recur(self, recur):
     """
     Sets the recur value.
     
     :Parameters:
         #. recur (integer): Set the recur value.
            It must be a positive integer.
     """
     assert is_integer(recur), LOGGER.error("recur must be an integer")
     recur = INT_TYPE(recur)
     assert recur >= 0, LOGGER.error("recur must be positive")
     self.__recur = recur
     self.__recurAsSet = recur
Пример #22
0
 def set_axis(self, axis):
     """
     Sets the symmetry axis index to translate along.
     
     :Parameters:
         #. axis (integer): Must be 0,1 or 2 for respectively the main, secondary or tertiary symmetry axis
     """
     assert is_integer(axis), LOGGER.error("rotation symmetry axis must be an integer.")
     axis = INT_TYPE(axis)
     assert axis>=0, LOGGER.error("rotation symmetry axis must be positive.")
     assert axis<=2, LOGGER.error("rotation symmetry axis must be smaller or equal to 2.")
     # convert to radian and store amplitude
     self.__axis = axis
Пример #23
0
 def set_group(self, group):
     """
     Set the MoveGenerator group.
     
     :Parameters:
         #. group (None, Group): group instance. 
     """
     if group is not None:
         from fullrmc.Core.Group import Group
         assert isinstance(group, Group), LOGGER.error("group must be a fullrmc Group instance")
         valid, message = self.check_group(group)
         if not valid:
             raise Exception( LOGGER.error("%s"%message) )
     self.__group = group
Пример #24
0
def atoms(ENGINE, rang=30, recur=20, refine=False, explore=True):
    ENGINE.set_groups_as_atoms()
    # set selector
    if refine or explore:
        gs = RecursiveGroupSelector(RandomSelector(ENGINE),
                                    recur=recur,
                                    refine=refine,
                                    explore=explore)
        ENGINE.set_group_selector(gs)
    # number of steps
    nsteps = recur * len(ENGINE.groups)
    for stepIdx in range(rang):
        LOGGER.info("Running 'atoms' mode step %i" % (stepIdx))
        ENGINE.run(numberOfSteps=nsteps, saveFrequency=nsteps)
Пример #25
0
 def set_amplitude(self, amplitude):
     """
     Sets maximum rotation angle in degrees and transforms it to rad.
     
     :Parameters:
         #. amplitude (number): the maximum allowed rotation angle in degrees.
            It must be strictly bigger than 0 and strictly smaller than 360.
     """
     assert is_number(amplitude), LOGGER.error("rotation amplitude must be a number")
     amplitude = float(amplitude)
     assert amplitude>0, LOGGER.error("rotation amplitude must be bigger than 0 deg.")
     assert amplitude<360, LOGGER.error("rotation amplitude must be smaller than 360 deg.")
     # convert to radian and store amplitude
     self.__amplitude = FLOAT_TYPE(PI*amplitude/180.)
Пример #26
0
    def set_axis(self, axis):
        """
        Set the symmetry axis index to translate along.

        :Parameters:
            #. axis (integer): Must be 0,1 or 2 for respectively the main,
               secondary or tertiary symmetry axis
        """
        assert is_integer(axis), LOGGER.error("rotation symmetry axis must be an integer.")
        axis = INT_TYPE(axis)
        assert axis>=0, LOGGER.error("rotation symmetry axis must be positive.")
        assert axis<=2, LOGGER.error("rotation symmetry axis must be smaller or equal to 2.")
        # convert to radian and store amplitude
        self.__axis = axis
Пример #27
0
 def set_tried(self, value):
     """
     Sets constraint's engine tried moves.
     
     :Parameters:
         #. value (integer): constraint tried moves value
     """
     try:
         value = float(value)
     except:
         raise Exception(LOGGER.error("tried value must be convertible to a number"))
     assert is_integer(value), LOGGER.error("tried value must be integer")
     assert value>=0, LOGGER.error("tried value must be positive")
     self.__tried = int(value)
Пример #28
0
 def set_axis(self, axis):
     """
     Sets the axis along which the translation will be performed.
     
     :Parameters:
         #. axis (list,set,tuple,numpy.ndarray): The translation axis vector.
     """
     assert isinstance(axis, (list,set,tuple,np.ndarray)), LOGGER.error("axis must be a list")
     axis = list(axis)
     assert len(axis)==3, LOGGER.error("axis list must have 3 items")
     for pos in axis:
         assert is_number(pos), LOGGER.error( "axis items must be numbers")
     axis = [FLOAT_TYPE(pos) for pos in axis]
     axis =  np.array(axis, dtype=FLOAT_TYPE)
     self.__axis = axis/FLOAT_TYPE( np.linalg.norm(axis) )
Пример #29
0
    def set_axis(self, axis):
        """
        Set the axis along which the translation will be performed.

        :Parameters:
            #. axis (list,set,tuple,numpy.ndarray): Translation axis vector.
        """
        assert isinstance(axis, (list,set,tuple,np.ndarray)), LOGGER.error("axis must be a list")
        axis = list(axis)
        assert len(axis)==3, LOGGER.error("axis list must have 3 items")
        for pos in axis:
            assert is_number(pos), LOGGER.error( "axis items must be numbers")
        axis = [FLOAT_TYPE(pos) for pos in axis]
        axis =  np.array(axis, dtype=FLOAT_TYPE)
        self.__axis = axis/FLOAT_TYPE( np.linalg.norm(axis) )
Пример #30
0
 def set_combination(self, combination):
     """
     Sets the generators combination list.
     
     :Parameters:
         #. combination (list): The list of MoveGenerator instances.
     """
     assert isinstance(combination, (list,set,tuple)), LOGGER.error("combination must be a list")
     combination = list(combination)
     for c in combination:
         assert isinstance(c, MoveGenerator), LOGGER.error("every item in combination list must be a MoveGenerator instance")
         assert not isinstance(c, SwapGenerator), LOGGER.error("SwapGenerator is not allowed to be combined")
         assert not isinstance(c, SwapGenerator), LOGGER.error("RemoveGenerator is not allowed to be combined")
         c.set_group(self.group)
     self.__combination = combination
Пример #31
0
def run_atoms(ENGINE, rang=None, recur=None, xyzFrequency=500):
    ENGINE.set_groups(None)
    # set selector
    if recur is None: recur = 10
    ENGINE.set_group_selector(RandomSelector(ENGINE))
    # number of steps
    nsteps = recur * len(ENGINE.groups)
    if rang is None: rang = 20
    for stepIdx in range(rang):
        LOGGER.info("Running 'atoms' mode step %i" % (stepIdx))
        ENGINE.run(numberOfSteps=nsteps,
                   saveFrequency=nsteps,
                   xyzFrequency=xyzFrequency,
                   xyzPath="atomsTraj.xyz",
                   restartPdb=None)
Пример #32
0
 def set_reject_probability(self, rejectProbability):
     """
     Set the rejection probability.
     
     :Parameters:
         #. rejectProbability (Number): rejecting probability of all steps where standardError increases. 
            It must be between 0 and 1 where 1 means rejecting all steps where standardError increases
            and 0 means accepting all steps regardless whether standardError increases or not.
     """
     assert is_number(rejectProbability), LOGGER.error("rejectProbability must be a number")
     rejectProbability = FLOAT_TYPE(rejectProbability)
     assert rejectProbability>=0 and rejectProbability<=1, LOGGER.error("rejectProbability must be between 0 and 1")
     self.__rejectProbability = rejectProbability
     # dump to repository
     self._dump_to_repository({'_RigidConstraint__dataWeights': self.__rejectProbability})
Пример #33
0
 def set_amplitude(self, amplitude):
     """
     Sets maximum allowed agitation rotation angle amplitude in degrees of left and right atoms separately and transforms it to rad.
     
     :Parameters:
         #. amplitude (number):  The maximum agitation angle amplitude in degrees of left and right atoms separately.
     """
     assert is_number(amplitude), LOGGER.error(
         "Agitation angle amplitude must be a number")
     amplitude = float(amplitude)
     assert amplitude > 0, LOGGER.error(
         "Agitation angle amplitude must be bigger than 0")
     assert amplitude <= 90, LOGGER.error(
         "Agitation angle amplitude must be smaller than 90")
     self.__amplitude = FLOAT_TYPE(amplitude * PI / 180.)
Пример #34
0
 def set_agitate(self, agitate):
     """
     Sets agitate tuple value.
     
     :Parameters:
         #. agitate (tuple): It's a tuple of two boolean values, at least one of them must be True.
            Whether to agitate the first atom, the second or both. This is useful to set an atom fixed while only 
            the other succumb the agitation to adjust the distance. For instance in a C-H group it can be useful and 
            logical to adjust the bond length by moving only the hydrogen atom along the bond direction.
     """
     assert isinstance(agitate, (list,tuple)), LOGGER.error("agitate must be a list or a tuple")
     assert len(agitate)==2, LOGGER.error("agitate must have 2 items")
     assert [isinstance(a,bool) for a in agitate]==[True,True], LOGGER.error("agitate items must be boolean")
     assert agitate[0] or agitate[1], LOGGER.error("agitate both items can't be False")
     self.__agitate = (agitate[0], agitate[1])     
Пример #35
0
 def _set_engine(self, engine):
     assert self.__engine is None, LOGGER.error("Re-setting constraint engine is not allowed.")
     from fullrmc.Engine import Engine
     assert isinstance(engine, Engine),LOGGER.error("engine must be a fullrmc Engine instance")
     self.__engine = engine
     # set constraint unique id
     names = [c.constraintId for c in engine.constraints]
     idx = 0
     while True:
         name = self.__class__.__name__ + "_%i"%idx
         if name not in names:
             self.__constraintId = name
             break
         else:
             idx += 1
Пример #36
0
 def set_threshold_ratio(self, thresholdRatio):
     """
     Set the rejection probability function.
     
     :Parameters:
         #. thresholdRatio(Number): The threshold of satisfied data, above which the constraint become free.
            It must be between 0 and 1 where 1 means all data must be satisfied and therefore the constraint
            behave like a RigidConstraint and 0 means none of the data must be satisfied and therefore the
            constraint becomes always free and useless.
     """
     assert is_number(thresholdRatio), LOGGER.error("thresholdRatio must be a number")
     thresholdRatio = FLOAT_TYPE(thresholdRatio)
     assert thresholdRatio>=0 and thresholdRatio<=1, LOGGER.error("thresholdRatio must be between 0 and 1")
     self.__thresholdRatio = thresholdRatio
     # dump to repository
     self._dump_to_repository({'_QuasiRigidConstraint__thresholdRatio': self.__thresholdRatio})
Пример #37
0
 def set_unbias_factor(self, unbiasFactor):
     """
     Set the unbiasing factor.
 
     :Parameters:
         #. unbiasFactor(None, Number): Whether to unbias a group's weight when a move is rejected.
            If None, unbiasing is turned off.
            Unbiasing will be performed only if group weight remains positive.
     """
     if unbiasFactor is not None:
         assert is_number(unbiasFactor), LOGGER.error(
             "unbiasFactor must be a number")
         unbiasFactor = FLOAT_TYPE(unbiasFactor)
         assert unbiasFactor >= 0, LOGGER.error(
             "unbiasFactor must be positive")
     self.__unbiasFactor = unbiasFactor
Пример #38
0
 def set_maximum_collected(self, maximumCollected):
     """
     Set maximum collected number of atoms allowed.
     
     :Parameters:
         #. maximumCollected (None, Integer): The maximum number allowed of atoms to be 
            removed and collected from the engine. This property is general to the 
            system and checks engine's collected atoms not the number of removed atoms 
            via this generator. If None is given, the remover will not check for the
            number of already removed atoms before attempting a remove.
     """
     if maximumCollected is not None:
         assert is_integer(maximumCollected), LOGGER.error("maximumCollected must be an integer")
         maximumCollected = INT_TYPE(maximumCollected)
         assert maximumCollected>0, LOGGER.error("maximumCollected must be bigger than 0")
     self.__maximumCollected = maximumCollected
Пример #39
0
    def get_constraint_value(self):
        """
        Get partial Mean Pair Distances (MPD) below the defined
        minimum distance.

        :Returns:
            #. MPD (dictionary): MPD dictionary, where keys are the
               element wise intra and inter molecular MPDs and values are
               the computed MPDs.
        """
        if self.data is None:
            LOGGER.warn(
                "%s data must be computed first using 'compute_data' method." %
                (self.__class__.__name__))
            return {}
        return self.data
Пример #40
0
 def set_maximum_offset_angle(self, maximumOffsetAngle):
     """
     Sets the maximum offset angle allowed.
     
     :Parameters:
         #. maximumOffsetAngle (number): The maximum offset angle in degrees between groupAxis and orientationAxis in degrees.
     """
     assert is_number(maximumOffsetAngle), LOGGER.error(
         "maximumOffsetAngle must be a number")
     maximumOffsetAngle = float(maximumOffsetAngle)
     assert maximumOffsetAngle > 0, LOGGER.error(
         "maximumOffsetAngle must be bigger than 0 deg.")
     assert maximumOffsetAngle < 180, LOGGER.error(
         "maximumOffsetAngle must be smaller than 180 deg.")
     # convert to radian and store amplitude
     self.__maximumOffsetAngle = FLOAT_TYPE(PI * maximumOffsetAngle / 180.)
Пример #41
0
 def _runtime_initialize(self):
     """   
     Automatically sets the selector order at the engine runtime.
     """
     assert self.engine is not None, LOGGER.error("engine must be set prior to calling _runtime_initialize")
     if self.__order is None:
         self.__order = np.array(range(len(self.engine.groups)), dtype=INT_TYPE)
         self.__initialize_selector__()
 def set_limits(self, limits):
     """
     Set the histogram computation limits.
     
     :Parameters:
         #. limits (None, tuple, list): The distance limits to compute the histograms and compute with the experimental data.
            If None, the limits will be automatically set the the min and max distance recorded in the experimental data.
            If not None, a tuple of minimum distance or None and maximum distance or None should be given.    
     """
     if limits is None:
         self.__limits = (None, None)
     else:
         assert isinstance(limits, (list, tuple)), LOGGER.error("limits must be None or a list")
         limits = list(limits)
         assert len(limits) == 2, LOGGER.error("limits list must have exactly two elements")
         if limits[0] is not None:
             assert is_number(limits[0]), LOGGER.error("if not None, the first limits element must be a number")
             limits[0] = FLOAT_TYPE(limits[0])
             assert is_number(limits[0]), LOGGER.error("if not None, the first limits element must be a positive number")
         if limits[1] is not None:
             assert is_number(limits[1]), LOGGER.error("if not None, the second limits element must be a number")
             limits[1] = FLOAT_TYPE(limits[1])
             assert is_number(limits[1]), LOGGER.error("if not None, the second limits element must be a positive number")
         if  limits[0] is not None and limits[1] is not None:
             assert limits[0]<limits[1], LOGGER.error("if not None, the first limits element must be smaller than the second limits element")
         self.__limits = (limits[0], limits[1])
     # get minimumDistance and maximumDistance indexes
     if self.__limits[0] is None:
         minDistIdx = 0
     else:
         minDistIdx = (np.abs(self.experimentalData[:,0]-self.__limits[0])).argmin()
     if self.__limits[1] is None:
         maxDistIdx = -1
     else:
         maxDistIdx =(np.abs(self.experimentalData[:,0]-self.__limits[1])).argmin()
     # set minimumDistance and maximumDistance 
     self.__minimumDistance = FLOAT_TYPE(self.experimentalData[minDistIdx,0] - self.__bin/2. )
     self.__maximumDistance = FLOAT_TYPE(self.experimentalData[maxDistIdx,0] + self.__bin/2. )
     # get histogram size    
     self.__histogramSize = INT_TYPE((self.__maximumDistance-self.__minimumDistance)/self.__bin)
     # get histogram edges
     self.__edges         = np.array([self.__minimumDistance+idx*self.__bin for idx in xrange(self.__histogramSize+1)], dtype=FLOAT_TYPE)       
     self.__shellsCenter  = (self.__edges[1:]+self.__edges[0:-1])/FLOAT_TYPE(2.)
     self.__shellsVolumes = FLOAT_TYPE(4.0)*PI*self.__shellsCenter*self.__shellsCenter*self.__bin 
     # set limits indexes for range
     if (minDistIdx == -1) or (minDistIdx == self.experimentalData.shape[0]):
         minDistIdx = self.experimentalData.shape[0]
     if (maxDistIdx == -1) or (maxDistIdx == self.experimentalData.shape[0]):
         maxDistIdx = self.experimentalData.shape[0]
     self.__experimentalDistances = self.experimentalData[minDistIdx:maxDistIdx+1,0]
     self.__experimentalPDF       = self.experimentalData[minDistIdx:maxDistIdx+1,1] 
     # check distances and shells
     for diff in self.__shellsCenter-self.__experimentalDistances:
         assert abs(diff)<=PRECISION, LOGGER.error("experimental data distances are not coherent")
     # reset constraint
     self.reset_constraint()
Пример #43
0
 def __setattr__(self, name, value):
     if name in (
             'FRAME_DATA',
             'RUNTIME_DATA',
     ):
         raise LOGGER.error("Setting '%s' is not allowed." % name)
     else:
         object.__setattr__(self, name, value)
Пример #44
0
 def set_angle(self, angle):
     """
     Sets the tolerance maximum angle.
     
     :Parameters:
         #. angle (None, number): The maximum tolerance angle in degrees between a generated translation vector and the computed direction. 
            If None is given, all generated translation vectors will be along the direction to center.        
     """
     if angle is not None:
         assert is_number(angle), LOGGER.error("angle must be numbers")
         assert angle>=0, LOGGER.error("angle must be positive")
         assert angle<=360, LOGGER.error("angle must be smaller than 360")
         if FLOAT_TYPE(angle) == FLOAT_TYPE(0.0):
             angle = None
         else:
             angle = FLOAT_TYPE(angle)*PI/FLOAT_TYPE(180.)
     self.__angle = angle
Пример #45
0
 def set_center(self, center):
     """
     Sets center value.
     
     :Parameters:
         #. center (dict): The center value dictionary. Must have a single key and this can only be 'fixed' or 'indexes'.
            If key is fixed, value must be a list or a numpy.array of a point coordinates such as [X,Y,Z]
            If key is indexes, value must be a list or a numpy array of indexes.
     """
     assert isinstance(center,
                       dict), LOGGER.error("center must be a dictionary")
     assert len(center) == 1, LOGGER.error("center must have a single key")
     key = center.keys()[0]
     val = center[key]
     assert isinstance(
         val, (list, set, tuple,
               np.ndarray)), LOGGER.error("center value must be a list")
     if isinstance(val, np.ndarray):
         assert len(val.shape) == 1, LOGGER.error(
             "center value must have a single dimension")
     assert len(val) > 0, LOGGER.error(
         "center value must be a non-zero list.")
     for v in val:
         assert is_number(v), LOGGER.error(
             "center value item must be numbers")
     if key == "fixed":
         self.__mustCompute = False
         assert len(val) == 3, LOGGER.error(
             "fixed center must have exactly 3 elements corresponding to X,Y and Z coordinates of the center point."
         )
         val = np.array([FLOAT_TYPE(v) for v in val], dtype=FLOAT_TYPE)
     elif key == "indexes":
         self.__mustCompute = True
         for v in val:
             assert is_integer(v), LOGGER.error(
                 "indexes center items be integers")
         val = np.array([INT_TYPE(v) for v in val], dtype=INT_TYPE)
         for v in val:
             assert v >= 0, LOGGER.error(
                 "indexes center items be positive integers")
     else:
         self.__mustCompute = None
         raise Exception(
             LOGGER.error("center key must be either 'fixed' or 'indexes'"))
     # set center
     self.__center = {key: val}
Пример #46
0
 def set_angle(self, angle):
     """
     Sets the tolerance maximum angle.
     
     :Parameters:
         #. angle (None, number): The maximum tolerance angle in degrees between a generated translation vector and the computed direction. 
            If None is given, all generated translation vectors will be along the direction to center.        
     """
     if angle is not None:
         assert is_number(angle), LOGGER.error("angle must be numbers")
         assert angle >= 0, LOGGER.error("angle must be positive")
         assert angle <= 360, LOGGER.error("angle must be smaller than 360")
         if FLOAT_TYPE(angle) == FLOAT_TYPE(0.0):
             angle = None
         else:
             angle = FLOAT_TYPE(angle) * PI / FLOAT_TYPE(180.)
     self.__angle = angle
 def set_scale_factor(self, scaleFactor):
     """
     Sets the scale factor.
     
     :Parameters:
          #. scaleFactor (string): A normalization scale factor used to normalize the computed data to the experimental ones.
     """
     assert is_number(scaleFactor), LOGGER.error("scaleFactor must be a number")
     self.__scaleFactor = FLOAT_TYPE(scaleFactor)
Пример #48
0
 def set_symmetric(self, symmetric):
     """
     Sets symmetric flag value.
     
     :Parameters:
         #. symmetric (bool): Whether to apply the same amplitude of translation on both atoms or not.         
     """
     assert isinstance(symmetric, bool), LOGGER.error("symmetric must be boolean")
     self.__symmetric = symmetric
Пример #49
0
 def set_generators_parameters(self, generatorsParams):
     """
     Set move generators parameters.
     
     #. generatorsParams (None, dict): The automatically created moves generators parameters.
        If None is given, default parameters are used. If a dictionary is given, only two keys are allowed.
        'TG' key is for TranslationTowardsCenterGenerator parameters and 'RG' key is
        for RotationGenerator parameters. TranslationTowardsCenterGenerator amplitude parameter
        is not the same for all groups but intelligently allowing certain groups to move more than
        others according to damping parameter.
        
        **Parameters are the following:**\n
        * TG_amp = generatorsParams['TG']['amplitude']: Used for TranslationTowardsCenterGenerator amplitude parameters.
        * TG_ang = generatorsParams['TG']['angle']: Used as TranslationTowardsCenterGenerator angle parameters.
        * TG_dam = generatorsParams['TG']['damping']: Also used for TranslationTowardsCenterGenerator amplitude parameters.
        * RG_ang = generatorsParams['RG']['amplitude']: Used as RotationGenerator angle parameters.
        
        **Parameters are used as the following:**\n
        * TG = TranslationTowardsCenterGenerator(center={"fixed":center}, amplitude=AMPLITUDE, angle=TG_ang)\n
          Where TG_amp < AMPLITUDE < TG_amp.TG_dam
        * RG = RotationGenerator(amplitude=RG_ang)         
        * MoveGeneratorCollector(collection=[TG,RG], randomize=True)
        
        **NB: The parameters are not checked for errors until engine runtime.** 
     """
     if generatorsParams is None:
         generatorsParams = {}
     assert isinstance(generatorsParams, dict), LOGGER.error("generatorsParams must be a python dictionary")
     newGenParams = {"TG":{"amplitude":0.1, "damping":0.1, "angle":90},
                     "RG":{"amplitude":10}}
     # update  TranslationTowardsCenterGenerator values
     for gkey in newGenParams.keys():
         if not generatorsParams.has_key(gkey):
             continue
         assert isinstance(generatorsParams[gkey], dict), LOGGER.error("generatorsParams value must be a python dictionary")
         for key in newGenParams[gkey].keys():
             newGenParams[gkey][key] = generatorsParams[gkey].get(key, newGenParams[gkey][key])
     # check generatorsParams damping parameters
     assert is_number(generatorsParams["TG"]["damping"]), LOGGER.error("generatorsParams['TG']['damping'] must be a number")
     generatorsParams["TG"]["damping"] = FLOAT_TYPE(generatorsParams["TG"]["damping"])
     assert generatorsParams["TG"]["damping"]>=0, LOGGER.error("generatorsParams['TG']['damping'] must be bigger than 0")
     assert generatorsParams["TG"]["damping"]<=1, LOGGER.error("generatorsParams['TG']['damping'] must be smaller than 1")
     # set generatorsParams
     self.__generatorsParams = newGenParams   
 def set_window_function(self, windowFunction):
     """
     Sets the window function.
     
     :Parameters:
          #. windowFunction (None, numpy.ndarray): The window function to convolute with the computed pair distribution function
             of the system prior to comparing it with the experimental data. In general, the experimental pair
             distribution function G(r) shows artificial wrinkles, among others the main reason is because G(r) is computed
             by applying a sine Fourier transform to the experimental structure factor S(q). Therefore window function is
             used to best imitate the numerical artefacts in the experimental data.
     """
     if windowFunction is not None:
         assert isinstance(windowFunction, np.ndarray), LOGGER.error("windowFunction must be a numpy.ndarray")
         assert windowFunction.dtype.type is FLOAT_TYPE, LOGGER.error("windowFunction type must be %s"%FLOAT_TYPE)
         assert len(windowFunction.shape) == 1, LOGGER.error("experimentalData must be of dimension 2")
         # normalize window function
         windowFunction /= np.sum(windowFunction)
     # set windowFunction
     self.__windowFunction = windowFunction
Пример #51
0
 def set_expand(self, expand): 
     """
     Set expand.
     
     :Parameters:
         #. expand (bool): Whether to set the order from the the further to the closest 
            or from the closest to the further if it is set to False.   
     """  
     assert isinstance(expand, bool), LOGGER.error("expand must be boolean")
     self.__expand = expand
Пример #52
0
 def set_type_definition(self, typeDefinition, pairsLimitsDefinition=None):
     """
     Its an alias to set_pairs_limits with pairsLimits argument passed as the already defined pairsLimitsDefinitions
     """
     # set typeDefinition
     assert typeDefinition in ("name", "element"), LOGGER.error("typeDefinition must be either 'name' or 'element'")
     if self.engine is None:
         self.__types                = None
         self.__allTypes             = None
         self.__numberOfTypes        = None
         self.__typesIndexes         = None
         self.__numberOfAtomsPerType = None
     elif typeDefinition == "name":
         self.__types                = self.engine.names
         self.__allTypes             = self.engine.allNames
         self.__numberOfTypes        = self.engine.numberOfNames
         self.__typesIndexes         = self.engine.namesIndexes
         self.__numberOfAtomsPerType = self.engine.numberOfAtomsPerName
     elif typeDefinition == "element":
         self.__types                = self.engine.elements
         self.__allTypes             = self.engine.allElements
         self.__numberOfTypes        = self.engine.numberOfElements
         self.__typesIndexes         = self.engine.elementsIndexes
         self.__numberOfAtomsPerType = self.engine.numberOfAtomsPerElement
     self.__typeDefinition = typeDefinition
     # check pdb atoms
     if self.engine is not None:
         lastMolIdx = None
         lut = {}
         for idx in range(len(self.__allTypes)):
             molIdx = self.engine.moleculesIndexes[idx]
             name   = self.__allTypes[idx]
             if lastMolIdx != molIdx:
                 lut = {}
                 lastMolIdx = molIdx
             if lut.has_key(name):
                 raise Exception( LOGGER.error("molecule index '%i' is found to have the same atom %s '%s', This is not allowed for '%s' constraint"%(lastMolIdx, self.__typeDefinition, name, self.__class__.__name__)) )
             else:
                 lut[name] = 1
     # set pairs limits
     if pairsLimitsDefinition is None:
         pairsLimitsDefinition = self.__pairsLimitsDefinition
     self.set_pairs_limits(pairsLimitsDefinition)
Пример #53
0
 def set_mode(self, mode):
     """ 
     Sets the chiSquare mode of calculation. 
     
     :Parameters:
         #. mode (object): The mode of calculation
     """
     assert mode in self.__chiSquareModes.keys(), LOGGER.error("allowed modes are %s"%self.__chiSquareModes.keys())
     self.__mode = mode
     # reinitialize constraint
     self.__initialize_constraint__()
Пример #54
0
 def set_direction(self, direction):
     """
     Sets the generated translation vectors direction.
     
     :Parameters:
         #. direction (None, True, False): Whether to generate translation vector in the same direction of axis or not.
            If None generated axis can be in the same direction of axis or in the opposite.
            If True all generated vectors are in the same direction of axis.
            If False all generated vectors are in the opposite direction of axis.
     """
     assert direction in (None, True, False), LOGGER.error("direction can only be None, True or False")
     self.__direction = direction
Пример #55
0
 def set_flip(self, flip):
     """
     Sets flip flag value.
     
     :Parameters:
         #. flip (None, bool): Whether to allow flipping axis orientation or not.
            If True, orientationAxis will be flipped forcing anti-parallel orientation.
            If False, orientationAxis will not be flipped forcing parallel orientation.
            If None, no flipping is forced, flipping can be set randomly to True or False during run time execution. 
     """
     assert flip in (None, True, False), LOGGER.error("flip can only be None, True or False")
     self.__flip = flip
Пример #56
0
 def set_shrink(self, shrink):
     """
     Sets shrink flag value.
     
     :Parameters:
         #. shrink (None, bool): Whether to always shrink the distance or expand it.
            If True, moves will always bring atoms closer to each other.
            If False, moves will always bring atoms away from each other.
            If None, no orientation is forced, therefore distance can increase or decrease randomly at every step.           
     """
     assert shrink in (None, True, False), LOGGER.error("shrink can only be None, True or False")
     self.__shrink = shrink
Пример #57
0
 def set_order(self, order):
     """
     Set selector groups order.
     
     :Parameters:
         #. order (None, list, set, tuple, numpy.ndarray): The selector order of groups.
     """
     if order is None:
         newOrder = None
     else:
         assert isinstance(order, (list, set, tuple, np.ndarray)), LOGGER.error("order must a instance among list, set, tuple or numpy.ndarray")
         if isinstance(order, np.ndarray):
             assert len(order.shape)==1, LOGGER.error("order numpy.ndarray must have one dimension")
         order = list(order)
         assert len(order)>0, LOGGER.error("order can't be empty")
         newOrder = []
         for idx in order:
             assert is_integer(idx), LOGGER.error("order indexes must be integers")
             idx = int(idx)
             assert idx>=0, LOGGER.error("order indexes must be positive")
             assert idx<len(self.engine.groups), LOGGER.error("order indexes must be smaller than engine's number of groups")
             newOrder.append(idx)
         newOrder = np.array(newOrder, dtype=INT_TYPE)
     # set order
     self.__order = newOrder
     # re-initialize selector
     self.__initialize_selector__()
Пример #58
0
 def set_adjust_move_generators(self, adjustMoveGenerators):
     """
     Set expand.
     
     :Parameters:
         #. adjustMoveGenerators (bool): If set to True, all groups move generator instances will
            be changed automatically at engine runtime to a MoveGeneratorCollector of 
            TranslationTowardsCenterGenerator and a randomRotation (for only more than 2 atoms groups). 
            Generators parameters can be given by generatorsParams. It is advisable to 
            set this flag to True in order to take advantage of an automatic and intelligent directional moves.  
     """  
     assert isinstance(adjustMoveGenerators, bool), LOGGER.error("adjustMoveGenerators must be boolean")
     self.__adjustMoveGenerators = adjustMoveGenerators
Пример #59
0
 def set_group_axis(self, groupAxis):
     """
     Sets group axis value.
     
     :Parameters:
        #. groupAxis (dict): The group axis. Only one key is allowed.
           If key is fixed, value must be a list, tuple or a numpy.array of a vector such as [X,Y,Z]
           If key is symmetry, in this case the group axis is computed as one of the three 
           symmetry axis of the group atoms. the value must be even 0, 1 or 2 for respectively 
           the first, second and tertiary symmetry axis.
     """
     assert isinstance(groupAxis, dict), LOGGER.error("groupAxis must be a dictionary")
     assert len(groupAxis) == 1, LOGGER.error("groupAxis must have a single key")       
     key = groupAxis.keys()[0]
     val = groupAxis[key]
     if key == "fixed":
         self.__mustComputeGroupAxis = False
         assert isinstance(val, (list,set,tuple,np.ndarray)), LOGGER.error("groupAxis value must be a list")
         if isinstance(val, np.ndarray):
             assert len(val.shape) == 1, LOGGER.error("groupAxis value must have a single dimension")
         val = list(val)
         assert len(val)==3, LOGGER.error("groupAxis fixed value must be a vector")
         for v in val:
             assert is_number(v), LOGGER.error("groupAxis value item must be numbers") 
         val  = np.array([FLOAT_TYPE(v) for v in val], dtype=FLOAT_TYPE)  
         norm = FLOAT_TYPE(np.sqrt(np.sum(val**2)))    
         val /= norm              
     elif key == "symmetry":
         self.__mustComputeGroupAxis = True
         assert is_integer(val), LOGGER.error("groupAxis symmetry value must be an integer") 
         val = INT_TYPE(val)
         assert val>=0 and val<3, LOGGER.error("groupAxis symmetry value must be positive smaller than 3") 
     else:
         self.__mustComputeGroupAxis = None
         raise Exception(LOGGER.error("groupAxis key must be either 'fixed' or 'symmetry'"))        
     # set groupAxis
     self.__groupAxis = {key:val}
Пример #60
0
 def should_step_get_rejected(self, chiSquare):
     """
     Overloads 'EnhanceOnlyConstraint' should_step_get_rejected method.
     It computes whether to accept or reject a move based on before and after move calculation and not chiSquare.
     If any of activeAtomsDataBeforeMove or activeAtomsDataAfterMove is None an Exception will get raised.
     
     :Parameters:
         #. chiSquare (number): not used in this case
     
     :Return:
         #. result (boolean): True to reject step, False to accept
     """
     if self.activeAtomsDataBeforeMove is None or self.activeAtomsDataAfterMove is None:
         raise Exception(LOGGER.error("must compute data before and after group move"))
     reject = False
     for index in self.activeAtomsDataBeforeMove.keys():
         before = self.activeAtomsDataBeforeMove[index]["reducedDistances"]
         after  = self.activeAtomsDataAfterMove[index]["reducedDistances"]
         if np.any((after-before)>PRECISION):
             reject = True
             break
     return reject