diff --git a/api/tests/integration/ref/formats/cdxml_to_mol.py.out b/api/tests/integration/ref/formats/cdxml_to_mol.py.out
index 72ef61c5e1..cdee36b9da 100644
--- a/api/tests/integration/ref/formats/cdxml_to_mol.py.out
+++ b/api/tests/integration/ref/formats/cdxml_to_mol.py.out
@@ -4,46 +4,46 @@ sgroups.cdxml
-INDIGO-01000000002D
40 36 0 0 0 0 0 0 0 0999 V2000
- 384.2900 7.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 396.7600 0.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 409.2300 7.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 421.7100 0.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 359.3500 7.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 371.8200 0.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 434.1800 7.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 446.6500 0.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 362.9500 153.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 375.4200 146.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 387.8900 153.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 400.3600 146.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 412.8300 153.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 425.3100 146.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 437.7800 153.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 450.2500 146.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 365.4700 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 377.9400 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 390.4100 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 402.8800 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 415.3500 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 427.8300 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 440.3000 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 452.7700 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 362.5900 52.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 375.0600 45.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 387.5300 52.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 400.0000 45.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 412.4700 52.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 424.9500 45.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 437.4200 52.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 449.8900 45.3100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 390.4100 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 402.8800 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 415.3500 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 427.8300 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 390.4100 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 402.8800 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 415.3500 105.0700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 427.8300 97.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.8363 -5.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.2520 -5.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.6677 -5.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.0837 -5.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.0050 -5.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.4207 -5.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.4993 -5.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.9150 -5.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.1250 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.5407 -0.4900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.9563 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.3720 -0.4900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.7877 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.2037 -0.4900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.6193 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.0350 -0.4900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.2090 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.6247 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.0403 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.4560 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.8717 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.2877 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.7033 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.1190 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.1130 -3.6100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.5287 -3.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.9443 -3.6100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.3600 -3.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.7757 -3.6100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.1917 -3.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.6073 -3.6100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.0230 -3.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.0403 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.4560 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.8717 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.2877 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.0403 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.4560 -2.0980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.8717 -1.8580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.2877 -2.0980 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 4 1 0 0 0 0
@@ -103,202 +103,202 @@ test-multi.cdxml
-INDIGO-01000000002D
196212 0 0 0 0 0 0 0 0999 V2000
- 290.9700 1245.0699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 264.9900 1230.0699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 239.0100 1245.0699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 290.9700 1275.0699 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 213.0300 1230.0699 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 333.8700 1062.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 333.7900 1092.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 359.7300 1107.5699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 307.7700 1107.4199 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 359.6500 1137.5699 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 307.9400 1047.4199 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 280.7000 1059.4299 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 260.7300 1037.1899 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 275.6700 1011.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 304.8600 1017.5800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 266.4200 982.9200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 286.3500 960.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 315.5300 966.7999 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 324.7900 995.1500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 329.6700 1062.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 329.5900 1092.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 355.5300 1107.5699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 303.5700 1107.4199 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 355.4500 1137.5699 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 303.7400 1047.4199 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 276.5000 1059.4299 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 256.5300 1037.1899 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 271.4700 1011.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 300.6600 1017.5800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 262.2200 982.9200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 282.1500 960.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 311.3300 966.7999 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 320.5900 995.1500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 214.7100 1139.7400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 216.7500 1191.6699 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 230.7200 1165.1200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 260.7000 1163.9399 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 274.6700 1137.3900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 276.7100 1189.3099 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 184.7400 1140.9199 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 232.7600 1217.0399 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 262.7400 1215.8600 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 218.7900 1243.5900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 234.8000 1268.9600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 264.7800 1267.7800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 280.7800 1293.1500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 266.8200 1319.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 236.8400 1320.8800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 220.8300 1295.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 149.7000 790.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 123.7200 775.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 97.7400 790.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 149.7000 820.5100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 71.7600 775.5099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 205.6800 790.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 231.6600 775.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 179.7000 775.5099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 231.6600 745.5099 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 214.9200 887.8300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 224.2500 916.1600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 253.4400 922.2400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 273.3200 899.9200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 234.7900 865.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 264.0000 871.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 278.8700 845.6400 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 258.8500 823.4500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 231.6400 835.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 205.6700 820.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 287.6400 775.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 313.6200 790.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 261.6600 790.5099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 313.6200 820.5100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 296.8700 678.1800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 306.2100 649.8600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 335.4000 643.7800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 355.2800 666.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 316.7500 700.6600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 345.9600 694.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 360.8400 720.3799 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 340.8100 742.5699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 313.6000 730.4900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 287.6300 745.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 417.5500 790.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 391.5700 745.5099 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 391.5700 775.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 365.5900 790.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 365.5900 820.5100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 339.6100 775.5099 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 417.5500 820.5100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 417.5500 730.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 417.5500 700.5099 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 443.5300 745.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 469.5100 730.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 469.5100 700.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 495.4900 685.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 521.4700 700.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 521.4700 730.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 495.4900 745.5099 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 168.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 253.5600 183.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 253.5600 213.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 201.6000 183.0200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 228.0200 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 253.5600 123.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 279.5400 138.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 138.0200 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 305.5200 123.0200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 190.9000 118.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 161.5600 124.9900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 141.4800 102.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 150.7500 74.1699 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 200.1700 90.2200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 180.1000 67.9299 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 195.1000 41.9500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 224.4400 48.1799 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 78.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 253.5600 93.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 305.5200 183.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 305.5200 213.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 279.5400 168.0200 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 331.5000 228.0200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 394.1600 142.2899 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 423.5000 136.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 443.5800 158.3400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 434.3100 186.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 384.8900 170.8199 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 404.9600 193.1100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 389.9600 219.0900 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 360.6200 212.8600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 357.4800 183.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 331.5000 168.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 258.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 253.5600 303.0200 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 253.5600 273.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 279.5400 258.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 305.5200 273.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 279.5400 228.0200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 201.6000 273.0200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 318.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 227.5800 348.0200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 201.6000 303.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 175.6200 318.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 175.6200 348.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 149.6400 363.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 123.6500 348.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 123.6500 318.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 149.6400 303.0200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 930.8300 826.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 901.4800 832.9399 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 881.4100 810.6400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 852.0600 816.8800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 831.9900 794.5800 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 842.7900 845.4100 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 813.4500 851.6500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 804.1800 880.1799 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 774.8300 886.4200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 824.2500 902.4700 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 814.9800 931.0100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 835.0500 953.2999 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 825.7800 981.8300 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 864.4000 947.0599 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 873.6700 918.5300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 903.0100 912.2900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 912.2800 883.7600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 941.6300 877.5200 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 892.2100 861.4700 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 785.6400 937.2400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 776.3700 965.7700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 794.0000 990.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 776.3700 1014.3199 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 747.8300 1005.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 747.8300 975.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 721.8500 960.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 695.8700 975.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 695.8700 1005.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 721.8500 1020.0499 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 793.3700 829.3500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 764.0300 835.5900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 751.8300 863.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 721.9900 859.8600 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 715.7500 830.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 741.7400 815.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 741.7400 785.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 715.7500 770.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 689.7700 785.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 689.7700 815.5200 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 890.6800 782.1100 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
- 920.0200 775.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 929.2900 747.3400 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
- 941.2400 797.0900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 970.2100 789.3199 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 991.4300 810.5300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 1020.4000 802.7700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 1028.1700 773.7900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 1006.9600 752.5800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
- 977.9800 760.3400 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.6673 -2.0793 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.8013 -2.5793 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.9353 -2.0793 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.6673 -1.0793 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.0693 -2.5793 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.0973 -8.1650 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.0947 -7.1650 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.9593 -6.6627 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.2273 -6.6677 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.9567 -5.6627 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.2330 -8.6677 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.3250 -8.2673 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.6593 -9.0087 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.1573 -9.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.1303 -9.6623 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.8490 -10.8177 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.5133 -11.5600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.4860 -11.3550 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.7947 -10.4100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.9573 -8.1650 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.9547 -7.1650 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.8193 -6.6627 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.0873 -6.6677 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.8167 -5.6627 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.0930 -8.6677 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.1850 -8.2673 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.5193 -9.0087 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.0173 -9.8700 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.9903 -9.6623 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.7090 -10.8177 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.3733 -11.5600 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.3460 -11.3550 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.6547 -10.4100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.1253 -5.5903 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.1933 -3.8593 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.6590 -4.7443 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.6583 -4.7837 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.1240 -5.6687 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.1920 -3.9380 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.1263 -5.5510 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.7270 -3.0137 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.7263 -3.0530 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.2613 -2.1287 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.7950 -1.2830 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.7943 -1.3223 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.3277 -0.4767 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.8623 0.4083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.8630 0.4477 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.3293 -0.3980 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.9583 -17.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.0923 -17.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 1.2263 -17.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.9583 -16.2313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 0.3603 -17.7313 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.8243 -17.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.6903 -17.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.9583 -17.7313 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.6903 -18.7313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.1323 -13.9873 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.4433 -13.0430 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4163 -12.8403 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.0790 -13.5843 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.7947 -14.7367 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.7683 -14.5313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.2640 -15.3937 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.5967 -16.1333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.6897 -15.7310 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.8240 -16.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.5563 -17.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.4223 -17.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.6903 -17.2313 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.4223 -16.2313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.8640 -20.9757 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.1753 -21.9197 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.1483 -22.1223 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.8110 -21.3783 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.5267 -20.2263 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.5003 -20.4317 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.9963 -19.5690 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.3287 -18.8293 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.4217 -19.2320 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.5560 -18.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.8867 -17.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.0207 -18.7313 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.0207 -17.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 10.1547 -17.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 10.1547 -16.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.2887 -17.7313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.8867 -16.2313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.8867 -19.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.8867 -20.2313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 12.7527 -18.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 13.6187 -19.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 13.6187 -20.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 14.4847 -20.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 15.3507 -20.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 15.3507 -19.2313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 14.4847 -18.7313 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -37.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4203 -37.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4203 -36.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.6883 -37.4810 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -35.9810 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4203 -39.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.2863 -38.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -38.9810 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.1523 -39.4810 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.3317 -39.6233 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.3537 -39.4153 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.6843 -40.1583 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.9933 -41.1093 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.6407 -40.5743 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.9717 -41.3173 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.4717 -42.1833 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.4497 -41.9757 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -40.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4203 -40.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.1523 -37.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.1523 -36.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.2863 -37.9810 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.0183 -35.9810 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.1070 -38.8387 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 12.0850 -39.0467 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 12.7543 -38.3037 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 12.4453 -37.3527 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 10.7980 -37.8877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 11.4670 -37.1447 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 10.9670 -36.2787 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.9890 -36.4863 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.8843 -37.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 9.0183 -37.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -34.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4203 -33.4810 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 6.4203 -34.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.2863 -34.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 8.1523 -34.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 7.2863 -35.9810 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.6883 -34.4810 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -32.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 5.5543 -31.9810 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 4.6883 -33.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.8223 -32.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 3.8223 -31.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.9563 -31.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.0900 -31.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.0900 -32.9810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 2.9563 -33.4810 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 28.9960 -16.0250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 28.0177 -15.8170 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 27.3487 -16.5603 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 26.3703 -16.3523 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 25.7013 -17.0957 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 26.0613 -15.4013 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 25.0833 -15.1933 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 24.7743 -14.2423 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 23.7960 -14.0343 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 25.4433 -13.4993 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 25.1343 -12.5480 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 25.8033 -11.8050 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 25.4943 -10.8540 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 26.7817 -12.0130 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 27.0907 -12.9640 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 28.0687 -13.1720 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 28.3777 -14.1230 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 29.3560 -14.3310 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 27.7087 -14.8660 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 24.1563 -12.3403 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 23.8473 -11.3893 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 24.4350 -10.5800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 23.8473 -9.7710 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.8960 -10.0800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.8960 -11.0800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.0300 -11.5800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 21.1640 -11.0800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 21.1640 -10.0800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.0300 -9.5800 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 24.4140 -15.9367 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 23.4360 -15.7287 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 23.0293 -14.8150 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.0347 -14.9197 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 21.8267 -15.8977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.6930 -16.3977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 22.6930 -17.3977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 21.8267 -17.8977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 20.9607 -17.3977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 20.9607 -16.3977 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 27.6577 -17.5113 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
+ 28.6357 -17.7193 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 28.9447 -18.6703 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
+ 29.3430 -17.0120 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 30.3087 -17.2710 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 31.0160 -16.5640 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 31.9817 -16.8227 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 32.2407 -17.7887 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 31.5337 -18.4957 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
+ 30.5677 -18.2370 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
1 4 2 0 0 0 0
diff --git a/api/tests/integration/ref/formats/linux/rxn_to_cdxml.py.out b/api/tests/integration/ref/formats/linux/rxn_to_cdxml.py.out
deleted file mode 100644
index ddc38675f8..0000000000
--- a/api/tests/integration/ref/formats/linux/rxn_to_cdxml.py.out
+++ /dev/null
@@ -1,2697 +0,0 @@
-*** Rxn to CDXML ***
-1-3-Quinazoline-2-4-dione.rxn
-*** Try as Reaction ***
-molfile loader: atom lists are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
- Cl,Br,I
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
-
-
-
-
- 1,3-Quinazoline 2,4-dione formation
-
-
-
-
-AcetylateSecondaryAmine.rxn
-*** Try as Reaction ***
-molfile loader: 'any' atoms are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
- N
-
-
-
-
- A
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
- N
-
-
-
-
- A
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-AmideFormation.ket
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-AmideFormation.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
- Amide Formation
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
- Amide Formation
-
-
-
-
-CN_Bond-S-GRP.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-CN_Bond.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-CN_Bond_map.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-Claisen.ket
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Claisen.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Markush6.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-SN2_XtoOR_Stereo.rxn
-*** Try as Reaction ***
-molfile loader: atom lists are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
-
- H
-
-
-
-
- A
-
-
-
-
- Cl,Br,I
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- H
-
-
-
-
-
-
-
- A
-
-
-
-
-
- H
-
-
-
-
- A
-
-
-
-
- OH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-amiderxn3.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
- NH
- 2
-
-
-
-
- R2
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
- NH
- 2
-
-
-
-
- R2
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-only_products.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-only_reactants.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-v3000.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
diff --git a/api/tests/integration/ref/formats/mac/rxn_to_cdxml.py.out b/api/tests/integration/ref/formats/mac/rxn_to_cdxml.py.out
deleted file mode 100644
index 46761d92dd..0000000000
--- a/api/tests/integration/ref/formats/mac/rxn_to_cdxml.py.out
+++ /dev/null
@@ -1,2697 +0,0 @@
-*** Rxn to CDXML ***
-1-3-Quinazoline-2-4-dione.rxn
-*** Try as Reaction ***
-molfile loader: atom lists are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
- Cl,Br,I
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
-
-
-
-
- 1,3-Quinazoline 2,4-dione formation
-
-
-
-
-AcetylateSecondaryAmine.rxn
-*** Try as Reaction ***
-molfile loader: 'any' atoms are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
- N
-
-
-
-
- A
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
- N
-
-
-
-
- A
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-AmideFormation.ket
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-AmideFormation.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
- Amide Formation
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
- Amide Formation
-
-
-
-
-CN_Bond-S-GRP.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-CN_Bond.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-CN_Bond_map.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-Claisen.ket
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Claisen.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Markush6.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-SN2_XtoOR_Stereo.rxn
-*** Try as Reaction ***
-molfile loader: atom lists are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
-
- H
-
-
-
-
- A
-
-
-
-
- Cl,Br,I
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- H
-
-
-
-
-
-
-
- A
-
-
-
-
-
- H
-
-
-
-
- A
-
-
-
-
- OH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-amiderxn3.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
- NH
- 2
-
-
-
-
- R2
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
- NH
- 2
-
-
-
-
- R2
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-only_products.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-only_reactants.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-v3000.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
diff --git a/api/tests/integration/ref/formats/mingw/rxn_to_cdxml.py.out b/api/tests/integration/ref/formats/mingw/rxn_to_cdxml.py.out
deleted file mode 100644
index ddc38675f8..0000000000
--- a/api/tests/integration/ref/formats/mingw/rxn_to_cdxml.py.out
+++ /dev/null
@@ -1,2697 +0,0 @@
-*** Rxn to CDXML ***
-1-3-Quinazoline-2-4-dione.rxn
-*** Try as Reaction ***
-molfile loader: atom lists are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
- Cl,Br,I
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
-
-
-
-
- 1,3-Quinazoline 2,4-dione formation
-
-
-
-
-AcetylateSecondaryAmine.rxn
-*** Try as Reaction ***
-molfile loader: 'any' atoms are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
- N
-
-
-
-
- A
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
- N
-
-
-
-
- A
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-AmideFormation.ket
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-AmideFormation.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
- Amide Formation
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
- Amide Formation
-
-
-
-
-CN_Bond-S-GRP.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-CN_Bond.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-CN_Bond_map.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-Claisen.ket
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Claisen.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- O
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Markush6.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- N
-
-
-
-
- O
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- R2
-
-
-
-
-
- R1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-SN2_XtoOR_Stereo.rxn
-*** Try as Reaction ***
-molfile loader: atom lists are allowed only for queries
-*** Try as QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A
-
-
-
-
-
- H
-
-
-
-
- A
-
-
-
-
- Cl,Br,I
-
-
-
-
-
-
-
-
-
-
- OH
-
-
-
-
- H
-
-
-
-
-
-
-
- A
-
-
-
-
-
- H
-
-
-
-
- A
-
-
-
-
- OH
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-amiderxn3.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
- NH
- 2
-
-
-
-
- R2
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- OH
-
-
-
-
-
-
-
-
-
- NH
- 2
-
-
-
-
- R2
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
-
-
- R1
-
-
-
-
-
- O
-
-
-
-
- NH
-
-
-
-
- R2
-
-
-
-
-
-
-
-
-
-
- R3
-
-
-
-
- SH
-
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-only_products.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-only_reactants.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-v3000.rxn
-*** Try as Reaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
-*** Compare with QueryReaction ***
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Br
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
- H
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
-
-
-
-
- NH
-
-
-
-
-
-
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
- +
-
-
-
-
-
-
-
-
diff --git a/api/tests/integration/ref/formats/mol_to_cdxml.py.out b/api/tests/integration/ref/formats/mol_to_cdxml.py.out
index c85fec3fc0..774328b082 100644
--- a/api/tests/integration/ref/formats/mol_to_cdxml.py.out
+++ b/api/tests/integration/ref/formats/mol_to_cdxml.py.out
@@ -4,8 +4,8 @@ stereo_either-0020.mol
-
-
+
+
diff --git a/api/tests/integration/ref/formats/rxn_to_cdxml.py.out b/api/tests/integration/ref/formats/rxn_to_cdxml.py.out
index 4b1c9bf6a2..16ab45eb92 100644
--- a/api/tests/integration/ref/formats/rxn_to_cdxml.py.out
+++ b/api/tests/integration/ref/formats/rxn_to_cdxml.py.out
@@ -7,8 +7,8 @@ molfile loader: atom lists are allowed only for queries
-
-
+
+
@@ -23,40 +23,40 @@ molfile loader: atom lists are allowed only for queries
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
N
-
-
-
+
+
+
O
-
-
+
+
O
-
-
+
+
H
-
-
+
+
H
-
-
+
+
H
@@ -75,24 +75,24 @@ molfile loader: atom lists are allowed only for queries
-
-
+
+
N
-
-
-
+
+
+
H
-
-
+
+
H
-
-
+
+
H
@@ -102,14 +102,14 @@ molfile loader: atom lists are allowed only for queries
-
-
-
+
+
+
Cl,Br,I
-
-
+
+
H
@@ -117,36 +117,36 @@ molfile loader: atom lists are allowed only for queries
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
N
-
-
-
+
+
+
N
-
-
+
+
O
-
-
+
+
O
-
-
+
+
@@ -163,17 +163,17 @@ molfile loader: atom lists are allowed only for queries
-
+
+
-
+
+
-
+
-
+
1,3-Quinazoline 2,4-dione formation
@@ -187,8 +187,8 @@ molfile loader: 'any' atoms are allowed only for queries
-
-
+
+
@@ -203,23 +203,23 @@ molfile loader: 'any' atoms are allowed only for queries
-
-
+
+
A
-
-
+
+
N
-
-
+
+
A
-
-
+
+
H
@@ -228,35 +228,35 @@ molfile loader: 'any' atoms are allowed only for queries
-
-
+
+
A
-
-
+
+
N
-
-
+
+
A
-
-
-
+
+
+
O
-
+
-
+
@@ -269,8 +269,8 @@ AmideFormation.ket
-
-
+
+
@@ -356,9 +356,9 @@ AmideFormation.ket
+
-
+
-
+
@@ -368,8 +368,8 @@ AmideFormation.ket
-
-
+
+
@@ -455,9 +455,9 @@ AmideFormation.ket
+
-
+
-
+
@@ -468,8 +468,8 @@ AmideFormation.rxn
-
-
+
+
@@ -484,20 +484,20 @@ AmideFormation.rxn
-
-
-
-
+
+
+
+
O
-
-
+
+
O
-
-
+
+
H
@@ -507,24 +507,24 @@ AmideFormation.rxn
-
-
+
+
N
-
-
-
+
+
+
H
-
-
+
+
H
-
-
+
+
H
@@ -534,32 +534,32 @@ AmideFormation.rxn
-
-
-
-
+
+
+
+
O
-
-
+
+
NH
-
+
-
+
+
-
+
-
+
Amide Formation
@@ -570,8 +570,8 @@ AmideFormation.rxn
-
-
+
+
@@ -586,20 +586,20 @@ AmideFormation.rxn
-
-
-
-
+
+
+
+
O
-
-
+
+
O
-
-
+
+
H
@@ -609,24 +609,24 @@ AmideFormation.rxn
-
-
+
+
N
-
-
-
+
+
+
H
-
-
+
+
H
-
-
+
+
H
@@ -636,32 +636,32 @@ AmideFormation.rxn
-
-
-
-
+
+
+
+
O
-
-
+
+
NH
-
+
-
+
+
-
+
-
+
Amide Formation
@@ -673,8 +673,8 @@ CN_Bond-S-GRP.rxn
-
-
+
+
@@ -689,23 +689,23 @@ CN_Bond-S-GRP.rxn
-
-
-
+
+
+
Br
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -713,20 +713,20 @@ CN_Bond-S-GRP.rxn
-
-
-
+
+
+
NH
-
+
-
+
+
-
+
@@ -738,8 +738,8 @@ CN_Bond-S-GRP.rxn
-
-
+
+
@@ -754,23 +754,23 @@ CN_Bond-S-GRP.rxn
-
-
-
+
+
+
Br
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -778,20 +778,20 @@ CN_Bond-S-GRP.rxn
-
-
-
+
+
+
NH
-
+
-
+
+
-
+
@@ -804,8 +804,8 @@ CN_Bond.rxn
-
-
+
+
@@ -820,10 +820,10 @@ CN_Bond.rxn
-
-
-
-
+
+
+
+
Br
@@ -831,14 +831,14 @@ CN_Bond.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -846,22 +846,22 @@ CN_Bond.rxn
-
-
-
-
+
+
+
+
NH
-
+
-
+
+
-
+
@@ -873,8 +873,8 @@ CN_Bond.rxn
-
-
+
+
@@ -889,10 +889,10 @@ CN_Bond.rxn
-
-
-
-
+
+
+
+
Br
@@ -900,14 +900,14 @@ CN_Bond.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -915,22 +915,22 @@ CN_Bond.rxn
-
-
-
-
+
+
+
+
NH
-
+
-
+
+
-
+
@@ -943,8 +943,8 @@ CN_Bond_map.rxn
-
-
+
+
@@ -959,10 +959,10 @@ CN_Bond_map.rxn
-
-
-
-
+
+
+
+
Br
@@ -970,14 +970,14 @@ CN_Bond_map.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -985,22 +985,22 @@ CN_Bond_map.rxn
-
-
-
-
+
+
+
+
NH
-
+
-
+
+
-
+
@@ -1012,8 +1012,8 @@ CN_Bond_map.rxn
-
-
+
+
@@ -1028,10 +1028,10 @@ CN_Bond_map.rxn
-
-
-
-
+
+
+
+
Br
@@ -1039,14 +1039,14 @@ CN_Bond_map.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -1054,22 +1054,22 @@ CN_Bond_map.rxn
-
-
-
-
+
+
+
+
NH
-
+
-
+
+
-
+
@@ -1082,8 +1082,8 @@ Claisen.ket
-
-
+
+
@@ -1124,14 +1124,14 @@ Claisen.ket
-
-
+
+
-
-
+
+
-
+
@@ -1149,9 +1149,9 @@ Claisen.ket
-
+
-
+
@@ -1161,8 +1161,8 @@ Claisen.ket
-
-
+
+
@@ -1203,14 +1203,14 @@ Claisen.ket
-
-
+
+
-
-
+
+
-
+
@@ -1228,9 +1228,9 @@ Claisen.ket
-
+
-
+
@@ -1241,8 +1241,8 @@ Claisen.rxn
-
-
+
+
@@ -1257,20 +1257,20 @@ Claisen.rxn
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
O
-
-
-
+
+
+
@@ -1283,17 +1283,17 @@ Claisen.rxn
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
OH
@@ -1308,7 +1308,7 @@ Claisen.rxn
-
+
@@ -1320,8 +1320,8 @@ Claisen.rxn
-
-
+
+
@@ -1336,20 +1336,20 @@ Claisen.rxn
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
O
-
-
-
+
+
+
@@ -1362,17 +1362,17 @@ Claisen.rxn
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
OH
@@ -1387,7 +1387,7 @@ Claisen.rxn
-
+
@@ -1400,8 +1400,8 @@ Markush6.rxn
-
-
+
+
@@ -1416,36 +1416,36 @@ Markush6.rxn
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
OH
-
-
+
+
O
-
-
+
+
H
-
-
+
+
H
-
-
-
+
+
+
R1
@@ -1463,33 +1463,33 @@ Markush6.rxn
-
-
+
+
N
-
-
+
+
H
-
-
+
+
H
-
-
-
-
-
-
+
+
+
+
+
+
NH
-
-
-
+
+
+
R2
@@ -1504,56 +1504,56 @@ Markush6.rxn
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
N
-
-
+
+
O
-
-
+
+
H
-
-
+
+
H
-
-
+
+
H
-
-
-
-
-
-
+
+
+
+
+
+
NH
-
-
-
+
+
+
R2
-
-
-
+
+
+
R1
@@ -1578,10 +1578,10 @@ Markush6.rxn
-
+
+
-
+
@@ -1593,8 +1593,8 @@ Markush6.rxn
-
-
+
+
@@ -1609,36 +1609,36 @@ Markush6.rxn
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
OH
-
-
+
+
O
-
-
+
+
H
-
-
+
+
H
-
-
-
+
+
+
R1
@@ -1656,33 +1656,33 @@ Markush6.rxn
-
-
+
+
N
-
-
+
+
H
-
-
+
+
H
-
-
-
-
-
-
+
+
+
+
+
+
NH
-
-
-
+
+
+
R2
@@ -1697,56 +1697,56 @@ Markush6.rxn
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
N
-
-
+
+
O
-
-
+
+
H
-
-
+
+
H
-
-
+
+
H
-
-
-
-
-
-
+
+
+
+
+
+
NH
-
-
-
+
+
+
R2
-
-
-
+
+
+
R1
@@ -1771,10 +1771,10 @@ Markush6.rxn
-
+
+
-
+
@@ -1789,8 +1789,8 @@ molfile loader: atom lists are allowed only for queries
-
-
+
+
@@ -1805,76 +1805,76 @@ molfile loader: atom lists are allowed only for queries
-
-
+
+
A
-
-
-
+
+
+
H
-
-
+
+
A
-
-
+
+
Cl,Br,I
-
-
+
+
-
-
+
+
OH
-
-
+
+
H
-
-
+
+
A
-
-
-
+
+
+
H
-
-
+
+
A
-
-
+
+
OH
-
-
+
+
-
+
+
-
+
@@ -1887,8 +1887,8 @@ amiderxn3.rxn
-
-
+
+
@@ -1903,19 +1903,19 @@ amiderxn3.rxn
-
-
+
+
R1
-
-
-
+
+
+
O
-
-
+
+
OH
@@ -1924,55 +1924,55 @@ amiderxn3.rxn
-
-
+
+
NH
2
-
-
+
+
R2
-
-
+
+
R3
-
-
+
+
SH
-
-
+
+
-
-
+
+
R1
-
-
-
+
+
+
O
-
-
+
+
NH
-
-
+
+
R2
@@ -1982,32 +1982,32 @@ amiderxn3.rxn
-
-
+
+
R3
-
-
+
+
SH
-
-
+
+
-
+
+
-
+
+
-
+
+
-
+
@@ -2019,8 +2019,8 @@ amiderxn3.rxn
-
-
+
+
@@ -2035,19 +2035,19 @@ amiderxn3.rxn
-
-
+
+
R1
-
-
-
+
+
+
O
-
-
+
+
OH
@@ -2056,55 +2056,55 @@ amiderxn3.rxn
-
-
+
+
NH
2
-
-
+
+
R2
-
-
+
+
R3
-
-
+
+
SH
-
-
+
+
-
-
+
+
R1
-
-
-
+
+
+
O
-
-
+
+
NH
-
-
+
+
R2
@@ -2114,32 +2114,32 @@ amiderxn3.rxn
-
-
+
+
R3
-
-
+
+
SH
-
-
+
+
-
+
+
-
+
+
-
+
+
-
+
@@ -2152,8 +2152,8 @@ only_products.rxn
-
-
+
+
@@ -2168,12 +2168,12 @@ only_products.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2182,12 +2182,12 @@ only_products.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2195,10 +2195,10 @@ only_products.rxn
-
+
+
-
+
@@ -2210,8 +2210,8 @@ only_products.rxn
-
-
+
+
@@ -2226,12 +2226,12 @@ only_products.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2240,12 +2240,12 @@ only_products.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2253,10 +2253,10 @@ only_products.rxn
-
+
+
-
+
@@ -2269,8 +2269,8 @@ only_reactants.rxn
-
-
+
+
@@ -2285,12 +2285,12 @@ only_reactants.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2299,12 +2299,12 @@ only_reactants.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2312,10 +2312,10 @@ only_reactants.rxn
-
+
+
-
+
@@ -2327,8 +2327,8 @@ only_reactants.rxn
-
-
+
+
@@ -2343,12 +2343,12 @@ only_reactants.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2357,12 +2357,12 @@ only_reactants.rxn
-
-
-
-
-
-
+
+
+
+
+
+
@@ -2370,10 +2370,10 @@ only_reactants.rxn
-
+
+
-
+
@@ -2386,8 +2386,8 @@ v3000.rxn
-
-
+
+
@@ -2402,10 +2402,10 @@ v3000.rxn
-
-
-
-
+
+
+
+
Br
@@ -2413,14 +2413,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2428,14 +2428,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2443,14 +2443,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2458,14 +2458,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2473,14 +2473,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2488,50 +2488,50 @@ v3000.rxn
-
-
-
-
+
+
+
+
NH
-
+
-
-
-
-
+
+
+
+
NH
-
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
@@ -2543,8 +2543,8 @@ v3000.rxn
-
-
+
+
@@ -2559,10 +2559,10 @@ v3000.rxn
-
-
-
-
+
+
+
+
Br
@@ -2570,14 +2570,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2585,14 +2585,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2600,14 +2600,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2615,14 +2615,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2630,14 +2630,14 @@ v3000.rxn
-
-
+
+
NH
-
-
-
+
+
+
H
@@ -2645,50 +2645,50 @@ v3000.rxn
-
-
-
-
+
+
+
+
NH
-
+
-
-
-
-
+
+
+
+
NH
-
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
diff --git a/api/tests/integration/tests/formats/rxn_to_cdxml.py b/api/tests/integration/tests/formats/rxn_to_cdxml.py
index 7259f38261..4f58a19871 100644
--- a/api/tests/integration/tests/formats/rxn_to_cdxml.py
+++ b/api/tests/integration/tests/formats/rxn_to_cdxml.py
@@ -21,16 +21,13 @@
print("*** Try as Reaction ***")
rxn = indigo.loadReactionFromFile(os.path.join(root, filename))
indigo.setOption("layout-horintervalfactor", "1.4")
- rxn.layout()
print(rxn.cdxml())
print("*** Compare with QueryReaction ***")
rxn2 = indigo.loadQueryReactionFromFile(os.path.join(root, filename))
- rxn2.layout()
print(rxn2.cdxml())
except IndigoException as e:
print(getIndigoExceptionText(e))
print("*** Try as QueryReaction ***")
rxn = indigo.loadQueryReactionFromFile(os.path.join(root, filename))
indigo.setOption("layout-horintervalfactor", "1.4")
- rxn.layout()
print(rxn.cdxml())
diff --git a/api/wasm/indigo-ketcher/indigo-ketcher.cpp b/api/wasm/indigo-ketcher/indigo-ketcher.cpp
index fb3e134e6a..c22fcd2e90 100644
--- a/api/wasm/indigo-ketcher/indigo-ketcher.cpp
+++ b/api/wasm/indigo-ketcher/indigo-ketcher.cpp
@@ -139,6 +139,10 @@ namespace indigo
{
return _checkResultString(indigoCml(id()));
}
+ else if (outputFormat == "cdxml" || outputFormat == "chemical/x-cdxml")
+ {
+ return _checkResultString(indigoCdxml(id()));
+ }
else if (outputFormat == "inchi" || outputFormat == "chemical/x-inchi")
{
return _checkResultString(indigoInchiGetInchi(id()));
diff --git a/core/indigo-core/common/base_cpp/properties_map.cpp b/core/indigo-core/common/base_cpp/properties_map.cpp
index 65a6283b77..f8312436c3 100644
--- a/core/indigo-core/common/base_cpp/properties_map.cpp
+++ b/core/indigo-core/common/base_cpp/properties_map.cpp
@@ -15,6 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
+#include
#include "base_cpp/properties_map.h"
@@ -38,6 +39,12 @@ void PropertiesMap::copy(PropertiesMap& other)
insert(other.key(p), other.value(p));
}
}
+
+void PropertiesMap::insert(const char* key, const std::string& value)
+{
+ insert(key, value.c_str());
+}
+
void PropertiesMap::insert(const char* key, const char* value)
{
if (_properties.find(key))
diff --git a/core/indigo-core/common/base_cpp/properties_map.h b/core/indigo-core/common/base_cpp/properties_map.h
index a2df3a2eba..fc35aaa735 100644
--- a/core/indigo-core/common/base_cpp/properties_map.h
+++ b/core/indigo-core/common/base_cpp/properties_map.h
@@ -45,6 +45,8 @@ namespace indigo
void copy(RedBlackStringObjMap>& properties);
void copy(PropertiesMap&);
void insert(const char* key, const char* value);
+ void insert(const char* key, const std::string& value);
+
Array& insert(const char* key);
const char* key(int);
diff --git a/core/indigo-core/common/math/algebra.h b/core/indigo-core/common/math/algebra.h
index 498b1119b5..310e5d05e5 100644
--- a/core/indigo-core/common/math/algebra.h
+++ b/core/indigo-core/common/math/algebra.h
@@ -417,6 +417,16 @@ namespace indigo
return Vec2f(middleX(), middleY());
}
+ inline float width() const
+ {
+ return _rightTop.x - _leftBottom.x;
+ }
+
+ inline float height() const
+ {
+ return _rightTop.y - _leftBottom.y;
+ }
+
protected:
Vec2f _leftBottom;
Vec2f _rightTop;
diff --git a/core/indigo-core/molecule/base_molecule.h b/core/indigo-core/molecule/base_molecule.h
index ca879b4aaf..20988fa6de 100644
--- a/core/indigo-core/molecule/base_molecule.h
+++ b/core/indigo-core/molecule/base_molecule.h
@@ -94,7 +94,6 @@ namespace indigo
SKIP_ATTACHMENT_POINTS = 0x10,
SKIP_TGROUPS = 0x20,
SKIP_TEMPLATE_ATTACHMENT_POINTS = 0x40,
- COPY_BOND_DIRECTIONS = 0x80
};
class Molecule;
diff --git a/core/indigo-core/molecule/ket_commons.h b/core/indigo-core/molecule/ket_commons.h
index e5161db7e4..89afef6428 100644
--- a/core/indigo-core/molecule/ket_commons.h
+++ b/core/indigo-core/molecule/ket_commons.h
@@ -32,6 +32,11 @@ namespace indigo
{
const double KETDefaultFontSize = 13;
const double KETFontScaleFactor = 47;
+ const auto KETFontBoldStr = "BOLD";
+ const auto KETFontItalicStr = "ITALIC";
+ const auto KETFontSuperscriptStr = "SUPERSCRIPT";
+ const auto KETFontSubscriptStr = "SUBSCRIPT";
+ const auto KETFontCustomSizeStr = "CUSTOM_FONT_SIZE";
struct compareFunction
{
@@ -53,8 +58,6 @@ namespace indigo
return string_hash(s, count);
}
- const std::unordered_map KTextStylesMap{{"BOLD", 0}, {"ITALIC", 1}, {"SUPERSCRIPT", 2}, {"SUBSCRIPT", 3}};
-
class KETSimpleObject : public MetaObject
{
public:
@@ -85,13 +88,17 @@ namespace indigo
public:
enum
{
- EBold = 0,
- EItalic = 1,
- ESuperScript = 2,
- ESubScript = 3,
- EFontSize = 4
+ EPlain = 0,
+ EBold = 1,
+ EItalic = 2,
+ ESuperScript = 3,
+ ESubScript = 4,
+ EFontSize = 5
};
+ const std::unordered_map KTextStylesMap{
+ {KETFontBoldStr, EBold}, {KETFontItalicStr, EItalic}, {KETFontSuperscriptStr, ESuperScript}, {KETFontSubscriptStr, ESubScript}};
+
struct KETTextLine
{
std::string text;
diff --git a/core/indigo-core/molecule/metadata_storage.h b/core/indigo-core/molecule/metadata_storage.h
index a4efef968c..1e8392daca 100644
--- a/core/indigo-core/molecule/metadata_storage.h
+++ b/core/indigo-core/molecule/metadata_storage.h
@@ -38,12 +38,13 @@ namespace indigo
public:
DECL_ERROR;
void clone(const MetaDataStorage& other);
+ void append(const MetaDataStorage& other);
virtual ~MetaDataStorage()
{
}
- void addMetaObject(MetaObject* pobj);
+ int addMetaObject(MetaObject* pobj);
void resetMetaData()
{
diff --git a/core/indigo-core/molecule/molecule_cdxml_loader.h b/core/indigo-core/molecule/molecule_cdxml_loader.h
index aa52fb9cda..a7c2e5957d 100644
--- a/core/indigo-core/molecule/molecule_cdxml_loader.h
+++ b/core/indigo-core/molecule/molecule_cdxml_loader.h
@@ -38,6 +38,8 @@ typedef int INT32;
typedef unsigned int UINT32;
#include "molecule/CDXConstants.h"
+const int KCDXMLChemicalFontStyle = 96;
+
namespace tinyxml2
{
class XMLHandle;
@@ -77,6 +79,23 @@ namespace indigo
int val;
};
+ union CDXMLFontStyle {
+ CDXMLFontStyle(unsigned int val) : face(val)
+ {
+ }
+ struct
+ {
+ unsigned int is_bold : 1;
+ unsigned int is_italic : 1;
+ unsigned int is_underline : 1;
+ unsigned int is_outline : 1;
+ unsigned int is_shadow : 1;
+ unsigned int is_subscript : 1;
+ unsigned int is_superscript : 1;
+ };
+ unsigned int face;
+ };
+
struct _ExtConnection
{
int bond_id;
@@ -156,20 +175,30 @@ namespace indigo
MoleculeCdxmlLoader(Scanner& scanner);
void loadMolecule(BaseMolecule& mol);
+ void loadMoleculeFromFragment(BaseMolecule& mol, tinyxml2::XMLElement* pElem);
+
+ static void applyDispatcher(const tinyxml2::XMLAttribute* pAttr,
+ const std::unordered_map>& dispatcher);
+ void parseCDXMLAttributes(const tinyxml2::XMLAttribute* pAttr);
+ void parseBBox(const std::string& data, Rect2f& bbox);
+ void parsePos(const std::string& data, Vec3f& bbox);
StereocentersOptions stereochemistry_options;
bool ignore_bad_valence;
bool _has_bounding_box;
- Rect2f _cdxml_bbox;
- AutoInt _cdxml_bond_length;
- std::vector _nodes;
- std::vector _bonds;
- std::vector _brackets;
+ Rect2f cdxml_bbox;
+ AutoInt cdxml_bond_length;
+ std::vector nodes;
+ std::vector bonds;
+ std::vector brackets;
+ static const int SCALE = 30;
protected:
Scanner* _scanner;
const tinyxml2::XMLNode* _fragment;
- void _parseCDXMLAttributes(const tinyxml2::XMLAttribute* pAttr);
+ void _initMolecule(BaseMolecule& mol);
+ void _parseCollections(BaseMolecule& mol);
+
void _parseNode(CdxmlNode& node, tinyxml2::XMLElement* pElem);
void _addNode(CdxmlNode& node);
@@ -177,14 +206,16 @@ namespace indigo
void _addBond(CdxmlBond& node);
void _parseBracket(CdxmlBracket& bracket, const tinyxml2::XMLAttribute* pAttr);
+ void _parseText(const tinyxml2::XMLElement* pElem);
+ void _parseGraphic(const tinyxml2::XMLElement* pElem);
+ void _parseArrow(const tinyxml2::XMLElement* pElem);
- void _applyDispatcher(const tinyxml2::XMLAttribute* pAttr, const std::unordered_map>& dispatcher);
void _addAtomsAndBonds(BaseMolecule& mol, const std::vector& atoms, const std::vector& bonds);
void _addBracket(BaseMolecule& mol, const CdxmlBracket& bracket);
void _handleSGroup(SGroup& sgroup, const std::unordered_set& atoms, BaseMolecule& bmol);
void _parseCDXMLPage(tinyxml2::XMLElement* pElem);
- void _parseCDXMLFragment(tinyxml2::XMLElement* pElem);
+ void _parseCDXMLElements(tinyxml2::XMLElement* pElem, bool no_siblings = false);
void _parseFragmentAttributes(const tinyxml2::XMLAttribute* pAttr);
void _appendQueryAtom(const char* atom_label, std::unique_ptr& atom);
@@ -196,6 +227,13 @@ namespace indigo
std::unordered_map _id_to_node_index;
std::unordered_map _id_to_bond_index;
std::vector _fragment_nodes;
+ std::vector> _text_objects;
+ std::vector _pluses;
+ std::vector, int>> _arrows;
+
+ std::unordered_set _superced_ids;
+
+ float _bond_length;
private:
MoleculeCdxmlLoader(const MoleculeCdxmlLoader&); // no implicit copy
diff --git a/core/indigo-core/molecule/molecule_cdxml_saver.h b/core/indigo-core/molecule/molecule_cdxml_saver.h
index 2bf0814287..b4969e3e86 100644
--- a/core/indigo-core/molecule/molecule_cdxml_saver.h
+++ b/core/indigo-core/molecule/molecule_cdxml_saver.h
@@ -22,6 +22,7 @@
#include
#include "base_cpp/properties_map.h"
+#include "ket_commons.h"
#include "math/algebra.h"
namespace tinyxml2
@@ -44,11 +45,8 @@ namespace indigo
~MoleculeCdxmlSaver();
void saveMolecule(BaseMolecule& mol);
- enum
- {
- BOND_LENGTH = 30
- };
-
+ static const int SCALE = 30;
+ static const int MAX_PAGE_HEIGHT = 64;
struct Bounds
{
Vec2f min, max;
@@ -61,11 +59,12 @@ namespace indigo
void addColorTable(const char* color);
void addColorToTable(int id, int r, int g, int b);
void saveMoleculeFragment(BaseMolecule& mol, const Vec2f& offset, float scale, int id, Array& nodes_ids);
+ void addMetaData(const MetaDataStorage& meta, int id);
void addText(const Vec2f& pos, const char* text);
void addText(const Vec2f& pos, const char* text, const char* alignment);
void addCustomText(const Vec2f& pos, const char* alignment, float line_height, const char* text);
void addTitle(const Vec2f& pos, const char* text);
- void addGraphic(int id, const Vec2f& p1, const Vec2f& p2, PropertiesMap& attrs);
+ void addElement(const char* element, int id, const Vec2f& p1, const Vec2f& p2, PropertiesMap& attrs);
void addCustomElement(int id, Array& name, PropertiesMap& attrs);
void startCurrentElement(int id, Array& name, PropertiesMap& attrs);
void endCurrentElement();
diff --git a/core/indigo-core/molecule/src/base_molecule.cpp b/core/indigo-core/molecule/src/base_molecule.cpp
index 705976f0ac..a9ce50c04a 100644
--- a/core/indigo-core/molecule/src/base_molecule.cpp
+++ b/core/indigo-core/molecule/src/base_molecule.cpp
@@ -92,8 +92,8 @@ void BaseMolecule::clear()
use_scsr_name = false;
expand_mod_templates = false;
ignore_chem_templates = false;
-
updateEditRevision();
+ _meta.resetMetaData();
}
bool BaseMolecule::hasCoord(BaseMolecule& mol)
@@ -267,6 +267,7 @@ void BaseMolecule::_mergeWithSubmolecule_Sub(BaseMolecule& mol, const Array
reaction_atom_inversion.expandFill(vertexEnd(), 0);
reaction_atom_exact_change.expandFill(vertexEnd(), 0);
reaction_bond_reacting_center.expandFill(edgeEnd(), 0);
+ _bond_directions.expandFill(edgeEnd(), -1);
for (i = mol.vertexBegin(); i != mol.vertexEnd(); i = mol.vertexNext(i))
{
@@ -278,37 +279,13 @@ void BaseMolecule::_mergeWithSubmolecule_Sub(BaseMolecule& mol, const Array
reaction_atom_exact_change[mapping[i]] = mol.reaction_atom_exact_change[i];
}
- if (skip_flags & COPY_BOND_DIRECTIONS)
- {
- _bond_directions.expandFill(edgeEnd() + mol.edgeEnd(), 0);
- }
- else
- _bond_directions.expandFill(mol.edgeEnd(), 0);
-
for (int j = mol.edgeBegin(); j != mol.edgeEnd(); j = mol.edgeNext(j))
{
- const Edge& edge = mol.getEdge(j);
-
- if ((mapping[edge.beg] > -1) && (mapping[edge.end] > -1))
- {
- int bond_idx = findEdgeIndex(mapping[edge.beg], mapping[edge.end]);
- if (bond_idx > -1)
- {
- reaction_bond_reacting_center[bond_idx] = mol.reaction_bond_reacting_center[j];
- }
- }
- }
-
- // trick for molecules with incorrect stereochemistry, of which we do permutations
- if ((skip_flags & COPY_BOND_DIRECTIONS) || (vertexCount() == mol.vertexCount() && edgeCount() == mol.edgeCount()))
- {
- for (int j = mol.edgeBegin(); j != mol.edgeEnd(); j = mol.edgeNext(j))
- {
- const Edge& edge = mol.getEdge(j);
-
- if (mol.getBondDirection(j) != 0)
- _bond_directions[findEdgeIndex(mapping[edge.beg], mapping[edge.end])] = mol.getBondDirection(j);
- }
+ int edge_idx = edge_mapping[j];
+ if (edge_idx < 0)
+ continue;
+ reaction_bond_reacting_center[edge_idx] = mol.reaction_bond_reacting_center[j];
+ _bond_directions[edge_idx] = mol.getBondDirection(j);
}
// RGroups
diff --git a/core/indigo-core/molecule/src/metadata_storage.cpp b/core/indigo-core/molecule/src/metadata_storage.cpp
index 9f7d430935..5ee8c7912d 100644
--- a/core/indigo-core/molecule/src/metadata_storage.cpp
+++ b/core/indigo-core/molecule/src/metadata_storage.cpp
@@ -6,7 +6,7 @@ using namespace indigo;
IMPL_ERROR(MetaDataStorage, "metadata storage");
-void MetaDataStorage::addMetaObject(MetaObject* pobj)
+int MetaDataStorage::addMetaObject(MetaObject* pobj)
{
int index = _meta_data.size();
_meta_data.expand(index + 1);
@@ -29,16 +29,22 @@ void MetaDataStorage::addMetaObject(MetaObject* pobj)
default:
break;
}
+ return index;
}
-void MetaDataStorage::clone(const MetaDataStorage& other)
+void MetaDataStorage::append(const MetaDataStorage& other)
{
- resetMetaData();
const auto& meta = other.metaData();
for (int i = 0; i < meta.size(); i++)
addMetaObject(meta[i]->clone());
}
+void MetaDataStorage::clone(const MetaDataStorage& other)
+{
+ resetMetaData();
+ append(other);
+}
+
const MetaObject& MetaDataStorage::getMetaObject(uint32_t meta_type, int index) const
{
switch (meta_type)
diff --git a/core/indigo-core/molecule/src/molecule_auto_loader.cpp b/core/indigo-core/molecule/src/molecule_auto_loader.cpp
index 95fde3fe69..e2fa095046 100644
--- a/core/indigo-core/molecule/src/molecule_auto_loader.cpp
+++ b/core/indigo-core/molecule/src/molecule_auto_loader.cpp
@@ -325,6 +325,8 @@ void MoleculeAutoLoader::_loadMolecule(BaseMolecule& mol, bool query)
_scanner->skipSpace();
if (_scanner->lookNext() == '<' && _scanner->findWord("CDXML"))
{
+ if (_scanner->findWord("seek(pos, SEEK_SET);
MoleculeCdxmlLoader loader(*_scanner);
loader.stereochemistry_options = stereochemistry_options;
diff --git a/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp b/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp
index 05a687d101..b4e2892b2e 100644
--- a/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp
+++ b/core/indigo-core/molecule/src/molecule_cdxml_loader.cpp
@@ -16,17 +16,21 @@
* limitations under the License.
***************************************************************************/
-#include "molecule/molecule_cdxml_loader.h"
-
+#include
+#include
+#include
#include
#include "base_cpp/scanner.h"
#include "molecule/elements.h"
+#include "molecule/ket_commons.h"
#include "molecule/molecule.h"
+#include "molecule/molecule_cdxml_loader.h"
#include "molecule/molecule_scaffold_detection.h"
using namespace indigo;
using namespace tinyxml2;
+using namespace rapidjson;
static float readFloat(const char* point_str)
{
@@ -46,9 +50,18 @@ MoleculeCdxmlLoader::MoleculeCdxmlLoader(Scanner& scanner)
_scanner = &scanner;
}
-void MoleculeCdxmlLoader::loadMolecule(BaseMolecule& mol)
+void MoleculeCdxmlLoader::_initMolecule(BaseMolecule& mol)
{
mol.clear();
+ nodes.clear();
+ bonds.clear();
+ _id_to_atom_idx.clear();
+ _id_to_node_index.clear();
+ _id_to_bond_index.clear();
+ _fragment_nodes.clear();
+ _text_objects.clear();
+ _pluses.clear();
+ brackets.clear();
_pmol = NULL;
_pqmol = NULL;
if (mol.isQueryMolecule())
@@ -60,7 +73,11 @@ void MoleculeCdxmlLoader::loadMolecule(BaseMolecule& mol)
_pmol = &mol.asMolecule();
_pmol->setIgnoreBadValenceFlag(ignore_bad_valence);
}
+}
+void MoleculeCdxmlLoader::loadMolecule(BaseMolecule& mol)
+{
+ _initMolecule(mol);
if (_scanner != 0)
{
QS_DEF(Array, buf);
@@ -72,79 +89,104 @@ void MoleculeCdxmlLoader::loadMolecule(BaseMolecule& mol)
if (xml.Error())
throw Error("XML parsing error: %s", xml.ErrorStr());
- _parseCDXMLAttributes(xml.RootElement()->FirstAttribute());
+ parseCDXMLAttributes(xml.RootElement()->FirstAttribute());
_parseCDXMLPage(xml.RootElement());
- if (!_nodes.size())
+ if (!nodes.size())
throw Error("CDXML has no data");
- std::vector atoms;
- for (auto& node : _nodes)
+ _parseCollections(mol);
+ }
+}
+
+void MoleculeCdxmlLoader::_parseCollections(BaseMolecule& mol)
+{
+ std::vector atoms;
+ for (auto& node : nodes)
+ {
+ int node_idx = _id_to_node_index.at(node.id);
+ switch (node.type)
{
- int node_idx = _id_to_node_index.at(node.id);
- switch (node.type)
- {
- case kCDXNodeType_Element:
- case kCDXNodeType_ElementList:
- atoms.push_back(node_idx);
- break;
- case kCDXNodeType_ExternalConnectionPoint:
- break;
- case kCDXNodeType_Fragment:
- _fragment_nodes.push_back(node_idx);
- break;
- default:
- break;
- }
+ case kCDXNodeType_Element:
+ case kCDXNodeType_ElementList:
+ atoms.push_back(node_idx);
+ break;
+ case kCDXNodeType_ExternalConnectionPoint:
+ break;
+ case kCDXNodeType_Fragment:
+ _fragment_nodes.push_back(node_idx);
+ break;
+ default:
+ break;
}
+ }
- _addAtomsAndBonds(mol, atoms, _bonds);
+ _addAtomsAndBonds(mol, atoms, bonds);
- for (auto& brk : _brackets)
- _addBracket(mol, brk);
+ for (auto& brk : brackets)
+ _addBracket(mol, brk);
+
+ for (const auto& to : _text_objects)
+ mol.meta().addMetaObject(new KETTextObject(to.first, to.second));
+
+ for (const auto& plus : _pluses)
+ mol.meta().addMetaObject(new KETReactionPlus(plus));
+
+ for (const auto& arrow : _arrows)
+ {
+ const auto& arr_info = arrow.first;
+ Vec2f v1(arr_info.first.x, arr_info.first.y);
+ Vec2f v2(arr_info.second.x, arr_info.second.y);
+ mol.meta().addMetaObject(new KETReactionArrow(arrow.second, v1, v2));
}
}
-void MoleculeCdxmlLoader::_parseCDXMLAttributes(const XMLAttribute* pAttr)
+void MoleculeCdxmlLoader::loadMoleculeFromFragment(BaseMolecule& mol, tinyxml2::XMLElement* pElem)
+{
+ _initMolecule(mol);
+ _parseCDXMLElements(pElem, true);
+ _parseCollections(mol);
+}
+
+void MoleculeCdxmlLoader::parseCDXMLAttributes(const XMLAttribute* pAttr)
{
- auto cdxml_bbox_lambda = [this](std::string& data) {
+ auto cdxml_bbox_lambda = [this](const std::string& data) {
std::vector coords = split(data, ' ');
if (coords.size() == 4)
{
this->_has_bounding_box = true;
- this->_cdxml_bbox = Rect2f(Vec2f(std::stof(coords[0]), std::stof(coords[1])), Vec2f(std::stof(coords[2]), std::stof(coords[3])));
+ this->cdxml_bbox = Rect2f(Vec2f(std::stof(coords[0]), std::stof(coords[1])), Vec2f(std::stof(coords[2]), std::stof(coords[3])));
}
else
throw Error("Not enought coordinates for atom position");
};
- auto& bond_length = _cdxml_bond_length;
- auto cdxml_bond_length_lambda = [&bond_length](std::string& data) { bond_length = data; };
- std::unordered_map> cdxml_dispatcher = {{"BoundingBox", cdxml_bbox_lambda},
- {"BondLength", cdxml_bond_length_lambda}};
- _applyDispatcher(pAttr, cdxml_dispatcher);
+ auto& bond_length = cdxml_bond_length;
+ auto cdxml_bond_length_lambda = [&bond_length](const std::string& data) { bond_length = data; };
+ std::unordered_map> cdxml_dispatcher = {{"BoundingBox", cdxml_bbox_lambda},
+ {"BondLength", cdxml_bond_length_lambda}};
+ applyDispatcher(pAttr, cdxml_dispatcher);
}
void MoleculeCdxmlLoader::_parseCDXMLPage(XMLElement* pElem)
{
- auto pPageElem = pElem->FirstChildElement();
- for (pPageElem; pPageElem; pPageElem = pPageElem->NextSiblingElement())
+ for (auto pPageElem = pElem->FirstChildElement(); pPageElem; pPageElem = pPageElem->NextSiblingElement())
{
if (std::string(pPageElem->Value()).compare("page") == 0)
{
- _parseCDXMLFragment(pPageElem->FirstChildElement());
+ _parseCDXMLElements(pPageElem->FirstChildElement());
}
}
}
-void MoleculeCdxmlLoader::_parseCDXMLFragment(XMLElement* pElem)
+void MoleculeCdxmlLoader::_parseCDXMLElements(XMLElement* pElem, bool no_siblings)
{
auto node_lambda = [this](XMLElement* pElem) {
CdxmlNode node;
this->_parseNode(node, pElem);
_addNode(node);
if (node.type == kCDXNodeType_Fragment)
- this->_parseCDXMLFragment(pElem->FirstChildElement());
+ this->_parseCDXMLElements(pElem->FirstChildElement());
};
auto bond_lambda = [this](XMLElement* pElem) {
@@ -155,19 +197,26 @@ void MoleculeCdxmlLoader::_parseCDXMLFragment(XMLElement* pElem)
auto fragment_lambda = [this](XMLElement* pElem) {
this->_parseFragmentAttributes(pElem->FirstAttribute());
- this->_parseCDXMLFragment(pElem->FirstChildElement());
+ this->_parseCDXMLElements(pElem->FirstChildElement());
};
- auto group_lambda = [this](XMLElement* pElem) { this->_parseCDXMLFragment(pElem->FirstChildElement()); };
+ auto group_lambda = [this](XMLElement* pElem) { this->_parseCDXMLElements(pElem->FirstChildElement()); };
auto bracketed_lambda = [this](XMLElement* pElem) {
CdxmlBracket bracket;
this->_parseBracket(bracket, pElem->FirstAttribute());
- this->_brackets.push_back(bracket);
+ this->brackets.push_back(bracket);
};
+ auto text_lambda = [this](XMLElement* pElem) { this->_parseText(pElem); };
+
+ auto graphic_lambda = [this](XMLElement* pElem) { this->_parseGraphic(pElem); };
+
+ auto arrow_lambda = [this](XMLElement* pElem) { this->_parseArrow(pElem); };
+
std::unordered_map> cdxml_dispatcher = {
- {"n", node_lambda}, {"b", bond_lambda}, {"fragment", fragment_lambda}, {"group", group_lambda}, {"bracketedgroup", bracketed_lambda}};
+ {"n", node_lambda}, {"b", bond_lambda}, {"fragment", fragment_lambda}, {"group", group_lambda}, {"bracketedgroup", bracketed_lambda},
+ {"t", text_lambda}, {"graphic", graphic_lambda}, {"arrow", arrow_lambda}};
for (pElem; pElem; pElem = pElem->NextSiblingElement())
{
@@ -178,8 +227,9 @@ void MoleculeCdxmlLoader::_parseCDXMLFragment(XMLElement* pElem)
}
else
{
- // printf("Unhandled cdxml tag: %s\n", pElem->Value());
}
+ if (no_siblings)
+ break;
}
}
@@ -187,7 +237,7 @@ void MoleculeCdxmlLoader::_updateConnection(const CdxmlNode& node, int atom_idx)
{
for (auto fidx : _fragment_nodes)
{
- auto& frag_node = _nodes[fidx];
+ auto& frag_node = nodes[fidx];
auto fit = frag_node.node_id_to_connection_idx.find(node.id);
if (fit != frag_node.node_id_to_connection_idx.end())
{
@@ -210,7 +260,7 @@ void MoleculeCdxmlLoader::_addAtomsAndBonds(BaseMolecule& mol, const std::vector
int atom_idx;
for (auto atom_idx : atoms)
{
- auto& atom = _nodes[atom_idx];
+ auto& atom = nodes[atom_idx];
if (_pmol)
{
atom_idx = _pmol->addAtom(atom.element);
@@ -236,8 +286,8 @@ void MoleculeCdxmlLoader::_addAtomsAndBonds(BaseMolecule& mol, const std::vector
{
auto bond_first_it = _id_to_atom_idx.find(bond.be.first);
auto bond_second_it = _id_to_atom_idx.find(bond.be.second);
- auto& fn = _nodes[_id_to_node_index.at(bond.be.first)];
- auto& sn = _nodes[_id_to_node_index.at(bond.be.second)];
+ auto& fn = nodes[_id_to_node_index.at(bond.be.first)];
+ auto& sn = nodes[_id_to_node_index.at(bond.be.second)];
if (bond_first_it != _id_to_atom_idx.end() && bond_second_it != _id_to_atom_idx.end())
{
@@ -343,7 +393,6 @@ void MoleculeCdxmlLoader::_addBracket(BaseMolecule& mol, const CdxmlBracket& bra
default:
break;
}
-
_handleSGroup(sgroup, sgroup_atoms, mol);
}
}
@@ -436,9 +485,9 @@ void MoleculeCdxmlLoader::_parseFragmentAttributes(const XMLAttribute* pAttr)
{
// it means that we are inside of NodeType=Fragment
// let's check it
- if (_nodes.size() && _nodes.back().type == kCDXNodeType_Fragment)
+ if (nodes.size() && nodes.back().type == kCDXNodeType_Fragment)
{
- auto& fn = _nodes.back();
+ auto& fn = nodes.back();
auto vec_str = split(pAttr->Value(), ' ');
if (fn.connections.size() == vec_str.size())
{
@@ -458,7 +507,7 @@ void MoleculeCdxmlLoader::_parseFragmentAttributes(const XMLAttribute* pAttr)
}
}
-void MoleculeCdxmlLoader::_applyDispatcher(const XMLAttribute* pAttr, const std::unordered_map>& dispatcher)
+void MoleculeCdxmlLoader::applyDispatcher(const XMLAttribute* pAttr, const std::unordered_map>& dispatcher)
{
for (pAttr; pAttr; pAttr = pAttr->Next())
{
@@ -474,15 +523,15 @@ void MoleculeCdxmlLoader::_applyDispatcher(const XMLAttribute* pAttr, const std:
void MoleculeCdxmlLoader::_parseNode(CdxmlNode& node, XMLElement* pElem)
{
// Atom parsing lambdas definition
- auto id_lambda = [&node](std::string& data) { node.id = data; };
- auto hydrogens_lambda = [&node](std::string& data) { node.hydrogens = data; };
- auto charge_lambda = [&node](std::string& data) { node.charge = data; };
- auto element_lambda = [&node](std::string& data) { node.element = data; };
- auto isotope_lambda = [&node](std::string& data) { node.isotope = data; };
- auto radical_lambda = [&node](std::string& data) { node.radical = data; };
- auto label_lambda = [&node](std::string& data) { node.label = data; };
-
- auto bond_ordering_lambda = [&node](std::string& data) {
+ auto id_lambda = [&node](const std::string& data) { node.id = data; };
+ auto hydrogens_lambda = [&node](const std::string& data) { node.hydrogens = data; };
+ auto charge_lambda = [&node](const std::string& data) { node.charge = data; };
+ auto element_lambda = [&node](const std::string& data) { node.element = data; };
+ auto isotope_lambda = [&node](const std::string& data) { node.isotope = data; };
+ auto radical_lambda = [&node](const std::string& data) { node.radical = data; };
+ auto label_lambda = [&node](const std::string& data) { node.label = data; };
+
+ auto bond_ordering_lambda = [&node](const std::string& data) {
auto vec_str = split(data, ' ');
for (auto& str : vec_str)
{
@@ -492,29 +541,14 @@ void MoleculeCdxmlLoader::_parseNode(CdxmlNode& node, XMLElement* pElem)
}
};
- auto pos_lambda = [&node, this](std::string& data) {
- std::vector coords = split(data, ' ');
- if (coords.size() >= 2)
- {
- node.pos.x = std::stof(coords[0]);
- node.pos.y = std::stof(coords[1]);
- if (this->_has_bounding_box)
- node.pos.y = this->_cdxml_bbox.top() - node.pos.y;
- if (coords.size() == 3)
- node.pos.z = std::stof(coords[2]);
- else
- node.pos.z = 0;
- }
- else
- throw Error("Not enought coordinates for atom position");
- };
+ auto pos_lambda = [&node, this](const std::string& data) { this->parsePos(data, node.pos); };
- auto stereo_lambda = [&node](std::string& data) {
+ auto stereo_lambda = [&node](const std::string& data) {
static const std::unordered_map cip_map = {{"U", 0}, {"N", 1}, {"R", 2}, {"S", 3}, {"r", 4}, {"s", 5}, {"u", 6}};
node.stereo = cip_map.at(data);
};
- auto node_type_lambda = [&node](std::string& data) {
+ auto node_type_lambda = [&node](const std::string& data) {
static const std::unordered_map node_type_map = {{"Unspecified", kCDXNodeType_Unspecified},
{"Element", kCDXNodeType_Element},
{"ElementList", kCDXNodeType_ElementList},
@@ -532,7 +566,7 @@ void MoleculeCdxmlLoader::_parseNode(CdxmlNode& node, XMLElement* pElem)
node.type = node_type_map.at(data);
};
- auto element_list_lambda = [&node](std::string& data) {
+ auto element_list_lambda = [&node](const std::string& data) {
std::vector elements = split(data, ' ');
if (elements.size() && elements.front().compare("NOT") == 0)
{
@@ -542,47 +576,47 @@ void MoleculeCdxmlLoader::_parseNode(CdxmlNode& node, XMLElement* pElem)
node.element_list.assign(elements.begin(), elements.end());
};
- std::unordered_map> node_dispatcher = {{"id", id_lambda},
- {"p", pos_lambda},
- {"xyz", pos_lambda},
- {"NumHydrogens", hydrogens_lambda},
- {"Charge", charge_lambda},
- {"Isotope", isotope_lambda},
- {"Radical", radical_lambda},
- {"AS", stereo_lambda},
- {"NodeType", node_type_lambda},
- {"Element", element_lambda},
- {"GenericNickname", label_lambda},
- {"ElementList", element_list_lambda},
- {"BondOrdering", bond_ordering_lambda}};
-
- _applyDispatcher(pElem->FirstAttribute(), node_dispatcher);
+ std::unordered_map> node_dispatcher = {{"id", id_lambda},
+ {"p", pos_lambda},
+ {"xyz", pos_lambda},
+ {"NumHydrogens", hydrogens_lambda},
+ {"Charge", charge_lambda},
+ {"Isotope", isotope_lambda},
+ {"Radical", radical_lambda},
+ {"AS", stereo_lambda},
+ {"NodeType", node_type_lambda},
+ {"Element", element_lambda},
+ {"GenericNickname", label_lambda},
+ {"ElementList", element_list_lambda},
+ {"BondOrdering", bond_ordering_lambda}};
+
+ applyDispatcher(pElem->FirstAttribute(), node_dispatcher);
}
void MoleculeCdxmlLoader::_addNode(CdxmlNode& node)
{
- _nodes.push_back(node);
- _id_to_node_index.emplace(node.id, _nodes.size() - 1);
+ nodes.push_back(node);
+ _id_to_node_index.emplace(node.id, nodes.size() - 1);
}
void MoleculeCdxmlLoader::_addBond(CdxmlBond& bond)
{
- _bonds.push_back(bond);
- _id_to_bond_index.emplace(bond.id, _bonds.size() - 1);
+ bonds.push_back(bond);
+ _id_to_bond_index.emplace(bond.id, bonds.size() - 1);
}
void MoleculeCdxmlLoader::_parseBond(CdxmlBond& bond, const XMLAttribute* pAttr)
{
- auto id_lambda = [&bond](std::string& data) { bond.id = data; };
- auto bond_begin_lambda = [&bond](std::string& data) { bond.be.first = data; };
- auto bond_end_lambda = [&bond](std::string& data) { bond.be.second = data; };
- auto bond_order_lambda = [&bond](std::string& data) {
+ auto id_lambda = [&bond](const std::string& data) { bond.id = data; };
+ auto bond_begin_lambda = [&bond](const std::string& data) { bond.be.first = data; };
+ auto bond_end_lambda = [&bond](const std::string& data) { bond.be.second = data; };
+ auto bond_order_lambda = [&bond](const std::string& data) {
static const std::unordered_map order_map = {
{"1", BOND_SINGLE}, {"2", BOND_DOUBLE}, {"3", BOND_TRIPLE}, {"1.5", BOND_AROMATIC}, {"dative", _BOND_COORDINATION}, {"hydrogen", _BOND_HYDROGEN}};
bond.order = order_map.at(data);
};
- auto bond_dir_lambda = [&bond](std::string& data) {
+ auto bond_dir_lambda = [&bond](const std::string& data) {
static const std::unordered_map> dir_map = {{"WedgedHashBegin", {BOND_DOWN, false}},
{"WedgedHashEnd", {BOND_DOWN, true}},
{"WedgeBegin", {BOND_UP, false}},
@@ -599,20 +633,235 @@ void MoleculeCdxmlLoader::_parseBond(CdxmlBond& bond, const XMLAttribute* pAttr)
}
};
- std::unordered_map> bond_dispatcher = {
+ std::unordered_map> bond_dispatcher = {
{"id", id_lambda}, {"B", bond_begin_lambda}, {"E", bond_end_lambda}, {"Order", bond_order_lambda}, {"Display", bond_dir_lambda}};
- _applyDispatcher(pAttr, bond_dispatcher);
+ applyDispatcher(pAttr, bond_dispatcher);
+}
+
+void MoleculeCdxmlLoader::parsePos(const std::string& data, Vec3f& pos)
+{
+ std::vector coords = split(data, ' ');
+ if (coords.size() >= 2)
+ {
+ pos.x = std::stof(coords[0]);
+ pos.y = std::stof(coords[1]);
+ pos.z = 0;
+ if (this->_has_bounding_box)
+ {
+ pos.x -= this->cdxml_bbox.left();
+ pos.y -= this->cdxml_bbox.bottom();
+ }
+ pos.x /= SCALE;
+ pos.y /= -SCALE;
+ }
+ else
+ throw Error("Not enought coordinates");
+}
+
+void MoleculeCdxmlLoader::parseBBox(const std::string& data, Rect2f& bbox)
+{
+ std::vector coords = split(data, ' ');
+ if (coords.size() == 4)
+ {
+ Vec2f v1(std::stof(coords[0]), std::stof(coords[1]));
+ Vec2f v2(std::stof(coords[2]), std::stof(coords[3]));
+ if (this->_has_bounding_box)
+ {
+ v1.sub(this->cdxml_bbox.leftBottom());
+ v2.sub(this->cdxml_bbox.leftBottom());
+ }
+ v1.x /= SCALE;
+ v2.x /= SCALE;
+ v1.y /= -SCALE;
+ v2.y /= -SCALE;
+ bbox = Rect2f(v1, v2);
+ }
+ else
+ throw Error("Not enought coordinates for text bounding box");
+}
+
+void MoleculeCdxmlLoader::_parseGraphic(const XMLElement* pElem)
+{
+ AutoInt superseded_id = 0;
+ auto superseded_lambda = [&superseded_id](const std::string& data) { superseded_id = data; };
+
+ Rect2f graph_bbox;
+ auto graphic_bbox_lambda = [&graph_bbox, this](const std::string& data) { this->parseBBox(data, graph_bbox); };
+
+ std::string graphic_type;
+ auto graphic_type_lambda = [&graphic_type](const std::string& data) { graphic_type = data; };
+
+ std::string symbol_type;
+ auto symbol_type_lambda = [&symbol_type](const std::string& data) { symbol_type = data; };
+
+ std::string arrow_type;
+ auto arrow_type_lambda = [&arrow_type](const std::string& data) { arrow_type = data; };
+
+ AutoInt head_size;
+ auto head_size_lambda = [&head_size](const std::string& data) { head_size = data; };
+
+ std::unordered_map> graphic_dispatcher = {
+ {"SupersededBy", superseded_lambda}, {"BoundingBox", graphic_bbox_lambda}, {"GraphicType", graphic_type_lambda},
+ {"SymbolType", symbol_type_lambda}, {"ArrowType", arrow_type_lambda}, {"HeadSize", head_size_lambda}};
+
+ auto pAttr = pElem->FirstAttribute();
+ applyDispatcher(pAttr, graphic_dispatcher);
+
+ if (graphic_type == "Line" && arrow_type == "FullHead")
+ {
+ }
+ else if (graphic_type == "Symbol" && symbol_type == "Plus")
+ {
+ _pluses.emplace_back(graph_bbox.center());
+ }
+}
+
+void MoleculeCdxmlLoader::_parseArrow(const tinyxml2::XMLElement* pElem)
+{
+ Rect2f text_bbox;
+ auto arrow_bbox_lambda = [&text_bbox, this](const std::string& data) { this->parseBBox(data, text_bbox); };
+ Vec3f begin_pos;
+ auto arrow_begin_lambda = [&begin_pos, this](const std::string& data) { this->parsePos(data, begin_pos); };
+ Vec3f end_pos;
+ auto arrow_end_lambda = [&end_pos, this](const std::string& data) { this->parsePos(data, end_pos); };
+ std::string fill_type;
+ auto fill_type_lambda = [&fill_type](const std::string& data) { fill_type = data; };
+ std::string arrow_head;
+ auto arrow_head_lambda = [&arrow_head](const std::string& data) { arrow_head = data; };
+ std::string head_type;
+ auto head_type_lambda = [&head_type](const std::string& data) { head_type = data; };
+ std::unordered_map> arrow_dispatcher = {
+ {"BoundingBox", arrow_bbox_lambda}, {"FillType", fill_type_lambda}, {"ArrowheadHead", arrow_head_lambda},
+ {"ArrowheadType", head_type_lambda}, {"Head3D", arrow_end_lambda}, {"Tail3D", arrow_begin_lambda}};
+
+ auto pAttr = pElem->FirstAttribute();
+ applyDispatcher(pAttr, arrow_dispatcher);
+ _arrows.push_back(std::make_pair(std::make_pair(begin_pos, end_pos), 2));
+}
+
+void MoleculeCdxmlLoader::_parseText(const XMLElement* pElem)
+{
+ Vec3f text_pos;
+ auto text_coordinates_lambda = [&text_pos, this](const std::string& data) { this->parsePos(data, text_pos); };
+
+ Rect2f text_bbox;
+ auto text_bbox_lambda = [&text_bbox, this](const std::string& data) { this->parseBBox(data, text_bbox); };
+
+ std::string label_justification, label_alignment;
+ auto label_justification_lambda = [&label_justification, this](const std::string& data) { label_justification = data; };
+ auto label_justification_alignment_lambda = [&label_alignment, this](const std::string& data) { label_alignment = data; };
+
+ std::unordered_map> text_dispatcher = {{"p", text_coordinates_lambda},
+ {"BoundingBox", text_bbox_lambda},
+ {"LabelJustification", label_justification_lambda},
+ {"LabelAlignment", label_justification_alignment_lambda}};
+
+ AutoInt font_id, font_color_id, font_face;
+ float font_size;
+
+ auto style_font_lambda = [&font_id](const std::string& data) { font_id = data; };
+ auto style_size_lambda = [&font_size](const std::string& data) { font_size = std::stof(data) * 1.5; };
+ auto style_color_lambda = [&font_color_id](const std::string& data) { font_color_id = data; };
+ auto style_face_lambda = [&font_face](const std::string& data) { font_face = data; };
+
+ std::unordered_map> style_dispatcher = {
+ {"font", style_font_lambda}, {"size", style_size_lambda}, {"color", style_color_lambda}, {"face", style_face_lambda}};
+
+ auto pAttr = pElem->FirstAttribute();
+ applyDispatcher(pAttr, text_dispatcher);
+
+ StringBuffer s;
+ Writer writer(s);
+ writer.StartObject();
+ writer.Key("blocks");
+ writer.StartArray();
+ for (auto pTextStyle = pElem->FirstChildElement(); pTextStyle; pTextStyle = pTextStyle->NextSiblingElement())
+ {
+ std::string text_element = pTextStyle->Value();
+ if (text_element == "s")
+ {
+ font_face = 0;
+ font_size = 0.0;
+ auto pStyleAttribute = pTextStyle->FirstAttribute();
+ applyDispatcher(pStyleAttribute, style_dispatcher);
+ std::vector text_vec_styles;
+ CDXMLFontStyle fs(font_face);
+ if (font_face == KCDXMLChemicalFontStyle)
+ {
+ // special case
+ }
+ else
+ {
+ if (fs.is_bold)
+ text_vec_styles.push_back(KETFontBoldStr);
+ if (fs.is_italic)
+ text_vec_styles.push_back(KETFontItalicStr);
+ if (fs.is_superscript)
+ text_vec_styles.push_back(KETFontSuperscriptStr);
+ if (fs.is_superscript)
+ text_vec_styles.push_back(KETFontSubscriptStr);
+ }
+ if (font_size > 0)
+ text_vec_styles.push_back(std::string(KETFontCustomSizeStr) + "_" + std::to_string((int)ceil(font_size)) + "px");
+
+ std::string label_plain = pTextStyle->GetText();
+ std::remove_if(label_plain.begin(), label_plain.end(), [](char c) { return (c == '\r'); });
+
+ auto labels = split(label_plain, '\n');
+ for (const auto& label : labels)
+ {
+ writer.StartObject();
+ writer.Key("text");
+ writer.String(label.c_str());
+ writer.Key("inlineStyleRanges");
+ writer.StartArray();
+ for (auto style_str : text_vec_styles)
+ {
+ writer.StartObject();
+ writer.Key("offset");
+ writer.Int(0);
+ writer.Key("length");
+ writer.Int(label.size());
+ writer.Key("style");
+ writer.String(style_str.c_str());
+ }
+ writer.EndObject();
+ writer.EndArray();
+
+ writer.Key("entityRanges");
+ writer.StartArray();
+ writer.EndArray();
+
+ writer.Key("data");
+ writer.StartObject();
+ writer.EndObject();
+
+ writer.EndObject();
+ }
+ }
+ else
+ {
+ throw Error("unrecognized text element: %s", text_element.c_str());
+ }
+ }
+ writer.EndArray();
+ writer.Key("entityMap");
+ writer.StartObject();
+ writer.EndObject();
+
+ writer.EndObject();
+ text_pos.y -= text_bbox.height() / 2;
+ _text_objects.emplace_back(text_pos, s.GetString());
}
void MoleculeCdxmlLoader::_parseBracket(CdxmlBracket& bracket, const XMLAttribute* pAttr)
{
- auto bracketed_ids_lambda = [&bracket](std::string& data) {
+ auto bracketed_ids_lambda = [&bracket](const std::string& data) {
std::vector vec_str = split(data, ' ');
bracket.bracketed_list.assign(vec_str.begin(), vec_str.end());
};
-
- auto bracket_usage_lambda = [&bracket](std::string& data) {
+ auto bracket_usage_lambda = [&bracket](const std::string& data) {
static const std::unordered_map usage_map = {{"Unspecified", kCDXBracketUsage_Unspecified},
{"Unused1", kCDXBracketUsage_Unused1},
{"Unused2", kCDXBracketUsage_Unused2},
@@ -637,22 +886,22 @@ void MoleculeCdxmlLoader::_parseBracket(CdxmlBracket& bracket, const XMLAttribut
bracket.usage = usage_map.at(data);
};
- auto repeat_count_lambda = [&bracket](std::string& data) { bracket.repeat_count = data; };
- auto repeat_pattern_lambda = [&bracket](std::string& data) {
+ auto repeat_count_lambda = [&bracket](const std::string& data) { bracket.repeat_count = data; };
+ auto repeat_pattern_lambda = [&bracket](const std::string& data) {
static const std::unordered_map rep_map = {
{"HeadToTail", RepeatingUnit::HEAD_TO_TAIL}, {"HeadToHead", RepeatingUnit::HEAD_TO_HEAD}, {"EitherUnknown", RepeatingUnit::EITHER}};
bracket.repeat_pattern = rep_map.at(data);
};
- auto sru_label_lambda = [&bracket](std::string& data) { bracket.sru_label = data; };
+ auto sru_label_lambda = [&bracket](const std::string& data) { bracket.sru_label = data; };
- std::unordered_map> bracket_dispatcher = {{"BracketedObjectIDs", bracketed_ids_lambda},
- {"BracketUsage", bracket_usage_lambda},
- {"RepeatCount", repeat_count_lambda},
- {"PolymerRepeatPattern", repeat_pattern_lambda},
- {"SRULabel", sru_label_lambda}};
+ std::unordered_map> bracket_dispatcher = {{"BracketedObjectIDs", bracketed_ids_lambda},
+ {"BracketUsage", bracket_usage_lambda},
+ {"RepeatCount", repeat_count_lambda},
+ {"PolymerRepeatPattern", repeat_pattern_lambda},
+ {"SRULabel", sru_label_lambda}};
- _applyDispatcher(pAttr, bracket_dispatcher);
+ applyDispatcher(pAttr, bracket_dispatcher);
}
void MoleculeCdxmlLoader::_appendQueryAtom(const char* atom_label, std::unique_ptr& atom)
diff --git a/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp b/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp
index 5e5202a82c..9e0b71a676 100644
--- a/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp
+++ b/core/indigo-core/molecule/src/molecule_cdxml_saver.cpp
@@ -16,14 +16,15 @@
* limitations under the License.
***************************************************************************/
-#include "molecule/molecule_cdxml_saver.h"
-
+#include
#include
#include "base_cpp/locale_guard.h"
#include "base_cpp/output.h"
#include "molecule/elements.h"
#include "molecule/molecule.h"
+#include "molecule/molecule_cdxml_loader.h"
+#include "molecule/molecule_cdxml_saver.h"
#include "molecule/query_molecule.h"
using namespace indigo;
@@ -33,8 +34,8 @@ IMPL_ERROR(MoleculeCdxmlSaver, "molecule CDXML saver");
MoleculeCdxmlSaver::MoleculeCdxmlSaver(Output& output) : _output(output)
{
- _bond_length = BOND_LENGTH;
- _max_page_height = 64;
+ _bond_length = SCALE;
+ _max_page_height = MAX_PAGE_HEIGHT;
_pages_height = 1;
}
@@ -201,7 +202,6 @@ void MoleculeCdxmlSaver::addColorToTable(int id, int r, int g, int b)
void MoleculeCdxmlSaver::addDefaultFontTable()
{
- int id = -1;
Array name;
PropertiesMap attrs;
@@ -209,17 +209,17 @@ void MoleculeCdxmlSaver::addDefaultFontTable()
attrs.clear();
name.readString("fonttable", true);
- startCurrentElement(id, name, attrs);
+ startCurrentElement(-1, name, attrs);
name.readString("font", true);
- id = 3;
- attrs.insert("charset", "iso-8859-1");
+ int id = 1;
+ attrs.insert("charset", "utf-8");
attrs.insert("name", "Arial");
addCustomElement(id, name, attrs);
attrs.clear();
- id = 4;
- attrs.insert("charset", "iso-8859-1");
+ id++;
+ attrs.insert("charset", "utf-8");
attrs.insert("name", "Times New Roman");
addCustomElement(id, name, attrs);
@@ -667,7 +667,6 @@ void MoleculeCdxmlSaver::saveMoleculeFragment(BaseMolecule& mol, const Vec2f& of
}
if (parity == MoleculeCisTrans::TRANS)
{
-
std::swap(s3, s4);
}
QS_DEF(Array, buf);
@@ -703,6 +702,235 @@ void MoleculeCdxmlSaver::saveMoleculeFragment(BaseMolecule& mol, const Vec2f& of
_current = parent;
}
+void MoleculeCdxmlSaver::addMetaData(const MetaDataStorage& meta, int id)
+{
+ const auto& meta_objects = meta.metaData();
+ for (int meta_index = 0; meta_index < meta_objects.size(); ++meta_index)
+ {
+ id++;
+ PropertiesMap attrs;
+ attrs.clear();
+ auto pobj = meta_objects[meta_index];
+ switch (pobj->_class_id)
+ {
+ case KETReactionArrow::CID: {
+ KETReactionArrow& ar = (KETReactionArrow&)(*pobj);
+ attrs.insert("FillType", "None");
+ attrs.insert("ArrowheadType", "Solid");
+ attrs.insert("HeadSize", "2250");
+ attrs.insert("ArrowheadWidth", "563");
+ switch (ar._arrow_type)
+ {
+ case KETReactionArrow::EOpenAngle:
+ attrs.insert("ArrowheadHead", "Full");
+ attrs.insert("ArrowheadCenterSize", "25");
+ break;
+ case KETReactionArrow::EFilledTriangle:
+ attrs.insert("ArrowheadHead", "Full");
+ attrs.insert("ArrowheadCenterSize", "2250");
+ break;
+
+ case KETReactionArrow::EFilledBow:
+ attrs.insert("ArrowheadHead", "Full");
+ attrs.insert("ArrowheadCenterSize", "1125");
+ break;
+
+ case KETReactionArrow::EDashedOpenAngle:
+ attrs.insert("ArrowheadHead", "Full");
+ attrs.insert("ArrowheadCenterSize", "25");
+ attrs.insert("LineType", "Dashed");
+ break;
+
+ case KETReactionArrow::EFailed:
+ attrs.insert("ArrowheadHead", "Full");
+ attrs.insert("ArrowheadCenterSize", "1125");
+ attrs.insert("NoGo", "Cross");
+ break;
+
+ case KETReactionArrow::EBothEndsFilledTriangle:
+ attrs.insert("ArrowheadCenterSize", "2250");
+ attrs.insert("ArrowheadHead", "Full");
+ attrs.insert("ArrowheadTail", "Full");
+ break;
+
+ case KETReactionArrow::EEquilibriumFilledHalfBow:
+ attrs.insert("ArrowheadHead", "HalfLeft");
+ attrs.insert("ArrowheadTail", "HalfLeft");
+ attrs.insert("ArrowheadCenterSize", "1125");
+ attrs.insert("ArrowShaftSpacing", "300");
+ break;
+
+ case KETReactionArrow::EEquilibriumFilledTriangle:
+ attrs.insert("ArrowheadHead", "HalfLeft");
+ attrs.insert("ArrowheadTail", "HalfLeft");
+ attrs.insert("ArrowheadCenterSize", "2250");
+ attrs.insert("ArrowShaftSpacing", "300");
+ break;
+
+ case KETReactionArrow::EEquilibriumOpenAngle:
+ attrs.insert("ArrowheadHead", "HalfLeft");
+ attrs.insert("ArrowheadTail", "HalfLeft");
+ attrs.insert("ArrowheadCenterSize", "25");
+ attrs.insert("ArrowShaftSpacing", "300");
+ break;
+
+ case KETReactionArrow::EUnbalancedEquilibriumFilledHalfBow:
+ break;
+
+ case KETReactionArrow::EUnbalancedEquilibriumLargeFilledHalfBow:
+ break;
+
+ case KETReactionArrow::EUnbalancedEquilibriumOpenHalfAngle:
+ break;
+
+ case KETReactionArrow::EUnbalancedEquilibriumFilledHalfTriangle:
+ break;
+
+ case KETReactionArrow::EEllipticalArcFilledBow:
+ break;
+
+ case KETReactionArrow::EEllipticalArcFilledTriangle:
+ break;
+
+ case KETReactionArrow::EEllipticalArcOpenAngle:
+ break;
+
+ case KETReactionArrow::EEllipticalArcOpenHalfAngle:
+ break;
+
+ default:
+ break;
+ }
+
+ Vec3f ar_beg(ar._begin.x, -ar._begin.y, 0);
+ Vec3f ar_end(ar._end.x, -ar._end.y, 0);
+ ar_beg.scale(_bond_length);
+ ar_end.scale(_bond_length);
+
+ attrs.insert("Head3D", std::to_string(ar_end.x) + " " + std::to_string(ar_end.y) + " " + std::to_string(ar_end.z));
+ attrs.insert("Tail3D", std::to_string(ar_beg.x) + " " + std::to_string(ar_beg.y) + " " + std::to_string(ar_beg.z));
+ addElement("arrow", id, ar._end, ar._begin, attrs);
+ }
+ break;
+ case KETReactionPlus::CID: {
+ KETReactionPlus& rp = (KETReactionPlus&)(*pobj);
+ }
+ break;
+ case KETSimpleObject::CID: {
+ auto simple_obj = (KETSimpleObject*)pobj;
+ Rect2f bbox(simple_obj->_coordinates.first, simple_obj->_coordinates.second);
+ switch (simple_obj->_mode)
+ {
+ case KETSimpleObject::EKETEllipse: {
+ auto ecenter = bbox.center();
+ Vec2f maj_axis, min_axis;
+ if (bbox.width() > bbox.height())
+ {
+ maj_axis.copy(bbox.rightMiddle());
+ min_axis.copy(bbox.topMiddle());
+ }
+ else
+ {
+ maj_axis.copy(bbox.topMiddle());
+ min_axis.copy(bbox.rightMiddle());
+ }
+ ecenter.scale(_bond_length);
+ min_axis.scale(_bond_length);
+ maj_axis.scale(_bond_length);
+ ecenter.y = -ecenter.y;
+ min_axis.y = -min_axis.y;
+ maj_axis.y = -maj_axis.y;
+ Rect2f bbox_new(ecenter, bbox.rightTop());
+ bbox.copy(bbox_new);
+ attrs.insert("Center3D", std::to_string(ecenter.x) + " " + std::to_string(ecenter.y));
+ attrs.insert("MajorAxisEnd3D", std::to_string(maj_axis.x) + " " + std::to_string(maj_axis.y));
+ attrs.insert("MinorAxisEnd3D", std::to_string(min_axis.x) + " " + std::to_string(min_axis.y));
+ attrs.insert("GraphicType", "Oval");
+ }
+ break;
+ case KETSimpleObject::EKETRectangle:
+ attrs.insert("GraphicType", "Rectangle");
+ break;
+ case KETSimpleObject::EKETLine:
+ attrs.insert("GraphicType", "Line");
+ break;
+ }
+ addElement("graphic", id, bbox.leftBottom(), bbox.rightTop(), attrs);
+ }
+ break;
+ case KETTextObject::CID: {
+ const KETTextObject& ko = static_cast(*pobj);
+ double text_offset_y = 0;
+ int font_size = 13;
+ CDXMLFontStyle font_face(0);
+ for (auto& text_item : ko._block)
+ {
+ int first_index = -1;
+ int second_index = -1;
+ double text_offset_x = 0;
+ FONT_STYLE_SET current_styles;
+ Vec2f text_origin(ko._pos.x, ko._pos.y);
+ std::string pos_str = std::to_string(_bond_length * text_origin.x) + " " + std::to_string(-_bond_length * text_origin.y);
+ XMLElement* t = _doc->NewElement("t");
+ _current->LinkEndChild(t);
+ t->SetAttribute("p", pos_str.c_str());
+ t->SetAttribute("Justification", "Left");
+ t->SetAttribute("InterpretChemically", "no");
+ for (auto& kvp : text_item.styles)
+ {
+ if (first_index == -1)
+ {
+ first_index = kvp.first;
+ current_styles = kvp.second;
+ continue;
+ }
+ second_index = kvp.first;
+
+ std::wstring_convert> utf82w;
+ std::wstring_convert> w2utf8;
+
+ auto sub_text = w2utf8.to_bytes(utf82w.from_bytes(text_item.text).substr(first_index, second_index - first_index));
+ for (const auto& text_style : current_styles)
+ {
+ switch (text_style.first)
+ {
+ case KETTextObject::EPlain:
+ break;
+ case KETTextObject::EBold:
+ font_face.is_bold = text_style.second;
+ break;
+ case KETTextObject::EItalic:
+ font_face.is_italic = text_style.second;
+ break;
+ case KETTextObject::ESuperScript:
+ font_face.is_superscript = text_style.second;
+ break;
+ case KETTextObject::ESubScript:
+ font_face.is_subscript = text_style.second;
+ break;
+ default:
+ font_size = text_style.second ? text_style.first : 13;
+ break;
+ }
+ }
+
+ XMLElement* s = _doc->NewElement("s");
+ t->LinkEndChild(s);
+ s->SetAttribute("font", 4);
+ s->SetAttribute("size", font_size);
+ s->SetAttribute("face", font_face.face);
+ XMLText* txt = _doc->NewText(sub_text.c_str());
+ s->LinkEndChild(txt);
+ current_styles = kvp.second;
+ first_index = second_index;
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
void MoleculeCdxmlSaver::addText(const Vec2f& pos, const char* text)
{
addText(pos, text, "Center");
@@ -762,9 +990,9 @@ void MoleculeCdxmlSaver::addTitle(const Vec2f& pos, const char* text)
s->LinkEndChild(txt);
}
-void MoleculeCdxmlSaver::addGraphic(int id, const Vec2f& p1, const Vec2f& p2, PropertiesMap& attrs)
+void MoleculeCdxmlSaver::addElement(const char* element, int id, const Vec2f& p1, const Vec2f& p2, PropertiesMap& attrs)
{
- XMLElement* g = _doc->NewElement("graphic");
+ XMLElement* g = _doc->NewElement(element);
_current->LinkEndChild(g);
if (id > 0)
diff --git a/core/indigo-core/molecule/src/molecule_json_loader.cpp b/core/indigo-core/molecule/src/molecule_json_loader.cpp
index b3cedbb480..b00b935a93 100644
--- a/core/indigo-core/molecule/src/molecule_json_loader.cpp
+++ b/core/indigo-core/molecule/src/molecule_json_loader.cpp
@@ -931,7 +931,7 @@ void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows)
}
Array mapping;
- mol.mergeWithMolecule(*pmol, &mapping, COPY_BOND_DIRECTIONS);
+ mol.mergeWithMolecule(*pmol, &mapping, 0);
for (auto& sc : stereo_centers)
{
@@ -994,6 +994,7 @@ void MoleculeJsonLoader::loadMolecule(BaseMolecule& mol, bool load_arrows)
}
mol.buildCisTrans(ignore_cistrans.data());
+ mol.have_xyz = true;
if (mol.stereocenters.size() == 0)
{
mol.buildFrom3dCoordinatesStereocenters(stereochemistry_options);
diff --git a/core/indigo-core/molecule/src/molecule_json_saver.cpp b/core/indigo-core/molecule/src/molecule_json_saver.cpp
index 81790b0a70..ebb9492e24 100644
--- a/core/indigo-core/molecule/src/molecule_json_saver.cpp
+++ b/core/indigo-core/molecule/src/molecule_json_saver.cpp
@@ -855,6 +855,7 @@ void MoleculeJsonSaver::saveMolecule(BaseMolecule& bmol, Writer& w
{
std::unique_ptr mol(bmol.neu());
mol->clone_KeepIndices(bmol);
+
MoleculeCIPCalculator mcc;
mcc.updateCIPStereoDescriptors(*mol, _add_stereo_desc);
@@ -865,6 +866,7 @@ void MoleculeJsonSaver::saveMolecule(BaseMolecule& bmol, Writer& w
ml.make();
}
BaseMolecule::collapse(*mol);
+
QS_DEF(Array, buf);
ArrayOutput out(buf);
std::set rgrp_full_list;
diff --git a/core/indigo-core/reaction/base_reaction.h b/core/indigo-core/reaction/base_reaction.h
index f208bb6675..cdc001c955 100644
--- a/core/indigo-core/reaction/base_reaction.h
+++ b/core/indigo-core/reaction/base_reaction.h
@@ -37,6 +37,16 @@ namespace indigo
class QueryReaction;
class BaseReaction;
+ struct SpecialCondition
+ {
+ public:
+ SpecialCondition(int idx, const Rect2f& box) : meta_idx(idx), bbox(box)
+ {
+ }
+ int meta_idx;
+ Rect2f bbox;
+ };
+
class SideIter : public AutoIterator
{
public:
@@ -197,6 +207,16 @@ namespace indigo
return _types[index];
}
+ int undefinedCount() const
+ {
+ return _undefinedCount;
+ }
+
+ int intermediateCount() const
+ {
+ return _intermediateCount;
+ }
+
int reactantsCount() const
{
return _reactantCount;
@@ -210,6 +230,11 @@ namespace indigo
return _catalystCount;
}
+ int specialConditionsCount() const
+ {
+ return _specialConditions.size();
+ }
+
int reactionBlocksCount() const
{
return _reactionBlocks.size();
@@ -270,6 +295,9 @@ namespace indigo
int addCatalyst();
int addIntermediate();
int addUndefined();
+ int addSpecialCondition(int meta_idx, const Rect2f& bbox);
+ void clearSpecialConditions();
+ const SpecialCondition& specialCondition(int meta_idx) const;
int addReactantCopy(BaseMolecule& mol, Array* mapping, Array* inv_mapping);
int addProductCopy(BaseMolecule& mol, Array* mapping, Array* inv_mapping);
@@ -304,12 +332,14 @@ namespace indigo
ObjArray _reactionBlocks; // for multistep reactions only
Array _types;
+ Array _specialConditions;
int _reactantCount;
int _productCount;
int _catalystCount;
int _intermediateCount;
int _undefinedCount;
+ int _specialCount;
int _nextElement(int type, int index);
diff --git a/core/indigo-core/reaction/reaction_cdxml_loader.h b/core/indigo-core/reaction/reaction_cdxml_loader.h
new file mode 100644
index 0000000000..91bbb0f61d
--- /dev/null
+++ b/core/indigo-core/reaction/reaction_cdxml_loader.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * Copyright (C) from 2009 to Present EPAM Systems.
+ *
+ * This file is part of Indigo toolkit.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+#ifndef __reaction_cdxml_loader__
+#define __reaction_cdxml_loader__
+
+#include "base_cpp/exception.h"
+#include "molecule/molecule.h"
+#include "molecule/molecule_cdxml_loader.h"
+#include "molecule/molecule_stereocenter_options.h"
+#include "molecule/query_molecule.h"
+#include "reaction/base_reaction.h"
+
+namespace indigo
+{
+
+ class Scanner;
+ class Reaction;
+
+ class ReactionCdxmlLoader
+ {
+ public:
+ DECL_ERROR;
+
+ ReactionCdxmlLoader(Scanner& scanner);
+ ~ReactionCdxmlLoader();
+
+ void loadReaction(BaseReaction& rxn);
+
+ StereocentersOptions stereochemistry_options;
+ bool ignore_bad_valence;
+ std::set reactants_ids;
+ std::set products_ids;
+ std::set intermediates_ids;
+ std::set arrows_ids;
+ std::set agents_ids;
+
+ protected:
+ Scanner& _scanner;
+
+ private:
+ ReactionCdxmlLoader(const ReactionCdxmlLoader&); // no implicit copy
+ void _initReaction(BaseReaction& rxn);
+ void _parseStep(const tinyxml2::XMLAttribute* pAttr);
+ Reaction* _prxn;
+ QueryReaction* _pqrxn;
+ Molecule _mol;
+ QueryMolecule _qmol;
+ BaseMolecule* _pmol;
+ std::map _cdxml_elements;
+ };
+
+}; // namespace indigo
+
+#endif
diff --git a/core/indigo-core/reaction/reaction_cdxml_saver.h b/core/indigo-core/reaction/reaction_cdxml_saver.h
index 42094a820d..bfdcd1a294 100644
--- a/core/indigo-core/reaction/reaction_cdxml_saver.h
+++ b/core/indigo-core/reaction/reaction_cdxml_saver.h
@@ -19,6 +19,8 @@
#ifndef __reaction_cdxml_saver__
#define __reaction_cdxml_saver__
+#include
+
#include "base_cpp/array.h"
#include "base_cpp/exception.h"
#include "base_cpp/obj_array.h"
@@ -51,9 +53,9 @@ namespace indigo
void _addArrow(BaseReaction& rxn, MoleculeCdxmlSaver& molsaver, int arrow_id);
void _addScheme(MoleculeCdxmlSaver& molsaver);
void _closeScheme(MoleculeCdxmlSaver& molsaver);
- void _addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsaver, Array& reactants_ids, Array& products_ids, ObjArray>& nodes_ids,
- int arrow_id);
- void _generateCdxmlObjIds(BaseReaction& rxn, Array& reactants_ids, Array& products_ids, ObjArray>& nodes_ids, int& arrow_id);
+ void _addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsaver, std::unordered_map& mol_ids, ObjArray>& nodes_ids, int arrow_id);
+ void _generateCdxmlObjIds(BaseReaction& rxn, std::unordered_map& mol_ids, std::unordered_map& meta_ids,
+ ObjArray>& nodes_ids, int& arrow_id);
void _addTitle(BaseReaction& rxn, MoleculeCdxmlSaver& molsaver);
};
diff --git a/core/indigo-core/reaction/reaction_json_loader.h b/core/indigo-core/reaction/reaction_json_loader.h
index 451a81a9b2..87df4f06d2 100644
--- a/core/indigo-core/reaction/reaction_json_loader.h
+++ b/core/indigo-core/reaction/reaction_json_loader.h
@@ -37,7 +37,7 @@ namespace indigo
lb.x = std::min(bb1.left(), bb2.left());
rt.x = std::max(bb1.right(), bb2.right());
lb.y = std::min(bb1.bottom(), bb2.bottom());
- lb.y = std::max(bb1.top(), bb2.top());
+ rt.y = std::max(bb1.top(), bb2.top());
bb1 = Rect2f(lb, rt);
}
diff --git a/core/indigo-core/reaction/src/base_reaction.cpp b/core/indigo-core/reaction/src/base_reaction.cpp
index daace30bd3..e133105549 100644
--- a/core/indigo-core/reaction/src/base_reaction.cpp
+++ b/core/indigo-core/reaction/src/base_reaction.cpp
@@ -268,6 +268,22 @@ void BaseReaction::clearAAM()
}
}
+int BaseReaction::addSpecialCondition(int meta_idx, const Rect2f& bbox)
+{
+ _specialConditions.push(SpecialCondition(meta_idx, bbox));
+ return _specialConditions.size() - 1;
+}
+
+void BaseReaction::clearSpecialConditions()
+{
+ _specialConditions.clear();
+}
+
+const SpecialCondition& BaseReaction::specialCondition(int meta_idx) const
+{
+ return _specialConditions[meta_idx];
+}
+
int BaseReaction::addReactantCopy(BaseMolecule& mol, Array* mapping, Array* inv_mapping)
{
int idx = _allMolecules.add(mol.neu());
diff --git a/core/indigo-core/reaction/src/reaction_auto_loader.cpp b/core/indigo-core/reaction/src/reaction_auto_loader.cpp
index d37dccf865..1cc39c42f7 100644
--- a/core/indigo-core/reaction/src/reaction_auto_loader.cpp
+++ b/core/indigo-core/reaction/src/reaction_auto_loader.cpp
@@ -23,6 +23,7 @@
#include "reaction/icr_saver.h"
#include "reaction/query_reaction.h"
#include "reaction/reaction.h"
+#include "reaction/reaction_cdxml_loader.h"
#include "reaction/reaction_cml_loader.h"
#include "reaction/reaction_json_loader.h"
#include "reaction/rsmiles_loader.h"
@@ -174,6 +175,28 @@ void ReactionAutoLoader::_loadReaction(BaseReaction& reaction, bool query)
_scanner->seek(pos, SEEK_SET);
}
+ // check for CDXML format
+ {
+ long long pos = _scanner->tell();
+ _scanner->skipSpace();
+ if (_scanner->lookNext() == '<' && _scanner->findWord("findWord("seek(pos, SEEK_SET);
+ ReactionCdxmlLoader loader(*_scanner);
+ loader.stereochemistry_options = stereochemistry_options;
+ loader.loadReaction(reaction);
+ return;
+ }
+ else
+ {
+ throw Error("CDXML: not a reacton. No arrows found.");
+ }
+ }
+ _scanner->seek(pos, SEEK_SET);
+ }
+
// check for JSON-KET format
{
diff --git a/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp b/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp
new file mode 100644
index 0000000000..b6a2091742
--- /dev/null
+++ b/core/indigo-core/reaction/src/reaction_cdxml_loader.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+ * Copyright (C) from 2009 to Present EPAM Systems.
+ *
+ * This file is part of Indigo toolkit.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***************************************************************************/
+
+#include
+
+#include "base_cpp/scanner.h"
+#include "base_cpp/tlscont.h"
+#include "molecule/ket_commons.h"
+#include "molecule/molecule_cdxml_loader.h"
+#include "reaction/reaction.h"
+#include "reaction/reaction_cdxml_loader.h"
+
+using namespace indigo;
+using namespace tinyxml2;
+
+IMPL_ERROR(ReactionCdxmlLoader, "reaction CDXML loader");
+
+ReactionCdxmlLoader::ReactionCdxmlLoader(Scanner& scanner) : _scanner(scanner)
+{
+ ignore_bad_valence = false;
+}
+
+ReactionCdxmlLoader::~ReactionCdxmlLoader()
+{
+}
+
+void ReactionCdxmlLoader::_initReaction(BaseReaction& rxn)
+{
+ rxn.clear();
+ reactants_ids.clear();
+ products_ids.clear();
+ intermediates_ids.clear();
+ arrows_ids.clear();
+ agents_ids.clear();
+
+ if (rxn.isQueryReaction())
+ _pqrxn = &rxn.asQueryReaction();
+ else
+ _prxn = &rxn.asReaction();
+
+ if (_prxn)
+ {
+ _pmol = &_mol;
+ }
+ else if (_pqrxn)
+ {
+ _pmol = &_qmol;
+ }
+ else
+ throw Error("unknown reaction type: %s", typeid(rxn).name());
+}
+
+void ReactionCdxmlLoader::_parseStep(const XMLAttribute* pAttr)
+{
+ auto reactants_lambda = [this](const std::string& data) {
+ std::vector frag_ids = split(data, ' ');
+ for (const auto& ids : frag_ids)
+ {
+ auto id = std::stoi(ids);
+ if (this->products_ids.find(id) != this->products_ids.end())
+ {
+ this->products_ids.erase(id);
+ this->intermediates_ids.insert(id);
+ }
+ else
+ {
+ this->reactants_ids.insert(id);
+ }
+ }
+ };
+ auto products_lambda = [this](const std::string& data) {
+ std::vector frag_ids = split(data, ' ');
+ for (const auto& ids : frag_ids)
+ {
+ auto id = std::stoi(ids);
+ if (this->reactants_ids.find(id) != this->reactants_ids.end())
+ {
+ this->reactants_ids.erase(id);
+ this->intermediates_ids.insert(id);
+ }
+ else
+ {
+ this->products_ids.insert(id);
+ }
+ }
+ };
+ auto arrows_lambda = [this](const std::string& data) {
+ std::vector frag_ids = split(data, ' ');
+ for (const auto& ids : frag_ids)
+ this->arrows_ids.insert(std::stoi(ids));
+ };
+ auto agents_lambda = [this](const std::string& data) {
+ std::vector frag_ids = split(data, ' ');
+ for (const auto& ids : frag_ids)
+ this->agents_ids.insert(std::stoi(ids));
+ };
+
+ std::unordered_map> cdxml_dispatcher = {{"ReactionStepReactants", reactants_lambda},
+ {"ReactionStepProducts", products_lambda},
+ {"ReactionStepArrows", arrows_lambda},
+ {"ReactionStepObjectsAboveArrow", agents_lambda},
+ {"ReactionStepObjectsBelowArrow", agents_lambda}};
+ MoleculeCdxmlLoader::applyDispatcher(pAttr, cdxml_dispatcher);
+}
+
+void ReactionCdxmlLoader::loadReaction(BaseReaction& rxn)
+{
+ _initReaction(rxn);
+ QS_DEF(Array, buf);
+ _scanner.readAll(buf);
+ buf.push(0);
+ XMLDocument xml;
+ xml.Parse(buf.ptr());
+
+ if (xml.Error())
+ throw Error("XML parsing error: %s", xml.ErrorStr());
+
+ MoleculeCdxmlLoader loader(_scanner);
+ loader.parseCDXMLAttributes(xml.RootElement()->FirstAttribute());
+
+ for (auto pPageElem = xml.RootElement()->FirstChildElement(); pPageElem; pPageElem = pPageElem->NextSiblingElement())
+ {
+ if (std::string(pPageElem->Value()).compare("page") == 0)
+ {
+ for (auto pCdxmlElem = pPageElem->FirstChildElement(); pCdxmlElem; pCdxmlElem = pCdxmlElem->NextSiblingElement())
+ {
+ if (std::string(pCdxmlElem->Value()).compare("scheme") == 0)
+ {
+ for (auto pSchemeElement = pCdxmlElem->FirstChildElement(); pSchemeElement; pSchemeElement = pSchemeElement->NextSiblingElement())
+ if (std::string(pSchemeElement->Value()).compare("step") == 0)
+ _parseStep(pSchemeElement->FirstAttribute());
+ }
+ else
+ {
+ auto pid = pCdxmlElem->FindAttribute("id");
+ if (pid)
+ _cdxml_elements.emplace(atoi(pid->Value()), pCdxmlElem);
+ }
+ }
+ }
+ }
+
+ for (auto id : reactants_ids)
+ {
+ auto elem_it = _cdxml_elements.find(id);
+ if (elem_it != _cdxml_elements.end())
+ {
+ loader.loadMoleculeFromFragment(*_pmol, elem_it->second);
+ if (_pmol->vertexCount())
+ rxn.addReactantCopy(*_pmol, 0, 0);
+ else
+ throw Error("Empty reactant: %d", id);
+ _cdxml_elements.erase(elem_it);
+ }
+ }
+
+ for (auto id : products_ids)
+ {
+ auto elem_it = _cdxml_elements.find(id);
+ if (elem_it != _cdxml_elements.end())
+ {
+ loader.loadMoleculeFromFragment(*_pmol, elem_it->second);
+ if (_pmol->vertexCount())
+ rxn.addProductCopy(*_pmol, 0, 0);
+ else
+ throw Error("Empty product: %d", id);
+ _cdxml_elements.erase(elem_it);
+ }
+ }
+
+ for (auto id : agents_ids)
+ {
+ auto elem_it = _cdxml_elements.find(id);
+ if (elem_it != _cdxml_elements.end())
+ {
+ loader.loadMoleculeFromFragment(*_pmol, elem_it->second);
+ if (_pmol->vertexCount())
+ rxn.addCatalystCopy(*_pmol, 0, 0);
+ else
+ {
+ for (int i = 0; i < _pmol->meta().getMetaCount(KETTextObject::CID); ++i)
+ {
+ auto& text = (KETTextObject&)_pmol->meta().getMetaObject(KETTextObject::CID, i);
+ int idx = rxn.meta().addMetaObject(text.clone());
+ rxn.addSpecialCondition(idx, Rect2f(Vec2f(text._pos.x, text._pos.y), Vec2f(text._pos.x, text._pos.y)));
+ }
+ _pmol->meta().resetMetaData();
+ }
+ _cdxml_elements.erase(elem_it);
+ }
+ }
+
+ for (auto id : arrows_ids)
+ {
+ auto elem_it = _cdxml_elements.find(id);
+ if (elem_it != _cdxml_elements.end())
+ {
+ loader.loadMoleculeFromFragment(*_pmol, elem_it->second);
+ rxn.meta().append(_pmol->meta());
+ _cdxml_elements.erase(elem_it);
+ }
+ }
+
+ for (const auto& kvp : _cdxml_elements)
+ {
+ loader.loadMoleculeFromFragment(*_pmol, kvp.second);
+ rxn.meta().append(_pmol->meta());
+ }
+}
diff --git a/core/indigo-core/reaction/src/reaction_cdxml_saver.cpp b/core/indigo-core/reaction/src/reaction_cdxml_saver.cpp
index bf5902a39a..8f9adf7b1a 100644
--- a/core/indigo-core/reaction/src/reaction_cdxml_saver.cpp
+++ b/core/indigo-core/reaction/src/reaction_cdxml_saver.cpp
@@ -16,10 +16,13 @@
* limitations under the License.
***************************************************************************/
-#include "reaction/reaction_cdxml_saver.h"
+#include
+
#include "base_cpp/output.h"
+#include "molecule/ket_commons.h"
#include "molecule/molecule_cdxml_saver.h"
#include "reaction/reaction.h"
+#include "reaction/reaction_cdxml_saver.h"
using namespace indigo;
@@ -74,8 +77,9 @@ ReactionCdxmlSaver::~ReactionCdxmlSaver()
void ReactionCdxmlSaver::saveReaction(BaseReaction& rxn)
{
int i;
- Array reactants_ids;
- Array products_ids;
+ std::unordered_map mol_ids;
+ std::unordered_map meta_ids;
+
ObjArray> nodes_ids;
int arrow_id;
@@ -83,10 +87,7 @@ void ReactionCdxmlSaver::saveReaction(BaseReaction& rxn)
MoleculeCdxmlSaver molsaver(_output);
MoleculeCdxmlSaver::Bounds b;
- reactants_ids.clear();
- products_ids.clear();
-
- _generateCdxmlObjIds(rxn, reactants_ids, products_ids, nodes_ids, arrow_id);
+ _generateCdxmlObjIds(rxn, mol_ids, meta_ids, nodes_ids, arrow_id);
molsaver.beginDocument(NULL);
molsaver.addDefaultFontTable();
@@ -95,34 +96,21 @@ void ReactionCdxmlSaver::saveReaction(BaseReaction& rxn)
Vec2f offset(0, 0);
- if (rxn.reactantsCount() > 0)
+ for (i = rxn.begin(); i != rxn.end(); i = rxn.next(i))
+ molsaver.saveMoleculeFragment(rxn.getBaseMolecule(i), offset, 1, mol_ids[i], nodes_ids[i]);
+
+ _addPlusses(rxn, molsaver);
+ if (rxn.meta().metaData().size()) // we have metadata
{
- for (i = rxn.reactantBegin(); i != rxn.reactantEnd(); i = rxn.reactantNext(i))
- {
- molsaver.saveMoleculeFragment(rxn.getBaseMolecule(i), offset, 1, reactants_ids[i], nodes_ids[i]);
- }
+ molsaver.addMetaData(rxn.meta(), arrow_id);
}
- if (rxn.productsCount() > 0)
+ else
{
- for (i = rxn.productBegin(); i != rxn.productEnd(); i = rxn.productNext(i))
- {
- molsaver.saveMoleculeFragment(rxn.getBaseMolecule(i), offset, 1, products_ids[i], nodes_ids[i]);
- }
+ _addArrow(rxn, molsaver, arrow_id);
}
- /*
- if (rxn.catalystCount() > 0)
- {
- for (i = rxn.catalystBegin(); i != rxn.catalystEnd(); i = rxn.catalystNext(i))
- {
- molsaver.saveMoleculeFragment(rxn.getBaseMolecule(i), offset, 1);
- }
- }
- */
- _addPlusses(rxn, molsaver);
- _addArrow(rxn, molsaver, arrow_id);
_addScheme(molsaver);
- _addStep(rxn, molsaver, reactants_ids, products_ids, nodes_ids, arrow_id);
+ _addStep(rxn, molsaver, mol_ids, nodes_ids, arrow_id);
_closeScheme(molsaver);
if (rxn.name.size() > 0)
@@ -282,7 +270,7 @@ void ReactionCdxmlSaver::_addArrow(BaseReaction& rxn, MoleculeCdxmlSaver& molsav
attrs.insert("ArrowType", "FullHead");
attrs.insert("HeadSize", "1000");
- molsaver.addGraphic(id, p1, p2, attrs);
+ molsaver.addElement("graphic", id, p1, p2, attrs);
}
void ReactionCdxmlSaver::_addScheme(MoleculeCdxmlSaver& molsaver)
@@ -303,8 +291,8 @@ void ReactionCdxmlSaver::_closeScheme(MoleculeCdxmlSaver& molsaver)
molsaver.endCurrentElement();
}
-void ReactionCdxmlSaver::_addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsaver, Array& reactants_ids, Array& products_ids,
- ObjArray>& nodes_ids, int arrow_id)
+void ReactionCdxmlSaver::_addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsaver, std::unordered_map& mol_ids, ObjArray>& nodes_ids,
+ int arrow_id)
{
int id = -1;
Array name;
@@ -317,10 +305,10 @@ void ReactionCdxmlSaver::_addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsave
Array buf;
ArrayOutput buf_out(buf);
- for (auto i = 0; i < reactants_ids.size(); i++)
+ for (auto i = rxn.reactantBegin(); i < rxn.reactantEnd(); i = rxn.reactantNext(i))
{
- if (reactants_ids[i] > 0)
- buf_out.printf("%d ", reactants_ids[i]);
+ if (mol_ids[i] > 0)
+ buf_out.printf("%d ", mol_ids[i]);
}
if (buf.size() > 1)
{
@@ -330,10 +318,10 @@ void ReactionCdxmlSaver::_addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsave
}
buf.clear();
- for (auto i = 0; i < products_ids.size(); i++)
+ for (auto i = rxn.productBegin(); i < rxn.productEnd(); i = rxn.productNext(i))
{
- if (products_ids[i] > 0)
- buf_out.printf("%d ", products_ids[i]);
+ if (mol_ids[i] > 0)
+ buf_out.printf("%d ", mol_ids[i]);
}
if (buf.size() > 1)
{
@@ -342,6 +330,22 @@ void ReactionCdxmlSaver::_addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsave
attrs.insert("ReactionStepProducts", buf.ptr());
}
+ std::string below_arrow, above_arrow;
+ for (auto i = rxn.catalystBegin(); i < rxn.catalystEnd(); i = rxn.catalystNext(i))
+ {
+ if (mol_ids[i] > 0)
+ {
+ if (above_arrow.size())
+ above_arrow += " ";
+ above_arrow += std::to_string(mol_ids[i]);
+ }
+ }
+ if (above_arrow.size())
+ attrs.insert("ReactionStepObjectsAboveArrow", above_arrow.c_str());
+
+ if (below_arrow.size())
+ attrs.insert("ReactionStepObjectsAboveArrow", above_arrow.c_str());
+
buf.clear();
buf_out.printf("%d", arrow_id);
buf.push(0);
@@ -380,21 +384,15 @@ void ReactionCdxmlSaver::_addStep(BaseReaction& rxn, MoleculeCdxmlSaver& molsave
molsaver.addCustomElement(id, name, attrs);
}
-void ReactionCdxmlSaver::_generateCdxmlObjIds(BaseReaction& rxn, Array& reactants_ids, Array& products_ids, ObjArray>& nodes_ids,
- int& arrow_id)
+void ReactionCdxmlSaver::_generateCdxmlObjIds(BaseReaction& rxn, std::unordered_map& mol_ids, std::unordered_map& meta_ids,
+ ObjArray>& nodes_ids, int& arrow_id)
{
- reactants_ids.clear_resize(rxn.reactantEnd());
- reactants_ids.zerofill();
-
- products_ids.clear_resize(rxn.productEnd());
- products_ids.zerofill();
int id = 0;
-
- for (auto i = rxn.reactantBegin(); i != rxn.reactantEnd(); i = rxn.reactantNext(i))
+ for (auto i = rxn.begin(); i != rxn.end(); i = rxn.next(i))
{
id++;
- reactants_ids[i] = id;
+ mol_ids.insert(std::make_pair(i, id));
BaseMolecule& mol = rxn.getBaseMolecule(i);
@@ -409,26 +407,20 @@ void ReactionCdxmlSaver::_generateCdxmlObjIds(BaseReaction& rxn, Array& rea
}
}
- for (auto i = rxn.productBegin(); i != rxn.productEnd(); i = rxn.productNext(i))
+ // generate ids for meta objects. 1 node and 1 extra object. text or graphics
+ for (auto i = 0; i < rxn.meta().metaData().size(); ++i)
{
+ int r_id = i + rxn.end();
id++;
- products_ids[i] = id;
-
- BaseMolecule& mol = rxn.getBaseMolecule(i);
-
- nodes_ids.expand(i + 1);
- nodes_ids[i].clear_resize(mol.vertexEnd());
- nodes_ids[i].zerofill();
-
- for (auto j = mol.vertexBegin(); j != mol.vertexEnd(); j = mol.vertexNext(j))
- {
- id++;
- nodes_ids[i][j] = id;
- }
+ meta_ids.insert(std::make_pair(r_id, id));
+ nodes_ids.expand(r_id + 1);
+ nodes_ids[r_id].clear_resize(1);
+ nodes_ids[r_id].zerofill();
+ id += 2;
+ nodes_ids[r_id][0] = id;
}
arrow_id = id + 1;
-
return;
}
diff --git a/core/indigo-core/reaction/src/reaction_json_loader.cpp b/core/indigo-core/reaction/src/reaction_json_loader.cpp
index 830f78a772..e585d4058a 100644
--- a/core/indigo-core/reaction/src/reaction_json_loader.cpp
+++ b/core/indigo-core/reaction/src/reaction_json_loader.cpp
@@ -449,7 +449,7 @@ void ReactionJsonLoader::parseOneArrowReaction(BaseReaction& rxn)
{
enum RecordIndexes
{
- LEFT_BOUND_IDX = 0,
+ BBOX_IDX = 0,
FRAGMENT_TYPE_IDX,
MOLECULE_IDX
};
@@ -458,74 +458,92 @@ void ReactionJsonLoader::parseOneArrowReaction(BaseReaction& rxn)
{
MOLECULE,
PLUS,
- ARROW
+ ARROW,
+ TEXT
};
- using ReactionComponent = std::tuple>;
-
- std::unique_ptr merged_molecule;
-
- if (rxn.isQueryReaction())
- merged_molecule = std::make_unique();
- else
- merged_molecule = std::make_unique();
-
- int count = _pmol->countComponents();
+ using ReactionComponent = std::tuple>;
std::vector components;
- for (int index = 0; index < count; ++index)
+ for (int index = 0; index < _pmol->countComponents(); ++index)
{
+ std::unique_ptr mol;
if (_pmol->isQueryMolecule())
- components.emplace_back(0, ReactionFragmentType::MOLECULE, std::make_unique());
+ mol = std::make_unique();
else
- components.emplace_back(0, ReactionFragmentType::MOLECULE, std::make_unique());
+ mol = std::make_unique();
+
Filter filter(_pmol->getDecomposition().ptr(), Filter::EQ, index);
- ReactionComponent& rc = components.back();
- BaseMolecule& mol = *(std::get(rc));
- mol.makeSubmolecule(*_pmol, filter, 0, 0);
+ mol->makeSubmolecule(*_pmol, filter, 0, 0);
Rect2f bbox;
- mol.getBoundingBox(bbox);
-
- std::get(rc) = bbox.left();
+ mol->getBoundingBox(bbox);
+ components.emplace_back(bbox, ReactionFragmentType::MOLECULE, std::move(mol));
}
auto& arrow = (const KETReactionArrow&)rxn.meta().getMetaObject(KETReactionArrow::CID, 0);
+ Vec2f arrow_vec(arrow._begin);
+ arrow_vec.sub(arrow._end);
- float arrow_x = arrow._begin.x;
- components.emplace_back(arrow_x, ReactionFragmentType::ARROW, nullptr);
- for (int i = 0; i < rxn.meta().getMetaCount(KETReactionPlus::CID); ++i)
+ for (int i = 0; i < rxn.meta().getMetaCount(KETTextObject::CID); ++i)
{
- auto& plus = (const KETReactionPlus&)rxn.meta().getMetaObject(KETReactionPlus::CID, i);
- components.emplace_back(plus._pos.x, ReactionFragmentType::PLUS, nullptr);
+ auto& text = (const KETReactionPlus&)rxn.meta().getMetaObject(KETTextObject::CID, i);
+ Rect2f bbox(text._pos, text._pos); // change to real text box later
+ components.emplace_back(bbox, ReactionFragmentType::TEXT, nullptr);
}
- std::sort(components.begin(), components.end(),
- [](const ReactionComponent& a, const ReactionComponent& b) -> bool { return std::get(a) < std::get(b); });
-
- bool is_arrow_passed = false;
-
+ int text_meta_idx = 0;
for (const auto& comp : components)
{
switch (std::get(comp))
{
- case ReactionFragmentType::MOLECULE:
- merged_molecule->mergeWithMolecule(*std::get(comp), 0, 0);
- break;
- case ReactionFragmentType::ARROW:
- rxn.addReactantCopy(*merged_molecule, 0, 0);
- is_arrow_passed = true;
- merged_molecule->clear();
- break;
- case ReactionFragmentType::PLUS:
- if (is_arrow_passed)
- rxn.addProductCopy(*merged_molecule, 0, 0);
- else
- rxn.addReactantCopy(*merged_molecule, 0, 0);
- merged_molecule->clear();
+ case ReactionFragmentType::MOLECULE: {
+ auto& cmol = *std::get(comp);
+ for (int idx = cmol.vertexBegin(); idx < cmol.vertexEnd(); idx = cmol.vertexNext(idx))
+ {
+ Vec3f& v3 = cmol.getAtomXyz(idx);
+ Vec2f slope1(v3.x, v3.y);
+ Vec2f slope2(slope1);
+ slope1.sub(arrow._begin);
+ slope2.sub(arrow._end);
+ auto dt1 = Vec2f::dot(slope1, arrow_vec);
+ auto dt2 = Vec2f::dot(slope2, arrow_vec);
+ if (std::signbit(dt1) != std::signbit(dt2))
+ {
+ rxn.addCatalystCopy(cmol, 0, 0);
+ break;
+ }
+ else if (std::signbit(dt1) && std::signbit(dt2))
+ {
+ rxn.addProductCopy(cmol, 0, 0);
+ break;
+ }
+ else
+ {
+ rxn.addReactantCopy(cmol, 0, 0);
+ break;
+ }
+ }
+ }
+ case ReactionFragmentType::TEXT: {
+ const auto& bbox = std::get(comp);
+ Vec2f slope1(bbox.leftTop().x, bbox.leftTop().y);
+ Vec2f slope2(slope1);
+ slope1.sub(arrow._begin);
+ slope2.sub(arrow._end);
+ auto dt1 = Vec2f::dot(slope1, arrow_vec);
+ auto dt2 = Vec2f::dot(slope2, arrow_vec);
+ if (std::signbit(dt1) != std::signbit(dt2))
+ {
+ rxn.addSpecialCondition(text_meta_idx, bbox);
+ break;
+ }
+ text_meta_idx++;
+ }
+ break;
+ default:
break;
}
}
- rxn.addProductCopy(*merged_molecule, 0, 0);
}
diff --git a/core/indigo-core/reaction/src/reaction_json_saver.cpp b/core/indigo-core/reaction/src/reaction_json_saver.cpp
index d51dd79ee2..72b6746823 100644
--- a/core/indigo-core/reaction/src/reaction_json_saver.cpp
+++ b/core/indigo-core/reaction/src/reaction_json_saver.cpp
@@ -78,7 +78,7 @@ void ReactionJsonSaver::saveReaction(BaseReaction& rxn, BaseMolecule& merged, Mo
{
std::vector pluses;
- Vec2f rmin(0, 0), rmax(0, 0), pmin(0, 0), pmax(0, 0);
+ Vec2f rmin(0, 0), rmax(0, 0), pmin(0, 0), pmax(0, 0), cmin(0, 0), cmax(0, 0);
if (rxn.reactantsCount() > 0)
{
@@ -142,6 +142,26 @@ void ReactionJsonSaver::saveReaction(BaseReaction& rxn, BaseMolecule& merged, Mo
}
}
+ if (rxn.catalystCount() > 0)
+ {
+ for (int i = rxn.catalystBegin(); i != rxn.catalystEnd(); i = rxn.catalystNext(i))
+ {
+ Vec2f min1, max1;
+ _getBounds(rxn.getBaseMolecule(i), min1, max1, 1.0);
+ merged.mergeWithMolecule(rxn.getBaseMolecule(i), 0, 0);
+ if (i == rxn.catalystBegin())
+ {
+ cmin = min1;
+ cmax = max1;
+ }
+ else
+ {
+ cmin.min(min1);
+ cmax.max(max1);
+ }
+ }
+ }
+
// dump molecules
StringBuffer s;
Writer writer(s);
@@ -208,6 +228,14 @@ void ReactionJsonSaver::saveReaction(BaseReaction& rxn, BaseMolecule& merged, Mo
p1.x = (rmax.x + pmin.x) / 2 + 1.0f;
p1.y = (pmin.y + pmax.y) / 2;
}
+ if (rxn.catalystCount() && cmin.x != cmax.x)
+ {
+ if (cmin.x < p2.x)
+ p2.x = cmin.x;
+
+ if (cmax.x > p1.x)
+ p1.x = cmax.x;
+ }
}
Value arrow(kObjectType);
diff --git a/core/render2d/src/render_cdxml.cpp b/core/render2d/src/render_cdxml.cpp
index c9b8824df0..8306805cea 100644
--- a/core/render2d/src/render_cdxml.cpp
+++ b/core/render2d/src/render_cdxml.cpp
@@ -223,7 +223,7 @@ void RenderParamCdxmlInterface::_renderMols(RenderParams& params)
// On average letters has width 6
float letter_width = params.rOpt.titleFontFactor / 1.5f;
- float title_width = longest_line * letter_width / MoleculeCdxmlSaver::BOND_LENGTH;
+ float title_width = longest_line * letter_width / MoleculeCdxmlSaver::SCALE;
title_widths[mol_idx] = title_width;
width = std::max(width, title_width);
}
@@ -237,10 +237,10 @@ void RenderParamCdxmlInterface::_renderMols(RenderParams& params)
float letter_width = context.propertyFontSize / 1.5f;
int longest_line = _getLongestLineXml(data.propertyName);
- key_widths[mol_idx] = longest_line * letter_width / MoleculeCdxmlSaver::BOND_LENGTH;
+ key_widths[mol_idx] = longest_line * letter_width / MoleculeCdxmlSaver::SCALE;
longest_line += _getLongestLineXml(data.propertyValue);
- float prop_width = longest_line * letter_width / MoleculeCdxmlSaver::BOND_LENGTH;
+ float prop_width = longest_line * letter_width / MoleculeCdxmlSaver::SCALE;
prop_widths[mol_idx] = prop_width;
width = std::max(width, prop_width);
@@ -287,7 +287,7 @@ void RenderParamCdxmlInterface::_renderMols(RenderParams& params)
if (title.size() > 0)
{
int lines = title.count('\n') + 1;
- float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::BOND_LENGTH;
+ float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::SCALE;
// float title_height = lines * saver.textLineHeight();
// p.all_size.y += title_height + saver.textLineHeight(); // Add blank line
float title_height = lines * letter_height;
@@ -303,7 +303,7 @@ void RenderParamCdxmlInterface::_renderMols(RenderParams& params)
RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
int lines = data.propertyName.count('\n') + 1;
- float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::BOND_LENGTH;
+ float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::SCALE;
float prop_height = lines * letter_height;
p.all_size.y += prop_height + letter_height; // Add blank line
}
diff --git a/utils/indigo-depict/main.c b/utils/indigo-depict/main.c
index d1a0e26ac6..a09fda90a8 100644
--- a/utils/indigo-depict/main.c
+++ b/utils/indigo-depict/main.c
@@ -247,6 +247,7 @@ enum
OEXT_KER,
OEXT_CDX,
OEXT_CDXML,
+ OEXT_CDXMLR,
OEXT_SMI,
OEXT_OTHER
};
@@ -283,7 +284,7 @@ void renderToFile(int obj, const char* outfile)
typedef struct tagParams
{
const char* outfile;
- char outfile_ext[4], infile_ext[7];
+ char outfile_ext[7], infile_ext[7];
int width;
int height;
int bond;
@@ -337,7 +338,7 @@ int parseParams(Params* p, int argc, char* argv[])
if (strcasecmp(p->infile_ext, "cdx") == 0 || strcasecmp(p->infile_ext, "mol") == 0 || strcasecmp(p->infile_ext, "ket") == 0 ||
strcasecmp(p->infile_ext, "xml") == 0)
p->mode = MODE_SINGLE_MOLECULE;
- else if (strcasecmp(p->infile_ext, "rxn") == 0 || strcasecmp(p->infile_ext, "ker") == 0)
+ else if (strcasecmp(p->infile_ext, "rxn") == 0 || strcasecmp(p->infile_ext, "ker") == 0 || strcasecmp(p->infile_ext, "xmr") == 0)
p->mode = MODE_SINGLE_REACTION;
else if (strcasecmp(p->infile_ext, "smi") == 0)
{
@@ -379,11 +380,11 @@ int parseParams(Params* p, int argc, char* argv[])
p->outfile = argv[i++];
- if (strlen(p->outfile) < 5 || p->outfile[strlen(p->outfile) - 4] != '.')
+ const char* ptr_dot = strstr(p->outfile, ".");
+ if (!ptr_dot)
USAGE();
- p->outfile_ext[3] = 0;
- strncpy(p->outfile_ext, p->outfile + strlen(p->outfile) - 3, 3);
+ strcpy(p->outfile_ext, ptr_dot + 1);
indigoSetOptionBool("treat-x-as-pseudoatom", 1);
indigoSetOptionBool("render-coloring", 1);
@@ -865,6 +866,10 @@ int main(int argc, char* argv[])
p.out_ext = OEXT_KER;
else if (strcmp(p.outfile_ext, "smi") == 0)
p.out_ext = OEXT_SMI;
+ else if (strcmp(p.outfile_ext, "cdxml") == 0)
+ p.out_ext = OEXT_CDXML;
+ else if (strcmp(p.outfile_ext, "cdxmr") == 0)
+ p.out_ext = OEXT_CDXMLR;
// guess whether to layout or render by extension
p.action = ACTION_LAYOUT;
@@ -920,6 +925,10 @@ int main(int argc, char* argv[])
return -1;
}
}
+ else if (p.out_ext == OEXT_CDXML)
+ {
+ indigoSaveCdxmlToFile(obj, p.outfile);
+ }
else
indigoSaveCmlToFile(obj, p.outfile);
}
@@ -951,8 +960,13 @@ int main(int argc, char* argv[])
indigoSaveCmlToFile(obj, p.outfile);
else if (p.out_ext == OEXT_RXN)
indigoSaveRxnfileToFile(obj, p.outfile);
+ else if (p.out_ext == OEXT_CDXML)
+ indigoSaveCdxmlToFile(obj, p.outfile);
else
+ {
indigoSaveJsonToFile(obj, p.outfile);
+ printf("smiles: %s\n", indigoSmiles(obj));
+ }
}
else
{
diff --git a/utils/indigo-service/backend/service/v2/indigo_api.py b/utils/indigo-service/backend/service/v2/indigo_api.py
index 86797ccd69..30bc435085 100644
--- a/utils/indigo-service/backend/service/v2/indigo_api.py
+++ b/utils/indigo-service/backend/service/v2/indigo_api.py
@@ -370,6 +370,8 @@ def save_moldata(md, output_format=None, options={}, indigo=None):
return md.struct.smarts()
elif output_format == "chemical/x-cml":
return md.struct.cml()
+ elif output_format == "chemical/x-cdxml":
+ return md.struct.cdxml()
elif output_format == "chemical/x-inchi":
return indigo.inchi.getInchi(md.struct)
elif output_format == "chemical/x-inchi-key":