Update upstream source from tag 'upstream/3.0.1'
Update to upstream version '3.0.1'
with Debian dir 158a841d12b8bdbcd6ad36b166cd7e0d21f9544c
Andrius Merkys
1 year, 7 months ago
13 | 13 | mkdir build && cd build |
14 | 14 | call activate coordgen_build |
15 | 15 | cmake .. ^ |
16 | -G "Visual Studio 15 2017 Win64" ^ | |
16 | -G "Visual Studio 16 2019" ^ | |
17 | 17 | -DCMAKE_BUILD_TYPE=Release ^ |
18 | 18 | -DCOORDGEN_RIGOROUS_BUILD=ON ^ |
19 | 19 | -DBoost_NO_SYSTEM_PATHS=ON ^ |
85 | 85 | |
86 | 86 | set_target_properties(coordgen |
87 | 87 | PROPERTIES |
88 | VERSION 3.0.0 | |
88 | VERSION 3.0.1 | |
89 | 89 | SOVERSION 3 |
90 | 90 | ) |
91 | 91 | |
128 | 128 | |
129 | 129 | install(EXPORT coordgen-targets |
130 | 130 | FILE ${PROJECT_NAME}-config.cmake |
131 | DESTINATION lib/cmake) | |
131 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) | |
132 | 132 | |
133 | 133 | # Example |
134 | 134 | if(COORDGEN_BUILD_EXAMPLE) |
29 | 29 | void CoordgenFragmentBuilder::initializeCoordinates( |
30 | 30 | sketcherMinimizerFragment* fragment) const |
31 | 31 | { |
32 | assert(fragment->getAtoms().size()); | |
32 | assert(!fragment->getAtoms().empty()); | |
33 | 33 | buildFragment(fragment); |
34 | 34 | fragment->storeCoordinateInformation(); |
35 | 35 | } |
65 | 65 | constrainOldCenter += a->templateCoordinates; |
66 | 66 | constrainNewCenter += a->coordinates; |
67 | 67 | } |
68 | if (constrainedAtoms.size() > 0) { | |
68 | if (!constrainedAtoms.empty()) { | |
69 | 69 | constrainOldCenter /= constrainedAtoms.size(); |
70 | 70 | constrainNewCenter /= constrainedAtoms.size(); |
71 | 71 | } |
143 | 143 | for (auto& temp : sketcherMinimizer::m_templates.getTemplates()) { |
144 | 144 | foundTemplate = sketcherMinimizer::compare(atoms, bonds, temp, mapping); |
145 | 145 | if (foundTemplate) { |
146 | if (atoms.size() > 0) { | |
146 | if (!atoms.empty()) { | |
147 | 147 | atoms[0]->fragment->isTemplated = true; |
148 | 148 | } |
149 | 149 | for (unsigned int i = 0; i < atoms.size(); i++) { |
214 | 214 | if (needsTemplate) { |
215 | 215 | findTemplate(rings); |
216 | 216 | } |
217 | while (rings.size() != 0) { | |
217 | while (!rings.empty()) { | |
218 | 218 | auto centralRing = findCentralRingOfSystem(rings); |
219 | 219 | buildRing(centralRing); |
220 | 220 | rings.erase( |
278 | 278 | void CoordgenFragmentBuilder::generateCoordinatesSideRings( |
279 | 279 | stack<sketcherMinimizerRing*> sideRings) const |
280 | 280 | { |
281 | while (sideRings.size()) { | |
281 | while (!sideRings.empty()) { | |
282 | 282 | sketcherMinimizerRing* ring = sideRings.top(); |
283 | 283 | sideRings.pop(); |
284 | 284 | buildRing(ring); |
384 | 384 | pivotAtom = fusionAtoms.at(0); |
385 | 385 | pivotAtomOnParent = fusionAtoms.at(0); |
386 | 386 | } else { |
387 | assert(fusionBond != NULL); | |
387 | assert(fusionBond != nullptr); | |
388 | 388 | if (find(atoms.begin(), atoms.end(), |
389 | 389 | fusionBond->getStartAtom()) != atoms.end()) { |
390 | 390 | pivotAtom = fusionBond->getStartAtom(); |
544 | 544 | const vector<sketcherMinimizerAtom*>& atoms) |
545 | 545 | { |
546 | 546 | vector<sketcherMinimizerPointF> out; |
547 | assert(atoms.size()); | |
547 | assert(!atoms.empty()); | |
548 | 548 | auto a = static_cast<float>(2 * M_PI / atoms.size()); |
549 | 549 | sketcherMinimizerPointF coords(0.f, 0.f); |
550 | 550 | float angle = 0; |
581 | 581 | isAtomVisited.insert(atomToStartFrom); |
582 | 582 | } |
583 | 583 | |
584 | while (q.size()) { | |
584 | while (!q.empty()) { | |
585 | 585 | generateCoordinatesNeighborsOfFirstAtomInQueue(q, isAtomVisited, |
586 | 586 | fragment); |
587 | 587 | } |
613 | 613 | angles.push_back(static_cast<float>(M_PI * 0.5)); |
614 | 614 | } |
615 | 615 | } |
616 | if (!angles.size()) { | |
616 | if (angles.empty()) { | |
617 | 617 | for (unsigned int i = 0; i < atom->neighbors.size(); i++) { |
618 | 618 | angles.push_back(static_cast<float>(2 * M_PI / angleDivision)); |
619 | 619 | } |
627 | 627 | vector<sketcherMinimizerAtom*>& orderedNeighbors, |
628 | 628 | vector<float>& angles) const |
629 | 629 | { |
630 | if (atom->rings.size()) { | |
630 | if (!atom->rings.empty()) { | |
631 | 631 | return initializeVariablesForNeighboursCoordinatesRingAtom( |
632 | 632 | atom, isAtomVisited, startCoordinates, orderedNeighbors, angles); |
633 | 633 | } |
828 | 828 | if (doubleBond == nullptr) { |
829 | 829 | return; |
830 | 830 | } |
831 | if (atomsToMirror.size() && doubleBond) { | |
831 | if (!atomsToMirror.empty() && doubleBond) { | |
832 | 832 | sketcherMinimizerAtom* firstCIPNeighborStart = |
833 | 833 | doubleBond->startAtomCIPFirstNeighbor(); |
834 | 834 | if (firstCIPNeighborStart == nullptr) { |
962 | 962 | break; |
963 | 963 | } |
964 | 964 | } |
965 | assert(startAtom != NULL); | |
965 | assert(startAtom != nullptr); | |
966 | 966 | r->fusionAtoms[i] = orderChainOfAtoms(fusionAtoms, startAtom); |
967 | 967 | } |
968 | 968 | } |
166 | 166 | sketcherMinimizerAtom* atom, |
167 | 167 | std::set<sketcherMinimizerAtom*>& isAtomVisited, |
168 | 168 | sketcherMinimizerPointF& startCoordinates, |
169 | std::vector<sketcherMinimizerAtom*>& orderedNeighbours, | |
169 | std::vector<sketcherMinimizerAtom*>& orderedNeighbors, | |
170 | 170 | std::vector<float>& angles) const; |
171 | 171 | |
172 | 172 | /* initialize data to generate coordinates of atoms bound to a ring atom */ |
174 | 174 | const sketcherMinimizerAtom* atom, |
175 | 175 | std::set<sketcherMinimizerAtom*>& isAtomVisited, |
176 | 176 | sketcherMinimizerPointF& startCoordinates, |
177 | std::vector<sketcherMinimizerAtom*>& orderedNeighbours, | |
177 | std::vector<sketcherMinimizerAtom*>& orderedNeighbors, | |
178 | 178 | std::vector<float>& angles) const; |
179 | 179 | |
180 | 180 | /* check if the atom is part of a macrocycle and has some degrees of freedom |
43 | 43 | } |
44 | 44 | #ifndef NDEBUG |
45 | 45 | for (auto atom : molecule->getAtoms()) { |
46 | assert(atom->getFragment() != NULL); | |
46 | assert(atom->getFragment() != nullptr); | |
47 | 47 | } |
48 | 48 | #endif |
49 | if (fragments.size()) { | |
49 | if (!fragments.empty()) { | |
50 | 50 | initializeInformation(fragments, molecule); |
51 | 51 | } |
52 | 52 | } |
151 | 151 | if (atom->getBonds().size() > 3) { |
152 | 152 | return false; |
153 | 153 | } |
154 | if (atom->getRings().size()) { | |
154 | if (!atom->getRings().empty()) { | |
155 | 155 | return false; |
156 | 156 | } |
157 | 157 | } |
344 | 344 | // itself so it results visited |
345 | 345 | q.push(fragment); |
346 | 346 | sketcherMinimizerFragment* lastFragment = nullptr; |
347 | while (q.size()) { | |
347 | while (!q.empty()) { | |
348 | 348 | lastFragment = q.front(); |
349 | 349 | q.pop(); |
350 | 350 | for (sketcherMinimizerBond* b : lastFragment->_interFragmentBonds) { |
384 | 384 | { |
385 | 385 | queue<sketcherMinimizerFragment*> fragmentsQueue; |
386 | 386 | fragmentsQueue.push(mainFragment); |
387 | while (fragmentsQueue.size() > 0) { | |
387 | while (!fragmentsQueue.empty()) { | |
388 | 388 | sketcherMinimizerFragment* fragment = fragmentsQueue.front(); |
389 | 389 | fragmentsQueue.pop(); |
390 | 390 | for (sketcherMinimizerBond* bond : fragment->_interFragmentBonds) { |
429 | 429 | queue<sketcherMinimizerFragment*> q; |
430 | 430 | vector<sketcherMinimizerFragment*> new_fragments; |
431 | 431 | q.push(mainFragment); |
432 | while (q.size()) { | |
432 | while (!q.empty()) { | |
433 | 433 | sketcherMinimizerFragment* fragment = q.front(); |
434 | 434 | q.pop(); |
435 | 435 | new_fragments.push_back(fragment); |
109 | 109 | for (Hex* hex : p.m_list) { |
110 | 110 | targetCoords.push_back(hex->coords()); |
111 | 111 | } |
112 | if (!targetCoords.size()) { | |
112 | if (targetCoords.empty()) { | |
113 | 113 | return true; // both polyominoes are empty |
114 | 114 | } |
115 | 115 | int lowestx = m_list[0]->coords().x; |
463 | 463 | void Polyomino::addHex(hexCoords coords) |
464 | 464 | { |
465 | 465 | int index = getIndexInList(coords); |
466 | assert(m_grid[index] == NULL); | |
466 | assert(m_grid[index] == nullptr); | |
467 | 467 | Hex* h = new Hex(coords); |
468 | 468 | m_list.push_back(h); |
469 | 469 | m_grid[index] = h; |
473 | 473 | { |
474 | 474 | int index = getIndexInList(coords); |
475 | 475 | Hex* hex = m_grid[getIndexInList(coords)]; |
476 | assert(hex != NULL); | |
476 | assert(hex != nullptr); | |
477 | 477 | for (unsigned int i = 0; i < m_list.size(); i++) { |
478 | 478 | if (m_list[i] == hex) { |
479 | 479 | m_list.erase(m_list.begin() + i); |
506 | 506 | vertexCoords Polyomino::coordinatesOfSubstituent(const vertexCoords pos) const |
507 | 507 | { |
508 | 508 | vector<Hex*> neighbors = vertexNeighbors(pos); |
509 | assert(neighbors.size() != 0); | |
509 | assert(!neighbors.empty()); | |
510 | 510 | assert(neighbors.size() < 3); |
511 | 511 | vertexCoords out = pos; |
512 | 512 | |
557 | 557 | vertexCoords nextVertex = currentHex->followingVertex(currentVertex); |
558 | 558 | do { |
559 | 559 | bool skip = false; |
560 | if (pentagonVertices.size()) { | |
560 | if (!pentagonVertices.empty()) { | |
561 | 561 | for (auto pentagonVertice : pentagonVertices) { |
562 | 562 | if (pentagonVertice == currentVertex) { |
563 | 563 | skip = true; |
685 | 685 | pols = listOfEquivalents(pols); |
686 | 686 | pols = removeDuplicates(pols); |
687 | 687 | |
688 | } while (pols.size()); | |
688 | } while (!pols.empty()); | |
689 | 689 | } |
690 | 690 | if (found) { |
691 | 691 | vector<vertexCoords> path = chosenP.getPath(); |
692 | 692 | |
693 | 693 | writePolyominoCoordinates(path, atoms, startOfChosen); |
694 | if (chosenP.pentagonVertices.size()) { | |
694 | if (!chosenP.pentagonVertices.empty()) { | |
695 | 695 | atoms.at(0)->molecule->requireMinimization(); |
696 | 696 | } |
697 | 697 | } else { // could not find a shape. fallback methods |
981 | 981 | queue<sketcherMinimizerAtom*> q; |
982 | 982 | q.push(a); |
983 | 983 | visited[parent] = true; |
984 | while (q.size()) { | |
984 | while (!q.empty()) { | |
985 | 985 | sketcherMinimizerAtom* thisA = q.front(); |
986 | 986 | q.pop(); |
987 | 987 | visited[thisA] = true; |
1140 | 1140 | vector<hexCoords> newPos = p.freeVertexNeighborPositions(path[counter]); |
1141 | 1141 | vector<hexCoords> oldPos = allowedHexs[r]; |
1142 | 1142 | vector<hexCoords> nextPos; |
1143 | if (!oldPos.size()) { | |
1143 | if (oldPos.empty()) { | |
1144 | 1144 | nextPos = newPos; |
1145 | 1145 | } else { |
1146 | 1146 | for (auto toCheck : newPos) { |
1152 | 1152 | } |
1153 | 1153 | } |
1154 | 1154 | } |
1155 | if (!nextPos.size()) { | |
1155 | if (nextPos.empty()) { | |
1156 | 1156 | return false; |
1157 | 1157 | } |
1158 | 1158 | allowedHexs[r] = nextPos; |
152 | 152 | { |
153 | 153 | public: |
154 | 154 | Polyomino(); |
155 | Polyomino(const Polyomino& p); | |
155 | Polyomino(const Polyomino& rhs); | |
156 | 156 | ~Polyomino(); |
157 | Polyomino& operator=(const Polyomino& rhv); | |
157 | Polyomino& operator=(const Polyomino& rhs); | |
158 | 158 | |
159 | 159 | /* |
160 | 160 | explore the topology of the polyominoes and returns true if they have the |
73 | 73 | if (skipMinimization) { |
74 | 74 | return; |
75 | 75 | } |
76 | if (!_interactions.size()) { | |
76 | if (_interactions.empty()) { | |
77 | 77 | setupInteractions(); |
78 | 78 | } |
79 | 79 | |
550 | 550 | if (ringInteractions.size() != 1 || nonRingInteractions.size() != 2) { |
551 | 551 | invertedMacrocycleBond = false; |
552 | 552 | } |
553 | if (ringInteractions.size()) { // subtract all the ring angles from 360 | |
553 | if (!ringInteractions.empty()) { // subtract all the ring angles from 360 | |
554 | 554 | // and divide the remaining equally |
555 | 555 | // between the other interactions |
556 | 556 | float totalAngleInRings = 0; |
862 | 862 | } |
863 | 863 | } |
864 | 864 | } |
865 | if (m_residueInteractions.size() && residueInteractions) { | |
865 | if (!m_residueInteractions.empty() && residueInteractions) { | |
866 | 866 | for (auto r : m_residues) { |
867 | 867 | if (r->residueInteractions.size() > 1) { |
868 | 868 | for (unsigned int ri1 = 0; |
1512 | 1512 | bool CoordgenMinimizer::hasNaNCoordinates( |
1513 | 1513 | const std::vector<sketcherMinimizerAtom*>& atoms) |
1514 | 1514 | { |
1515 | for (sketcherMinimizerAtom* a : atoms) | |
1516 | if (a->coordinates.x() != a->coordinates.x() || | |
1517 | a->coordinates.y() != a->coordinates.y()) { | |
1515 | for (sketcherMinimizerAtom* a : atoms) { | |
1516 | if (std::isnan(a->coordinates.x()) || std::isnan(a->coordinates.y())) { | |
1518 | 1517 | return true; |
1519 | 1518 | } |
1519 | } | |
1520 | 1520 | return false; |
1521 | 1521 | } |
1522 | 1522 |
1 | 1 | |
2 | 2 | [![Azure_Build_Status](https://dev.azure.com/patlorton/coordgenlibs/_apis/build/status/schrodinger.coordgenlibs?branchName=master)](https://dev.azure.com/patlorton/coordgenlibs/_build/latest?definitionId=2&branchName=master) |
3 | 3 | |
4 | This is **Schrödinger, Inc's** 2D coordinate generation. It was formerly proprietary code, but is now released under the [BSD license](https://github.com/schrodinger/coordgenlibs/blob/master/LICENSE). The emphasis of these algorithms are on quality of 2D coordinates rather than speed of generation. The algorithm distinguishes itself from many others by doing well with both macrocycles and metal complexes. It also does extremely well on typical drug-like small molecules, and has been validated on millions of compounds. | |
4 | This is **Schrödinger, Inc's** 2D coordinate generation. It was formerly | |
5 | proprietary code, but is now released under the [BSD | |
6 | license](https://github.com/schrodinger/coordgenlibs/blob/master/LICENSE). The | |
7 | emphasis of these algorithms are on quality of 2D coordinates rather than speed | |
8 | of generation. The algorithm distinguishes itself from many others by doing | |
9 | well with both macrocycles and metal complexes. It also does extremely well on | |
10 | typical drug-like small molecules, and has been validated on millions of | |
11 | compounds. | |
5 | 12 | |
6 | Schrodinger intends to continue to contribute to this code as it still uses it inside its products, but will also be happy if others contribute pull-requests when there are improvements they would like to make. We'll also be happy to hear bug reports or feature requests from use of this code, though make no guarantee on our ability to process these. | |
13 | Schrodinger intends to continue to contribute to this code as it still uses it | |
14 | inside its products, but will also be happy if others contribute pull-requests | |
15 | when there are improvements they would like to make. We'll also be happy to | |
16 | hear bug reports or feature requests from use of this code, though make no | |
17 | guarantee on our ability to process these. | |
7 | 18 | |
8 | 19 | ## Documentation |
9 | 20 | |
11 | 22 | |
12 | 23 | ## Templates |
13 | 24 | |
14 | Coordgen uses templates for some macrocycle systems. The source for the templates is `templates.mae`. If | |
15 | you're an end user of coordgen, you can add local templates in a file called | |
16 | `user_templates.mae` in a directory specified by `CoordgenTemplates::setTemplateDir()`. If you want to | |
17 | update the templates, add new templates to `templates.mae` and run `mol_generator.py` to generate the | |
25 | Coordgen uses templates for some macrocycle systems. The source for the | |
26 | templates is `templates.mae`. If you're an end user of coordgen, you can add | |
27 | local templates in a file called `user_templates.mae` in a directory specified | |
28 | by `CoordgenTemplates::setTemplateDir()`. If you want to update the templates, | |
29 | add new templates to `templates.mae` and run `mol_generator.py` to generate the | |
18 | 30 | source files. |
19 | 31 | |
20 | 32 | ## Usage example |
21 | 33 | |
22 | Code for a sample executable is provided in the `example_dir` directory. Building the example executable is enabled by default, but can be disabled by means of the `COORDGEN_BUILD_EXAMPLE` option. | |
34 | Code for a sample executable is provided in the `example_dir` directory. | |
35 | Building the example executable is enabled by default, but can be disabled by | |
36 | means of the `COORDGEN_BUILD_EXAMPLE` option. | |
23 | 37 | |
24 | 38 | ## Automated Testing |
25 | 39 | |
26 | Automated testing is still primarily taking place inside Schrodinger's internal build system, although tests are incrementally being added to the `testing` directory. Building the tests is enabled by default, but can be disabled by means of the `COORDGEN_BUILD_TESTS` option. | |
40 | Automated testing is still primarily taking place inside Schrodinger's internal | |
41 | build system, although tests are incrementally being added to the `testing` | |
42 | directory. Building the tests is enabled by default, but can be disabled by | |
43 | means of the `COORDGEN_BUILD_TESTS` option. | |
27 | 44 | |
28 | Memory debugging is, by default, configured to use `valgrind`. It can be run on the tests by passing `-DCMAKE_BUILD_TYPE=Debug` to cmake, to enable building the debugging symbols, and then using `ctest -T memcheck` inside the build directory. | |
45 | Memory debugging is, by default, configured to use `valgrind`. It can be run on | |
46 | the tests by passing `-DCMAKE_BUILD_TYPE=Debug` to cmake, to enable building | |
47 | the debugging symbols, and then using `ctest -T memcheck` inside the build | |
48 | directory. | |
29 | 49 | |
30 | 50 | ## Building from source |
31 | 51 | |
32 | 52 | ### Requirements |
33 | 53 | |
34 | To build coordgen, you will need to have the following installed in your system: | |
54 | To build coordgen, you will need to have the following installed in your | |
55 | system: | |
35 | 56 | |
36 | 57 | - **CMake** version 3.2 or later. |
37 | - The development files for the **Boost libraries**. At least the **iostreams** and **regex** components are required. In case of also building the unit tests, the **filesystems** and **unit_test_framework** components will also be required. | |
58 | - The development files for the **Boost libraries**. At least the **iostreams** | |
59 | and **regex** components are required. In case of also building the unit | |
60 | tests, the **filesystems** and **unit_test_framework** components will also | |
61 | be required. | |
38 | 62 | - A **C++ compiler** supporting the C++11 standard. |
39 | 63 | - A compiled instance of the **maeparser library** or its source code. |
40 | 64 | |
41 | In case **maeparser** is not available on your system, neither as a compiled library or as source code, if a working `git` executable and an internet connection are available, the builder can automatically download the source and build **maeparser** for you. | |
65 | In case **maeparser** is not available on your system, neither as a compiled | |
66 | library or as source code, if a working `git` executable and an internet | |
67 | connection are available, the builder can automatically download the source and | |
68 | build **maeparser** for you. | |
42 | 69 | |
43 | 70 | ### Building |
44 | 71 | |
45 | 1. Create a build directory inside the the one that contains Coordgen, and move into it: | |
72 | 1. Create a build directory inside the the one that contains Coordgen, and move | |
73 | into it: | |
46 | 74 | |
47 | ```bash | |
48 | mkdir build | |
49 | cd build | |
50 | ``` | |
75 | ```bash | |
76 | mkdir build | |
77 | cd build | |
78 | ``` | |
51 | 79 | |
52 | 1. Run `cmake` to configure the build, passing the path to the directory where the sources are located (just `..` if you created `build` inside the sources directory). At this point, you should add any required flags to the `cmake` command. Check the 'Options' section in CMakeLists.txt to see which options are available. | |
80 | 1. Run `cmake` to configure the build, passing the path to the directory where | |
81 | the sources are located (just `..` if you created `build` inside the sources | |
82 | directory). At this point, you should add any required flags to the `cmake` | |
83 | command. Check the 'Options' section in CMakeLists.txt to see which options | |
84 | are available. | |
53 | 85 | |
54 | ```bash | |
55 | cmake .. -Dmaeparser_DIR=/home/schrodinger/maeparser_install -DCMAKE_INSTALL_PREFIX=/home/schrodinger/coordgen_install` | |
56 | ``` | |
86 | ```bash | |
87 | cmake .. -Dmaeparser_DIR=/home/schrodinger/maeparser_install -DCMAKE_INSTALL_PREFIX=/home/schrodinger/coordgen_install` | |
88 | ``` | |
57 | 89 | |
58 | A few notes on the maeparser dependency: | |
90 | A few notes on the maeparser dependency: | |
59 | 91 | |
60 | - CMake will, by default, search your system's default library paths for the maeparser library. If a `CMAKE_INSTALL_PREFIX` was specified to Coordgen, CMake will also search for maeparser there. | |
92 | - CMake will, by default, search your system's default library paths for | |
93 | the maeparser library. If a `CMAKE_INSTALL_PREFIX` was specified to | |
94 | Coordgen, CMake will also search for maeparser there. | |
61 | 95 | |
62 | - If you already built and installed maeparser using the `CMAKE_INSTALL_PREFIX` to set the installation path, you should pass the exact same path to Coordgen with `maeparser_DIR`. | |
96 | - If you already built and installed maeparser using the | |
97 | `CMAKE_INSTALL_PREFIX` to set the installation path, you should pass the | |
98 | exact same path to Coordgen with `maeparser_DIR`. | |
63 | 99 | |
64 | - If CMake cannot find a compiled library for maeparser, it will attempt to download the source code from GitHub and build it. The release to be downloaded if the library is not found can be set using the `-DMAEPARSER_VERSION` flag. The sources will be stored in a directory named like `maeparser-{MAEPARSER_VERSION}` under the coordgen sources. | |
100 | - If CMake cannot find a compiled library for maeparser, it will attempt to | |
101 | download the source code from GitHub and build it. The release to be | |
102 | downloaded if the library is not found can be set using the | |
103 | `-DMAEPARSER_VERSION` flag. The sources will be stored in a directory | |
104 | named like `maeparser-{MAEPARSER_VERSION}` under the coordgen sources. | |
65 | 105 | |
66 | - If `maeparser_DIR` was passed to CMake, and the library was not found, CMake will **NOT** download the sources from GitHub (since we expected to find a compiled library). | |
106 | - If `maeparser_DIR` was passed to CMake, and the library was not found, | |
107 | CMake will **NOT** download the sources from GitHub (since we expected to | |
108 | find a compiled library). | |
67 | 109 | |
68 | - If a copy of maeparser's source is found under the proper path, it be used, instead of being downloaded again. | |
110 | - If a copy of maeparser's source is found under the proper path, it be | |
111 | used, instead of being downloaded again. | |
69 | 112 | |
70 | - If you want to use Coordgen in a CMake project that also depends on maeparser, set up the maeparser first, as Coordgen will be able to find and use it, without searching for further libraries or compiling it again from the source code. | |
113 | - If you want to use Coordgen in a CMake project that also depends on | |
114 | maeparser, set up the maeparser first, as Coordgen will be able to find | |
115 | and use it, without searching for further libraries or compiling it again | |
116 | from the source code. | |
71 | 117 | |
72 | 118 | 1. Build and install: |
73 | 119 | |
74 | ```bash | |
75 | make -j install | |
76 | ``` | |
120 | ```bash | |
121 | make -j install | |
122 | ``` |
2 | 2 | - dev/* |
3 | 3 | |
4 | 4 | jobs: |
5 | - job: Ubuntu_18_04_x64 | |
5 | - job: Ubuntu_20_04_x64 | |
6 | 6 | timeoutInMinutes: 90 |
7 | 7 | pool: |
8 | vmImage: ubuntu-18.04 | |
8 | vmImage: ubuntu-20.04 | |
9 | 9 | variables: |
10 | compiler: gxx_linux-64=7.2.0 | |
10 | compiler: gxx_linux-64 | |
11 | 11 | boost_version: 1.67.0 |
12 | 12 | number_of_cores: nproc |
13 | 13 | python_name: python37 |
14 | 14 | shared_lib: ON |
15 | 15 | steps: |
16 | 16 | - template: .azure-pipelines/linux_build.yml |
17 | - job: Ubuntu_18_04_x64_static | |
17 | - job: Ubuntu_20_04_x64_static | |
18 | 18 | timeoutInMinutes: 90 |
19 | 19 | pool: |
20 | vmImage: ubuntu-18.04 | |
20 | vmImage: ubuntu-20.04 | |
21 | 21 | variables: |
22 | compiler: gxx_linux-64=7.2.0 | |
22 | compiler: gxx_linux-64 | |
23 | 23 | boost_version: 1.67.0 |
24 | 24 | number_of_cores: nproc |
25 | 25 | python_name: python37 |
26 | 26 | shared_lib: OFF |
27 | 27 | steps: |
28 | 28 | - template: .azure-pipelines/linux_build.yml |
29 | - job: macOS_10_14_x64 | |
29 | - job: macOS_10_15_x64 | |
30 | 30 | timeoutInMinutes: 90 |
31 | 31 | pool: |
32 | vmImage: macos-10.14 | |
32 | vmImage: macos-10.15 | |
33 | 33 | variables: |
34 | 34 | compiler: clangxx_osx-64 |
35 | 35 | boost_version: 1.67.0 |
39 | 39 | shared_lib: ON |
40 | 40 | steps: |
41 | 41 | - template: .azure-pipelines/mac_build.yml |
42 | - job: macOS_10_14_x64_static | |
42 | - job: macOS_10_15_x64_static | |
43 | 43 | timeoutInMinutes: 90 |
44 | 44 | pool: |
45 | vmImage: macos-10.14 | |
45 | vmImage: macos-10.15 | |
46 | 46 | variables: |
47 | 47 | compiler: clangxx_osx-64 |
48 | 48 | boost_version: 1.67.0 |
52 | 52 | shared_lib: OFF |
53 | 53 | steps: |
54 | 54 | - template: .azure-pipelines/mac_build.yml |
55 | - job: Windows_VS2017_x64 | |
55 | - job: Windows_VS2019_x64 | |
56 | 56 | timeoutInMinutes: 90 |
57 | 57 | pool: |
58 | vmImage: vs2017-win2016 | |
58 | vmImage: windows-2019 | |
59 | 59 | variables: |
60 | compiler: vs2017_win-64 | |
60 | compiler: vs2019_win-64 | |
61 | 61 | boost_version: 1.67.0 |
62 | 62 | number_of_cores: "%NUMBER_OF_PROCESSORS%" |
63 | 63 | python_name: python37 |
65 | 65 | boost_lib_prefix: "" |
66 | 66 | steps: |
67 | 67 | - template: .azure-pipelines/vs_build.yml |
68 | - job: Windows_VS2017_x64_static | |
68 | - job: Windows_VS2019_x64_static | |
69 | 69 | timeoutInMinutes: 90 |
70 | 70 | pool: |
71 | vmImage: vs2017-win2016 | |
71 | vmImage: windows-2019 | |
72 | 72 | variables: |
73 | compiler: vs2017_win-64 | |
73 | compiler: vs2019_win-64 | |
74 | 74 | boost_version: 1.67.0 |
75 | 75 | number_of_cores: "%NUMBER_OF_PROCESSORS%" |
76 | 76 | python_name: python37 |
115 | 115 | q.push(minMol->_atoms[scoreMaxI]); |
116 | 116 | minMol->_atoms[scoreMaxI]->_generalUseVisited = true; |
117 | 117 | |
118 | while (q.size()) { | |
118 | while (!q.empty()) { | |
119 | 119 | sketcherMinimizerAtom* at = q.front(); |
120 | 120 | newAtoms.push_back(at); |
121 | 121 | q.pop(); |
280 | 280 | |
281 | 281 | bool sketcherMinimizer::structurePassSanityCheck() const |
282 | 282 | { |
283 | if (!m_atoms.size()) { | |
283 | if (m_atoms.empty()) { | |
284 | 284 | return false; |
285 | 285 | } |
286 | 286 | for (auto molecule : m_molecules) { |
372 | 372 | sketcherMinimizerMolecule* mol, vector<sketcherMinimizerMolecule*>& mols) |
373 | 373 | { |
374 | 374 | |
375 | if (!mol->_atoms.size()) { | |
375 | if (mol->_atoms.empty()) { | |
376 | 376 | mols.push_back(mol); |
377 | 377 | return; |
378 | 378 | } |
387 | 387 | break; |
388 | 388 | } |
389 | 389 | } |
390 | while (q.size()) { | |
390 | while (!q.empty()) { | |
391 | 391 | sketcherMinimizerAtom* a = q.front(); |
392 | 392 | q.pop(); |
393 | 393 | a->_generalUseVisited = true; |
404 | 404 | newAtoms.push_back(a); |
405 | 405 | } |
406 | 406 | } |
407 | if (!newAtoms.size()) { | |
407 | if (newAtoms.empty()) { | |
408 | 408 | mols.push_back(mol); |
409 | 409 | for (sketcherMinimizerMolecule* m : mols) { |
410 | 410 | for (sketcherMinimizerAtom* a : m->_atoms) { |
455 | 455 | const sketcherMinimizerAtom* at2, |
456 | 456 | const sketcherMinimizerAtom* at3) |
457 | 457 | { |
458 | if (!at1->rings.size()) { | |
458 | if (at1->rings.empty()) { | |
459 | 459 | return nullptr; |
460 | 460 | } |
461 | if (!at2->rings.size()) { | |
461 | if (at2->rings.empty()) { | |
462 | 462 | return nullptr; |
463 | 463 | } |
464 | if (!at3->rings.size()) { | |
464 | if (at3->rings.empty()) { | |
465 | 465 | return nullptr; |
466 | 466 | } |
467 | 467 | sketcherMinimizerRing* r = nullptr; |
532 | 532 | if (lastAtom) { |
533 | 533 | queue<sketcherMinimizerAtom*> q; |
534 | 534 | q.push(lastAtom); |
535 | while (q.size()) { | |
535 | while (!q.empty()) { | |
536 | 536 | lastAtom = q.front(); |
537 | 537 | q.pop(); |
538 | 538 | lastAtom->_generalUseVisited = true; |
627 | 627 | sketcherMinimizerPointF cent(0.f, 0.f); |
628 | 628 | for (sketcherMinimizerAtom* a : mol->_atoms) |
629 | 629 | cent += a->coordinates; |
630 | if (mol->_atoms.size()) { | |
630 | if (!mol->_atoms.empty()) { | |
631 | 631 | cent /= mol->_atoms.size(); |
632 | 632 | } |
633 | 633 | |
786 | 786 | break; |
787 | 787 | } |
788 | 788 | } |
789 | if (!angles.size()) { | |
789 | if (angles.empty()) { | |
790 | 790 | angles.emplace_back(weight, angle); |
791 | 791 | } |
792 | 792 | } |
832 | 832 | float weight = 1.f; |
833 | 833 | auto increment = static_cast<float>(M_PI / 6); |
834 | 834 | for (sketcherMinimizerAtom* a : mol->_atoms) { |
835 | if (a->rings.size()) { | |
835 | if (!a->rings.empty()) { | |
836 | 836 | continue; |
837 | 837 | } |
838 | 838 | if (a->neighbors.size() > 1) { |
988 | 988 | } |
989 | 989 | } |
990 | 990 | |
991 | if (angles.size()) { | |
991 | if (!angles.empty()) { | |
992 | 992 | int bestI = 0; |
993 | 993 | for (i = 0; i < angles.size(); i++) { |
994 | 994 | if (angles[i].first > angles[bestI].first) { |
1000 | 1000 | sketcherMinimizerPointF center(0.f, 0.f); |
1001 | 1001 | for (sketcherMinimizerAtom* at : mol->_atoms) |
1002 | 1002 | center += at->coordinates; |
1003 | if (mol->_atoms.size()) { | |
1003 | if (!mol->_atoms.empty()) { | |
1004 | 1004 | center /= mol->_atoms.size(); |
1005 | 1005 | } |
1006 | 1006 | |
1051 | 1051 | void sketcherMinimizer::findFragments() |
1052 | 1052 | { |
1053 | 1053 | |
1054 | assert(m_molecules.size()); | |
1054 | assert(!m_molecules.empty()); | |
1055 | 1055 | for (sketcherMinimizerMolecule* mol : m_molecules) { |
1056 | 1056 | CoordgenFragmenter::splitIntoFragments(mol); |
1057 | if (!mol->_fragments.size()) { | |
1057 | if (mol->_fragments.empty()) { | |
1058 | 1058 | continue; |
1059 | 1059 | } |
1060 | 1060 | vector<sketcherMinimizerFragment*> fragments = mol->_fragments; |
1150 | 1150 | } |
1151 | 1151 | |
1152 | 1152 | sketcherMinimizer min; |
1153 | if (metaMol->_atoms.size()) { | |
1153 | if (!metaMol->_atoms.empty()) { | |
1154 | 1154 | min.setEvenAngles(true); |
1155 | 1155 | min.initialize(metaMol); |
1156 | 1156 | findFragments(); |
1205 | 1205 | } |
1206 | 1206 | residueQueue.push(residue); |
1207 | 1207 | visitedResidues.insert(residue); |
1208 | while (residueQueue.size()) { | |
1208 | while (!residueQueue.empty()) { | |
1209 | 1209 | auto topResidue = residueQueue.front(); |
1210 | 1210 | finalVec.push_back(topResidue); |
1211 | 1211 | residueQueue.pop(); |
1455 | 1455 | sketcherMinimizerPointF position = shape.at(index); |
1456 | 1456 | if (alreadyAResidueHere || |
1457 | 1457 | (placeOnlyInteracting && |
1458 | !residue->residueInteractionPartners.size())) { | |
1458 | residue->residueInteractionPartners.empty())) { | |
1459 | 1459 | outliers.insert(residue); |
1460 | 1460 | } else { |
1461 | 1461 | residue->coordinates = position; |
1667 | 1667 | return firstContour.size() > secondContour.size(); |
1668 | 1668 | }); |
1669 | 1669 | vector<sketcherMinimizerPointF> returnValue; |
1670 | if (result.size() > 0) { | |
1670 | if (!result.empty()) { | |
1671 | 1671 | for (unsigned int i = 0; i < result.at(0).size(); i += 2) { |
1672 | 1672 | returnValue.emplace_back(result.at(0).at(i), |
1673 | 1673 | result.at(0).at(i + 1)); |
1722 | 1722 | void sketcherMinimizer::placeResidues( |
1723 | 1723 | const vector<sketcherMinimizerAtom*>& atoms) |
1724 | 1724 | { |
1725 | if (!m_residues.size()) { | |
1725 | if (m_residues.empty()) { | |
1726 | 1726 | return; |
1727 | 1727 | } |
1728 | if (!atoms.size()) { | |
1728 | if (atoms.empty()) { | |
1729 | 1729 | placeResiduesProteinOnlyMode(); |
1730 | 1730 | return; |
1731 | 1731 | } |
2141 | 2141 | mol->isPlaced = true; |
2142 | 2142 | continue; |
2143 | 2143 | } |
2144 | if (mol->m_proximityRelations.size()) { | |
2144 | if (!mol->m_proximityRelations.empty()) { | |
2145 | 2145 | sketcherMinimizerPointF atomsCenter = |
2146 | 2146 | sketcherMinimizerPointF(0, 0); |
2147 | 2147 | int atomsN = 0; |
2245 | 2245 | |
2246 | 2246 | auto* metaMol = new sketcherMinimizerMolecule; |
2247 | 2247 | for (sketcherMinimizerMolecule* mol : m_molecules) { |
2248 | if (mol->m_proximityRelations.size()) { | |
2248 | if (!mol->m_proximityRelations.empty()) { | |
2249 | 2249 | auto* a = new sketcherMinimizerAtom; |
2250 | 2250 | a->molecule = metaMol; |
2251 | 2251 | metaMol->_atoms.push_back(a); |
2276 | 2276 | } |
2277 | 2277 | sketcherMinimizer min(m_minimizer.getPrecision()); |
2278 | 2278 | |
2279 | if (metaMol->_atoms.size()) { | |
2279 | if (!metaMol->_atoms.empty()) { | |
2280 | 2280 | min.setEvenAngles(true); |
2281 | 2281 | |
2282 | 2282 | min.initialize(metaMol); |
2293 | 2293 | // a bonding pattern |
2294 | 2294 | |
2295 | 2295 | for (auto molecule : min.m_molecules) { |
2296 | if (molecule->_rings.size() > | |
2297 | 0) { // if at least three molecules are connected to each other | |
2296 | if (!molecule->_rings.empty()) { | |
2297 | // if at least three molecules are connected to each other | |
2298 | 2298 | // (i.e. two residues are connected to each other and both to |
2299 | 2299 | // the ligand) abort the ligandResidue display style) |
2300 | 2300 | ligandResidueStyle = false; |
2331 | 2331 | map<sketcherMinimizerMolecule*, sketcherMinimizerMolecule*> getParent; |
2332 | 2332 | |
2333 | 2333 | q.push(centralMol); |
2334 | while (q.size()) { | |
2334 | while (!q.empty()) { | |
2335 | 2335 | sketcherMinimizerMolecule* mol = q.front(); |
2336 | 2336 | q.pop(); |
2337 | 2337 | if (mol->isPlaced) { |
2405 | 2405 | if (b->isResidueInteraction()) { |
2406 | 2406 | auto* ri = static_cast<sketcherMinimizerResidueInteraction*>(b); |
2407 | 2407 | if (ri->startAtom->molecule == parent && |
2408 | ri->m_otherStartAtoms.size()) { | |
2408 | !ri->m_otherStartAtoms.empty()) { | |
2409 | 2409 | paddV = sketcherMinimizerAtom::getSingleAdditionVector( |
2410 | 2410 | ri->getAllStartAtoms()); |
2411 | 2411 | } else if (ri->endAtom->molecule == parent && |
2412 | ri->m_otherEndAtoms.size()) { | |
2412 | !ri->m_otherEndAtoms.empty()) { | |
2413 | 2413 | paddV = sketcherMinimizerAtom::getSingleAdditionVector( |
2414 | 2414 | ri->getAllEndAtoms()); |
2415 | 2415 | } |
2547 | 2547 | // find centers for molecules bound by proximity relations |
2548 | 2548 | vector<sketcherMinimizerMolecule*> proximityMols; |
2549 | 2549 | for (sketcherMinimizerMolecule* mol : m_molecules) { |
2550 | if (mol->m_proximityRelations.size()) { | |
2550 | if (!mol->m_proximityRelations.empty()) { | |
2551 | 2551 | proximityMols.push_back(mol); |
2552 | 2552 | } |
2553 | 2553 | } |
2554 | 2554 | sketcherMinimizerPointF center(0.f, 0.f); |
2555 | if (proximityMols.size()) { | |
2555 | if (!proximityMols.empty()) { | |
2556 | 2556 | placeMoleculesWithProximityRelations(proximityMols); |
2557 | 2557 | } else { |
2558 | 2558 | int maxI = 0; |
2712 | 2712 | void sketcherMinimizer::initializeFragments() |
2713 | 2713 | { |
2714 | 2714 | |
2715 | if (!_fragments.size()) { | |
2715 | if (_fragments.empty()) { | |
2716 | 2716 | cerr << "Sketcherlibs warning: no fragments to initialize" << endl; |
2717 | 2717 | return; |
2718 | 2718 | } |
3320 | 3320 | } |
3321 | 3321 | |
3322 | 3322 | bool ok = false; |
3323 | if (b->rings.size() == 0) { | |
3323 | if (b->rings.empty()) { | |
3324 | 3324 | ok = true; |
3325 | 3325 | } else { |
3326 | 3326 | ok = true; |
3538 | 3538 | } |
3539 | 3539 | } |
3540 | 3540 | |
3541 | if (dds.size()) { | |
3541 | if (!dds.empty()) { | |
3542 | 3542 | int maxI = 0; |
3543 | 3543 | for (unsigned int i = 0; i < ns.size(); ++i) { |
3544 | 3544 | if (ns[i] > ns[maxI]) { |
405 | 405 | /* score the position of the given strands */ |
406 | 406 | float scoreSSEPosition(const std::vector<sketcherMinimizerResidue*>& SSE, |
407 | 407 | const std::vector<sketcherMinimizerPointF>& shape, |
408 | int shapeN, std::vector<bool>& penalties, float f, | |
408 | int shapeN, std::vector<bool>& penalties, float startingPosition, | |
409 | 409 | float increment); |
410 | 410 | |
411 | 411 | /* score the distance between the two given points of connected residues */ |
113 | 113 | for (size_t i = 0; i < a.allParents.size(); i++) { |
114 | 114 | os << a.allParents[i]->atomicNumber << "(" |
115 | 115 | << (*a.scores)[a.allParents[i]] << ")"; |
116 | if ((*a.medals)[a.allParents[i]].size()) { | |
116 | if (!(*a.medals)[a.allParents[i]].empty()) { | |
117 | 117 | cerr << "<"; |
118 | 118 | for (int ii : (*a.medals)[a.allParents[i]]) { |
119 | 119 | cerr << ii << "|"; |
231 | 231 | { |
232 | 232 | /* return a ring shared by the two atoms. return a non-macrocycle if |
233 | 233 | * possible */ |
234 | if (!atom1->rings.size()) { | |
234 | if (atom1->rings.empty()) { | |
235 | 235 | return nullptr; |
236 | 236 | } |
237 | if (!atom2->rings.size()) { | |
237 | if (atom2->rings.empty()) { | |
238 | 238 | return nullptr; |
239 | 239 | } |
240 | 240 | |
350 | 350 | vector<sketcherMinimizerAtom*> |
351 | 351 | sketcherMinimizerAtom::clockwiseOrderedNeighbors() const |
352 | 352 | { |
353 | vector<pair<float, sketcherMinimizerAtom*>> rankedNeighbors; | |
354 | rankedNeighbors.reserve(neighbors.size()); | |
355 | for (auto&& neighbor : neighbors) { | |
356 | float newAngle = sketcherMinimizerMaths::signedAngle( | |
357 | neighbors[0]->coordinates, coordinates, | |
358 | neighbor->coordinates); | |
359 | if (std::isnan(newAngle)) { | |
360 | newAngle = 361; | |
361 | } else if (newAngle < 0) { | |
362 | newAngle += 360; | |
363 | } | |
364 | rankedNeighbors.emplace_back(newAngle, neighbor); | |
365 | } | |
366 | std::sort(rankedNeighbors.begin(), rankedNeighbors.end()); | |
353 | 367 | vector<sketcherMinimizerAtom*> orderedNeighs; |
354 | vector<sketcherMinimizerAtom*> neighs = neighbors; | |
355 | int lastPoppedIndex = 0; | |
356 | sketcherMinimizerAtom* lastPoppedAtom = neighs[lastPoppedIndex]; | |
357 | orderedNeighs.push_back(lastPoppedAtom); | |
358 | neighs.erase(neighs.begin() + lastPoppedIndex); | |
359 | ||
360 | while (neighs.size()) { | |
361 | float smallestAngle = 361; | |
362 | for (unsigned int i = 0; i < neighs.size(); i++) { | |
363 | float newAngle = sketcherMinimizerMaths::signedAngle( | |
364 | lastPoppedAtom->coordinates, coordinates, | |
365 | neighs[i]->coordinates); | |
366 | if (newAngle < 0) { | |
367 | newAngle += 360; | |
368 | } | |
369 | if (newAngle < smallestAngle) { | |
370 | smallestAngle = newAngle; | |
371 | lastPoppedIndex = i; | |
372 | } | |
373 | } | |
374 | lastPoppedAtom = neighs[lastPoppedIndex]; | |
375 | orderedNeighs.push_back(lastPoppedAtom); | |
376 | neighs.erase(neighs.begin() + lastPoppedIndex); | |
368 | orderedNeighs.reserve(neighbors.size()); | |
369 | for (const auto& rankedNeighbor : rankedNeighbors) { | |
370 | orderedNeighs.push_back(rankedNeighbor.second); | |
377 | 371 | } |
378 | 372 | return orderedNeighs; |
379 | 373 | } |
419 | 413 | bbonds.erase(bbonds.begin() + lastPoppedIndex); |
420 | 414 | |
421 | 415 | // TODO: consider using sketcherMinimizerAtom::clockwiseOrderedNeighbors |
422 | while (neighs.size()) { // order atoms | |
416 | while (!neighs.empty()) { // order atoms | |
423 | 417 | float smallestAngle = 361; |
424 | 418 | for (unsigned int i = 0; i < neighs.size(); i++) { |
425 | 419 | float newAngle = sketcherMinimizerMaths::signedAngle( |
830 | 824 | center->_generalUseVisited = true; |
831 | 825 | atomPriorities[i].a->_generalUseVisited = true; |
832 | 826 | int counter = 0; |
833 | while (q.size()) { | |
827 | while (!q.empty()) { | |
834 | 828 | counter++; |
835 | 829 | sketcherMinimizerAtom* at = q.front(); |
836 | 830 | q.pop(); |
968 | 962 | assert(center->molecule); |
969 | 963 | assert(at1->molecule == center->molecule); |
970 | 964 | assert(at2->molecule == center->molecule); |
971 | assert(center->molecule->_atoms.size()); | |
965 | assert(!center->molecule->_atoms.empty()); | |
972 | 966 | assert(at1); |
973 | 967 | assert(at2); |
974 | 968 | |
1018 | 1012 | |
1019 | 1013 | int level = 1; |
1020 | 1014 | |
1021 | while (AN1.size() || AN2.size()) { | |
1015 | while (!AN1.empty() || !AN2.empty()) { | |
1022 | 1016 | level++; |
1023 | 1017 | |
1024 | 1018 | stable_sort(AN1.begin(), AN1.end()); |
1068 | 1062 | vector<CIPAtom> copyV = V; |
1069 | 1063 | V.clear(); |
1070 | 1064 | map<sketcherMinimizerAtom*, unsigned int> friendsMask; |
1071 | while (copyV.size()) { | |
1065 | while (!copyV.empty()) { | |
1072 | 1066 | int bestI = 0; |
1073 | 1067 | for (unsigned int i = 1; i < copyV.size(); i++) { |
1074 | 1068 | if (copyV[i].isBetter(copyV[bestI], &friendsMask)) { |
1158 | 1152 | void sketcherMinimizerAtom::assignMedals(vector<CIPAtom>& v) |
1159 | 1153 | { |
1160 | 1154 | |
1161 | if (v.size() < 1) { | |
1155 | if (v.empty()) { | |
1162 | 1156 | return; |
1163 | 1157 | } |
1164 | 1158 | map<sketcherMinimizerAtom*, vector<int>>* medals = v[0].medals; |
1197 | 1191 | void sketcherMinimizerAtom::finalizeScores(vector<CIPAtom>& v) |
1198 | 1192 | { |
1199 | 1193 | |
1200 | if (v.size() < 1) { | |
1194 | if (v.empty()) { | |
1201 | 1195 | return; |
1202 | 1196 | } |
1203 | 1197 | vector<bool> isEqualToPrevious(v.size()); |
1277 | 1271 | bnds.erase(bnds.begin() + lastPoppedIndex); |
1278 | 1272 | |
1279 | 1273 | // TODO: consider using sketcherMinimizerAtom::clockwiseOrderedNeighbors |
1280 | while (neighs.size()) { // order atoms | |
1274 | while (!neighs.empty()) { // order atoms | |
1281 | 1275 | float smallestAngle = 361; |
1282 | 1276 | for (unsigned int i = 0; i < neighs.size(); i++) { |
1283 | 1277 | float newAngle = sketcherMinimizerMaths::signedAngle( |
1567 | 1561 | { |
1568 | 1562 | sketcherMinimizerPointF out(0.f, 0.f); |
1569 | 1563 | float totalf = 0.f; |
1570 | if (neighbors.size()) { | |
1564 | if (!neighbors.empty()) { | |
1571 | 1565 | for (auto neighbor : neighbors) { |
1572 | 1566 | float f = 1.f; |
1573 | 1567 | if (sketcherMinimizer::sameRing(this, neighbor)) { |
1677 | 1671 | isVisited[excludedAtom] = true; |
1678 | 1672 | q.push(this); |
1679 | 1673 | isVisited[this] = true; |
1680 | while (q.size()) { | |
1674 | while (!q.empty()) { | |
1681 | 1675 | sketcherMinimizerAtom* atom = q.front(); |
1682 | 1676 | subMolecule.push_back(atom); |
1683 | 1677 | q.pop(); |
123 | 123 | |
124 | 124 | int CoordgenScaleFragmentDOF::numberOfStates() const |
125 | 125 | { |
126 | if (m_fragment->getRings().size() == 0) { | |
126 | if (m_fragment->getRings().empty()) { | |
127 | 127 | return 1; |
128 | 128 | } |
129 | 129 | return 5; |
282 | 282 | : CoordgenFragmentDOF(pivotAtom->getFragment()), m_pivotAtom(pivotAtom), |
283 | 283 | m_boundAtom(boundAtom) |
284 | 284 | { |
285 | assert(pivotAtom->bondTo(boundAtom) != NULL); | |
285 | assert(pivotAtom->bondTo(boundAtom) != nullptr); | |
286 | 286 | addAtom(boundAtom); |
287 | 287 | } |
288 | 288 |
76 | 76 | return m_grid; |
77 | 77 | }; // returns a vector of all the data set with setValue. |
78 | 78 | |
79 | float getNodeValue(unsigned int i, unsigned int j) const; | |
79 | float getNodeValue(unsigned int x, unsigned int y) const; | |
80 | 80 | |
81 | 81 | private: |
82 | 82 | void addSide(sketcherMinimizerMarchingSquaresPoint* p1, |
61 | 61 | min.setY(0.f); |
62 | 62 | max.setX(0.f); |
63 | 63 | max.setY(0.f); |
64 | if (_atoms.size()) { | |
64 | if (!_atoms.empty()) { | |
65 | 65 | min = _atoms[0]->coordinates; |
66 | 66 | max = _atoms[0]->coordinates; |
67 | 67 | for (auto a : _atoms) { |
93 | 93 | |
94 | 94 | sketcherMinimizerPointF sketcherMinimizerMolecule::center() |
95 | 95 | { |
96 | if (!_atoms.size()) { | |
96 | if (_atoms.empty()) { | |
97 | 97 | return sketcherMinimizerPointF(0.f, 0.f); |
98 | 98 | } |
99 | 99 | sketcherMinimizerPointF c(.0f, .0f); |
433 | 433 | fragmentBuilder.orderRingAtoms(ring); |
434 | 434 | std::vector<doubleBondConstraint> constraints = |
435 | 435 | macrocycleBuilder.getDoubleBondConstraints(atoms); |
436 | BOOST_REQUIRE(constraints.size() == 0); | |
436 | BOOST_REQUIRE(constraints.empty()); | |
437 | 437 | } |
438 | 438 | } |
439 | 439 | } |
488 | 488 | BOOST_REQUIRE_EQUAL(orderedNeighbors[1], neigh3); |
489 | 489 | BOOST_REQUIRE_EQUAL(orderedNeighbors[2], neigh2); |
490 | 490 | } |
491 | ||
492 | BOOST_AUTO_TEST_CASE(testClockwiseOrderedNaN) | |
493 | { | |
494 | std::unique_ptr<sketcherMinimizerMolecule> mol("CN(C)C"_smiles); | |
495 | auto& atoms = mol->getAtoms(); | |
496 | sketcherMinimizerAtom* center = atoms.at(0); | |
497 | sketcherMinimizerAtom* neigh1 = atoms.at(1); | |
498 | neigh1->coordinates = sketcherMinimizerPointF(std::nanf("name"), std::nanf("name")); | |
499 | const auto orderedNeighbors = center->clockwiseOrderedNeighbors(); | |
500 | } | |
501 | ||
491 | 502 | |
492 | 503 | BOOST_AUTO_TEST_CASE(testbicyclopentane) |
493 | 504 | { |