diff --git a/api/tests/integration/ref/formats/cdx.py.out b/api/tests/integration/ref/formats/cdx.py.out index 187f1b7ba3..d85e04b319 100644 --- a/api/tests/integration/ref/formats/cdx.py.out +++ b/api/tests/integration/ref/formats/cdx.py.out @@ -692,7 +692,7 @@ Properties: ***** 5 Smiles: -c:c +CC Molfile: -INDIGO-01000000002D @@ -700,7 +700,7 @@ Molfile: 2 1 0 0 0 0 0 0 0 0999 V2000 9.3843 -4.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 10.2507 -3.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 - 1 2 4 0 0 0 0 + 1 2 5 0 0 0 0 M END Properties: diff --git a/core/indigo-core/molecule/CDXCommons.h b/core/indigo-core/molecule/CDXCommons.h index 58a63eb96b..8dd86b2874 100644 --- a/core/indigo-core/molecule/CDXCommons.h +++ b/core/indigo-core/molecule/CDXCommons.h @@ -456,6 +456,17 @@ namespace indigo {kCDXBondDisplay_Dot, "Dot"}, {kCDXBondDisplay_DashDot, "DashDot"}}; + static const std::unordered_map> display_to_direction = {{kCDXBondDisplay_WedgedHashBegin, {BOND_DOWN, false}}, + {kCDXBondDisplay_WedgedHashEnd, {BOND_DOWN, true}}, + {kCDXBondDisplay_Hash, {BOND_DOWN, false}}, + {kCDXBondDisplay_Dash, {BOND_DOWN, false}}, + {kCDXBondDisplay_WedgeBegin, {BOND_UP, false}}, + {kCDXBondDisplay_WedgeEnd, {BOND_UP, true}}, + {kCDXBondDisplay_HollowWedgeBegin, {BOND_UP, false}}, + {kCDXBondDisplay_HollowWedgeEnd, {BOND_UP, true}}, + {kCDXBondDisplay_Bold, {BOND_UP, false}}, + {kCDXBondDisplay_Wavy, {BOND_EITHER, false}}}; + const std::unordered_map kCDXEnhancedStereoStrToID = {{"Unspecified", EnhancedStereoType::UNSPECIFIED}, {"None", EnhancedStereoType::NONE}, {"Absolute", EnhancedStereoType::ABSOLUTE}, diff --git a/core/indigo-core/molecule/molecule_cdxml_loader.h b/core/indigo-core/molecule/molecule_cdxml_loader.h index 602fa3391c..de53741bdb 100644 --- a/core/indigo-core/molecule/molecule_cdxml_loader.h +++ b/core/indigo-core/molecule/molecule_cdxml_loader.h @@ -159,7 +159,7 @@ namespace indigo struct CdxmlBond { - CdxmlBond() : order(1), stereo(0), dir(0), topology(0), reaction_center(0), swap_bond(false) + CdxmlBond() : order(1), stereo(0), dir(0), display(0), display2(0), topology(0), reaction_center(0), swap_bond(false) { } AutoInt id; @@ -167,6 +167,8 @@ namespace indigo AutoInt order; AutoInt stereo; AutoInt dir; + AutoInt display; + AutoInt display2; AutoInt topology; AutoInt reaction_center; bool swap_bond; diff --git a/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp b/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp index c4f355fbda..faa10fae2f 100644 --- a/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp +++ b/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp @@ -253,7 +253,8 @@ std::string CDXProperty::parseCDXINT16(int16_t val) const return KNodeTypeIntToName.at(val); } break; - case kCDXProp_Bond_Display: { + case kCDXProp_Bond_Display: + case kCDXProp_Bond_Display2: { return kCDXProp_Bond_DisplayIdToStr.at((CDXBondDisplay)val); } break; @@ -759,12 +760,20 @@ int MoleculeCdxmlLoader::_addBond(Molecule& mol, const CdxmlBond& bond, int begi // bond topology is allowed only for queries but queries not supported for now // if (bond.topology > 0 && _pqmol == nullptr) // throw Error("bond topology is allowed only for queries"); - int bond_idx = _pmol != nullptr ? _pmol->addBond_Silent(begin, end, bond.order) - : _pqmol->addBond(begin, end, QueryMolecule::createQueryMoleculeBond(bond.order, bond.topology, bond.dir)); - if (bond.order == BOND_DOUBLE && bond.dir == BOND_EITHER) + int order = bond.order; + int direction = bond.dir; + + if (order == BOND_AROMATIC && bond.display == kCDXBondDisplay_Solid && bond.display2 == kCDXBondDisplay_Dash) // tautomeric bond + { + order = _BOND_SINGLE_OR_DOUBLE; + } + + int bond_idx = _pmol != nullptr ? _pmol->addBond_Silent(begin, end, order) + : _pqmol->addBond(begin, end, QueryMolecule::createQueryMoleculeBond(order, bond.topology, direction)); + if (order == BOND_DOUBLE && direction == BOND_EITHER) mol.cis_trans.ignore(bond_idx); - else if (bond.dir > 0 && bond.order == BOND_SINGLE) - mol.setBondDirection(bond_idx, bond.dir); + else if (direction > 0 && order == BOND_SINGLE) + mol.setBondDirection(bond_idx, direction); if (bond.reaction_center > 0) mol.reaction_bond_reacting_center[bond_idx] = bond.reaction_center; @@ -1267,19 +1276,14 @@ void MoleculeCdxmlLoader::_parseBond(CdxmlBond& bond, BaseCDXProperty& prop) auto stereo_lambda = [&bond](const std::string& data) { bond.stereo = kCIPBondStereochemistryCharToIndex.at(data.front()); }; - auto bond_dir_lambda = [&bond](const std::string& data) { - static const std::unordered_map> dir_map = {{"WedgedHashBegin", {BOND_DOWN, false}}, - {"WedgedHashEnd", {BOND_DOWN, true}}, - {"Hash", {BOND_DOWN, false}}, - {"Dash", {BOND_DOWN, false}}, - {"WedgeBegin", {BOND_UP, false}}, - {"WedgeEnd", {BOND_UP, true}}, - {"HollowWedgeBegin", {BOND_UP, false}}, - {"HollowWedgeEnd", {BOND_UP, true}}, - {"Bold", {BOND_UP, false}}, - {"Wavy", {BOND_EITHER, false}}}; - auto disp_it = dir_map.find(data); - if (disp_it != dir_map.end()) + auto bond_display_lambda = [&bond](const std::string& data) { + auto dislay_it = kCDXProp_Bond_DisplayStrToID.find(data); + if (dislay_it != kCDXProp_Bond_DisplayStrToID.end()) + { + bond.display = dislay_it->second; + } + auto disp_it = display_to_direction.find(bond.display); + if (disp_it != display_to_direction.end()) { auto& dir = disp_it->second; bond.dir = dir.first; @@ -1287,6 +1291,14 @@ void MoleculeCdxmlLoader::_parseBond(CdxmlBond& bond, BaseCDXProperty& prop) } }; + auto bond_display2_lambda = [&bond](const std::string& data) { + auto disp_it = kCDXProp_Bond_DisplayStrToID.find(data); + if (disp_it != kCDXProp_Bond_DisplayStrToID.end()) + { + bond.display2 = disp_it->second; + } + }; + auto reaction_center_lambda = [&bond](const std::string& data) { uint8_t rxn_participation = kBondReactionParticipationNameToInt.at(data); auto it = bond_rxn_participation_to_reaction_center.find(rxn_participation); @@ -1303,7 +1315,8 @@ void MoleculeCdxmlLoader::_parseBond(CdxmlBond& bond, BaseCDXProperty& prop) {"B", bond_begin_lambda}, {"E", bond_end_lambda}, {"Order", bond_order_lambda}, - {"Display", bond_dir_lambda}, + {"Display", bond_display_lambda}, + {"Display2", bond_display2_lambda}, {"BS", stereo_lambda}, {"RxnParticipation", reaction_center_lambda}, {"Topology", topology_lambda}};