Пример #1
0
 def set_amplitude(self, amplitude):
     """
     Sets maximum translation vector allowed amplitude.
     
     :Parameters:
         #. amplitude (number, tuple): The translation amplitude in Angstroms.
            If number is given, it is the maximum translation amplitude in Angstroms and must be bigger than 0.
            If tuple is given, it is the limits of translation boundaries as [min,max] where min>=0 and max>min.
     """
     if isinstance(amplitude, (list, tuple, set)):
         assert len(amplitude) == 2, LOGGER.error(
             "Translation amplitude tuple must have exactly two items")
         assert is_number(amplitude[0]), LOGGER.error(
             "Translation amplitude first item must be a number")
         assert is_number(amplitude[1]), LOGGER.error(
             "Translation amplitude second item must be a number")
         min = FLOAT_TYPE(amplitude[0])
         max = FLOAT_TYPE(amplitude[1])
         assert min >= 0, LOGGER.error(
             "Translation amplitude first item must be bigger than 0")
         assert max > min, LOGGER.error(
             "Translation amplitude first item must be bigger than the second item"
         )
         amplitude = (min, max)
     else:
         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")
         amplitude = (FLOAT_TYPE(0), FLOAT_TYPE(amplitude))
     self.__amplitude = amplitude
Пример #2
0
 def set_adjust_scale_factor(self, adjustScaleFactor):
     """
     Sets adjust scale factor.
     
     :Parameters:
         #. adjustScaleFactor (list, tuple): Used to adjust fit or guess the best scale factor during EMC runtime. 
            It must be a list of exactly three entries.\n
            1. The frequency in number of accepted moves of finding the best scale factor. 
               If 0 frequency is given, it means that the scale factor is fixed.
            2. The minimum allowed scale factor value.
            3. The maximum allowed scale factor value.
     """
     assert isinstance(adjustScaleFactor, (list, tuple)), LOGGER.error('adjustScaleFactor must be a list.')
     assert len(adjustScaleFactor) == 3, LOGGER.error('adjustScaleFactor must be a list of exactly three items.')
     freq  = adjustScaleFactor[0]
     minSF = adjustScaleFactor[1]
     maxSF = adjustScaleFactor[2]
     assert is_integer(freq), LOGGER.error("adjustScaleFactor first item (frequency) must be an integer.")
     freq = INT_TYPE(freq)
     assert freq>=0, LOGGER.error("adjustScaleFactor first (frequency) item must be bigger or equal to 0.")
     assert is_number(minSF), LOGGER.error("adjustScaleFactor second item (minimum) must be a number.")
     minSF = FLOAT_TYPE(minSF)
     assert is_number(maxSF), LOGGER.error("adjustScaleFactor third item (maximum) must be a number.")
     maxSF = FLOAT_TYPE(maxSF)
     assert minSF<=maxSF, LOGGER.error("adjustScaleFactor second item (minimum) must be smaller or equal to third second item (maximum).")
     # set values
     self.__adjustScaleFactorFrequency = freq
     self.__adjustScaleFactorMinimum   = minSF
     self.__adjustScaleFactorMaximum   = maxSF
     # dump to repository
     self._dump_to_repository({'_ExperimentalConstraint__adjustScaleFactorFrequency': self.__adjustScaleFactorFrequency,
                               '_ExperimentalConstraint__adjustScaleFactorMinimum'  : self.__adjustScaleFactorMinimum,
                               '_ExperimentalConstraint__adjustScaleFactorMaximum'  : self.__adjustScaleFactorMaximum})
     # reset constraint
     self.reset_constraint()
Пример #3
0
 def __init__(self, engine, weighting="atomicNumber",
                    qmin=0.001, qmax=1, dq=0.005,
                    rmin=0.00, rmax=100, dr=1):
     # get qmin
     assert is_number(qmin), LOGGER.error("qmin must be a number")
     qmin = FLOAT_TYPE(qmin)
     assert qmin>0, LOGGER.error("qmin '%s' must be bigger than 0"%qmin)
     # get qmin
     assert is_number(qmax), LOGGER.error("qmax must be a number")
     qmax = FLOAT_TYPE(qmax)
     assert qmax>qmin, LOGGER.error("qmax '%s' must be bigger than qmin '%s'"%(qmin,qmax))
     # get dq
     assert is_number(dq), LOGGER.error("dq must be a number")
     dq = FLOAT_TYPE(dq)
     assert dq>0, LOGGER.error("dq '%s' must be bigger than 0"%dq)
     # import StructureFactorConstraint
     from fullrmc.Constraints.StructureFactorConstraints import StructureFactorConstraint
     # create StructureFactorConstraint
     Q = np.arange(qmin, qmax, dq)
     D = np.transpose([Q, np.zeros(len(Q))]).astype(FLOAT_TYPE)
     self._SFC = StructureFactorConstraint(rmin=rmin, rmax=rmax, dr=dr, experimentalData=D, weighting="atomicNumber")
     self._SFC._set_engine(engine)
     self._SFC.listen(message="engine set")
     # set parameters
     self._rmin = FLOAT_TYPE(rmin)
     self._rmax = FLOAT_TYPE(rmax)
     self._dr   = FLOAT_TYPE(dr)
     self._qmin = FLOAT_TYPE(qmin)
     self._qmax = FLOAT_TYPE(qmax)
     self._dq   = FLOAT_TYPE(dq)
     self._weighting = weighting
Пример #4
0
 def set_center(self, center):
     """
     Set the center.
     
     :Parameters:
         #. center (None, list, set, tuple, numpy.ndarray): The center of expansion.
            If None, the center is automatically set to the origin (0,0,0).
     """
     if center is None:
         center = np.array((0, 0, 0), dtype=FLOAT_TYPE)
     else:
         assert isinstance(
             center, (list, set, tuple, np.ndarray)
         ), LOGGER.error(
             "center must a instance among list, set, tuple or numpy.ndarray"
         )
         if isinstance(center, np.ndarray):
             assert len(center.shape) == 1, LOGGER.error(
                 "center numpy.ndarray must have one dimension")
         center = list(center)
         assert len(center) == 3, LOGGER.error(
             "center must have exactly three items")
         assert is_number(
             center[0]), LOGGER.error("center items must be numbers")
         assert is_number(
             center[1]), LOGGER.error("center items must be numbers")
         assert is_number(
             center[2]), LOGGER.error("center items must be numbers")
         center = np.array(([float(c) for c in center]), dtype=FLOAT_TYPE)
     # set center
     self.__center = center
 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()
Пример #6
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
Пример #7
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}
 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)
Пример #9
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
Пример #10
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})
Пример #11
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.)
Пример #12
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.)
Пример #13
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
Пример #14
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)
Пример #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.)
Пример #16
0
 def set_scale_factor(self, scaleFactor):
     """
     Sets the scale factor.
     
     :Parameters:
          #. scaleFactor (number): 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)
     # dump to repository
     self._dump_to_repository({'_ExperimentalConstraint__scaleFactor' :self.__scaleFactor})
     ## reset constraint
     self.reset_constraint()
Пример #17
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.)
Пример #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_center(self, center):
     """
     Set the center.
     
     :Parameters:
         #. center (None, list, set, tuple, numpy.ndarray): The center of expansion.
            If None, the center is automatically set to the origin (0,0,0).
     """
     if center is None:
         center = np.array((0,0,0), dtype=FLOAT_TYPE)
     else:
         assert isinstance(center, (list, set, tuple, np.ndarray)), LOGGER.error("center must a instance among list, set, tuple or numpy.ndarray")
         if isinstance(center, np.ndarray):
             assert len(center.shape)==1,LOGGER.error("center numpy.ndarray must have one dimension")
         center = list(center)
         assert len(center) == 3, LOGGER.error("center must have exactly three items")
         assert is_number(center[0]), LOGGER.error("center items must be numbers")
         assert is_number(center[1]), LOGGER.error("center items must be numbers")
         assert is_number(center[2]), LOGGER.error("center items must be numbers")
         center = np.array(([float(c) for c in center]), dtype=FLOAT_TYPE)
     # set center
     self.__center = center
Пример #20
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
Пример #21
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.)
Пример #22
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}
Пример #23
0
 def set_orientation_axis(self, orientationAxis):
     """
     Sets orientation axis value.
     
     :Parameters:
        #. orientationAxis (dict): The axis to align the group axis with.
           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 the value must be a list of two items, the first one is a list
           of atoms indexes to compute symmetry axis and the second item must be even 0, 1 or 2 for respectively 
           the first, second and tertiary symmetry axis. 
     """
     assert isinstance(orientationAxis, dict), LOGGER.error("orientationAxis must be a dictionary")
     assert len(orientationAxis) == 1, LOGGER.error("orientationAxis must have a single key")       
     key = orientationAxis.keys()[0]
     val = orientationAxis[key]
     if key == "fixed":
         self.__mustComputeOrientationAxis = False
         assert isinstance(val, (list,set,tuple,np.ndarray)), LOGGER.error("orientationAxis value must be a list")
         if isinstance(val, np.ndarray):
             assert len(val.shape) == 1, LOGGER.error("orientationAxis value must have a single dimension")
         val = list(val)
         assert len(val)==3, LOGGER.error("orientationAxis fixed value must be a vector")
         for v in val:
             assert is_number(v), LOGGER.error("orientationAxis 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.__mustComputeOrientationAxis = True
         assert isintance(val, (list, tuple)), LOGGER.error("orientationAxis symmetry value must be a list") 
         assert len(val) == 2, LOGGER.error("orientationAxis symmetry value must be a list of two items")
         val0 = []
         for v in val[0]:
             assert is_integer(v), LOGGER.error("orientationAxis symmetry value list items must be integers") 
             v0 = INT_TYPE(v)
             assert v0>=0, LOGGER.error("orientationAxis symmetry value list items must be positive") 
             val0.append(v0)
         assert len(set(val0))==len(val[0]), LOGGER.error("orientationAxis symmetry value list redundant items indexes found") 
         val0 = np.array(val0, dtype=INT_TYPE)
         val1 = val[1]
         assert is_integer(val1), LOGGER.error("orientationAxis symmetry value second item must be an integer") 
         val1 = INT_TYPE(val1)
         assert val1>=0 and val1<3, LOGGER.error("orientationAxis symmetry value second item must be positive smaller than 3") 
         val = (val0,val1)
     else:
         self.__mustComputeOrientationAxis = None
         raise Exception(LOGGER.error("orientationAxis key must be either 'fixed' or 'symmetry'"))        
     # set orientationAxis
     self.__orientationAxis = {key:val}
Пример #24
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})
Пример #25
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.)
Пример #26
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) )
Пример #27
0
 def __check_single_weight(self, w):
     """Checks a single group weight tuple format"""
     assert isinstance(w, (list,set,tuple)),LOGGER.error("weights list items must be tuples")
     assert len(w)==2, LOGGER.error("weights list tuples must have exactly 2 items")
     idx  = w[0]
     wgt = w[1]
     assert is_integer(idx), LOGGER.error("weights list tuples first item must be an integer")
     idx = INT_TYPE(idx)
     assert idx>=0, LOGGER.error("weights list tuples first item must be positive")
     assert idx<len(self.__collection), LOGGER.error("weights list tuples first item must be smaller than the number of generators in collection")
     assert is_number(wgt), LOGGER.error("weights list tuples second item must be an integer")
     wgt = FLOAT_TYPE(wgt)
     assert wgt>0, LOGGER.error("weights list tuples first item must be bigger than 0")
     # all True return idx and weight
     return idx, wgt  
Пример #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_amplitude(self, amplitude):
     """
     Sets maximum translation vector allowed amplitude.
     
     :Parameters:
         #. amplitude (number, tuple): The translation amplitude in Angstroms.
            If number is given, it is the maximum translation amplitude in Angstroms and must be bigger than 0.
            If tuple is given, it is the limits of translation boundaries as [min,max] where min>=0 and max>min.
     """
     if isinstance(amplitude, (list, tuple, set)):
         assert len(amplitude) == 2, LOGGER.error("Translation amplitude tuple must have exactly two items")
         assert is_number(amplitude[0]), LOGGER.error("Translation amplitude first item must be a number")
         assert is_number(amplitude[1]), LOGGER.error("Translation amplitude second item must be a number")
         min = FLOAT_TYPE(amplitude[0])
         max = FLOAT_TYPE(amplitude[1])
         assert min>=0, LOGGER.error("Translation amplitude first item must be bigger than 0")
         assert max>min, LOGGER.error("Translation amplitude first item must be bigger than the second item")
         amplitude = (min,max)
     else:
         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")
         amplitude = (FLOAT_TYPE(0),FLOAT_TYPE(amplitude))
     self.__amplitude = amplitude
Пример #30
0
 def check_path(self, path):
     """
     Checks the generator's path.
     
     :Parameters:
         #. path (None, list): The list of moves.
     """
     if not isinstance(path, (list, set, tuple, np.ndarray)):
         return False, "path must be a list"
     path = list(path)
     if not len(path):
         return False, "path can't be empty"
     for distance in path:
         if not is_number(distance):
             return False, "path items must be numbers"
     return True, ""
Пример #31
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.)
Пример #32
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})
Пример #33
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
Пример #34
0
 def check_path(self, path):
     """
     Checks the generator's path.
     
     :Parameters:
         #. path (None, list): The list of moves.
     """
     if not isinstance(path, (list, set, tuple, np.ndarray)):
         return False, "path must be a list"
     path = list(path)
     if not len(path):
         return False, "path can't be empty"
     for distance in path:
         if not is_number(distance):
             return False, "path items must be numbers"
     return True, ""
Пример #35
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
Пример #36
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}
Пример #37
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
Пример #38
0
 def set_computation_cost(self, value):
     """
     Sets constraint's computation cost value. This is used at engine runtime 
     to minimize computations and enhance performance by computing less costly
     constraints first. At every step, constraints will be computed in order 
     starting from the less to the most computationally costly. Therefore
     upon rejection of a step because of an unsatisfactory rigid constraint, 
     the left un-computed constraints at this step are guaranteed to be the        
     most costly ones. 
             
     :Parameters:
         #. value (number): Any number.
     """
     assert is_number(value), LOGGER.error("computation cost value must be convertible to a number")
     self.__computationCost  = FLOAT_TYPE(value)
     # dump to repository
     self._dump_to_repository({'_Constraint__computationCost' :self.__computationCost})
Пример #39
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.)
Пример #40
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   
Пример #41
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}
 def set_angles(self, anglesMap):
     """ 
     Sets the angles dictionary by parsing the anglesMap list.
     
     :Parameters:
         #. anglesMap (list): The angles map definition.
            Every item must be a list of five items.\n
            #. First item: The improper atom index that must be in the plane.
            #. Second item: The index of the atom 'O' considered the origin of the plane.
            #. Third item: The index of the atom 'x' used to calculated 'Ox' vector.
            #. Fourth item: The index of the atom 'y' used to calculated 'Oy' vector.
            #. Fifth item: The minimum lower limit or the minimum angle allowed in rad.
            #. Sixth item: The maximum upper limit or the maximum angle allowed in rad.
     """
     map = []
     if self.engine is not None:
         if anglesMap is not None:
             assert isinstance(anglesMap, (list, set, tuple)), LOGGER.error("anglesMap must be None or a list")
             for angle in anglesMap:
                 assert isinstance(angle, (list, set, tuple)), LOGGER.error("anglesMap items must be lists")
                 angle = list(angle)
                 assert len(angle)==6, LOGGER.error("anglesMap items must be lists of 6 items each")
                 improperIdx, oIdx, xIdx, yIdx, lower, upper = angle
                 assert is_integer(improperIdx), LOGGER.error("anglesMap items lists of first item must be an integer")
                 improperIdx = INT_TYPE(improperIdx)
                 assert is_integer(oIdx), LOGGER.error("anglesMap items lists of second item must be an integer")
                 oIdx = INT_TYPE(oIdx)
                 assert is_integer(xIdx), LOGGER.error("anglesMap items lists of third item must be an integer")
                 xIdx = INT_TYPE(xIdx)
                 assert is_integer(yIdx), LOGGER.error("anglesMap items lists of fourth item must be an integer")
                 yIdx = INT_TYPE(yIdx)
                 assert improperIdx>=0, LOGGER.error("anglesMap items lists first item must be positive")
                 assert oIdx>=0, LOGGER.error("anglesMap items lists second item must be positive")
                 assert xIdx>=0, LOGGER.error("anglesMap items lists third item must be positive")
                 assert yIdx>=0, LOGGER.error("anglesMap items lists fourth item must be positive")
                 assert improperIdx!=oIdx, LOGGER.error("bondsMap items lists first and second items can't be the same")
                 assert improperIdx!=xIdx, LOGGER.error("bondsMap items lists first and third items can't be the same")
                 assert improperIdx!=yIdx, LOGGER.error("bondsMap items lists first and fourth items can't be the same")
                 assert oIdx!=xIdx, LOGGER.error("bondsMap items lists second and third items can't be the same")
                 assert oIdx!=yIdx, LOGGER.error("bondsMap items lists second and fourth items can't be the same")
                 assert xIdx!=yIdx, LOGGER.error("bondsMap items lists third and fourth items can't be the same")
                 assert is_number(lower), LOGGER.error("anglesMap items lists of fifth item must be a number")
                 lower = FLOAT_TYPE(lower)
                 assert is_number(upper), LOGGER.error("anglesMap items lists of sixth item must be a number")
                 upper = FLOAT_TYPE(upper)
                 assert lower>=FLOAT_TYPE(-PI/2), LOGGER.error("anglesMap items lists fifth item must be bigger than %10f"%FLOAT_TYPE(-PI/2))
                 assert upper>lower, LOGGER.error("anglesMap items lists fifth item must be smaller than the sixth item")
                 assert upper<=FLOAT_TYPE(PI/2), LOGGER.error("anglesMap items lists fifth item must be smaller or equal to %.10f"%FLOAT_TYPE(PI/2))
                 map.append((improperIdx, oIdx, xIdx, yIdx, lower, upper))  
     # set anglesMap definition
     self.__anglesMap = map      
     # create bonds list of indexes arrays
     self.__angles = {}
     self.__atomsLUAD = {}
     if self.engine is not None:
         # parse bondsMap
         for angle in self.__anglesMap:
             improperIdx, oIdx, xIdx, yIdx, lower, upper = angle
             assert improperIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             assert oIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             assert xIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             assert yIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             # create atoms look up angles dictionary
             if not self.__atomsLUAD.has_key(improperIdx):
                 self.__atomsLUAD[improperIdx] = []
             if not self.__atomsLUAD.has_key(oIdx):
                 self.__atomsLUAD[oIdx] = []
             if not self.__atomsLUAD.has_key(xIdx):
                 self.__atomsLUAD[xIdx] = []
             if not self.__atomsLUAD.has_key(yIdx):
                 self.__atomsLUAD[yIdx] = []
             # create improper angles
             if not self.__angles.has_key(improperIdx):
                 self.__angles[improperIdx] = {"oIndexes":[],"xIndexes":[],"yIndexes":[],"lower":[],"upper":[]}
             # check for redundancy and append
             elif oIdx in self.__angles[improperIdx]["oIndexes"]:
                 index = self.__angles[improperIdx]["oIndexes"].index(oIndexes)
                 if sorted(oIdx,xIdx,yIdx) == sorted(self.__angles[improperIdx]["oIndexes"][index],self.__angles[improperIdx]["xIndexes"][index],self.__angles[improperIdx]["yIndexes"][index]):
                     log.LocalLogger("fullrmc").logger.warn("Improper angle definition for improper atom index '%i' and (O,x,y) atoms indexes (%i,%i,%i)  already defined. New angle limits [%.3f,%.3f] ignored and old angle limits [%.3f,%.3f] kept."%(improperIdx, oIdx, xIdx, yIdx, lower, upper, self.__angles[improperIdx]["lower"][index], self.__angles[improperIdx]["upper"][index]))
                     continue
             # add improper angle definition
             self.__angles[improperIdx]["oIndexes"].append(oIdx)
             self.__angles[improperIdx]["xIndexes"].append(xIdx)
             self.__angles[improperIdx]["yIndexes"].append(yIdx)
             self.__angles[improperIdx]["lower"].append(lower)
             self.__angles[improperIdx]["upper"].append(upper)
             self.__atomsLUAD[improperIdx].append(improperIdx)
             self.__atomsLUAD[oIdx].append(improperIdx)
             self.__atomsLUAD[xIdx].append(improperIdx)
             self.__atomsLUAD[yIdx].append(improperIdx)
         # finalize improper angles
         for idx in self.engine.pdb.xindexes:
             angles = self.__angles.get(idx, {"oIndexes":[],"xIndexes":[],"yIndexes":[],"lower":[],"upper":[]} )
             self.__angles[INT_TYPE(idx)] =  {"oIndexes": np.array(angles["oIndexes"], dtype = INT_TYPE), 
                                              "xIndexes": np.array(angles["xIndexes"], dtype = INT_TYPE),
                                              "yIndexes": np.array(angles["yIndexes"], dtype = INT_TYPE),
                                              "lower"  : np.array(angles["lower"]  , dtype = FLOAT_TYPE),
                                              "upper"  : np.array(angles["upper"]  , dtype = FLOAT_TYPE) }
             lut = self.__atomsLUAD.get(idx, [] )
             self.__atomsLUAD[INT_TYPE(idx)] = sorted(set(lut))
     # reset constraint
     self.__initialize_constraint__()
Пример #43
0
 def set_pairs_distance(self, pairsDistance):
     """ 
     Sets the pairs intermolecular minimum distance. 
     
     :Parameters:
         #. pairsDistance (None, list, set, tuple): The minimum distance set to every pair of elements. 
            A list of tuples must be given, all missing pairs will get automatically assigned the given defaultMinimumDistance value.
            First defined elements pair distance will cancel all redundant. 
            If None is given all pairs will be automatically generated and assigned the given defaultMinimumDistance value 
            ::
            
                e.g. [('h','h',1.5), ('h','c',2.015), ...] 
            
     """
     if self.engine is None:
         newPairsDistance = None
     elif pairsDistance is None:
         newPairsDistance = {}
         for el1 in self.engine.elements:
             newPairsDistance[el1] = {}
             for el2 in self.engine.elements:
                 newPairsDistance[el1][el2] = self.__defaultDistance
     else:
         newPairsDistance = {}
         assert isinstance(pairsDistance, (list, set, tuple)), LOGGER.error("pairsDistance must be a list")
         for pair in pairsDistance:
             assert isinstance(pair, (list, set, tuple)), LOGGER.error("pairsDistance list items must be lists as well")
             pair = list(pair)
             assert len(pair)==3, LOGGER.error("pairsDistance list pair item list must have three items")
             if pair[0] not in self.engine.elements:
                 log.LocalLogger("fullrmc").logger.warn("pairsDistance list pair item '%s' is not a valid engine element, definition item omitted"%pair[0])
                 continue
             if pair[1] not in self.engine.elements: 
                 log.LocalLogger("fullrmc").logger.warn("pairsDistance list pair item '%s' is not a valid engine element, definition item omitted"%pair[1])
                 continue
             # create elements keys
             if not newPairsDistance.has_key(pair[0]):
                 newPairsDistance[pair[0]] = {}
             if not newPairsDistance.has_key(pair[1]):
                 newPairsDistance[pair[1]] = {}
             assert is_number(pair[2]), LOGGER.error("pairsDistance list pair item list third item must be a number")
             distance = FLOAT_TYPE(pair[2])
             assert distance>=0, LOGGER.error("pairsDistance list pair item list third item must be bigger than 0")
             # set minimum distance
             if newPairsDistancepair[0].has_key(pair[1]):
                 log.LocalLogger("fullrmc").logger.warn("elements pair ('%s','%s') distance definition is redundant, '%s' is omitted"%(pair[0], pair[1], pair))
             else:
                 newPairsDistance[pair[0]][pair[1]] = distance
             if newPairsDistancepair[1].has_key(pair[0]):
                 log.LocalLogger("fullrmc").logger.warn("elements pair ('%s','%s') distance definition is redundant, '%s' is omitted"%(pair[1], pair[0], pair))
             else:
                 newPairsDistance[pair[1]][pair[0]] = distance
     # set new pairsDistance value
     self.__pairsDistanceDefinition = pairsDistance
     self.__pairsDistance = newPairsDistance
     if self.__pairsDistance is not None:
         self.__lowerLimitArray = np.zeros((self.engine.numberOfElements, self.engine.numberOfElements, 1), dtype=FLOAT_TYPE) 
         self.__upperLimitArray = np.zeros((self.engine.numberOfElements, self.engine.numberOfElements, 1), dtype=FLOAT_TYPE) 
         for idx1 in range(self.engine.numberOfElements):
             el1 = self.engine.elements[idx1]
             for idx2 in range(self.engine.numberOfElements): 
                 el1  = self.engine.elements[idx1]
                 dist = self.__pairsDistance[el1][el2]
                 assert dist == self.__pairsDistance[el2][el1], LOGGER.error("pairsDistance must be symmetric")
                 self.__upperLimitArray[idx1,idx2,0] = FLOAT_TYPE(dist)
                 self.__upperLimitArray[idx2,idx1,0] = FLOAT_TYPE(dist)
     else:
         self.__lowerLimitArray = None     
         self.__upperLimitArray = None                 
Пример #44
0
 def create_bonds_by_definition(self, bondsDefinition):
     """ 
     Creates bondsMap using bonds definition.
     Calls set_bonds(bondsMap) and generates bonds attribute.
     
     :Parameters:
         #. bondsDefinition (dict): The bonds definition. 
            Every key must be a molecule name (residue name in pdb file). 
            Every key value must be a list of bonds definitions. 
            Every bond definition is a list of four items where:
            
            #. First item: The name of the first atom forming the bond.
            #. Second item: The name of the second atom forming the bond.
            #. Third item: The lower limit or the minimum bond length allowed.
            #. Fourth item: The upper limit or the maximum bond length allowed.
            
        ::
        
             e.g. (Carbon tetrachloride):  bondsDefinition={"CCL4": [('C','CL1' , 1.55, 1.95),
                                                                     ('C','CL2' , 1.55, 1.95),
                                                                     ('C','CL3' , 1.55, 1.95),                                       
                                                                     ('C','CL4' , 1.55, 1.95) ] }
                                                                 
     """
     if self.engine is None:
         raise Exception(LOGGER.error("engine is not defined. Can't create bonds"))
     assert isinstance(bondsDefinition, dict), LOGGER.error("bondsDefinition must be a dictionary")
     # check map definition
     existingMoleculesNames = sorted(set(self.engine.moleculesNames))
     bondsDef = {}
     for mol, bonds in bondsDefinition.items():
         if mol not in existingMoleculesNames:
             log.LocalLogger("fullrmc").logger.warn("Molecule name '%s' in bondsDefinition is not recognized, bonds definition for this particular molecule is omitted"%str(mol))
             continue
         assert isinstance(bonds, (list, set, tuple)), LOGGER.error("mapDefinition molecule bonds must be a list")
         bonds = list(bonds)
         molBondsMap = []
         for bond in bonds:
             assert isinstance(bond, (list, set, tuple)), LOGGER.error("mapDefinition bonds must be a list")
             bond = list(bond)
             assert len(bond)==4, LOGGER.error("mapDefinition bonds list must be of length 4")
             at1, at2, lower, upper = bond
             assert is_number(lower), LOGGER.error("mapDefinition bonds list third item must be a number")
             lower = FLOAT_TYPE(lower)
             assert is_number(upper), LOGGER.error("mapDefinition bonds list fourth item must be a number")
             upper = FLOAT_TYPE(upper)
             assert lower>=0, LOGGER.error("mapDefinition bonds list third item must be bigger than 0")
             assert upper>lower, LOGGER.error("mapDefinition bonds list fourth item must be bigger than the third item")
             # check for redundancy
             append = True
             for b in molBondsMap:
                 if (b[0]==at1 and b[1]==at2) or (b[1]==at1 and b[0]==at2):
                     log.LocalLogger("fullrmc").logger.warn("Redundant definition for bondsDefinition found. The later '%s' is ignored"%str(b))
                     append = False
                     break
             if append:
                 molBondsMap.append((at1, at2, lower, upper))
         # create bondDef for molecule mol 
         bondsDef[mol] = molBondsMap
     # create mols dictionary
     mols = {}
     for idx in self.engine.pdb.xindexes:
         molName = self.engine.moleculesNames[idx]
         if not molName in bondsDef.keys():    
             continue
         molIdx = self.engine.moleculesIndexes[idx]
         if not mols.has_key(molIdx):
             mols[molIdx] = {"name":molName, "indexes":[], "names":[]}
         mols[molIdx]["indexes"].append(idx)
         mols[molIdx]["names"].append(self.engine.allNames[idx])
     # get bondsMap
     bondsMap = []         
     for val in mols.values():
         indexes = val["indexes"]
         names   = val["names"]
         # get definition for this molecule
         thisDef = bondsDef[val["name"]]
         for bond in thisDef:
             idx1  = indexes[ names.index(bond[0]) ]
             idx2  = indexes[ names.index(bond[1]) ]
             lower = bond[2]
             upper = bond[3]
             bondsMap.append((idx1, idx2, lower, upper))
     # create bonds
     self.set_bonds(bondsMap=bondsMap)
Пример #45
0
    def set_orientation_axis(self, orientationAxis):
        """
        Set orientation axis value.

        :Parameters:
            #. orientationAxis (dict): The axis to align the group axis with.
               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 value must be a list of two items, the first one is a list
               of atoms indexes to compute symmetry axis and the second item
               must be even 0, 1 or 2 for respectively the first, second and
               tertiary symmetry axis.
        """
        assert isinstance(
            orientationAxis,
            dict), LOGGER.error("orientationAxis must be a dictionary")
        assert len(orientationAxis) == 1, LOGGER.error(
            "orientationAxis must have a single key")
        key = orientationAxis.keys()[0]
        val = orientationAxis[key]
        if key == "fixed":
            self.__mustComputeOrientationAxis = False
            assert isinstance(val,
                              (list, set, tuple, np.ndarray)), LOGGER.error(
                                  "orientationAxis value must be a list")
            if isinstance(val, np.ndarray):
                assert len(val.shape) == 1, LOGGER.error(
                    "orientationAxis value must have a single dimension")
            val = list(val)
            assert len(val) == 3, LOGGER.error(
                "orientationAxis fixed value must be a vector")
            for v in val:
                assert is_number(v), LOGGER.error(
                    "orientationAxis 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.__mustComputeOrientationAxis = True
            assert isintance(val, (list, tuple)), LOGGER.error(
                "orientationAxis symmetry value must be a list")
            assert len(val) == 2, LOGGER.error(
                "orientationAxis symmetry value must be a list of two items")
            val0 = []
            for v in val[0]:
                assert is_integer(v), LOGGER.error(
                    "orientationAxis symmetry value list items must be integers"
                )
                v0 = INT_TYPE(v)
                assert v0 >= 0, LOGGER.error(
                    "orientationAxis symmetry value list items must be positive"
                )
                val0.append(v0)
            assert len(set(val0)) == len(val[0]), LOGGER.error(
                "orientationAxis symmetry value list redundant items indexes found"
            )
            val0 = np.array(val0, dtype=INT_TYPE)
            val1 = val[1]
            assert is_integer(val1), LOGGER.error(
                "orientationAxis symmetry value second item must be an integer"
            )
            val1 = INT_TYPE(val1)
            assert val1 >= 0 and val1 < 3, LOGGER.error(
                "orientationAxis symmetry value second item must be positive smaller than 3"
            )
            val = (val0, val1)
        else:
            self.__mustComputeOrientationAxis = None
            raise Exception(
                LOGGER.error(
                    "orientationAxis key must be either 'fixed' or 'symmetry'")
            )
        # set orientationAxis
        self.__orientationAxis = {key: val}
Пример #46
0
    def add_angle(self, angle):
        """
        Add a single angle to the list of constraint angles.
        All angles are in degrees.

        :Parameters:
            #. angle (list): The angle list of five items.\n
               #. Central atom index.
               #. Index of the left atom forming the angle
                  (interchangeable with the right atom).
               #. Index of the right atom forming the angle
                  (interchangeable with the left atom).
               #. Minimum lower limit or the minimum angle
                  allowed in degrees which later will be converted to rad.
               #. Maximum upper limit or the maximum angle
                  allowed in degrees which later will be converted to rad.
        """
        assert self.engine is not None, LOGGER.error(
            "setting an angle is not allowed unless engine is defined.")
        NUMBER_OF_ATOMS = self.engine.get_original_data("numberOfAtoms")
        assert isinstance(
            angle,
            (list, set, tuple)), LOGGER.error("angle items must be lists")
        assert len(angle) == 5, LOGGER.error(
            "angle items must be lists of 5 items each")
        centralIdx, leftIdx, rightIdx, lower, upper = angle
        assert centralIdx < NUMBER_OF_ATOMS, LOGGER.error(
            "angle atom index must be smaller than maximum number of atoms")
        assert leftIdx < NUMBER_OF_ATOMS, LOGGER.error(
            "angle atom index must be smaller than maximum number of atoms")
        assert rightIdx < NUMBER_OF_ATOMS, LOGGER.error(
            "angle atom index must be smaller than maximum number of atoms")
        centralIdx = INT_TYPE(centralIdx)
        leftIdx = INT_TYPE(leftIdx)
        rightIdx = INT_TYPE(rightIdx)
        assert is_number(lower)
        lower = FLOAT_TYPE(lower)
        assert is_number(upper)
        upper = FLOAT_TYPE(upper)
        assert lower >= 0, LOGGER.error(
            "angle items lists fourth item must be positive")
        assert upper > lower, LOGGER.error(
            "angle items lists fourth item must be smaller than the fifth item"
        )
        assert upper <= 180, LOGGER.error(
            "angle items lists fifth item must be smaller or equal to 180")
        lower *= FLOAT_TYPE(PI / FLOAT_TYPE(180.))
        upper *= FLOAT_TYPE(PI / FLOAT_TYPE(180.))
        # create central angle
        if not self.__angles.has_key(centralIdx):
            anglesCentral = {
                "left": [],
                "right": [],
                "centralMap": [],
                "otherMap": []
            }
        else:
            anglesCentral = {
                "left": self.__angles[centralIdx]["left"],
                "right": self.__angles[centralIdx]["right"],
                "centralMap": self.__angles[centralIdx]["centralMap"],
                "otherMap": self.__angles[centralIdx]["otherMap"]
            }
        # create left angle
        if not self.__angles.has_key(leftIdx):
            anglesLeft = {
                "left": [],
                "right": [],
                "centralMap": [],
                "otherMap": []
            }
        else:
            anglesLeft = {
                "left": self.__angles[leftIdx]["left"],
                "right": self.__angles[leftIdx]["right"],
                "centralMap": self.__angles[leftIdx]["centralMap"],
                "otherMap": self.__angles[leftIdx]["otherMap"]
            }
        # create right angle
        if not self.__angles.has_key(rightIdx):
            anglesRight = {
                "left": [],
                "right": [],
                "centralMap": [],
                "otherMap": []
            }
        else:
            anglesRight = {
                "left": self.__angles[rightIdx]["left"],
                "right": self.__angles[rightIdx]["right"],
                "centralMap": self.__angles[rightIdx]["centralMap"],
                "otherMap": self.__angles[rightIdx]["otherMap"]
            }

        # check for re-defining
        setPos = ileft = iright = None
        if leftIdx in anglesCentral["left"] and rightIdx in anglesCentral[
                "right"]:
            ileft = anglesCentral["left"].index(leftIdx)
            iright = anglesCentral["right"].index(rightIdx)
        elif leftIdx in anglesCentral["right"] and rightIdx in anglesCentral[
                "left"]:
            ileft = anglesCentral["right"].index(leftIdx)
            iright = anglesCentral["left"].index(rightIdx)
        if (ileft is not None) and (ileft == iright):
            LOGGER.warn(
                "Angle definition for central atom index '%i' and interchangeable left '%i' atom and right '%i' atom is  already defined. New angle limits [%.3f,%.3f] are set."
                % (centralIdx, leftIdx, rightIdx, lower, upper))
            setPos = anglesCentral["centralMap"][ileft]
        # set angle
        if setPos is None:
            anglesCentral['left'].append(leftIdx)
            anglesCentral['right'].append(rightIdx)
            anglesCentral['centralMap'].append(len(self.__anglesList[0]))
            anglesLeft['otherMap'].append(len(self.__anglesList[0]))
            anglesRight['otherMap'].append(len(self.__anglesList[0]))
            self.__anglesList[0] = np.append(self.__anglesList[0], centralIdx)
            self.__anglesList[1] = np.append(self.__anglesList[1], leftIdx)
            self.__anglesList[2] = np.append(self.__anglesList[2], rightIdx)
            self.__anglesList[3] = np.append(self.__anglesList[3], lower)
            self.__anglesList[4] = np.append(self.__anglesList[4], upper)
        else:
            assert self.__anglesList[0][setPos] == centralIdx, LOOGER.error(
                "mismatched angles central atom '%s' and '%s'" %
                (elf.__anglesList[0][setPos], centralIdx))
            assert sorted([leftIdx, rightIdx]) == sorted([
                self.__anglesList[1][setPos], self.__anglesList[2][setPos]
            ]), LOOGER.error(
                "mismatched angles left and right at central atom '%s' and '%s'"
                % (elf.__anglesList[0][setPos], centralIdx))
            self.__anglesList[3][setPos] = lower
            self.__anglesList[4][setPos] = upper
        self.__angles[centralIdx] = anglesCentral
        self.__angles[leftIdx] = anglesLeft
        self.__angles[rightIdx] = anglesRight
        # dump to repository
        if self.__dumpAngles:
            self._dump_to_repository({
                '_BondsAngleConstraint__anglesList':
                self.__anglesList,
                '_BondsAngleConstraint__angles':
                self.__angles
            })
            # reset constraint
            self.reset_constraint()
Пример #47
0
    def set_coordination_number_definition(self, coordNumDef):
        """
        Set the coordination number definition.

        :Parameters:
            #. coordNumDef (None, list, tuple): Coordination number definition.
               It must be None, list or tuple where every element is a list or
               a tuple of exactly 6 items and an optional 7th item for weight.

               #. core atoms: Can be any of the following:

                  * string: indicating atomic element.
                  * dictionary: Key as atomic attribute among (element, name)
                    and value is the attribute value.
                  * list, tuple, set, numpy.ndarray: core atoms index.

               #. in shell atoms: Can be any of the following:

                  * string: indicating atomic element.
                  * dictionary: Key as atomic attribute among (element, name)
                    and value is the attribute value.
                  * list, tuple, set, numpy.ndarray: in shell atoms index

               #. Lower distance limit of the coordination shell.
               #. Upper distance limit of the coordination shell.
               #. :math:`N_{min}` : minimum number of neighbours in the
                  shell.
               #. :math:`N_{max}` : maximum number of neighbours in the
                  shell.
               #. :math:`W_{i}` : weight contribution to the standard error,
                  this is optional, if not given it is set automatically to 1.0.

               ::

                   e.g. [ ('Ti','Ti', 2.5, 3.5, 5, 7.1, 1), ('Ni','Ti', 2.2, 3.1, 7.2, 9.7, 100), ...]
                        [ ({'element':'Ti'},'Ti', 2.5, 3.5, 5, 7.1, 0.1), ...]
                        [ ({'name':'au'},'Au', 2.5, 3.5, 4.1, 6.3), ...]
                        [ ({'name':'Ni'},{'element':'Ti'}, 2.2, 3.1, 7, 9), ...]
                        [ ('Ti',range(100,500), 2.2, 3.1, 7, 9), ...]
                        [ ([0,10,11,15,1000],{'name':'Ti'}, 2.2, 3.1, 7, 9, 5), ...]

        """
        if self.engine is None:
            self.__coordNumDef = coordNumDef
            return
        elif coordNumDef is None:
            coordNumDef = []
        ########## check definitions, create coordination number data ##########
        self.__initialize_constraint_data()
        ALL_NAMES = self.engine.get_original_data("allNames")
        NAMES = self.engine.get_original_data("names")
        ALL_ELEMENTS = self.engine.get_original_data("allElements")
        ELEMENTS = self.engine.get_original_data("elements")
        NUMBER_OF_ATOMS = self.engine.get_original_data("numberOfAtoms")
        for CNDef in coordNumDef:
            assert isinstance(CNDef, (list, tuple)), LOGGER.error(
                "coordNumDef item must be a list or a tuple")
            if len(CNDef) == 6:
                coreDef, shellDef, lowerShell, upperShell, minCN, maxCN = CNDef
                weight = 1.0
            elif len(CNDef) == 7:
                coreDef, shellDef, lowerShell, upperShell, minCN, maxCN, weight = CNDef
            else:
                raise LOGGER.error("coordNumDef item must have 6 or 7 items")
            # core definition
            if isinstance(coreDef, basestring):
                coreDef = str(coreDef)
                assert coreDef in ELEMENTS, LOGGER.error(
                    "core atom definition '%s' is not a valid element" %
                    coreDef)
                coreIndexes = [
                    idx for idx, el in enumerate(ALL_ELEMENTS) if el == coreDef
                ]
            elif isinstance(coreDef, dict):
                assert len(coreDef) == 1, LOGGER.error(
                    "core atom definition dictionary must be of length 1")
                key, value = coreDef.keys()[0], coreDef.values()[0]
                if key is "name":
                    assert value in NAMES, LOGGER.error(
                        "core atom definition '%s' is not a valid name" %
                        coreDef)
                    coreIndexes = [
                        idx for idx, el in enumerate(ALL_NAMES)
                        if el == coreDef
                    ]
                elif key is "element":
                    assert value in ELEMENTS, LOGGER.error(
                        "core atom definition '%s' is not a valid element" %
                        coreDef)
                    coreIndexes = [
                        idx for idx, el in enumerate(ALL_ELEMENTS)
                        if el == coreDef
                    ]
                else:
                    raise LOGGER.error(
                        "core atom definition dictionary key must be either 'name' or 'element'"
                    )
            elif isinstance(coreDef, (list, tuple, set, np.ndarray)):
                coreIndexes = []
                if isinstance(coreDef, np.ndarray):
                    assert len(coreDef.shape) == 1, LOGGER.error(
                        "core atom definition numpy.ndarray must be 1D")
                for c in coreDef:
                    assert is_integer(c), LOGGER.error(
                        "core atom definition index must be integer")
                    c = INT_TYPE(c)
                    assert c >= 0, LOGGER.error(
                        "core atom definition index must be >=0")
                    assert c < NUMBER_OF_ATOMS, LOGGER.error(
                        "core atom definition index must be smaler than number of atoms in system"
                    )
                    coreIndexes.append(c)
            # shell definition
            if isinstance(shellDef, basestring):
                shellDef = str(shellDef)
                assert shellDef in ELEMENTS, LOGGER.error(
                    "core atom definition '%s' is not a valid element" %
                    shellDef)
                shellIndexes = [
                    idx for idx, el in enumerate(ALL_ELEMENTS)
                    if el == shellDef
                ]
            elif isinstance(shellDef, dict):
                assert len(shellDef) == 1, LOGGER.error(
                    "core atom definition dictionary must be of length 1")
                key, value = shellDef.keys()[0], shellDef.values()[0]
                if key is "name":
                    assert value in NAMES, LOGGER.error(
                        "core atom definition '%s' is not a valid name" %
                        shellDef)
                    shellIndexes = [
                        idx for idx, el in enumerate(ALL_NAMES)
                        if el == shellDef
                    ]
                elif key is "element":
                    assert value in ELEMENTS, LOGGER.error(
                        "core atom definition '%s' is not a valid element" %
                        shellDef)
                    shellIndexes = [
                        idx for idx, el in enumerate(ALL_ELEMENTS)
                        if el == shellDef
                    ]
                else:
                    raise LOGGER.error(
                        "core atom definition dictionary key must be either 'name' or 'element'"
                    )
            elif isinstance(shellDef, (list, tuple, set, np.ndarray)):
                shellIndexes = []
                if isinstance(shellDef, np.ndarray):
                    assert len(shellDef.shape) == 1, LOGGER.error(
                        "core atom definition numpy.ndarray must be 1D")
                for c in shellDef:
                    assert is_integer(c), LOGGER.error(
                        "core atom definition index must be integer")
                    c = INT_TYPE(c)
                    assert c >= 0, LOGGER.error(
                        "core atom definition index must be >=0")
                    assert c < NUMBER_OF_ATOMS, LOGGER.error(
                        "core atom definition index must be smaler than number of atoms in system"
                    )
                    shellIndexes.append(c)
            # lower and upper shells definition
            assert is_number(lowerShell), LOGGER.error(
                "Coordination number lower shell '%s' must be a number." %
                lowerShell)
            lowerShell = FLOAT_TYPE(lowerShell)
            assert lowerShell >= 0, LOGGER.error(
                "Coordination number lower shell '%s' must be a positive." %
                lowerShell)
            assert is_number(upperShell), LOGGER.error(
                "Coordination number upper shell '%s' must be a number." % key)
            upperShell = FLOAT_TYPE(upperShell)
            assert upperShell > lowerShell, LOGGER.error(
                "Coordination number lower shell '%s' must be smaller than upper shell %s"
                % (lowerShell, upperShell))
            # minimum and maximum number of atoms definitions
            assert is_number(minCN), LOGGER.error(
                "Coordination number minimum atoms '%s' must be a number." %
                minCN)
            minCN = FLOAT_TYPE(minCN)
            assert minCN >= 0, LOGGER.error(
                "Coordination number minimim atoms '%s' must be >=0." % minCN)
            assert is_number(maxCN), LOGGER.error(
                "Coordination number maximum atoms '%s' must be a number." %
                key)
            maxCN = FLOAT_TYPE(maxCN)
            assert maxCN >= minCN, LOGGER.error(
                "Coordination number minimum atoms '%s' must be smaller than maximum atoms %s"
                % (minCN, maxCN))
            # check weight
            assert is_number(weight), LOGGER.error(
                "Coordination number weight '%s' must be a number." % weight)
            weight = FLOAT_TYPE(weight)
            assert weight > 0, LOGGER.error(
                "Coordination number weight '%s' must be >0." % weight)
            # append coordination number data
            self.__coresIndexes.append(sorted(set(coreIndexes)))
            self.__shellsIndexes.append(sorted(set(shellIndexes)))
            self.__lowerShells.append(lowerShell)
            self.__upperShells.append(upperShell)
            self.__minAtoms.append(minCN)
            self.__maxAtoms.append(maxCN)
            #self.__coordNumData.append( FLOAT_TYPE(0) )
            self.__coordNumData.append(None)
            self.__weights.append(weight)
        ########## set asCoreDefIdxs and inShellDefIdxs points ##########
        for _ in xrange(NUMBER_OF_ATOMS):
            self.__asCoreDefIdxs.append([])
            self.__inShellDefIdxs.append([])
        for defIdx, indexes in enumerate(self.__coresIndexes):
            self.__coresIndexes[defIdx] = np.array(indexes, dtype=INT_TYPE)
            for atIdx in indexes:
                self.__asCoreDefIdxs[atIdx].append(defIdx)
        for defIdx, indexes in enumerate(self.__shellsIndexes):
            self.__shellsIndexes[defIdx] = np.array(indexes, dtype=INT_TYPE)
            for atIdx in indexes:
                self.__inShellDefIdxs[atIdx].append(defIdx)
        for atIdx in xrange(NUMBER_OF_ATOMS):
            self.__asCoreDefIdxs[atIdx] = np.array(self.__asCoreDefIdxs[atIdx],
                                                   dtype=INT_TYPE)
            self.__inShellDefIdxs[atIdx] = np.array(
                self.__inShellDefIdxs[atIdx], dtype=INT_TYPE)
        # set all to arrays
        #self.__coordNumData  = np.array( self.__coordNumData, dtype=FLOAT_TYPE )
        self.__weights = np.array(self.__weights, dtype=FLOAT_TYPE)
        self.__numberOfCores = np.array(
            [len(idxs) for idxs in self.__coresIndexes], dtype=FLOAT_TYPE)
        # set definition
        self.__coordNumDef = coordNumDef
        # dump to repository
        self._dump_to_repository({
            '_AtomicCoordinationNumberConstraint__coordNumDef':
            self.__coordNumDef,
            '_AtomicCoordinationNumberConstraint__coordNumData':
            self.__coordNumData,
            '_AtomicCoordinationNumberConstraint__weights':
            self.__weights,
            '_AtomicCoordinationNumberConstraint__numberOfCores':
            self.__numberOfCores,
            '_AtomicCoordinationNumberConstraint__coresIndexes':
            self.__coresIndexes,
            '_AtomicCoordinationNumberConstraint__shellsIndexes':
            self.__shellsIndexes,
            '_AtomicCoordinationNumberConstraint__lowerShells':
            self.__lowerShells,
            '_AtomicCoordinationNumberConstraint__upperShells':
            self.__upperShells,
            '_AtomicCoordinationNumberConstraint__minAtoms':
            self.__minAtoms,
            '_AtomicCoordinationNumberConstraint__maxAtoms':
            self.__maxAtoms
        })
        # reset constraint
        self.reset_constraint()  # ADDED 2017-JAN-08
Пример #48
0
    def add_bond(self, bond):
        """
        Add a single bond to constraint's list of bonds.

        :Parameters:
            #. bond (list): The bond list of four items.\n
               #. First atom index forming the bond.
               #. Second atom index forming the bond.
               #. Lower limit or the minimum bond length allowed.
               #. Upper limit or the maximum bond length allowed.
        """
        assert self.engine is not None, LOGGER.error(
            "setting a bond is not allowed unless engine is defined.")
        NUMBER_OF_ATOMS = self.engine.get_original_data("numberOfAtoms")
        assert isinstance(
            bond, (list, set, tuple)), LOGGER.error("bond items must be lists")
        assert len(bond) == 4, LOGGER.error(
            "bond items must be lists of 4 items each")
        idx1, idx2, lower, upper = bond
        assert is_integer(idx1), LOGGER.error(
            "bondsList items lists first item must be an integer")
        idx1 = INT_TYPE(idx1)
        assert is_integer(idx2), LOGGER.error(
            "bondsList items lists second item must be an integer")
        idx2 = INT_TYPE(idx2)
        assert idx1 < NUMBER_OF_ATOMS, LOGGER.error(
            "bond atom index must be smaller than maximum number of atoms")
        assert idx2 < NUMBER_OF_ATOMS, LOGGER.error(
            "bond atom index must be smaller than maximum number of atoms")
        assert idx1 >= 0, LOGGER.error("bond first item must be positive")
        assert idx2 >= 0, LOGGER.error("bond second item must be positive")
        assert idx1 != idx2, LOGGER.error(
            "bond first and second items can't be the same")
        assert is_number(lower), LOGGER.error(
            "bond third item must be a number")
        lower = FLOAT_TYPE(lower)
        assert is_number(upper), LOGGER.error(
            "bond fourth item must be a number")
        upper = FLOAT_TYPE(upper)
        assert lower >= 0, LOGGER.error("bond third item must be positive")
        assert upper > lower, LOGGER.error(
            "bond third item must be smaller than the fourth item")
        # create bonds
        if not self.__bonds.has_key(idx1):
            bondsIdx1 = {"indexes": [], "map": []}
        else:
            bondsIdx1 = {
                "indexes": self.__bonds[idx1]["indexes"],
                "map": self.__bonds[idx1]["map"]
            }
        if not self.__bonds.has_key(INT_TYPE(idx2)):
            bondsIdx2 = {"indexes": [], "map": []}
        else:
            bondsIdx2 = {
                "indexes": self.__bonds[idx2]["indexes"],
                "map": self.__bonds[idx2]["map"]
            }
        # set bond
        if idx2 in bondsIdx1["indexes"]:
            assert idx1 in bondsIdx2["indexes"], LOOGER.error(
                "mismatched bonds between atom '%s' and '%s'" % (idx1, idx2))
            at2InAt1 = bondsIdx1["indexes"].index(idx2)
            at1InAt2 = bondsIdx2["indexes"].index(idx1)
            assert bondsIdx1["map"][at2InAt1] == bondsIdx2["map"][
                at1InAt2], LOOGER.error(
                    "bonded atoms '%s' and '%s' point to different defintions"
                    % (idx1, idx2))
            setPos = bondsIdx1["map"][at2InAt1]
            LOGGER.warn(
                "Bond between atom index '%i' and '%i' is already defined. New bond limits [%.3f,%.3f] will replace old bond limits [%.3f,%.3f]. "
                % (idx2, idx1, lower, upper, self.__bondsList[2][setPos],
                   self.__bondsList[3][setPos]))
            self.__bondsList[0][setPos] = idx1
            self.__bondsList[1][setPos] = idx2
            self.__bondsList[2][setPos] = lower
            self.__bondsList[3][setPos] = upper
        else:
            bondsIdx1["map"].append(len(self.__bondsList[0]))
            bondsIdx2["map"].append(len(self.__bondsList[0]))
            bondsIdx1["indexes"].append(idx2)
            bondsIdx2["indexes"].append(idx1)
            self.__bondsList[0] = np.append(self.__bondsList[0], idx1)
            self.__bondsList[1] = np.append(self.__bondsList[1], idx2)
            self.__bondsList[2] = np.append(self.__bondsList[2], lower)
            self.__bondsList[3] = np.append(self.__bondsList[3], upper)
        self.__bonds[idx1] = bondsIdx1
        self.__bonds[idx2] = bondsIdx2
        # dump to repository
        if self.__dumpBonds:
            self._dump_to_repository({
                '_BondConstraint__bondsList': self.__bondsList,
                '_BondConstraint__bonds': self.__bonds
            })
            # reset constraint
            self.reset_constraint()
Пример #49
0
 def set_bonds(self, bondsMap):
     """ 
     Sets the bonds dictionary by parsing the bondsMap list.
     
     :Parameters:
         #. bondsMap (list): The bonds map definition.
            Every item must be a list of four items.\n
            #. First item is the first atom index.
            #. Second item the second atom index forming the bond, 
            #. Third item: The lower limit or the minimum bond length allowed.
            #. Fourth item: The upper limit or the maximum bond length allowed.
     """
     map = []
     if self.engine is not None:
         if bondsMap is not None:
             assert isinstance(bondsMap, (list, set, tuple)), LOGGER.error("bondsMap must be None or a list")
             for bond in bondsMap:
                 assert isinstance(bond, (list, set, tuple)), LOGGER.error("bondsMap items must be lists")
                 bond = list(bond)
                 assert len(bond)==4, LOGGER.error("bondsMap items must be lists of 4 items each")
                 idx1, idx2, lower, upper = bond
                 assert is_integer(idx1), LOGGER.error("bondsMap items lists first item must be an integer")
                 idx1 = INT_TYPE(idx1)
                 assert is_integer(idx2), LOGGER.error("bondsMap items lists second item must be an integer")
                 idx2 = INT_TYPE(idx2)
                 assert idx1>=0, LOGGER.error("bondsMap items lists first item must be positive")
                 assert idx2>=0, LOGGER.error("bondsMap items lists second item must be positive")
                 assert idx1!=idx2, LOGGER.error("bondsMap items lists first and second items can't be the same")
                 assert is_number(lower), LOGGER.error("bondsMap items lists of third item must be a number")
                 lower = FLOAT_TYPE(lower)
                 assert is_number(upper), LOGGER.error("bondsMap items lists of fourth item must be a number")
                 upper = FLOAT_TYPE(upper)
                 assert lower>=0, LOGGER.error("bondsMap items lists third item must be positive")
                 assert upper>lower, LOGGER.error("bondsMap items lists third item must be smaller than the fourth item")
                 map.append((idx1, idx2, lower, upper))  
     # set bondsMap definition
     self.__bondsMap = map      
     # create bonds list of indexes arrays
     self.__bonds = {}
     if self.engine is not None:
         # parse bondsMap
         for bond in self.__bondsMap:
             idx1, idx2, lower, upper = bond
             assert idx1<len(self.engine.pdb), LOGGER.error("bond atom index must be smaller than maximum number of atoms")
             assert idx2<len(self.engine.pdb), LOGGER.error("bond atom index must be smaller than maximum number of atoms")
             # create bonds
             if not self.__bonds.has_key(idx1):
                 self.__bonds[idx1] = {"indexes":[],"lower":[],"upper":[]}
             if not self.__bonds.has_key(idx2):
                 self.__bonds[idx2] = {"indexes":[],"lower":[],"upper":[]}
             # check for redundancy and append
             if idx2 in self.__bonds[idx1]["indexes"]:
                 index = self.__bonds[idx1]["indexes"].index(idx2)
                 log.LocalLogger("fullrmc").logger.warn("Atom index '%i' is already defined in atom '%i' bonds list. New bond limits [%.3f,%.3f] ignored and old bond limits [%.3f,%.3f] kept. "%(idx2, idx1, lower, upper, self.__bonds[idx1]["lower"][indexes], self.__bonds[idx1]["upper"][indexes]))
             else:
                 self.__bonds[idx1]["indexes"].append(idx2)
                 self.__bonds[idx1]["lower"].append(lower)
                 self.__bonds[idx1]["upper"].append(upper)
             if idx1 in self.__bonds[idx2]["indexes"]:
                 index = self.__bonds[idx2]["indexes"].index(idx1)
                 log.LocalLogger("fullrmc").logger.warn("Atom index '%i' is already defined in atom '%i' bonds list. New bond limits [%.3f,%.3f] ignored and old bond limits [%.3f,%.3f] kept. "%(idx1, idx2, lower, upper, self.__bonds[idx2]["lower"][indexes], self.__bonds[idx1]["upper"][indexes]))
             else:
                 self.__bonds[idx2]["indexes"].append(idx1)
                 self.__bonds[idx2]["lower"].append(lower)
                 self.__bonds[idx2]["upper"].append(upper)
         # finalize bonds
         for idx in self.engine.pdb.xindexes:
             bonds = self.__bonds.get(idx, {"indexes":[],"lower":[],"upper":[]} )
             self.__bonds[INT_TYPE(idx)] =  {"indexes": np.array(bonds["indexes"], dtype = INT_TYPE)  ,
                                             "lower"  : np.array(bonds["lower"]  , dtype = FLOAT_TYPE),
                                             "upper"  : np.array(bonds["upper"]  , dtype = FLOAT_TYPE) }
     # reset constraint
     self.__initialize_constraint__()
Пример #50
0
 def create_angles_by_definition(self, anglesDefinition):
     """ 
     Creates anglesMap using angles definition.
     Calls set_angles(anglesMap) and generates angles attribute.
     
     :Parameters:
         #. anglesDefinition (dict): The angles definition. 
            Every key must be a molecule name (residue name in pdb file). 
            Every key value must be a list of angles definitions. 
            Every angle definition is a list of five items where:
            
            #. First item: The name of the central atom forming the angle.
            #. Second item: The name of the left atom forming the angle (interchangeable with the right atom).
            #. Third item: The name of the right atom forming the angle (interchangeable with the left atom).
            #. Fourth item: The minimum lower limit or the minimum angle allowed in degrees.
            #. Fifth item: The maximum upper limit or the maximum angle allowed in degrees.
     
     ::
     
         e.g. (Carbon tetrachloride):  anglesDefinition={"CCL4": [('C','CL1','CL2' , 105, 115),
                                                                  ('C','CL2','CL3' , 105, 115),
                                                                  ('C','CL3','CL4' , 105, 115),                                      
                                                                  ('C','CL4','CL1' , 105, 115) ] }
                                                              
     """
     if self.engine is None:
         raise Exception(LOGGER.error("Engine is not defined. Can't create angles"))
     assert isinstance(anglesDefinition, dict), LOGGER.error("anglesDefinition must be a dictionary")
     # check map definition
     existingMoleculesNames = sorted(set(self.engine.moleculesNames))
     anglesDef = {}
     for mol, angles in anglesDefinition.items():
         if mol not in existingMoleculesNames:
             LOGGER.warn("Molecule name '%s' in anglesDefinition is not recognized, angles definition for this particular molecule is omitted"%str(mol))
             continue
         assert isinstance(angles, (list, set, tuple)), LOGGER.error("mapDefinition molecule angles must be a list")
         angles = list(angles)
         molAnglesMap = []
         for angle in angles:
             assert isinstance(angle, (list, set, tuple)), LOGGER.error("mapDefinition angles must be a list")
             angle = list(angle)
             assert len(angle)==5
             centralAt, leftAt, rightAt, lower, upper = angle
             assert is_number(lower)
             lower = FLOAT_TYPE(lower)
             assert is_number(upper)
             upper = FLOAT_TYPE(upper)
             assert lower>=0, LOGGER.error("anglesMap items lists fourth item must be positive")
             assert upper>lower, LOGGER.error("anglesMap items lists fourth item must be smaller than the fifth item")
             assert upper<=180, LOGGER.error("anglesMap items lists fifth item must be smaller or equal to 180")
             lower *= FLOAT_TYPE( PI/FLOAT_TYPE(180.) )
             upper *= FLOAT_TYPE( PI/FLOAT_TYPE(180.) )
             # check for redundancy
             append = True
             for b in molAnglesMap:
                 if (b[0]==centralAt) and ( (b[1]==leftAt and b[2]==rightAt) or (b[1]==rightAt and b[2]==leftAt) ):
                     LOGGER.warn("Redundant definition for anglesDefinition found. The later '%s' is ignored"%str(b))
                     append = False
                     break
             if append:
                 molAnglesMap.append((centralAt, leftAt, rightAt, lower, upper))
         # create bondDef for molecule mol 
         anglesDef[mol] = molAnglesMap
     # create mols dictionary
     mols = {}
     for idx in self.engine.pdb.xindexes:
         molName = self.engine.moleculesNames[idx]
         if not molName in anglesDef.keys():    
             continue
         molIdx = self.engine.moleculesIndexes[idx]
         if not mols.has_key(molIdx):
             mols[molIdx] = {"name":molName, "indexes":[], "names":[]}
         mols[molIdx]["indexes"].append(idx)
         mols[molIdx]["names"].append(self.engine.allNames[idx])
     # get anglesMap
     anglesMap = []         
     for val in mols.values():
         indexes = val["indexes"]
         names   = val["names"]
         # get definition for this molecule
         thisDef = anglesDef[val["name"]]
         for angle in thisDef:
             centralIdx = indexes[ names.index(angle[0]) ]
             leftIdx    = indexes[ names.index(angle[1]) ]
             rightIdx   = indexes[ names.index(angle[2]) ]
             lower      = angle[3]
             upper      = angle[4]
             anglesMap.append((centralIdx, leftIdx, rightIdx, lower, upper))
     # create angles
     self.set_angles(anglesMap=anglesMap)
Пример #51
0
 def set_pairs_limits(self, pairsLimitsDefinition):
     """ 
     Sets the pairs intermolecular minimum distance. 
     
     :Parameters:
         #. pairsLimitsDefinition (None, list, set, tuple): The lower and upper limits distance set to every pair of elements. 
            A list of tuples must be given, all missing pairs will get automatically assigned the given defaultMinDistance to infinity value.
            First defined elements pair distance will cancel all redundant. 
            If None is given all pairs will be automatically generated and assigned the given defaultMinDistance to infinity value.
            ::
            
                e.g. [('c','h',0.9, 1.2), ...] 
     
     """
     # set types pairs
     if self.__types is not None:
         self.__typesPairs = sorted(itertools.combinations_with_replacement(self.__types,2))
     else:
         self.__typesPairs = None
     # get pairs limits
     pairsLimitsDict = {}
     if self.engine is None:
         pairsLimitsDict = None
     elif pairsLimitsDefinition is not None:
         pairsLimitsDict = {}
         assert isinstance(pairsLimitsDefinition, (list, set, tuple)), LOGGER.error("pairsLimitsDefinition must be a list")
         for pair in pairsLimitsDefinition:
             assert isinstance(pair, (list, set, tuple)), LOGGER.error("pairsLimitsDefinition list items must be lists as well")
             pair = list(pair)
             assert len(pair)==4, LOGGER.error("pairsLimitsDefinition list pair item list must have four items")
             if pair[0] not in self.__types:
                 log.LocalLogger("fullrmc").logger.warn("pairsLimitsDefinition list pair item '%s' is not a valid type, definition item omitted"%pair[0])
                 continue
             if pair[1] not in self.__types: 
                 log.LocalLogger("fullrmc").logger.warn("pairsLimitsDefinition list pair item '%s' is not a valid type, definition item omitted"%pair[1])
                 continue
             # create type keys
             if not pairsLimitsDict.has_key(pair[0]):
                 pairsLimitsDict[pair[0]] = {}
             if not pairsLimitsDict.has_key(pair[1]):
                 pairsLimitsDict[pair[1]] = {}
             assert is_number(pair[2]), LOGGER.error("pairsLimitsDefinition list pair item list third item must be a number")
             lower = FLOAT_TYPE(pair[2])
             assert is_number(pair[3]), LOGGER.error("pairsLimitsDefinition list pair item list foruth item must be a number")
             upper = FLOAT_TYPE(pair[3])
             assert lower>=0, LOGGER.error("pairsLimitsDefinition list pair item list third item must be bigger than 0")
             assert upper>lower, LOGGER.error("pairsLimitsDefinition list pair item list fourth item must be bigger than the third item")
             # set minimum distance
             if pairsLimitsDict[pair[0]].has_key(pair[1]):
                 log.LocalLogger("fullrmc").logger.warn("elements pair ('%s','%s') distance definition is redundant, '%s' is omitted"%(pair[0], pair[1], pair))
             else:
                 pairsLimitsDict[pair[0]][pair[1]] = (lower, upper)
             if pairsLimitsDict[pair[1]].has_key(pair[0]):
                 log.LocalLogger("fullrmc").logger.warn("elements pair ('%s','%s') distance definition is redundant, '%s' is omitted"%(pair[1], pair[0], pair))
             else:
                 pairsLimitsDict[pair[1]][pair[0]] = (lower, upper)
     # complete pairsLimitsDict to all elements
     if self.engine is not None:
         for el1 in self.__types:
             if not pairsLimitsDict.has_key(el1):
                 pairsLimitsDict[el1] = {}
             for el2 in self.__types:
                 if not pairsLimitsDict[el1].has_key(el2):
                     pairsLimitsDict[el1][el2] = (self.__defaultMinDistance, FLOAT_PLUS_INFINITY)
     # set new pairsLimitsDefinition value
     self.__pairsLimitsDefinition = pairsLimitsDefinition
     self.__pairsLimits = pairsLimitsDict
     # set limits arrays
     if self.__pairsLimits is not None:
         self.__lowerLimitArray = np.zeros((self.__numberOfTypes, self.__numberOfTypes, 1), dtype=FLOAT_TYPE) 
         self.__upperLimitArray = np.zeros((self.__numberOfTypes, self.__numberOfTypes, 1), dtype=FLOAT_TYPE) 
         for idx1 in range(self.__numberOfTypes):
             el1 = self.__types[idx1]
             for idx2 in range(self.__numberOfTypes): 
                 el2  = self.__types[idx2]
                 l,u = self.__pairsLimits[el1][el2]
                 sl,su = self.__pairsLimits[el2][el1]
                 assert l==sl and u==su, "pairsDistance must be symmetric"
                 self.__lowerLimitArray[idx1,idx2,0] = FLOAT_TYPE(l)
                 self.__upperLimitArray[idx1,idx2,0] = FLOAT_TYPE(u)
                 self.__lowerLimitArray[idx2,idx1,0] = FLOAT_TYPE(l)
                 self.__upperLimitArray[idx2,idx1,0] = FLOAT_TYPE(u)
     else:
         self.__lowerLimitArray = None  
         self.__upperLimitArray = None            
Пример #52
0
 def set_angles(self, anglesMap):
     """ 
     Sets the angles dictionary by parsing the anglesMap list.
     
     :Parameters:
         #. anglesMap (list): The angles map definition.
            Every item must be a list of five items.
            
            #. First item: The central atom index.
            #. Second item: The index of the left atom forming the angle (interchangeable with the right atom).
            #. Third item: The index of the right atom forming the angle (interchangeable with the left atom).
            #. Fourth item: The minimum lower limit or the minimum angle allowed in rad.
            #. Fifth item: The maximum upper limit or the maximum angle allowed in rad.
     """
     map = []
     if self.engine is not None:
         if anglesMap is not None:
             assert isinstance(anglesMap, (list, set, tuple)), LOGGER.error("anglesMap must be None or a list")
             for angle in anglesMap:
                 assert isinstance(angle, (list, set, tuple)), LOGGER.error("anglesMap items must be lists")
                 angle = list(angle)
                 assert len(angle)==5, LOGGER.error("anglesMap items must be lists of 5 items each")
                 centralIdx, leftIdx, rightIdx, lower, upper = angle
                 assert is_integer(centralIdx), LOGGER.error("anglesMap items lists of first item must be an integer")
                 centralIdx = INT_TYPE(centralIdx)
                 assert is_integer(leftIdx), LOGGER.error("anglesMap items lists of second item must be an integer")
                 leftIdx = INT_TYPE(leftIdx)
                 assert is_integer(rightIdx), LOGGER.error("anglesMap items lists of third item must be an integer")
                 rightIdx = INT_TYPE(rightIdx)
                 assert centralIdx>=0, LOGGER.error("anglesMap items lists first item must be positive")
                 assert leftIdx>=0, LOGGER.error("anglesMap items lists second item must be positive")
                 assert rightIdx>=0, LOGGER.error("anglesMap items lists third item must be positive")
                 assert centralIdx!=leftIdx, LOGGER.error("bondsMap items lists first and second items can't be the same")
                 assert centralIdx!=rightIdx, LOGGER.error("bondsMap items lists first and third items can't be the same")
                 assert leftIdx!=rightIdx, LOGGER.error("bondsMap items lists second and third items can't be the same")
                 assert is_number(lower), LOGGER.error("anglesMap items lists of third item must be a number")
                 lower = FLOAT_TYPE(lower)
                 assert is_number(upper), LOGGER.error("anglesMap items lists of fourth item must be a number")
                 upper = FLOAT_TYPE(upper)
                 assert lower>=0, LOGGER.error("anglesMap items lists fourth item must be positive")
                 assert upper>lower, LOGGER.error("anglesMap items lists fourth item must be smaller than the fifth item")
                 assert upper<=PI, LOGGER.error("anglesMap items lists fifth item must be smaller or equal to %.10f"%PI)
                 map.append((centralIdx, leftIdx, rightIdx, lower, upper))  
     # set anglesMap definition
     self.__anglesMap = map     
     # create bonds list of indexes arrays
     self.__angles = {}
     self.__atomsLUAD = {}
     if self.engine is not None:
         # parse bondsMap
         for angle in self.__anglesMap:
             centralIdx, leftIdx, rightIdx, lower, upper = angle
             assert centralIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             assert leftIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             assert rightIdx<len(self.engine.pdb), LOGGER.error("angle atom index must be smaller than maximum number of atoms")
             # create atoms look up angles dictionary
             if not self.__atomsLUAD.has_key(centralIdx):
                 self.__atomsLUAD[centralIdx] = []
             if not self.__atomsLUAD.has_key(leftIdx):
                 self.__atomsLUAD[leftIdx] = []
             if not self.__atomsLUAD.has_key(rightIdx):
                 self.__atomsLUAD[rightIdx] = []
             # create angles
             if not self.__angles.has_key(centralIdx):
                 self.__angles[centralIdx] = {"leftIndexes":[],"rightIndexes":[],"lower":[],"upper":[]}
             # check for redundancy and append
             elif leftIdx in self.__angles[centralIdx]["leftIndexes"]:
                 index = self.__angles[centralIdx]["leftIndexes"].index(leftIdx)
                 if rightIdx == self.__angles[centralIdx]["rightIndexes"][index]:
                     LOGGER.warn("Angle definition for central atom index '%i' and interchangeable left an right '%i' and '%i' is  already defined. New angle limits [%.3f,%.3f] ignored and old angle limits [%.3f,%.3f] kept."%(centralIdx, leftIdx, rightIdx, lower, upper, self.__angles[centralIdx]["lower"][index], self.__angles[centralIdx]["upper"][index]))
                     continue
             elif leftIdx in self.__angles[centralIdx]["rightIndexes"]:
                 index = self.__angles[centralIdx]["rightIndexes"].index(leftIdx)
                 if rightIdx == self.__angles[centralIdx]["leftIndexes"][index]:
                     LOGGER.warn("Angle definition for central atom index '%i' and interchangeable left an right '%i' and '%i' is  already defined. New angle limits [%.3f,%.3f] ignored and old angle limits [%.3f,%.3f] kept."%(centralIdx, leftIdx, rightIdx, lower, upper, self.__angles[centralIdx]["lower"][index], self.__angles[centralIdx]["upper"][index]))
                     continue
             # add angle definition
             self.__angles[centralIdx]["leftIndexes"].append(leftIdx)
             self.__angles[centralIdx]["rightIndexes"].append(rightIdx)
             self.__angles[centralIdx]["lower"].append(lower)
             self.__angles[centralIdx]["upper"].append(upper)
             self.__atomsLUAD[centralIdx].append(centralIdx)
             self.__atomsLUAD[leftIdx].append(centralIdx)
             self.__atomsLUAD[rightIdx].append(centralIdx)
         # finalize angles
         for idx in self.engine.pdb.xindexes:
             angles = self.__angles.get(idx, {"leftIndexes":[],"rightIndexes":[],"lower":[],"upper":[]} )
             self.__angles[INT_TYPE(idx)] =  {"leftIndexes": np.array(angles["leftIndexes"], dtype = INT_TYPE), 
                                              "rightIndexes": np.array(angles["rightIndexes"], dtype = INT_TYPE),
                                              "lower"  : np.array(angles["lower"]  , dtype = FLOAT_TYPE),
                                              "upper"  : np.array(angles["upper"]  , dtype = FLOAT_TYPE) }
             lut = self.__atomsLUAD.get(idx, [] )
             self.__atomsLUAD[INT_TYPE(idx)] = sorted(set(lut))
     # reset constraint
     self.__initialize_constraint__()
Пример #53
0
    def create_bonds_by_definition(self, bondsDefinition):
        """
        Creates bondsList using bonds definition.
        Calls set_bonds(bondsList) and generates bonds attribute.

        :Parameters:
            #. bondsDefinition (dict): The bonds definition.
               Every key must be a molecule's name.
               Every key value must be a list of bonds definitions.
               Every bond definition is a list of four items where:

               #. Name of the first atom forming the bond.
               #. Name of the second atom forming the bond.
               #. Lower limit or the minimum bond length allowed.
               #. Upper limit or the maximum bond length allowed.

           ::

                e.g. (Carbon tetrachloride):  bondsDefinition={"CCL4": [('C','CL1' , 1.55, 1.95),
                                                                        ('C','CL2' , 1.55, 1.95),
                                                                        ('C','CL3' , 1.55, 1.95),
                                                                        ('C','CL4' , 1.55, 1.95) ] }

        """
        if self.engine is None:
            raise Exception(
                LOGGER.error(
                    "engine is not defined. Can't create bonds by definition"))
            return
        if bondsDefinition is None:
            bondsDefinition = {}
        assert isinstance(
            bondsDefinition,
            dict), LOGGER.error("bondsDefinition must be a dictionary")
        ALL_NAMES = self.engine.get_original_data("allNames")
        NUMBER_OF_ATOMS = self.engine.get_original_data("numberOfAtoms")
        MOLECULES_NAME = self.engine.get_original_data("moleculesName")
        MOLECULES_INDEX = self.engine.get_original_data("moleculesIndex")
        # check map definition
        existingmoleculesName = sorted(set(MOLECULES_NAME))
        bondsDef = {}
        for mol, bonds in bondsDefinition.items():
            if mol not in existingmoleculesName:
                LOGGER.warn(
                    "Molecule name '%s' in bondsDefinition is not recognized, bonds definition for this particular molecule is omitted"
                    % str(mol))
                continue
            assert isinstance(bonds, (list, set, tuple)), LOGGER.error(
                "mapDefinition molecule bonds must be a list")
            bonds = list(bonds)
            molbondsList = []
            for bond in bonds:
                assert isinstance(bond, (
                    list, set,
                    tuple)), LOGGER.error("mapDefinition bonds must be a list")
                bond = list(bond)
                assert len(bond) == 4, LOGGER.error(
                    "mapDefinition bonds list must be of length 4")
                at1, at2, lower, upper = bond
                assert is_number(lower), LOGGER.error(
                    "mapDefinition bonds list third item must be a number")
                lower = FLOAT_TYPE(lower)
                assert is_number(upper), LOGGER.error(
                    "mapDefinition bonds list fourth item must be a number")
                upper = FLOAT_TYPE(upper)
                assert lower >= 0, LOGGER.error(
                    "mapDefinition bonds list third item must be bigger than 0"
                )
                assert upper > lower, LOGGER.error(
                    "mapDefinition bonds list fourth item must be bigger than the third item"
                )
                # check for redundancy
                append = True
                for b in molbondsList:
                    if (b[0] == at1 and b[1] == at2) or (b[1] == at1
                                                         and b[0] == at2):
                        LOGGER.warn(
                            "Redundant definition for bondsDefinition found. The later '%s' is ignored"
                            % str(b))
                        append = False
                        break
                if append:
                    molbondsList.append((at1, at2, lower, upper))
            # create bondDef for molecule mol
            bondsDef[mol] = molbondsList
        # create mols dictionary
        mols = {}
        for idx in xrange(NUMBER_OF_ATOMS):
            molName = MOLECULES_NAME[idx]
            if not molName in bondsDef.keys():
                continue
            molIdx = MOLECULES_INDEX[idx]
            if not mols.has_key(molIdx):
                mols[molIdx] = {"name": molName, "indexes": [], "names": []}
            mols[molIdx]["indexes"].append(idx)
            mols[molIdx]["names"].append(ALL_NAMES[idx])
        # get bondsList
        bondsList = []
        for val in mols.values():
            indexes = val["indexes"]
            names = val["names"]
            # get definition for this molecule
            thisDef = bondsDef[val["name"]]
            for bond in thisDef:
                idx1 = indexes[names.index(bond[0])]
                idx2 = indexes[names.index(bond[1])]
                lower = bond[2]
                upper = bond[3]
                bondsList.append((idx1, idx2, lower, upper))
        # create bonds
        self.set_bonds(bondsList=bondsList)
 def create_angles_by_definition(self, anglesDefinition):
     """ 
     Creates anglesMap using angles definition.
     Calls set_angles(anglesMap) and generates angles attribute.
     
     :Parameters:
         #. anglesDefinition (dict): The angles definition. 
            Every key must be a molecule name (residue name in pdb file). 
            Every key value must be a list of angles definitions. 
            Every angle definition is a list of five items where:
            
            #. First item: The name of the improper atom that must be in the plane.
            #. Second item: The name of the atom 'O' considered the origin of the plane.
            #. Third item: The name of the atom 'x' used to calculated 'Ox' vector.
            #. Fourth item: The name of the atom 'y' used to calculated 'Oy' vector.
            #. Fifth item: The minimum lower limit or the minimum angle allowed in degrees.
            #. Sixth item: The maximum upper limit or the maximum angle allowed in degrees.
     
     ::
     
         e.g. (Benzene):  anglesDefinition={"BENZ": [('C3','C1','C2','C6', -10, 10),
                                                     ('C4','C1','C2','C6', -10, 10),
                                                     ('C5','C1','C2','C6', -10, 10) ] }
                                               
     """
     if self.engine is None:
         raise Exception("Engine is not defined. Can't create angles")
     assert isinstance(anglesDefinition, dict), "anglesDefinition must be a dictionary"
     # check map definition
     existingMoleculesNames = sorted(set(self.engine.moleculesNames))
     anglesDef = {}
     for mol, angles in anglesDefinition.items():
         if mol not in existingMoleculesNames:
             log.LocalLogger("fullrmc").logger.warn("Molecule name '%s' in anglesDefinition is not recognized, angles definition for this particular molecule is omitted"%str(mol))
             continue
         assert isinstance(angles, (list, set, tuple)), LOGGER.error("mapDefinition molecule angles must be a list")
         angles = list(angles)
         molAnglesMap = []
         for angle in angles:
             assert isinstance(angle, (list, set, tuple)), LOGGER.error("mapDefinition angles must be a list")
             angle = list(angle)
             assert len(angle)==6
             improperAt, oAt, xAt, yAt, lower, upper = angle
             assert is_number(lower)
             lower = FLOAT_TYPE(lower)
             assert is_number(upper)
             upper = FLOAT_TYPE(upper)
             assert lower>=-90, LOGGER.error("anglesMap items lists fifth item must be bigger or equal to -90 deg.")
             assert upper>lower, LOGGER.error("anglesMap items lists fifth item must be smaller than the sixth item")
             assert upper<=90, LOGGER.error("anglesMap items lists sixth item must be smaller or equal to 90")
             lower *= FLOAT_TYPE( PI/FLOAT_TYPE(180.) )
             upper *= FLOAT_TYPE( PI/FLOAT_TYPE(180.) )
             # check for redundancy
             append = True
             for b in molAnglesMap:
                 if (b[0]==improperAt):
                     if sorted(oAt,xAt,yAt) == sorted(b[1],b[2],b[3]):
                         log.LocalLogger("fullrmc").logger.warn("Improper angle definition for improper atom index '%i' and (O,x,y) atoms indexes (%i,%i,%i)  already defined. New angle limits [%.3f,%.3f] ignored and old angle limits [%.3f,%.3f] kept."%(improperIdx, oIdx, xIdx, yIdx, lower, upper, self.__angles[improperIdx]["lower"][index], self.__angles[improperIdx]["upper"][index]))
                         append = False
                         break
             if append:
                 molAnglesMap.append((improperAt, oAt, xAt, yAt, lower, upper))
         # create bondDef for molecule mol 
         anglesDef[mol] = molAnglesMap
     # create mols dictionary
     mols = {}
     for idx in self.engine.pdb.xindexes:
         molName = self.engine.moleculesNames[idx]
         if not molName in anglesDef.keys():    
             continue
         molIdx = self.engine.moleculesIndexes[idx]
         if not mols.has_key(molIdx):
             mols[molIdx] = {"name":molName, "indexes":[], "names":[]}
         mols[molIdx]["indexes"].append(idx)
         mols[molIdx]["names"].append(self.engine.allNames[idx])
     # get anglesMap
     anglesMap = []         
     for val in mols.values():
         indexes = val["indexes"]
         names   = val["names"]
         # get definition for this molecule
         thisDef = anglesDef[val["name"]]
         for angle in thisDef:
             improperIdx = indexes[ names.index(angle[0]) ]
             oIdx        = indexes[ names.index(angle[1]) ]
             xIdx        = indexes[ names.index(angle[2]) ]
             yIdx        = indexes[ names.index(angle[3]) ]
             lower       = angle[4]
             upper       = angle[5]
             anglesMap.append((improperIdx, oIdx, xIdx, yIdx, lower, upper))
     # create angles
     self.set_angles(anglesMap=anglesMap)