@@ -152,14 +152,22 @@ void MoleculeCdxmlLoader::_parseCollections(BaseMolecule& mol)
152
152
int node_idx = _id_to_node_index.at (node.id );
153
153
switch (node.type )
154
154
{
155
+ case kCDXNodeType_NamedAlternativeGroup :
155
156
case kCDXNodeType_Element :
156
157
case kCDXNodeType_ElementList :
157
158
atoms.push_back (node_idx);
158
159
break ;
159
160
case kCDXNodeType_ExternalConnectionPoint : {
160
- auto & fn = nodes[_fragment_nodes.back ()];
161
- if (fn.connections .size () == 0 )
162
- fn.ext_connections .push_back (node.id );
161
+ if (_fragment_nodes.size ())
162
+ {
163
+ auto & fn = nodes[_fragment_nodes.back ()];
164
+ if (fn.connections .size () == 0 )
165
+ fn.ext_connections .push_back (node.id );
166
+ }
167
+ else
168
+ {
169
+ // handle free external connection. attachment point?
170
+ }
163
171
}
164
172
break ;
165
173
case kCDXNodeType_Nickname :
@@ -366,9 +374,11 @@ void MoleculeCdxmlLoader::_parseCDXMLElements(CDXElement elem, bool no_siblings,
366
374
367
375
auto arrow_lambda = [this ](CDXElement elem) { this ->_parseArrow (elem); };
368
376
377
+ auto altgroup_lambda = [this ](CDXElement elem) { this ->_parseAltGroup (elem); };
378
+
369
379
std::unordered_map<std::string, std::function<void (CDXElement elem)>> cdxml_dispatcher = {
370
- {" n" , node_lambda}, {" b" , bond_lambda}, {" fragment" , fragment_lambda}, {" group" , group_lambda}, {" bracketedgroup" , bracketed_lambda},
371
- {" t" , text_lambda}, {" graphic" , graphic_lambda}, {" arrow" , arrow_lambda}};
380
+ {" n" , node_lambda}, {" b" , bond_lambda}, {" fragment" , fragment_lambda}, {" group" , group_lambda}, {" bracketedgroup" , bracketed_lambda},
381
+ {" t" , text_lambda}, {" graphic" , graphic_lambda}, {" arrow" , arrow_lambda}, { " altgroup " , altgroup_lambda} };
372
382
373
383
for (elem; elem.hasContent (); elem = elem.nextSiblingElement ())
374
384
{
@@ -416,6 +426,10 @@ void MoleculeCdxmlLoader::_addAtomsAndBonds(BaseMolecule& mol, const std::vector
416
426
if (_pmol)
417
427
{
418
428
atom_idx = _pmol->addAtom (atom.element );
429
+
430
+ if (atom.type == kCDXNodeType_NamedAlternativeGroup )
431
+ mol.allowRGroupOnRSite (atom_idx, atom.rg_index );
432
+
419
433
_id_to_atom_idx.emplace (atom.id , atom_idx);
420
434
mol.setAtomXyz (atom_idx, atom.pos );
421
435
_pmol->setAtomCharge_Silent (atom_idx, atom.charge );
@@ -752,7 +766,11 @@ void MoleculeCdxmlLoader::_parseNode(CdxmlNode& node, CDXElement elem)
752
766
753
767
auto stereo_lambda = [&node](const std::string& data) { node.stereo = KCIPStereochemistryCharToIndex.at (data.front ()); };
754
768
755
- auto node_type_lambda = [&node](const std::string& data) { node.type = KNodeTypeNameToInt.at (data); };
769
+ auto node_type_lambda = [&node](const std::string& data) {
770
+ node.type = KNodeTypeNameToInt.at (data);
771
+ if (node.type == kCDXNodeType_NamedAlternativeGroup )
772
+ node.element = ELEM_RSITE;
773
+ };
756
774
757
775
auto element_list_lambda = [&node](const std::string& data) {
758
776
std::vector<std::string> elements = split (data, ' ' );
@@ -770,25 +788,36 @@ void MoleculeCdxmlLoader::_parseNode(CdxmlNode& node, CDXElement elem)
770
788
771
789
auto enhanced_stereo_group_lambda = [&node](const std::string& data) { node.enhanced_stereo_group = data; };
772
790
773
- std::unordered_map<std::string, std::function<void (const std::string&)>> node_dispatcher = {
774
- {" id" , id_lambda},
775
- {" p" , pos_lambda},
776
- {" xyz" , pos_lambda},
777
- {" NumHydrogens" , hydrogens_lambda},
778
- {" Charge" , charge_lambda},
779
- {" Isotope" , isotope_lambda},
780
- {" Radical" , radical_lambda},
781
- {" AS" , stereo_lambda},
782
- {" NodeType" , node_type_lambda},
783
- {" Element" , element_lambda},
784
- {" GenericNickname" , label_lambda},
785
- {" ElementList" , element_list_lambda},
786
- {" BondOrdering" , bond_ordering_lambda},
787
- {" Geometry" , geometry_lambda},
788
- {" EnhancedStereoType" , enhanced_stereo_type_lambda},
789
- {" EnhancedStereoGroupNum" , enhanced_stereo_group_lambda},
790
- };
791
+ auto alt_group_id_lambda = [&node](const std::string& data) { node.alt_group_id = data; };
792
+
793
+ std::unordered_map<std::string, std::function<void (const std::string&)>> node_dispatcher = {{" id" , id_lambda},
794
+ {" p" , pos_lambda},
795
+ {" xyz" , pos_lambda},
796
+ {" NumHydrogens" , hydrogens_lambda},
797
+ {" Charge" , charge_lambda},
798
+ {" Isotope" , isotope_lambda},
799
+ {" Radical" , radical_lambda},
800
+ {" AS" , stereo_lambda},
801
+ {" NodeType" , node_type_lambda},
802
+ {" Element" , element_lambda},
803
+ {" GenericNickname" , label_lambda},
804
+ {" ElementList" , element_list_lambda},
805
+ {" BondOrdering" , bond_ordering_lambda},
806
+ {" Geometry" , geometry_lambda},
807
+ {" EnhancedStereoType" , enhanced_stereo_type_lambda},
808
+ {" EnhancedStereoGroupNum" , enhanced_stereo_group_lambda},
809
+ {" AltGroupID" , alt_group_id_lambda}};
791
810
applyDispatcher (elem.firstProperty (), node_dispatcher);
811
+ for (auto child_elem = elem.firstChildElement (); child_elem.hasContent (); child_elem = child_elem.nextSiblingElement ())
812
+ {
813
+ if (child_elem.name () == " t" )
814
+ {
815
+ std::string label;
816
+ _parseLabel (child_elem, label);
817
+ if (label.find (" R" ) == 0 )
818
+ node.rg_index = label.substr (1 );
819
+ }
820
+ }
792
821
}
793
822
794
823
void MoleculeCdxmlLoader::_addNode (CdxmlNode& node)
@@ -879,6 +908,37 @@ void MoleculeCdxmlLoader::parseBBox(const std::string& data, Rect2f& bbox)
879
908
throw Error (" Not enought coordinates for text bounding box" );
880
909
}
881
910
911
+ void MoleculeCdxmlLoader::_parseAltGroup (CDXElement elem)
912
+ {
913
+ std::vector<AutoInt> r_labels;
914
+ std::vector<CDXElement> r_fragments;
915
+ for (auto r_elem = elem.firstChildElement (); r_elem.hasContent (); r_elem = r_elem.nextSiblingElement ())
916
+ {
917
+ auto el_name = r_elem.name ();
918
+ if (el_name == " fragment" )
919
+ r_fragments.push_back (r_elem);
920
+ else if (el_name == " t" )
921
+ {
922
+ std::string rl;
923
+ _parseLabel (r_elem, rl);
924
+ if (rl.find (" R" ) == 0 )
925
+ r_labels.push_back (rl.substr (1 ));
926
+ }
927
+ }
928
+
929
+ if (r_fragments.size () && r_labels.size ())
930
+ {
931
+ MoleculeCdxmlLoader alt_loader (_scanner, _is_binary);
932
+ BaseMolecule& mol = _pmol ? *(BaseMolecule*)_pmol : *(BaseMolecule*)_pqmol;
933
+ std::unique_ptr<BaseMolecule> fragment (mol.neu ());
934
+ alt_loader.stereochemistry_options = stereochemistry_options;
935
+ alt_loader.loadMoleculeFromFragment (*fragment.get (), r_fragments.front ());
936
+ MoleculeRGroups& rgroups = mol.rgroups ;
937
+ RGroup& rgroup = rgroups.getRGroup (r_labels.front ());
938
+ rgroup.fragments .add (fragment.release ());
939
+ }
940
+ }
941
+
882
942
void MoleculeCdxmlLoader::_parseGraphic (CDXElement elem)
883
943
{
884
944
AutoInt superseded_id = 0 ;
0 commit comments