Skip to content

Commit

Permalink
Backmerge: #1452 Convert from implicit hydrogens change layout (#1554)
Browse files Browse the repository at this point in the history
  • Loading branch information
AliaksandrDziarkach authored Jan 22, 2024
1 parent a8742ec commit 6934d7d
Show file tree
Hide file tree
Showing 8 changed files with 375 additions and 407 deletions.
20 changes: 19 additions & 1 deletion api/c/indigo/src/indigo_misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "base_cpp/output.h"
#include "base_cpp/scanner.h"
#include "layout/molecule_layout.h"
#include "molecule/elements.h"
#include "molecule/icm_loader.h"
#include "molecule/icm_saver.h"
Expand Down Expand Up @@ -456,7 +457,24 @@ CEXPORT int indigoUnfoldHydrogens(int item)

if (IndigoBaseMolecule::is(obj))
{
obj.getBaseMolecule().unfoldHydrogens(&markers, -1);
BaseMolecule& bmol = obj.getBaseMolecule();
bmol.unfoldHydrogens(&markers, -1);
// Layout hydrogens
MoleculeLayoutGraphSimple layout;
layout.preserve_existing_layout = true;
layout.makeOnGraph(bmol);
for (int i = layout.vertexBegin(); i < layout.vertexEnd(); i = layout.vertexNext(i))
{
const Vec3f& pos = bmol.getAtomXyz(layout.getVertexExtIdx(i));
layout.getPos(i).set(pos.x, pos.y);
}
Filter new_filter(markers.ptr(), Filter::EQ, 1);
layout.layout(bmol, 1, &new_filter, true);
for (int i = layout.vertexBegin(); i < layout.vertexEnd(); i = layout.vertexNext(i))
{
const LayoutVertex& vert = layout.getLayoutVertex(i);
bmol.setAtomXyz(vert.ext_idx, vert.pos.x, vert.pos.y, 0.f);
}
}
else if (IndigoBaseReaction::is(obj))
{
Expand Down
76 changes: 76 additions & 0 deletions api/tests/integration/ref/basic/unfold_layout_hydrogens.py.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

testing molfile:

-INDIGO-01102422162D

7 7 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0972 2.5109 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0935 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
5.8603 0.9988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
8.0828 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
4 5 1 0 0 0 0
5 7 1 0 0 0 0
7 6 1 0 0 0 0
6 4 1 0 0 0 0
M END


Unfolded mol equal to expected

After fold molfile:

-INDIGO-01000000002D

7 7 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0972 2.5109 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0935 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
5.8603 0.9988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
8.0828 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
4 5 1 0 0 0 0
5 7 1 0 0 0 0
7 6 1 0 0 0 0
6 4 1 0 0 0 0
M END


testing molfile:

-INDIGO-01102422162D

3 3 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
M END


Unfolded mol equal to expected

After fold molfile:

-INDIGO-01000000002D

3 3 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
M END

145 changes: 145 additions & 0 deletions api/tests/integration/tests/basic/unfold_layout_hydrogens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
from __future__ import print_function

import difflib
import os
import sys

sys.path.append(
os.path.normpath(
os.path.join(os.path.abspath(__file__), "..", "..", "..", "common")
)
)
from env_indigo import * # noqa

indigo = Indigo()
indigo.setOption("molfile-saving-skip-date", "1")


def test_mol_unfold(mol, expected_unfolded):
print("\ntesting molfile:\n%s" % mol)
molecule = indigo.loadMolecule(mol)
molecule.unfoldHydrogens()
unfolded = molecule.molfile()
unfolded_list = sorted(unfolded.split("\n"))
expected_unfolded_list = sorted(expected_unfolded.split("\n"))
diff = "".join(difflib.context_diff(unfolded_list, expected_unfolded_list))
if diff:
print("\nDiff between expected and after unfold molfile:\n%s" % diff)
else:
print("Unfolded mol equal to expected")
molecule.foldHydrogens()
print("\nAfter fold molfile:\n%s" % molecule.molfile())


multi_component_mol = """
-INDIGO-01102422162D
7 7 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0972 2.5109 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0935 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
5.8603 0.9988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
8.0828 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
4 5 1 0 0 0 0
5 7 1 0 0 0 0
7 6 1 0 0 0 0
6 4 1 0 0 0 0
M END
"""

multi_component_mol_unfolded = """
-INDIGO-01000000002D
21 21 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0972 2.5109 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
9.0935 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
5.8603 0.9988 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
8.0828 3.5060 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.0000 5.5688 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1.7654 4.2413 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
3.8801 5.5686 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
3.1146 4.2413 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1.6743 6.7340 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
3.2060 6.7339 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
9.3856 1.5534 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
10.0862 2.6585 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
9.0923 4.5060 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
10.0935 3.5085 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
5.9099 0.0000 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
4.9168 1.3303 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
7.1974 3.9709 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
8.3222 4.4769 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
4 5 1 0 0 0 0
5 7 1 0 0 0 0
7 6 1 0 0 0 0
6 4 1 0 0 0 0
1 8 1 0 0 0 0
1 9 1 0 0 0 0
2 10 1 0 0 0 0
2 11 1 0 0 0 0
3 12 1 0 0 0 0
3 13 1 0 0 0 0
4 14 1 0 0 0 0
4 15 1 0 0 0 0
5 16 1 0 0 0 0
5 17 1 0 0 0 0
6 18 1 0 0 0 0
6 19 1 0 0 0 0
7 20 1 0 0 0 0
7 21 1 0 0 0 0
M END
"""
test_mol_unfold(multi_component_mol, multi_component_mol_unfolded)

single_component_mol = """
-INDIGO-01102422162D
3 3 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
M END
"""

single_component_mol_unfolded = """
-INDIGO-01000000002D
9 9 0 0 0 0 0 0 0 0999 V2000
1.9394 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.9406 5.2260 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.4401 6.0909 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.0000 5.5688 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1.7654 4.2413 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
3.8801 5.5686 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
3.1146 4.2413 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1.6743 6.7340 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
3.2060 6.7339 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 1 1 0 0 0 0
1 4 1 0 0 0 0
1 5 1 0 0 0 0
2 6 1 0 0 0 0
2 7 1 0 0 0 0
3 8 1 0 0 0 0
3 9 1 0 0 0 0
M END
"""

test_mol_unfold(single_component_mol, single_component_mol_unfolded)
2 changes: 0 additions & 2 deletions api/wasm/indigo-ketcher/indigo-ketcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,9 +466,7 @@ namespace indigo
}
else
{
indigoSetOptionBool("layout-preserve-existing", true);
_checkResult(indigoUnfoldHydrogens(iko.id()));
indigoSetOptionBool("layout-preserve-existing", false);
}
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}
Expand Down
37 changes: 14 additions & 23 deletions core/indigo-core/layout/molecule_layout_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ namespace indigo
void cloneLayoutGraph(MoleculeLayoutGraph& other, Array<int>* mapping);
void copyLayoutTo(MoleculeLayoutGraph& other, const Array<int>& mapping) const;

virtual void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing) = 0;
virtual void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing);

const BaseMolecule* getMolecule(const int** molecule_edge_mapping) const
{
Expand All @@ -169,6 +169,8 @@ namespace indigo
int max_iterations;
layout_orientation_value layout_orientation;

bool preserve_existing_layout;

CancellationHandler* cancellation;

DECL_ERROR;
Expand Down Expand Up @@ -295,8 +297,12 @@ namespace indigo
bool _isPointOutsideCycleEx(const Cycle& cycle, const Vec2f& p, const Array<int>& mapping) const;
static bool _border_cb(Graph& graph, const Array<int>& vertices, const Array<int>& edges, void* context);

void getBoundingBox(Rect2f& bbox) const;
void getBoundingBox(Vec2f& left_bottom, Vec2f& right_top) const;
void copyCoordsFromComponent(MoleculeLayoutGraph& component, Vec2f shift = {0, 0});

// for components
virtual void _calcMorganCodes() = 0;
virtual void _calcMorganCodes();

// for whole graph
virtual void _assignAbsoluteCoordinates(float bond_length) = 0;
Expand Down Expand Up @@ -336,6 +342,12 @@ namespace indigo
void _attachCrossingEdges();

void _buildOutline(void);

// make tree of biconnected components (tree[i] - component incoming to vertex i or -1)
static void _makeComponentsTree(BiconnectedDecomposer& decon, PtrArray<MoleculeLayoutGraph>& components, Array<int>& tree);

void _layoutMultipleComponents(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
void _layoutSingleComponent(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
};

class DLLEXPORT MoleculeLayoutGraphSimple : public MoleculeLayoutGraph
Expand All @@ -352,8 +364,6 @@ namespace indigo

void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& filter) override;

void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing) override;

void flipped() override
{
_flipped = true;
Expand All @@ -378,9 +388,6 @@ namespace indigo
// for whole graph
void _assignAbsoluteCoordinates(float bond_length) override;

// for components
void _calcMorganCodes() override;

// assigning coordinates
void _assignRelativeCoordinates(int& fixed_component, const MoleculeLayoutGraph& supergraph) override;
bool _tryToFindPattern(int& fixed_component);
Expand All @@ -404,12 +411,6 @@ namespace indigo
bool _isPointOutsideCycle(const Cycle& cycle, const Vec2f& p) const override;

static bool _edge_check(Graph& graph, int e_idx, void* context);

// make tree of biconnected components (tree[i] - component incoming to vertex i or -1)
static void _makeComponentsTree(BiconnectedDecomposer& decon, PtrArray<MoleculeLayoutGraph>& components, Array<int>& tree);

void _layoutMultipleComponents(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
void _layoutSingleComponent(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
};

struct local_pair_ii
Expand Down Expand Up @@ -571,7 +572,6 @@ namespace indigo

void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& vertex_filter) override;
void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& vertex_filter, Filter* edge_filter);
void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing) override;

void calcMorganCode();
long getMorganCode();
Expand Down Expand Up @@ -608,9 +608,6 @@ namespace indigo
// for whole graph
void _assignAbsoluteCoordinates(float bond_length) override;

// for components
void _calcMorganCodes() override;

// assigning coordinates
struct interval
{
Expand Down Expand Up @@ -674,12 +671,6 @@ namespace indigo
const float _energyOfPoint(Vec2f p) const;
int _isCisConfiguratuin(Vec2f p1, Vec2f p2, Vec2f p3, Vec2f p4);

// make tree of biconnected components (tree[i] - -1 or component incoming to vertex i)
static void _makeComponentsTree(BiconnectedDecomposer& decon, PtrArray<MoleculeLayoutGraph>& components, Array<int>& tree);

void _layoutMultipleComponents(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
void _layoutSingleComponent(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);

Array<int> _layout_component_number; // number of layout component of certain edge
int _layout_component_count;

Expand Down
Loading

0 comments on commit 6934d7d

Please sign in to comment.