From 4bc788f1e1cb4fdd8c10374905f110e01ca02658 Mon Sep 17 00:00:00 2001 From: Nikita Date: Tue, 29 Nov 2022 11:07:06 +0300 Subject: [PATCH 01/27] #1811 added more functional groups (#1868) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #1839 – removed lightweight tag from page title * #1845 – added more functional groups * #1811 – updated Boc and Mes functional groups * #1811 – removed X in all functional groups --- example/public/templates/fg.sdf | 631 ++++++++++++++++++++++++++++++++ 1 file changed, 631 insertions(+) diff --git a/example/public/templates/fg.sdf b/example/public/templates/fg.sdf index 84d7ba1314..3a9d0321a2 100644 --- a/example/public/templates/fg.sdf +++ b/example/public/templates/fg.sdf @@ -55,6 +55,38 @@ Functional Groups $$$$ +Boc +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 7 6 0 0 1 0 0 0 0 0999 V2000 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 1.2990 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 -1.2990 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 2.7990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 -0.2010 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 Bn +M END + +> +Functional Groups + +> +0 + +$$$$ + Bu Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -112,6 +144,46 @@ Functional Groups > 0 + +$$$$ + +Cbz +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 10 10 0 0 1 0 0 0 0 0999 V2000 + 8.5563 4.7294 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.8554 3.9794 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.8554 2.4794 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5563 1.7294 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.2573 2.4794 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.2573 3.9794 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9582 4.7294 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6592 3.9794 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3602 4.7294 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3602 6.2294 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 1 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 9 10 2 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 Cbz +M SAL 1 10 1 2 3 4 5 6 7 8 9 10 +M END + +> +Functional Groups + +> +0 + $$$$ C2H5 @@ -186,6 +258,28 @@ Functional Groups $$$$ +CN +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 2 1 0 0 1 0 0 0 0 0999 V2000 + -4.4500 5.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.9500 5.0500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 3 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 CN +M SAL 1 2 1 2 +M END + +> +Functional Groups + +> +0 + +$$$$ + CO2Et Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -264,6 +358,30 @@ Functional Groups $$$$ +CONH2 +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 3 2 0 0 1 0 0 0 0 0999 V2000 + -7.8000 3.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -7.0500 4.5490 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -7.0500 1.9510 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 CONH2 +M SAL 1 3 1 2 3 +M END + +> +Functional Groups + +> +0 + +$$$$ + CO2Pr Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -415,6 +533,37 @@ Functional Groups $$$$ +Cy +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 6 6 0 0 1 0 0 0 0 0999 V2000 + 3.9490 -2.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9490 -5.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 1 0 0 0 0 + 2 1 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 1 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 Cy +M END + +> +Functional Groups + +> +0 + +$$$$ + Et Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -438,6 +587,61 @@ Functional Groups $$$$ +FMOC +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 17 19 0 0 1 0 0 0 0 0999 V2000 + 7.2573 3.9794 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9582 4.7294 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6592 3.9794 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3602 4.7294 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3602 6.2294 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.4141 2.4876 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8814 2.1758 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.6313 3.4748 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6276 4.5895 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.0985 3.7867 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5620 5.2133 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.5583 6.3280 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0911 6.0161 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4105 1.3729 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8740 -0.0537 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.3412 -0.3655 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.3449 0.7492 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 + 4 5 2 0 0 0 0 + 1 6 1 0 0 0 0 + 6 7 2 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 1 1 0 0 0 0 + 8 10 1 0 0 0 0 + 10 11 2 0 0 0 0 + 11 12 1 0 0 0 0 + 12 13 2 0 0 0 0 + 13 9 1 0 0 0 0 + 6 14 1 0 0 0 0 + 14 15 2 0 0 0 0 + 15 16 1 0 0 0 0 + 16 17 2 0 0 0 0 + 17 7 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +M SMT 1 FMOC +M END + +> +Functional Groups + +> +0 + +$$$$ + iBu Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -546,6 +750,41 @@ Functional Groups $$$$ +Mes +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 8 8 0 0 1 0 0 0 0 0999 V2000 + -0.1000 1.6571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6500 0.3581 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6500 2.9561 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1500 0.3581 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9000 1.6571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1500 2.9561 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9000 4.2552 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9000 -0.9409 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 + 6 7 1 0 0 0 0 + 4 8 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 Mes +M END + +> +Functional Groups + +> +0 + +$$$$ + Ms Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -653,6 +892,85 @@ Functional Groups $$$$ +NO2 +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 3 2 0 0 1 0 0 0 0 0999 V2000 + -6.6000 4.4000 0.0000 N 0 3 0 0 0 0 0 0 0 0 0 0 + -5.8500 5.6990 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -5.8500 3.1010 0.0000 O 0 5 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 +M CHG 2 1 1 3 -1 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 NO2 +M SAL 1 3 1 2 3 +M END + +> +Functional Groups + +> +0 + +$$$$ + +OAc +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 4 3 0 0 1 0 0 0 0 0999 V2000 + -8.0010 2.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.7019 3.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.4029 2.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -6.7019 4.7500 0.0000 O 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 + 2 4 2 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 OAc +M SAL 1 4 1 2 3 4 +M END + +> +Functional Groups + +> +0 + +$$$$ + +OCF3 +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 5 4 0 0 1 0 0 0 0 0999 V2000 + 0.0000 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -1.5000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 1.5000 0.0000 F 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 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 OCF3 +M SAL 1 5 1 2 3 4 5 +M END + +> +Functional Groups + +> +0 + +$$$$ + OCN Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -791,6 +1109,36 @@ Functional Groups $$$$ +Piv +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 6 5 0 0 1 0 0 0 0 0999 V2000 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 1.2990 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -2.5981 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5490 -0.5490 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9510 -2.0490 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 Piv +M SAL 1 6 1 2 3 4 5 6 +M END + +> +Functional Groups + +> +0 + +$$$$ + PO2 Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -843,6 +1191,32 @@ Functional Groups $$$$ +PO3H2 +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 4 3 0 0 1 0 0 0 0 0999 V2000 + -1.2500 0.8500 0.0000 P 0 0 0 0 0 5 0 0 0 0 0 0 + -1.2500 2.3500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 -0.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2500 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 PO3H2 +M SAL 1 4 1 2 3 4 +M END + +> +Functional Groups + +> +0 + +$$$$ + PO4 Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -872,6 +1246,34 @@ Functional Groups $$$$ +PO4H2 +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 5 4 0 0 1 0 0 0 0 0999 V2000 + -2.7500 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 0.8500 0.0000 P 0 0 0 0 0 5 0 0 0 0 0 0 + -1.2500 2.3500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 -0.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2500 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 2 1 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 PO4H2 +M SAL 1 5 1 2 3 4 5 +M END + +> +Functional Groups + +> +0 + +$$$$ + Pr Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -996,6 +1398,30 @@ Functional Groups $$$$ +SO2H +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 3 2 0 0 1 0 0 0 0 0999 V2000 + -1.2500 0.8500 0.0000 S 0 0 0 0 0 5 0 0 0 0 0 0 + -1.2500 2.3500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 -0.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 SO2H +M SAL 1 3 1 2 3 +M END + +> +Functional Groups + +> +0 + +$$$$ + SO3 Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -1023,6 +1449,32 @@ Functional Groups $$$$ +SO3H +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 4 3 0 0 1 0 0 0 0 0999 V2000 + -1.2500 0.8500 0.0000 S 0 0 0 0 0 6 0 0 0 0 0 0 + -1.2500 2.3500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 -0.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2500 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 SO3H +M SAL 1 4 1 2 3 4 +M END + +> +Functional Groups + +> +0 + +$$$$ + SO4 Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -1052,6 +1504,34 @@ Functional Groups $$$$ +SO4H +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 5 4 0 0 1 0 0 0 0 0999 V2000 + -2.7500 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 0.8500 0.0000 S 0 0 0 0 0 6 0 0 0 0 0 0 + -1.2500 2.3500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2500 -0.6500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2500 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 2 5 1 0 0 0 0 + 2 1 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 SO4H +M SAL 1 5 1 2 3 4 5 +M END + +> +Functional Groups + +> +0 + +$$$$ + ster Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -1108,6 +1588,92 @@ Functional Groups $$$$ +TBDMS +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 7 6 0 0 1 0 0 0 0 0999 V2000 + 0.0000 0.0000 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 2 6 1 0 0 0 0 + 2 7 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 TBDMS +M SAL 1 7 1 2 3 4 5 6 7 +M END + +> +Functional Groups + +> +0 + +$$$$ + +TBDPS +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 17 18 0 0 1 0 0 0 0 0999 V2000 + 0.0000 0.0000 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2990 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2990 3.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2990 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2990 3.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 4.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2990 -2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2990 -3.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2990 -2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2990 -3.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -4.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 1 6 1 0 0 0 0 + 7 6 1 0 0 0 0 + 7 8 2 0 0 0 0 + 6 9 2 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 2 0 0 0 0 + 11 8 1 0 0 0 0 + 1 12 1 0 0 0 0 + 13 12 1 0 0 0 0 + 13 14 2 0 0 0 0 + 12 15 2 0 0 0 0 + 15 16 1 0 0 0 0 + 16 17 2 0 0 0 0 + 17 14 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 TBDPS +M SAL 1 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +M END + +> +Functional Groups + +> +0 + +$$$$ + tBu Ketcher 11161713142D 1 1.00000 0.00000 0 @@ -1167,6 +1733,71 @@ Functional Groups $$$$ +TMS +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 4 3 0 0 1 0 0 0 0 0999 V2000 + 1.5000 0.0000 0.0000 Si 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SMT 1 TMS +M SAL 1 4 1 2 3 4 +M END + +> +Functional Groups + +> +0 + +$$$$ + +Tos +Ketcher 11161713142D 1 1.00000 0.00000 0 + + 10 10 0 0 1 0 0 0 0 0999 V2000 + 0.0000 0.0000 0.0000 S 0 0 0 0 0 6 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 2 0 0 0 0 + 2 5 2 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 2 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 2 1 0 0 0 0 + 7 10 1 0 0 0 0 +G 1 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 10 1 2 3 4 5 6 7 8 9 10 +M SMT 1 Tos +M END + +> +Functional Groups + +> +0 + +$$$$ + Ts Ketcher 11161713142D 1 1.00000 0.00000 0 From 1296bd7fffcb9bf80229379baecb5f599eabdf75 Mon Sep 17 00:00:00 2001 From: porcelain11 <112183450+porcelain11@users.noreply.github.com> Date: Tue, 29 Nov 2022 23:49:06 +0500 Subject: [PATCH 02/27] #1852 Implements automatic selection of mol encoding (#1870) * #1852 Implements automatic selection of mol encoding * #1852 Refactor types * #1852 Fix errors in identifyStructFormat * #1852 Fix build * #1852 Fix react build errors * #1852 Run prettier to fix build * #1852 Small fix on comments * #1852 Fix build (prettier-write) --- .../formatters/formatProperties.ts | 8 ++++ .../formatters/formatterFactory.ts | 24 +++++------ .../formatters/identifyStructFormat.ts | 18 ++++----- .../application/formatters/serverFormatter.ts | 8 ++-- .../formatters/structFormatter.types.ts | 28 +++++++------ .../ketcher-core/src/application/ketcher.ts | 40 +++++++++++++------ .../src/script/ui/action/copyAs.js | 2 +- .../modal/components/process/Miew/Miew.tsx | 9 ++++- 8 files changed, 85 insertions(+), 52 deletions(-) diff --git a/packages/ketcher-core/src/application/formatters/formatProperties.ts b/packages/ketcher-core/src/application/formatters/formatProperties.ts index 9e2fd133e1..7653f650c8 100644 --- a/packages/ketcher-core/src/application/formatters/formatProperties.ts +++ b/packages/ketcher-core/src/application/formatters/formatProperties.ts @@ -23,6 +23,14 @@ type FormatPropertiesMap = { } const formatProperties: FormatPropertiesMap = { + molAuto: new SupportedFormatProperties( + // TODO: is it a valid name? + 'MDL Molfile Auto Format detect', + ChemicalMimeType.Mol, + ['.mol'], + true, + { 'molfile-saving-mode': 'auto' } + ), mol: new SupportedFormatProperties( 'MDL Molfile V2000', ChemicalMimeType.Mol, diff --git a/packages/ketcher-core/src/application/formatters/formatterFactory.ts b/packages/ketcher-core/src/application/formatters/formatterFactory.ts index f60373d461..9489fa2b09 100644 --- a/packages/ketcher-core/src/application/formatters/formatterFactory.ts +++ b/packages/ketcher-core/src/application/formatters/formatterFactory.ts @@ -68,29 +68,29 @@ export class FormatterFactory { let formatter: StructFormatter switch (format) { - case 'ket': + case SupportedFormat.ket: formatter = new KetFormatter(new KetSerializer()) break - case 'rxn': + case SupportedFormat.rxn: formatter = new RxnFormatter(new MolSerializer(molSerializerOptions)) break - case 'mol': + case SupportedFormat.mol: formatter = new MolfileV2000Formatter( new MolSerializer(molSerializerOptions) ) break - case 'cml': - case 'inChIAuxInfo': - case 'inChI': - case 'molV3000': - case 'smiles': - case 'rxnV3000': - case 'smilesExt': - case 'smarts': - case 'cdxml': + case SupportedFormat.cml: + case SupportedFormat.inChIAuxInfo: + case SupportedFormat.inChI: + case SupportedFormat.molV3000: + case SupportedFormat.smiles: + case SupportedFormat.rxnV3000: + case SupportedFormat.smilesExt: + case SupportedFormat.smarts: + case SupportedFormat.cdxml: default: formatter = new ServerFormatter( this.#structService, diff --git a/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts b/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts index 7bb8c51d15..57dfa1f868 100644 --- a/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts +++ b/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts @@ -24,16 +24,16 @@ export function identifyStructFormat( try { if (JSON.parse(sanitizedString)) { - return 'ket' + return SupportedFormat.ket } } catch (er) {} // eslint-disable-line if (sanitizedString.indexOf('$RXN') !== -1) { - return 'rxn' + return SupportedFormat.rxn } if (sanitizedString.indexOf('V3000') !== -1) { - return 'molV3000' + return SupportedFormat.molV3000 } const match = sanitizedString.match(/^(M {2}END|\$END MOL)$/m) @@ -44,28 +44,28 @@ export function identifyStructFormat( end === sanitizedString.length || sanitizedString.slice(end, end + 20).search(/^\$(MOL|END CTAB)$/m) !== -1 ) { - return 'mol' + return SupportedFormat.mol } } if ( sanitizedString[0] === '<' && sanitizedString.indexOf(' Promise } -export type SupportedFormat = - | 'rxn' - | 'rxnV3000' - | 'mol' - | 'molV3000' - | 'smiles' - | 'smilesExt' - | 'smarts' - | 'inChI' - | 'inChIAuxInfo' - | 'cml' - | 'ket' - | 'cdxml' +export enum SupportedFormat { + mol = 'mol', + molV3000 = 'molV3000', + molAuto = 'molAuto', + rxn = 'rxn', + rxnV3000 = 'rxnV3000', + smiles = 'smiles', + smilesExt = 'smilesExt', + smarts = 'smarts', + inChI = 'inChI', + inChIAuxInfo = 'inChIAuxInfo', + cml = 'cml', + ket = 'ket', + cdxml = 'cdxml' +} export type FormatterFactoryOptions = Partial< MolSerializerOptions & StructServiceOptions diff --git a/packages/ketcher-core/src/application/ketcher.ts b/packages/ketcher-core/src/application/ketcher.ts index aee7b21c8a..18f164ec62 100644 --- a/packages/ketcher-core/src/application/ketcher.ts +++ b/packages/ketcher-core/src/application/ketcher.ts @@ -63,7 +63,7 @@ function parseStruct( } function getStructure( - structureFormat: SupportedFormat = 'rxn', + structureFormat = SupportedFormat.rxn, formatterFactory: FormatterFactory, struct: Struct ): Promise { @@ -133,19 +133,23 @@ export class Ketcher { } getSmiles(isExtended = false): Promise { - const format: SupportedFormat = isExtended ? 'smilesExt' : 'smiles' + const format = isExtended + ? SupportedFormat.smilesExt + : SupportedFormat.smiles return getStructure(format, this.#formatterFactory, this.editor.struct()) } - async getMolfile(molfileFormat: MolfileFormat = 'v2000'): Promise { + async getMolfile(molfileFormat?: MolfileFormat): Promise { if (this.containsReaction()) { throw Error( 'The structure cannot be saved as *.MOL due to reaction arrrows.' ) } - const format: SupportedFormat = - molfileFormat === 'v3000' ? 'molV3000' : 'mol' + const formatPassed = + molfileFormat === 'v3000' ? SupportedFormat.molV3000 : SupportedFormat.mol + const format = molfileFormat ? formatPassed : SupportedFormat.molAuto + const molfile = await getStructure( format, this.#formatterFactory, @@ -161,8 +165,8 @@ export class Ketcher { 'The structure cannot be saved as *.RXN: there is no reaction arrows.' ) } - const format: SupportedFormat = - molfileFormat === 'v3000' ? 'rxnV3000' : 'rxn' + const format = + molfileFormat === 'v3000' ? SupportedFormat.rxnV3000 : SupportedFormat.rxn const rxnfile = await getStructure( format, this.#formatterFactory, @@ -173,20 +177,32 @@ export class Ketcher { } getKet(): Promise { - return getStructure('ket', this.#formatterFactory, this.#editor.struct()) + return getStructure( + SupportedFormat.ket, + this.#formatterFactory, + this.#editor.struct() + ) } getSmarts(): Promise { - return getStructure('smarts', this.#formatterFactory, this.#editor.struct()) + return getStructure( + SupportedFormat.smarts, + this.#formatterFactory, + this.#editor.struct() + ) } getCml(): Promise { - return getStructure('cml', this.#formatterFactory, this.#editor.struct()) + return getStructure( + SupportedFormat.cml, + this.#formatterFactory, + this.#editor.struct() + ) } getInchi(withAuxInfo = false): Promise { return getStructure( - withAuxInfo ? 'inChIAuxInfo' : 'inChI', + withAuxInfo ? SupportedFormat.inChIAuxInfo : SupportedFormat.inChI, this.#formatterFactory, this.#editor.struct() ) @@ -194,7 +210,7 @@ export class Ketcher { async generateInchIKey(): Promise { const struct: string = await getStructure( - 'ket', + SupportedFormat.ket, this.#formatterFactory, this.#editor.struct() ) diff --git a/packages/ketcher-react/src/script/ui/action/copyAs.js b/packages/ketcher-react/src/script/ui/action/copyAs.js index e414ab10eb..a3cd247630 100644 --- a/packages/ketcher-react/src/script/ui/action/copyAs.js +++ b/packages/ketcher-react/src/script/ui/action/copyAs.js @@ -14,7 +14,7 @@ * limitations under the License. ***************************************************************************/ -import { KetSerializer, MolSerializer } from 'ketcher-core' +import { KetSerializer, MolSerializer, SupportedFormat } from 'ketcher-core' export default function copyAs(type) { const state = global.currentState diff --git a/packages/ketcher-react/src/script/ui/views/modal/components/process/Miew/Miew.tsx b/packages/ketcher-react/src/script/ui/views/modal/components/process/Miew/Miew.tsx index c9bda6084d..37d69d04f4 100644 --- a/packages/ketcher-react/src/script/ui/views/modal/components/process/Miew/Miew.tsx +++ b/packages/ketcher-react/src/script/ui/views/modal/components/process/Miew/Miew.tsx @@ -15,7 +15,12 @@ ***************************************************************************/ import { Dialog } from '../../../../components' -import { FormatterFactory, Struct, StructService } from 'ketcher-core' +import { + FormatterFactory, + Struct, + StructService, + SupportedFormat +} from 'ketcher-core' import { MIEW_OPTIONS } from '../../../../../data/schema/options-schema' import classes from './Miew.module.less' import { connect } from 'react-redux' @@ -117,7 +122,7 @@ const MiewDialog = ({ (miew: MiewAsType) => { miewRef.current = miew const factory = new FormatterFactory(server) - const service = factory.create('cml') + const service = factory.create(SupportedFormat.cml) service .getStructureFromStructAsync(struct) From bb22853570b91dbbd38c349b62d67f4d2936a3c3 Mon Sep 17 00:00:00 2001 From: Svetlana Terenteva Date: Wed, 30 Nov 2022 15:54:17 +0500 Subject: [PATCH 03/27] #1878 Remove husky --- .husky/pre-commit | 4 ---- .husky/pre-push | 4 ---- package.json | 3 +-- yarn.lock | 21 ++++++++++----------- 4 files changed, 11 insertions(+), 21 deletions(-) delete mode 100644 .husky/pre-commit delete mode 100644 .husky/pre-push diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100644 index 0982f91a45..0000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -yarn precommit diff --git a/.husky/pre-push b/.husky/pre-push deleted file mode 100644 index 84489edd6a..0000000000 --- a/.husky/pre-push +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -yarn prepush diff --git a/package.json b/package.json index 0289f01520..afa8a2bdac 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,9 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.2.0", "eslint-plugin-workspaces": "^0.7.0", - "husky": "^7.0.4", "lint-staged": "^12.1.2", "npm-run-all": "^4.1.5", - "prettier": "^2.5.1", + "prettier": "2.8.0", "prettier-config-standard": "^4.0.0", "stylelint": "13.13.1", "stylelint-config-prettier": "^9.0.3", diff --git a/yarn.lock b/yarn.lock index 614f42eb63..4ad0e3a2d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9108,15 +9108,6 @@ __metadata: languageName: node linkType: hard -"husky@npm:^7.0.4": - version: 7.0.4 - resolution: "husky@npm:7.0.4" - bin: - husky: lib/bin.js - checksum: c6ec4af63da2c9522da8674a20ad9b48362cc92704896cc8a58c6a2a39d797feb2b806f93fbd83a6d653fbdceb2c3b6e0b602c6b2e8565206ffc2882ef7db9e9 - languageName: node - linkType: hard - "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -14469,6 +14460,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:2.8.0": + version: 2.8.0 + resolution: "prettier@npm:2.8.0" + bin: + prettier: bin-prettier.js + checksum: 72004ce0cc9bb097daf3e3833f62495768724392c1d5b178dd47372337616e9e50ecbb0804f236596223f7b5eb1bbe69cefc8957dca21112c5777e77ef73a564 + languageName: node + linkType: hard + "prettier@npm:^2.5.1": version: 2.6.0 resolution: "prettier@npm:2.6.0" @@ -15792,10 +15792,9 @@ __metadata: eslint-plugin-node: ^11.1.0 eslint-plugin-promise: ^5.2.0 eslint-plugin-workspaces: ^0.7.0 - husky: ^7.0.4 lint-staged: ^12.1.2 npm-run-all: ^4.1.5 - prettier: ^2.5.1 + prettier: 2.8.0 prettier-config-standard: ^4.0.0 stylelint: 13.13.1 stylelint-config-prettier: ^9.0.3 From fb39619e23820f30243175dbe9877b7b34523980 Mon Sep 17 00:00:00 2001 From: Svetlana Terenteva Date: Wed, 30 Nov 2022 18:46:24 +0500 Subject: [PATCH 04/27] #1878 Re-install husky, test commit --- .husky/pre-commit | 4 +++ package.json | 9 ++++-- .../ui/state/{hotkeys.js => hotkeys.ts} | 13 ++++---- yarn.lock | 30 +++++++++++++++++++ 4 files changed, 47 insertions(+), 9 deletions(-) create mode 100755 .husky/pre-commit rename packages/ketcher-react/src/script/ui/state/{hotkeys.js => hotkeys.ts} (96%) diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000000..303dd1fce8 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn run precommit diff --git a/package.json b/package.json index afa8a2bdac..ee5b152d4d 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ ], "scripts": { "postinstall": "husky install", - "precommit": "lint-staged --allow-empty", - "prepush": "yarn workspaces foreach -pv run test:eslint", + "precommit": "lint-staged --allow-empty && yarn workspaces foreach -pv run prettier:write", "build": "yarn workspaces foreach -ptvR --from ketcher-react-app run build", "build:demo": "yarn workspaces foreach -ptvR --from demo run build", "test": "yarn workspaces foreach -v run test", @@ -27,6 +26,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.2.0", "eslint-plugin-workspaces": "^0.7.0", + "husky": "^8.0.2", "lint-staged": "^12.1.2", "npm-run-all": "^4.1.5", "prettier": "2.8.0", @@ -38,5 +38,8 @@ "resolutions": { "react-error-overlay": "6.0.9" }, - "packageManager": "yarn@3.1.0" + "packageManager": "yarn@3.1.0", + "dependencies": { + "react-device-detect": "^2.2.2" + } } diff --git a/packages/ketcher-react/src/script/ui/state/hotkeys.js b/packages/ketcher-react/src/script/ui/state/hotkeys.ts similarity index 96% rename from packages/ketcher-react/src/script/ui/state/hotkeys.js rename to packages/ketcher-react/src/script/ui/state/hotkeys.ts index b7d0fd64eb..6656c2b5a9 100644 --- a/packages/ketcher-react/src/script/ui/state/hotkeys.js +++ b/packages/ketcher-react/src/script/ui/state/hotkeys.ts @@ -28,6 +28,7 @@ import { load, onAction } from './shared' import actions from '../action' import keyNorm from '../data/convert/keynorm' import { openDialog } from './modal' +import { isIE } from 'react-device-detect' export function initKeydownListener(element) { return function (dispatch, getState) { @@ -49,7 +50,7 @@ function keyHandle(dispatch, state, hotKeys, event) { const key = keyNorm(event) const atomsSelected = editor.selection() && editor.selection().atoms - let group = null + let group if (key && key.length === 1 && atomsSelected && key.match(/\w/)) { openDialog(dispatch, 'labelEdit', { letter: key }) @@ -71,7 +72,7 @@ function keyHandle(dispatch, state, hotKeys, event) { const newAction = actions[actName].action dispatch(onAction(newAction)) event.preventDefault() - } else if (window.clipboardData) { + } else if (isIE) { // IE support clipArea.exec(event) } @@ -116,7 +117,7 @@ function checkGroupOnTool(group, actionTool) { const rxnTextPlain = /\$RXN\n+\s+0\s+0\s+0\n*/ /* ClipArea */ -export function initClipboard(dispatch, getState) { +export function initClipboard(dispatch, _getState) { const formats = Object.keys(formatProperties).map( (format) => formatProperties[format].mime ) @@ -169,7 +170,7 @@ function clipData(editor) { const simpleObjectOrText = Boolean( struct.simpleObjects.size || struct.texts.size ) - if (simpleObjectOrText && window.clipboardData) { + if (simpleObjectOrText && isIE) { errorHandler( 'The structure you are trying to copy contains Simple object or/and Text object.' + 'To copy Simple object or Text object in Internet Explorer try "Copy as KET" button' @@ -189,8 +190,8 @@ function clipData(editor) { // res['chemical/x-daylight-smiles'] = smiles.stringify(struct); return res - } catch (ex) { - errorHandler(ex.message) + } catch (e: any) { + errorHandler(e.message) } return null diff --git a/yarn.lock b/yarn.lock index 4ad0e3a2d8..70b3a340f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9108,6 +9108,15 @@ __metadata: languageName: node linkType: hard +"husky@npm:^8.0.2": + version: 8.0.2 + resolution: "husky@npm:8.0.2" + bin: + husky: lib/bin.js + checksum: e101656fcb56163d610488f186448c78b132626aa427094489d886ce9374955a90274912b0f3a34af3326eaa74977883b032e5f701d7aaf4554daa5a7931be43 + languageName: node + linkType: hard + "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -14868,6 +14877,18 @@ __metadata: languageName: node linkType: hard +"react-device-detect@npm:^2.2.2": + version: 2.2.2 + resolution: "react-device-detect@npm:2.2.2" + dependencies: + ua-parser-js: ^1.0.2 + peerDependencies: + react: ">= 0.14.0" + react-dom: ">= 0.14.0" + checksum: d9245cf5a1c1e565e88523ed6be580497d1f6a972fb100a81092943bb7e44afdcdbae0d67bebe7424c4ba5b27a5d13df7894d122307f070fc26062704f7ec788 + languageName: node + linkType: hard + "react-dom@npm:^17.0.2": version: 17.0.2 resolution: "react-dom@npm:17.0.2" @@ -15792,10 +15813,12 @@ __metadata: eslint-plugin-node: ^11.1.0 eslint-plugin-promise: ^5.2.0 eslint-plugin-workspaces: ^0.7.0 + husky: ^8.0.2 lint-staged: ^12.1.2 npm-run-all: ^4.1.5 prettier: 2.8.0 prettier-config-standard: ^4.0.0 + react-device-detect: ^2.2.2 stylelint: 13.13.1 stylelint-config-prettier: ^9.0.3 stylelint-config-standard: 22.0.0 @@ -17747,6 +17770,13 @@ __metadata: languageName: node linkType: hard +"ua-parser-js@npm:^1.0.2": + version: 1.0.32 + resolution: "ua-parser-js@npm:1.0.32" + checksum: 79a80efd9c21511fdafc042ab748e0e93c8cdb0e8925bf6d48ad7dbb08e808c60fcecd49e679670def44ef428c005aa1810810f6773e7d8135a7817338080813 + languageName: node + linkType: hard + "uglify-js@npm:^3.1.4": version: 3.16.1 resolution: "uglify-js@npm:3.16.1" From 9a5e8d33046688a9fa6abd44eda1c9d037142731 Mon Sep 17 00:00:00 2001 From: Svetlana Terenteva Date: Wed, 30 Nov 2022 18:54:48 +0500 Subject: [PATCH 05/27] #1878 add pre-push hook --- .husky/pre-push | 4 ++++ package.json | 1 + 2 files changed, 5 insertions(+) create mode 100755 .husky/pre-push diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 0000000000..57db2274ed --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn run prepush diff --git a/package.json b/package.json index ee5b152d4d..5f6e4e02dd 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "scripts": { "postinstall": "husky install", "precommit": "lint-staged --allow-empty && yarn workspaces foreach -pv run prettier:write", + "prepush": "yarn workspaces foreach -pv run test:eslint", "build": "yarn workspaces foreach -ptvR --from ketcher-react-app run build", "build:demo": "yarn workspaces foreach -ptvR --from demo run build", "test": "yarn workspaces foreach -v run test", From 5a695e289cb698ba4c741e17dc84ddae8268ea37 Mon Sep 17 00:00:00 2001 From: Svetlana Terenteva Date: Thu, 1 Dec 2022 13:10:25 +0500 Subject: [PATCH 06/27] #1878 Fixes on comments --- package.json | 1 - packages/ketcher-react/package.json | 1 + packages/ketcher-react/src/script/ui/state/hotkeys.ts | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 5f6e4e02dd..3b9e8db2d0 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "resolutions": { "react-error-overlay": "6.0.9" }, - "packageManager": "yarn@3.1.0", "dependencies": { "react-device-detect": "^2.2.2" } diff --git a/packages/ketcher-react/package.json b/packages/ketcher-react/package.json index c9bcf70c7c..05b6c7adc5 100644 --- a/packages/ketcher-react/package.json +++ b/packages/ketcher-react/package.json @@ -130,6 +130,7 @@ "ts-jest": "^27.1.2", "typescript": "^4.5.2" }, + "packageManager": "yarn@3.1.0", "files": [ "dist" ] diff --git a/packages/ketcher-react/src/script/ui/state/hotkeys.ts b/packages/ketcher-react/src/script/ui/state/hotkeys.ts index 6656c2b5a9..9776897246 100644 --- a/packages/ketcher-react/src/script/ui/state/hotkeys.ts +++ b/packages/ketcher-react/src/script/ui/state/hotkeys.ts @@ -73,7 +73,6 @@ function keyHandle(dispatch, state, hotKeys, event) { dispatch(onAction(newAction)) event.preventDefault() } else if (isIE) { - // IE support clipArea.exec(event) } } From 514004b2640a232d966ea439132cf1c7c6779b1b Mon Sep 17 00:00:00 2001 From: Svetlana Terenteva Date: Thu, 1 Dec 2022 15:59:22 +0500 Subject: [PATCH 07/27] #1878 Fix deps --- package.json | 4 +--- packages/ketcher-react/package.json | 2 +- yarn.lock | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3b9e8db2d0..ef7576a3eb 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,8 @@ "stylelint-config-prettier": "^9.0.3", "stylelint-config-standard": "22.0.0" }, + "packageManager": "yarn@3.1.0", "resolutions": { "react-error-overlay": "6.0.9" - }, - "dependencies": { - "react-device-detect": "^2.2.2" } } diff --git a/packages/ketcher-react/package.json b/packages/ketcher-react/package.json index 05b6c7adc5..710c3ee134 100644 --- a/packages/ketcher-react/package.json +++ b/packages/ketcher-react/package.json @@ -63,6 +63,7 @@ "miew-react": "^1.0.0", "react-colorful": "^5.4.0", "react-contextmenu": "^2.14.0", + "react-device-detect": "^2.2.2", "react-dropzone": "^11.7.1", "react-intersection-observer": "^8.32.1", "react-redux": "^7.2.1", @@ -130,7 +131,6 @@ "ts-jest": "^27.1.2", "typescript": "^4.5.2" }, - "packageManager": "yarn@3.1.0", "files": [ "dist" ] diff --git a/yarn.lock b/yarn.lock index 70b3a340f1..a9f5f99d5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11395,6 +11395,7 @@ __metadata: prettier: ^2.5.1 react-colorful: ^5.4.0 react-contextmenu: ^2.14.0 + react-device-detect: ^2.2.2 react-dropzone: ^11.7.1 react-intersection-observer: ^8.32.1 react-redux: ^7.2.1 @@ -15818,7 +15819,6 @@ __metadata: npm-run-all: ^4.1.5 prettier: 2.8.0 prettier-config-standard: ^4.0.0 - react-device-detect: ^2.2.2 stylelint: 13.13.1 stylelint-config-prettier: ^9.0.3 stylelint-config-standard: 22.0.0 From d53a09f5b997090593df6602e0f7c571a0249a53 Mon Sep 17 00:00:00 2001 From: KonstantinEpam23 <101649391+KonstantinEpam23@users.noreply.github.com> Date: Thu, 1 Dec 2022 21:52:19 +0100 Subject: [PATCH 08/27] #1826 dont select tools on hover (#1877) * #1826: do not select a hotkey tool if we are hovering over an atom * #1826: do not select a hotkey tool if we are hovering over an atom / eslint * #1826: do not select a hotkey tool if we are hovering over an atom / let -> const * #1826: do not select a hotkey tool if we are hovering over an atom / fix types for hotkeys.js * #1826: do not select a hotkey tool if we are hovering over an atom / fix import error Co-authored-by: Konstantin Levin --- .../src/script/ui/state/hotkeys.ts | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/state/hotkeys.ts b/packages/ketcher-react/src/script/ui/state/hotkeys.ts index 9776897246..455b8ad551 100644 --- a/packages/ketcher-react/src/script/ui/state/hotkeys.ts +++ b/packages/ketcher-react/src/script/ui/state/hotkeys.ts @@ -20,7 +20,9 @@ import { KetSerializer, MolSerializer, formatProperties, - ChemicalMimeType + ChemicalMimeType, + fromAtomsAttrs, + ReAtom } from 'ketcher-core' import { debounce, isEqual } from 'lodash/fp' import { load, onAction } from './shared' @@ -43,14 +45,15 @@ export function initKeydownListener(element) { function keyHandle(dispatch, state, hotKeys, event) { if (state.modal) return - const editor = state.editor + const { editor } = state + const { render } = editor const actionState = state.actionState const actionTool = actionState.activeTool const key = keyNorm(event) const atomsSelected = editor.selection() && editor.selection().atoms - let group + let group: any = null if (key && key.length === 1 && atomsSelected && key.match(/\w/)) { openDialog(dispatch, 'labelEdit', { letter: key }) @@ -61,7 +64,8 @@ function keyHandle(dispatch, state, hotKeys, event) { event.preventDefault() } else if ((group = keyNorm.lookup(hotKeys, event)) !== undefined) { let index = checkGroupOnTool(group, actionTool) // index currentTool in group || -1 - index = (index + 1) % group.length + const groupLength = group !== null ? group.length : 1 + index = (index + 1) % groupLength const actName = group[index] if (actionState[actName] && actionState[actName].disabled === true) { @@ -70,7 +74,24 @@ function keyHandle(dispatch, state, hotKeys, event) { } if (clipArea.actions.indexOf(actName) === -1) { const newAction = actions[actName].action - dispatch(onAction(newAction)) + const hoverItemId = getHoveredAtomId(render.ctab.atoms) + const isHoveringOverAtom = hoverItemId !== null + if (isHoveringOverAtom) { + // check if atom is currently hovered over + // in this case we do not want to activate the corresponding tool + // and just insert the atom directly + const atomProps = { ...newAction.opts } + const updatedAtoms = fromAtomsAttrs( + render.ctab, + hoverItemId, + atomProps, + true + ) + editor.update(updatedAtoms) + } else { + dispatch(onAction(newAction)) + } + event.preventDefault() } else if (isIE) { clipArea.exec(event) @@ -78,6 +99,13 @@ function keyHandle(dispatch, state, hotKeys, event) { } } +function getHoveredAtomId(atoms: Map): number | null { + for (const [id, atom] of atoms.entries()) { + if (atom.hover) return id + } + return null +} + function setHotKey(key, actName, hotKeys) { if (Array.isArray(hotKeys[key])) hotKeys[key].push(actName) else hotKeys[key] = [actName] @@ -116,7 +144,7 @@ function checkGroupOnTool(group, actionTool) { const rxnTextPlain = /\$RXN\n+\s+0\s+0\s+0\n*/ /* ClipArea */ -export function initClipboard(dispatch, _getState) { +export function initClipboard(dispatch) { const formats = Object.keys(formatProperties).map( (format) => formatProperties[format].mime ) From 7d7a9d9857e0f9e1a587abb4ddd62808d2044825 Mon Sep 17 00:00:00 2001 From: Nikolai Iakushchenko Date: Tue, 6 Dec 2022 18:33:18 +0300 Subject: [PATCH 09/27] #1823 Add a template to the clipboard when selected --- .../ui/dialog/template/TemplateDialog.tsx | 32 +++++-------------- .../ui/dialog/template/TemplateTable.tsx | 3 -- 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx index f9c32d1a2f..a4c25beb48 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx @@ -176,28 +176,15 @@ const TemplateDialog: FC = (props) => { ) } - const result = (): Result | null => { - const tmpl = props.selected - return tmpl - ? { - struct: tmpl.struct, - aid: parseInt(String(tmpl.props.atomid)) || null, - bid: parseInt(String(tmpl.props.bondid)) || null, - mode: mode - } - : null - } - const sdfSerializer = new SdfSerializer() const data = tab === TemplateTabs.TemplateLibrary ? sdfSerializer.serialize(templateLib) : sdfSerializer.serialize(functionalGroups) - const select = (tmpl: Template, activateImmediately = false): void => { + const select = (tmpl: Template): void => { onChangeGroup(tmpl.props.group) - if (activateImmediately) props.onOk(result()) - else props.onSelect(tmpl) + props.onSelect(tmpl) } return ( @@ -206,7 +193,6 @@ const TemplateDialog: FC = (props) => { footerContent={} className={`${classes.dialog_body}`} params={omit(['group'], rest)} - result={() => result()} buttons={['OK']} buttonsNameMap={{ OK: 'Add to canvas' }} needMargin={false} @@ -268,7 +254,6 @@ const TemplateDialog: FC = (props) => { : [] } onSelect={(templ) => select(templ)} - onDoubleClick={(templ) => select(templ, true)} selected={props.selected} onDelete={props.onDelete} onAttach={props.onAttach} @@ -289,7 +274,6 @@ const TemplateDialog: FC = (props) => {
select(templ, true)} templates={filteredFG} onSelect={(templ) => select(templ)} selected={props.selected} @@ -318,13 +302,13 @@ export default connect( }), (dispatch: Dispatch, props) => ({ onFilter: (filter) => dispatch(changeFilter(filter)), - onSelect: (tmpl) => dispatch(selectTmpl(tmpl)), + onSelect: (tmpl) => { + dispatch(selectTmpl(tmpl)) + dispatch(onAction({ tool: 'template', opts: tmpl })) + ;(props as any).onOk(tmpl) + }, onChangeGroup: (group) => dispatch(changeGroup(group)), onAttach: (tmpl) => dispatch(editTmpl(tmpl)), - onDelete: (tmpl) => dispatch(deleteTmpl(tmpl)), - onOk: (res) => { - dispatch(onAction({ tool: 'template', opts: res })) - ;(props as any).onOk(res) - } + onDelete: (tmpl) => dispatch(deleteTmpl(tmpl)) }) )(TemplateDialog) diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx index 66404b4aff..fe952a0232 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx @@ -40,7 +40,6 @@ interface TemplateTableProps { onDelete?: (tmpl: Template) => void onAttach?: (tmpl: Template) => void titleRows?: 1 | 2 - onDoubleClick: (tmpl: Template) => void } const getSettingsSelector = (state) => state.options.settings @@ -70,7 +69,6 @@ const TemplateTable: FC = (props) => { onSelect, onDelete, onAttach, - onDoubleClick, titleRows = 2 } = props const options = useSelector((state) => getSettingsSelector(state)) @@ -96,7 +94,6 @@ const TemplateTable: FC = (props) => { : `${tmpl.struct.name}_${i}_selected` } onClick={() => onSelect(tmpl)} - onDoubleClick={() => onDoubleClick(tmpl)} > Date: Thu, 8 Dec 2022 11:01:01 +0300 Subject: [PATCH 10/27] remove Result interface --- .../src/script/ui/dialog/template/TemplateDialog.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx index a4c25beb48..7c57618bd4 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx @@ -94,13 +94,6 @@ enum TemplateTabs { FunctionalGroupLibrary = 1 } -export interface Result { - struct: Struct - aid: number | null - bid: number | null - mode: string -} - const filterLibSelector = createSelector( (props: Props) => props.lib, (props: Props) => props.filter, From 33de419369cf7716a3b04f3155a58292cedce379 Mon Sep 17 00:00:00 2001 From: Nikolai Iakushchenko Date: Thu, 8 Dec 2022 11:20:36 +0300 Subject: [PATCH 11/27] add type for props --- .../src/script/ui/dialog/template/TemplateDialog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx index 7c57618bd4..1404cd6c37 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx @@ -293,12 +293,12 @@ export default connect( return { ...template, modifiedStruct: struct } }) }), - (dispatch: Dispatch, props) => ({ + (dispatch: Dispatch, props: Props) => ({ onFilter: (filter) => dispatch(changeFilter(filter)), onSelect: (tmpl) => { dispatch(selectTmpl(tmpl)) dispatch(onAction({ tool: 'template', opts: tmpl })) - ;(props as any).onOk(tmpl) + props.onOk(tmpl) }, onChangeGroup: (group) => dispatch(changeGroup(group)), onAttach: (tmpl) => dispatch(editTmpl(tmpl)), From 1f483991fe1d5b094ba93773a8bc7e8b745f3158 Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 8 Dec 2022 16:24:29 +0300 Subject: [PATCH 12/27] #1820 add salts and solvents tab (#1891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #1820 – adding salts and solvents tab * #1820 added possibility to add Salts And Solvents to canvas * #1820 – added salts and solvents merge prevention. Removed buttons from footer * #1820 – changed display of title and name for salts and solvents * #1820 – removed modifiedStruct from templates * #1820 – UI improvements * #1820 – fixed dragging structure on salt or solvent --- .../public/templates/salts-and-solvents.sdf | 4020 +++++++++++++++++ .../src/application/editor/actions/atom.ts | 4 +- .../src/domain/entities/sgroup.ts | 31 + .../helpers/functionalGroupsProvider.ts | 4 + .../ketcher-core/src/domain/helpers/index.ts | 1 + .../helpers/saltsAndSolventsProvider.ts | 40 + .../src/script/editor/tool/select.ts | 80 +- .../src/script/editor/tool/template.ts | 36 +- .../ketcher-react/src/script/ui/App/App.tsx | 2 + .../src/script/ui/component/structrender.tsx | 41 +- .../ui/dialog/template/TemplateDialog.tsx | 106 +- .../dialog/template/TemplateTable.module.less | 2 + .../ui/dialog/template/TemplateTable.tsx | 38 +- .../src/script/ui/state/index.js | 2 + .../src/script/ui/state/options/index.js | 3 +- .../script/ui/state/saltsAndSolvents/index.ts | 76 + .../state/saltsAndSolvents/selectors/index.ts | 19 + .../src/script/ui/utils/index.ts | 10 +- 18 files changed, 4443 insertions(+), 72 deletions(-) create mode 100644 example/public/templates/salts-and-solvents.sdf create mode 100644 packages/ketcher-core/src/domain/helpers/saltsAndSolventsProvider.ts create mode 100644 packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts create mode 100644 packages/ketcher-react/src/script/ui/state/saltsAndSolvents/selectors/index.ts diff --git a/example/public/templates/salts-and-solvents.sdf b/example/public/templates/salts-and-solvents.sdf new file mode 100644 index 0000000000..b083dbe474 --- /dev/null +++ b/example/public/templates/salts-and-solvents.sdf @@ -0,0 +1,4020 @@ +acetic acid + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.5143 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7848 -0.2357 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8133 -0.2357 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5143 2.0143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 acetic acid +M END +> +acetic acid + +> +acetic acid + +> +Salts and Solvents + +$$$$ +acetic anhydride + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 0.5143 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7848 -0.2357 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8133 -0.2357 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5143 2.0143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1123 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1124 2.0143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4114 -0.2357 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 5 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 acetic anhydride +M END +> +acetic anhydride + +> +acetic anhydride + +> +Salts and Solvents + +$$$$ +formic acid + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.5143 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7848 -0.2357 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8133 -0.2357 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5143 2.0143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 formic acid +M END +> +formic acid + +> +formic acid + +> +Salts and Solvents + +$$$$ +methane sulphonic acid + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.5143 0.5143 0.0000 S 0 0 0 0 0 6 0 0 0 0 0 0 + 0.5143 2.0143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5143 -0.9857 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.0143 0.5143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.9857 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 methane sulphonic acid +M END +> +methane sulphonic acid + +> +methane sulphonic acid + +> +Salts and Solvents + +$$$$ +propionic acid + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.5143 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7848 -0.2357 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8133 -0.2357 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5143 2.0143 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0838 0.5143 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 + 2 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 propionic acid +M END +> +propionic acid + +> +propionic acid + +> +Salts and Solvents + +$$$$ +1,2-propanediol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + -3.3587 -3.5057 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0597 -2.7557 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0596 -1.2558 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7606 -3.5057 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5384 -2.7557 0.0000 O 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 + 2 4 1 0 0 0 0 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 1,2-propanediol +M END +> +1,2-propanediol + +> +1,2-propanediol + +> +Salts and Solvents + +$$$$ +1,3-propanediol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 15.0779 -8.5508 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 16.3769 -9.3007 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 17.6759 -8.5507 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 18.9750 -9.3007 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 20.2740 -8.5507 0.0000 O 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 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 1,3-propanediol +M END +> +1,3-propanediol + +> +1,3-propanediol + +> +Salts and Solvents + +$$$$ +1,4-butanediol + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + -0.3480 1.2991 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9509 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 1.2991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5491 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8481 1.2991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1472 2.0491 0.0000 O 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 1,4-butanediol +M END +> +1,4-butanediol + +> +1,4-butanediol + +> +Salts and Solvents + +$$$$ +1-butanol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.1714 0.3286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4705 1.0786 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 1.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 0.3286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7257 1.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 1-butanol +M END +> +1-butanol + +> +1-butanol + +> +Salts and Solvents + +$$$$ +1-propanol + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.1714 1.2286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 1.2286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7257 0.4786 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 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 1-propanol +M END +> +1-propanol + +> +1-propanol + +> +Salts and Solvents + +$$$$ +2-butanol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.1714 1.2286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4705 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 1.2286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1714 2.7286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 2-butanol +M END +> +2-butanol + +> +2-butanol + +> +Salts and Solvents + +$$$$ +2-ethylhexanol + -INDIGO-11302219142D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + 10.7337 0.4167 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.1355 0.4167 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8365 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5375 0.4167 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.1355 1.9167 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.4345 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2384 -0.3333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.4345 2.6667 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9394 0.4167 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 6 1 0 0 0 0 + 2 3 1 0 0 0 0 + 2 5 1 0 0 0 0 + 2 6 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 7 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 2-ethylhexanol +M END +> +2-ethylhexanol + +> +2-ethylhexanol + +> +Salts and Solvents + +$$$$ +isopropanol + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.1714 1.2286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4705 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1714 2.7286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 2-propanol +M END +> +isopropanol + +> +2-propanol + +> +Salts and Solvents + +$$$$ +2-methoxyethanol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.1714 0.3286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4705 1.0786 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 1.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 0.3286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7257 1.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 2-methoxyethanol +M END +> +2-methoxyethanol + +> +2-methoxyethanol + +> +Salts and Solvents + +$$$$ +2-pentanol + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + -5.1971 -3.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8980 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5991 -3.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0009 -3.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3000 -1.2500 0.0000 O 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 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 2-pentanol +M END +> +2-pentanol + +> +2-pentanol + +> +Salts and Solvents + +$$$$ +benzyl alcohol + -INDIGO-11302219142D + + 8 8 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 2.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 + 1 7 1 0 0 0 0 + 7 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 benzyl alcohol +M END +> +benzyl alcohol + +> +benzyl alcohol + +> +Salts and Solvents + +$$$$ +cyclohexanol + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 4.2990 2.0175 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2990 0.5175 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -0.2325 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 -0.2325 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -1.7325 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 -1.7325 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2990 -2.4825 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 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 6 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 cyclohexanol +M END +> +cyclohexanol + +> +cyclohexanol + +> +Salts and Solvents + +$$$$ +ethanol + -INDIGO-11302219142D + + 3 2 0 0 0 0 0 0 0 0999 V2000 + 0.1714 1.2286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 1.2286 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 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 3 1 2 3 +M SMT 1 ethyl alcohol +M END +> +ethanol + +> +ethyl alcohol + +> +Salts and Solvents + +$$$$ +ethylene glycol + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.1714 1.2286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 1.2286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7256 0.4786 0.0000 O 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 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 ethane-1,2-diol +M END +> +ethylene glycol + +> +ethane-1,2-diol + +> +Salts and Solvents + +$$$$ +glycerol + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 0.9915 2.6580 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2906 1.9080 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5896 2.6580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5897 4.1580 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8887 1.9080 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1878 2.6580 0.0000 O 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 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 glycerol +M END +> +glycerol + +> +glycerol + +> +Salts and Solvents + +$$$$ +isoamyl alcohol + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 0.1714 0.3286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4705 1.0786 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 1.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 0.3286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7257 1.0786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 -1.1714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 isoamyl alcohol +M END +> +isoamyl alcohol + +> +isoamyl alcohol + +> +Salts and Solvents + +$$$$ +isobutanol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.1714 1.2286 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1276 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 1.2286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7257 0.4786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.4266 2.7286 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 + 3 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 isobutanol +M END +> +isobutanol + +> +isobutanol + +> +Salts and Solvents + +$$$$ +methanol + -INDIGO-11302219142D + + 2 1 0 0 0 0 0 0 0 0999 V2000 + 0.0709 0.8536 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5710 0.8536 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 2 1 2 +M SMT 1 methyl alcohol +M END +> +methanol + +> +methyl alcohol + +> +Salts and Solvents + +$$$$ +t-butanol + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.0709 0.8536 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5710 0.8536 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.4291 0.8536 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0709 2.3536 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0709 -0.6464 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 t-butanol +M END +> +t-butanol + +> +t-butanol + +> +Salts and Solvents + +$$$$ +water + -INDIGO-11302219142D + + 1 0 0 0 0 0 0 0 0 0999 V2000 + 0.7500 2.9500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 1 1 +M SMT 1 water +M END +> +water + +> +water + +> +Salts and Solvents + +$$$$ +carbon dioxide + -INDIGO-11302219142D + + 3 2 0 0 0 0 0 0 0 0999 V2000 + -1.2000 0.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7000 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3000 0.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 3 1 2 3 +M SMT 1 carbon dioxide +M END +> +carbon dioxide + +> +carbon dioxide + +> +Salts and Solvents + +$$$$ +benzene + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 benzene +M END +> +benzene + +> +benzene + +> +Salts and Solvents + +$$$$ +cumene + -INDIGO-11302219142D + + 9 9 0 0 0 0 0 0 0 0999 V2000 + 4.2989 1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2989 0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 2.6250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 2.6250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 -0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 -1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2989 -2.6250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 2 5 2 0 0 0 0 + 2 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 6 8 2 0 0 0 0 + 7 9 2 0 0 0 0 + 8 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 cumene +M END +> +cumene + +> +cumene + +> +Salts and Solvents + +$$$$ +mesitylene + -INDIGO-11302219142D + + 9 9 0 0 0 0 0 0 0 0999 V2000 + 1.2991 3.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5980 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5980 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8971 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2991 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 4 6 2 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 7 9 2 0 0 0 0 + 2 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 mesitylene +M END +> +mesitylene + +> +mesitylene + +> +Salts and Solvents + +$$$$ +toluene + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 + 1 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 toluene +M END +> +toluene + +> +toluene + +> +Salts and Solvents + +$$$$ +n,n-dimethylaniline + -INDIGO-11302219142D + + 9 9 0 0 0 0 0 0 0 0999 V2000 + 4.2989 1.8750 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2989 0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 -0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 2.6250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 2.6250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 -1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2989 -2.6250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 5 1 0 0 0 0 + 1 6 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 3 7 1 0 0 0 0 + 4 8 2 0 0 0 0 + 7 9 2 0 0 0 0 + 8 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 N,N-dimethylaniline +M END +> +n,n-dimethylaniline + +> +N,N-dimethylaniline + +> +Salts and Solvents + +$$$$ +pyridine + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 pyridine +M END +> +pyridine + +> +pyridine + +> +Salts and Solvents + +$$$$ +triethylamine + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 1.5000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2010 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7990 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7990 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0980 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0980 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 3 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 triethylamine +M END +> +triethylamine + +> +triethylamine + +> +Salts and Solvents + +$$$$ +acetonitrile + -INDIGO-11302219142D + + 3 2 0 0 0 0 0 0 0 0999 V2000 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 3 0 0 0 0 + 1 3 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 3 1 2 3 +M SMT 1 acetonitrile +M END +> +acetonitrile + +> +acetonitrile + +> +Salts and Solvents + +$$$$ +dimethyl acetamide + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 2.7990 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7990 1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0980 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -0.7500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2009 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 dimethyl acetamide +M END +> +dimethyl acetamide + +> +dimethyl acetamide + +> +Salts and Solvents + +$$$$ +dimethyl formamide + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 2.7990 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7990 1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0980 -0.7500 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -0.7500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 -2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2009 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 DMF +M END +> +dimethyl formamide + +> +DMF + +> +Salts and Solvents + +$$$$ +dimethyl sulfoxide + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 1.5000 0.0000 0.0000 S 0 0 0 0 0 4 0 0 0 0 0 0 + 0.2010 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7990 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 1.5000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 DMSO +M END +> +dimethyl sulfoxide + +> +DMSO + +> +Salts and Solvents + +$$$$ +dimethylpropylene urea + -INDIGO-11302219142D + + 9 9 0 0 0 0 0 0 0 0999 V2000 + 3.4378 2.0544 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1388 1.3044 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1387 -0.1955 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8397 -0.9455 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4593 -0.1956 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4593 1.3044 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.7584 2.0545 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8397 2.0544 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8397 3.5545 0.0000 O 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 6 8 1 0 0 0 0 + 2 8 1 0 0 0 0 + 8 9 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 dimethylpropylene urea +M END +> +dimethylpropylene urea + +> +dimethylpropylene urea + +> +Salts and Solvents + +$$$$ +formamide + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.2485 -6.0342 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5476 -5.2841 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5476 -3.7842 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8467 -6.0341 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 formamide +M END +> +formamide + +> +formamide + +> +Salts and Solvents + +$$$$ +n-methyl-2-pyrrolidone + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 0.7500 2.3100 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7500 3.8100 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3860 1.8953 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3 2 1 0 0 0 0 + 2 1 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 3 1 0 0 0 0 + 1 6 1 0 0 0 0 + 4 7 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 N-methyl-2-pyrrolidone +M END +> +n-methyl-2-pyrrolidone + +> +N-methyl-2-pyrrolidone + +> +Salts and Solvents + +$$$$ +n-methylformamide + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.1009 0.5500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4000 1.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4000 2.8000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6990 0.5500 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1981 1.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 N-methylformamide +M END +> +n-methylformamide + +> +N-methylformamide + +> +Salts and Solvents + +$$$$ +propane nitrile + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 6.8971 0.7500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2990 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5981 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 4 3 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 propane nitrile +M END +> +propane nitrile + +> +propane nitrile + +> +Salts and Solvents + +$$$$ +sulfolane + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 0.7500 2.3100 0.0000 S 0 0 0 0 0 6 0 0 0 0 0 0 + -0.4600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 3.6090 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.0673 3.5678 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3 2 1 0 0 0 0 + 2 1 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 3 1 0 0 0 0 + 1 6 2 0 0 0 0 + 1 7 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 sulfolane +M END +> +sulfolane + +> +sulfolane + +> +Salts and Solvents + +$$$$ +amyl acetate + -INDIGO-11302219142D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + 5.8307 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.1297 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5316 -0.3786 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.8307 1.8714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2326 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9335 -0.3785 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.6345 0.3715 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.6646 -0.3785 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.9636 0.3715 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 amyl acetate +M END +> +amyl acetate + +> +amyl acetate + +> +Salts and Solvents + +$$$$ +butyl acetate + -INDIGO-11302219142D + + 8 7 0 0 0 0 0 0 0 0999 V2000 + 7.5466 0.0000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8456 2.2500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9486 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6495 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.2476 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3505 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8456 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.1446 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 5 1 0 0 0 0 + 1 7 1 0 0 0 0 + 2 7 2 0 0 0 0 + 3 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 7 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 butyl acetate +M END +> +butyl acetate + +> +butyl acetate + +> +Salts and Solvents + +$$$$ +dimethyl carbonate + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 0.5429 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5429 1.1571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7562 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8419 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0552 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1409 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 dimethyl carbonate +M END +> +dimethyl carbonate + +> +dimethyl carbonate + +> +Salts and Solvents + +$$$$ +ethyl acetate + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 2.7079 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7079 1.1571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0070 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.4089 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.1099 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.1891 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 ethyl acetate +M END +> +ethyl acetate + +> +ethyl acetate + +> +Salts and Solvents + +$$$$ +ethyl formate + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 5.8087 -2.6404 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.8087 -1.1506 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5094 -3.4018 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2098 -2.6486 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9103 -3.4018 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.1078 -3.3904 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2 1 2 0 0 0 0 + 3 1 1 0 0 0 0 + 4 3 1 0 0 0 0 + 5 4 1 0 0 0 0 + 1 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 ethyl formate +M END +> +ethyl formate + +> +ethyl formate + +> +Salts and Solvents + +$$$$ +ethyl lactate + -INDIGO-11302219142D + + 8 7 0 0 0 0 0 0 0 0999 V2000 + -0.3480 1.2991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9509 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 1.2991 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5491 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5491 3.5491 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8480 1.2991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1471 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8480 -0.2009 0.0000 O 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 + 4 5 2 0 0 0 0 + 4 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 6 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 ethyl lactate +M END +> +ethyl lactate + +> +ethyl lactate + +> +Salts and Solvents + +$$$$ +ethyl propionate + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + -0.3480 1.2991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9509 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2500 1.2991 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5491 2.0491 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5491 3.5491 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8480 1.2991 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1471 2.0491 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 + 4 5 2 0 0 0 0 + 4 6 1 0 0 0 0 + 6 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 ethyl propionate +M END +> +ethyl propionate + +> +ethyl propionate + +> +Salts and Solvents + +$$$$ +ethylene carbonate + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 1.0323 3.5259 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0323 2.0259 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2458 1.1443 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7823 -0.2824 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2824 -0.2824 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.1813 1.1443 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 2 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 ethylene carbonate +M END +> +ethylene carbonate + +> +ethylene carbonate + +> +Salts and Solvents + +$$$$ +isobutyl acetate + -INDIGO-11302219142D + + 8 7 0 0 0 0 0 0 0 0999 V2000 + 4.4399 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4399 1.1571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7390 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1409 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8419 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5429 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5429 -2.5929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7561 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 6 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 isobutyl acetate +M END +> +isobutyl acetate + +> +isobutyl acetate + +> +Salts and Solvents + +$$$$ +isopropyl acetate + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 3.1409 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1409 1.1571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4400 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8419 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5429 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7561 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5429 1.1571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 isopropyl acetate +M END +> +isopropyl acetate + +> +isopropyl acetate + +> +Salts and Solvents + +$$$$ +methyl acetate + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.5429 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5429 1.1571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7562 -1.0929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.8419 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1409 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 methyl acetate +M END +> +methyl acetate + +> +methyl acetate + +> +Salts and Solvents + +$$$$ +methyl formate + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 1.5821 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5821 1.1571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8812 -1.0929 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2831 -1.0929 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.0159 -0.3429 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 methyl formate +M END +> +methyl formate + +> +methyl formate + +> +Salts and Solvents + +$$$$ +methyl lactate + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 7.6971 -2.1071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3980 -2.8571 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0991 -2.1071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0991 -0.6071 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8000 -2.8571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5009 -2.1071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8000 -4.3571 0.0000 O 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 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 methyl lactate +M END +> +methyl lactate + +> +methyl lactate + +> +Salts and Solvents + +$$$$ +n-octylacetate + -INDIGO-11302219142D + + 12 11 0 0 0 0 0 0 0 0999 V2000 + 7.7009 4.9462 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0000 5.6962 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.2991 4.9462 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5980 5.6962 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.8971 4.9462 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.1962 5.6962 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.4953 4.9462 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 16.7942 5.6962 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 18.0933 4.9462 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 19.3924 5.6962 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 20.6913 4.9462 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 19.3924 7.1962 0.0000 O 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 1 0 0 0 0 + 10 12 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 4 9 10 11 12 +M SMT 1 n-octylacetate +M END +> +n-octylacetate + +> +n-octylacetate + +> +Salts and Solvents + +$$$$ +propyl acetate + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 6.3403 -0.1607 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6395 2.0893 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7423 -0.1607 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0413 0.5893 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4433 0.5893 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6395 0.5893 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.9385 -0.1607 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 4 1 0 0 0 0 + 1 6 1 0 0 0 0 + 2 6 2 0 0 0 0 + 3 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 6 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 propyl acetate +M END +> +propyl acetate + +> +propyl acetate + +> +Salts and Solvents + +$$$$ +propylene carbonate + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 0.5661 -1.8745 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.5661 -0.3746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.6474 0.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.1839 1.9338 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3160 1.9338 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1978 3.1472 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7797 0.5071 0.0000 O 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 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 5 7 1 0 0 0 0 + 2 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 propylene carbonate +M END +> +propylene carbonate + +> +propylene carbonate + +> +Salts and Solvents + +$$$$ +t-butyl acetate + -INDIGO-11302219142D + + 8 7 0 0 0 0 0 0 0 0999 V2000 + 6.0125 -7.4927 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.7134 -6.7427 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.7134 -5.2428 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.4144 -7.4928 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1153 -6.7428 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.8163 -5.9928 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3653 -8.0418 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8653 -5.4437 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 5 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 t-butyl acetate +M END +> +t-butyl acetate + +> +t-butyl acetate + +> +Salts and Solvents + +$$$$ +1,2-dimethoxyethane + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + -0.0857 0.1714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2133 -0.5786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5124 0.1714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3848 -0.5786 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8114 -0.5786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6838 0.1714 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 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 1,2-dimethoxyethane +M END +> +1,2-dimethoxyethane + +> +1,2-dimethoxyethane + +> +Salts and Solvents + +$$$$ +1,4-dioxane + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 3.9490 -2.3000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9490 -5.3000 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 1 0 0 0 0 + 2 1 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 1 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 1,4-dioxane +M END +> +1,4-dioxane + +> +1,4-dioxane + +> +Salts and Solvents + +$$$$ +2-methyl tetrahydrofuran + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 0.7500 2.3100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.3860 1.8953 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3 2 1 0 0 0 0 + 2 1 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 3 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 2-methyl tetrahydrofuran +M END +> +2-methyl tetrahydrofuran + +> +2-methyl tetrahydrofuran + +> +Salts and Solvents + +$$$$ +anisole + -INDIGO-11302219142D + + 8 8 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 2.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 + 1 7 1 0 0 0 0 + 7 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 anisole +M END +> +anisole + +> +anisole + +> +Salts and Solvents + +$$$$ +butyl carbitol + -INDIGO-11302219142D + + 11 10 0 0 0 0 0 0 0 0999 V2000 + -0.2227 -3.0342 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0742 -3.7829 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3750 -3.0387 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6719 -3.7875 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9782 -3.0336 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.2751 -3.7823 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.5758 -3.0382 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.8728 -3.7870 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 10.1792 -3.0330 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.4761 -3.7817 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.7768 -3.0376 0.0000 O 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 3 9 10 11 +M SMT 1 butyl carbitol +M END +> +butyl carbitol + +> +butyl carbitol + +> +Salts and Solvents + +$$$$ +cyclopentyl methyl ether + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 6.1000 1.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5053 1.7481 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3855 0.7467 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.4886 -0.4632 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9950 -0.6239 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 5 4 1 0 0 0 0 + 4 2 1 0 0 0 0 + 2 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 cyclopentyl methyl ether +M END +> +cyclopentyl methyl ether + +> +cyclopentyl methyl ether + +> +Salts and Solvents + +$$$$ +dibutyl ether + -INDIGO-11302219142D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + 5.4509 4.6471 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.7500 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.0491 4.6471 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.3480 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.6470 4.6471 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 11.9461 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 13.2452 4.6471 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.5441 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.8432 4.6471 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 dibutyl ether +M END +> +dibutyl ether + +> +dibutyl ether + +> +Salts and Solvents + +$$$$ +diethyl ether + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 6.1000 1.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 2.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 2.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5019 1.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.6980 1.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 2 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 ether +M END +> +diethyl ether + +> +ether + +> +Salts and Solvents + +$$$$ +diethylene glycol + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 7.7875 -1.4835 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4896 -2.2328 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1892 -1.4790 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8854 -2.2317 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5884 -1.4840 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2906 -2.2333 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0845 -2.2313 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 7 1 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 diethylene glycol +M END +> +diethylene glycol + +> +diethylene glycol + +> +Salts and Solvents + +$$$$ +diglyme + -INDIGO-11302219142D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + -0.0857 0.1714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2133 -0.5786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5124 0.1714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3848 -0.5786 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8114 -0.5786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.6838 0.1714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.9828 -0.5786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -5.2818 0.1714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -6.5809 -0.5786 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 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 diglyme +M END +> +diethylene glycol dimethyl ether + +> +diglyme + +> +Salts and Solvents + +$$$$ +diisopropyl ether + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 5.5971 2.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2980 3.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2980 5.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9991 2.8500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7000 3.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4009 2.8500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7000 5.1000 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 + 2 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 diisopropyl ether +M END +> +diisopropyl ether + +> +diisopropyl ether + +> +Salts and Solvents + +$$$$ +dimethyl ether + -INDIGO-11302219142D + + 3 2 0 0 0 0 0 0 0 0999 V2000 + 4.2989 -0.3750 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5980 0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9999 0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 3 1 2 3 +M SMT 1 dimethyl ether +M END +> +dimethyl ether + +> +dimethyl ether + +> +Salts and Solvents + +$$$$ +diphenyl ether + -INDIGO-11302219142D + + 13 14 0 0 0 0 0 0 0 0999 V2000 + 7.1190 1.0305 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.8200 0.2805 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.8200 -1.2196 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5210 -1.9696 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2219 -1.2195 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2219 0.2805 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5209 1.0305 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.4181 0.2804 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.7171 1.0304 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.0161 0.2805 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.0161 -1.2194 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.7170 -1.9694 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.4180 -1.2195 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 2 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 2 0 0 0 0 + 2 7 1 0 0 0 0 + 1 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 9 10 1 0 0 0 0 + 10 11 2 0 0 0 0 + 11 12 1 0 0 0 0 + 12 13 2 0 0 0 0 + 8 13 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 5 9 10 11 12 13 +M SMT 1 diphenyl ether +M END +> +diphenyl ether + +> +diphenyl ether + +> +Salts and Solvents + +$$$$ +ethoxybenzene + -INDIGO-11302219142D + + 9 9 0 0 0 0 0 0 0 0999 V2000 + 0.0000 6.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 4.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 3.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5980 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5980 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.5000 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 + 4 5 2 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 2 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 2 0 0 0 0 + 4 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 ethoxybenzene +M END +> +ethoxybenzene + +> +ethoxybenzene + +> +Salts and Solvents + +$$$$ +methyl t-butyl ether + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 6.1000 1.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5019 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0510 2.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5510 -0.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 2 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 methyl t-butyl ether +M END +> +methyl t-butyl ether + +> +methyl t-butyl ether + +> +Salts and Solvents + +$$$$ +t-amyl methyl ether + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 6.8972 0.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2990 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8482 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3482 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.1962 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 7 1 0 0 0 0 + 2 3 1 0 0 0 0 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 3 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 t-amyl methyl ether +M END +> +t-amyl methyl ether + +> +t-amyl methyl ether + +> +Salts and Solvents + +$$$$ +t-butylethyl ether + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 2.3688 -7.1130 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0698 -7.8630 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2293 -7.1129 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5283 -7.8629 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8274 -8.6129 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.2783 -6.5639 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7783 -9.1620 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 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 t-butylethyl ether +M END +> +t-butylethyl ether + +> +t-butylethyl ether + +> +Salts and Solvents + +$$$$ +tetrahydrofuran + -INDIGO-11302219142D + + 5 5 0 0 0 0 0 0 0 0999 V2000 + 0.7500 2.3100 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.9600 1.4300 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3 2 1 0 0 0 0 + 2 1 1 0 0 0 0 + 1 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 3 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 THF +M END +> +tetrahydrofuran + +> +THF + +> +Salts and Solvents + +$$$$ +triethylene glycol + -INDIGO-11302219142D + + 10 9 0 0 0 0 0 0 0 0999 V2000 + 4.1520 3.8971 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4509 4.6471 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.7500 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.0491 4.6471 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 9.3480 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.6471 4.6471 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.9462 3.8971 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 13.2453 4.6471 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 14.5442 3.8971 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 15.8433 4.6471 0.0000 O 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 9 10 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 2 9 10 +M SMT 1 triethylene glycol +M END +> +triethylene glycol + +> +triethylene glycol + +> +Salts and Solvents + +$$$$ +1,2,4-trichlorobenzene + -INDIGO-11302219142D + + 9 9 0 0 0 0 0 0 0 0999 V2000 + 2.2506 -3.8983 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9991 -2.5989 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2506 -1.2994 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7485 -1.2994 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -2.5989 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7485 -3.8983 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -5.1978 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 2.9991 0.0000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 6 2 0 0 0 0 + 2 3 2 0 0 0 0 + 3 4 1 0 0 0 0 + 3 9 1 0 0 0 0 + 4 5 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 1,2,4-trichlorobenzene +M END +> +1,2,4-trichlorobenzene + +> +1,2,4-trichlorobenzene + +> +Salts and Solvents + +$$$$ +1,2-dichlorobenzene + -INDIGO-11302219142D + + 8 8 0 0 0 0 0 0 0 0999 V2000 + 0.9558 -0.8403 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4581 -0.8408 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2048 0.4582 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.4555 1.7560 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.9571 1.7589 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2065 0.4576 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2078 3.0567 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 3.2060 3.0573 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 6 2 0 0 0 0 + 2 3 2 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 2 0 0 0 0 + 4 8 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 1,2-dichlorobenzene +M END +> +1,2-dichlorobenzene + +> +1,2-dichlorobenzene + +> +Salts and Solvents + +$$$$ +1,2-dichloroethane + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + -0.2571 0.8286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0419 1.5786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3409 0.8286 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5562 1.5786 0.0000 Cl 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 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 DCE +M END +> +1,2-dichloroethane + +> +DCE + +> +Salts and Solvents + +$$$$ +2,2,2-trifluoroethanol + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 2.3661 -2.2500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0670 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0670 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0670 1.5000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4330 0.0000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5670 0.0000 0.0000 F 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 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 2,2,2-trifluoroethanol +M END +> +2,2,2-trifluoroethanol + +> +2,2,2-trifluoroethanol + +> +Salts and Solvents + +$$$$ +2,3,4-trifluorotoluene + -INDIGO-11302219142D + + 10 10 0 0 0 0 0 0 0 0999 V2000 + 4.0898 1.7173 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0899 1.7173 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5899 -0.8808 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0898 -0.8807 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8398 0.4183 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8399 -2.1798 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3399 0.4182 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5898 -0.8807 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3399 -2.1798 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0899 -0.8808 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 5 1 0 0 0 0 + 2 7 1 0 0 0 0 + 3 10 1 0 0 0 0 + 4 5 2 0 0 0 0 + 4 6 1 0 0 0 0 + 4 8 1 0 0 0 0 + 5 7 1 0 0 0 0 + 6 9 2 0 0 0 0 + 7 10 2 0 0 0 0 + 9 10 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 2 9 10 +M SMT 1 2,3,4-trifluorotoluene +M END +> +2,3,4-trifluorotoluene + +> +2,3,4-trifluorotoluene + +> +Salts and Solvents + +$$$$ +carbon tetrachloride + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -1.2500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6000 0.2500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6000 0.2500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 carbon tetrachloride +M END +> +carbon tetrachloride + +> +carbon tetrachloride + +> +Salts and Solvents + +$$$$ +chloroacetic acid + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 9.0626 -7.0246 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.0626 -5.5268 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 10.3632 -7.7759 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4658 -7.0246 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 7.7666 -7.7759 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2 1 2 0 0 0 0 + 3 1 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 1 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 chloroacetic acid +M END +> +chloroacetic acid + +> +chloroacetic acid + +> +Salts and Solvents + +$$$$ +chlorobenzene + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 + 1 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 chlorobenzene +M END +> +chlorobenzene + +> +chlorobenzene + +> +Salts and Solvents + +$$$$ +chloroform + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -1.2500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6000 0.2500 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6000 0.2500 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 chloroform +M END +> +chloroform + +> +chloroform + +> +Salts and Solvents + +$$$$ +dichloromethane + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8500 1.5490 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3500 1.5490 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 DCM +M END +> +dichloromethane + +> +DCM + +> +Salts and Solvents + +$$$$ +fluorobenzene + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 1.2991 3.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5980 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5980 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2991 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 2 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 2 0 0 0 0 + 2 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 fluorobenzene +M END +> +fluorobenzene + +> +fluorobenzene + +> +Salts and Solvents + +$$$$ +perfluorocyclic ether + -INDIGO-11302219142D + + 25 25 0 0 0 0 0 0 0 0999 V2000 + -1.9038 -6.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -1.9038 -4.5746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4038 -4.5746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -1.9038 -3.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4038 -4.5746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4038 -6.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -0.4038 -3.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0962 -4.5746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0962 -6.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0962 -3.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5962 -4.5746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5962 -6.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5962 -3.0746 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0962 -4.5746 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9395 -6.0662 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9395 -3.0827 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.3099 -2.4726 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5598 -1.1736 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 6.5233 -1.5909 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3135 -3.5873 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3173 -2.4726 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.5271 -4.4689 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5635 -4.8864 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.7677 -5.7808 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4224 -6.3797 0.0000 F 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 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 8 10 1 0 0 0 0 + 8 11 1 0 0 0 0 + 11 12 1 0 0 0 0 + 11 13 1 0 0 0 0 + 11 14 1 0 0 0 0 + 14 15 1 0 0 0 0 + 14 16 1 0 0 0 0 + 16 17 1 0 0 0 0 + 17 18 1 0 0 0 0 + 17 19 1 0 0 0 0 + 17 20 1 0 0 0 0 + 20 21 1 0 0 0 0 + 20 22 1 0 0 0 0 + 20 23 1 0 0 0 0 + 14 23 1 0 0 0 0 + 23 24 1 0 0 0 0 + 23 25 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 8 9 10 11 12 13 14 15 16 +M SAL 1 8 17 18 19 20 21 22 23 24 +M SAL 1 1 25 +M SMT 1 perfluorocyclic ether +M END +> +perfluorocyclic ether + +> +perfluorocyclic ether + +> +Salts and Solvents + +$$$$ +perfluorocyclohexane + -INDIGO-11302219142D + + 18 18 0 0 0 0 0 0 0 0999 V2000 + 7.8482 2.0490 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5982 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 6.5491 2.7990 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0490 2.7990 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5982 -0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.8482 -2.0490 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 2.0490 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0490 -2.7990 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 6.5491 -2.7990 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.7500 -2.0490 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0982 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7991 1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0982 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5000 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.7991 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.5000 -0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 13 1 0 0 0 0 + 2 13 1 0 0 0 0 + 3 14 1 0 0 0 0 + 4 14 1 0 0 0 0 + 5 15 1 0 0 0 0 + 6 15 1 0 0 0 0 + 7 16 1 0 0 0 0 + 8 16 1 0 0 0 0 + 9 17 1 0 0 0 0 + 10 17 1 0 0 0 0 + 11 18 1 0 0 0 0 + 12 18 1 0 0 0 0 + 13 14 1 0 0 0 0 + 13 15 1 0 0 0 0 + 14 16 1 0 0 0 0 + 15 17 1 0 0 0 0 + 16 18 1 0 0 0 0 + 17 18 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 8 9 10 11 12 13 14 15 16 +M SAL 1 2 17 18 +M SMT 1 perfluorocyclohexane +M END +> +perfluorocyclohexane + +> +perfluorocyclohexane + +> +Salts and Solvents + +$$$$ +perfluorohexane + -INDIGO-11302219142D + + 20 19 0 0 0 0 0 0 0 0999 V2000 + 6.1472 0.9240 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6472 -1.6740 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.9463 -0.9240 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.4462 1.6740 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 6.3482 -2.4240 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8482 0.1740 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.7453 2.4240 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 10.2453 -0.1740 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0491 -3.1740 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5490 -0.5760 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -2.6250 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 10.0444 3.1740 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 11.5444 0.5760 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 12.0935 2.6250 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8972 -0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.1963 0.3750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 -1.1250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.4953 1.1250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2991 -1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 10.7944 1.8750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 15 1 0 0 0 0 + 2 15 1 0 0 0 0 + 3 16 1 0 0 0 0 + 4 16 1 0 0 0 0 + 5 17 1 0 0 0 0 + 6 17 1 0 0 0 0 + 7 18 1 0 0 0 0 + 8 18 1 0 0 0 0 + 9 19 1 0 0 0 0 + 10 19 1 0 0 0 0 + 11 19 1 0 0 0 0 + 12 20 1 0 0 0 0 + 13 20 1 0 0 0 0 + 14 20 1 0 0 0 0 + 15 16 1 0 0 0 0 + 15 17 1 0 0 0 0 + 16 18 1 0 0 0 0 + 17 19 1 0 0 0 0 + 18 20 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 8 9 10 11 12 13 14 15 16 +M SAL 1 4 17 18 19 20 +M SMT 1 perfluorohexane +M END +> +perfluorohexane + +> +perfluorohexane + +> +Salts and Solvents + +$$$$ +perfluorotoluene + -INDIGO-11302219142D + + 15 15 0 0 0 0 0 0 0 0999 V2000 + 3.0000 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.1962 0.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 3.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.0982 2.2500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0982 2.2500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 8.1962 -2.2500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -2.2500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 -3.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2990 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8972 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.8972 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2990 -1.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.5982 -2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 10 1 0 0 0 0 + 2 11 1 0 0 0 0 + 3 12 1 0 0 0 0 + 4 12 1 0 0 0 0 + 5 12 1 0 0 0 0 + 6 13 1 0 0 0 0 + 7 14 1 0 0 0 0 + 8 15 1 0 0 0 0 + 9 10 2 0 0 0 0 + 9 11 1 0 0 0 0 + 9 12 1 0 0 0 0 + 10 14 1 0 0 0 0 + 11 13 2 0 0 0 0 + 13 15 1 0 0 0 0 + 14 15 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 7 9 10 11 12 13 14 15 +M SMT 1 perfluorotoluene +M END +> +perfluorotoluene + +> +perfluorotoluene + +> +Salts and Solvents + +$$$$ +trichloroacetic acid + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 4.3154 -3.6247 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.6336 -2.8642 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.6336 -1.3688 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0543 -2.8010 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 3.1051 -4.3218 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 4.3090 -5.1835 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 6.9579 -3.6120 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2 1 1 0 0 0 0 + 3 2 2 0 0 0 0 + 4 1 1 0 0 0 0 + 5 1 1 0 0 0 0 + 6 1 1 0 0 0 0 + 7 2 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 trichloroacetic acid +M END +> +trichloroacetic acid + +> +trichloroacetic acid + +> +Salts and Solvents + +$$$$ +trichloroacetonitrile + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 4.5000 0.0000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 1.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0000 -1.5000 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 + 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 0.0000 0.0000 N 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 + 2 4 1 0 0 0 0 + 2 5 1 0 0 0 0 + 5 6 3 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 trichloroacetonitrile +M END +> +trichloroacetonitrile + +> +trichloroacetonitrile + +> +Salts and Solvents + +$$$$ +trifluoroacetic acid + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 1.0500 -4.9991 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 0.3000 -3.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0500 -2.4009 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2000 -3.7000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7000 -3.7000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2000 -2.2000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2000 -5.2000 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 2 3 2 0 0 0 0 + 2 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 + 4 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 trifluoroacetic acid +M END +> +trifluoroacetic acid + +> +trifluoroacetic acid + +> +Salts and Solvents + +$$$$ +trifluoromethylbenzene + -INDIGO-11302219142D + + 10 10 0 0 0 0 0 0 0 0999 V2000 + 6.1000 0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -0.5000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8010 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 -2.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.3990 -2.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 1.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1000 3.2500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 4.6000 1.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 7.6000 1.7500 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 2 0 0 0 0 + 2 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 3 1 0 0 0 0 + 1 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 7 9 1 0 0 0 0 + 7 10 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 2 9 10 +M SMT 1 trifluoromethylbenzene +M END +> +trifluoromethylbenzene + +> +trifluoromethylbenzene + +> +Salts and Solvents + +$$$$ +2-methylpentane + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 0.5471 -1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7520 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.0509 -1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3500 -0.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.6491 -1.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.3500 1.2500 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 + 4 5 1 0 0 0 0 + 4 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 2-methylpentane +M END +> +2-methylpentane + +> +2-methylpentane + +> +Salts and Solvents + +$$$$ +cis-decalin + -INDIGO-11302219142D + + 12 13 0 0 1 0 0 0 0 0999 V2000 + 2.6130 -0.7481 0.0000 C 0 0 2 0 0 0 0 0 0 0 0 0 + 2.6130 -2.2234 0.0000 C 0 0 1 0 0 0 0 0 0 0 0 0 + 1.3195 -3.0026 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3195 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8754 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8754 -2.9714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -0.7481 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1948 -0.7481 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1948 -2.2234 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 -2.2234 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5583 0.8018 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6130 -3.6988 0.0000 H 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 4 1 0 0 0 0 + 1 5 1 0 0 0 0 + 2 3 1 0 0 0 0 + 2 6 1 0 0 0 0 + 3 10 1 0 0 0 0 + 4 7 1 0 0 0 0 + 5 8 1 0 0 0 0 + 6 9 1 0 0 0 0 + 7 10 1 0 0 0 0 + 8 9 1 0 0 0 0 + 1 11 1 1 0 0 0 + 2 12 1 1 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 4 9 10 11 12 +M SMT 1 cis-decalin +M END +> +cis-decalin + +> +cis-decalin + +> +Salts and Solvents + +$$$$ +cyclohexane + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 3.9490 -2.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9490 -5.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 1 0 0 0 0 + 2 1 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 1 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 cyclohexane +M END +> +cyclohexane + +> +cyclohexane + +> +Salts and Solvents + +$$$$ +isooctane + -INDIGO-11302219142D + + 8 7 0 0 0 0 0 0 0 0999 V2000 + 4.6062 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9052 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.2043 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5033 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.8023 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1552 -0.4581 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.6552 -0.4580 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5033 -0.2571 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 + 4 5 1 0 0 0 0 + 2 6 1 0 0 0 0 + 2 7 1 0 0 0 0 + 4 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 isooctane +M END +> +isooctane + +> +isooctane + +> +Salts and Solvents + +$$$$ +methylcyclohexane + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 3.9490 -2.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6500 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9490 -5.3000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -4.5500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2481 -3.0500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9490 -0.8000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 1 0 0 0 0 + 2 1 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 1 1 0 0 0 0 + 1 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 methylcyclohexane +M END +> +methylcyclohexane + +> +methylcyclohexane + +> +Salts and Solvents + +$$$$ +methylcyclopentane + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 4.2136 0.4041 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.4271 -0.4776 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.0001 -0.4776 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.9636 -1.9041 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.4636 -1.9041 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2136 1.9041 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 6 1 0 0 0 0 + 2 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 4 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 methylcyclopentane +M END +> +methylcyclopentane + +> +methylcyclopentane + +> +Salts and Solvents + +$$$$ +heptane + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 4.6062 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9052 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.2043 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5033 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.8023 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.1014 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 12.4004 -2.5071 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 n-heptane +M END +> +heptane + +> +n-heptane + +> +Salts and Solvents + +$$$$ +hexane + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 4.6062 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.9052 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.2043 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 8.5033 -1.7571 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 9.8023 -2.5071 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 11.1014 -1.7571 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 n-hexane +M END +> +hexane + +> +n-hexane + +> +Salts and Solvents + +$$$$ +pentane + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 2.5624 -4.3230 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1578 -4.3230 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.8600 -3.5708 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.4556 -3.5708 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.2647 -3.5708 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2 3 1 0 0 0 0 + 3 1 1 0 0 0 0 + 4 2 1 0 0 0 0 + 5 1 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 pentane +M END +> +pentane + +> +pentane + +> +Salts and Solvents + +$$$$ +2-pentanone + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + -1.5971 -4.2000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2980 -3.4500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0009 -4.2000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3000 -3.4500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5991 -4.2000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.3000 -1.9500 0.0000 O 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 + 4 5 1 0 0 0 0 + 4 6 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 2-pentanone +M END +> +2-pentanone + +> +2-pentanone + +> +Salts and Solvents + +$$$$ +3-pentanone + -INDIGO-11302219142D + + 6 5 0 0 0 0 0 0 0 0999 V2000 + 2.6558 5.4039 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9548 4.6539 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2538 5.4039 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 5.2539 6.9040 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 6.5530 4.6539 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 7.8520 5.4039 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 2 0 0 0 0 + 3 5 1 0 0 0 0 + 5 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 3-pentanone +M END +> +3-pentanone + +> +3-pentanone + +> +Salts and Solvents + +$$$$ +acetone + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 0.0571 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2419 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3562 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0571 1.8714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 propanone +M END +> +acetone + +> +propanone + +> +Salts and Solvents + +$$$$ +cyclohexanone + -INDIGO-11302219142D + + 7 7 0 0 0 0 0 0 0 0999 V2000 + 0.0571 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2419 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3562 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0571 1.8714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2419 -1.8786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0571 -2.6286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3562 -1.8786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 + 2 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 3 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 cyclohexanone +M END +> +cyclohexanone + +> +cyclohexanone + +> +Salts and Solvents + +$$$$ +cyclopentanone + -INDIGO-11302219142D + + 6 6 0 0 0 0 0 0 0 0999 V2000 + 1.0323 3.5259 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0323 2.0259 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.2458 1.1443 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.7823 -0.2824 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2824 -0.2824 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.1813 1.1443 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 2 6 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 6 1 2 3 4 5 6 +M SMT 1 cyclopentanone +M END +> +cyclopentanone + +> +cyclopentanone + +> +Salts and Solvents + +$$$$ +methyl ethyl ketone + -INDIGO-11302219142D + + 5 4 0 0 0 0 0 0 0 0999 V2000 + 0.0571 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2419 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3562 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0571 1.8714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5409 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 + 2 5 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 5 1 2 3 4 5 +M SMT 1 MEK +M END +> +methyl ethyl ketone + +> +MEK + +> +Salts and Solvents + +$$$$ +methyl isobutyl ketone + -INDIGO-11302219142D + + 7 6 0 0 0 0 0 0 0 0999 V2000 + 0.0571 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2419 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3562 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0571 1.8714 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5409 0.3714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.8399 -0.3786 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.5409 1.8714 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 2 0 0 0 0 + 2 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 7 1 2 3 4 5 6 7 +M SMT 1 methyl isobutyl ketone +M END +> +methyl isobutyl ketone + +> +methyl isobutyl ketone + +> +Salts and Solvents + +$$$$ +carbon disulfide + -INDIGO-11302219142D + + 3 2 0 0 0 0 0 0 0 0999 V2000 + 5.7990 0.0000 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 2.7989 0.0000 0.0000 S 0 0 0 0 0 0 0 0 0 0 0 0 + 4.2989 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 3 2 0 0 0 0 + 2 3 2 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 3 1 2 3 +M SMT 1 carbon disulfide +M END +> +carbon disulfide + +> +carbon disulfide + +> +Salts and Solvents + +$$$$ +nitromethane + -INDIGO-11302219142D + + 4 3 0 0 0 0 0 0 0 0999 V2000 + 1.5009 0.7500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8000 1.5000 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.0991 0.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.8000 3.0000 0.0000 O 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 + 2 4 2 0 0 0 0 +M CHG 2 2 1 3 -1 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 4 1 2 3 4 +M SMT 1 nitromethane +M END +> +nitromethane + +> +nitromethane + +> +Salts and Solvents + +$$$$ +o-xylene + -INDIGO-11302219142D + + 8 8 0 0 0 0 0 0 0 0999 V2000 + -2.1500 4.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4490 3.7250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4490 2.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 1.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8510 2.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8510 3.7250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 5.9750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4481 4.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 1 1 0 0 0 0 + 1 7 1 0 0 0 0 + 6 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 o-xylene +M END +> +o-xylene + +> +o-xylene + +> +Salts and Solvents + +$$$$ +m-xylene + -INDIGO-11302219142D + + 8 8 0 0 0 0 0 0 0 0999 V2000 + -2.1500 4.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4490 3.7250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4490 2.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 1.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8510 2.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8510 3.7250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 5.9750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.4480 1.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 1 1 0 0 0 0 + 1 7 1 0 0 0 0 + 5 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 m-xylene +M END +> +m-xylene + +> +m-xylene + +> +Salts and Solvents + +$$$$ +p-xylene + -INDIGO-11302219142D + + 8 8 0 0 0 0 0 0 0 0999 V2000 + -2.1500 4.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4490 3.7250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.4490 2.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 1.4750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8510 2.2250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.8510 3.7250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 5.9750 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.1500 -0.0250 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 2 0 0 0 0 + 2 3 1 0 0 0 0 + 3 4 2 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 2 0 0 0 0 + 6 1 1 0 0 0 0 + 1 7 1 0 0 0 0 + 4 8 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SMT 1 p-xylene +M END +> +p-xylene + +> +p-xylene + +> +Salts and Solvents + +$$$$ +DIPEA + -INDIGO-11302219142D + + 9 8 0 0 0 0 0 0 0 0999 V2000 + -1.5490 7.3145 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.5490 8.8145 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8481 6.5645 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2500 6.5645 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -4.1471 7.3145 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8481 5.0645 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0490 7.3145 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.2500 5.0645 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.8481 9.5645 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1 2 1 0 0 0 0 + 1 3 1 0 0 0 0 + 1 4 1 0 0 0 0 + 3 5 1 0 0 0 0 + 3 6 1 0 0 0 0 + 4 7 1 0 0 0 0 + 4 8 1 0 0 0 0 + 2 9 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 1 9 +M SMT 1 DIPEA +M END +> +n,n-diisopropylethylamine + +> +DIPEA + +> +Salts and Solvents + +$$$$ +1,5-diazabicyclo[5.4.0]undec-7-ene + -INDIGO-11302219142D + + 11 12 0 0 0 0 0 0 0 0999 V2000 + 1.6852 -0.3846 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3514 1.0778 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.0000 1.7286 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.3515 1.0777 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -1.6852 -0.3847 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + -3.1695 -0.6090 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -3.7175 -2.0053 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -2.7822 -3.1781 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -1.2990 -2.9545 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + -0.7500 -1.5574 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 0.7500 -1.5574 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 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 7 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 9 10 2 3 0 0 0 + 10 5 1 0 0 0 0 + 10 11 1 0 0 0 0 + 11 1 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 3 9 10 11 +M SMT 1 DBU +M END +> +1,5-diazabicyclo[5.4.0]undec-7-ene + +> +DBU + +> +Salts and Solvents + +$$$$ +hexamethylphosphoramide + -INDIGO-11302219142D + + 11 10 0 0 0 0 0 0 0 0999 V2000 + 2.3174 -0.9012 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.6235 -1.9903 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 4.8900 -0.9145 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.5935 -3.2519 0.0000 P 0 0 0 0 0 5 0 0 0 0 0 0 + 3.5935 -4.7619 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 5.0831 -3.2205 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 6.0654 -4.1562 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 6.1687 -1.9999 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.1521 -3.2278 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3934 -4.5570 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.0626 -2.3997 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 + 2 4 1 0 0 0 0 + 4 5 2 0 0 0 0 + 4 6 1 0 0 0 0 + 6 7 1 0 0 0 0 + 6 8 1 0 0 0 0 + 4 9 1 0 0 0 0 + 9 10 1 0 0 0 0 + 9 11 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 3 9 10 11 +M SMT 1 HMPA +M END +> +hexamethylphosphoramide + +> +HMPA + +> +Salts and Solvents + +$$$$ +hexamethylphosphorous triamide + -INDIGO-11302219142D + + 10 9 0 0 0 0 0 0 0 0999 V2000 + 0.0007 0.0004 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3000 0.7500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3000 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6000 0.0000 0.0000 P 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9000 0.7500 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 5.1992 0.0004 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9000 2.2500 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 2.6031 -1.5008 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 + 3.9032 -2.2490 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3053 -2.2531 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 + 2 4 1 0 0 0 0 + 4 5 1 0 0 0 0 + 5 6 1 0 0 0 0 + 5 7 1 0 0 0 0 + 4 8 1 0 0 0 0 + 8 9 1 0 0 0 0 + 8 10 1 0 0 0 0 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 8 1 2 3 4 5 6 7 8 +M SAL 1 2 9 10 +M SMT 1 HMPT +M END +> +hexamethylphosphorous triamide + +> +HMPT + +> +Salts and Solvents + +$$$$ +heavy water + -INDIGO-11302219142D + + 3 2 0 0 0 0 0 0 0 0999 V2000 + 0.0007 0.0004 0.0000 D 0 0 0 0 0 0 0 0 0 0 0 0 + 1.3000 0.7500 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 + 2.5993 0.0004 0.0000 D 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 +M STY 1 1 SUP +M SLB 1 1 1 +M SAL 1 3 1 2 3 +M SMT 1 D2O +M END +> +heavy water + +> +D2O + +> +Salts and Solvents + +$$$$ diff --git a/packages/ketcher-core/src/application/editor/actions/atom.ts b/packages/ketcher-core/src/application/editor/actions/atom.ts index d13b80f7d5..6f291475c3 100644 --- a/packages/ketcher-core/src/application/editor/actions/atom.ts +++ b/packages/ketcher-core/src/application/editor/actions/atom.ts @@ -226,7 +226,9 @@ export function fromAtomMerge(restruct, srcId, dstId) { export function mergeFragmentsIfNeeded(action, restruct, srcId, dstId) { const frid = atomGetAttr(restruct, srcId, 'fragment') const frid2 = atomGetAttr(restruct, dstId, 'fragment') - if (frid2 === frid || typeof frid2 !== 'number') return + if (frid2 === frid || typeof frid2 !== 'number') { + return + } const struct = restruct.molecule diff --git a/packages/ketcher-core/src/domain/entities/sgroup.ts b/packages/ketcher-core/src/domain/entities/sgroup.ts index 4c489338ad..171cf00f9d 100644 --- a/packages/ketcher-core/src/domain/entities/sgroup.ts +++ b/packages/ketcher-core/src/domain/entities/sgroup.ts @@ -19,6 +19,7 @@ import { Bond } from './bond' import { Box2Abs } from './box2Abs' import { Pile } from './pile' import { Struct } from './struct' +import { SaltsAndSolventsProvider } from '../helpers' import { Vec2 } from './vec2' export class SGroupBracketParams { @@ -216,6 +217,36 @@ export class SGroup { return Vec2.diff(sgroup.pp, sgroup.bracketBox.p1) } + static isSaltOrSolvent(moleculeName: string): boolean { + const saltsAndSolventsProvider = SaltsAndSolventsProvider.getInstance() + const saltsAndSolvents = saltsAndSolventsProvider.getSaltsAndSolventsList() + return saltsAndSolvents.some(({ name }) => name === moleculeName) + } + + static isAtomInSaltOrSolvent( + atomId: number, + sgroupsOnCanvas: SGroup[] + ): boolean { + const onlySaltsOrSolvents = sgroupsOnCanvas.filter((sgroup) => + this.isSaltOrSolvent(sgroup.data.name) + ) + return onlySaltsOrSolvents.some(({ atoms }) => + atoms.some((atomIdInSaltOrSolvent) => atomIdInSaltOrSolvent === atomId) + ) + } + + static isBondInSaltOrSolvent( + bondId: number, + sgroupsOnCanvas: SGroup[] + ): boolean { + const onlySaltsOrSolvents = sgroupsOnCanvas.filter((sgroup) => + this.isSaltOrSolvent(sgroup.data.name) + ) + return onlySaltsOrSolvents.some(({ bonds }) => + bonds.some((bondIdInSaltOrSolvent) => bondIdInSaltOrSolvent === bondId) + ) + } + static filterAtoms(atoms: any, map: any) { const newAtoms: Array = [] for (let i = 0; i < atoms.length; ++i) { diff --git a/packages/ketcher-core/src/domain/helpers/functionalGroupsProvider.ts b/packages/ketcher-core/src/domain/helpers/functionalGroupsProvider.ts index 78f5a16514..07392fdbec 100644 --- a/packages/ketcher-core/src/domain/helpers/functionalGroupsProvider.ts +++ b/packages/ketcher-core/src/domain/helpers/functionalGroupsProvider.ts @@ -37,4 +37,8 @@ export class FunctionalGroupsProvider { public setFunctionalGroupsList(list: Struct[]): void { this.functionalGroupsList = list } + + public addToFunctionalGroupsList(list: Struct[]): void { + this.functionalGroupsList = [...this.functionalGroupsList, ...list] + } } diff --git a/packages/ketcher-core/src/domain/helpers/index.ts b/packages/ketcher-core/src/domain/helpers/index.ts index f2b7b32562..082196d3b6 100644 --- a/packages/ketcher-core/src/domain/helpers/index.ts +++ b/packages/ketcher-core/src/domain/helpers/index.ts @@ -17,3 +17,4 @@ export * from './scale' export * from './stereoValidator' export * from './functionalGroupsProvider' +export * from './saltsAndSolventsProvider' diff --git a/packages/ketcher-core/src/domain/helpers/saltsAndSolventsProvider.ts b/packages/ketcher-core/src/domain/helpers/saltsAndSolventsProvider.ts new file mode 100644 index 0000000000..bfacfdd3d9 --- /dev/null +++ b/packages/ketcher-core/src/domain/helpers/saltsAndSolventsProvider.ts @@ -0,0 +1,40 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ +import { Struct } from '../entities' + +export class SaltsAndSolventsProvider { + // eslint-disable-next-line no-use-before-define + private static instance: SaltsAndSolventsProvider + saltsAndSolventsList: Struct[] + constructor() { + this.saltsAndSolventsList = [] + } + + public static getInstance(): SaltsAndSolventsProvider { + if (!SaltsAndSolventsProvider.instance) { + SaltsAndSolventsProvider.instance = new SaltsAndSolventsProvider() + } + return SaltsAndSolventsProvider.instance + } + + public getSaltsAndSolventsList() { + return this.saltsAndSolventsList + } + + public setSaltsAndSolventsList(list: Struct[]): void { + this.saltsAndSolventsList = list + } +} diff --git a/packages/ketcher-react/src/script/editor/tool/select.ts b/packages/ketcher-react/src/script/editor/tool/select.ts index c401bf6b86..c57ee8fc97 100644 --- a/packages/ketcher-react/src/script/editor/tool/select.ts +++ b/packages/ketcher-react/src/script/editor/tool/select.ts @@ -27,7 +27,9 @@ import { getItemsToFuse, FunctionalGroup, fromSimpleObjectResizing, - fromArrowResizing + fromArrowResizing, + ReStruct, + ReSGroup } from 'ketcher-core' import LassoHelper from './helper/lasso' @@ -373,6 +375,23 @@ class SelectTool { if (dragCtx && dragCtx.stopTapping) dragCtx.stopTapping() + const possibleSaltOrSolvent = struct.sgroups.get(actualSgroupId) + const isDraggingSaltOrSolventOnStructure = SGroup.isSaltOrSolvent( + possibleSaltOrSolvent?.item.data.name + ) + if ( + (isDraggingSaltOrSolventOnStructure || + this.isDraggingStructureOnSaltOrSolvent(dragCtx, struct.sgroups)) && + dragCtx + ) { + preventSaltAndSolventsMerge(struct, dragCtx, editor) + delete this.dragCtx + if (this.#lassoHelper.running()) { + this.selectElementsOnCanvas(newSelected, editor, event) + } + return true + } + if (dragCtx && dragCtx.item) { dragCtx.action = dragCtx.action ? fromItemsFuse(struct, dragCtx.mergeItems).mergeWith(dragCtx.action) @@ -385,13 +404,7 @@ class SelectTool { delete this.dragCtx } else if (this.#lassoHelper.running()) { // TODO it catches more events than needed, to be re-factored - const sel = - newSelected.atoms.length > 0 - ? selMerge(this.#lassoHelper.end(), newSelected, false) - : this.#lassoHelper.end() - editor.selection( - !event.shiftKey ? sel : selMerge(sel, editor.selection(), false) - ) + this.selectElementsOnCanvas(newSelected, editor, event) } else if (this.#lassoHelper.fragment) { if (!event.shiftKey) editor.selection(null) } @@ -558,6 +571,39 @@ class SelectTool { this.editor.hover(null) } + + selectElementsOnCanvas( + elements: { atoms: number[]; bonds: number[] }, + editor: Editor, + event + ) { + const sel = + elements.atoms.length > 0 + ? selMerge(this.#lassoHelper.end(), elements, false) + : this.#lassoHelper.end() + editor.selection( + !event.shiftKey ? sel : selMerge(sel, editor.selection(), false) + ) + } + + isDraggingStructureOnSaltOrSolvent(dragCtx, sgroups: Map) { + let isDraggingOnSaltOrSolventAtom + let isDraggingOnSaltOrSolventBond + if (dragCtx?.mergeItems) { + const mergeAtoms = Array.from(dragCtx.mergeItems.atoms.values()) + const mergeBonds = Array.from(dragCtx.mergeItems.bonds.values()) + const sgroupsOnCanvas = Array.from(sgroups.values()).map( + ({ item }) => item + ) + isDraggingOnSaltOrSolventAtom = mergeAtoms.some((atomId) => + SGroup.isAtomInSaltOrSolvent(atomId as number, sgroupsOnCanvas) + ) + isDraggingOnSaltOrSolventBond = mergeBonds.some((bondId) => + SGroup.isBondInSaltOrSolvent(bondId as number, sgroupsOnCanvas) + ) + } + return isDraggingOnSaltOrSolventAtom || isDraggingOnSaltOrSolventBond + } } function closestToSel(ci) { @@ -591,4 +637,22 @@ function uniqArray(dest, add, reversible: boolean) { }, []) } +function preventSaltAndSolventsMerge( + struct: ReStruct, + dragCtx, + editor: Editor +) { + const action = dragCtx.action + ? fromItemsFuse(struct, null).mergeWith(dragCtx.action) + : fromItemsFuse(struct, null) + editor.hover(null) + if (dragCtx.mergeItems) { + editor.selection(null) + } + editor.update(action) + editor.event.message.dispatch({ + info: false + }) +} + export default SelectTool diff --git a/packages/ketcher-react/src/script/editor/tool/template.ts b/packages/ketcher-react/src/script/editor/tool/template.ts index 87578504c9..04e1d6f868 100644 --- a/packages/ketcher-react/src/script/editor/tool/template.ts +++ b/packages/ketcher-react/src/script/editor/tool/template.ts @@ -22,7 +22,10 @@ import { fromTemplateOnCanvas, getHoverToFuse, getItemsToFuse, - FunctionalGroup + FunctionalGroup, + SGroup, + ReStruct, + Struct } from 'ketcher-core' import utils from '../shared/utils' @@ -393,6 +396,16 @@ class TemplateTool { let action let pasteItems = null + if (SGroup.isSaltOrSolvent(this.template.molecule.name)) { + addSaltsAndSolventsOnCanvasWithoutMerge( + restruct, + this.template, + dragCtx, + this.editor + ) + return true + } + if (!dragCtx.action) { if (!ci) { // ci.type == 'Canvas' @@ -460,16 +473,18 @@ class TemplateTool { this.editor.selection(null) - if (!dragCtx.mergeItems && pasteItems && this.mode !== 'fg') + if (!dragCtx.mergeItems && pasteItems && this.mode !== 'fg') { dragCtx.mergeItems = getItemsToFuse(this.editor, pasteItems) + } dragCtx.action = dragCtx.action ? fromItemsFuse(restruct, dragCtx.mergeItems).mergeWith(dragCtx.action) : fromItemsFuse(restruct, dragCtx.mergeItems) this.editor.hover(null) const completeAction = dragCtx.action - if (completeAction && !completeAction.isDummy()) + if (completeAction && !completeAction.isDummy()) { this.editor.update(completeAction) + } this.editor.event.message.dispatch({ info: false }) @@ -486,6 +501,21 @@ class TemplateTool { } } +function addSaltsAndSolventsOnCanvasWithoutMerge( + restruct: ReStruct, + template: Struct, + dragCtx, + editor: Editor +) { + const [action] = fromTemplateOnCanvas(restruct, template, dragCtx.xy0, 0) + editor.update(action) + editor.selection(null) + editor.hover(null) + editor.event.message.dispatch({ + info: false + }) +} + function getSign(molecule, bond, v) { const begin = molecule.atoms.get(bond.begin).pp const end = molecule.atoms.get(bond.end).pp diff --git a/packages/ketcher-react/src/script/ui/App/App.tsx b/packages/ketcher-react/src/script/ui/App/App.tsx index 656e40af4e..cc1b5b1a85 100644 --- a/packages/ketcher-react/src/script/ui/App/App.tsx +++ b/packages/ketcher-react/src/script/ui/App/App.tsx @@ -29,6 +29,7 @@ import AppModalContainer from '../views/modal' import Editor from '../views/Editor' import classes from './App.module.less' import { initFGTemplates } from '../state/functionalGroups' +import { initSaltsAndSolventsTemplates } from '../state/saltsAndSolvents' import { useSettingsContext, useSubscriptionOnEvents } from '../../../hooks' interface AppCallProps { @@ -57,6 +58,7 @@ const App = (props: Props) => { useEffect(() => { checkServer() dispatch(initFGTemplates(staticResourcesUrl)) + dispatch(initSaltsAndSolventsTemplates(staticResourcesUrl)) window.scrollTo(0, 0) }, []) diff --git a/packages/ketcher-react/src/script/ui/component/structrender.tsx b/packages/ketcher-react/src/script/ui/component/structrender.tsx index 53a1c7306c..7c28aac45b 100644 --- a/packages/ketcher-react/src/script/ui/component/structrender.tsx +++ b/packages/ketcher-react/src/script/ui/component/structrender.tsx @@ -17,27 +17,36 @@ import { Component, ComponentType, createRef } from 'react' import { MolSerializer, Render, Struct } from 'ketcher-core' +/** + * for S-Groups we want to show expanded structure + * without brackets + */ +function prepareStruct(struct: Struct) { + if (struct.sgroups.size > 0) { + const newStruct = struct.clone() + newStruct.sgroups.delete(0) + return newStruct + } + return struct +} + function renderStruct( el: HTMLElement | null, struct: Struct | null, options = {} ) { - if (el) { - if (struct) { - console.info('render!', el.clientWidth, el.clientWidth) - struct.initHalfBonds() - struct.initNeighbors() - struct.setImplicitHydrogen() - struct.markFragments() - const rnd = new Render(el, { - autoScale: true, - ...options - }) - rnd.setMolecule(struct) - rnd.update() - // console.info('render!');//, el.innerHTML); - // struct.prerender = el.innerHTML; - } + if (el && struct) { + const preparedStruct = prepareStruct(struct) + preparedStruct.initHalfBonds() + preparedStruct.initNeighbors() + preparedStruct.setImplicitHydrogen() + preparedStruct.markFragments() + const rnd = new Render(el, { + autoScale: true, + ...options + }) + rnd.setMolecule(preparedStruct) + rnd.update() } } diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx index 1404cd6c37..388404685b 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx @@ -32,13 +32,14 @@ import Icon from '../../component/view/icon' import { Dialog } from '../../views/components' import Input from '../../component/form/input' import SaveButton from '../../component/view/savebutton' -import { SdfSerializer, Struct } from 'ketcher-core' +import { SdfSerializer } from 'ketcher-core' import classes from './template-lib.module.less' import { connect } from 'react-redux' import { createSelector } from 'reselect' import { omit } from 'lodash/fp' import { onAction } from '../../state' import { functionalGroupsSelector } from '../../state/functionalGroups/selectors' +import { saltsAndSolventsSelector } from '../../state/saltsAndSolvents/selectors' import EmptySearchResult from '../../../ui/dialog/template/EmptySearchResult' import Tabs from '@mui/material/Tabs' @@ -74,6 +75,7 @@ interface TemplateLibProps { selected: Template mode: string initialTab: number + saltsAndSolvents: Template[] } interface TemplateLibCallProps { @@ -84,14 +86,15 @@ interface TemplateLibCallProps { onFilter: (filter: string) => void onOk: (res: any) => void onSelect: (res: any) => void - functionalGroups: (Template & { modifiedStruct: Struct })[] + functionalGroups: Template[] } type Props = TemplateLibProps & TemplateLibCallProps enum TemplateTabs { TemplateLibrary = 0, - FunctionalGroupLibrary = 1 + FunctionalGroupLibrary = 1, + SaltsAndSolvents = 2 } const filterLibSelector = createSelector( @@ -101,6 +104,7 @@ const filterLibSelector = createSelector( ) const FUNCTIONAL_GROUPS = 'Functional Groups' +const SALTS_AND_SOLVENTS = 'Salts and Solvents' const HeaderContent = () => (
@@ -109,24 +113,36 @@ const HeaderContent = () => (
) -const FooterContent = ({ data, tab }) => ( -
- { + const clickToAddToCanvas = Click to add to canvas + if (tab === TemplateTabs.SaltsAndSolvents) { + return clickToAddToCanvas + } + return ( +
- {tab === TemplateTabs.TemplateLibrary - ? 'Save template library to SDF' - : 'Save functional groups to SDF'} - -
-) + + Save to SDF + + {clickToAddToCanvas} +
+ ) +} const TemplateDialog: FC = (props) => { const { @@ -137,6 +153,7 @@ const TemplateDialog: FC = (props) => { initialTab, functionalGroups, lib: templateLib, + saltsAndSolvents, ...rest } = props @@ -147,6 +164,9 @@ const TemplateDialog: FC = (props) => { const [filteredFG, setFilteredFG] = useState( functionalGroups[FUNCTIONAL_GROUPS] ) + const [filteredSaltsAndSolvents, setFilteredSaltsAndSolvents] = useState( + saltsAndSolvents[SALTS_AND_SOLVENTS] + ) const filteredTemplateLib = filterLibSelector(props) @@ -154,6 +174,12 @@ const TemplateDialog: FC = (props) => { setFilteredFG(filterFGLib(functionalGroups, filter)[FUNCTIONAL_GROUPS]) }, [functionalGroups, filter]) + useEffect(() => { + setFilteredSaltsAndSolvents( + filterFGLib(saltsAndSolvents, filter)[SALTS_AND_SOLVENTS] + ) + }, [saltsAndSolvents, filter]) + const handleTabChange = (_, tab) => { setTab(tab) props.onSelect(null) @@ -170,10 +196,12 @@ const TemplateDialog: FC = (props) => { } const sdfSerializer = new SdfSerializer() - const data = - tab === TemplateTabs.TemplateLibrary - ? sdfSerializer.serialize(templateLib) - : sdfSerializer.serialize(functionalGroups) + const serializerMapper = { + [TemplateTabs.TemplateLibrary]: templateLib, + [TemplateTabs.FunctionalGroupLibrary]: functionalGroups, + [TemplateTabs.SaltsAndSolvents]: saltsAndSolvents + } + const data = sdfSerializer.serialize(serializerMapper[tab]) const select = (tmpl: Template): void => { onChangeGroup(tmpl.props.group) @@ -186,8 +214,7 @@ const TemplateDialog: FC = (props) => { footerContent={} className={`${classes.dialog_body}`} params={omit(['group'], rest)} - buttons={['OK']} - buttonsNameMap={{ OK: 'Add to canvas' }} + buttons={[]} needMargin={false} >
@@ -210,6 +237,10 @@ const TemplateDialog: FC = (props) => { label="Functional Groups" {...a11yProps(TemplateTabs.FunctionalGroupLibrary)} /> +
@@ -278,6 +309,22 @@ const TemplateDialog: FC = (props) => {
)} + + {filteredSaltsAndSolvents?.length ? ( +
+ select(templ)} + selected={props.selected} + /> +
+ ) : ( +
+ +
+ )} +
) @@ -287,11 +334,8 @@ export default connect( (store) => ({ ...omit(['attach'], (store as any).templates), initialTab: (store as any).modal?.prop?.tab, - functionalGroups: functionalGroupsSelector(store).map((template) => { - const struct = template.struct.clone() - struct.sgroups.delete(0) - return { ...template, modifiedStruct: struct } - }) + functionalGroups: functionalGroupsSelector(store), + saltsAndSolvents: saltsAndSolventsSelector(store) }), (dispatch: Dispatch, props: Props) => ({ onFilter: (filter) => dispatch(changeFilter(filter)), diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.module.less b/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.module.less index 4e1cdd2460..13731ce925 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.module.less +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.module.less @@ -30,6 +30,8 @@ border: 1px solid transparent; border-radius: 6px; overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; max-width: 100px; max-height: 30px; } diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx index fe952a0232..760ee7eadb 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateTable.tsx @@ -24,12 +24,13 @@ import Icon from 'src/script/ui/component/view/icon' export interface Template { struct: Struct - modifiedStruct?: Struct // TODO: Do something with that, in future it shouldn't be here props: { atomid: number bondid: number group: string prerender?: string + abbreviation: string + name: string } } @@ -43,8 +44,22 @@ interface TemplateTableProps { } const getSettingsSelector = (state) => state.options.settings +const isSaltOrSolventTemplate = (template) => + template.props.group === 'Salts and Solvents' +const isFunctionalGroupTemplate = (template) => + template.props.group === 'Functional Groups' + +function getTemplateTitle(template: Template, index: number): string { + if (isSaltOrSolventTemplate(template)) { + return template.props.name + } + return template.struct.name || `${template.props.group} template ${index + 1}` +} function tmplName(tmpl: Template, i: number): string { + if (isSaltOrSolventTemplate(tmpl)) { + return tmpl.props.abbreviation + } return tmpl.struct.name || `${tmpl.props.group} template ${i + 1}` } @@ -55,7 +70,7 @@ const RenderTmpl: FC<{ }> = ({ tmpl, options, ...props }) => { return ( @@ -87,7 +102,7 @@ const TemplateTable: FC = (props) => { ? classes.td : `${classes.td} ${classes.selected}` } - title={greekify(tmplName(tmpl, i))} + title={greekify(getTemplateTitle(tmpl, i))} key={ tmpl.struct.name !== selected?.struct.name ? `${tmpl.struct.name}_${i}` @@ -115,14 +130,15 @@ const TemplateTable: FC = (props) => { )} - {tmpl.props.group !== 'Functional Groups' && ( - - )} + {!isFunctionalGroupTemplate(tmpl) && + !isSaltOrSolventTemplate(tmpl) && ( + + )}
) })} diff --git a/packages/ketcher-react/src/script/ui/state/index.js b/packages/ketcher-react/src/script/ui/state/index.js index 7a72362c8c..5c777a2e90 100644 --- a/packages/ketcher-react/src/script/ui/state/index.js +++ b/packages/ketcher-react/src/script/ui/state/index.js @@ -21,6 +21,7 @@ import templatesReducer, { initTmplsState } from './templates' import actionStateReducer from './action' import functionalGroupsReducer from './functionalGroups' +import saltsAndSolventsReducer from './saltsAndSolvents' import { logger } from 'redux-logger' import modalReducer from './modal' import { pick } from 'lodash/fp' @@ -39,6 +40,7 @@ const shared = combineReducers({ options: optionsReducer, templates: templatesReducer, functionalGroups: functionalGroupsReducer, + saltsAndSolvents: saltsAndSolventsReducer, requestsStatuses: requestReducer }) diff --git a/packages/ketcher-react/src/script/ui/state/options/index.js b/packages/ketcher-react/src/script/ui/state/options/index.js index 49319c9c11..350180d151 100644 --- a/packages/ketcher-react/src/script/ui/state/options/index.js +++ b/packages/ketcher-react/src/script/ui/state/options/index.js @@ -27,7 +27,8 @@ export const initOptionsState = { app: { server: false, templates: false, - functionalGroups: false + functionalGroups: false, + saltsAndSolvents: false }, analyse: { values: null, diff --git a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts new file mode 100644 index 0000000000..44bdb98c53 --- /dev/null +++ b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts @@ -0,0 +1,76 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ + +import { AnyAction } from 'redux' +import { appUpdate } from '../options' +import { + SaltsAndSolventsProvider, + FunctionalGroupsProvider, + SdfItem, + SdfSerializer, + Struct +} from 'ketcher-core' +import { prefetchStatic } from '../templates/init-lib' + +interface SaltsAndSolventsState { + lib: [] + mode: string +} + +const initialState: SaltsAndSolventsState = { + lib: [], + mode: 'fg' +} + +const saltsAndSolventsReducer = ( + state = initialState, + { type, payload }: AnyAction +) => { + switch (type) { + case 'SALTS_AND_SOLVENTS_INIT': + return { ...state, ...payload } + + default: + return state + } +} + +const initSaltsAndSolvents = (lib: SdfItem[]) => ({ + type: 'SALTS_AND_SOLVENTS_INIT', + payload: { lib } +}) + +export function initSaltsAndSolventsTemplates(baseUrl: string) { + return async (dispatch) => { + const fileName = 'salts-and-solvents.sdf' + const url = `${baseUrl}/templates/${fileName}` + const saltsAndSolventsProvider = SaltsAndSolventsProvider.getInstance() + const functionalGroupsProvider = FunctionalGroupsProvider.getInstance() + const sdfSerializer = new SdfSerializer() + const text = await prefetchStatic(url) + const templates = sdfSerializer.deserialize(text) + const saltsAndSolvents = templates.reduce( + (acc: Struct[], { struct }) => [...acc, struct], + [] + ) + saltsAndSolventsProvider.setSaltsAndSolventsList(saltsAndSolvents) + functionalGroupsProvider.addToFunctionalGroupsList(saltsAndSolvents) + dispatch(initSaltsAndSolvents(templates)) + dispatch(appUpdate({ saltsAndSolvents: true })) + } +} + +export default saltsAndSolventsReducer diff --git a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/selectors/index.ts b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/selectors/index.ts new file mode 100644 index 0000000000..8b1fd1ef53 --- /dev/null +++ b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/selectors/index.ts @@ -0,0 +1,19 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ + +export const saltsAndSolventsSelector = (state) => { + return state.saltsAndSolvents.lib +} diff --git a/packages/ketcher-react/src/script/ui/utils/index.ts b/packages/ketcher-react/src/script/ui/utils/index.ts index a7f8cfed9f..1869115391 100644 --- a/packages/ketcher-react/src/script/ui/utils/index.ts +++ b/packages/ketcher-react/src/script/ui/utils/index.ts @@ -55,8 +55,16 @@ export function filterLib(lib, filter) { export function filterFGLib(lib, filter) { console.warn('Filter', filter) const re = new RegExp(escapeRegExp(greekify(filter)), 'i') + const searchFunction = (item) => { + const fields = [ + item.struct.name, + item.props.abbreviation, + item.props.name + ].filter(Boolean) + return fields.some((field) => re.test(greekify(field))) + } return flow( - _filter((item: any) => !filter || re.test(greekify(item.struct.name))), + _filter((item: any) => !filter || searchFunction(item)), reduce((res, item) => { if (!res[item.props.group]) res[item.props.group] = [item] else res[item.props.group].push(item) From 2863e94c9d0d370b5bdf442d79072c821e828704 Mon Sep 17 00:00:00 2001 From: Anna Zhuravleva <56927722+ansivgit@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:18:21 +0300 Subject: [PATCH 13/27] #1827 currently selected tool with mouse cursor (#1883) * #1827 - wip * #1827 test for husky * fix: clean code * #1827 hovered icon disappear if atom tool inactive * #1827 - fix after review * #1827 - add yarn.lock * #1827 - fix raphael types * #1827 - fix font-style * #1827 - small tweaks * #1827 - remove comment Co-authored-by: Konstantin Levin --- .../ketcher-react/src/script/editor/Editor.ts | 12 ++++++++++++ .../src/script/editor/tool/atom.ts | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index 1b5639a012..faa831019b 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -38,6 +38,7 @@ import { Highlighter } from './highlighter' const SCALE = 40 const HISTORY_SIZE = 32 // put me to options +const HOVER_ICON_OPACITY = 0.7 const structObjects = [ 'atoms', @@ -109,6 +110,7 @@ class Editor implements KetcherEditor { historyPtr: any errorHandler: ((message: string) => void) | null highlights: Highlighter + hoverIcon: any event: { message: Subscription elementEdit: PipelineSubscription @@ -151,6 +153,11 @@ class Editor implements KetcherEditor { this.renderAndRecoordinateStruct.bind(this) this.setOptions = this.setOptions.bind(this) + this.hoverIcon = this.render.paper + .text(0, 0, '') + .attr('font-size', options.fontsz) + .attr('opacity', HOVER_ICON_OPACITY) + this.event = { message: new Subscription(), elementEdit: new PipelineSubscription(), @@ -200,6 +207,11 @@ class Editor implements KetcherEditor { const tool = new toolMap[name](this, opts) + const isAtomToolChosen = name === 'atom' + if (!isAtomToolChosen) { + this.hoverIcon.hide() + } + if (!tool || tool.isNotActiveTool) { return null } diff --git a/packages/ketcher-react/src/script/editor/tool/atom.ts b/packages/ketcher-react/src/script/editor/tool/atom.ts index 633d1283eb..794bc58d53 100644 --- a/packages/ketcher-react/src/script/editor/tool/atom.ts +++ b/packages/ketcher-react/src/script/editor/tool/atom.ts @@ -24,7 +24,8 @@ import { fromAtomsAttrs, fromBondAddition, fromFragmentDeletion, - fromSgroupDeletion + fromSgroupDeletion, + ElementColor } from 'ketcher-core' import Editor from '../Editor' @@ -41,6 +42,12 @@ class AtomTool { this.editor = editor this.atomProps = atomProps this.#bondProps = { type: 1, stereo: Bond.PATTERN.STEREO.NONE } + + this.editor.hoverIcon + .show() + .attr('text', `${atomProps.label}`) + .attr('fill', `${ElementColor[atomProps.label]}`) + if (editor.selection()) { if (editor.selection()?.atoms) { const action = fromAtomsAttrs( @@ -129,7 +136,15 @@ class AtomTool { mousemove(event) { const rnd = this.editor.render + const { layerX, layerY } = event + if (!this.dragCtx || !this.dragCtx.item) { + const { height, width } = this.editor.hoverIcon.getBBox() + + this.editor.hoverIcon.attr({ + x: layerX - width / 2, + y: layerY - height / 2 + }) this.editor.hover( this.editor.findItem(event, ['atoms', 'functionalGroups']) ) From dbe1d4d6f25ccc94d4e26d850cb8cf570e07d407 Mon Sep 17 00:00:00 2001 From: Nikita Date: Mon, 12 Dec 2022 17:07:52 +0300 Subject: [PATCH 14/27] =?UTF-8?q?=20=20#1894=20=E2=80=93=20added=20support?= =?UTF-8?q?=20for=20extra=20spaces=20and=20alias=20in=20mol=20v2000=20file?= =?UTF-8?q?s=20(#1904)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ketcher-core/src/domain/entities/atom.ts | 18 ++++++++++++------ .../src/domain/serializers/mol/common.js | 10 +++++++--- .../src/domain/serializers/mol/v2000.js | 13 ++++++++----- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/ketcher-core/src/domain/entities/atom.ts b/packages/ketcher-core/src/domain/entities/atom.ts index 8c68fa10d3..6ac38c27fc 100644 --- a/packages/ketcher-core/src/domain/entities/atom.ts +++ b/packages/ketcher-core/src/domain/entities/atom.ts @@ -24,13 +24,14 @@ function getValueOrDefault(value: T | undefined, defaultValue: T): T { return typeof value !== 'undefined' ? value : defaultValue } +function isCorrectPseudo(label) { + return ( + !Elements.get(label) && label !== 'L' && label !== 'L#' && label !== 'R#' + ) +} + function getPseudo(label: string) { - return !Elements.get(label) && - label !== 'L' && - label !== 'L#' && - label !== 'R#' - ? label - : '' + return isCorrectPseudo(label) ? label : '' } export function radicalElectrons(radical: any) { @@ -213,6 +214,11 @@ export class Atom { enumerable: true, get: function () { return getPseudo(this.label) + }, + set: function (value) { + if (isCorrectPseudo(value)) { + this.label = value + } } }) } diff --git a/packages/ketcher-core/src/domain/serializers/mol/common.js b/packages/ketcher-core/src/domain/serializers/mol/common.js index 396cfdbb95..a33ad6000d 100644 --- a/packages/ketcher-core/src/domain/serializers/mol/common.js +++ b/packages/ketcher-core/src/domain/serializers/mol/common.js @@ -43,10 +43,14 @@ function parseCTab(/* string */ ctabLines) /* Struct */ { ) const version = countsSplit[11].trim() ctabLines = ctabLines.slice(1) - if (version === 'V2000') return v2000.parseCTabV2000(ctabLines, countsSplit) - else if (version === 'V3000') { + if (version === 'V2000') { + return v2000.parseCTabV2000(ctabLines, countsSplit) + } + if (version === 'V3000') { return v3000.parseCTabV3000(ctabLines, !loadRGroupFragments) - } else throw new Error('Molfile version unknown: ' + version) // eslint-disable-line no-else-return + } else { + throw new Error('Molfile version unknown: ' + version) + } } /* Parse Rxn */ diff --git a/packages/ketcher-core/src/domain/serializers/mol/v2000.js b/packages/ketcher-core/src/domain/serializers/mol/v2000.js index 0ddb121576..a1de1f0959 100644 --- a/packages/ketcher-core/src/domain/serializers/mol/v2000.js +++ b/packages/ketcher-core/src/domain/serializers/mol/v2000.js @@ -136,17 +136,20 @@ function parsePropertyLines(ctab, ctabLines, shift, end, sGroups, rLogic) { while (shift < end) { const line = ctabLines[shift] if (line.charAt(0) === 'A') { - let propValue = ctabLines[++shift] + const propValue = ctabLines[++shift] // TODO: Atom entity only have pseudo getter. Check during refactoring // this type of pseudo labeling is not used in current BIOVIA products. See ctab documentation 2020 // https://discover.3ds.com/sites/default/files/2020-08/biovia_ctfileformats_2020.pdf (page 47) const isPseudo = /'.+'/.test(propValue) - if (isPseudo && !props.get('pseudo')) props.set('pseudo', new Pool()) - if (!isPseudo && !props.get('alias')) props.set('alias', new Pool()) - if (isPseudo) propValue = propValue.replace(/'/g, '') + if (isPseudo && !props.get('pseudo')) { + props.set('pseudo', new Pool()) + } + if (!isPseudo && !props.get('alias')) { + props.set('alias', new Pool()) + } props .get(isPseudo ? 'pseudo' : 'alias') - .set(utils.parseDecimalInt(line.slice(3, 6)) - 1, propValue) + .set(utils.parseDecimalInt(line.slice(3)) - 1, propValue) } else if (line.charAt(0) === 'M') { const type = line.slice(3, 6) let propertyData = line.slice(6) From e3a7411561c80a092411a8355e7307ba99beac9d Mon Sep 17 00:00:00 2001 From: Anna Zhuravleva <56927722+ansivgit@users.noreply.github.com> Date: Mon, 12 Dec 2022 18:29:27 +0300 Subject: [PATCH 15/27] #1827-fixes-hover-icon (#1909) Co-authored-by: Konstantin Levin --- packages/ketcher-react/src/script/editor/tool/atom.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/ketcher-react/src/script/editor/tool/atom.ts b/packages/ketcher-react/src/script/editor/tool/atom.ts index 794bc58d53..48e91ee19f 100644 --- a/packages/ketcher-react/src/script/editor/tool/atom.ts +++ b/packages/ketcher-react/src/script/editor/tool/atom.ts @@ -134,6 +134,14 @@ class AtomTool { } } + mouseleave() { + this.editor.hoverIcon.hide() + } + + mouseover() { + this.editor.hoverIcon.show() + } + mousemove(event) { const rnd = this.editor.render const { layerX, layerY } = event From 4edb41e61d8016b6d3cfa02d342d1faa3cfffeb0 Mon Sep 17 00:00:00 2001 From: KonstantinEpam23 <101649391+KonstantinEpam23@users.noreply.github.com> Date: Mon, 12 Dec 2022 20:59:02 +0300 Subject: [PATCH 16/27] #1824: expand function groups on hover (#1907) * #1824: expand function groups on hover * #1824: temporary fixes for sgroup hover * #1824: temporary fixes for sgroup hover * #1824: fix double dependency * #1824: remove comments Co-authored-by: Konstantin Levin --- .../src/application/render/raphaelRender.js | 13 +- .../src/domain/entities/functionalGroup.ts | 6 + .../ketcher-react/src/script/editor/Editor.ts | 42 ++++- .../src/script/editor/tool/select.ts | 2 +- .../src/script/editor/tool/template.ts | 6 +- .../ui/component/ContextMenu/ContextMenu.tsx | 4 + .../src/script/ui/component/structrender.tsx | 22 ++- .../src/script/ui/state/editor/index.js | 16 +- .../script/ui/state/functionalGroups/index.ts | 13 ++ .../state/functionalGroups/selectors/index.ts | 2 + .../components/StructEditor/InfoPanel.jsx | 166 ++++++++++++++++++ .../StructEditor/InfoPanel.module.less | 9 + .../components/StructEditor/StructEditor.jsx | 12 +- 13 files changed, 289 insertions(+), 24 deletions(-) create mode 100644 packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx create mode 100644 packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less diff --git a/packages/ketcher-core/src/application/render/raphaelRender.js b/packages/ketcher-core/src/application/render/raphaelRender.js index 0c17a0e755..abd280cd60 100644 --- a/packages/ketcher-core/src/application/render/raphaelRender.js +++ b/packages/ketcher-core/src/application/render/raphaelRender.js @@ -23,8 +23,8 @@ import defaultOptions from './options' import draw from './draw' export function Render(clientArea, opt) { - let renderWidth = clientArea.clientWidth - 10 - let renderHeight = clientArea.clientHeight - 10 + let renderWidth = opt.width || clientArea.clientWidth - 10 + let renderHeight = opt.height || clientArea.clientHeight - 10 renderWidth = renderWidth > 0 ? renderWidth : 0 renderHeight = renderHeight > 0 ? renderHeight : 0 @@ -229,13 +229,12 @@ Render.prototype.update = function (force = false, viewSz = null) { const marg = this.options.autoScaleMargin const mv = new Vec2(marg, marg) const csz = viewSz - if (csz.x < 2 * marg + 1 || csz.y < 2 * marg + 1) { + if (marg && (csz.x < 2 * marg + 1 || csz.y < 2 * marg + 1)) { throw new Error('View box too small for the given margin') } - let rescale = Math.max( - sz1.x / (csz.x - 2 * marg), - sz1.y / (csz.y - 2 * marg) - ) + let rescale = + this.options.rescaleAmount || + Math.max(sz1.x / (csz.x - 2 * marg), sz1.y / (csz.y - 2 * marg)) if (this.options.maxBondLength / rescale > 1.0) rescale = 1.0 const sz2 = sz1.add(mv.scaled(2 * rescale)) /* eslint-disable no-mixed-operators */ diff --git a/packages/ketcher-core/src/domain/entities/functionalGroup.ts b/packages/ketcher-core/src/domain/entities/functionalGroup.ts index 7e9ede4c49..637abdbb65 100644 --- a/packages/ketcher-core/src/domain/entities/functionalGroup.ts +++ b/packages/ketcher-core/src/domain/entities/functionalGroup.ts @@ -52,6 +52,12 @@ export class FunctionalGroup { ) } + static getFunctionalGroupByName(searchName: string): Struct | null { + const provider = FunctionalGroupsProvider.getInstance() + const types = provider.getFunctionalGroupsList() + return types.find((fnGroup) => fnGroup.name === searchName) || null + } + static atomsInFunctionalGroup(functionalGroups, atom): number | null { if (functionalGroups.size === 0) { return null diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index faa831019b..92ed7c1d4d 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -22,7 +22,8 @@ import { Struct, Vec2, fromDescriptorsAlign, - fromNewCanvas + fromNewCanvas, + FunctionalGroup } from 'ketcher-core' import { DOMSubscription, @@ -127,6 +128,7 @@ class Editor implements KetcherEditor { dearomatizeStruct: PipelineSubscription enhancedStereoEdit: PipelineSubscription confirm: PipelineSubscription + showInfo: PipelineSubscription cursor: Subscription } @@ -175,7 +177,8 @@ class Editor implements KetcherEditor { // TODO: correct enhancedStereoEdit: new PipelineSubscription(), confirm: new PipelineSubscription(), - cursor: new PipelineSubscription() + cursor: new PipelineSubscription(), + showInfo: new PipelineSubscription() } domEventSetup(this, clientArea) @@ -207,9 +210,9 @@ class Editor implements KetcherEditor { const tool = new toolMap[name](this, opts) - const isAtomToolChosen = name === 'atom' - if (!isAtomToolChosen) { - this.hoverIcon.hide() + // hide icon if not AtomToll chosen + if (name !== 'atom') { + this.render.paper.getById('atomHoverIcon')?.hide() } if (!tool || tool.isNotActiveTool) { @@ -343,9 +346,11 @@ class Editor implements KetcherEditor { return this._selection // eslint-disable-line } - hover(ci: any, newTool?: any) { + hover(ci: any, newTool?: any, event?: PointerEvent) { const tool = newTool || this._tool // eslint-disable-line + let highlight: any = false + if ( 'ci' in tool && (!ci || tool.ci.map !== ci.map || tool.ci.id !== ci.id) @@ -355,6 +360,31 @@ class Editor implements KetcherEditor { } if (ci && setHover(ci, true, this.render)) tool.ci = ci + + if (!event) return + + const myCi = this.findItem(event, ['sgroups', 'functionalGroups']) + if (myCi) { + if (myCi.map === 'sgroups' || myCi.map === 'functionalGroups') { + const sGroup = this.struct()?.sgroups.get(myCi.id) + if (sGroup && !sGroup.data.expanded) { + const groupName = sGroup.data.name + const groupStruct = + FunctionalGroup.getFunctionalGroupByName(groupName) + highlight = { + group: groupStruct, + x: event.clientX, + y: event.clientY, + groupId: myCi.id + } + } + } + } + if (highlight) { + this.event.showInfo.dispatch(highlight) + } else { + this.event.showInfo.dispatch(null) + } } update(action: Action | true, ignoreHistory?) { diff --git a/packages/ketcher-react/src/script/editor/tool/select.ts b/packages/ketcher-react/src/script/editor/tool/select.ts index c57ee8fc97..091dae5897 100644 --- a/packages/ketcher-react/src/script/editor/tool/select.ts +++ b/packages/ketcher-react/src/script/editor/tool/select.ts @@ -305,7 +305,7 @@ class SelectTool { 'texts' ] - editor.hover(editor.findItem(event, maps, null)) + editor.hover(editor.findItem(event, maps, null), null, event) return true } diff --git a/packages/ketcher-react/src/script/editor/tool/template.ts b/packages/ketcher-react/src/script/editor/tool/template.ts index 04e1d6f868..6919e69b88 100644 --- a/packages/ketcher-react/src/script/editor/tool/template.ts +++ b/packages/ketcher-react/src/script/editor/tool/template.ts @@ -239,7 +239,11 @@ class TemplateTool { const restruct = this.editor.render.ctab if (!this.dragCtx) { - this.editor.hover(this.editor.findItem(event, this.findItems)) + this.editor.hover( + this.editor.findItem(event, this.findItems), + null, + event + ) return true } diff --git a/packages/ketcher-react/src/script/ui/component/ContextMenu/ContextMenu.tsx b/packages/ketcher-react/src/script/ui/component/ContextMenu/ContextMenu.tsx index 874e915aba..0300cff552 100644 --- a/packages/ketcher-react/src/script/ui/component/ContextMenu/ContextMenu.tsx +++ b/packages/ketcher-react/src/script/ui/component/ContextMenu/ContextMenu.tsx @@ -1,5 +1,6 @@ import { ContextMenu, MenuItem } from 'react-contextmenu' import { useState } from 'react' +import { useDispatch } from 'react-redux' import { FunctionalGroup, setExpandSGroup, @@ -9,9 +10,11 @@ import { import { useAppContext } from '../../../../hooks' import clsx from 'clsx' import classes from './ContextMenu.module.less' +import { highlightFG } from '../../state/functionalGroups' const FGContextMenu = () => { const { getKetcherInstance } = useAppContext() + const dispatch = useDispatch() const handleExpand = () => { const editor = getKetcherInstance().editor as any @@ -27,6 +30,7 @@ const FGContextMenu = () => { editor.update(action) setShowSGroupMenu(false) setTargetItems([]) + highlightFG(dispatch, { group: null, id: null }) } const handleRemove = function () { diff --git a/packages/ketcher-react/src/script/ui/component/structrender.tsx b/packages/ketcher-react/src/script/ui/component/structrender.tsx index 7c28aac45b..ce743b9afe 100644 --- a/packages/ketcher-react/src/script/ui/component/structrender.tsx +++ b/packages/ketcher-react/src/script/ui/component/structrender.tsx @@ -33,7 +33,7 @@ function prepareStruct(struct: Struct) { function renderStruct( el: HTMLElement | null, struct: Struct | null, - options = {} + options: any = {} ) { if (el && struct) { const preparedStruct = prepareStruct(struct) @@ -46,13 +46,14 @@ function renderStruct( ...options }) rnd.setMolecule(preparedStruct) - rnd.update() + rnd.update(true, options.viewSz) } } interface StructRenderProps { struct: Struct options: any + id?: any Tag?: string | ComponentType } @@ -63,11 +64,11 @@ class StructRender extends Component { this.tagRef = createRef() } - shouldComponentUpdate() { - return false + shouldComponentUpdate(previousProps) { + return this.props.id && this.props.id !== previousProps.id } - componentDidMount() { + update() { const el = this.tagRef.current const { struct, options } = this.props let parsedStruct: Struct | null @@ -83,9 +84,20 @@ class StructRender extends Component { } else { parsedStruct = struct } + el?.childNodes.forEach((node) => { + node.remove() + }) renderStruct(el, parsedStruct, options) } + componentDidMount() { + this.update() + } + + componentDidUpdate() { + this.update() + } + render() { const { struct, Tag = 'div', ...props } = this.props return ( diff --git a/packages/ketcher-react/src/script/ui/state/editor/index.js b/packages/ketcher-react/src/script/ui/state/editor/index.js index 21941e0523..49cfab6c43 100644 --- a/packages/ketcher-react/src/script/ui/state/editor/index.js +++ b/packages/ketcher-react/src/script/ui/state/editor/index.js @@ -29,6 +29,7 @@ import { Elements } from 'ketcher-core' import acts from '../../action' import { debounce } from 'lodash/fp' import { openDialog } from '../modal' +import { highlightFG } from '../functionalGroups' import { serverCall } from '../server' export default function initEditor(dispatch, getState) { @@ -155,7 +156,10 @@ export default function initEditor(dispatch, getState) { }, onSgroupEdit: (sgroup) => sleep(0) // huck to open dialog after dispatch sgroup tool action - .then(() => openDialog(dispatch, 'sgroup', fromSgroup(sgroup))) + .then(() => { + console.log('onSgroupEdit') + openDialog(dispatch, 'sgroup', fromSgroup(sgroup)) + }) .then(toSgroup), onRemoveFG: (result) => sleep(0).then(() => openDialog(dispatch, 'removeFG', result)), @@ -199,6 +203,14 @@ export default function initEditor(dispatch, getState) { onMouseDown: () => { updateAction() }, - onConfirm: () => openDialog(dispatch, 'confirm') + onConfirm: () => openDialog(dispatch, 'confirm'), + onShowInfo: (pl) => { + if (pl) { + const { group, groupId, x, y } = pl + highlightFG(dispatch, { group, id: group?.name, x, y, groupId }) + } else { + highlightFG(dispatch, { group: null, id: null }) + } + } } } diff --git a/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts b/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts index 2f9bd29a0b..a11d92e1ee 100644 --- a/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts +++ b/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts @@ -26,11 +26,13 @@ import { prefetchStatic } from '../templates/init-lib' interface FGState { lib: [] + functionalGroupInfo: any mode: string } const initialState: FGState = { lib: [], + functionalGroupInfo: null, mode: 'fg' } @@ -42,12 +44,23 @@ const functionalGroupsReducer = ( case 'FG_INIT': return { ...state, ...payload } + case 'FG_HIGHLIGHT': + return { ...state, functionalGroupInfo: payload } + default: return state } } const initFGroups = (lib: SdfItem[]) => ({ type: 'FG_INIT', payload: { lib } }) +const highlightFGroup = (group: any) => ({ + type: 'FG_HIGHLIGHT', + payload: group +}) + +export function highlightFG(dispatch, group: any) { + dispatch(highlightFGroup(group)) +} export function initFGTemplates(baseUrl: string) { return async (dispatch) => { diff --git a/packages/ketcher-react/src/script/ui/state/functionalGroups/selectors/index.ts b/packages/ketcher-react/src/script/ui/state/functionalGroups/selectors/index.ts index f69bb5e9dd..768602bbfe 100644 --- a/packages/ketcher-react/src/script/ui/state/functionalGroups/selectors/index.ts +++ b/packages/ketcher-react/src/script/ui/state/functionalGroups/selectors/index.ts @@ -15,4 +15,6 @@ ***************************************************************************/ export const functionalGroupsSelector = (state) => state.functionalGroups.lib +export const functionGroupInfoSelector = (state) => + state.functionalGroups.functionalGroupInfo export const modeSelector = (state) => state.functionalGroups.mode diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx new file mode 100644 index 0000000000..3addb5fcff --- /dev/null +++ b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx @@ -0,0 +1,166 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ + +import { useState, useEffect, useRef } from 'react' +import { Scale, ReStruct, Vec2 } from 'ketcher-core' + +import StructRender from '../../../component/structrender' +// import { setRef } from '@mui/material' +import { + functionalGroupsSelector, + functionGroupInfoSelector +} from '../../../state/functionalGroups/selectors' +import { saltsAndSolventsSelector } from '../../../state/saltsAndSolvents/selectors' +import { connect, useSelector } from 'react-redux' +import { render } from '@testing-library/react' +import clsx from 'clsx' + +import classes from './InfoPanel.module.less' + +const HOVER_DELAY = 400 + +const allSGroupsSelector = (store) => { + const result = [...store.functionalGroups.lib, ...store.saltsAndSolvents.lib] + return result +} + +const options = { + autoScale: true, + autoScaleMargin: 0 +} + +const InfoPanel = (props) => { + const { + id, + functionalGroups, + x = 0, + y = 0, + groupId, + restruct, + baba, + className + } = props + const [molecule, setMolecule] = useState(null) + const childRef = useRef(null) + + let timer = -1 + + const pos = baba?.sgroups.get(groupId)?.areas[0].p1 + + let gr = null + + useEffect(() => { + const group = functionalGroups + ? functionalGroups.find((g) => g.modifiedStruct.name === id) + : null + if (group) { + gr = group.modifiedStruct.clone() + gr.name = id + timer = setTimeout(() => { + setMolecule(gr) + }, HOVER_DELAY) + } else { + setMolecule(null) + } + return () => clearTimeout(timer) + }, [id]) + + useEffect(() => { + childRef?.current?.forceUpdate() + }, [molecule]) + + let width = 0 + let height = 0 + let rX = 0 + let rY = 0 + if (baba) { + const vbox = restruct.sgroups?.get(groupId)?.item?.areas[0] + if (vbox) { + const start = Scale.obj2scaled(vbox.p0, restruct.render.options) + const end = Scale.obj2scaled(vbox.p1, restruct.render.options) + width = end.x - start.x + height = end.y - start.y + } + const { atomSelectionPlateRadius = 10 } = + restruct.render.options.atomSelectionPlateRadius + const padding = atomSelectionPlateRadius + var pos2 = baba?.sgroups?.get(groupId)?.firstSgroupAtom?.pp + const panelPosition = pos2 + ? Scale.obj2scaled(pos2, restruct.render.options) + : { x: 0, y: 0 } + rX = panelPosition.x - width / 2 - 10 + rY = panelPosition.y + 32 + } + + return ( + molecule && ( +
+ +
+ ) + ) +} + +export default connect((store) => ({ + // settings: (state) => state.options.settings, + // highlight: highlightSelector(store), + id: functionGroupInfoSelector(store) + ? functionGroupInfoSelector(store).id + : null, + x: functionGroupInfoSelector(store) ? functionGroupInfoSelector(store).x : 0, + y: functionGroupInfoSelector(store) ? functionGroupInfoSelector(store).y : 0, + restruct: store.editor?.render?.ctab, + baba: store.editor?.struct(), + groupId: functionGroupInfoSelector(store) + ? functionGroupInfoSelector(store).groupId + : null, + functionalGroups: allSGroupsSelector(store).map((template) => { + const struct = template.struct.clone() + struct.sgroups.delete(0) + return { ...template, modifiedStruct: struct } + }) +}))(InfoPanel) diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less new file mode 100644 index 0000000000..ed2044bd43 --- /dev/null +++ b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less @@ -0,0 +1,9 @@ +.infoPanel svg { + overflow: visible !important; + position: absolute; + padding: 20px; + background: white; + border: 1px solid #b4b9d6; + border-radius: 3px; + pointer-events: none; +} \ No newline at end of file diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx b/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx index 09256ea61d..36dc1d98c7 100644 --- a/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx +++ b/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx @@ -27,6 +27,8 @@ import handIcon from '../../../../../icons/files/hand.svg' import compressedHandIcon from '../../../../../icons/files/compressed-hand.svg' import Cursor from '../Cursor' +import InfoPanel from './InfoPanel' + // TODO: need to update component after making refactoring of store function setupEditor(editor, props, oldProps = {}) { const { struct, tool, toolOpts, options } = props @@ -70,7 +72,9 @@ class StructEditor extends Component { constructor(props) { super(props) this.state = { - enableCursor: false + enableCursor: false, + clientX: 0, + clientY: 0 } this.editorRef = createRef() this.logRef = createRef() @@ -130,7 +134,9 @@ class StructEditor extends Component { case 'move': this.editorRef.current.classList.add(classes.enableCursor) this.setState({ - enableCursor: true + enableCursor: true, + clientX, + clientY }) break case 'disable': @@ -190,6 +196,7 @@ class StructEditor extends Component { onCipChange, className, onConfirm, + onShowInfo, showAttachmentPoints = true, ...props } = this.props @@ -226,6 +233,7 @@ class StructEditor extends Component { )} + ) From bb780b59deed2d4ca83ffcd017be386bb24e98c2 Mon Sep 17 00:00:00 2001 From: Nikita Date: Tue, 13 Dec 2022 16:49:46 +0300 Subject: [PATCH 17/27] =?UTF-8?q?=20=20#1915=20=E2=80=93=20improved=20sear?= =?UTF-8?q?ch=20performance=20in=20template=20dialog=20(#1917)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/script/ui/component/structrender.tsx | 13 ++++++++++++- .../src/script/ui/state/templates/index.js | 2 +- packages/ketcher-react/src/script/ui/utils/index.ts | 12 +++++++----- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/component/structrender.tsx b/packages/ketcher-react/src/script/ui/component/structrender.tsx index ce743b9afe..9dfed7b078 100644 --- a/packages/ketcher-react/src/script/ui/component/structrender.tsx +++ b/packages/ketcher-react/src/script/ui/component/structrender.tsx @@ -30,12 +30,22 @@ function prepareStruct(struct: Struct) { return struct } +/** + * Is used to improve search and opening tab performance in Template Dialog + * Rendering a lot of structures causes great delay + */ +const renderCache = new Map() + function renderStruct( el: HTMLElement | null, struct: Struct | null, options: any = {} ) { if (el && struct) { + if (renderCache.has(struct.name)) { + el.innerHTML = renderCache.get(struct.name) + return + } const preparedStruct = prepareStruct(struct) preparedStruct.initHalfBonds() preparedStruct.initNeighbors() @@ -47,6 +57,7 @@ function renderStruct( }) rnd.setMolecule(preparedStruct) rnd.update(true, options.viewSz) + renderCache.set(struct.name, rnd.clientArea.innerHTML) } } @@ -65,7 +76,7 @@ class StructRender extends Component { } shouldComponentUpdate(previousProps) { - return this.props.id && this.props.id !== previousProps.id + return Boolean(this.props.id && this.props.id !== previousProps.id) } update() { diff --git a/packages/ketcher-react/src/script/ui/state/templates/index.js b/packages/ketcher-react/src/script/ui/state/templates/index.js index 1d466c88eb..c39ac9a633 100644 --- a/packages/ketcher-react/src/script/ui/state/templates/index.js +++ b/packages/ketcher-react/src/script/ui/state/templates/index.js @@ -41,7 +41,7 @@ export function changeGroup(group) { export function changeFilter(filter) { return { type: 'TMPL_CHANGE_FILTER', - data: { filter: filter.trim(), selected: null } // TODO: change this + data: { filter, selected: null } } } diff --git a/packages/ketcher-react/src/script/ui/utils/index.ts b/packages/ketcher-react/src/script/ui/utils/index.ts index 1869115391..3e47065a3c 100644 --- a/packages/ketcher-react/src/script/ui/utils/index.ts +++ b/packages/ketcher-react/src/script/ui/utils/index.ts @@ -34,13 +34,14 @@ export function greekify(str: string): string { return str.replace(greekRe, (sym) => GREEK_SIMBOLS[sym]) } -export function filterLib(lib, filter) { +export function filterLib(lib, filter: string) { console.warn('Filter', filter) - const re = new RegExp(escapeRegExp(greekify(filter)), 'i') + const trimmedFilter = filter.trim() + const re = new RegExp(escapeRegExp(greekify(trimmedFilter)), 'i') return flow( _filter( (item: any) => - !filter || + !trimmedFilter || re.test(greekify(item.struct.name)) || re.test(greekify(item.props.group)) ), @@ -54,7 +55,8 @@ export function filterLib(lib, filter) { export function filterFGLib(lib, filter) { console.warn('Filter', filter) - const re = new RegExp(escapeRegExp(greekify(filter)), 'i') + const trimmedFilter = filter.trim() + const re = new RegExp(escapeRegExp(greekify(trimmedFilter)), 'i') const searchFunction = (item) => { const fields = [ item.struct.name, @@ -64,7 +66,7 @@ export function filterFGLib(lib, filter) { return fields.some((field) => re.test(greekify(field))) } return flow( - _filter((item: any) => !filter || searchFunction(item)), + _filter((item: any) => !trimmedFilter || searchFunction(item)), reduce((res, item) => { if (!res[item.props.group]) res[item.props.group] = [item] else res[item.props.group].push(item) From 8e0545a48f8fbfdf58bac07c0ba020d6c92dbaa7 Mon Sep 17 00:00:00 2001 From: porcelain11 <112183450+porcelain11@users.noreply.github.com> Date: Wed, 14 Dec 2022 19:11:03 +0500 Subject: [PATCH 18/27] #1864 If the coordinates have a centroid that is far from zero, the molecule placed far offscreen (#1901) * #1864 refactor Render class * #1864 Update setScrollOffset method * #1864 Small fixes on comments --- .../editor/operations/CanvasLoad.ts | 5 +- .../src/application/render/raphaelRender.js | 250 --------------- .../src/application/render/raphaelRender.ts | 290 ++++++++++++++++++ .../application/render/restruct/restruct.ts | 12 +- .../ketcher-react/src/script/editor/Editor.ts | 8 +- .../src/script/editor/tool/paste.ts | 5 +- 6 files changed, 310 insertions(+), 260 deletions(-) delete mode 100644 packages/ketcher-core/src/application/render/raphaelRender.js create mode 100644 packages/ketcher-core/src/application/render/raphaelRender.ts diff --git a/packages/ketcher-core/src/application/editor/operations/CanvasLoad.ts b/packages/ketcher-core/src/application/editor/operations/CanvasLoad.ts index 8abb792a70..738104fdb4 100644 --- a/packages/ketcher-core/src/application/editor/operations/CanvasLoad.ts +++ b/packages/ketcher-core/src/application/editor/operations/CanvasLoad.ts @@ -32,7 +32,10 @@ export class CanvasLoad extends BaseOperation { execute(restruct: ReStruct) { const oldStruct = restruct.molecule restruct.clearVisels() // TODO: What is it? - restruct.render.setMolecule(this.data.struct) + if (this.data.struct) { + restruct.render.setMolecule(this.data.struct) + } + this.data.struct = oldStruct } diff --git a/packages/ketcher-core/src/application/render/raphaelRender.js b/packages/ketcher-core/src/application/render/raphaelRender.js deleted file mode 100644 index abd280cd60..0000000000 --- a/packages/ketcher-core/src/application/render/raphaelRender.js +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************** - * Copyright 2021 EPAM Systems - * - * 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. - ***************************************************************************/ - -import { Box2Abs, Struct, Vec2 } from 'domain/entities' - -import Raphael from './raphael-ext' -import { ReStruct } from './restruct' -import { Scale } from 'domain/helpers' -import defaultOptions from './options' -import draw from './draw' - -export function Render(clientArea, opt) { - let renderWidth = opt.width || clientArea.clientWidth - 10 - let renderHeight = opt.height || clientArea.clientHeight - 10 - renderWidth = renderWidth > 0 ? renderWidth : 0 - renderHeight = renderHeight > 0 ? renderHeight : 0 - - this.userOpts = opt - this.clientArea = clientArea - this.paper = new Raphael(clientArea, renderWidth, renderHeight) - this.sz = Vec2.ZERO - this.ctab = new ReStruct(new Struct(), this) - this.options = defaultOptions(this.userOpts) -} - -Render.prototype.updateOptions = function (opts) { - try { - const passedOptions = JSON.parse(opts) - if (passedOptions && typeof passedOptions === 'object') { - this.options = { ...this.options, ...passedOptions } - return this.options - } - } catch (e) { - console.log('Not a valid settings object') - } - return false -} - -Render.prototype.selectionPolygon = function (r) { - return draw.selectionPolygon(this.paper, r, this.options) -} - -Render.prototype.selectionLine = function (p0, p1) { - return draw.selectionLine(this.paper, p0, p1, this.options) -} - -Render.prototype.selectionRectangle = function (p0, p1) { - return draw.selectionRectangle(this.paper, p0, p1, this.options) -} - -Render.prototype.view2obj = function (p, isRelative) { - let scroll = this.scrollPos() - if (!this.useOldZoom) { - p = p.scaled(1 / this.options.zoom) - scroll = scroll.scaled(1 / this.options.zoom) - } - p = isRelative ? p : p.add(scroll).sub(this.options.offset) - return Scale.scaled2obj(p, this.options) -} - -Render.prototype.obj2view = function (v, isRelative) { - let p = Scale.obj2scaled(v, this.options) - p = isRelative - ? p - : p - .add(this.options.offset) - .sub(this.scrollPos().scaled(1 / this.options.zoom)) - if (!this.useOldZoom) p = p.scaled(this.options.zoom) - return p -} - -Render.prototype.scrollPos = function () { - return new Vec2(this.clientArea.scrollLeft, this.clientArea.scrollTop) -} - -Render.prototype.page2obj = function (event) { - const clientArea = this.clientArea - - const { top: offsetTop, left: offsetLeft } = - clientArea.getBoundingClientRect() - - const pp = new Vec2(event.clientX - offsetLeft, event.clientY - offsetTop) - return this.view2obj(pp) -} - -Render.prototype.setPaperSize = function (sz) { - this.sz = sz - this.paper.setSize(sz.x * this.options.zoom, sz.y * this.options.zoom) - this.setViewBox(this.options.zoom) -} - -Render.prototype.setOffset = function (newoffset) { - const delta = new Vec2( - newoffset.x - this.options.offset.x, - newoffset.y - this.options.offset.y - ) - this.clientArea.scrollLeft += delta.x - this.clientArea.scrollTop += delta.y - this.options.offset = newoffset -} - -Render.prototype.setZoom = function (zoom) { - // when scaling the canvas down it may happen that the scaled canvas is smaller than the view window - // don't forget to call setScrollOffset after zooming (or use extendCanvas directly) - this.options.zoom = zoom - this.paper.setSize(this.sz.x * zoom, this.sz.y * zoom) - this.setViewBox(zoom) -} - -function calcExtend(sSz, x0, y0, x1, y1) { - // eslint-disable-line max-params - let ex = x0 < 0 ? -x0 : 0 - let ey = y0 < 0 ? -y0 : 0 - - if (sSz.x < x1) ex += x1 - sSz.x - if (sSz.y < y1) ey += y1 - sSz.y - return new Vec2(ex, ey) -} - -Render.prototype.setScrollOffset = function (x, y) { - const clientArea = this.clientArea - const cx = clientArea.clientWidth - const cy = clientArea.clientHeight - const e = calcExtend( - this.sz.scaled(this.options.zoom), - x, - y, - cx + x, - cy + y - ).scaled(1 / this.options.zoom) - if (e.x > 0 || e.y > 0) { - this.setPaperSize(this.sz.add(e)) - const d = new Vec2(x < 0 ? -x : 0, y < 0 ? -y : 0).scaled( - 1 / this.options.zoom - ) - if (d.x > 0 || d.y > 0) { - this.ctab.translate(d) - this.setOffset(this.options.offset.add(d)) - } - } - clientArea.scrollLeft = x - clientArea.scrollTop = y - // TODO: store drag position in scaled systems - // scrollLeft = clientArea.scrollLeft; - // scrollTop = clientArea.scrollTop; - this.update(false) -} - -Render.prototype.setScale = function (z) { - if (this.options.offset) { - this.options.offset = this.options.offset.scaled(1 / z).scaled(z) - } - this.userOpts.scale *= z - this.options = null - this.update(true) -} - -Render.prototype.setViewBox = function (z) { - if (!this.useOldZoom) { - this.paper.canvas.setAttribute( - 'viewBox', - '0 0 ' + this.sz.x + ' ' + this.sz.y - ) - } else this.setScale(z) -} - -Render.prototype.setMolecule = function (ctab) { - this.paper.clear() - this.ctab = new ReStruct(ctab, this) - this.options.offset = new Vec2() - this.update(false) -} - -Render.prototype.update = function (force = false, viewSz = null) { - // eslint-disable-line max-statements - viewSz = - viewSz || - new Vec2( - this.clientArea.clientWidth || 100, - this.clientArea.clientHeight || 100 - ) - - const changes = this.ctab.update(force) - this.ctab.setSelection() // [MK] redraw the selection bits where necessary - if (changes) { - const sf = this.options.scale - const bb = this.ctab - .getVBoxObj() - .transform(Scale.obj2scaled, this.options) - .translate(this.options.offset || new Vec2()) - - if (!this.options.autoScale) { - const ext = Vec2.UNIT.scaled(sf) - const eb = bb.sz().length() > 0 ? bb.extend(ext, ext) : bb - const vb = new Box2Abs( - this.scrollPos(), - viewSz.scaled(1 / this.options.zoom).sub(Vec2.UNIT.scaled(20)) - ) - const cb = Box2Abs.union(vb, eb) - if (!this.oldCb) this.oldCb = new Box2Abs() - - const sz = cb.sz().floor() - const delta = this.oldCb.p0.sub(cb.p0).ceil() - this.oldBb = bb - if (!this.sz || sz.x !== this.sz.x || sz.y !== this.sz.y) { - this.setPaperSize(sz) - } - - this.options.offset = this.options.offset || new Vec2() - if (delta.x !== 0 || delta.y !== 0) { - this.setOffset(this.options.offset.add(delta)) - this.ctab.translate(delta) - } - } else { - const sz1 = bb.sz() - const marg = this.options.autoScaleMargin - const mv = new Vec2(marg, marg) - const csz = viewSz - if (marg && (csz.x < 2 * marg + 1 || csz.y < 2 * marg + 1)) { - throw new Error('View box too small for the given margin') - } - let rescale = - this.options.rescaleAmount || - Math.max(sz1.x / (csz.x - 2 * marg), sz1.y / (csz.y - 2 * marg)) - if (this.options.maxBondLength / rescale > 1.0) rescale = 1.0 - const sz2 = sz1.add(mv.scaled(2 * rescale)) - /* eslint-disable no-mixed-operators */ - this.paper.setViewBox( - bb.pos().x - marg * rescale - (csz.x * rescale - sz2.x) / 2, - bb.pos().y - marg * rescale - (csz.y * rescale - sz2.y) / 2, - csz.x * rescale, - csz.y * rescale - ) - /* eslint-enable no-mixed-operators */ - } - } -} diff --git a/packages/ketcher-core/src/application/render/raphaelRender.ts b/packages/ketcher-core/src/application/render/raphaelRender.ts new file mode 100644 index 0000000000..c652b63cfd --- /dev/null +++ b/packages/ketcher-core/src/application/render/raphaelRender.ts @@ -0,0 +1,290 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ + +import { Box2Abs, Struct, Vec2 } from 'domain/entities' + +import Raphael from './raphael-ext' +import { ReStruct } from './restruct' +import { Scale } from 'domain/helpers' +import defaultOptions from './options' +import draw from './draw' +import { RaphaelPaper } from 'raphael' +// TODO: add types for options +// import { RenderOptions } from './render.types' + +function calcExtend( + scaledSz: Vec2, + x0: number, + y0: number, + x1: number, + y1: number +) { + // eslint-disable-line max-params + let ex = x0 < 0 ? -x0 : 0 + let ey = y0 < 0 ? -y0 : 0 + + if (scaledSz.x < x1) { + ex += x1 - scaledSz.x + } + if (scaledSz.y < y1) { + ey += y1 - scaledSz.y + } + + return new Vec2(ex, ey) +} + +class Render { + public clientArea: HTMLElement + private userOpts: any + public paper: RaphaelPaper + private sz: Vec2 + public ctab: ReStruct + public options: any + private renderWidth: number + private renderHeight: number + private useOldZoom: boolean + private oldCb: Box2Abs | null + + constructor(clientArea: HTMLElement, opt: any) { + this.userOpts = opt + this.clientArea = clientArea + this.renderWidth = + clientArea.clientWidth - 10 > 0 ? clientArea.clientWidth - 10 : 0 + this.renderHeight = + clientArea.clientHeight - 10 > 0 ? clientArea.clientHeight - 10 : 0 + this.paper = new Raphael(clientArea, this.renderWidth, this.renderHeight) + this.sz = Vec2.ZERO + this.ctab = new ReStruct(new Struct(), this) + this.options = defaultOptions(this.userOpts) + this.useOldZoom = false // where it comes from? + this.oldCb = null // where it comes from? + } + + updateOptions(opts) { + try { + const passedOptions = JSON.parse(opts) + if (passedOptions && typeof passedOptions === 'object') { + this.options = { ...this.options, ...passedOptions } + return this.options + } + } catch (e) { + console.log('Not a valid settings object') + } + return false + } + + selectionPolygon(r) { + return draw.selectionPolygon(this.paper, r, this.options) + } + + selectionLine(p0: Vec2, p1: Vec2) { + return draw.selectionLine(this.paper, p0, p1, this.options) + } + + selectionRectangle(p0: Vec2, p1: Vec2) { + return draw.selectionRectangle(this.paper, p0, p1, this.options) + } + + getScrollPos() { + return new Vec2(this.clientArea.scrollLeft, this.clientArea.scrollTop) + } + + view2obj(p: Vec2, isRelative?: boolean) { + let scroll = this.getScrollPos() + if (!this.useOldZoom) { + p = p.scaled(1 / this.options.zoom) + scroll = scroll.scaled(1 / this.options.zoom) + } + p = isRelative ? p : p.add(scroll).sub(this.options.offset) + return Scale.scaled2obj(p, this.options) + } + + obj2view(v: Vec2, isRelative: boolean) { + let p = Scale.obj2scaled(v, this.options) + p = isRelative + ? p + : p + .add(this.options.offset) + .sub(this.getScrollPos().scaled(1 / this.options.zoom)) + + if (!this.useOldZoom) { + p = p.scaled(this.options.zoom) + } + + return p + } + + page2obj(event: MouseEvent) { + const clientArea = this.clientArea + const { top: offsetTop, left: offsetLeft } = + clientArea.getBoundingClientRect() + + const pp = new Vec2(event.clientX - offsetLeft, event.clientY - offsetTop) + + return this.view2obj(pp) + } + + setViewBox(z: number) { + if (!this.useOldZoom) { + this.paper.canvas.setAttribute( + 'viewBox', + '0 0 ' + this.sz.x + ' ' + this.sz.y + ) + } else this.setScale(z) + } + + setScale(z: number) { + if (this.options.offset) { + this.options.offset = this.options.offset.scaled(1 / z).scaled(z) + } + this.userOpts.scale *= z + this.options = null + this.update(true) + } + + setPaperSize(sz: Vec2) { + this.sz = sz + this.paper.setSize(sz.x * this.options.zoom, sz.y * this.options.zoom) + this.setViewBox(this.options.zoom) + } + + setZoom(zoom: number) { + // when scaling the canvas down it may happen that the scaled canvas is smaller than the view window + // don't forget to call setScrollOffset after zooming (or use extendCanvas directly) + this.options.zoom = zoom + this.paper.setSize(this.sz.x * zoom, this.sz.y * zoom) + this.setViewBox(zoom) + } + + setOffset(newoffset: Vec2) { + const delta = new Vec2( + newoffset.x - this.options.offset.x, + newoffset.y - this.options.offset.y + ) + this.clientArea.scrollLeft += delta.x + this.clientArea.scrollTop += delta.y + this.options.offset = newoffset + } + + setMolecule(struct: Struct) { + this.paper.clear() + this.ctab = new ReStruct(struct, this) + this.options.offset = new Vec2() + this.update(false) + } + + setScrollOffset(x: number, y: number) { + const clientArea = this.clientArea + const cx = clientArea.clientWidth + const cy = clientArea.clientHeight + const e = calcExtend( + this.sz.scaled(this.options.zoom), + x, + y, + cx + x, + cy + y + ).scaled(1 / this.options.zoom) + if (e.x > 0 || e.y > 0) { + this.setPaperSize(this.sz.add(e)) + const d = new Vec2(x < 0 ? -x : 0, y < 0 ? -y : 0).scaled( + 1 / this.options.zoom + ) + if (d.x > 0 || d.y > 0) { + this.ctab.translate(d) + this.setOffset(this.options.offset.add(d)) + } + } + + clientArea.scrollLeft = x * this.options.scale + clientArea.scrollTop = y * this.options.scale + } + + update(force = false, viewSz: Vec2 | null = null) { + viewSz = + viewSz || + new Vec2( + this.clientArea.clientWidth || 100, + this.clientArea.clientHeight || 100 + ) + + const changes = this.ctab.update(force) + this.ctab.setSelection() // [MK] redraw the selection bits where necessary + + if (changes) { + const boundingBox = this.ctab + ?.getVBoxObj() + ?.transform(Scale.obj2scaled, this.options) + .translate(this.options.offset || new Vec2()) + + if (!this.options.autoScale && boundingBox) { + const ext = Vec2.UNIT.scaled(this.options.scale) + const extendedBox = + boundingBox.sz().length() > 0 + ? boundingBox.extend(ext, ext) + : boundingBox + const viewBox = new Box2Abs( + this.getScrollPos(), + viewSz.scaled(1 / this.options.zoom).sub(Vec2.UNIT.scaled(20)) + ) + const cb = Box2Abs.union(viewBox, extendedBox) + if (!this.oldCb) { + this.oldCb = new Box2Abs() + } + + const sz = cb.sz().floor() + const delta = this.oldCb.p0.sub(cb.p0).ceil() + // TODO: do we need this.oldBb? Seem it's not in use + // this.oldBb = bb + if (!this.sz || sz.x !== this.sz.x || sz.y !== this.sz.y) { + this.setPaperSize(sz) + } + + this.options.offset = this.options.offset || new Vec2() + if (delta.x !== 0 || delta.y !== 0) { + this.setOffset(this.options.offset.add(delta)) + this.ctab.translate(delta) + } + } else { + if (!boundingBox) { + return + } + const sz1 = boundingBox.sz() + const marg = this.options.autoScaleMargin + const mv = new Vec2(marg, marg) + const csz = viewSz + if (csz.x < 2 * marg + 1 || csz.y < 2 * marg + 1) { + throw new Error('View box too small for the given margin') + } + let rescale = Math.max( + sz1.x / (csz.x - 2 * marg), + sz1.y / (csz.y - 2 * marg) + ) + if (this.options.maxBondLength / rescale > 1.0) rescale = 1.0 + const sz2 = sz1.add(mv.scaled(2 * rescale)) + /* eslint-disable no-mixed-operators */ + this.paper.setViewBox( + boundingBox.pos().x - marg * rescale - (csz.x * rescale - sz2.x) / 2, + boundingBox.pos().y - marg * rescale - (csz.y * rescale - sz2.y) / 2, + csz.x * rescale, + csz.y * rescale + ) + /* eslint-enable no-mixed-operators */ + } + } + } +} + +export { Render } diff --git a/packages/ketcher-core/src/application/render/restruct/restruct.ts b/packages/ketcher-core/src/application/render/restruct/restruct.ts index 97f4db682c..1f875b7944 100644 --- a/packages/ketcher-core/src/application/render/restruct/restruct.ts +++ b/packages/ketcher-core/src/application/render/restruct/restruct.ts @@ -308,7 +308,7 @@ class ReStruct { }) } - getVBoxObj(selection): Box2Abs | null { + getVBoxObj(selection?): Box2Abs | null { selection = selection || {} if (isSelectionEmpty(selection)) { @@ -575,8 +575,7 @@ class ReStruct { }) } - setSelection(selection) { - const redraw = arguments.length === 0 // render.update only + setSelection(selection?) { const atoms: { selected: boolean; sgroup: number }[] = [] Object.keys(ReStruct.maps).forEach((map) => { @@ -605,9 +604,10 @@ class ReStruct { ) item.selected = sGroupAtoms.length > 0 && sGroupAtoms[0].selected } - const selected = redraw - ? item.selected - : selection && selection[map] && selection[map].indexOf(id) > -1 + + const selected = selection?.[map] + ? selection[map].indexOf(id) > -1 + : item.selected this.showItemSelection(item, selected) }) diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index 92ed7c1d4d..279ad8578a 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -612,12 +612,16 @@ function domEventSetup(editor: Editor, clientArea) { }) } -function recoordinate(editor: Editor, rp /* , vp */) { +function recoordinate(editor: Editor, rp?: Vec2 /* , vp */) { // rp is a point in scaled coordinates, which will be positioned // vp is the point where the reference point should now be (in view coordinates) // or the center if not set console.assert(rp, 'Reference point not specified') - editor.render.setScrollOffset(0, 0) + if (rp) { + editor.render.setScrollOffset(rp.x, rp.y) + } else { + editor.render.setScrollOffset(0, 0) + } } function getStructCenter(ReStruct, selection?) { diff --git a/packages/ketcher-react/src/script/editor/tool/paste.ts b/packages/ketcher-react/src/script/editor/tool/paste.ts index 2e28eee81f..2747cc5645 100644 --- a/packages/ketcher-react/src/script/editor/tool/paste.ts +++ b/packages/ketcher-react/src/script/editor/tool/paste.ts @@ -39,7 +39,10 @@ class PasteTool { const { clientHeight, clientWidth } = rnd.clientArea const point = this.editor.lastEvent ? rnd.page2obj(this.editor.lastEvent) - : rnd.page2obj({ pageX: clientWidth / 2, pageY: clientHeight / 2 }) + : rnd.page2obj({ + pageX: clientWidth / 2, + pageY: clientHeight / 2 + } as MouseEvent) const [action, pasteItems] = fromPaste(rnd.ctab, this.struct, point) this.action = action From 9c8298161370d967553611311d59c0a79c11e785 Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 15 Dec 2022 12:14:11 +0300 Subject: [PATCH 19/27] =?UTF-8?q?#1920=20=E2=80=93=20added=20abbreviation?= =?UTF-8?q?=20to=20Struct,=20fixed=20isSaltOrSolvent=20check=20(#1927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ketcher-core/src/domain/entities/functionalGroup.ts | 8 ++++++-- packages/ketcher-core/src/domain/entities/sgroup.ts | 5 ++++- packages/ketcher-core/src/domain/entities/struct.ts | 2 ++ packages/ketcher-react/src/script/editor/tool/bond.ts | 6 ++++-- .../src/script/ui/state/saltsAndSolvents/index.ts | 5 ++++- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/ketcher-core/src/domain/entities/functionalGroup.ts b/packages/ketcher-core/src/domain/entities/functionalGroup.ts index 637abdbb65..32276823f6 100644 --- a/packages/ketcher-core/src/domain/entities/functionalGroup.ts +++ b/packages/ketcher-core/src/domain/entities/functionalGroup.ts @@ -46,9 +46,13 @@ export class FunctionalGroup { static isFunctionalGroup(sgroup): boolean { const provider = FunctionalGroupsProvider.getInstance() const types = provider.getFunctionalGroupsList() + const { + data: { name }, + type + } = sgroup return ( - types.some((type) => type.name === sgroup.data.name) && - sgroup.type === 'SUP' + type === 'SUP' && + (types.some((type) => type.name === name) || SGroup.isSaltOrSolvent(name)) ) } diff --git a/packages/ketcher-core/src/domain/entities/sgroup.ts b/packages/ketcher-core/src/domain/entities/sgroup.ts index 171cf00f9d..089801cb39 100644 --- a/packages/ketcher-core/src/domain/entities/sgroup.ts +++ b/packages/ketcher-core/src/domain/entities/sgroup.ts @@ -220,7 +220,10 @@ export class SGroup { static isSaltOrSolvent(moleculeName: string): boolean { const saltsAndSolventsProvider = SaltsAndSolventsProvider.getInstance() const saltsAndSolvents = saltsAndSolventsProvider.getSaltsAndSolventsList() - return saltsAndSolvents.some(({ name }) => name === moleculeName) + return saltsAndSolvents.some( + ({ name, abbreviation }) => + name === moleculeName || moleculeName === abbreviation + ) } static isAtomInSaltOrSolvent( diff --git a/packages/ketcher-core/src/domain/entities/struct.ts b/packages/ketcher-core/src/domain/entities/struct.ts index 67b69c0ad5..c76d9be480 100644 --- a/packages/ketcher-core/src/domain/entities/struct.ts +++ b/packages/ketcher-core/src/domain/entities/struct.ts @@ -60,6 +60,7 @@ export class Struct { frags: Pool rgroups: Pool name: string + abbreviation?: string sGroupForest: SGroupForest simpleObjects: Pool texts: Pool @@ -78,6 +79,7 @@ export class Struct { this.frags = new Pool() this.rgroups = new Pool() this.name = '' + this.abbreviation = '' this.sGroupForest = new SGroupForest() this.simpleObjects = new Pool() this.texts = new Pool() diff --git a/packages/ketcher-react/src/script/editor/tool/bond.ts b/packages/ketcher-react/src/script/editor/tool/bond.ts index c4be830368..2392cac74c 100644 --- a/packages/ketcher-react/src/script/editor/tool/bond.ts +++ b/packages/ketcher-react/src/script/editor/tool/bond.ts @@ -237,7 +237,7 @@ class BondTool { } } // don't rotate the bond if the distance between the start and end point is too small - if (dist > 0.3) + if (dist > 0.3) { dragCtx.action = fromBondAddition( rnd.ctab, this.bondProps, @@ -246,7 +246,9 @@ class BondTool { beginPos, endPos )[0] - else delete dragCtx.action + } else { + delete dragCtx.action + } this.editor.update(dragCtx.action, true) return true } diff --git a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts index 44bdb98c53..35f85390f2 100644 --- a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts +++ b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts @@ -63,7 +63,10 @@ export function initSaltsAndSolventsTemplates(baseUrl: string) { const text = await prefetchStatic(url) const templates = sdfSerializer.deserialize(text) const saltsAndSolvents = templates.reduce( - (acc: Struct[], { struct }) => [...acc, struct], + (acc: Struct[], { struct, props }) => { + acc.push({ ...struct, abbreviation: props.abbreviation } as Struct) + return acc + }, [] ) saltsAndSolventsProvider.setSaltsAndSolventsList(saltsAndSolvents) From c5d9ba0644c99cbb4e9dd9b648f98e9a728f32c9 Mon Sep 17 00:00:00 2001 From: KonstantinEpam23 <101649391+KonstantinEpam23@users.noreply.github.com> Date: Thu, 15 Dec 2022 13:57:31 +0300 Subject: [PATCH 20/27] #1921: Hovering over some functional groups crops the expanded view of it (#1923) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #1921: refactor info panel and fix bug with cropped expanded molecules * #1921: small tweak * #1921: add more tools * #1921: fix zoom * #1921: review comments * #1920 – added abbreviation to Struct, fixed isSaltOrSolvent check * #1912: fix missing first atom in sGroup * #1912: fix showing popup for salts and solvents * #1912: small tweak * #1912: fix bug with determining salts * #1912: fix merge Co-authored-by: Nikita_Vozisov --- .../src/application/render/raphaelRender.ts | 29 +-- .../src/domain/entities/functionalGroup.ts | 12 +- .../src/domain/entities/sgroup.ts | 1 + .../ketcher-react/src/script/editor/Editor.ts | 40 ++--- .../src/script/editor/tool/atom.ts | 4 +- .../src/script/editor/tool/bond.ts | 6 +- .../src/script/editor/tool/chain.ts | 2 +- .../src/script/editor/tool/charge.ts | 2 +- .../src/script/editor/tool/reactionarrow.ts | 2 +- .../src/script/editor/tool/text.ts | 2 +- .../src/script/ui/component/structrender.tsx | 8 +- .../src/script/ui/state/editor/index.js | 15 +- .../script/ui/state/saltsAndSolvents/index.ts | 3 +- .../components/StructEditor/InfoPanel.jsx | 166 ------------------ .../StructEditor/InfoPanel.module.less | 9 +- .../components/StructEditor/InfoPanel.tsx | 160 +++++++++++++++++ .../components/StructEditor/StructEditor.jsx | 1 - 17 files changed, 239 insertions(+), 223 deletions(-) delete mode 100644 packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx create mode 100644 packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.tsx diff --git a/packages/ketcher-core/src/application/render/raphaelRender.ts b/packages/ketcher-core/src/application/render/raphaelRender.ts index c652b63cfd..c68a1abc49 100644 --- a/packages/ketcher-core/src/application/render/raphaelRender.ts +++ b/packages/ketcher-core/src/application/render/raphaelRender.ts @@ -262,22 +262,31 @@ class Render { return } const sz1 = boundingBox.sz() - const marg = this.options.autoScaleMargin - const mv = new Vec2(marg, marg) + const { autoScaleMargin, rescaleAmount, maxBondLength } = this.options + const mv = new Vec2(autoScaleMargin, autoScaleMargin) const csz = viewSz - if (csz.x < 2 * marg + 1 || csz.y < 2 * marg + 1) { + if ( + autoScaleMargin && + (csz.x < 2 * autoScaleMargin + 1 || csz.y < 2 * autoScaleMargin + 1) + ) { throw new Error('View box too small for the given margin') } - let rescale = Math.max( - sz1.x / (csz.x - 2 * marg), - sz1.y / (csz.y - 2 * marg) - ) - if (this.options.maxBondLength / rescale > 1.0) rescale = 1.0 + let rescale = + rescaleAmount || + Math.max( + sz1.x / (csz.x - 2 * autoScaleMargin), + sz1.y / (csz.y - 2 * autoScaleMargin) + ) + if (maxBondLength / rescale > 1.0) rescale = 1.0 const sz2 = sz1.add(mv.scaled(2 * rescale)) /* eslint-disable no-mixed-operators */ this.paper.setViewBox( - boundingBox.pos().x - marg * rescale - (csz.x * rescale - sz2.x) / 2, - boundingBox.pos().y - marg * rescale - (csz.y * rescale - sz2.y) / 2, + boundingBox.pos().x - + autoScaleMargin * rescale - + (csz.x * rescale - sz2.x) / 2, + boundingBox.pos().y - + autoScaleMargin * rescale - + (csz.y * rescale - sz2.y) / 2, csz.x * rescale, csz.y * rescale ) diff --git a/packages/ketcher-core/src/domain/entities/functionalGroup.ts b/packages/ketcher-core/src/domain/entities/functionalGroup.ts index 32276823f6..22ad8860f6 100644 --- a/packages/ketcher-core/src/domain/entities/functionalGroup.ts +++ b/packages/ketcher-core/src/domain/entities/functionalGroup.ts @@ -45,21 +45,25 @@ export class FunctionalGroup { static isFunctionalGroup(sgroup): boolean { const provider = FunctionalGroupsProvider.getInstance() - const types = provider.getFunctionalGroupsList() + const functionalGroups = provider.getFunctionalGroupsList() const { data: { name }, type } = sgroup return ( type === 'SUP' && - (types.some((type) => type.name === name) || SGroup.isSaltOrSolvent(name)) + (functionalGroups.some((type) => type.name === name) || + SGroup.isSaltOrSolvent(name)) ) } static getFunctionalGroupByName(searchName: string): Struct | null { const provider = FunctionalGroupsProvider.getInstance() - const types = provider.getFunctionalGroupsList() - return types.find((fnGroup) => fnGroup.name === searchName) || null + const functionalGroups = provider.getFunctionalGroupsList() + const foundGroup = functionalGroups.find(({ name, abbreviation }) => { + return name === searchName || abbreviation === searchName + }) + return foundGroup || null } static atomsInFunctionalGroup(functionalGroups, atom): number | null { diff --git a/packages/ketcher-core/src/domain/entities/sgroup.ts b/packages/ketcher-core/src/domain/entities/sgroup.ts index 089801cb39..1139642cb1 100644 --- a/packages/ketcher-core/src/domain/entities/sgroup.ts +++ b/packages/ketcher-core/src/domain/entities/sgroup.ts @@ -77,6 +77,7 @@ export class SGroup { neiAtoms: any pp: Vec2 | null data: any + firstSgroupAtom: any constructor(type: string) { this.type = type diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index 279ad8578a..8ddbf03fed 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -210,9 +210,9 @@ class Editor implements KetcherEditor { const tool = new toolMap[name](this, opts) - // hide icon if not AtomToll chosen - if (name !== 'atom') { - this.render.paper.getById('atomHoverIcon')?.hide() + const isAtomToolChosen = name === 'atom' + if (!isAtomToolChosen) { + this.hoverIcon.hide() } if (!tool || tool.isNotActiveTool) { @@ -349,7 +349,7 @@ class Editor implements KetcherEditor { hover(ci: any, newTool?: any, event?: PointerEvent) { const tool = newTool || this._tool // eslint-disable-line - let highlight: any = false + let infoPanelData: any = null if ( 'ci' in tool && @@ -363,25 +363,25 @@ class Editor implements KetcherEditor { if (!event) return - const myCi = this.findItem(event, ['sgroups', 'functionalGroups']) - if (myCi) { - if (myCi.map === 'sgroups' || myCi.map === 'functionalGroups') { - const sGroup = this.struct()?.sgroups.get(myCi.id) - if (sGroup && !sGroup.data.expanded) { - const groupName = sGroup.data.name - const groupStruct = - FunctionalGroup.getFunctionalGroupByName(groupName) - highlight = { - group: groupStruct, - x: event.clientX, - y: event.clientY, - groupId: myCi.id - } + const checkFunctionGroupTypes = ['sgroups', 'functionalGroups'] + const closestCollapsibleStructures = this.findItem( + event, + checkFunctionGroupTypes + ) + if (closestCollapsibleStructures) { + const sGroup = this.struct()?.sgroups.get(closestCollapsibleStructures.id) + if (sGroup && !sGroup.data.expanded) { + const groupName = sGroup.data.name + const groupStruct = FunctionalGroup.getFunctionalGroupByName(groupName) + infoPanelData = { + groupStruct, + event, + sGroup } } } - if (highlight) { - this.event.showInfo.dispatch(highlight) + if (infoPanelData) { + this.event.showInfo.dispatch(infoPanelData) } else { this.event.showInfo.dispatch(null) } diff --git a/packages/ketcher-react/src/script/editor/tool/atom.ts b/packages/ketcher-react/src/script/editor/tool/atom.ts index 48e91ee19f..569c968ad4 100644 --- a/packages/ketcher-react/src/script/editor/tool/atom.ts +++ b/packages/ketcher-react/src/script/editor/tool/atom.ts @@ -154,7 +154,9 @@ class AtomTool { y: layerY - height / 2 }) this.editor.hover( - this.editor.findItem(event, ['atoms', 'functionalGroups']) + this.editor.findItem(event, ['atoms', 'functionalGroups']), + null, + event ) return } diff --git a/packages/ketcher-react/src/script/editor/tool/bond.ts b/packages/ketcher-react/src/script/editor/tool/bond.ts index 2392cac74c..ea58033434 100644 --- a/packages/ketcher-react/src/script/editor/tool/bond.ts +++ b/packages/ketcher-react/src/script/editor/tool/bond.ts @@ -253,7 +253,11 @@ class BondTool { return true } } - this.editor.hover(this.editor.findItem(event, ['atoms', 'bonds'])) + this.editor.hover( + this.editor.findItem(event, ['atoms', 'bonds']), + null, + event + ) return true } diff --git a/packages/ketcher-react/src/script/editor/tool/chain.ts b/packages/ketcher-react/src/script/editor/tool/chain.ts index 51c585a346..e9f4965615 100644 --- a/packages/ketcher-react/src/script/editor/tool/chain.ts +++ b/packages/ketcher-react/src/script/editor/tool/chain.ts @@ -124,7 +124,7 @@ class ChainTool { const restruct = editor.render.ctab const dragCtx = this.dragCtx - editor.hover(this.editor.findItem(event, ['atoms', 'bonds'])) + editor.hover(this.editor.findItem(event, ['atoms', 'bonds']), null, event) if (!dragCtx) { return true } diff --git a/packages/ketcher-react/src/script/editor/tool/charge.ts b/packages/ketcher-react/src/script/editor/tool/charge.ts index 456cf8ccbd..27c8a78e4c 100644 --- a/packages/ketcher-react/src/script/editor/tool/charge.ts +++ b/packages/ketcher-react/src/script/editor/tool/charge.ts @@ -38,7 +38,7 @@ class ChargeTool { ) { this.editor.hover(ci) } else { - this.editor.hover(null) + this.editor.hover(null, null, event) } return true } diff --git a/packages/ketcher-react/src/script/editor/tool/reactionarrow.ts b/packages/ketcher-react/src/script/editor/tool/reactionarrow.ts index 83e25dd9b1..47dc2b7c63 100644 --- a/packages/ketcher-react/src/script/editor/tool/reactionarrow.ts +++ b/packages/ketcher-react/src/script/editor/tool/reactionarrow.ts @@ -107,7 +107,7 @@ class ReactionArrowTool { } } else { const items = this.editor.findItem(event, ['rxnArrows']) - this.editor.hover(items) + this.editor.hover(items, null, event) } } diff --git a/packages/ketcher-react/src/script/editor/tool/text.ts b/packages/ketcher-react/src/script/editor/tool/text.ts index caca00e7ff..6b57c36a4d 100644 --- a/packages/ketcher-react/src/script/editor/tool/text.ts +++ b/packages/ketcher-react/src/script/editor/tool/text.ts @@ -68,7 +68,7 @@ class TextTool { ) this.editor.update(this.dragCtx.action, true) } else { - this.editor.hover(this.editor.findItem(event, ['texts'])) + this.editor.hover(this.editor.findItem(event, ['texts']), null, event) } } diff --git a/packages/ketcher-react/src/script/ui/component/structrender.tsx b/packages/ketcher-react/src/script/ui/component/structrender.tsx index 9dfed7b078..ddc47664b9 100644 --- a/packages/ketcher-react/src/script/ui/component/structrender.tsx +++ b/packages/ketcher-react/src/script/ui/component/structrender.tsx @@ -42,8 +42,10 @@ function renderStruct( options: any = {} ) { if (el && struct) { - if (renderCache.has(struct.name)) { - el.innerHTML = renderCache.get(struct.name) + const { cachePrefix = '' } = options + const cacheKey = `${cachePrefix}${struct.name}` + if (renderCache.has(cacheKey)) { + el.innerHTML = renderCache.get(cacheKey) return } const preparedStruct = prepareStruct(struct) @@ -57,7 +59,7 @@ function renderStruct( }) rnd.setMolecule(preparedStruct) rnd.update(true, options.viewSz) - renderCache.set(struct.name, rnd.clientArea.innerHTML) + renderCache.set(cacheKey, rnd.clientArea.innerHTML) } } diff --git a/packages/ketcher-react/src/script/ui/state/editor/index.js b/packages/ketcher-react/src/script/ui/state/editor/index.js index 49cfab6c43..2a8d356dbb 100644 --- a/packages/ketcher-react/src/script/ui/state/editor/index.js +++ b/packages/ketcher-react/src/script/ui/state/editor/index.js @@ -156,10 +156,7 @@ export default function initEditor(dispatch, getState) { }, onSgroupEdit: (sgroup) => sleep(0) // huck to open dialog after dispatch sgroup tool action - .then(() => { - console.log('onSgroupEdit') - openDialog(dispatch, 'sgroup', fromSgroup(sgroup)) - }) + .then(() => openDialog(dispatch, 'sgroup', fromSgroup(sgroup))) .then(toSgroup), onRemoveFG: (result) => sleep(0).then(() => openDialog(dispatch, 'removeFG', result)), @@ -204,12 +201,12 @@ export default function initEditor(dispatch, getState) { updateAction() }, onConfirm: () => openDialog(dispatch, 'confirm'), - onShowInfo: (pl) => { - if (pl) { - const { group, groupId, x, y } = pl - highlightFG(dispatch, { group, id: group?.name, x, y, groupId }) + onShowInfo: (payload) => { + if (payload) { + const { groupStruct, event, sGroup } = payload + highlightFG(dispatch, { groupStruct, event, sGroup }) } else { - highlightFG(dispatch, { group: null, id: null }) + highlightFG(dispatch, { groupStruct: null, event: null, sGroup: null }) } } } diff --git a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts index 35f85390f2..c7cc5e54fb 100644 --- a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts +++ b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts @@ -64,7 +64,8 @@ export function initSaltsAndSolventsTemplates(baseUrl: string) { const templates = sdfSerializer.deserialize(text) const saltsAndSolvents = templates.reduce( (acc: Struct[], { struct, props }) => { - acc.push({ ...struct, abbreviation: props.abbreviation } as Struct) + struct.abbreviation = String(props.abbreviation) + acc.push(struct) return acc }, [] diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx deleted file mode 100644 index 3addb5fcff..0000000000 --- a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.jsx +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** - * Copyright 2021 EPAM Systems - * - * 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. - ***************************************************************************/ - -import { useState, useEffect, useRef } from 'react' -import { Scale, ReStruct, Vec2 } from 'ketcher-core' - -import StructRender from '../../../component/structrender' -// import { setRef } from '@mui/material' -import { - functionalGroupsSelector, - functionGroupInfoSelector -} from '../../../state/functionalGroups/selectors' -import { saltsAndSolventsSelector } from '../../../state/saltsAndSolvents/selectors' -import { connect, useSelector } from 'react-redux' -import { render } from '@testing-library/react' -import clsx from 'clsx' - -import classes from './InfoPanel.module.less' - -const HOVER_DELAY = 400 - -const allSGroupsSelector = (store) => { - const result = [...store.functionalGroups.lib, ...store.saltsAndSolvents.lib] - return result -} - -const options = { - autoScale: true, - autoScaleMargin: 0 -} - -const InfoPanel = (props) => { - const { - id, - functionalGroups, - x = 0, - y = 0, - groupId, - restruct, - baba, - className - } = props - const [molecule, setMolecule] = useState(null) - const childRef = useRef(null) - - let timer = -1 - - const pos = baba?.sgroups.get(groupId)?.areas[0].p1 - - let gr = null - - useEffect(() => { - const group = functionalGroups - ? functionalGroups.find((g) => g.modifiedStruct.name === id) - : null - if (group) { - gr = group.modifiedStruct.clone() - gr.name = id - timer = setTimeout(() => { - setMolecule(gr) - }, HOVER_DELAY) - } else { - setMolecule(null) - } - return () => clearTimeout(timer) - }, [id]) - - useEffect(() => { - childRef?.current?.forceUpdate() - }, [molecule]) - - let width = 0 - let height = 0 - let rX = 0 - let rY = 0 - if (baba) { - const vbox = restruct.sgroups?.get(groupId)?.item?.areas[0] - if (vbox) { - const start = Scale.obj2scaled(vbox.p0, restruct.render.options) - const end = Scale.obj2scaled(vbox.p1, restruct.render.options) - width = end.x - start.x - height = end.y - start.y - } - const { atomSelectionPlateRadius = 10 } = - restruct.render.options.atomSelectionPlateRadius - const padding = atomSelectionPlateRadius - var pos2 = baba?.sgroups?.get(groupId)?.firstSgroupAtom?.pp - const panelPosition = pos2 - ? Scale.obj2scaled(pos2, restruct.render.options) - : { x: 0, y: 0 } - rX = panelPosition.x - width / 2 - 10 - rY = panelPosition.y + 32 - } - - return ( - molecule && ( -
- -
- ) - ) -} - -export default connect((store) => ({ - // settings: (state) => state.options.settings, - // highlight: highlightSelector(store), - id: functionGroupInfoSelector(store) - ? functionGroupInfoSelector(store).id - : null, - x: functionGroupInfoSelector(store) ? functionGroupInfoSelector(store).x : 0, - y: functionGroupInfoSelector(store) ? functionGroupInfoSelector(store).y : 0, - restruct: store.editor?.render?.ctab, - baba: store.editor?.struct(), - groupId: functionGroupInfoSelector(store) - ? functionGroupInfoSelector(store).groupId - : null, - functionalGroups: allSGroupsSelector(store).map((template) => { - const struct = template.struct.clone() - struct.sgroups.delete(0) - return { ...template, modifiedStruct: struct } - }) -}))(InfoPanel) diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less index ed2044bd43..2cb35f5415 100644 --- a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less +++ b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.module.less @@ -1,9 +1,12 @@ -.infoPanel svg { - overflow: visible !important; +.infoPanel { position: absolute; padding: 20px; background: white; border: 1px solid #b4b9d6; border-radius: 3px; pointer-events: none; -} \ No newline at end of file + + svg { + overflow: visible !important; + } +} diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.tsx b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.tsx new file mode 100644 index 0000000000..e3d9ab8844 --- /dev/null +++ b/packages/ketcher-react/src/script/ui/views/components/StructEditor/InfoPanel.tsx @@ -0,0 +1,160 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ + +import { useState, useEffect, useRef, FC } from 'react' +import { Scale, Vec2, Render, Struct, SGroup } from 'ketcher-core' + +import StructRender from '../../../component/structrender' +import { functionGroupInfoSelector } from '../../../state/functionalGroups/selectors' +import { connect } from 'react-redux' +import clsx from 'clsx' + +import classes from './InfoPanel.module.less' + +const HOVER_DELAY = 400 +const HOVER_PANEL_PADDING = 20 + +function getSGroupFirstAtom(sGroup: SGroup, render: Render): Vec2 { + const { firstSgroupAtom } = sGroup + if (firstSgroupAtom) return firstSgroupAtom.pp + const [firstAtomId] = sGroup.atoms + return render.ctab.atoms?.get(firstAtomId)?.a.pp || new Vec2(0, 0) +} + +function getPanelPosition( + clientX: number, + clientY: number, + render: Render, + sGroup: SGroup +): [Vec2, Vec2] { + let width = 0 + let height = 0 + let x = 0 + let y = 0 + + if (sGroup) { + // calculate width and height + const groupBoundingBox = sGroup.areas[0] + const start = Scale.obj2scaled(groupBoundingBox.p0, render.options) + const end = Scale.obj2scaled(groupBoundingBox.p1, render.options) + width = end.x - start.x + height = end.y - start.y + // calculate initial position + const firstAtomPosition = getSGroupFirstAtom(sGroup, render) + const panelPosition = Scale.obj2scaled(firstAtomPosition, { + scale: render.options.scale * render.options.zoom + }) + x = panelPosition.x - width / 2 - HOVER_PANEL_PADDING + y = panelPosition.y + HOVER_PANEL_PADDING + // adjust position to keep inside viewport + const viewportRightLimit = render?.clientArea?.clientWidth - width / 2 + const viewportLeftLimit = HOVER_PANEL_PADDING * 2 + width / 2 + const viewportBottomLimit = render?.clientArea?.clientHeight - height + if (clientX > viewportRightLimit) { + x = panelPosition.x - width - HOVER_PANEL_PADDING + } else if (clientX < viewportLeftLimit) { + x = panelPosition.x - HOVER_PANEL_PADDING + } + if (clientY > viewportBottomLimit) { + y = panelPosition.y - height - HOVER_PANEL_PADDING * 3 + } + // adjust position to current scroll offset + const scrollOffsetX = + render?.options.offset?.x - render?.clientArea?.scrollLeft + const scrollOffsetY = + render?.options?.offset?.y - render?.clientArea?.scrollTop + x += scrollOffsetX + y += scrollOffsetY + } + + return [new Vec2(x, y), new Vec2(width, height)] +} + +interface InfoPanelProps { + clientX: number + clientY: number + render: Render + groupStruct: Struct + sGroup: SGroup + className?: string +} + +const InfoPanel: FC = (props) => { + const { + clientX = 0, + clientY = 0, + render, + className, + groupStruct, + sGroup + } = props + const [molecule, setMolecule] = useState(null) + const childRef = useRef(null) + const groupName = sGroup?.data?.name + let timer: ReturnType + + useEffect(() => { + if (groupStruct) { + timer = setTimeout(() => { + setMolecule(groupStruct.clone()) + }, HOVER_DELAY) + } else { + setMolecule(null) + } + return () => clearTimeout(timer) + }, [groupName]) + + const [position, size] = getPanelPosition(clientX, clientY, render, sGroup) + const { x, y } = position + const width = size.x + const height = size.y + + return ( + molecule && ( +
+ +
+ ) + ) +} +export default connect((store: any) => ({ + clientX: functionGroupInfoSelector(store)?.event?.clientX || 0, + clientY: functionGroupInfoSelector(store)?.event?.clientY || 0, + groupStruct: functionGroupInfoSelector(store)?.groupStruct || null, + sGroup: functionGroupInfoSelector(store)?.sGroup || null, + render: store.editor?.render?.ctab?.render +}))(InfoPanel) diff --git a/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx b/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx index 36dc1d98c7..9d5cdbead4 100644 --- a/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx +++ b/packages/ketcher-react/src/script/ui/views/components/StructEditor/StructEditor.jsx @@ -45,7 +45,6 @@ function setupEditor(editor, props, oldProps = {}) { if (oldProps.options && options !== oldProps.options) editor.options(options) Object.keys(editor.event).forEach((name) => { - // console.log('event name', name); const eventName = `on${upperFirst(name)}` if (props[eventName] !== oldProps[eventName]) { From 8f62a34087b0becaba8c06b42fb85b5b9ca10149 Mon Sep 17 00:00:00 2001 From: Anna Zhuravleva <56927722+ansivgit@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:39:03 +0300 Subject: [PATCH 21/27] #1888 - remove dropdowns & add custom name & values (#1928) --- .../src/script/ui/data/schema/sdata-schema.js | 16 ++-- .../src/script/ui/dialog/toolbox/sdata.jsx | 78 +++++++------------ .../src/script/ui/state/modal/form.js | 5 +- .../src/script/ui/state/modal/sdata.js | 30 ++++--- 4 files changed, 61 insertions(+), 68 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/data/schema/sdata-schema.js b/packages/ketcher-react/src/script/ui/data/schema/sdata-schema.js index 2e248e1f6a..b07e68a8bb 100644 --- a/packages/ketcher-react/src/script/ui/data/schema/sdata-schema.js +++ b/packages/ketcher-react/src/script/ui/data/schema/sdata-schema.js @@ -308,7 +308,7 @@ export const sdataCustomSchema = { type: { enum: ['DAT'] }, context: { title: 'Context', - enum: ['Fragment', 'Multifragment', 'Bond', 'Atom', 'Group'], + enum: ['Atom', 'Bond', 'Fragment', 'Group', 'Multifragment'], default: 'Fragment' }, fieldName: { @@ -358,12 +358,16 @@ function firstKeyOf(obj) { * @param fieldName? { string } * @returns { string } */ -export function getSdataDefault(context, fieldName) { - if (!context && !fieldName) return firstKeyOf(sdataSchema) +export function getSdataDefault(schema = sdataSchema, context, fieldName) { + if (schema.key === 'Custom') { + return schema.properties[context]?.default + } + + if (!context && !fieldName) return firstKeyOf(schema) - if (!fieldName) return firstKeyOf(sdataSchema[context]) + if (!fieldName) return firstKeyOf(schema[context]) - return sdataSchema[context][fieldName] - ? sdataSchema[context][fieldName].properties.fieldValue.default + return schema[context][fieldName] + ? schema[context][fieldName].properties.fieldValue.default : '' } diff --git a/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx b/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx index d4cec75f6e..d1eef7e290 100644 --- a/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx +++ b/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx @@ -14,45 +14,17 @@ * limitations under the License. ***************************************************************************/ -import Form, { Field, SelectOneOf } from '../../component/form/form/form' +import Form, { Field } from '../../component/form/form/form' import { getSdataDefault, - sdataCustomSchema, - sdataSchema + sdataCustomSchema } from '../../data/schema/sdata-schema' +import { getSelectOptionsFromSchema } from '../../utils' import { Dialog } from '../../views/components' import Select from '../../component/form/Select' import classes from './sgroup.module.less' import { connect } from 'react-redux' -import { getSelectOptionsFromSchema } from '../../utils' - -function SelectInput({ title, name, schema, ...prop }) { - const inputSelect = Object.keys(schema).reduce( - (acc, item) => { - acc.enum.push(item) - acc.enumNames.push(schema[item].title || item) - return acc - }, - { - title, - type: 'string', - default: '', - minLength: 1, - enum: [], - enumNames: [] - } - ) - - return ( - - ) -} function SData({ context, @@ -65,17 +37,16 @@ function SData({ }) { const { result, valid } = formState + const formSchema = sdataCustomSchema + const init = { - context, - fieldName: fieldName || getSdataDefault(context), + context: context || getSdataDefault(formSchema, 'context'), + fieldName: fieldName || getSdataDefault(formSchema, 'fieldName'), type, - radiobuttons + radiobuttons: radiobuttons || getSdataDefault(formSchema, 'radiobuttons') } - init.fieldValue = fieldValue || getSdataDefault(context, init.fieldName) - - const formSchema = - sdataSchema[result.context][result.fieldName] || sdataCustomSchema + init.fieldValue = fieldValue || getSdataDefault(formSchema, 'fieldValue') const serialize = { context: result.context.trim(), @@ -105,26 +76,32 @@ function SData({ {...formState} >
- - - {content(formSchema, result.context, result.fieldName, radiobuttons)} + + {content( + formSchema, + result.context, + result.fieldName, + result.fieldValue, + radiobuttons + )}
) } -const content = (schema, context, fieldName, checked) => +const content = (schema, context, fieldName, fieldValue, checked) => Object.keys(schema.properties) .filter( (prop) => prop !== 'type' && prop !== 'context' && prop !== 'fieldName' ) - .map((prop) => - prop === 'radiobuttons' ? ( + .map((prop) => { + return prop === 'radiobuttons' ? ( key={`${context}-${fieldName}-${prop}-radio`} labelPos={false} /> - ) : prop === 'fieldValue' && schema.properties.fieldValue.enum ? ( + ) : prop === 'fieldValue' ? ( ) : ( key={`${context}-${fieldName}-${prop}-select`} /> ) - ) + }) export default connect((store) => ({ formState: store.modal.form }))(SData) diff --git a/packages/ketcher-react/src/script/ui/state/modal/form.js b/packages/ketcher-react/src/script/ui/state/modal/form.js index dd2f3612f6..c3c90ea0dc 100644 --- a/packages/ketcher-react/src/script/ui/state/modal/form.js +++ b/packages/ketcher-react/src/script/ui/state/modal/form.js @@ -17,6 +17,7 @@ import { initSdata, sdataReducer } from './sdata' import { getDefaultOptions } from '../../data/schema/options-schema' +import { sdataCustomSchema } from '../../data/schema/sdata-schema' export const formsState = { // TODO: create from schema.{smth}.defaultValue @@ -117,7 +118,7 @@ export const formsState = { valid: true, result: {} }, - sdata: initSdata() + sdata: initSdata(sdataCustomSchema) } export function updateFormState(data) { @@ -138,7 +139,7 @@ export function setDefaultSettings() { return { type: 'UPDATE_FORM', data: { - result: getDefaultOptions(), + result: getDefaultOptions(sdataCustomSchema), valid: true, errors: {} } diff --git a/packages/ketcher-react/src/script/ui/state/modal/sdata.js b/packages/ketcher-react/src/script/ui/state/modal/sdata.js index 87eb1099d3..05fc1cd680 100644 --- a/packages/ketcher-react/src/script/ui/state/modal/sdata.js +++ b/packages/ketcher-react/src/script/ui/state/modal/sdata.js @@ -14,12 +14,24 @@ * limitations under the License. ***************************************************************************/ -import { getSdataDefault, sdataSchema } from '../../data/schema/sdata-schema' - -export const initSdata = () => { - const context = getSdataDefault() - const fieldName = getSdataDefault(context) - const fieldValue = getSdataDefault(context, fieldName) +import { + getSdataDefault, + sdataSchema, + sdataCustomSchema +} from '../../data/schema/sdata-schema' + +export const initSdata = (schema) => { + const isCustomShema = schema.key === 'Custom' + + const context = isCustomShema + ? getSdataDefault(sdataCustomSchema, 'context') + : getSdataDefault(sdataSchema) + const fieldName = isCustomShema + ? getSdataDefault(sdataCustomSchema, 'fieldName') + : getSdataDefault(sdataSchema, context) + const fieldValue = isCustomShema + ? getSdataDefault(sdataCustomSchema, 'fieldValue') + : getSdataDefault(sdataSchema, context, fieldName) const radiobuttons = 'Absolute' return { @@ -78,11 +90,11 @@ const correctErrors = (state, payload) => { const onContextChange = (state, payload) => { const { context, fieldValue } = payload - const fieldName = getSdataDefault(context) + const fieldName = getSdataDefault(sdataCustomSchema, 'fieldName') let fValue = fieldValue if (fValue === state.result.fieldValue) - fValue = getSdataDefault(context, fieldName) + fValue = getSdataDefault(sdataCustomSchema, 'fieldValue') return { result: { @@ -102,7 +114,7 @@ const onFieldNameChange = (state, payload) => { let fieldValue = payload.fieldValue if (sdataSchema[context][fieldName]) - fieldValue = getSdataDefault(context, fieldName) + fieldValue = getSdataDefault(sdataSchema, context, fieldName) if ( fieldValue === state.result.fieldValue && From f824020ae6719acace2cf3118e8d929b88c3e88d Mon Sep 17 00:00:00 2001 From: KonstantinEpam23 <101649391+KonstantinEpam23@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:39:21 +0300 Subject: [PATCH 22/27] #1912: update help.md with updated list of keyboard shortcuts (#1924) * #1912: update help.md with updated list of keyboard shortcuts * #1912: update description of shortcuts * #1912: fix formating / key code * #1912: fix formating / key code / md fixes * #1912: fix formating / key code / md fixes / fix * #1912: fix some key descriptions * #1912: fix formating * #1912: fix formating one more time * #1912: line break * #1912: markdown fix * #1912: small fix --- documentation/help.md | 270 ++++++++++++++++++++++++++---------------- 1 file changed, 165 insertions(+), 105 deletions(-) diff --git a/documentation/help.md b/documentation/help.md index a935803fb1..2815d4ba88 100644 --- a/documentation/help.md +++ b/documentation/help.md @@ -35,7 +35,7 @@ Using the _Tool palette_, you can - select the entire molecule or its fragment in one of the following ways (click on the button align=center to see the list of available options): - + To select **one atom or bond**, click Lasso (1) or Rectangle Selection tool (2), and then click the atom or bond. @@ -47,24 +47,24 @@ To select the **entire structure**: - Select the Lasso or Rectangle Selection tool, and then drag the mouse to select the object. -- `Ctrl-click` with the Lasso or Rectangle Selection tool. +-`Ctrl-click`with the Lasso or Rectangle Selection tool. To select **multiple atoms, bonds, structures, or other objects**, do one of the following: -- `Shift-click` with the Lasso or Rectangle Selection tool selects +-`Shift-click`with the Lasso or Rectangle Selection tool selects some (connected or not) atoms/bonds. - With the Lasso or Rectangle Selection tool click and drag the mouse around the atoms, bonds, or structures that you want to select. -**Note** : `Ctrl+Shift-click each structure` with the Lasso or Rectangle Selection tool +**Note** :`Ctrl+Shift-click each structure`with the Lasso or Rectangle Selection tool selects several structures. You can use the buttons of the _Main_ toolbar: -![](images/4_main_toolbarn.png 'Main Toolbar') +![](images/4_main_toolbarn.png 'Main Toolbar') - **Clear Canvas** (1) button to start drawing a new molecule; this command clears the drawing area; @@ -75,13 +75,13 @@ You can use the buttons of the _Main_ toolbar: - **Copy** with additional abilties to **Copy As** (4), **Paste** (5), **Cut** (6) buttons to perform the corresponding actions; - -- **Undo** (7) / **Redo** (8) to manage the last actions taken on the canvas; - + +- **Undo** (7) / **Redo** (8) to manage the last actions taken on the canvas; + - **Aromatize** (9) / **Dearomatize** (10) buttons to mark aromatic structures (to convert a structure to the Aromatic or Kekule presentation); - + - **Layout** button (11) to change the position of the structure to work with it with the most convenience; @@ -91,10 +91,10 @@ You can use the buttons of the _Main_ toolbar: - **Calculate CIP** button (13) to determine R/S and E/Z configurations; -- **Check Structure** button (14) to check the following properties of the structure. - Check will be conducted immediately when the operation is selected. - You can check only the Settings you are interested in and check structure again with new settings by clicking on Check button. - Apply button will save the Settings checked and they will be applied for the file saving. +- **Check Structure** button (14) to check the following properties of the structure. + Check will be conducted immediately when the operation is selected. + You can check only the Settings you are interested in and check structure again with new settings by clicking on Check button. + Apply button will save the Settings checked and they will be applied for the file saving. @@ -102,7 +102,7 @@ You can use the buttons of the _Main_ toolbar: the structure: - + - **Stereochemistry** button (16) to assign and display enhanced stereochemistry properties of the structure - **3D Viewer** button (17) to open the structure in the @@ -117,14 +117,14 @@ You can use the buttons of the _Main_ toolbar: - **About** button (20) to display version and copyright information of the program. - + - **Fullscreen mode** button (21) allows to initiate displaying Ketcher window in the fullscreen mode. - -- **Zoom panel** (22) displays the current zoom percentage. Click to expand the Zoom panel and use the following actions: **Zoom percentage** (23) to set the view manually, **Zoom in** (24) / **Zoom out** (25) to scale the view gradually, **Zoom 100%** (26) to enable the default zoom setting. + +- **Zoom panel** (22) displays the current zoom percentage. Click to expand the Zoom panel and use the following actions: **Zoom percentage** (23) to set the view manually, **Zoom in** (24) / **Zoom out** (25) to scale the view gradually, **Zoom 100%** (26) to enable the default zoom setting. - + # 3D Viewer @@ -175,20 +175,20 @@ To draw/edit atoms you can: - change an atom by clicking on an existing atom with the _Selection_ tool and starting to enter text after that; type another atom symbol in the text box: - + - + - change the charge of an atom by selecting the Charge Plus or Charge Minus tool and clicking consecutively on an atom to increase/decrease its charge: - + - change an atom or its properties by double-clicking on the atom to invoke the Atom Properties dialog (the dialog also provides atom query features): - + - click on the button to use the Extended table and select a corresponding Generic group or Special Node: @@ -219,9 +219,9 @@ To draw/edit bonds you can:

- - - + + + - select a bond type from the drop down list and click inside the drawing area; a bond of the selected type will be drawn; @@ -254,7 +254,7 @@ To draw/edit bonds you can: Use the _R-Group_ toolbox to draw R-groups in Markush structures: - + Selecting the _R-Group_ _Label_ Tool (1) and clicking on an atom in the structure invokes the dialog to select the R-Group label for a current @@ -265,11 +265,11 @@ atom position in the structure: Selecting the R-Group label and clicking **OK** converts the structure into a Markush structure with the selected R-Group label: -![](images/rgroup-example1.png) +![](images/rgroup-example1.png) **Note** : You can choose several R-Group labels simultaneously: -![](images/rgroup-example2.png) +![](images/rgroup-example2.png) Particular chemical fragments that may be substituted for a given R-Group form a set of R-Group members. R-Group members can be any @@ -306,9 +306,9 @@ attachment point. Schematically, the entire process of the R-Group member creation can be presented as: -![](images/rgroup-example3.png) +![](images/rgroup-example3.png) -![](images/rgroup-example4.png) +![](images/rgroup-example4.png) @@ -454,7 +454,7 @@ to open the drop-down list with the following tools: . - *Shape Ellipse* (1), *Shape Rectangle* (2), and *Shape Line* (3). + *Shape Ellipse* (1), *Shape Rectangle* (2), and *Shape Line* (3). @@ -484,19 +484,19 @@ To add a ring to the molecule, select a ring from the toolbar and click inside the drawing area, or click on an atom or a bond in the molecule. -Rules of using templates: +Rules of using templates: - Selecting a template and clicking on an atom in the existing structure adds the template to the structure connected with a single bond: - ![](images/template-example1.png) + ![](images/template-example1.png) - Selecting a template and dragging the cursor from an atom in the existing structure adds the template directly to this atom resulting in the fused structure: - ![](images/template-example2.png) + ![](images/template-example2.png) - Dragging the cursor from an atom in the existing structure results in the single bond attachment if the cursor is dragged to more than @@ -504,7 +504,7 @@ Rules of using templates: - Selecting a template and clicking on a bond in the existing structure created a bond-to-bond fused structure: - ![](images/template-example3.png) + ![](images/template-example3.png) - The bond in the initial structure is replaced with the bond in the template. @@ -532,21 +532,21 @@ To create a user template: - click the Save as button. -- click the Save to Templates button. _Template edit_ form will be displayed +- click the Save to Templates button. _Template edit_ form will be displayed -- enter a name and define the attachment atom and bond by clicking on the structure preview. Click on Apply button to save the template. +- enter a name and define the attachment atom and bond by clicking on the structure preview. Click on Apply button to save the template. -Saved template will be available in User Templates tab in the list of templates. +Saved template will be available in User Templates tab in the list of templates. # Functional Groups -Ketcher allows you to select and use Functional Groups to properly represent your structure on the canvas. -Set of functional groups available is predefined and can't be changed right now. +Ketcher allows you to select and use Functional Groups to properly represent your structure on the canvas. +Set of functional groups available is predefined and can't be changed right now. -Explore the list of the Functional Groups available in the Templates library. Open it using the icon in the bottom toolbar:
+Explore the list of the Functional Groups available in the Templates library. Open it using the icon in the bottom toolbar:

Navigate to the Functional Groups tab to explore the FGs available: @@ -564,11 +564,11 @@ To add Functional Group to the canvas and join it to the structure do the follow You can just click on the canvas having the FG selected. To connect it with other structure on the canvas do the following: 1. Select Simple Bond tool in the left Ketcher toolbar -2. Drag bond **from** the connection atom and drop it **to** the Functional Group on the canvas. +2. Drag bond **from** the connection atom and drop it **to** the Functional Group on the canvas. -Functional Group on the canvas can be **Expanded** to view it's internal structure. Expanded group can be **Contracted** back to the compact presentation. +Functional Group on the canvas can be **Expanded** to view it's internal structure. Expanded group can be **Contracted** back to the compact presentation. You can also **Remove the Abbreviation** on the group - it will allows you to work with the functional group atoms and bonds as with regular atoms and bonds on the canvas. To Expand, Contract and Remove Abbreviation: @@ -577,14 +577,14 @@ You can also **Remove the Abbreviation** on the group - it will allows you to wo -Please, note that a lot of Ketcher tools will be not applicable for the separate atoms and bonds of FG. FG can only be selected as a whole. It can also be deleted, moved, or rotated only as an entire entity. +Please, note that a lot of Ketcher tools will be not applicable for the separate atoms and bonds of FG. FG can only be selected as a whole. It can also be deleted, moved, or rotated only as an entire entity. -Ketcher will let you know if the tool is not applicable for the FG and will suggest to Remove the Abbreviation immediately:
+Ketcher will let you know if the tool is not applicable for the FG and will suggest to Remove the Abbreviation immediately:
-
-Aromatize & Dearomatize operations will not be applied to the rings that are part of the FG. +
+Aromatize & Dearomatize operations will not be applied to the rings that are part of the FG. -Functional Groups will be considered as **super atoms** when opening and saving .mol files. +Functional Groups will be considered as **super atoms** when opening and saving .mol files. # Working with Files @@ -592,11 +592,11 @@ Functional Groups will be considered as **super atoms** when opening and saving Ketcher supports the following molecular formats that can be entered either manually or from files: -![](images/formats-table.png) +![](images/formats-table.png) You can use the *Open…* and *Save As…* buttons of the _Main_ toolbar to import a molecule from a molecular file or save it to a -supported molecular file format. +supported molecular file format. The **_Open Structure_** dialog enables one to either browse for a file or manually input, e.g. @@ -610,18 +610,18 @@ The text editor form is initiated for the text from the Clipboard and when the f Ketcher suggests 2 ways for structure to be opened: -_Open as New Project_ will clear the canvas and position new structure on it. -_Add to Canvas_ will save the structure in the clipboard. Click on the canvas to place it. +_Open as New Project_ will clear the canvas and position new structure on it. +_Add to Canvas_ will save the structure in the clipboard. Click on the canvas to place it. The **_Save Structure_** dialog enables one to save the molecular file: -Select the format needed in the _File Format_ drop down. -
Check out the _Warnings_ tab if it's represented. It provides the list of chemical information that can't be saved properly to the format selected. +Select the format needed in the _File Format_ drop down. +
Check out the _Warnings_ tab if it's represented. It provides the list of chemical information that can't be saved properly to the format selected.

-You can save _a structure as image_ (in Standalone mode and in Remote mode when the server is available) by selectinig the _SVG Document_ or _PNG Image_ format. +You can save _a structure as image_ (in Standalone mode and in Remote mode when the server is available) by selectinig the _SVG Document_ or _PNG Image_ format. Please, note that saving structure to the image formats will results in chemical information loss in the file. You will not be able to open files in these formats in Ketcher. Supported graphics file formats are: *Portable Network Graphics (.png)* and *Scalable Vector Graphics (.svg)*. @@ -638,7 +638,7 @@ When the structure with the correct tetrahedral stereochemistry is created on th In the *Stereochemistry tab* in *Settings* you can: -- enable/disable display of the Stereo flags +- enable/disable display of the Stereo flags - set the text of the Absolute/AND/OR/Mixed flags - change the style of the Label display at stereogenic centers - select the color of Absolute/AND/OR stereogenic centers @@ -649,7 +649,7 @@ In the *Stereochemistry tab* in *Settings* you can: - + # Hotkeys @@ -658,53 +658,113 @@ features/commands of the Editor. To display the hotkeys just place the cursor over a toolbar button. If a hotkey is available for the button, it will appear in brackets after the description of the button. -| Key | Action | -| -------------- | ---------------------------------------------------------------------------------------------------------- | -| `Esc` | Switching between the Lasso/Rectangle/Fragment Selection tools | -| `Del` | Delete the selected objects | -| `0` | Draw Any bond. | -| `1` | Single / Single Up / Single Down / Single Up/Down bond. Consecutive pressing switches between these types. | -| `2` | Double / Double Cis/Trans bond | -| `3` | Draw a triple bond. | -| `4` | Draw an aromatic bond. | -| `5` | Charge Plus/Charge Minus | -| `A` | Draw any atom | -| `H` | Draw a hydrogen | -| `C` | Draw a carbon | -| `N` | Draw a nitrogen | -| `O` | Draw an oxygen | -| `S` | Draw a sulfur | -| `F` | Draw a fluorine | -| `P` | Draw a phosphorus | -| `I` | Draw an iodine | -| `T` | Basic templates. Consecutive pressing switches between different templates | -| `Shift+t` | Open template library | -| `Shift+f` | Open functional groups library | -| `Alt+r` | Rotate tool | -| `Alt+v` | Flip vertically | -| `Alt+h` | Flip horizontally | -| `Ctrl+g` | S-Group tool / Data S-Group tool | -| `Ctrl+d` | Align and select all S-Group data | -| `Ctrl+r` | Switching between the R-Group Label Tool/R-Group Fragment Tool/Attachment Point Tool | -| `Ctrl+Shift+r` | R-Group Fragment Tool | -| `Ctrl+Del` | Clear canvas | -| `Ctrl+o` | Open | -| `Ctrl+s` | Save As | -| `Ctrl+z` | Undo | -| `Ctrl+Shift+z` | Redo | -| `Ctrl+x` | Cut selected objects | -| `Ctrl+c` | Copy selected objects (not available for Simple objects and Text objects in IE) | -| `Ctrl+m` | Copy selected objects as Mol (not available for Simple objects and Text objects) | -| `Ctrl+Shift+k` | Copy selected objects as Ket | -| `Ctrl+Shift+f` | Copy selected objects as Image | -| `Ctrl+v` | Paste selected objects | -| `+` | Zoom In | -| `-` | Zoom Out | -| `Ctrl+l` | Layout | -| `Ctrl+Shift+l` | Clean Up | -| `Ctrl+p` | Calculate CIP | -| `?` | Help | - -**Note** : Please, use `Ctrl+V` to paste the selected object in +*NOTE: `Mod` key is `Command` on OSX and `Ctrl` on PC systems* + +**General** +| Shortcut| Action | +| --- | --- | +| `Mod+Delete` | Clear Canvas | +| `Mod+o` | Open… | +| `Mod+s` | Save As… | +| `Mod+z` | Undo | +| `Mod+Shift+z, Mod+y` | Redo | +| `Mod+x` | Cut | +| `Mod+c` | Copy | +| `Mod+Shift+f` | Copy Image | +| `Mod+m` | Copy as MOL | +| `Mod+Shift+k` | Copy as KET | +| `Mod+v` | Paste | +| `Mod+a` | Select All | +| `Mod+Shift+a` | Deselect All | +| `Mod+d` | Select descriptors | + + +**Server** +| Shortcut| Action | +| --- | --- | +| `Mod+l` | Layout | +| `Mod+Shift+l` | Clean Up | +| `Mod+p` | Calculate CIP | + + +**Debug** +| Shortcut| Action | +| --- | --- | +| `Ctrl+Shift+r` | force-update | +| `Alt+Shift+r` | qs-serialize | + + +**Tools** +| Shortcut| Action | +| --- | --- | +| `Mod+h` | Hand tool | +| `Escape` | Rotate between: Lasso Selection, Rectangle Selection, Fragment Selection | +| `Delete, Backspace` | Erase | +| `Alt+e` | Stereochemistry | +| `5` | Rotate between: Charge Plus, Charge Minus | +| `Alt+r` | Rotate Tool | +| `Alt+h` | Horizontal Flip | +| `Alt+v` | Vertical Flip | +| `Mod+g` | Rotate between: S-Group, Data S-Group | +| `Mod+r` | Rotate between: R-Group Label Tool, Attachment Point Tool | +| `Mod+Shift+r, Mod+r` | R-Group Fragment Tool | +| `1` | Rotate between: Single Bond, Single Up Bond, Single Down Bond, Single Up/Down Bond | +| `2` | Rotate between: Double Bond, Double Cis/Trans Bond | +| `3` | Triple Bond | +| `4` | Aromatic Bond | +| `0` | Any Bond | + + +**Atoms** +| Shortcut| Action | +| --- | --- | +| `h` | Atom H | +| `c` | Atom C | +| `n` | Atom N | +| `o` | Atom O | +| `s` | Atom S | +| `p` | Atom P | +| `f` | Atom F | +| `b` | Atom Br | +| `i` | Atom I | +| `k` | Atom K | +| `Shift+c` | Atom Cl | +| `Shift+s` | Atom Si | +| `Shift+n` | Atom Na | +| `Shift+b` | Atom B | +| `r` | Pseudoatom | +| `d` | Deuterium | +| `a` | Any atom | +| `q` | Any heteroatom | +| `m` | Any metal | +| `x` | Any halogen | + + +**Zoom** +| Shortcut| Action | +| --- | --- | +| `-, _, Shift+-` | Zoom Out | +| `+, =, Shift+=` | Zoom In | + + +**Templates** +| Shortcut| Action | +| --- | --- | +| `Shift+t` | Custom Templates | +| `t` | Rotate between: Benzene, Cyclopentadiene, Cyclohexane, Cyclopentane, Cyclopropane, Cyclobutane, Cycloheptane, Cyclooctane | + + +**FunctionalGroups** +| Shortcut| Action | +| --- | --- | +| `Shift+f` | Functional Groups | + + +**Help** +| Shortcut| Action | +| --- | --- | +| `?, &, Shift+/` | Help | + +**Note** : Please, use`Ctrl+V`to paste the selected object in Google Chrome and Mozilla Firefox browsers. From d3cd6f97aec6af1e699d062341a0462a9767601c Mon Sep 17 00:00:00 2001 From: KonstantinEpam23 <101649391+KonstantinEpam23@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:39:39 +0300 Subject: [PATCH 23/27] Release/2.6 backmerge (#1910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Release/2.6.1 (#1830) * highlight the element tool from the right side button panel * #1788 Update format when saving template library to sdf * added autofocus attribute for texarea * Change the default selection tool to the rectangle selection tool - To simplify interaction with selection tools we have changed the default selection tool to the rectangle selection tool. Co-authored-by: Svetlana Terenteva Co-authored-by: Evgenii Frolov * #1828 fix package version (#1833) * disabled polymer editor * updared version to 2.6.1 * #1839 – removed lightweight tag from page title (#1848) * added `render-coloring: true` to add colors when saving (#1849) * #1843 – added possibility to enable/disable redux-logger (#1847) * updated indigo version to 1.8.1 (#1846) * updated packages version to 2.6.2 (#1850) * #1764 ket objects coordinates issues (#1869) * fix: fix ket objects coordinates * #1764: create variable for arrow check, add comment * updated packages version to 2.6.3 and indigo to 1.8.2 (#1874) * updated packages version to 2.6.4 and indigo to 1.8.3 (#1881) Co-authored-by: Konstantin Levin Co-authored-by: Nikita Co-authored-by: Svetlana Terenteva Co-authored-by: Evgenii Frolov Co-authored-by: porcelain11 <112183450+porcelain11@users.noreply.github.com> Co-authored-by: Konstantin Levin --- packages/ketcher-core/package.json | 2 +- .../ketcher-core/src/domain/entities/struct.ts | 9 +++++++++ packages/ketcher-react/package.json | 2 +- .../src/script/ui/state/{shared.js => shared.ts} | 15 ++++++++------- packages/ketcher-standalone/package.json | 4 ++-- yarn.lock | 10 +++++----- 6 files changed, 26 insertions(+), 16 deletions(-) rename packages/ketcher-react/src/script/ui/state/{shared.js => shared.ts} (92%) diff --git a/packages/ketcher-core/package.json b/packages/ketcher-core/package.json index 9a653dac6d..7d6825a655 100644 --- a/packages/ketcher-core/package.json +++ b/packages/ketcher-core/package.json @@ -1,6 +1,6 @@ { "name": "ketcher-core", - "version": "2.6.1", + "version": "2.6.4", "description": "Web-based molecule sketcher", "license": "Apache-2.0", "homepage": "http://lifescience.opensource.epam.com/ketcher", diff --git a/packages/ketcher-core/src/domain/entities/struct.ts b/packages/ketcher-core/src/domain/entities/struct.ts index c76d9be480..25fc892c64 100644 --- a/packages/ketcher-core/src/domain/entities/struct.ts +++ b/packages/ketcher-core/src/domain/entities/struct.ts @@ -740,6 +740,15 @@ export class Struct { this.sgroups.forEach((item) => { item.pp = item.pp ? item.pp.scaled(scale) : null }) + + this.texts.forEach((item) => { + // Scale text only for reactions - i.e file contains reaction arrows + const isReactionStruct = this.rxnArrows.size + if (isReactionStruct) { + item.pos = item.pos.map((p) => p.scaled(scale)) + item.position = item.position.scaled(scale) + } + }) } rescale() { diff --git a/packages/ketcher-react/package.json b/packages/ketcher-react/package.json index 710c3ee134..50e5f24b5c 100644 --- a/packages/ketcher-react/package.json +++ b/packages/ketcher-react/package.json @@ -1,6 +1,6 @@ { "name": "ketcher-react", - "version": "2.6.1", + "version": "2.6.4", "description": "Web-based molecule sketcher", "license": "Apache-2.0", "homepage": "http://lifescience.opensource.epam.com/ketcher", diff --git a/packages/ketcher-react/src/script/ui/state/shared.js b/packages/ketcher-react/src/script/ui/state/shared.ts similarity index 92% rename from packages/ketcher-react/src/script/ui/state/shared.js rename to packages/ketcher-react/src/script/ui/state/shared.ts index 5caffe59e6..88d599b6b4 100644 --- a/packages/ketcher-react/src/script/ui/state/shared.js +++ b/packages/ketcher-react/src/script/ui/state/shared.ts @@ -19,7 +19,8 @@ import { Pile, SGroup, getStereoAtomsMap, - identifyStructFormat + identifyStructFormat, + Struct } from 'ketcher-core' import { supportedSGroupTypes } from './constants' @@ -44,13 +45,13 @@ export function onAction(action) { } export function loadStruct(struct) { - return (dispatch, getState) => { + return (_dispatch, getState) => { const editor = getState().editor editor.struct(struct) } } -function parseStruct(struct, server, options) { +function parseStruct(struct: Struct, server, options?): Promise { if (typeof struct === 'string') { options = options || {} const { rescale, fragment, ...formatterOptions } = options @@ -65,7 +66,7 @@ function parseStruct(struct, server, options) { } } -export function load(struct, options) { +export function load(struct: Struct, options?) { return async (dispatch, getState) => { const state = getState() const editor = state.editor @@ -90,7 +91,7 @@ export function load(struct, options) { if (hasUnsupportedGroups) { await editor.event.confirm.dispatch() parsedStruct.sgroups = parsedStruct.sgroups.filter( - (key, sGroup) => supportedSGroupTypes[sGroup.type] + (_key, sGroup) => supportedSGroupTypes[sGroup.type] ) } @@ -117,7 +118,7 @@ export function load(struct, options) { ) parsedStruct.atoms.forEach((atom, id) => { - if (parsedStruct.atomGetNeighbors(id).length === 0) { + if (parsedStruct?.atomGetNeighbors(id)?.length === 0) { atom.stereoLabel = null atom.stereoParity = 0 } else { @@ -145,7 +146,7 @@ export function load(struct, options) { } dispatch(setAnalyzingFile(false)) dispatch({ type: 'MODAL_CLOSE' }) - } catch (err) { + } catch (err: any) { dispatch(setAnalyzingFile(false)) err && errorHandler(err.message) } diff --git a/packages/ketcher-standalone/package.json b/packages/ketcher-standalone/package.json index c2f0af2ac9..ae910d73f1 100644 --- a/packages/ketcher-standalone/package.json +++ b/packages/ketcher-standalone/package.json @@ -1,6 +1,6 @@ { "name": "ketcher-standalone", - "version": "2.6.1", + "version": "2.6.4", "description": "Web-based molecule sketcher", "license": "Apache-2.0", "homepage": "http://lifescience.opensource.epam.com/ketcher", @@ -39,7 +39,7 @@ }, "dependencies": { "@babel/runtime": "^7.17.9", - "indigo-ketcher": "1.8.0", + "indigo-ketcher": "1.8.3", "ketcher-core": "workspace:*" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index a9f5f99d5e..a08bed6e82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9265,10 +9265,10 @@ __metadata: languageName: node linkType: hard -"indigo-ketcher@npm:1.8.0": - version: 1.8.0 - resolution: "indigo-ketcher@npm:1.8.0" - checksum: 24b96f8300fb952a22f55eaf65f9a1d7fa29b380d03a8053d52af3231bb8be0ed49df472391740b76559404d3209c39d46bedb9a0217354e889dd19b1df6518c +"indigo-ketcher@npm:1.8.3": + version: 1.8.3 + resolution: "indigo-ketcher@npm:1.8.3" + checksum: 8bb4968438b607aa29c8260307e56353b4df1ca061c5047e4ec7720f6b2ac89070c443682df0f5a828bf853a636d2489117ce6464baa0811d1af70e306264535 languageName: node linkType: hard @@ -11448,7 +11448,7 @@ __metadata: cross-env: ^7.0.3 eslint: ^8.4.1 eslint-plugin-jest: ^25.3.0 - indigo-ketcher: 1.8.0 + indigo-ketcher: 1.8.3 jest: 26.6.0 ketcher-core: "workspace:*" npm-run-all: ^4.1.5 From fc6113a4cb86e0738cb8b02939fa77242782b8f0 Mon Sep 17 00:00:00 2001 From: Nikita Date: Fri, 16 Dec 2022 19:35:14 +0300 Subject: [PATCH 24/27] Backmerge: #1640 add cdx support (#1650) (#1944) * add cdx format to types * add check for cdx format * add magic word for cdx for recognizing on server * delete magik number * fix format check * update indigo to 1.7.3 * fix format check * clear string from unnecessary info * clear string from \n symbols from clipboard * update indigo version Co-authored-by: Nikita_Vozisov Co-authored-by: ZaimBeshich1 <102960050+ZaimBeshich1@users.noreply.github.com> --- .../application/formatters/formatProperties.ts | 6 ++++++ .../application/formatters/formatterFactory.ts | 1 + .../formatters/identifyStructFormat.ts | 16 +++++++++++++++- .../formatters/structFormatter.types.ts | 3 ++- .../services/struct/structService.types.ts | 1 + .../ketcher-react/src/script/ui/state/shared.ts | 12 ++++++++++-- .../src/script/ui/utils/fileOpener.js | 6 +++--- .../modal/components/document/Save/Save.jsx | 1 + .../services/struct/indigoWorker.types.ts | 1 + .../services/struct/standaloneStructService.ts | 4 ++++ 10 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/ketcher-core/src/application/formatters/formatProperties.ts b/packages/ketcher-core/src/application/formatters/formatProperties.ts index 7653f650c8..6091eec922 100644 --- a/packages/ketcher-core/src/application/formatters/formatProperties.ts +++ b/packages/ketcher-core/src/application/formatters/formatProperties.ts @@ -94,6 +94,12 @@ const formatProperties: FormatPropertiesMap = { ChemicalMimeType.CDXML, ['.cdxml'], true + ), + cdx: new SupportedFormatProperties( + 'Base64 CDX', + ChemicalMimeType.CDX, + ['.cdx'], + true ) } diff --git a/packages/ketcher-core/src/application/formatters/formatterFactory.ts b/packages/ketcher-core/src/application/formatters/formatterFactory.ts index 9489fa2b09..76d7a810a7 100644 --- a/packages/ketcher-core/src/application/formatters/formatterFactory.ts +++ b/packages/ketcher-core/src/application/formatters/formatterFactory.ts @@ -91,6 +91,7 @@ export class FormatterFactory { case SupportedFormat.smilesExt: case SupportedFormat.smarts: case SupportedFormat.cdxml: + case SupportedFormat.cdx: default: formatter = new ServerFormatter( this.#structService, diff --git a/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts b/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts index 57dfa1f868..cad099b4a7 100644 --- a/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts +++ b/packages/ketcher-core/src/application/formatters/identifyStructFormat.ts @@ -47,6 +47,7 @@ export function identifyStructFormat( return SupportedFormat.mol } } + if ( sanitizedString[0] === '<' && sanitizedString.indexOf(' { +function parseStruct( + struct: string | Struct, + server, + options? +): Promise { if (typeof struct === 'string') { options = options || {} const { rescale, fragment, ...formatterOptions } = options const format = identifyStructFormat(struct) + if (format === SupportedFormat.cdx) { + struct = `base64::${struct.replace(/\s/g, '')}` + } const factory = new FormatterFactory(server) const service = factory.create(format, formatterOptions) diff --git a/packages/ketcher-react/src/script/ui/utils/fileOpener.js b/packages/ketcher-react/src/script/ui/utils/fileOpener.js index d3baf9e921..c8762db815 100644 --- a/packages/ketcher-react/src/script/ui/utils/fileOpener.js +++ b/packages/ketcher-react/src/script/ui/utils/fileOpener.js @@ -40,11 +40,12 @@ export function fileOpener(server) { } function throughFileReader(file) { + const isCDX = file.name.endsWith('cdx') return new Promise((resolve, reject) => { const rd = new FileReader() // eslint-disable-line no-undef rd.onload = () => { - const content = rd.result + const content = isCDX ? rd.result.slice(37) : rd.result if (file.msClose) file.msClose() resolve(content) } @@ -52,8 +53,7 @@ function throughFileReader(file) { rd.onerror = (event) => { reject(event) } - - rd.readAsText(file, 'UTF-8') + isCDX ? rd.readAsDataURL(file) : rd.readAsText(file, 'UTF-8') }) } diff --git a/packages/ketcher-react/src/script/ui/views/modal/components/document/Save/Save.jsx b/packages/ketcher-react/src/script/ui/views/modal/components/document/Save/Save.jsx index 9834ec40f3..948676498e 100644 --- a/packages/ketcher-react/src/script/ui/views/modal/components/document/Save/Save.jsx +++ b/packages/ketcher-react/src/script/ui/views/modal/components/document/Save/Save.jsx @@ -88,6 +88,7 @@ class SaveDialog extends Component { 'svg', 'png', 'cdxml' + // 'cdx' TO DO: Uncomment, when export will be ready on Indigo side ) this.saveSchema = saveSchema diff --git a/packages/ketcher-standalone/src/infrastructure/services/struct/indigoWorker.types.ts b/packages/ketcher-standalone/src/infrastructure/services/struct/indigoWorker.types.ts index 73d2362f5d..07ba461f20 100644 --- a/packages/ketcher-standalone/src/infrastructure/services/struct/indigoWorker.types.ts +++ b/packages/ketcher-standalone/src/infrastructure/services/struct/indigoWorker.types.ts @@ -53,6 +53,7 @@ export enum SupportedFormat { InChI = 'inchi', InChIAuxInfo = 'inchi-aux', Ket = 'ket', + CDX = 'cdx', CDXML = 'cdxml' } diff --git a/packages/ketcher-standalone/src/infrastructure/services/struct/standaloneStructService.ts b/packages/ketcher-standalone/src/infrastructure/services/struct/standaloneStructService.ts index 88aa9e44bf..faa572c69d 100644 --- a/packages/ketcher-standalone/src/infrastructure/services/struct/standaloneStructService.ts +++ b/packages/ketcher-standalone/src/infrastructure/services/struct/standaloneStructService.ts @@ -112,6 +112,10 @@ function convertMimeTypeToOutputFormat( format = SupportedFormat.CDXML break } + case ChemicalMimeType.CDX: { + format = SupportedFormat.CDX + break + } default: { throw new Error('Unsupported chemical mime type') } From 038b94aa36a8e2165467c7ca15dc4023ae9e5f13 Mon Sep 17 00:00:00 2001 From: Nikita Date: Fri, 16 Dec 2022 19:37:07 +0300 Subject: [PATCH 25/27] Backmerge: #1914 fix radiobuttons container styles (#1938) (#1946) Co-authored-by: Anna Zhuravleva <56927722+ansivgit@users.noreply.github.com> --- .../src/script/ui/dialog/toolbox/sdata.jsx | 2 +- .../ui/dialog/toolbox/sgroup.module.less | 33 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx b/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx index d1eef7e290..d850d2219a 100644 --- a/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx +++ b/packages/ketcher-react/src/script/ui/dialog/toolbox/sdata.jsx @@ -75,7 +75,7 @@ function SData({ init={init} {...formState} > -
+
Date: Fri, 16 Dec 2022 19:46:14 +0300 Subject: [PATCH 26/27] Backmerge: #1939: The hover panel is displayed incorrectly (#1945) --- .../src/application/render/raphaelRender.js | 252 +++++++++++++++ .../src/application/render/raphaelRender.ts | 299 ------------------ 2 files changed, 252 insertions(+), 299 deletions(-) create mode 100644 packages/ketcher-core/src/application/render/raphaelRender.js delete mode 100644 packages/ketcher-core/src/application/render/raphaelRender.ts diff --git a/packages/ketcher-core/src/application/render/raphaelRender.js b/packages/ketcher-core/src/application/render/raphaelRender.js new file mode 100644 index 0000000000..4bff83e97e --- /dev/null +++ b/packages/ketcher-core/src/application/render/raphaelRender.js @@ -0,0 +1,252 @@ +/**************************************************************************** + * Copyright 2021 EPAM Systems + * + * 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. + ***************************************************************************/ + +import { Box2Abs, Struct, Vec2 } from 'domain/entities' + +import Raphael from './raphael-ext' +import { ReStruct } from './restruct' +import { Scale } from 'domain/helpers' +import defaultOptions from './options' +import draw from './draw' + +export function Render(clientArea, opt) { + let renderWidth = opt.width || clientArea.clientWidth - 10 + let renderHeight = opt.height || clientArea.clientHeight - 10 + renderWidth = renderWidth > 0 ? renderWidth : 0 + renderHeight = renderHeight > 0 ? renderHeight : 0 + + this.userOpts = opt + this.clientArea = clientArea + this.paper = new Raphael(clientArea, renderWidth, renderHeight) + this.sz = Vec2.ZERO + this.ctab = new ReStruct(new Struct(), this) + this.options = defaultOptions(this.userOpts) +} + +Render.prototype.updateOptions = function (opts) { + try { + const passedOptions = JSON.parse(opts) + if (passedOptions && typeof passedOptions === 'object') { + this.options = { ...this.options, ...passedOptions } + return this.options + } + } catch (e) { + console.log('Not a valid settings object') + } + return false +} + +Render.prototype.selectionPolygon = function (r) { + return draw.selectionPolygon(this.paper, r, this.options) +} + +Render.prototype.selectionLine = function (p0, p1) { + return draw.selectionLine(this.paper, p0, p1, this.options) +} + +Render.prototype.selectionRectangle = function (p0, p1) { + return draw.selectionRectangle(this.paper, p0, p1, this.options) +} + +Render.prototype.view2obj = function (p, isRelative) { + let scroll = this.scrollPos() + if (!this.useOldZoom) { + p = p.scaled(1 / this.options.zoom) + scroll = scroll.scaled(1 / this.options.zoom) + } + p = isRelative ? p : p.add(scroll).sub(this.options.offset) + return Scale.scaled2obj(p, this.options) +} + +Render.prototype.obj2view = function (v, isRelative) { + let p = Scale.obj2scaled(v, this.options) + p = isRelative + ? p + : p + .add(this.options.offset) + .sub(this.scrollPos().scaled(1 / this.options.zoom)) + if (!this.useOldZoom) p = p.scaled(this.options.zoom) + return p +} + +Render.prototype.scrollPos = function () { + return new Vec2(this.clientArea.scrollLeft, this.clientArea.scrollTop) +} + +Render.prototype.page2obj = function (event) { + const clientArea = this.clientArea + + const { top: offsetTop, left: offsetLeft } = + clientArea.getBoundingClientRect() + + const pp = new Vec2(event.clientX - offsetLeft, event.clientY - offsetTop) + return this.view2obj(pp) +} + +Render.prototype.setPaperSize = function (sz) { + this.sz = sz + this.paper.setSize(sz.x * this.options.zoom, sz.y * this.options.zoom) + this.setViewBox(this.options.zoom) +} + +Render.prototype.setOffset = function (newoffset) { + const delta = new Vec2( + newoffset.x - this.options.offset.x, + newoffset.y - this.options.offset.y + ) + this.clientArea.scrollLeft += delta.x + this.clientArea.scrollTop += delta.y + this.options.offset = newoffset +} + +Render.prototype.setZoom = function (zoom) { + // when scaling the canvas down it may happen that the scaled canvas is smaller than the view window + // don't forget to call setScrollOffset after zooming (or use extendCanvas directly) + this.options.zoom = zoom + this.paper.setSize(this.sz.x * zoom, this.sz.y * zoom) + this.setViewBox(zoom) +} + +function calcExtend(sSz, x0, y0, x1, y1) { + // eslint-disable-line max-params + let ex = x0 < 0 ? -x0 : 0 + let ey = y0 < 0 ? -y0 : 0 + + if (sSz.x < x1) ex += x1 - sSz.x + if (sSz.y < y1) ey += y1 - sSz.y + return new Vec2(ex, ey) +} + +Render.prototype.setScrollOffset = function (x, y) { + const clientArea = this.clientArea + const cx = clientArea.clientWidth + const cy = clientArea.clientHeight + const e = calcExtend( + this.sz.scaled(this.options.zoom), + x, + y, + cx + x, + cy + y + ).scaled(1 / this.options.zoom) + if (e.x > 0 || e.y > 0) { + this.setPaperSize(this.sz.add(e)) + const d = new Vec2(x < 0 ? -x : 0, y < 0 ? -y : 0).scaled( + 1 / this.options.zoom + ) + if (d.x > 0 || d.y > 0) { + this.ctab.translate(d) + this.setOffset(this.options.offset.add(d)) + } + } + // clientArea.scrollLeft = x + // clientArea.scrollTop = y + clientArea.scrollLeft = x * this.options.scale + clientArea.scrollTop = y * this.options.scale + // TODO: store drag position in scaled systems + // scrollLeft = clientArea.scrollLeft; + // scrollTop = clientArea.scrollTop; + this.update(false) +} + +Render.prototype.setScale = function (z) { + if (this.options.offset) { + this.options.offset = this.options.offset.scaled(1 / z).scaled(z) + } + this.userOpts.scale *= z + this.options = null + this.update(true) +} + +Render.prototype.setViewBox = function (z) { + if (!this.useOldZoom) { + this.paper.canvas.setAttribute( + 'viewBox', + '0 0 ' + this.sz.x + ' ' + this.sz.y + ) + } else this.setScale(z) +} + +Render.prototype.setMolecule = function (ctab) { + this.paper.clear() + this.ctab = new ReStruct(ctab, this) + this.options.offset = new Vec2() + this.update(false) +} + +Render.prototype.update = function (force = false, viewSz = null) { + // eslint-disable-line max-statements + viewSz = + viewSz || + new Vec2( + this.clientArea.clientWidth || 100, + this.clientArea.clientHeight || 100 + ) + + const changes = this.ctab.update(force) + this.ctab.setSelection() // [MK] redraw the selection bits where necessary + if (changes) { + const sf = this.options.scale + const bb = this.ctab + .getVBoxObj() + .transform(Scale.obj2scaled, this.options) + .translate(this.options.offset || new Vec2()) + + if (!this.options.autoScale) { + const ext = Vec2.UNIT.scaled(sf) + const eb = bb.sz().length() > 0 ? bb.extend(ext, ext) : bb + const vb = new Box2Abs( + this.scrollPos(), + viewSz.scaled(1 / this.options.zoom).sub(Vec2.UNIT.scaled(20)) + ) + const cb = Box2Abs.union(vb, eb) + if (!this.oldCb) this.oldCb = new Box2Abs() + + const sz = cb.sz().floor() + const delta = this.oldCb.p0.sub(cb.p0).ceil() + this.oldBb = bb + if (!this.sz || sz.x !== this.sz.x || sz.y !== this.sz.y) { + this.setPaperSize(sz) + } + + this.options.offset = this.options.offset || new Vec2() + if (delta.x !== 0 || delta.y !== 0) { + this.setOffset(this.options.offset.add(delta)) + this.ctab.translate(delta) + } + } else { + const sz1 = bb.sz() + const marg = this.options.autoScaleMargin + const mv = new Vec2(marg, marg) + const csz = viewSz + if (marg && (csz.x < 2 * marg + 1 || csz.y < 2 * marg + 1)) { + throw new Error('View box too small for the given margin') + } + let rescale = + this.options.rescaleAmount || + Math.max(sz1.x / (csz.x - 2 * marg), sz1.y / (csz.y - 2 * marg)) + if (this.options.maxBondLength / rescale > 1.0) rescale = 1.0 + const sz2 = sz1.add(mv.scaled(2 * rescale)) + /* eslint-disable no-mixed-operators */ + this.paper.setViewBox( + bb.pos().x - marg * rescale - (csz.x * rescale - sz2.x) / 2, + bb.pos().y - marg * rescale - (csz.y * rescale - sz2.y) / 2, + csz.x * rescale, + csz.y * rescale + ) + /* eslint-enable no-mixed-operators */ + } + } +} diff --git a/packages/ketcher-core/src/application/render/raphaelRender.ts b/packages/ketcher-core/src/application/render/raphaelRender.ts deleted file mode 100644 index c68a1abc49..0000000000 --- a/packages/ketcher-core/src/application/render/raphaelRender.ts +++ /dev/null @@ -1,299 +0,0 @@ -/**************************************************************************** - * Copyright 2021 EPAM Systems - * - * 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. - ***************************************************************************/ - -import { Box2Abs, Struct, Vec2 } from 'domain/entities' - -import Raphael from './raphael-ext' -import { ReStruct } from './restruct' -import { Scale } from 'domain/helpers' -import defaultOptions from './options' -import draw from './draw' -import { RaphaelPaper } from 'raphael' -// TODO: add types for options -// import { RenderOptions } from './render.types' - -function calcExtend( - scaledSz: Vec2, - x0: number, - y0: number, - x1: number, - y1: number -) { - // eslint-disable-line max-params - let ex = x0 < 0 ? -x0 : 0 - let ey = y0 < 0 ? -y0 : 0 - - if (scaledSz.x < x1) { - ex += x1 - scaledSz.x - } - if (scaledSz.y < y1) { - ey += y1 - scaledSz.y - } - - return new Vec2(ex, ey) -} - -class Render { - public clientArea: HTMLElement - private userOpts: any - public paper: RaphaelPaper - private sz: Vec2 - public ctab: ReStruct - public options: any - private renderWidth: number - private renderHeight: number - private useOldZoom: boolean - private oldCb: Box2Abs | null - - constructor(clientArea: HTMLElement, opt: any) { - this.userOpts = opt - this.clientArea = clientArea - this.renderWidth = - clientArea.clientWidth - 10 > 0 ? clientArea.clientWidth - 10 : 0 - this.renderHeight = - clientArea.clientHeight - 10 > 0 ? clientArea.clientHeight - 10 : 0 - this.paper = new Raphael(clientArea, this.renderWidth, this.renderHeight) - this.sz = Vec2.ZERO - this.ctab = new ReStruct(new Struct(), this) - this.options = defaultOptions(this.userOpts) - this.useOldZoom = false // where it comes from? - this.oldCb = null // where it comes from? - } - - updateOptions(opts) { - try { - const passedOptions = JSON.parse(opts) - if (passedOptions && typeof passedOptions === 'object') { - this.options = { ...this.options, ...passedOptions } - return this.options - } - } catch (e) { - console.log('Not a valid settings object') - } - return false - } - - selectionPolygon(r) { - return draw.selectionPolygon(this.paper, r, this.options) - } - - selectionLine(p0: Vec2, p1: Vec2) { - return draw.selectionLine(this.paper, p0, p1, this.options) - } - - selectionRectangle(p0: Vec2, p1: Vec2) { - return draw.selectionRectangle(this.paper, p0, p1, this.options) - } - - getScrollPos() { - return new Vec2(this.clientArea.scrollLeft, this.clientArea.scrollTop) - } - - view2obj(p: Vec2, isRelative?: boolean) { - let scroll = this.getScrollPos() - if (!this.useOldZoom) { - p = p.scaled(1 / this.options.zoom) - scroll = scroll.scaled(1 / this.options.zoom) - } - p = isRelative ? p : p.add(scroll).sub(this.options.offset) - return Scale.scaled2obj(p, this.options) - } - - obj2view(v: Vec2, isRelative: boolean) { - let p = Scale.obj2scaled(v, this.options) - p = isRelative - ? p - : p - .add(this.options.offset) - .sub(this.getScrollPos().scaled(1 / this.options.zoom)) - - if (!this.useOldZoom) { - p = p.scaled(this.options.zoom) - } - - return p - } - - page2obj(event: MouseEvent) { - const clientArea = this.clientArea - const { top: offsetTop, left: offsetLeft } = - clientArea.getBoundingClientRect() - - const pp = new Vec2(event.clientX - offsetLeft, event.clientY - offsetTop) - - return this.view2obj(pp) - } - - setViewBox(z: number) { - if (!this.useOldZoom) { - this.paper.canvas.setAttribute( - 'viewBox', - '0 0 ' + this.sz.x + ' ' + this.sz.y - ) - } else this.setScale(z) - } - - setScale(z: number) { - if (this.options.offset) { - this.options.offset = this.options.offset.scaled(1 / z).scaled(z) - } - this.userOpts.scale *= z - this.options = null - this.update(true) - } - - setPaperSize(sz: Vec2) { - this.sz = sz - this.paper.setSize(sz.x * this.options.zoom, sz.y * this.options.zoom) - this.setViewBox(this.options.zoom) - } - - setZoom(zoom: number) { - // when scaling the canvas down it may happen that the scaled canvas is smaller than the view window - // don't forget to call setScrollOffset after zooming (or use extendCanvas directly) - this.options.zoom = zoom - this.paper.setSize(this.sz.x * zoom, this.sz.y * zoom) - this.setViewBox(zoom) - } - - setOffset(newoffset: Vec2) { - const delta = new Vec2( - newoffset.x - this.options.offset.x, - newoffset.y - this.options.offset.y - ) - this.clientArea.scrollLeft += delta.x - this.clientArea.scrollTop += delta.y - this.options.offset = newoffset - } - - setMolecule(struct: Struct) { - this.paper.clear() - this.ctab = new ReStruct(struct, this) - this.options.offset = new Vec2() - this.update(false) - } - - setScrollOffset(x: number, y: number) { - const clientArea = this.clientArea - const cx = clientArea.clientWidth - const cy = clientArea.clientHeight - const e = calcExtend( - this.sz.scaled(this.options.zoom), - x, - y, - cx + x, - cy + y - ).scaled(1 / this.options.zoom) - if (e.x > 0 || e.y > 0) { - this.setPaperSize(this.sz.add(e)) - const d = new Vec2(x < 0 ? -x : 0, y < 0 ? -y : 0).scaled( - 1 / this.options.zoom - ) - if (d.x > 0 || d.y > 0) { - this.ctab.translate(d) - this.setOffset(this.options.offset.add(d)) - } - } - - clientArea.scrollLeft = x * this.options.scale - clientArea.scrollTop = y * this.options.scale - } - - update(force = false, viewSz: Vec2 | null = null) { - viewSz = - viewSz || - new Vec2( - this.clientArea.clientWidth || 100, - this.clientArea.clientHeight || 100 - ) - - const changes = this.ctab.update(force) - this.ctab.setSelection() // [MK] redraw the selection bits where necessary - - if (changes) { - const boundingBox = this.ctab - ?.getVBoxObj() - ?.transform(Scale.obj2scaled, this.options) - .translate(this.options.offset || new Vec2()) - - if (!this.options.autoScale && boundingBox) { - const ext = Vec2.UNIT.scaled(this.options.scale) - const extendedBox = - boundingBox.sz().length() > 0 - ? boundingBox.extend(ext, ext) - : boundingBox - const viewBox = new Box2Abs( - this.getScrollPos(), - viewSz.scaled(1 / this.options.zoom).sub(Vec2.UNIT.scaled(20)) - ) - const cb = Box2Abs.union(viewBox, extendedBox) - if (!this.oldCb) { - this.oldCb = new Box2Abs() - } - - const sz = cb.sz().floor() - const delta = this.oldCb.p0.sub(cb.p0).ceil() - // TODO: do we need this.oldBb? Seem it's not in use - // this.oldBb = bb - if (!this.sz || sz.x !== this.sz.x || sz.y !== this.sz.y) { - this.setPaperSize(sz) - } - - this.options.offset = this.options.offset || new Vec2() - if (delta.x !== 0 || delta.y !== 0) { - this.setOffset(this.options.offset.add(delta)) - this.ctab.translate(delta) - } - } else { - if (!boundingBox) { - return - } - const sz1 = boundingBox.sz() - const { autoScaleMargin, rescaleAmount, maxBondLength } = this.options - const mv = new Vec2(autoScaleMargin, autoScaleMargin) - const csz = viewSz - if ( - autoScaleMargin && - (csz.x < 2 * autoScaleMargin + 1 || csz.y < 2 * autoScaleMargin + 1) - ) { - throw new Error('View box too small for the given margin') - } - let rescale = - rescaleAmount || - Math.max( - sz1.x / (csz.x - 2 * autoScaleMargin), - sz1.y / (csz.y - 2 * autoScaleMargin) - ) - if (maxBondLength / rescale > 1.0) rescale = 1.0 - const sz2 = sz1.add(mv.scaled(2 * rescale)) - /* eslint-disable no-mixed-operators */ - this.paper.setViewBox( - boundingBox.pos().x - - autoScaleMargin * rescale - - (csz.x * rescale - sz2.x) / 2, - boundingBox.pos().y - - autoScaleMargin * rescale - - (csz.y * rescale - sz2.y) / 2, - csz.x * rescale, - csz.y * rescale - ) - /* eslint-enable no-mixed-operators */ - } - } - } -} - -export { Render } From 0174be46406d6de7214226c07e275eba693481ee Mon Sep 17 00:00:00 2001 From: KonstantinEpam23 <101649391+KonstantinEpam23@users.noreply.github.com> Date: Fri, 16 Dec 2022 20:22:42 +0300 Subject: [PATCH 27/27] Backmerge: #1936 Adding functional group to atom generate a JavaScript console error (#1949) Co-authored-by: ansivgit --- .../script/ui/dialog/template/TemplateDialog.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx index 388404685b..e6934530a4 100644 --- a/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx +++ b/packages/ketcher-react/src/script/ui/dialog/template/TemplateDialog.tsx @@ -72,7 +72,7 @@ interface TemplateLibProps { filter: string group: string lib: Array