def _update_shape_array(self):
     rmin = self._shapeFuncParams['rmin']
     rmax = self._shapeFuncParams['rmax']
     dr = self._shapeFuncParams['dr']
     qmin = self._shapeFuncParams['qmin']
     qmax = self._shapeFuncParams['qmax']
     dq = self._shapeFuncParams['dq']
     if rmax is None:
         if self.engine.isPBC:
             a = self.engine.boundaryConditions.get_a()
             b = self.engine.boundaryConditions.get_b()
             c = self.engine.boundaryConditions.get_c()
             rmax = FLOAT_TYPE(np.max([a, b, c]) + 10)
         else:
             coordsCenter = np.sum(
                 self.engine.realCoordinates,
                 axis=0) / self.engine.realCoordinates.shape[0]
             coordinates = self.engine.realCoordinates - coordsCenter
             distances = np.sqrt(np.sum(coordinates**2, axis=1))
             maxDistance = 2. * np.max(distances)
             rmax = FLOAT_TYPE(maxDistance + 10)
             LOGGER.warn(
                 "Better set shape function rmax with infinite boundary conditions. Here value is automatically set to %s"
                 % rmax)
     shapeFunc = ShapeFunction(engine=self.engine,
                               weighting=self.weighting,
                               qmin=qmin,
                               qmax=qmax,
                               dq=dq,
                               rmin=rmin,
                               rmax=rmax,
                               dr=dr)
     self._shapeArray = shapeFunc.get_gr_shape_function(self.shellCenters)
     del shapeFunc
 def export(self, fname, format='%12.5f', delimiter=' ', comments='# '):
     """
     Export pair distribution constraint.
     
     :Parameters:
         #. fname (path): full file name and path.
         #. format (string): string format to export the data.
            format is as follows (%[flag]width[.precision]specifier)
         #. delimiter (string): String or character separating columns.
         #. comments (string): String that will be prepended to the header.
     """
     # get constraint value
     output = self.get_constraint_value()
     if not len(output):
         LOGGER.warn("%s constraint data are not computed." %
                     (self.__class__.__name__))
         return
     # start creating header and data
     header = [
         "distances",
     ]
     data = [
         self.experimentalDistances,
     ]
     # add all intra data
     for key, val in output.items():
         if "inter" in key:
             continue
         header.append(key.replace(" ", "_"))
         data.append(val)
     # add all inter data
     for key, val in output.items():
         if "intra" in key:
             continue
         header.append(key.replace(" ", "_"))
         data.append(val)
     # add total
     header.append("total")
     data.append(output["pcf"])
     if self.windowFunction is not None:
         header.append("total_no_window")
         data.append(output["pcf_total"])
     if self._shapeArray is not None:
         header.append("shape_function")
         data.append(self._shapeArray)
     # add experimental data
     header.append("experimental")
     data.append(self.experimentalPDF)
     # create array and export
     data = np.transpose(data).astype(float)
     # save
     np.savetxt(fname=fname,
                X=data,
                fmt=format,
                delimiter=delimiter,
                header=" ".join(header),
                comments=comments)
 def get_constraint_original_value(self):
     """
     Compute all partial Pair Distribution Functions (PDFs). 
     
     :Returns:
         #. PDFs (dictionary): The PDFs dictionnary, where keys are the element wise intra and inter molecular PDFs and values are the computed PDFs.
     """
     if self.originalData is None:
         LOGGER.warn("originalData must be computed first using 'compute_data' method.")
         return {}
     return self._get_constraint_value(self.originalData)
 def get_constraint_value(self):
     """
     Compute all partial Pair Distribution Functions (PDFs). 
     
     :Returns:
         #. PDFs (dictionary): The PDFs dictionnary, where keys are the element wise intra and inter molecular PDFs and values are the computed PDFs.
     """
     if self.data is None:
         LOGGER.warn(
             "data must be computed first using 'compute_data' method.")
         return {}
     return self._get_constraint_value(self.data)
    def get_constraint_value(self):
        """
        Get constraint's data dictionary value.

        :Returns:
            #. data (dictionary): Constraint's data dictionary.
        """
        if self.data is None:
            LOGGER.warn(
                "data must be computed first using 'compute_data' method.")
            return {}
        return self._get_constraint_value(self.data)
Пример #6
0
    def get_constraint_value(self):
        """
        Get partial Mean Pair Distances (MPD) below the defined
        minimum distance.

        :Returns:
            #. MPD (dictionary): MPD dictionary, where keys are the
               element wise intra and inter molecular MPDs and values are
               the computed MPDs.
        """
        if self.data is None:
            LOGGER.warn(
                "%s data must be computed first using 'compute_data' method." %
                (self.__class__.__name__))
            return {}
        return self.data
Пример #7
0
    def export(self, fname, delimiter='     ', comments='# '):
        """
        Export atomic coordination number constraint data.

        :Parameters:
            #. fname (path): full file name and path.
            #. delimiter (string): String or character separating columns.
            #. comments (string): String that will be prepended to the header.
        """
        # get constraint value
        if all([d is None for d in self.data]):
            LOGGER.warn("%s constraint data are not computed." %
                        (self.__class__.__name__))
            return
        CN = self.data / self.__numberOfCores
        StdErrs = []
        for idx, cn in enumerate(CN):
            if cn < self.__minAtoms[idx]:
                StdErrs.append(self.__weights[idx] *
                               (self.__minAtoms[idx] - cn))
            elif cn > self.__maxAtoms[idx]:
                StdErrs.append(self.__weights[idx] *
                               (cn - self.__maxAtoms[idx]))
            else:
                StdErrs.append(0.)
        # create header
        header = [
            "core-shell", "ninimum_coord_num", "naximum_coord_num",
            "mean_coord_num", "standard_error"
        ]
        # create data lists
        data = [["%s-%s" % (e[:2]) for e in self.__coordNumDef],
                [str(i) for i in self.__minAtoms],
                [str(i) for i in self.__maxAtoms], [str(i) for i in CN],
                [str(i) for i in StdErrs]]
        # save
        data = np.transpose(data)
        np.savetxt(fname=fname,
                   X=data,
                   fmt='%s',
                   delimiter=delimiter,
                   header=" ".join(header),
                   comments=comments)
Пример #8
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()
    def plot(self,
             ax=None,
             intra=True,
             inter=True,
             shapeFunc=True,
             legend=True,
             legendCols=2,
             legendLoc='best',
             title=True,
             titleStdErr=True,
             titleScaleFactor=True,
             titleAtRem=True,
             titleUsedFrame=True,
             show=True):
        """ 
        Plot pair correlation constraint.
        
        :Parameters:
            #. ax (None, matplotlib Axes): matplotlib Axes instance to plot in.
               If None is given a new plot figure will be created.
            #. intra (boolean): Whether to add intra-molecular pair distribution function features to the plot.
            #. inter (boolean): Whether to add inter-molecular pair distribution function features to the plot.
            #. shapeFunc (boolean): Whether to add shape function to the plot only when exists.
            #. legend (boolean): Whether to create the legend or not
            #. legendCols (integer): Legend number of columns.
            #. legendLoc (string): The legend location. Anything among
               'right', 'center left', 'upper right', 'lower right', 'best', 'center', 
               'lower left', 'center right', 'upper left', 'upper center', 'lower center'
               is accepted.
            #. title (boolean): Whether to create the title or not.
            #. titleStdErr (boolean): Whether to show constraint standard error value in title.
            #. titleScaleFactor (boolean): Whether to show contraint's scale factor value in title.
            #. titleAtRem (boolean): Whether to show engine's number of removed atoms.
            #. titleUsedFrame(boolean): Whether to show used frame name in title.
            #. show (boolean): Whether to render and show figure before returning.
            
        :Returns:
            #. figure (matplotlib Figure): matplotlib used figure.
            #. axes (matplotlib Axes): matplotlib used axes.

        +------------------------------------------------------------------------------+ 
        |.. figure:: pair_correlation_constraint_plot_method.png                       | 
        |   :width: 530px                                                              | 
        |   :height: 400px                                                             |
        |   :align: left                                                               | 
        +------------------------------------------------------------------------------+
        """
        # get constraint value
        output = self.get_constraint_value()
        if not len(output):
            LOGGER.warn("%s constraint data are not computed." %
                        (self.__class__.__name__))
            return
        # import matplotlib
        import matplotlib.pyplot as plt
        # get axes
        if ax is None:
            FIG = plt.figure()
            AXES = plt.gca()
        else:
            AXES = ax
            FIG = AXES.get_figure()
        # Create plotting styles
        COLORS = ["b", 'g', 'r', 'c', 'y', 'm']
        MARKERS = ["", '.', '+', '^', '|']
        INTRA_STYLES = [
            r[0] + r[1]
            for r in itertools.product(['--'], list(reversed(COLORS)))
        ]
        INTRA_STYLES = [
            r[0] + r[1] for r in itertools.product(MARKERS, INTRA_STYLES)
        ]
        INTER_STYLES = [r[0] + r[1] for r in itertools.product(['-'], COLORS)]
        INTER_STYLES = [
            r[0] + r[1] for r in itertools.product(MARKERS, INTER_STYLES)
        ]
        # plot experimental
        AXES.plot(self.experimentalDistances,
                  self.experimentalPDF,
                  'ro',
                  label="experimental",
                  markersize=7.5,
                  markevery=1)
        AXES.plot(self.shellCenters,
                  output["pcf"],
                  'k',
                  linewidth=3.0,
                  markevery=25,
                  label="total")
        # plot without window function
        if self.windowFunction is not None:
            AXES.plot(self.shellCenters,
                      output["pcf_total"],
                      'k',
                      linewidth=1.0,
                      markevery=5,
                      label="total - no window")
        if shapeFunc and self._shapeArray is not None:
            AXES.plot(self.shellCenters,
                      self._shapeArray,
                      '--k',
                      linewidth=1.0,
                      markevery=5,
                      label="shape function")
        # plot partials
        intraStyleIndex = 0
        interStyleIndex = 0
        for key, val in output.items():
            if key in ("pcf_total", "pcf"):
                continue
            elif "intra" in key and intra:
                AXES.plot(self.shellCenters,
                          val,
                          INTRA_STYLES[intraStyleIndex],
                          markevery=5,
                          label=key)
                intraStyleIndex += 1
            elif "inter" in key and inter:
                AXES.plot(self.shellCenters,
                          val,
                          INTER_STYLES[interStyleIndex],
                          markevery=5,
                          label=key)
                interStyleIndex += 1
        # plot legend
        if legend:
            AXES.legend(frameon=False, ncol=legendCols, loc=legendLoc)
        # set title
        if title:
            FIG.canvas.set_window_title('Pair Correlation Constraint')
            if titleUsedFrame:
                t = '$frame: %s$ : ' % self.engine.usedFrame.replace('_', '\_')
            else:
                t = ''
            if titleAtRem:
                t += "$%i$ $rem.$ $at.$ - " % (len(
                    self.engine._atomsCollector))
            if titleStdErr and self.standardError is not None:
                t += "$std$ $error=%.6f$ " % (self.standardError)
            if titleScaleFactor:
                t += " - " * (len(t) >
                              0) + "$scale$ $factor=%.6f$" % (self.scaleFactor)
            if len(t):
                AXES.set_title(t)
        # set axis labels
        AXES.set_xlabel("$r(\AA)$", size=16)
        AXES.set_ylabel("$g(r)(\AA^{-2})$", size=16)
        # set background color
        FIG.patch.set_facecolor('white')
        #show
        if show:
            plt.show()
        return FIG, AXES
Пример #10
0
else:
    ENGINE = ENGINE.load(engineFilePath)
    # get constraints
    PDF_CONSTRAINT, EMD_CONSTRAINT, ACNC_CONSTRAINT = ENGINE.constraints



# add multiframe
if not ENGINE.is_frame(multiframe):
    ENGINE.add_frame({'name':multiframe, 'frames_name':numberOfFrames})
    for sf in ENGINE.frames[multiframe]['frames_name']:
        ENGINE.set_used_frame(os.path.join(multiframe, sf))
        ENGINE.set_pdb(os.path.join(DIR_PATH, 'multiframe_structure_%s.pdb'%sf))
        _usedConstraints, _constraints, _rigidConstraints = ENGINE.initialize_used_constraints(sortConstraints=True)
        if not len(_usedConstraints):
            LOGGER.warn("@%s No constraints are used. Configuration will be randomized"%ENGINE.usedFrame)
        # runtime initialize group selector
        ENGINE._Engine__groupSelector._runtime_initialize()
        # runtime initialize constraints
        _=[c._runtime_initialize() for c in _usedConstraints]
        LOGGER.info("@%s Stochastic engine files are created"%ENGINE.usedFrame)


################################################################################
###################### CREATE SOFTGRID WORKERS MANAGEMENT ######################
WM = MultiframeUtils.WorkersManagement()
WM.start(engine=ENGINE, multiframe='size_distribution', orchestrator=None)


################################################################################
######################## OPTIMIZE OXYGEN ATOMS POSITION ########################
Пример #11
0
    def run(self,
            numberOfSteps=100000,
            saveFrequency=1000,
            savePath="restart",
            xyzFrequency=None,
            xyzPath="trajectory.xyz"):
        """
        This is an exact copy of engine run method with slight changes marked with #-->
        to make two trajectories, one of the real system and another the explored space.
        new code is marked with #<--
        all leading variables double scores __ removed.
        """
        # get arguments
        #-->_numberOfSteps            = self.__runtime_get_number_of_steps(numberOfSteps)
        #-->_saveFrequency, _savePath = self.__runtime_get_save_engine(saveFrequency, savePath)
        #-->_xyzFrequency, _xyzPath   = self.__runtime_get_save_xyz(xyzFrequency, xyzPath)
        _numberOfSteps = numberOfSteps  #<--
        _saveFrequency = 2 * numberOfSteps  #<--
        _savePath = savePath  #<--
        # create xyz file
        #-->if _xyzFrequency is not None:
        #-->    _xyzfd = open(_xyzPath, 'a')
        _xyzfd = open("trajectory.xyz", 'a')  #<--
        # get and initialize used constraints
        _usedConstraints, _constraints, _rigidConstraints = self.initialize_used_constraints(
        )
        if not len(_usedConstraints):
            LOGGER.warn(
                "No constraints are used. Configuration will be randomize")
        # compute biasedStdErr
        self.biasedStdErr = self.compute_total_standard_error(_constraints,
                                                              current=True)
        # initialize useful arguments
        _engineStartTime = time.time()
        _lastSavedChiSquare = self.biasedStdErr
        _coordsBeforeMove = None
        _moveTried = False
        # initialize group selector
        self.groupSelector._runtime_initialize()

        self.__realCoords = self.realCoordinates  #<--
        self.__boxCoords = self.boxCoordinates  #<--
        #   #####################################################################################   #
        #   #################################### RUN ENGINE #####################################   #
        LOGGER.info("Engine started %i steps, biasedStdErr is: %.6f" %
                    (_numberOfSteps, self.biasedStdErr))
        self.__generated = 0  #<--
        self.__tried = 0  #<--
        self.__accepted = 0  #<--
        for step in xrange(_numberOfSteps):
            # increment generated
            self.__generated += 1
            # get group
            self.__lastSelectedGroupIndex = self.groupSelector.select_index()
            group = self.groups[self.__lastSelectedGroupIndex]
            # get atoms indexes
            groupAtomsIndexes = group.indexes
            # get move generator
            groupMoveGenerator = group.moveGenerator
            # get group atoms coordinates before applying move
            if _coordsBeforeMove is None or not self.groupSelector.isRecurring:
                _coordsBeforeMove = np.array(
                    self.realCoordinates[groupAtomsIndexes],
                    dtype=self.realCoordinates.dtype)
            elif self.groupSelector.explore:
                if _moveTried:
                    _coordsBeforeMove = movedRealCoordinates
            elif not self.groupSelector.refine:
                _coordsBeforeMove = np.array(
                    self.realCoordinates[groupAtomsIndexes],
                    dtype=self.realCoordinates.dtype)
            # compute moved coordinates
            movedRealCoordinates = groupMoveGenerator.move(_coordsBeforeMove)
            movedBoxCoordinates = transform_coordinates(
                transMatrix=self.reciprocalBasisVectors,
                coords=movedRealCoordinates)
            ########################### compute enhanceOnlyConstraints ############################
            rejectMove = False
            for c in _rigidConstraints:
                # compute before move
                c.compute_before_move(realIndexes=groupAtomsIndexes,
                                      relativeIndexes=groupAtomsIndexes)
                # compute after move
                c.compute_after_move(realIndexes=groupAtomsIndexes,
                                     relativeIndexes=groupAtomsIndexes,
                                     movedBoxCoordinates=movedBoxCoordinates)
                # get rejectMove
                rejectMove = c.should_step_get_rejected(
                    c.afterMoveStandardError)
                if rejectMove:
                    break
            _moveTried = not rejectMove
            ############################## reject move before trying ##############################
            if rejectMove:
                # enhanceOnlyConstraints reject move
                for c in _rigidConstraints:
                    c.reject_move(realIndexes=groupAtomsIndexes,
                                  relativeIndexes=groupAtomsIndexes)
                # log generated move rejected before getting tried
                LOGGER.log("move not tried",
                           "Generated move %i is not tried" % self.tried)
            ###################################### try move #######################################
            else:
                self.__tried += 1
                for c in _constraints:
                    # compute before move
                    c.compute_before_move(realIndexes=groupAtomsIndexes,
                                          relativeIndexes=groupAtomsIndexes)
                    # compute after move
                    c.compute_after_move(
                        realIndexes=groupAtomsIndexes,
                        relativeIndexes=groupAtomsIndexes,
                        movedBoxCoordinates=movedBoxCoordinates)
            ################################ compute new biasedStdErr ################################
                newStdErr = self.compute_total_standard_error(_constraints,
                                                              current=False)
                #if len(_constraints) and (newStdErr >= self.biasedStdErr):
                if newStdErr > self.biasedStdErr:
                    if generate_random_float() > self.tolerance:
                        rejectMove = True
                    else:
                        self.tolerated += 1
                        self.biasedStdErr = newStdErr
                else:
                    self.biasedStdErr = newStdErr
            ################################## reject tried move ##################################
            if rejectMove:
                # set selector move rejected
                self.groupSelector.move_rejected(self.__lastSelectedGroupIndex)
                if _moveTried:
                    # constraints reject move
                    for c in _constraints:
                        c.reject_move(realIndexes=groupAtomsIndexes,
                                      relativeIndexes=groupAtomsIndexes)
                    # log tried move rejected
                    LOGGER.log("move rejected",
                               "Tried move %i is rejected" % self.__generated)
            ##################################### accept move #####################################
            else:
                self.__accepted += 1
                # set selector move accepted
                self.groupSelector.move_accepted(self.__lastSelectedGroupIndex)
                # constraints reject move
                for c in _usedConstraints:
                    c.accept_move(realIndexes=groupAtomsIndexes,
                                  relativeIndexes=groupAtomsIndexes)
                # set new coordinates
                self.__realCoords[groupAtomsIndexes] = movedRealCoordinates
                self.__boxCoords[groupAtomsIndexes] = movedBoxCoordinates
                # log new successful move
                triedRatio = 100. * (float(self.__tried) /
                                     float(self.__generated))
                acceptedRatio = 100. * (float(self.__accepted) /
                                        float(self.__generated))
                LOGGER.log(
                    "move accepted",
                    "Generated:%i - Tried:%i(%.3f%%) - Accepted:%i(%.3f%%) - biasedStdErr:%.6f"
                    % (self.__generated, self.__tried, triedRatio,
                       self.__accepted, acceptedRatio, self.biasedStdErr))
            ##################################### save engine #####################################
            if _saveFrequency is not None:
                if not (step + 1) % _saveFrequency:
                    if _lastSavedChiSquare == self.biasedStdErr:
                        LOGGER.info(
                            "Save engine omitted because no improvement made since last save."
                        )
                    else:
                        # update state
                        self.state = time.time()
                        for c in _usedConstraints:
                            #c.increment_tried()
                            c.set_state(self.state)
                        # save engine
                        _lastSavedChiSquare = self.biasedStdErr
                        self.save(_savePath)
            ############################### dump coords to xyz file ###############################
            #-->if _xyzFrequency is not None:
            #-->    if not(step+1)%_xyzFrequency:
            #-->        _xyzfd.write("%s\n"%self.__pdb.numberOfAtoms)
            #-->        triedRatio    = 100.*(float(self.__tried)/float(self.__generated))
            #-->        acceptedRatio = 100.*(float(self.__accepted)/float(self.__generated))
            #-->        _xyzfd.write("Generated:%i - Tried:%i(%.3f%%) - Accepted:%i(%.3f%%) - biasedStdErr:%.6f\n" %(self.__generated , self.__tried, triedRatio, self.__accepted, acceptedRatio, self.biasedStdErr))
            #-->        frame = [self.allNames[idx]+ " " + "%10.5f"%self.__realCoords[idx][0] + " %10.5f"%self.__realCoords[idx][1] + " %10.5f"%self.__realCoords[idx][2] + "\n" for idx in self.__pdb.xindexes]
            #-->        _xyzfd.write("".join(frame))
            triedRatio = 100. * (float(self.__tried) / float(self.__generated)
                                 )  #<--
            acceptedRatio = 100. * (
                float(self.__accepted) / float(self.__generated))  #<--
            _xyzfd.write("%s\n" % (len(groupAtomsIndexes) * 2))  #<--
            _xyzfd.write(
                "Generated:%i - Tried:%i(%.3f%%) - Accepted:%i(%.3f%%) - biasedStdErr:%.6f\n"
                % (self.__generated, self.__tried, triedRatio, self.__accepted,
                   acceptedRatio, self.biasedStdErr))  #<--
            frame = [
                self.allNames[idx] + " " +
                "%10.5f" % self.realCoordinates[idx][0] +
                " %10.5f" % self.realCoordinates[idx][1] +
                " %10.5f" % self.realCoordinates[idx][2] + "\n"
                for idx in groupAtomsIndexes
            ]  #<--
            frame.extend([
                self.allNames[idx] + " " +
                "%10.5f" % _coordsBeforeMove[idx][0] +
                " %10.5f" % _coordsBeforeMove[idx][1] +
                " %10.5f" % _coordsBeforeMove[idx][2] + "\n"
                for idx in range(_coordsBeforeMove.shape[0])
            ])  #<--
            _xyzfd.write("".join(frame))  #<--
        #   #####################################################################################   #
        #   ################################# FINISH ENGINE RUN #################################   #
        #-->LOGGER.info("Engine finishes executing all '%i' steps in %s" % (_numberOfSteps, get_elapsed_time(_engineStartTime, format="%d(days) %d:%d:%d")))
        # close .xyz file
        #-->if _xyzFrequency is not None:
        #-->    _xyzfd.close()
        _xyzfd.close()  #<--
Пример #12
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__()
Пример #13
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)
Пример #14
0
    def export(self, fname, delimiter='     ', comments='# ', split=None):
        """
        Export bonds constraint's distribution histogram.

        :Parameters:
            #. fname (path): full file name and path.
            #. delimiter (string): String or character separating columns.
            #. comments (string): String that will be prepended to the header.
            #. split (None, 'name', 'element'): To split output into per atom
               names, elements in addition to lower and upper bounds.
               If None is given, output will be built from lower and upper
               bounds only.
        """
        # get constraint value
        output = self.get_constraint_value()
        if output is None:
            LOGGER.warn("%s constraint data are not computed." %
                        (self.__class__.__name__))
            return
        # compute categories
        if split == 'name':
            splitV = self.engine.get_original_data("allNames")
        elif split == 'element':
            splitV = self.engine.get_original_data("allElements")
        else:
            splitV = None
        atom1 = self.__bondsList[0]
        atom2 = self.__bondsList[1]
        lower = self.__bondsList[2]
        upper = self.__bondsList[3]
        categories = {}
        for idx in xrange(self.__bondsList[0].shape[0]):
            if self._atomsCollector.is_collected(idx):
                continue
            if splitV is not None:
                a1 = splitV[atom1[idx]]
                a2 = splitV[atom2[idx]]
            else:
                a1 = a2 = ''
            l = lower[idx]
            u = upper[idx]
            k = (a1, a2, l, u)
            L = categories.get(k, [])
            L.append(idx)
            categories[k] = L
        ncategories = len(categories.keys())
        # create data
        for idx, key in enumerate(categories.keys()):
            idxs = categories[key]
            data = self.data["bondsLength"][idxs]
            categories[key] = [str(d) for d in data]
        # adjust data size
        maxSize = max([len(v) for v in categories.values()])
        for key, data in categories.items():
            add = maxSize - len(data)
            if add > 0:
                categories[key] = data + [''] * add
        # start creating header and data
        sortCa = sorted(categories.keys())
        header = [("%s%s%s(%.2f,%.2f)" %
                   (a1, '-' * (len(a1) > 0), a2, L, U)).replace(" ", "_")
                  for a1, a2, L, U in sortCa]
        data = [categories[key] for key in sortCa]
        # save
        data = np.transpose(data)
        np.savetxt(fname=fname,
                   X=data,
                   fmt='%s',
                   delimiter=delimiter,
                   header=" ".join(header),
                   comments=comments)
Пример #15
0
 def plot(self, *args, **kwargs):
     """Method must be overloaded in children classes."""
     LOGGER.warn("%s plot method is not implemented" %
                 (self.__class__.__name__))
Пример #16
0
    def create_angles_by_definition(self, anglesDefinition):
        """
        Creates anglesList using angles definition.
        Calls set_angles(anglesList) and generates angles attribute.

        :Parameters:
            #. anglesDefinition (dict): Angles definition dictionary.
               Every key must be a molecule's name.
               Every key value must be a list of angles definitions.
               Every angle definition is a list of five items where:

               #. Name of the central atom forming the angle.
               #. Name of the left atom forming the angle
                  (interchangeable with the right atom).
               #. Name 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.

        ::

            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 by definition")
            )
        assert isinstance(
            anglesDefinition,
            dict), LOGGER.error("anglesDefinition 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))
        anglesDef = {}
        for mol, angles in anglesDefinition.items():
            if mol not in existingmoleculesName:
                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)
            molAnglesList = []
            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
                # check for redundancy
                append = True
                for b in molAnglesList:
                    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:
                    molAnglesList.append(
                        (centralAt, leftAt, rightAt, lower, upper))
            # create bondDef for molecule mol
            anglesDef[mol] = molAnglesList
        # create mols dictionary
        mols = {}
        for idx in xrange(NUMBER_OF_ATOMS):
            molName = MOLECULES_NAME[idx]
            if not molName in anglesDef.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 anglesList
        anglesList = []
        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]
                anglesList.append(
                    (centralIdx, leftIdx, rightIdx, lower, upper))
        # create angles
        self.set_angles(anglesList=anglesList)
Пример #17
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()
Пример #18
0
    def plot(self,
             ax=None,
             width=0.6,
             barColor='#99ccff',
             cnColor='#ffcc00',
             cnPtSize=20,
             stdErrors=True,
             xlabel=True,
             xlabelSize=16,
             ylabel=True,
             ylabelSize=16,
             legend=True,
             legendCols=1,
             legendLoc='best',
             title=True,
             titleStdErr=True,
             titleAtRem=True,
             titleUsedFrame=True,
             show=True):
        """
        Plot atomic coordination number constraint.

        :Parameters:
            #. ax (None, matplotlib Axes): matplotlib Axes instance to plot in.
               If ax is given, the figure won't be rendered and drawn.
               If None is given a new plot figure will be created and the figue
               will be rendered and drawn.
            #. width (number): Bars width, must be >0 and <=1
            #. barColor (color): boundaries bar color.
            #. cnColor (color): coordination number data points color.
            #. cnPtSize (number): coordination number data points size.
            #. stdErrors (boolean): Whether to show bars standard error.
            #. xlabel (boolean): Whether to create x label.
            #. xlabelSize (number): The x label font size.
            #. ylabel (boolean): Whether to create y label.
            #. ylabelSize (number): The y label font size.
            #. legend (boolean): Whether to create the legend or not
            #. legendCols (integer): Legend number of columns.
            #. legendLoc (string): The legend location. Anything among
               'right', 'center left', 'upper right', 'lower right', 'best',
               'center', 'lower left', 'center right', 'upper left',
               'upper center', 'lower center' is accepted.
            #. title (boolean): Whether to create the title or not
            #. titleStdErr (boolean): Whether to show constraint standard error
               value in title.
            #. titleAtRem (boolean): Whether to show engine's number of removed
               atoms.
            #. titleUsedFrame(boolean): Whether to show used frame name in
               title.
            #. show (boolean): Whether to render and show figure before
               returning.

        :Returns:
            #. figure (matplotlib Figure): matplotlib used figure.
            #. axes (matplotlib Axes): matplotlib used axes.

        +----------------------------------------------------------------------+
        |.. figure:: atomic_coordination_number_constraint_plot_method.png     |
        |   :width: 530px                                                      |
        |   :height: 400px                                                     |
        |   :align: left                                                       |
        +----------------------------------------------------------------------+
        """
        # get constraint value
        if all([d is None for d in self.data]):
            LOGGER.warn("%s constraint data are not computed." %
                        (self.__class__.__name__))
            return
        # check width
        assert 0 < width <= 1, LOGGER.error(
            "width must be a number between 0 and 1")
        # import matplotlib
        import matplotlib.pyplot as plt
        # get axes
        if ax is None:
            FIG = plt.figure()
            AXES = plt.gca()
        else:
            AXES = ax
            FIG = AXES.get_figure()
        # plot bars
        ind = np.arange(1,
                        len(self.data) + 1)  # the x locations for the groups
        bottom = self.minAtoms
        height = [
            self.maxAtoms[idx] - self.minAtoms[idx]
            for idx in xrange(len(self.maxAtoms))
        ]
        p = AXES.bar(ind + width / 2.,
                     height,
                     width,
                     bottom=self.minAtoms,
                     color=barColor,
                     label="boundaries")
        # add coordination number points
        CN = self.data / self.__numberOfCores
        AXES.plot(ind + width / 2.,
                  CN,
                  'o',
                  label="mean coord num",
                  color=cnColor,
                  markersize=cnPtSize,
                  markevery=1)
        # set ticks
        plt.xticks(ind + width / 2.,
                   ["%s-%s" % (e[:2]) for e in self.__coordNumDef])
        # compute standard errors
        if stdErrors:
            StdErrs = []
            for idx, cn in enumerate(CN):
                if cn < self.__minAtoms[idx]:
                    StdErrs.append(self.__weights[idx] *
                                   (self.__minAtoms[idx] - cn))
                elif cn > self.__maxAtoms[idx]:
                    StdErrs.append(self.__weights[idx] *
                                   (cn - self.__maxAtoms[idx]))
                else:
                    StdErrs.append(0.)
            for mi, ma, std, rect in zip(self.__minAtoms, self.__maxAtoms,
                                         StdErrs, AXES.patches):
                height = rect.get_height()
                t = AXES.text(x=rect.get_x() + rect.get_width() / 2,
                              y=float(ma + mi) / 2.,
                              s=" " + str(std),
                              color='black',
                              rotation=90,
                              horizontalalignment='center',
                              verticalalignment='center')
        # set limits
        minY = min([min(CN), min(self.minAtoms)])
        maxY = max([max(CN), max(self.maxAtoms)])
        AXES.set_xlim(0, len(self.data) + 1.5)
        AXES.set_ylim(minY - 1, maxY + 1)
        # set axis labels
        if xlabel:
            AXES.set_xlabel("Core-Shell atoms", size=xlabelSize)
        if ylabel:
            AXES.set_ylabel("Coordination number", size=ylabelSize)
        # set title
        if title:
            FIG.canvas.set_window_title(
                'Atomic Coordination Number Constraint')
            if titleUsedFrame:
                t = '$frame: %s$ : ' % self.engine.usedFrame.replace('_', '\_')
            else:
                t = ''
            if titleAtRem:
                t += "$%i$ $rem.$ $at.$ - " % (len(
                    self.engine._atomsCollector))
            if titleStdErr and self.standardError is not None:
                t += "$std$ $error=%.6f$ " % (self.standardError)
            if len(t):
                AXES.set_title(t)
        # set background color
        FIG.patch.set_facecolor('white')
        # plot legend
        if legend:
            AXES.legend(frameon=False,
                        ncol=legendCols,
                        loc=legendLoc,
                        numpoints=1)
        #show
        if show:
            plt.show()
        # return axes
        return FIG, AXES
Пример #19
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)
Пример #20
0
 def plot(self, *args, **kwargs):
     LOGGER.warn("%s plot method is not implemented"%(self.__class__.__name__))
Пример #21
0
    def plot(self,
             ax=None,
             nbins=25,
             subplots=True,
             split=None,
             wspace=0.3,
             hspace=0.3,
             histTtype='bar',
             lineWidth=None,
             lineColor=None,
             xlabel=True,
             xlabelSize=16,
             ylabel=True,
             ylabelSize=16,
             legend=True,
             legendCols=1,
             legendLoc='best',
             title=True,
             titleStdErr=True,
             titleAtRem=True,
             titleUsedFrame=True,
             show=True):
        """
        Plot bonds constraint's distribution histogram.

        :Parameters:
            #. ax (None, matplotlib Axes): matplotlib Axes instance to plot in.
               If ax is given,  subplots parameters will be omitted.
               If None is given a new plot figure will be created.
            #. nbins (int): number of bins in histogram.
            #. subplots (boolean): Whether to add plot constraint on multiple
               axes.
            #. split (None, 'name', 'element'): To split plots into histogram
               per atom names, elements in addition to lower and upper bounds.
               If None is given, histograms will be built from lower and upper
               bounds only.
            #. wspace (float): The amount of width reserved for blank space
               between subplots, expressed as a fraction of the average axis
               width.
            #. hspace (float): The amount of height reserved for white space
               between subplots, expressed as a fraction of the average axis
               height.
            #. histTtype (string): the histogram type. optional among
               ['bar', 'barstacked', 'step', 'stepfilled']
            #. lineWidth (None, integer): bars contour line width. If None is
               given then default value will be given.
            #. lineColor (None, integer): bars contour line color. If None is
               given then default value will be given.
            #. xlabel (boolean): Whether to create x label.
            #. xlabelSize (number): The x label font size.
            #. ylabel (boolean): Whether to create y label.
            #. ylabelSize (number): The y label font size.
            #. legend (boolean): Whether to create the legend or not
            #. legendCols (integer): Legend number of columns.
            #. legendLoc (string): The legend location. Anything among
               'right', 'center left', 'upper right', 'lower right', 'best',
               'center', 'lower left', 'center right', 'upper left',
               'upper center', 'lower center' is accepted.
            #. title (boolean): Whether to create the title or not.
            #. titleStdErr (boolean): Whether to show constraint standard error
               value in title.
            #. titleAtRem (boolean): Whether to show engine's number of removed
               atoms.
            #. titleUsedFrame(boolean): Whether to show used frame name in
               title.
            #. show (boolean): Whether to render and show figure before
               returning.

        :Returns:
            #. figure (matplotlib Figure): matplotlib used figure.
            #. axes (matplotlib Axes, List): matplotlib axes or a list of axes.

        +------------------------------------------------------------------------------+
        |.. figure:: bond_constraint_plot_method.png                                   |
        |   :width: 530px                                                              |
        |   :height: 400px                                                             |
        |   :align: left                                                               |
        +------------------------------------------------------------------------------+
        """
        def _get_bins(dmin, dmax, boundaries, nbins):
            # create bins
            delta = float(dmax - dmin) / float(nbins - 1)
            bins = range(nbins)
            bins = [b * delta for b in bins]
            bins = [b + dmin for b in bins]
            # check boundaries
            bidx = 0
            for b in sorted(boundaries):
                for i in range(bidx, len(bins) - 1):
                    bidx = i
                    # exact match with boundary
                    if b == bins[bidx]:
                        break
                    # boundary between two bins, move closest bin to boundary
                    if bins[bidx] < b < bins[bidx + 1]:
                        if b - bins[bidx] > bins[bidx + 1] - b:
                            bins[bidx + 1] = b
                        else:
                            bins[bidx] = b
                        break
            # return bins
            return bins

        # get constraint value
        output = self.get_constraint_value()
        if output is None:
            LOGGER.warn("%s constraint data are not computed." %
                        (self.__class__.__name__))
            return
        # import matplotlib
        import matplotlib.pyplot as plt
        # compute categories
        if split == 'name':
            splitV = self.engine.get_original_data("allNames")
        elif split == 'element':
            splitV = self.engine.get_original_data("allElements")
        else:
            splitV = None
        atom1 = self.__bondsList[0]
        atom2 = self.__bondsList[1]
        lower = self.__bondsList[2]
        upper = self.__bondsList[3]
        categories = {}
        for idx in xrange(self.__bondsList[0].shape[0]):
            if self._atomsCollector.is_collected(idx):
                continue
            if splitV is not None:
                a1 = splitV[atom1[idx]]
                a2 = splitV[atom2[idx]]
            else:
                a1 = a2 = ''
            l = lower[idx]
            u = upper[idx]
            k = (a1, a2, l, u)
            L = categories.get(k, [])
            L.append(idx)
            categories[k] = L
        ncategories = len(categories.keys())
        # get axes
        if ax is None:
            if subplots and ncategories > 1:
                x = np.ceil(np.sqrt(ncategories))
                y = np.ceil(ncategories / x)
                FIG, N_AXES = plt.subplots(int(x), int(y))
                N_AXES = N_AXES.flatten()
                FIG.subplots_adjust(wspace=wspace, hspace=hspace)
                [
                    N_AXES[i].axis('off')
                    for i in range(ncategories, len(N_AXES))
                ]
            else:
                FIG = plt.figure()
                AXES = FIG.gca()
                subplots = False
        else:
            AXES = ax
            FIG = AXES.get_figure()
            subplots = False
        # start plotting
        COLORS = ["b", 'g', 'r', 'c', 'y', 'm']
        if subplots:
            for idx, key in enumerate(categories.keys()):
                a1, a2, L, U = key
                # get label
                label = "%s%s%s(%.2f,%.2f)" % (a1, '-' *
                                               (len(a1) > 0), a2, L, U)
                COL = COLORS[idx % len(COLORS)]
                AXES = N_AXES[idx]
                idxs = categories[key]
                data = self.data["bondsLength"][idxs]
                # get data limits
                mn = np.min(data)
                mx = np.max(data)
                # get bins
                BINS = _get_bins(dmin=mn,
                                 dmax=mx,
                                 boundaries=[L, U],
                                 nbins=nbins)
                # plot histogram
                D, _, P = AXES.hist(x=data,
                                    bins=BINS,
                                    color=COL,
                                    label=label,
                                    histtype=histTtype)
                # vertical lines
                Y = max(D)
                AXES.plot([L, L], [0, Y + 0.1 * Y],
                          linewidth=1.0,
                          color='k',
                          linestyle='--')
                AXES.plot([U, U], [0, Y + 0.1 * Y],
                          linewidth=1.0,
                          color='k',
                          linestyle='--')
                # legend
                if legend:
                    AXES.legend(frameon=False, ncol=legendCols, loc=legendLoc)
                # set axis labels
                if xlabel:
                    AXES.set_xlabel("$r(\AA)$", size=xlabelSize)
                if ylabel:
                    AXES.set_ylabel("$number$", size=ylabelSize)
                if lineWidth is not None:
                    [p.set_linewidth(lineWidth) for p in P]
                if lineColor is not None:
                    [p.set_edgecolor(lineColor) for p in P]
                # update limits
                AXES.set_xmargin(0.1)
                AXES.autoscale()
        else:
            for idx, key in enumerate(categories.keys()):
                a1, a2, L, U = key
                label = "%s%s%s(%.2f,%.2f)" % (a1, '-' *
                                               (len(a1) > 0), a2, L, U)
                COL = COLORS[idx % len(COLORS)]
                idxs = categories[key]
                data = self.data["bondsLength"][idxs]
                # get data limits
                mn = np.min(data)
                mx = np.max(data)
                # get bins
                BINS = _get_bins(dmin=mn,
                                 dmax=mx,
                                 boundaries=[L, U],
                                 nbins=nbins)
                # plot histogram
                D, _, P = AXES.hist(x=data,
                                    bins=BINS,
                                    color=COL,
                                    label=label,
                                    histtype=histTtype)
                # vertical lines
                Y = max(D)
                AXES.plot([L, L], [0, Y + 0.1 * Y],
                          linewidth=1.0,
                          color='k',
                          linestyle='--')
                AXES.plot([U, U], [0, Y + 0.1 * Y],
                          linewidth=1.0,
                          color='k',
                          linestyle='--')
                if lineWidth is not None:
                    [p.set_linewidth(lineWidth) for p in P]
                if lineColor is not None:
                    [p.set_edgecolor(lineColor) for p in P]
            # legend
            if legend:
                AXES.legend(frameon=False, ncol=legendCols, loc=legendLoc)
            # set axis labels
            if xlabel:
                AXES.set_xlabel("$r(\AA)$", size=xlabelSize)
            if ylabel:
                AXES.set_ylabel("$number$", size=ylabelSize)
            # update limits
            AXES.set_xmargin(0.1)
            AXES.autoscale()
        # set title
        if title:
            FIG.canvas.set_window_title('Bond Constraint')
            if titleUsedFrame:
                t = '$frame: %s$ : ' % self.engine.usedFrame.replace('_', '\_')
            else:
                t = ''
            if titleAtRem:
                t += "$%i$ $rem.$ $at.$ - " % (len(
                    self.engine._atomsCollector))
            if titleStdErr and self.standardError is not None:
                t += "$std$ $error=%.6f$ " % (self.standardError)
            if len(t):
                FIG.suptitle(t, fontsize=14)
        # set background color
        FIG.patch.set_facecolor('white')
        #show
        if show:
            plt.show()
        # return axes
        if subplots:
            return FIG, N_AXES
        else:
            return FIG, AXES