eacortes commited on
Commit
0deb5b7
·
1 Parent(s): 9cd82f9

add: demo app code and deps.

Browse files
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__/
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM redis/redis-stack:latest
2
+
3
+ RUN apt-get update && apt-get install -y \
4
+ pip \
5
+ libxrender1 libxext6 \
6
+ && rm -rf /var/lib/apt/lists/*
7
+
8
+ WORKDIR /app
9
+
10
+ COPY requirements.txt .
11
+ RUN pip install --no-cache-dir torch==2.6.0+cpu --index-url https://download.pytorch.org/whl/cpu
12
+ RUN pip install --no-cache-dir -r requirements.txt
13
+
14
+ COPY redis.conf .
15
+ ENV REDIS_HOST=localhost
16
+ ENV REDIS_PORT=6379
17
+
18
+ COPY ./src ./src
19
+
20
+ CMD ["sh", "-c", "redis-server redis.conf & python3 src/app.py"]
redis.conf ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ loadmodule /opt/redis-stack/lib/redisearch.so
2
+ maxmemory 768mb
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ chem-mrl>=0.5.8
2
+ gradio[mcp]>=4.0.0
3
+ transformers>=4.30.0
4
+ torch>=2.0.0
5
+ redis>=4.5.0
6
+ redis-om>=0.2.0
7
+ numpy>=1.24.0
8
+ python-dotenv>=1.0.0
9
+ scikit-learn>=1.3.0
10
+ rdkit>=2025.3.2
11
+ sentence-transformers==4.0.1
src/app.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import pandas as pd
4
+ from rdkit import Chem
5
+ from rdkit.Chem import Draw
6
+ from rdkit.Chem.Draw import rdMolDraw2D
7
+
8
+ from constants import EMBEDDING_DIMENSION, LAUNCH_PARAMETERS, SUPPORTED_EMBEDDING_DIMENSIONS
9
+ from data import SAMPLE_SMILES
10
+ from service import MolecularEmbeddingService, SimilarMolecule, setup_logger
11
+
12
+ logger = setup_logger()
13
+
14
+
15
+ class App:
16
+ def __init__(self):
17
+ self.embedding_service = MolecularEmbeddingService()
18
+ self.demo = self.create_gradio_interface()
19
+
20
+ def molecule_similarity_search_pipeline(
21
+ self, smiles: str, embed_dim: int
22
+ ) -> tuple[list[float], list[SimilarMolecule], str]:
23
+ """Complete pipeline: SMILES -> Canonical SMILES -> Embedding -> Similar molecules"""
24
+ try:
25
+ if not smiles or smiles.strip() == "":
26
+ return [], [], "Please provide a valid SMILES string"
27
+
28
+ logger.info(f"Running similarity search: {smiles} - ({embed_dim})")
29
+ embedding = self.embedding_service.get_molecular_embedding(smiles, embed_dim)
30
+ neighbors = self.embedding_service.find_similar_molecules(embedding, embed_dim)
31
+
32
+ return embedding.tolist(), neighbors, "Search completed successfully"
33
+
34
+ except Exception as e:
35
+ error_msg = f"Search failed: {str(e)}"
36
+ logger.error(error_msg)
37
+ return [], [], error_msg
38
+
39
+ @staticmethod
40
+ def _truncated_attribute(obj, attr, max_len=45):
41
+ return f"{obj[attr][:max_len]}{'...' if len(obj[attr]) > max_len else ''}"
42
+
43
+ @classmethod
44
+ def _draw_molecule_grid(cls, similar: list[SimilarMolecule]) -> np.ndarray:
45
+ mols = [Chem.MolFromSmiles(m["smiles"]) for m in similar]
46
+ legends = [
47
+ f"{cls._truncated_attribute(m, 'name')}\n{m['category']}\n"
48
+ f"{cls._truncated_attribute(m, 'smiles')}\n({m['score']:.2E})"
49
+ for m in similar
50
+ ]
51
+
52
+ draw_options = rdMolDraw2D.MolDrawOptions()
53
+ draw_options.legendFontSize = 17
54
+ draw_options.legendFraction = 0.29
55
+ draw_options.drawMolsSameScale = False
56
+
57
+ img = Draw.MolsToGridImage(
58
+ mols,
59
+ legends=legends,
60
+ molsPerRow=2,
61
+ subImgSize=(250, 250),
62
+ drawOptions=draw_options,
63
+ )
64
+ return img
65
+
66
+ @staticmethod
67
+ def _display_sample_molecules(mols: pd.DataFrame):
68
+ for _, row in mols.iterrows():
69
+ with gr.Group():
70
+ gr.Textbox(value=row["smiles"], label=f"{row['name']} ({row['category']})", interactive=False, scale=3)
71
+ sample_btn = gr.Button(
72
+ f"Load {row['name']}",
73
+ scale=1,
74
+ size="sm",
75
+ variant="primary",
76
+ )
77
+ sample_btn.click(
78
+ fn=None,
79
+ js=f"() => {{window.setJSMESmiles('{row['smiles']}');}}",
80
+ )
81
+
82
+ @staticmethod
83
+ def clear_all():
84
+ return "", [], [], None, "Cleared - Draw a new molecule or enter SMILES"
85
+
86
+ def handle_search(self, smiles: str, embed_dim: int):
87
+ if not smiles.strip():
88
+ return (
89
+ [],
90
+ [],
91
+ None,
92
+ "Please draw a molecule or enter a SMILES string",
93
+ )
94
+ embedding, similar, status = self.molecule_similarity_search_pipeline(smiles, embed_dim)
95
+ img = self._draw_molecule_grid(similar)
96
+ return embedding, similar, img, status
97
+
98
+ def create_gradio_interface(self):
99
+ """Create the Gradio interface optimized for JavaScript client usage"""
100
+ head_scripts = """
101
+ <link rel="preconnect" href="https://jsme-editor.github.io">
102
+ <link rel="preload" href="https://jsme-editor.github.io/dist/jsme/jsme.nocache.js" as="script" crossorigin="anonymous">
103
+ <link rel="preload" href="gradio_api/file=src/main.min.js" as="script">
104
+ <script type="text/javascript" src="https://jsme-editor.github.io/dist/jsme/jsme.nocache.js" crossorigin="anonymous" defer></script>
105
+ <script type="text/javascript" src="gradio_api/file=src/main.min.js" defer></script>
106
+ """
107
+
108
+ with gr.Blocks(
109
+ title="Chem-MRL: Molecular Similarity Search Demo",
110
+ theme=gr.themes.Soft(),
111
+ head=head_scripts,
112
+ ) as demo:
113
+ gr.Markdown("""
114
+ # 🧪 Chem-MRL: Molecular Similarity Search Demo
115
+
116
+ Use the JSME editor to draw a molecule or input a SMILES string.
117
+ The backend encodes the molecule using the Chem-MRL model to produce a vector embedding.
118
+ Similarity search is performed via an HNSW-indexed Redis vector store to retrieve closest matches.<br/>
119
+
120
+ [Model Repo](https://github.com/emapco/chem-mrl) | [Demo Repo](https://github.com/emapco/chem-mrl-demo)
121
+ """)
122
+ with gr.Tab("🔬 Molecular Search"), gr.Row():
123
+ with gr.Column(scale=1):
124
+ gr.Markdown("### Molecule Input")
125
+ gr.HTML("<div id='jsme_container'></div>")
126
+
127
+ smiles_input = gr.Textbox(
128
+ label="SMILES String",
129
+ placeholder="Draw a molecule above or enter SMILES here (e.g., CCO for ethanol)",
130
+ lines=2,
131
+ elem_id="smiles_input",
132
+ )
133
+
134
+ embedding_dimension = gr.Dropdown(
135
+ choices=SUPPORTED_EMBEDDING_DIMENSIONS,
136
+ value=EMBEDDING_DIMENSION,
137
+ label="Embedding Dimension",
138
+ elem_id="embedding_dimension",
139
+ )
140
+
141
+ with gr.Row():
142
+ search_btn = gr.Button(
143
+ "🔍 Search Molecule Database",
144
+ variant="primary",
145
+ elem_id="search_btn",
146
+ )
147
+ clear_btn = gr.Button("🗑️ Clear All", variant="secondary")
148
+
149
+ with gr.Column(scale=1):
150
+ gr.Markdown("### Search Results")
151
+ status_output = gr.Textbox(
152
+ label="Status",
153
+ interactive=False,
154
+ elem_id="status_output",
155
+ value="Ready - Draw a molecule or enter SMILES",
156
+ )
157
+
158
+ with gr.Accordion("Molecular Embedding Vector", open=False):
159
+ embedding_output = gr.JSON(
160
+ label="Molecular Embedding",
161
+ elem_id="embedding_output",
162
+ )
163
+
164
+ with gr.Accordion("Similar Molecules Response", open=False):
165
+ similar_molecules_output = gr.JSON(
166
+ label="API Response",
167
+ elem_id="similar_molecules_output",
168
+ )
169
+
170
+ molecule_image = gr.Image(label="Similiar Molecules Grid", type="pil")
171
+
172
+ with gr.Tab("📊 Sample Molecules"):
173
+ gr.Markdown("""
174
+ ### Sample Molecules in Database
175
+ Click any button below to load the molecule into the JSME editor:
176
+ """)
177
+
178
+ with gr.Row():
179
+ with gr.Column(scale=1):
180
+ self._display_sample_molecules(SAMPLE_SMILES[::3])
181
+ with gr.Column(scale=1):
182
+ self._display_sample_molecules(SAMPLE_SMILES[1::3])
183
+ with gr.Column(scale=1):
184
+ self._display_sample_molecules(SAMPLE_SMILES[2::3])
185
+
186
+ search_btn.click(
187
+ fn=self.handle_search,
188
+ inputs=[smiles_input, embedding_dimension],
189
+ outputs=[
190
+ embedding_output,
191
+ similar_molecules_output,
192
+ molecule_image,
193
+ status_output,
194
+ ],
195
+ api_name="molecule_similarity_search_pipeline",
196
+ )
197
+
198
+ # Clear UI state
199
+ clear_btn.click(
200
+ fn=self.clear_all,
201
+ js="window.clearJSME",
202
+ outputs=[
203
+ smiles_input,
204
+ embedding_output,
205
+ similar_molecules_output,
206
+ molecule_image,
207
+ status_output,
208
+ ],
209
+ )
210
+
211
+ gr.set_static_paths(paths=["src/"])
212
+
213
+ return demo
214
+
215
+
216
+ if __name__ == "__main__":
217
+ app = App()
218
+ app.demo.launch(**LAUNCH_PARAMETERS)
src/constants.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model config
2
+ MODEL_NAME = "Derify/ChemMRL-alpha"
3
+ SUPPORTED_EMBEDDING_DIMENSIONS = [1024, 768, 512, 256, 128, 64, 32, 16, 8, 4, 2]
4
+ EMBEDDING_DIMENSION = max(SUPPORTED_EMBEDDING_DIMENSIONS)
5
+
6
+ # HNSW index parameters
7
+ HNSW_K = 6
8
+ HNSW_PARAMETERS = {
9
+ # Embedding vector dtype
10
+ "TYPE": "FLOAT32",
11
+ # Embedding vectors are normalized so COSINE and IP are equivalent
12
+ "DISTANCE_METRIC": "IP",
13
+ # Defines the initial capacity of the vector index. It helps in pre-allocating space for the index.
14
+ "INITIAL_CAP": 440,
15
+ # Max number of outgoing edges (connections) for each node in a graph layer.
16
+ "M": 32,
17
+ # Max number of connected neighbors to consider during graph building.
18
+ # Higher values increase accuracy, but also increase index build time.
19
+ "EF_CONSTRUCTION": 512,
20
+ # Max top candidates during KNN search. Higher values increase accuracy, but also increase search latency.
21
+ "EF_RUNTIME": 10,
22
+ }
23
+
24
+ # Gradio launch parameters
25
+ LAUNCH_PARAMETERS = {
26
+ "server_name": "0.0.0.0",
27
+ "server_port": 7860,
28
+ "share": True,
29
+ "debug": False,
30
+ "show_api": False,
31
+ "pwa": True,
32
+ "mcp_server": False,
33
+ }
src/data.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import pandas as pd
4
+
5
+ __data_dir = os.path.join(os.path.dirname(__file__), "data")
6
+
7
+ __dataset_smiles_file = os.path.join(__data_dir, "dataset_smiles.csv")
8
+ __sample_smiles_file = os.path.join(__data_dir, "sample_smiles.csv")
9
+ __isomer_design_subset_file = os.path.join(__data_dir, "isomer_design_subset.csv")
10
+
11
+ DATASET_SMILES = pd.read_csv(__dataset_smiles_file)
12
+ SAMPLE_SMILES = pd.read_csv(__sample_smiles_file)
13
+ ISOMER_DESIGN_SUBSET = pd.read_csv(__isomer_design_subset_file)
src/data/dataset_smiles.csv ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ smiles,name,category
2
+ CCO,Ethanol,Alcohol
3
+ CC(=O)O,Acetic acid,Carboxylic acid
4
+ c1ccccc1,Benzene,Aromatic hydrocarbon
5
+ CC(C)O,Isopropanol,Alcohol
6
+ CCN(CC)CC,Triethylamine,Amine
7
+ c1ccc(cc1)O,Phenol,Aromatic alcohol
8
+ CC(=O)OC1=CC=CC=C1C(=O)O,Aspirin,Carboxylic acid ester
9
+ CN1C=NC2=C1C(=O)N(C(=O)N2C)C,Caffeine,Alkaloid
10
+ CC(C)(C)OC(=O)NC1CCC(CC1)O,Boc-protected cyclohexanol,Protected alcohol
11
+ CCCCCCCCCCCCCCC(=O)O,Palmitic acid,Fatty acid
12
+ c1ccc2c(c1)cccn2,Quinoline,Aromatic heterocycle
13
+ CC1=CC=C(C=C1)C,p-Xylene,Aromatic hydrocarbon
14
+ CCCCO,Butanol,Alcohol
15
+ CC(C)C,Isobutane,Alkane
16
+ c1ccc(cc1)N,Aniline,Aromatic amine
17
+ CC(=O)N,Acetamide,Amide
18
+ CCCCCCCCCCCCCCCCCC(=O)O,Stearic acid,Fatty acid
19
+ c1ccc(cc1)C(=O)O,Benzoic acid,Aromatic carboxylic acid
20
+ CCc1ccccc1,Ethylbenzene,Aromatic hydrocarbon
21
+ CC(C)CC(C)(C)C,"2,2,4-Trimethylpentane",Branched alkane
22
+ O=C1c2ccccc2C(=O)N1C3CCC(=O)NC3=O,Thalidomide,Phthalimides
src/data/isomer_design_subset.csv ADDED
@@ -0,0 +1,415 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ smiles,name,category
2
+ O=C1CCCCC1(c1ccccc1Cl)N1CCCCC1,2-Cl-2'-Oxo-PCP,arylcycloalkylamine
3
+ CCCCNC1(c2ccccc2)CCCCC1,PCB,arylcycloalkylamine
4
+ COc1ccccc1C1(N2CCCCC2)CCCCC1,2-MeO-PCP,arylcycloalkylamine
5
+ c1ccc(C2(n3cccc3)CCCCC2)cc1,PCPyrrole,arylcycloalkylamine
6
+ Fc1cccc(C2(N3CCCC3)CC3CCC2C3)c1,3F-PBCHPy,arylcycloalkylamine
7
+ COc1ccc(C2(NCC3CCCO3)CCCCC2)cc1,1-(4-Methoxyphenyl)-N-[(oxolan-2-yl)methyl]cyclohexan-1-amine,arylcycloalkylamine
8
+ COc1ccc(C2(N3CCCC3)CC3CCC2C3)cc1,4-MeO-PBCHPy,arylcycloalkylamine
9
+ C=CCN(CC)C1(c2ccccc2)CCCCC1,N-Allyl-PCE,arylcycloalkylamine
10
+ CCCCCNC1(c2ccccc2)CCCCC1,PCPe,arylcycloalkylamine
11
+ OC1CCCCC1(c1ccccc1)N1CCCCC1,2'-HO-PCP,arylcycloalkylamine
12
+ Cc1ccccc1C1(N2CCCC(O)C2)CCCCC1,3″-HO-2-Me-PCP,arylcycloalkylamine
13
+ c1ccc(C2(N3CCCCC3)CCCC2)cc1,PCPEP,arylcycloalkylamine
14
+ CCN(C)C1(c2ccccc2C)CCCCC1,2-Me-PCEM,arylcycloalkylamine
15
+ Fc1ccccc1C1(N2CCCC2)CC2CCC1C2,2F-PBCHPy,arylcycloalkylamine
16
+ CC(C)OCCCNC1(c2ccccc2)CCCCC1,1-Phenyl-N-{3-[(propan-2-yl)oxy]propyl}cyclohexan-1-amine,arylcycloalkylamine
17
+ CCNC1(c2ccc(C)cc2)CCCCC1,4-Me-PCE,arylcycloalkylamine
18
+ CCNC1(c2cccc(OC)c2)CCCCC1=O,MXE,arylcycloalkylamine
19
+ CCOC(=O)CCCN(C)C1(c2ccccc2Cl)CCCCC1=O,Et-KE-Bu,arylcycloalkylamine
20
+ CCNC1(c2ccccc2)CCCCC1,PCE,arylcycloalkylamine
21
+ c1cc2c(cc1C1(N3CCOCC3)CCCCC1)OCO2,"3,4-MD-PCMo",arylcycloalkylamine
22
+ OCCNC1(c2ccccc2)CCCCC1,PCEOH,arylcycloalkylamine
23
+ c1ccc(C2(N3CCCCC3)CCCCCCC2)cc1,PCOP,arylcycloalkylamine
24
+ COc1ccc(C2(N3CCCCC3)CC3CCC2C3)cc1,4-MeO-PBCHP,arylcycloalkylamine
25
+ COc1cccc(C2(N3CCCCC3)CCCc3ccccc32)c1,"1-[1-(3-Methoxyphenyl)-1,2,3,4-tetrahydronaphthalen-1-yl]piperidine",arylcycloalkylamine
26
+ CCNC12CCCCC1CCc1ccccc12,"N-Ethyl-1,3,4,9,10,10a-hexahydrophenanthren-4a(2H)-amine",arylcycloalkylamine
27
+ c1ccc([C@]2(N3CCCCC3)C[C@H]3C[C@H]3C2)cc1,"1-[(1R,3r,5S)-3-Phenylbicyclo[3.1.0]hexan-3-yl]piperidine",arylcycloalkylamine
28
+ c1ccc(C2(N3CCCCC3)CN3CCC2CC3)cc1,P3QP,arylcycloalkylamine
29
+ COc1cccc(C2(N3CCCC3)CCCCC2=O)c1,3-MeO-2'-Oxo-PCPy,arylcycloalkylamine
30
+ c1cc2c(cc1C1(N3CCCCC3)CCCCC1)OCCO2,"3,4-ED-PCP",arylcycloalkylamine
31
+ NC1(c2ccccc2Cl)CCCNC1=O,3-Amino-3-(2-chlorophenyl)piperidin-2-one,arylcycloalkylamine
32
+ CC[C@]1(c2ccccc2)OC[C@H]([C@@H]2CCCCN2)O1,CL-1848C,arylcycloalkylamine
33
+ O=[N+]([O-])c1cccc(C2(N3CCCCC3)CCCCC2)c1,3-NO2-PCP,arylcycloalkylamine
34
+ Fc1cccc(C2(N3CCCCC3)CCCCCC2)c1,3F-PCHEP,arylcycloalkylamine
35
+ CCNC1(c2cccc(OC(C)C)c2)CCCCC1=O,iPXE,arylcycloalkylamine
36
+ COc1cc(C2(N3CCCCC3)CCCCC2)ccc1C,3-MeO-4-Me-PCP,arylcycloalkylamine
37
+ O=C1CCC(c2ccccc2)(N2CCCCC2)CC1,4'-Oxo-PCP,arylcycloalkylamine
38
+ CCNC1(c2ccc3c(c2)OCO3)CCCCC1,"3,4-MD-PCE",arylcycloalkylamine
39
+ CNC1(c2ccccc2OC)CCCCC1=O,2-MDCK,arylcycloalkylamine
40
+ CCOc1cccc(C2(N3CCCCC3)CCCCC2)c1,3-EtO-PCP,arylcycloalkylamine
41
+ CNC1(c2ccccc2C)CCCCC1=O,o-MDCK,arylcycloalkylamine
42
+ CNC1(c2cccc(Cl)c2)CCCCC1=O,meta-Ketamine,arylcycloalkylamine
43
+ CCNC1(c2cc(OC)ccc2Br)CCCCC1=O,Bromo-methoxetamine,arylcycloalkylamine
44
+ CNC1(c2cccc(OC)c2)CCCCC1=O,MXM,arylcycloalkylamine
45
+ CCCOC(=O)CCNC1(c2ccccc2Cl)CCCCC1=O,nPr-NKE-Et,arylcycloalkylamine
46
+ CC1CCCCC1(c1ccccc1)N1CCCCC1,2'-Me-PCP,arylcycloalkylamine
47
+ Cc1ccc(C2(N3CCC(O)CC3)CCCCC2O)cc1,"2',4″-HO-4-Me-PCP",arylcycloalkylamine
48
+ NC1(c2ccccc2Cl)CCC(O)CC1=O,"(2,5)-HNK",arylcycloalkylamine
49
+ Fc1cccc(C2(N3CCCCC3)CC3CCC2C3)c1,3F-PBCHP,arylcycloalkylamine
50
+ CC(C)NC1(c2ccccc2)CCCCC1,PCiP,arylcycloalkylamine
51
+ Fc1ccc(C2(N3CCCCC3)CCCCCC2)cc1,4F-PCHEP,arylcycloalkylamine
52
+ CCCNC1(c2ccccc2)CCCC1,PCPEPr,arylcycloalkylamine
53
+ CC(C)Oc1cccc(C2(N)CCCCC2)c1,3-IpO-PCA,arylcycloalkylamine
54
+ CC(O)CNC1(c2ccccc2)CCCCC1,1-[(1-Phenylcyclohexyl)amino]propan-2-ol,arylcycloalkylamine
55
+ Cc1ccc(C2(N(C)C)CCC(O)(CCc3ccccc3)CC2)cc1,MDPC,arylcycloalkylamine
56
+ Cc1cc(O)ccc1C1(N2CCOCC2)CCCCC1,4-HO-2-Me-PCMo,arylcycloalkylamine
57
+ O=C1CCCCC1(c1ccccc1)N1CCCC1,2-Phenyl-2-(pyrrolidin-1-yl)cyclohexan-1-one,arylcycloalkylamine
58
+ CNC1(c2ccccc2Cl)CCCCCC1=O,2-(2-Chlorophenyl)-2-(methylamino)cycloheptan-1-one,arylcycloalkylamine
59
+ CCN(CC)C1(c2ccccc2)CCCCC1,PCDE,arylcycloalkylamine
60
+ COc1cccc([C@@]2(O)CCN(C3(c4ccccc4)CCCCC3)C[C@@H]2CN(C)C)c1,US 7049327 #6,arylcycloalkylamine
61
+ Cc1cccc(C2(N3CCCC3)CC3CCC2C3)c1,3-Me-PBCHPy,arylcycloalkylamine
62
+ C#Cc1ccc2c(c1)C(c1ccccc1F)=N[C@@H](C)c1c(C(=O)N(C)C)ncn1-2,GL-i-54,aryldiazepine
63
+ O=C1CN=C(c2c(F)cccc2F)c2cc(Cl)ccc2N1,Ro-07-3953,aryldiazepine
64
+ O=C1CN=C(c2ccn[nH]2)c2cc(Cl)ccc2N1,SCHEMBL9684958,aryldiazepine
65
+ C#Cc1ccc2c(c1)C(c1ccccn1)=NCc1c(C(N)=O)ncn1-2,MP-ii-065,aryldiazepine
66
+ CN1C(=O)CN=C(c2ccccc2F)c2c(Cl)cccc21,Ro-13-0699,aryldiazepine
67
+ C#Cc1ccc2c(c1)C(c1ccccc1)=NCc1c(C(=O)OCC(F)(F)F)ncn1-2,DM-ii-20,aryldiazepine
68
+ O=C1OCCC2N=C(c3ccccc3)c3ccccc3-n3cnc1c32,"8-Phenyl-6,6a-dihydro-4-oxa-2,7,12b-triazabenzo[b]cyclopenta[kl]heptalen-3(5H)-one",aryldiazepine
69
+ CCC1C(C)=NN=C(c2ccc(OC)c(OC)c2)c2cc(OC)c(OC)cc21,Tofisopam,aryldiazepine
70
+ CN1C(=O)CN=C(c2ccc(F)cc2)c2cc(Cl)ccc21,4F-Diazepam,aryldiazepine
71
+ CC(C)COC(=O)c1ncn2c1C1CCCN1C(=O)c1c(Cl)cccc1-2,Ro-16-7082,aryldiazepine
72
+ CN1C(=O)CN=C(c2cccs2)c2cc(Cl)ccc21,WZ-113,aryldiazepine
73
+ CC(=O)c1ccc2c(c1)C(c1ccccc1)=NCC(=O)N2,Ro-20-3053,aryldiazepine
74
+ C#Cc1ccc2c(c1)C(=O)N(C)Cc1c(C(=O)OC(C)(C)C)ncn1-2,RY-24,aryldiazepine
75
+ CC(C)(C)OC(=O)c1ncn2c1C1CCCN1C(=O)c1c(F)cccc1-2,Ro-16-8912,aryldiazepine
76
+ O=C1CN=C(c2ccccc2F)c2cc(Cl)ccc2N1CCO,Ro-07-2750,aryldiazepine
77
+ CN1C(=O)CN=C(c2ccccc2Cl)c2cc([N+](=O)[O-])ccc21,Ro-05-4082,aryldiazepine
78
+ Cc1nnc2n1-c1sc(Cl)cc1C(c1ccccc1)=NC2,Deschloroclotizolam,aryldiazepine
79
+ CCOC(=O)c1ncn2c1C(C)N=C(c1ccc(F)cc1)c1cc(F)ccc1-2,"Ethyl 8-fluoro-6-(4-fluorophenyl)-4-methyl-4H-imidazo[1,5-a][1,4]benzodiazepine-3-carboxylate",aryldiazepine
80
+ O=C1CN=C(c2ccccc2F)c2cc(Cl)c(Cl)cc2N1,Ro-20-8065,aryldiazepine
81
+ CN1C(=O)CN=C(c2c(F)cccc2F)c2cc(Br)ccc21,Ro-13-3780,aryldiazepine
82
+ CN1C(=O)CC(=O)N(c2ccccc2)c2cc(Cl)ccc21,Clobazam,aryldiazepine
83
+ OCc1nnc2n1-c1ccc(Cl)cc1C(c1ccccc1)=NC2,alpha-Hydroxyalprazolam,aryldiazepine
84
+ O=C1Nc2ccc(Cl)cc2C(c2ccccc2)=NC1O,Oxazepam,aryldiazepine
85
+ CCOC(=O)c1ncn2c1CN=C(c1ccc([N+](=O)[O-])cc1)c1ccccc1-2,Ro-23-2896,aryldiazepine
86
+ CN1C(=O)CN=C(c2ccccc2F)c2cc(Br)ccc21,Flubrometazepam,aryldiazepine
87
+ CN(C)C(=O)c1nc2n(n1)-c1ccc(Cl)cc1C(c1ccccc1Cl)=NC2,Rilmazolam,aryldiazepine
88
+ CC1N=C(c2ccccc2F)c2cc(Cl)ccc2NC1=O,Ro-11-4878,aryldiazepine
89
+ CCOC(=O)c1ncn2c1C1CCCN1C(=O)c1cc(Br)ccc1-2,RY-054,aryldiazepine
90
+ CCOC(=O)c1ncn2c1C1CCN1C(=O)c1c(Cl)cccc1-2,Ro-16-0858,aryldiazepine
91
+ CN1C(=O)CN=C(c2ccc(Cl)cc2)c2cc(Cl)ccc21,Ro-05-4864,aryldiazepine
92
+ CN(C)CCc1nnc2n1-c1ccc(Cl)cc1C(c1ccccc1)=NC2,U-43465F,aryldiazepine
93
+ CN1C(=O)CN=C(c2ccccc2F)c2c(Cl)cc(Cl)cc21,Ro-13-0882,aryldiazepine
94
+ CCc1ccc2c(c1)C(c1ccccc1)=NCC(=O)N2,Ro-20-2533,aryldiazepine
95
+ CCOC(=O)c1ncn2c1CC=C(c1ccccc1F)c1ccccc1-2,Ro-15-2200,aryldiazepine
96
+ O=C1CC=C(c2ccccc2Cl)c2cc([N+](=O)[O-])ccc2N1,Ro-15-8867,aryldiazepine
97
+ Cc1cc2c(cc1Cl)NC(=O)CN=C2c1ccccc1F,Ro-20-8552,aryldiazepine
98
+ N#Cc1ncn2c1CN=C(c1ccc(Cl)cc1)c1cc(Cl)ccc1-2,"8-Chloro-6-(4-chlorophenyl)-4H-imidazo[1,5-a][1,4]benzodiazepine-3-carbonitrile",aryldiazepine
99
+ CC(C)c1nc(-c2ncn3c2CN(C)C(=O)c2c(Cl)cccc2-3)no1,FG-8205,aryldiazepine
100
+ Cc1nnc2n1-c1ccc([N+](=O)[O-])cc1C(c1ccccc1Cl)=NC2,Clonazolam,aryldiazepine
101
+ O=C1CN=C(c2ccccc2[N+](=O)[O-])c2cc(Br)ccc2N1,QH-II-067a,aryldiazepine
102
+ NC(=O)c1ncn2c1CC=C(c1ccccc1F)c1cc(Cl)ccc1-2,Ro-14-3930,aryldiazepine
103
+ COC(=O)CC[C@@H]1N=C(c2ccccn2)c2cc(Br)ccc2-n2c(C)cnc21,CNS-7056,aryldiazepine
104
+ CN1C(=O)CN=C(C2CCC2)c2cc(F)ccc21,"5-Cyclobutyl-7-fluoro-1-methyl-1,3-dihydro-2H-1,4-benzodiazepin-2-one",aryldiazepine
105
+ O=C1CN=C(c2c(F)cccc2Cl)c2cc(Cl)ccc2N1,Ro-07-5193,aryldiazepine
106
+ CN1C(=O)CN=C(c2ccccc2F)c2cc(I)ccc21,Ro-07-9957,aryldiazepine
107
+ O=C1CN=C(c2ccccc2)c2cc(Cl)ccc2N1CC1CC1,Prazepam,aryldiazepine
108
+ CCOC(=O)c1ncn2c1CN=C(c1cccc([N+](=O)[O-])c1)c1cc(F)ccc1-2,"Ethyl 8-fluoro-6-(3-nitrophenyl)-4H-imidazo[1,5-a][1,4]benzodiazepine-3-carboxylate",aryldiazepine
109
+ Clc1ccc2c(c1)-c1ncnn1Cc1c(Cl)ncn1-2,Ro4882224,aryldiazepine
110
+ [N-]=[N+]=Nc1ccc2c(c1)C(c1ccccc1F)=NCC(=O)N2,Ro-14-3074,aryldiazepine
111
+ Fc1ccccc1C1=NCC=Cc2ccc(Cl)cc21,Ro-22-1274,aryldiazepine
112
+ Nc1ncc2c(n1)-c1ccc(Cl)cc1C(c1ccccc1F)=NC2,Ro-22-2038,aryldiazepine
113
+ Clc1ccc2c(c1)C(c1ccccc1)=NCc1nncn1-2,Estazolam,aryldiazepine
114
+ Cc1nn(C)c2c1C(c1ccccc1F)=NCC(=O)N2C,Zolazepam,aryldiazepine
115
+ Cc1nnc2n1-c1ccc(Cl)cc1C(c1ccccn1)=NC2,Pyclazolam,aryldiazepine
116
+ S=C1CN=C(c2ccccc2)c2cc(Cl)ccc2N1,Thionordazepam,aryldiazepine
117
+ O=C1CN=C(c2ccccc2)c2cc(Cl)ccc2N1CC(F)(F)F,Halazepam,aryldiazepine
118
+ C#Cc1ccc2c(c1)C(c1ccccc1)=NCC1=N/C(=C\N3CCN(C)CC3)C(=O)N12,PS-i-37,aryldiazepine
119
+ C#Cc1ccc2c(c1)C(c1ccccc1F)=NCc1c(C(=O)OCC(F)(F)F)ncn1-2,JY-i-59,aryldiazepine
120
+ O=C1CN=C(c2ccccc2F)c2cc([N+](=O)[O-])ccc2N1,Fonazepam,aryldiazepine
121
+ CN1CCN(/C=C2\N=C3CN=C(c4ccccc4)c4cc(Br)ccc4N3C2=O)CC1,PS-1-35,aryldiazepine
122
+ CCCCCCC(C)(C)c1ccc([C@@H]2CCC[C@H](O)C2)c(O)c1,"(1R,3S) CP 47,497",cannabinoid
123
+ CCCc1ccc(C(=O)c2cn(CCCCCF)c3ccccc23)c2ccccc12,SGT-62,cannabinoid
124
+ CC(C)[C@H](NC(=O)c1cn(Cc2ccc(F)cc2)c2ccccc12)C(N)=O,AB-FUBICA,cannabinoid
125
+ CCCCCn1nc(C(=O)N[C@@H](Cc2ccccc2)C(=O)OC)c2ccccc21,MPP-PINACA,cannabinoid
126
+ O=C(Cc1cn(Cc2ccc(F)cc2)c2ccccc12)NC1C2CC3CC(C2)CC1C3,AFUBIATA,cannabinoid
127
+ CC(C)(C)c1nc(N2CCC(F)(F)C2)c2nnn(Cc3ccccc3S(C)(=O)=O)c2n1,"5-tert-Butyl-7-(3,3-difluoropyrrolidin-1-yl)-3-{[2-(methanesulfonyl)phenyl]methyl}-3H-[1,2,3]triazolo[4,5-d]pyrimidine",cannabinoid
128
+ CCC(C(N)=O)N(C)C(=O)c1nn(Cc2ccc(F)cc2)c2ccccc12,AB-FUBINACA isomer 5,cannabinoid
129
+ COc1cccc2c3c(=O)n([C@@H]4C(C)(C)[C@@H]5CC[C@@]4(C)C5)ccc3n(Cc3ccncc3)c12,WO 2001/058869 #190,cannabinoid
130
+ CCCC(F)Cn1cc(C(=O)C2C(C)(C)C2(C)C)c2ccccc21,(2-Fluoropentyl) XLR-11,cannabinoid
131
+ O=C(Nc1ccccc1)c1cn(CCCCCF)c2ccccc12,LTI-701,cannabinoid
132
+ C=CCCCn1nc(C(=O)N[C@H](C(=O)OC)C(C)C)c2ccccc21,MMB-4en-PINACA,cannabinoid
133
+ O=C(Nc1ccccc1)c1nn(CC2CCOCC2)c2ccccc12,SGT-224,cannabinoid
134
+ Cc1ccc(C(=O)NC(C)(C)c2ccccc2)cc1S(=O)(=O)N1CCC(F)(F)CC1,SGT-233,cannabinoid
135
+ CCCCCn1nc(C(=O)c2ccc(OC)c3ccccc23)c2ccccc21,SGT-35,cannabinoid
136
+ CC1(C)C(C(=O)c2cn(CC3CCCCC3)c3ccccc23)C1(C)C,(CHM) UR-144,cannabinoid
137
+ CN1CCCCC1Cn1cc(C(=O)c2ccc(N=C=S)c3ccccc23)c2ccc(N=C=S)cc21,AM-2215,cannabinoid
138
+ CCCCCCC1(c2ccc(-c3cc(C)cc(C)c3)c(O)c2)CC1,"4-(1-Hexylcyclopropyl)-3',5'-dimethyl[1,1'-biphenyl]-2-ol",cannabinoid
139
+ COC(=O)[C@@H](NC(=O)c1cn(Cc2ccc(F)cc2)c2ncccc12)C(C)(C)C,MDMB-FUB7AICA,cannabinoid
140
+ CN1CCCCC1Cn1cc(C(=O)c2ccccc2I)c2ccccc21,AM-2233,cannabinoid
141
+ O=C(c1cccc2ccccc12)n1c(-c2ccncc2)nc2ccccc21,(Naphthalen-1-yl)[2-(pyridin-4-yl)-1H-benzimidazol-1-yl]methanone,cannabinoid
142
+ C=CCCCn1nc(C(=O)N[C@H](C(=O)OC)C(C)(C)C)c2ccccc21,MDMB-4en-PINACA,cannabinoid
143
+ Oc1ccc(/C=C2\C=C(CCN3CCOCC3)c3ccccc32)c2ccccc12,US 5292736 #19,cannabinoid
144
+ CCc1c(C(=O)NN2CCCCC2)nn(-c2ccc(Cl)cc2Cl)c1-c1ccc(C#Cc2ccc(C(F)(F)F)cc2)s1,TM-38837,cannabinoid
145
+ COC(=O)[C@H](Cc1ccccc1)NC(=O)c1cn(CCCCCF)c2ccccc12,MPHP-2201,cannabinoid
146
+ Cc1ccc2c(C(C[N+](=O)[O-])c3ccccc3)c(-c3ccccc3)[nH]c2c1,GAT211,cannabinoid
147
+ CCCCCn1nc(C(=O)NC2CCCCC2)c2ccccc21,SGT-85,cannabinoid
148
+ CN1CCCCC1Cn1cc(C(=O)c2ccc([N+](=O)[O-])c3ccccc23)c2ccccc21,AM-1299,cannabinoid
149
+ CCc1c(C)cc(C(=O)NC2(C(=O)O)CCCCC2)c(=O)n1Cc1ccc(F)cc1,S-777469,cannabinoid
150
+ CCCCCC(C)NC(=O)c1nn(CCCCC)c2ccccc12,SGT-71,cannabinoid
151
+ CC1(C)Oc2cc(C34CC5CC(CC(C5)C3)C4)cc(O)c2[C@@H]2CC(O)CC[C@H]21,"(6aR,10aR)-3-(Adamantan-1-yl)-6,6-dimethyl-6a,7,8,9,10,10a-hexahydro-6H-dibenzo[b,d]pyran-1,9-diol",cannabinoid
152
+ C=C(C)[C@H]1CCC(CO)=C[C@@H]1c1c(O)cc(C(C)(C)CCCCN2CCOCC2)cc1O,"(1'S,2'S)-5'-(Hydroxymethyl)-4-[2-methyl-6-(morpholin-4-yl)hexan-2-yl]-2'-(prop-1-en-2-yl)-1',2',3',4'-tetrahydro[1,1'-biphenyl]-2,6-diol",cannabinoid
153
+ O=C(N/N=C1\C(=O)N(CCCCCF)c2ccccc21)c1ccccc1,BZO-5F-POXIZID,cannabinoid
154
+ CCCCCOc1c(OC)ccc2cc(C(=O)NCc3ccc4c(c3)OCO4)c(=O)[nH]c12,JTE-907,cannabinoid
155
+ CCCCn1nc(C(=O)N[C@@H](Cc2ccccc2)C(=O)OC)c2ccccc21,MPP(N)-073,cannabinoid
156
+ CCCCCCC(C)(C)c1ccc([C@@H]2CCC[C@@H](O)C2)c(O)c1,"(R,R)-epi-CP 47,497",cannabinoid
157
+ CCCCCOc1ccc(C(=O)c2cccc3ccccc23)c2ccccc12,CB-13,cannabinoid
158
+ COc1ccccc1OC(=O)c1ccc(C)c(S(=O)(=O)N2CCOCC2)c1,2-Methoxyphenyl 4-methyl-3-(morpholine-4-sulfonyl)benzoate,cannabinoid
159
+ CCCCCC#Cc1cc(O)c2c(c1)OC(C)(C)[C@@H]1CC=C(C)C[C@@H]21,AMG-1,cannabinoid
160
+ CC(C)[C@H](NC(=O)c1cn(CCCCCF)c2ccccc12)C(N)=O,5F-ABICA,cannabinoid
161
+ CCCCCn1cc(C(=O)NC23CC4CC(CC(C4)C2)C3)c(=O)c2ccc(F)cc21,"N-(Adamantan-1-yl)-7-fluoro-4-oxo-1-pentyl-1,4-dihydroquinoline-3-carboxamide",cannabinoid
162
+ CC1=CC[C@@H]2[C@@H](C1)c1c(O)cc(C(C)(C)CCCCCC#N)cc1OC2(C)C,O-774,cannabinoid
163
+ CC(C)(C)[C@H](NC(=O)n1c(=O)n(CCN2CCOCC2)c2ccccc21)C(N)=O,WO 2008/032164 #4,cannabinoid
164
+ COC(=O)[C@H](Cc1ccccc1)NC(=O)c1cn(CC2CCCCC2)c2ccccc12,MPP-CHMICA,cannabinoid
165
+ Fc1ccc2nc(-c3ccccn3)n(Cc3cccc4ccccc34)c2c1,6-Fluoro-1-[(naphthalen-1-yl)methyl]-2-(pyridin-2-yl)-1H-benzimidazole,cannabinoid
166
+ CCCCCn1cc(C(=O)N[C@@H](C)c2ccccc2)c2ccccc21,1-Pentyl-N-[(1S)-1-phenylethyl]-1H-indole-3-carboxamide,cannabinoid
167
+ CCCCCCCC(C)c1cc(OC(=O)CCCN(CC)CC)c2c(c1)OC(C)(C)C1=C2CC(C)CC1,SP-325,cannabinoid
168
+ CCCCCn1cc(C(=O)c2cccc3ccccc23)cc1-c1cccc(C)c1,JWH-346,cannabinoid
169
+ O=C(Cc1ccccc1)N/N=C1\C(=O)N(CC2CCCCC2)c2cc(OCCN3CCOCC3)ccc21,"N'-{1-(Cyclohexylmethyl)-6-[2-(morpholin-4-yl)ethoxy]-2-oxo-1,2-dihydro-3H-indol-3-ylidene}-2-phenylacetohydrazide",cannabinoid
170
+ Cc1c(C(=O)C2C(C)(C)C2(C)C)c2ccccc2n1CCCCCF,2-Me-XLR-11,cannabinoid
171
+ COc1ccc2c(c1)CCC2CNC(=O)c1cn(CCCCCF)c2ccccc12,SGT-105,cannabinoid
172
+ CCCCCc1cc(O)c2c(c1)OC(C)(C)C(CCC(C)=O)C2=O,CBCN,cannabinoid
173
+ CCCCCn1nc(C(=O)NC(C)(C)c2ccc(F)cc2)c2ccccc21,SGT-60,cannabinoid
174
+ CC(C)(C)[C@H](NC(=O)c1nn(CC2CCCCCC2)c2ccccc12)C(=O)NCCO,WO 2009/106980 #433,cannabinoid
175
+ CC(C)(NC(=O)c1cn(Cc2ccc(F)cc2)c2ccccc12)c1ccccc1,CUMYL-FUBICA,cannabinoid
176
+ COC(=O)[C@@H](NC(=O)c1nn(CC2CCCCC2)c2ccccc12)C(C)(C)C,MDMB(N)-CHM,cannabinoid
177
+ CCCCCn1nc(C(=O)c2cccc3ccccc23)c2ccccc21,SGT-17,cannabinoid
178
+ CCCCCn1cc(C(=O)N[C@H](C(N)=O)C(C)(C)C)c2ccccc21,ADBICA,cannabinoid
179
+ CN1CCCCC1Cn1cc(C(=O)c2cc(N=C=S)ccc2I)c2ccc(N=C=S)cc21,AM-2223,cannabinoid
180
+ CCCCCCCCCn1cc(C(=O)c2cccc3ccccc23)c2ccccc21,(Nonyl) JWH-018,cannabinoid
181
+ CCCCCCC(C)(C)c1cc(OC)c([C@@H]2C=C(CO)C3CC2C3(C)C)c(OC)c1,HU-433,cannabinoid
182
+ C=CCc1cc(OC)c(OC)c(OC)c1OC,"2,3,4,5-Tetramethoxyphenylprop-2-ene",essential oil
183
+ C/C=C\c1ccc(O)c(OC)c1,cis-4-Hydroxy-3-methoxyphenylprop-1-ene,essential oil
184
+ C/C=C/c1ccc2c(c1OC)OCO2,Isocroweacin,essential oil
185
+ C/C=C\c1cc(OC)c(O)c(OC)c1,"cis-4-Hydroxy-3,5-dimethoxyphenylprop-1-ene",essential oil
186
+ C=CCc1ccc2c(c1OC)OCO2,Croweacin,essential oil
187
+ C/C=C\c1cc2c(cc1OC)OCO2,"cis-2-Methoxy-4,5-methylenedioxyphenylprop-1-ene",essential oil
188
+ C=CCc1ccc2c(c1)OCO2,Safrole,essential oil
189
+ C/C=C\c1cc(OC)c2c(c1)OCO2,cis-Isomyristicin,essential oil
190
+ C/C=C\c1ccc(OC)cc1OC,"cis-2,4-Dimethoxyphenylprop-1-ene",essential oil
191
+ C/C=C\c1ccc2c(c1OC)OCO2,"cis-2-Methoxy-3,4-methylenedioxyphenylprop-1-ene",essential oil
192
+ C/C=C/c1ccc(OC)c(OC)c1,Methylisoeugenol,essential oil
193
+ C=CCc1ccc(OC)cc1OC,Osmorrhizole,essential oil
194
+ C=CCc1ccc(OC)c(OC)c1,Methyleugenol,essential oil
195
+ C=CCc1ccc(O)c(OC)c1,Eugenol,essential oil
196
+ C=CCc1cc2c(c(OC)c1OC)OCO2,Dillapiole,essential oil
197
+ C/C=C\c1ccc2c(c1)OCO2,alpha-Isosafrole,essential oil
198
+ C/C=C/c1cc(OC)c(OC)c(OC)c1,Isoelemicin,essential oil
199
+ C=CCc1ccc(OC)c(O)c1,Chavibetol,essential oil
200
+ C=CCc1cc(OC)c(OC)c(OC)c1,Elemicin,essential oil
201
+ C=CCc1cc(OC)cc(OC)c1,"3,5-Dimethoxyphenylprop-2-ene",essential oil
202
+ C/C=C\c1cc(OC)c(OC)c(OC)c1,cis-Isoelemicin,essential oil
203
+ C/C=C/c1cc(OC)c(OC)c(OC)c1OC,"trans-2,3,4,5-Tetramethoxyphenylprop-1-ene",essential oil
204
+ C/C=C/c1cc(OC)c2c(c1OC)OCO2,Isoapiole,essential oil
205
+ C/C=C\c1ccc(OC)c(O)c1,cis-3-Hydroxy-4-methoxyphenylprop-1-ene,essential oil
206
+ C=CCc1ccc(OC)cc1,Estragole,essential oil
207
+ C/C=C\c1cc(OC)c2c(c1OC)OCO2,"cis-2,5-Dimethoxy-3,4-methylenedioxyphenylprop-1-ene",essential oil
208
+ C=CCc1cc(OC)c2c(c1OC)OCO2,Apiole,essential oil
209
+ C/C=C/c1ccc(OC)cc1OC,Nothosmyrnol,essential oil
210
+ C/C=C/c1cc(OC)cc(OC)c1,"trans-3,5-Dimethoxyphenylprop-1-ene",essential oil
211
+ C/C=C\c1cc2c(c(OC)c1OC)OCO2,"cis-2,3-Dimethoxy-4,5-methylenedioxyphenylprop-1-ene",essential oil
212
+ C/C=C\c1ccc(OC)cc1,cis-4-Methoxyphenylprop-1-ene,essential oil
213
+ C/C=C/c1cc(OC)c(O)c(OC)c1,"2,6-Dimethoxy-4-[(1E)-prop-1-en-1-yl]phenol",essential oil
214
+ C=CCc1cc(OC)c(OC)cc1OC,γ-Asarone,essential oil
215
+ C/C=C/c1ccc(OC)cc1,Anethole,essential oil
216
+ C=CCc1cc2c(cc1OC)OCO2,Asaricin,essential oil
217
+ C/C=C/c1cc2c(c(OC)c1OC)OCO2,Isodillapiole,essential oil
218
+ C/C=C/c1cc(OC)c(OC)cc1OC,Asarone,essential oil
219
+ C/C=C/c1ccc(O)c(OC)c1,Isoeugenol,essential oil
220
+ C/C=C\c1cc(OC)cc(OC)c1,"cis-3,5-Dimethoxyphenylprop-1-ene",essential oil
221
+ C/C=C\c1cc(OC)c(OC)cc1OC,beta-Asarone,essential oil
222
+ C=CCc1cc(OC)c2c(c1)OCO2,Myristicin,essential oil
223
+ C/C=C/c1ccc(OC)c(O)c1,2-Methoxy-5-[(1E)-prop-1-en-1-yl]phenol,essential oil
224
+ C/C=C/c1cc(OC)c2c(c1)OCO2,Isomyristicin,essential oil
225
+ C/C=C\c1ccc(OC)c(OC)c1,"cis-3,4-Dimethoxyphenylprop-1-ene",essential oil
226
+ C=CCc1cc(OC)c(O)c(OC)c1,5-Methoxyeugenol,essential oil
227
+ C/C=C/c1ccc2c(c1)OCO2,beta-Isosafrole,essential oil
228
+ C/C=C\c1cc(OC)c(OC)c(OC)c1OC,"cis-2,3,4,5-Tetramethoxyphenylprop-1-ene",essential oil
229
+ C/C=C/c1cc2c(cc1OC)OCO2,Carpacin,essential oil
230
+ CCC(=O)N(c1ccccc1)C1(COC)CCN(CC(O)c2cccs2)CC1,beta-Hydroxy-sufentanil,fentanyl
231
+ CCC(=O)N(CCc1ccccc1)C1CCN(CCc2ccccc2)CC1,(ethylene) Fentanyl,fentanyl
232
+ CCC(=O)N(c1ccccc1F)C1(c2ccccc2)CCN(CCn2cccn2)CC1,N-(2-Fluorophenyl)-N-{4-phenyl-1-[2-(1H-pyrazol-1-yl)ethyl]piperidin-4-yl}propanamide,fentanyl
233
+ CCC(=O)N(c1ccccc1)C1CCN(C(C)Cc2cc(OC)c(I)cc2OC)CC1,N-(DOI) fentanyl,fentanyl
234
+ CCC(=O)N(c1ccccc1)C1(COC(=O)C(C)(C)C)CCN(CCN2C(=O)c3ccccc3C2=O)CC1,"{1-[2-(1,3-Dioxo-1,3-dihydro-2H-isoindol-2-yl)ethyl]-4-[phenyl(propanoyl)amino]piperidin-4-yl}methyl 2,2-dimethylpropanoate",fentanyl
235
+ CC(C)C(=O)N(c1cccc(F)c1)C1CCN(CCc2ccccc2)CC1,m-Fluoro-isobutyrylfentanyl,fentanyl
236
+ CCCC(=O)N(c1ccc(OC)cc1)C1CCN(CCc2ccccc2)CC1,p-MeO-BF,fentanyl
237
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(Cc2ccccc2)CC1,Benzylcarfentanil,fentanyl
238
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCc2ccsc2)CC1,Methyl 4-[phenyl(propanoyl)amino]-1-[2-(thiophen-3-yl)ethyl]piperidine-4-carboxylate,fentanyl
239
+ COCC(=O)N(c1ccc(C)cc1)C1CCN(CCc2ccccc2)CC1,p-Methyl-methoxyacetylfentanyl,fentanyl
240
+ CCCCC(=O)N(c1ccc(OC)cc1)C1CCN(CCc2ccccc2)CC1,p-Methoxy-valerylfentanyl,fentanyl
241
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)CC1F,NFEPP,fentanyl
242
+ CCC(=O)N(c1ccccc1)C1CCN(C(C)Cc2cc(OC)c(Br)cc2OC)CC1,N-(DOB) fentanyl,fentanyl
243
+ CCCC(=O)N(c1ccccc1)C1CCN(C)CC1,N-Methyl-butyrylfentanyl,fentanyl
244
+ O=C(c1ccco1)N(c1ccccc1)C1CCN(CCc2ccc(O)cc2)CC1,4'-Hydroxy-furanylfentanyl,fentanyl
245
+ CCC(=O)OCC1(N(C(=O)CC)c2ccccc2)CCN(CCN2C(=O)c3ccccc3C2=O)CC1,"{1-[2-(1,3-Dioxo-1,3-dihydro-2H-isoindol-2-yl)ethyl]-4-[phenyl(propanoyl)amino]piperidin-4-yl}methyl propanoate",fentanyl
246
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)C(C)C1,2-Methylfentanyl,fentanyl
247
+ CC(=O)N(c1ccccc1)C1CCN(CCCc2ccccc2)CC1,Phenylpropyl-acetyl-norfentanyl,fentanyl
248
+ CCC(=O)N(c1ccccc1)C1CCN(CCOc2ccccc2)CC1,POE-F,fentanyl
249
+ O=C(c1ccco1)N(c1ccccc1)C1CCNCC1,Furanyl-norfentanyl,fentanyl
250
+ CCC(=O)N(c1ccccc1)C1CCN(Cc2ccccc2)CC1,R-4129,fentanyl
251
+ Cc1ccc(NC2CCN(CCc3ccccc3)CC2)cc1,p-Me-4-ANPP,fentanyl
252
+ CCC(=O)N(c1ccccc1)C1(C(=O)O)CCN(CCc2ccccc2)C(O)C1,2-Hydroxycarfentanil acid,fentanyl
253
+ COCC(=O)N(c1ccc(F)cc1)C1CCN(CCc2ccccc2)CC1,p-Fluoro-methoxyacetylfentanyl,fentanyl
254
+ Cc1cccc(N(C(=O)c2ccco2)C2CCN(CCc3ccccc3)CC2)c1,m-Methyl-furanylfentanyl,fentanyl
255
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2F)CC1,2″-Fluorofentanyl,fentanyl
256
+ COc1ccccc1N(C(=O)c1ccco1)C1CCN(CCc2ccccc2)CC1,o-Methoxy-furanylfentanyl,fentanyl
257
+ CCC(=O)N(c1ccccc1)C1CCN(CC(O)c2ccc(F)cc2)CC1,N-{1-[2-(4-Fluorophenyl)-2-hydroxyethyl]piperidin-4-yl}-N-phenylpropanamide,fentanyl
258
+ CC(=O)N(c1ccccc1)C1CCN(CCc2cccs2)CC1,Acetylthiofentanyl,fentanyl
259
+ COCC(=O)N(c1cccc(F)c1)C1CCN(CCc2ccccc2)CC1,m-Fluoro-methoxyacetylfentanyl,fentanyl
260
+ COc1cc(CCN2CCC(N(C(=O)C(=O)CCC(=O)O)c3ccccc3)CC2)ccc1O,N-Phenyl-N-[1-(2-phenylethyl)piperidin-4-yl]-2-oxo-4-carboxybutanamide,fentanyl
261
+ CCC(=O)N(c1ccccc1)C1(COC)CCN(CCn2nnn(CC)c2=O)CC1,R-39209,fentanyl
262
+ CCC(=O)N(c1ccc(Cl)cc1)C1CCN(CCc2ccccc2)CC1,p-CF,fentanyl
263
+ CCC(=O)N(c1ccccc1)C1CCNCC1,Norfentanyl,fentanyl
264
+ COC(=O)CCN1CCC(Nc2ccccc2)(C(=O)OC)CC1,Despropionyl remifentanil,fentanyl
265
+ CCC(=O)N(c1ccccc1)C1(c2nc(C)cs2)CCN(CCc2ccccc2)CC1,"N-[4-(4-Methyl-1,3-thiazol-2-yl)-1-(2-phenylethyl)piperidin-4-yl]-N-phenylpropanamide",fentanyl
266
+ CCC(=O)N(c1ccccc1)C1(c2ccccc2)CCN(CCc2ccccc2)CC1,4-Phenylfentanyl,fentanyl
267
+ CCC(=O)N(c1ccccc1C)C1CCN(CCc2ccccc2)CC1,o-Methylfentanyl,fentanyl
268
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCCCCF)CC1,Fluoropentyl-norcarfentanil,fentanyl
269
+ O=C(c1ccco1)N(c1ccccc1)C1CCN(Cc2ccccc2)CC1,Furanylbenzylfentanyl,fentanyl
270
+ CCC(=O)N(c1ccc2ncoc2c1)C1CCN(CCc2ccccc2)CC1,N-Benzoxazolyl-fentanyl,fentanyl
271
+ COCC(=O)N(c1cccc(C)c1)C1CCN(CCc2ccccc2)CC1,m-Methyl-methoxyacetylfentanyl,fentanyl
272
+ CC(C)C(=O)OCC1(N(C(=O)C(C)C)c2ccccc2)CCN(CCN2C(=O)c3ccccc3C2=O)CC1,"{1-[2-(1,3-Dioxo-1,3-dihydro-2H-isoindol-2-yl)ethyl]-4-[(2-methylpropanoyl)(phenyl)amino]piperidin-4-yl}methyl 2-methylpropanoate",fentanyl
273
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCc2ccccn2)CC1,Methyl 4-[phenyl(propanoyl)amino]-1-[2-(pyridin-2-yl)ethyl]piperidine-4-carboxylate,fentanyl
274
+ c1ccc(CCN2CCC(Nc3ccccc3)CC2)cc1,ANPP,fentanyl
275
+ CCCc1cc(OC)c(CCN2CCC(N(C(=O)CC)c3ccccc3)CC2)cc1OC,N-(2C-P) fentanyl,fentanyl
276
+ CCC(=O)N(c1ccccc1)C1CCN(CC(O)c2ccncc2)CC1C,N-{1-[2-Hydroxy-2-(pyridin-4-yl)ethyl]-3-methylpiperidin-4-yl}-N-phenylpropanamide,fentanyl
277
+ CCC(=O)N(c1ccccc1)C1CCN(CC(=O)c2cccc(F)c2)CC1,N-{1-[2-(3-Fluorophenyl)-2-oxoethyl]piperidin-4-yl}-N-phenylpropanamide,fentanyl
278
+ CCCCc1cc(OC)c(CC(C)N2CCC(N(C(=O)CC)c3ccccc3)CC2)cc1OC,N-(DOBU) fentanyl,fentanyl
279
+ COCC(=O)N(c1ccccc1)C1C(C)CN(CCn2cccn2)CC1C,"N-{3,5-Dimethyl-1-[2-(1H-pyrazol-1-yl)ethyl]piperidin-4-yl}-2-methoxy-N-phenylacetamide",fentanyl
280
+ Cc1ccc(N(C(=O)C2CCCO2)C2CCN(CCc3ccccc3)CC2)cc1,p-Methyl-tetrahydrofuranylfentanyl,fentanyl
281
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2cc(OC)cc(OC)c2)CC1,"3″,5″-DiMeO-F",fentanyl
282
+ CC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)CC1,Acetylfentanyl,fentanyl
283
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccc(F)cc2)CC1,4″-Fluorofentanyl,fentanyl
284
+ CCC(=O)N(c1ccccc1)C1(COC(=O)OC)CCN(CCc2cccs2)CC1,Methyl {4-[phenyl(propanoyl)amino]-1-[2-(thiophen-2-yl)ethyl]piperidin-4-yl}methyl carbonate,fentanyl
285
+ CCC(=O)[N+]([O-])(c1ccccc1)C1(C(=O)OC)CCN(CCc2ccccc2)CC1,Carfentanil N-oxide,fentanyl
286
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCc2cccc(O)c2)CC1,3″-Hydroxycarfentanil,fentanyl
287
+ CCC(=O)N(c1ccccc1)C1CCN(C(C)C(=O)OC(C)C)CC1,Propan-2-yl 2-{4-[phenyl(propanoyl)amino]piperidin-1-yl}propanoate,fentanyl
288
+ O=C(C1CCC1)N(c1ccc(Cl)cc1)C1CCN(CCc2ccccc2)CC1,p-Chloro-cyclobutylfentanyl,fentanyl
289
+ CCC(C)C(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)CC1,alpha'-Methyl-butyrylfentanyl,fentanyl
290
+ Oc1cc2c(cc1O)CNCC2,Norsalsolinol,neurotoxin
291
+ CC(N)Cc1ccc(Cl)cc1,PCA,neurotoxin
292
+ CC1NCCc2cc(O)c(O)cc21,Salsolinol,neurotoxin
293
+ CC(N)Cc1ccc(Br)cc1,PBA,neurotoxin
294
+ NCCc1cc(O)c(O)cc1O,6-OHDA,neurotoxin
295
+ COc1ccc(CCN)cc1OC,DMPEA,peyote alkaloid
296
+ CNCCc1cc(OC)c(OC)c(OC)c1,M-M,peyote alkaloid
297
+ COc1cc2c(c(OC)c1OC)C(C)N(C=O)CC2,N-Formyl-O-methylanhalonidine,peyote alkaloid
298
+ COc1cc2c(c3c1OCO3)C(C)[N+](C)(C)CC2,Lophotine,peyote alkaloid
299
+ COc1cc(CCN)ccc1O,GEA,peyote alkaloid
300
+ COc1cc(CCNCC(=O)O)cc(OC)c1OC,Mescaloxylic acid,peyote alkaloid
301
+ COc1cc2c(c(O)c1OC)C(C)N(C=O)CC2,N-Formylanhalonidine,peyote alkaloid
302
+ COc1cc(CCN2C(=O)CC(O)C2=O)cc(OC)c1OC,Mescaline malimide,peyote alkaloid
303
+ CNCCc1ccc(O)c(O)c1,Epinine,peyote alkaloid
304
+ COc1cc2c(c(O)c1OC)C(C)(C(=O)O)NCC2,Peyoruvic acid,peyote alkaloid
305
+ CCN1CCc2cc(OC)c3c(c2C1C)OCO3,Peyophorine,peyote alkaloid
306
+ COc1cc(CCN2C(=O)C=CC2=O)cc(OC)c1OC,Mescaline maleimide,peyote alkaloid
307
+ COc1c(O)cc2c(c1OC)CN(C)CC2,Isoanhalidine,peyote alkaloid
308
+ NCCc1ccc2c(c1)OCO2,MDPEA,peyote alkaloid
309
+ COc1cc2c(c(O)c1OC)C1CCC(=O)N1CC2,Peyoglutam,peyote alkaloid
310
+ COc1cc(CCN)cc(O)c1OC,3-DESMETHYL,peyote alkaloid
311
+ CCOc1ccc(CC(C)N(C)C)c(OCC)c1,"2,4-Diethoxy-N,N-dimethylamphetamine",peyote alkaloid
312
+ CN(C)CCc1ccc2c(c1)OCO2,Lobivine,peyote alkaloid
313
+ COc1c(O)cc2c(c1OC)C(C)N(C)CC2,Isopellotine,peyote alkaloid
314
+ COc1cc(CCNC(C)=O)cc(OC)c1OC,N-Acetylmescaline,peyote alkaloid
315
+ COc1cc2c(c3c1OCO3)C(C)N(C(C)=O)CC2,N-Acetylanhalonine,peyote alkaloid
316
+ COc1cc(CCN(C)C)cc(O)c1OC,"N,N-Me-3-DESMETHYL",peyote alkaloid
317
+ COc1c(O)cc2c(c1OC)C(C)NCC2,Isoanhalonidine,peyote alkaloid
318
+ COc1cc(CCn2cccc2C(=O)O)cc(OC)c1OC,Peyonine,peyote alkaloid
319
+ COc1cc2c(c(O)c1OC)CN(C(C)=O)CC2,N-Acetylanhalamine,peyote alkaloid
320
+ COc1cc2c(c(O)c1OC)C(C(=O)O)NCC2,Peyoxylic acid,peyote alkaloid
321
+ COc1cc(CCN(C)C)ccc1O,MM-GEA,peyote alkaloid
322
+ COc1cc2c(c(OC)c1OC)CNCC2,Anhalinine,peyote alkaloid
323
+ CNCCc1ccc(O)cc1,HMePEA,peyote alkaloid
324
+ COc1cc2c(c(O)c1OC)C[N+](C)(C)CC2,Anhalotine,peyote alkaloid
325
+ COc1c(O)cc2c(c1OC)CNCC2,Isoanhalamine,peyote alkaloid
326
+ COc1cc(CCN)cc(O)c1O,"3,4-DESMETHYL",peyote alkaloid
327
+ COc1cc2c(c(O)c1OC)CN(C=O)CC2,N-Formylanhalamine,peyote alkaloid
328
+ COc1cc(CCNC(C)C(=O)O)cc(OC)c1OC,Mescaloruvic acid,peyote alkaloid
329
+ C[N+](C)(C)CCc1ccc(O)cc1,Candicine,peyote alkaloid
330
+ COc1cc2c(c(O)c1OC)C(C)NCC2,Anhalonidine,peyote alkaloid
331
+ COc1cc2c(c(OC)c1OC)C1CCC(=O)N1CC2,Mescalotam,peyote alkaloid
332
+ COc1cc2c(c3c1OCO3)C(C)NCC2,Anhalonine,peyote alkaloid
333
+ COc1cc2c(c(O)c1OC)C(C)N(C)CC2,Pellotine,peyote alkaloid
334
+ COc1cc2c(c(O)c1OC)CN(C)CC2,Anhalidine,peyote alkaloid
335
+ COc1cc2c(c3c1OCO3)C(C)N(C)CC2,Lophophorine,peyote alkaloid
336
+ COc1cc(CCN)cc2c1OCO2,LOPHOPHINE,peyote alkaloid
337
+ COc1cc(CCNC(C)=O)cc(O)c1OC,N-Acetyl-3-demethymescaline,peyote alkaloid
338
+ COc1cc(CCN)cc(OC)c1OC,M,peyote alkaloid
339
+ COc1cc(CCN2C(=O)CCC2=O)cc(OC)c1OC,Mescaline succinimide,peyote alkaloid
340
+ COc1cc2c(c(O)c1OC)C(C)[N+](C)(C)CC2,Peyotine,peyote alkaloid
341
+ COc1cc2c(c(OC)c1OC)C(C)NCC2,O-Methylanhalonidine,peyote alkaloid
342
+ COc1cc2c(c(O)c1OC)CNCC2,Anhalamine,peyote alkaloid
343
+ COc1cc(CCN2C(=O)CC(O)(CC(=O)O)C2=O)cc(OC)c1OC,Mescaline citrimide,peyote alkaloid
344
+ CN(C)CCc1ccc(O)cc1,Hordenine,peyote alkaloid
345
+ COc1cc(CCNC=O)cc(OC)c1OC,N-Formylmescaline,peyote alkaloid
346
+ CNCCc1cc(O)c(OC)c(OC)c1,N-Me-3-DESMETHYL,peyote alkaloid
347
+ COc1cc(CCn2c(C=O)ccc2CO)cc(OC)c1OC,Peyoglunal,peyote alkaloid
348
+ COc1cc(CCNC=O)cc(O)c1OC,N-Formyl-3-demethylmescaline,peyote alkaloid
349
+ NCCc1ccc(O)c(O)c1,Dopamine,peyote alkaloid
350
+ COc1cc2c(c3c1OCO3)C(C)N(C=O)CC2,N-Formylanhalonine,peyote alkaloid
351
+ CNCCc1ccc(O)c(OC)c1,N-Me-GEA,peyote alkaloid
352
+ COc1cc2c(c(OC)c1OC)CN(C=O)CC2,N-Formylanhalinine,peyote alkaloid
353
+ COc1cc(CCN2C(=O)C3CC(=O)OC3C2=O)cc(OC)c1OC,Mescaline isocitrimide lactone,peyote alkaloid
354
+ COc1cc2c(c(OC)c1OC)C(C)N(C)CC2,O-Methylpellotine,peyote alkaloid
355
+ CCC(C)N(CCc1c[nH]c2ccc(F)cc12)C(C)C,5-Fluoro-IPSBT,tryptamine
356
+ CC(C)N(CCc1c[nH]c2ccc(F)cc12)CC1CC1,5-Fluoro-N-cyclopropylmethyl-NIPT,tryptamine
357
+ CCCCCCN(C)CCc1c[nH]c2ccc(OC)cc12,N-[2-(5-Methoxy-1H-indol-3-yl)ethyl]-N-methylhexan-1-amine,tryptamine
358
+ CN(C)CCc1c[nH]c2c(Br)ccc(O)c12,7-Bromopsilocin,tryptamine
359
+ CCCCN(CCCC)CCc1c[nH]c2cc(OC)c(OC)cc12,"5,6-MeO-DBT",tryptamine
360
+ CN(C/C=C/c1ccccc1)CCc1c[nH]c2ccccc12,N-Phenylpropenyl-NMT,tryptamine
361
+ COc1cc2[nH]cc(CCN3CCCC3)c2cc1OC,"5,6-MeO-pyr-T",tryptamine
362
+ Cn1cc(CCN)c2c3c(ccc21)OCCC3,"CP 132,484",tryptamine
363
+ C=CCN(CCc1c(C)[nH]c2ccc(OC)cc12)C1CCCCC1,2-Methyl-5-methoxy-N-allyl-N-cyclohexyltryptamine,tryptamine
364
+ Cc1cc(OP(=O)(O)O)c2c(CCN)c[nH]c2c1,6-Methyl-4-PO-T,tryptamine
365
+ CCCCCN(CCCCC)CCc1c[nH]c2ccccc12,"N,N-Dipentyltryptamine",tryptamine
366
+ COc1ccc2[nH]cc(CC3CCCN3C)c2c1,CP-108509,tryptamine
367
+ COc1ccc(OC)c(CCCN(C)CCc2c[nH]c3ccc(OC)cc23)c1,"3-(2,5-Dimethoxyphenyl)-N-[2-(5-methoxy-1H-indol-3-yl)ethyl]-N-methylpropan-1-amine",tryptamine
368
+ C=CCN(CCc1c[nH]c2ccc(F)cc12)C(C)C,5-Fluoro-ALIPT,tryptamine
369
+ NCCc1c[nH]c2ccc(OC3CCCC3)cc12,5-Cyclopentyloxy-T,tryptamine
370
+ COc1ccc(OC)c(CCN(C)CCc2c[nH]c3ccc(OC)cc23)c1,"N-(2,5-Dimethoxyphenylethyl)-5-MeO-NMT",tryptamine
371
+ Oc1cccc2[nH]cc(CCN3CCCCC3)c12,4-HO-pip-T,tryptamine
372
+ CN(C)CCc1c[nH]c2cccc(OCc3ccccc3)c12,4-Benzyloxy-DMT,tryptamine
373
+ CN(C)CCc1c[nH]c2cccc(OC(=O)SCc3ccccc3)c12,S-Benzyl O-{3-[2-(dimethylamino)ethyl]-1H-indol-4-yl} carbonothioate,tryptamine
374
+ COc1cc(OC)c2[nH]cc(CCNCc3ccccc3)c2c1,"5,7-MeO-T-NB",tryptamine
375
+ CNC(C)Cc1c[nH]c2ccc(OCc3ccccc3)cc12,5-Benzyloxy-alpha-methyl-NMT,tryptamine
376
+ CC(C)(C)CCCCCCCOc1ccc2[nH]cc(CCN)c2c1,"5-(8,8-Dimethylnonyloxy)-T",tryptamine
377
+ CCCOc1ccc2[nH]cc(CCN(CC)CC)c2c1,5-PrO-DET,tryptamine
378
+ COc1ccc2[nH]cc(CCN(C)CCCc3cc(OC)c(OC)c(OC)c3)c2c1,"N-(3,4,5-Trimethoxyphenylpropyl)-5-MeO-NMT",tryptamine
379
+ c1ccc2c(CCN3CCN(CCc4c[nH]c5ccccc45)CC3)c[nH]c2c1,"3,3'-[Piperazine-1,4-diyldi(ethane-2,1-diyl)]di(1H-indole)",tryptamine
380
+ CC(C)N(CCc1c[nH]c2cccc(OCc3ccccc3)c12)C(C)C,4-Benzyloxy-DIPT,tryptamine
381
+ CC(C)N(CCc1c[nH]c2ccc(F)cc12)C1CCC1,5-Fluoro-IPCBT,tryptamine
382
+ CCOc1ccc(CNCCc2c[nH]c3ccccc23)cc1,T-NB4OEt,tryptamine
383
+ O=C(O)CCNCCc1c[nH]c2cc([N+](=O)[O-])ccc12,6-Nitro-N-(2-carboxyethyl)tryptamine,tryptamine
384
+ CN1CCN(CCc2c[nH]c3cccc(O)c23)CC1,4'-Methyl-4-HO-piperazine-T,tryptamine
385
+ CN(CCC#N)CCc1c[nH]c2ccccc12,N-Cyanoethyl-NMT,tryptamine
386
+ COc1cc(F)c2[nH]cc(CCN(C)C)c2c1,7-Fluoro-5-MeO-DMT,tryptamine
387
+ CN(CCc1c[nH]c2ccc(F)cc12)C1CCC1,5-Fluoro-MCBT,tryptamine
388
+ CNCCc1c[nH]c2c(OC)cccc12,7-MeO-NMT,tryptamine
389
+ Cc1c(O)c(O)cc2c(CCN)c[nH]c12,"7-Methyl-5,6-HO-T",tryptamine
390
+ Oc1ccc(CNCCc2c[nH]c3ccccc23)cc1,T-NB4OH,tryptamine
391
+ COc1c(Br)cc(Br)cc1CNCCc1c[nH]c2ccccc12,T-NBOMe35Br,tryptamine
392
+ CCn1cc(CCN(C)C)c2c(OCc3ccccc3)cc(F)cc21,1-Ethyl-6-fluoro-4-benzyloxy-DMT,tryptamine
393
+ CN(C)CCc1c[nH]c2cccc(OC(=O)c3cccc(C(=O)Oc4cccc5[nH]cc(CCN(C)C)c45)c3)c12,"Bis{3-[2-(dimethylamino)ethyl]-1H-indol-4-yl} benzene-1,3-dicarboxylate",tryptamine
394
+ CCN(CC)C(=O)CCN(C)CCc1c[nH]c2ccc(OC)cc12,"N,N-Diethyl-N3-[2-(5-methoxy-1H-indol-3-yl)ethyl]-N3-methyl-beta-alaninamide",tryptamine
395
+ COc1ccc(CNCCc2c[nH]c3c(Br)cc(OC)cc23)cc1,7-Bromo-5-MeO-T-NB4OMe,tryptamine
396
+ CCCN(C)CCc1c[nH]c2ccc(F)cc12,5-Fluoro-MPT,tryptamine
397
+ CN(CCc1c[nH]c2cc3c(cc12)OCO3)Cc1ccccc1,"5,6-MDO-NMT-NB",tryptamine
398
+ Cc1c(OC(=O)CCC(=O)O)ccc2[nH]cc(CCN(C)C)c12,Psilocin-4-methyl-5-succinate,tryptamine
399
+ COc1ccc2[nH]cc(CC(C)N)c2c1Br,4-Bromo-5-MeO-AMT,tryptamine
400
+ CN(C)CC(=O)c1c[nH]c2cc(F)ccc12,beta-Oxo-6-fluoro-DMT,tryptamine
401
+ COc1ccc2[nH]cc(C(O)CN(C)C)c2c1,beta-HO-5-MeO-DMT,tryptamine
402
+ COc1cccc2c(CCN)c[nH]c12,7-MeO-T,tryptamine
403
+ COc1cc(I)c2[nH]cc(CCN(C)C)c2c1,7-Iodo-5-MeO-DMT,tryptamine
404
+ C[C@@H]1CC[C@H](C)N1CCc1c[nH]c2ccccc12,"(R,S)-Dimethyl-pyr-T",tryptamine
405
+ COc1ccc(Sn2cc(CCN(C)C)c3c(OC)cccc32)cc1,1-(4-Methoxyphenylthio)-4-MeO-DMT,tryptamine
406
+ CCCN(CCc1c[nH]c2c(F)cccc12)C1CCC1,7-Fluoro-PCBT,tryptamine
407
+ CC(=O)NCCc1c[nH]c2cc(F)cc(NC(C)=O)c12,6-Fluoro-4-acetamido-N-acetyltryptamine,tryptamine
408
+ CCCCS(=O)(=O)n1cc(CCN(C)C)c2c(OC)cccc21,1-Butylsulfonyl-4-MeO-DMT,tryptamine
409
+ CCCN(CCC)CCc1c[nH]c2ccc(OC(C)=O)cc12,5-AcO-DPT,tryptamine
410
+ CN(C)CCc1cn(C)c2ccccc12,1-TMT,tryptamine
411
+ CCN(CCc1c[nH]c2cc(F)c(F)cc12)C(C)C,"5,6-Difluoro-EIPT",tryptamine
412
+ CN(C)CC(=O)c1c[nH]c2c(F)cc(F)cc12,"beta-Oxo-5,7-difluoro-DMT",tryptamine
413
+ CN(C)CCc1cn(C)c2cc(F)cc(OCc3ccccc3)c12,1-Methyl-6-fluoro-4-benzyloxy-DMT,tryptamine
414
+ CCCc1[nH]c2ccc(OC)cc2c1CCN(C)C,2-Propyl-5-MeO-DMT,tryptamine
415
+ CC(=O)Oc2cccc1[nH]cc(CCN(C)C)c12,4-AcO-DMT,tryptamine
src/data/sample_smiles.csv ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ smiles,name,category
2
+ CCO,Ethanol,Alcohol
3
+ CC(=O)O,Acetic acid,Carboxylic acid
4
+ c1ccccc1,Benzene,Aromatic hydrocarbon
5
+ CC(C)O,Isopropanol,Alcohol
6
+ c1ccc(cc1)O,Phenol,Aromatic alcohol
7
+ CC(=O)OC1=CC=CC=C1C(=O)O,Aspirin,Carboxylic acid ester
8
+ CN1C=NC2=C1C(=O)N(C(=O)N2C)C,Caffeine,Alkaloid
9
+ CCN(CC)CC,Triethylamine,Amine
10
+ c1ccc2c(c1)cccn2,Quinoline,Aromatic heterocycle
11
+ c1ccc(cc1)N,Aniline,Aromatic amine
12
+ O=P(O)(O)OP(=O)(O)OP(=O)(O)OC[C@H]3O[C@@H](n2cnc1c(ncnc12)N)[C@H](O)[C@@H]3O,ATP,Nucleotide
13
+ CN(C)CCC1=CNC2=C1C(=CC=C2)OP(=O)(O)O,Psilocybin,Tryptamine
src/main.js ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @fileoverview JSME (JavaScript Molecule Editor) integration with Gradio interface
3
+ * Handles bidirectional synchronization between JSME applet and Gradio textbox
4
+ * @author Manny Cortes ('[email protected]')
5
+ * @version 0.2.0
6
+ */
7
+
8
+ // ============================================================================
9
+ // GLOBAL VARIABLES
10
+ // ============================================================================
11
+
12
+ /** @type {Object|null} The JSME applet instance */
13
+ let jsmeApplet = null;
14
+
15
+ /** @type {string} Last known value of the textbox to prevent infinite loops */
16
+ let lastTextboxValue = "";
17
+
18
+ // ============================================================================
19
+ // CONSTANTS
20
+ // ============================================================================
21
+
22
+ /** @const {string} Default SMILES for initial molecule (ethanol) */
23
+ const DEFAULT_SMILES = "CCO";
24
+
25
+ /** @const {string} Container height for JSME applet */
26
+ const CONTAINER_HEIGHT = "450px";
27
+
28
+ /** @const {string} CSS selector for the Gradio SMILES input element */
29
+ const SMILES_INPUT_SELECTOR = "#smiles_input textarea, #smiles_input input";
30
+
31
+ /** @const {number} Delay for paste event handling (ms) */
32
+ const PASTE_DELAY = 50;
33
+
34
+ /** @const {number} Delay for initialization retry (ms) */
35
+ const INIT_RETRY_DELAY = 2000;
36
+
37
+ /** @const {string[]} Events to trigger for Gradio change detection */
38
+ const GRADIO_CHANGE_EVENTS = ["input", "change", "keyup"];
39
+
40
+ // ============================================================================
41
+ // CORE INITIALIZATION
42
+ // ============================================================================
43
+
44
+ /**
45
+ * Initializes the JSME applet after the library has been loaded
46
+ * Sets up the molecular editor with default options and callbacks
47
+ * @throws {Error} When JSME initialization fails
48
+ */
49
+ function initializeJSME() {
50
+ try {
51
+ console.log("Initializing JSME...");
52
+ // https://github.com/jsme-editor/jsme-editor.github.io
53
+ // https://jsme-editor.github.io/dist/api_javadoc/index.html
54
+ // http://wiki.jmol.org/index.php/Jmol_JavaScript_Object/JME/Options
55
+ jsmeApplet = new JSApplet.JSME(
56
+ "jsme_container",
57
+ getJsmeContainerWidthPx(),
58
+ CONTAINER_HEIGHT,
59
+ {
60
+ options:
61
+ "rButton,zoom,zoomgui,newLook,star,multipart,polarnitro,NOexportInChI,NOexportInChIkey,NOsearchInChIkey,NOexportSVG,NOpaste",
62
+ }
63
+ );
64
+
65
+ jsmeApplet.setCallBack("AfterStructureModified", handleJSMEStructureChange);
66
+ jsmeApplet.setMenuScale(getJsmeGuiScale());
67
+ jsmeApplet.setUserInterfaceBackgroundColor("#adadad");
68
+
69
+ // Set initial molecule and sync state
70
+ jsmeApplet.readGenericMolecularInput(DEFAULT_SMILES);
71
+ lastTextboxValue = DEFAULT_SMILES;
72
+
73
+ setupTextboxEventListeners();
74
+ window.addEventListener("resize", handleResize);
75
+
76
+ console.log("JSME initialized successfully");
77
+ } catch (error) {
78
+ console.error("Error initializing JSME:", error);
79
+ throw error;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Handles structure changes in the JSME applet
85
+ * Converts the structure to SMILES and updates the Gradio textbox
86
+ * @param {Event} event - The JSME structure modification event
87
+ */
88
+ function handleJSMEStructureChange(event) {
89
+ try {
90
+ const smiles = jsmeApplet.smiles();
91
+ updateGradioTextbox(smiles);
92
+ } catch (error) {
93
+ console.error("Error getting SMILES from JSME:", error);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Calculates the appropriate GUI scale for the JSME applet based on container width
99
+ * Uses breakpoints to determine optimal scaling for different screen sizes
100
+ * @returns {number} The scale factor for the JSME GUI (0.88 to 2.0)
101
+ */
102
+ function getJsmeGuiScale() {
103
+ const width = getJsmeContainerWidthNumber();
104
+ let menuScale;
105
+ if (width > 460) {
106
+ menuScale = 1.3;
107
+ } else if (width > 420) {
108
+ menuScale = 1.1;
109
+ } else if (width > 370) {
110
+ menuScale = 1.05;
111
+ } else if (width > 300) {
112
+ menuScale = 0.88;
113
+ } else {
114
+ menuScale = 2;
115
+ }
116
+ return menuScale;
117
+ }
118
+
119
+ /**
120
+ * Gets the JSME container width as a CSS-compatible string value
121
+ * Returns either a pixel value or percentage based on available width
122
+ * @returns {string} Width as "100%" or "{width}px" format
123
+ */
124
+ function getJsmeContainerWidthPx() {
125
+ const parentWidth = getJsmeContainerWidthNumber();
126
+ if (parentWidth == null || parentWidth <= 0) {
127
+ return "100%";
128
+ }
129
+ return `${parentWidth}px`;
130
+ }
131
+
132
+ /**
133
+ * Gets the numeric width of the JSME container's parent element
134
+ * Used for responsive scaling calculations
135
+ * @returns {number|null} Width in pixels, or null if container not found
136
+ */
137
+ function getJsmeContainerWidthNumber() {
138
+ const container = document.getElementById("jsme_container");
139
+ if (!container) {
140
+ return null;
141
+ }
142
+ return container.parentNode.offsetWidth;
143
+ }
144
+
145
+ // ============================================================================
146
+ // GRADIO INTEGRATION
147
+ // ============================================================================
148
+
149
+ /**
150
+ * Updates the Gradio textbox with a SMILES string
151
+ * Triggers appropriate events to ensure Gradio detects the change
152
+ * @param {string} smiles - The SMILES string to set in the textbox
153
+ */
154
+ function updateGradioTextbox(smiles) {
155
+ try {
156
+ const textbox = document.querySelector(SMILES_INPUT_SELECTOR);
157
+
158
+ if (!textbox || textbox.value === smiles) {
159
+ return;
160
+ }
161
+
162
+ textbox.value = smiles;
163
+ lastTextboxValue = smiles;
164
+
165
+ // Trigger events to ensure Gradio detects the change
166
+ GRADIO_CHANGE_EVENTS.forEach((eventType) => {
167
+ const event = new Event(eventType, {
168
+ bubbles: true,
169
+ cancelable: true,
170
+ });
171
+ textbox.dispatchEvent(event);
172
+ });
173
+ } catch (error) {
174
+ console.error("Error updating Gradio textbox:", error);
175
+ }
176
+ }
177
+
178
+ // ============================================================================
179
+ // JSME UPDATE FUNCTIONS
180
+ // ============================================================================
181
+
182
+ /**
183
+ * Updates the JSME applet with a SMILES string from the textbox
184
+ * @param {string} smiles - The SMILES string to display in JSME
185
+ */
186
+ function updateJSMEFromTextbox(smiles) {
187
+ if (!jsmeApplet) {
188
+ return;
189
+ }
190
+
191
+ try {
192
+ if (smiles && smiles.trim() !== "") {
193
+ jsmeApplet.readGenericMolecularInput(smiles.trim());
194
+ } else {
195
+ jsmeApplet.reset();
196
+ }
197
+ lastTextboxValue = smiles;
198
+ } catch (error) {
199
+ console.error("Error updating JSME from textbox:", error);
200
+ }
201
+ }
202
+
203
+ // ============================================================================
204
+ // UI MONITORING
205
+ // ============================================================================
206
+
207
+ /**
208
+ * Finds the textbox element and sets up event listeners
209
+ */
210
+ function setupTextboxEventListeners() {
211
+ const textbox = document.querySelector(SMILES_INPUT_SELECTOR);
212
+ if (!textbox) {
213
+ return;
214
+ }
215
+
216
+ textbox.addEventListener("input", handleTextboxChange);
217
+ textbox.addEventListener("change", handleTextboxChange);
218
+ textbox.addEventListener("paste", handleTextboxPaste);
219
+ textbox.addEventListener("keyup", handleTextboxChange);
220
+ }
221
+
222
+ /**
223
+ * Handles textbox change events
224
+ * @param {Event} event - The change event
225
+ */
226
+ function handleTextboxChange(event) {
227
+ if (event.target.value !== lastTextboxValue) {
228
+ updateJSMEFromTextbox(event.target.value);
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Handles textbox paste events with a delay to ensure content is available
234
+ * @param {Event} event - The paste event
235
+ */
236
+ function handleTextboxPaste(event) {
237
+ setTimeout(() => {
238
+ updateJSMEFromTextbox(event.target.value);
239
+ }, PASTE_DELAY);
240
+ }
241
+
242
+ /**
243
+ * Handles window resize events and updates JSME applet width
244
+ */
245
+ function handleResize() {
246
+ if (!jsmeApplet) {
247
+ return;
248
+ }
249
+
250
+ try {
251
+ jsmeApplet.setMenuScale(getJsmeGuiScale());
252
+ jsmeApplet.setWidth(getJsmeContainerWidthPx());
253
+ } catch (error) {
254
+ console.error("Error resizing JSME applet:", error);
255
+ }
256
+ }
257
+
258
+ // ============================================================================
259
+ // PUBLIC API
260
+ // ============================================================================
261
+
262
+ /**
263
+ * Sets a SMILES string in both JSME and Gradio textbox
264
+ * @param {string} smiles - The SMILES string to set
265
+ * @returns {string} The SMILES string that was set
266
+ * @public
267
+ */
268
+ window.setJSMESmiles = function (smiles) {
269
+ if (jsmeApplet) {
270
+ updateJSMEFromTextbox(smiles);
271
+ }
272
+
273
+ updateGradioTextbox(smiles);
274
+ return smiles;
275
+ };
276
+
277
+ /**
278
+ * Clears both JSME and Gradio textbox
279
+ * @returns {Array} Array containing cleared state for Gradio components
280
+ * @public
281
+ */
282
+ window.clearJSME = function () {
283
+ if (jsmeApplet) {
284
+ jsmeApplet.reset();
285
+ }
286
+
287
+ updateGradioTextbox("");
288
+ return ["", [], [], "Cleared - Draw a new molecule or enter SMILES"];
289
+ };
290
+
291
+ // ============================================================================
292
+ // INITIALIZATION LOGIC
293
+ // ============================================================================
294
+
295
+ /**
296
+ * Checks if JSME library is loaded and initializes JSME applet
297
+ * Retries until the library becomes available
298
+ */
299
+ function initializeWhenReady() {
300
+ if (typeof JSApplet !== "undefined" && JSApplet.JSME) {
301
+ console.log("JSME library loaded, initializing...");
302
+ initializeJSME();
303
+ } else {
304
+ console.log("JSME library not ready, retrying...");
305
+ setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Starts the initialization process based on document ready state
311
+ */
312
+ function startInitialization() {
313
+ if (document.readyState === "loading") {
314
+ document.addEventListener("DOMContentLoaded", () => {
315
+ setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
316
+ });
317
+ } else {
318
+ setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
319
+ }
320
+ }
321
+
322
+ startInitialization();
src/main.min.js ADDED
@@ -0,0 +1 @@
 
 
1
+ function initializeJSME(){try{(jsmeApplet=new JSApplet.JSME("jsme_container",getJsmeContainerWidthPx(),CONTAINER_HEIGHT,{options:"rButton,zoom,zoomgui,newLook,star,multipart,polarnitro,NOexportInChI,NOexportInChIkey,NOsearchInChIkey,NOexportSVG,NOpaste"})).setCallBack("AfterStructureModified",handleJSMEStructureChange),jsmeApplet.setMenuScale(getJsmeGuiScale()),jsmeApplet.setUserInterfaceBackgroundColor("#adadad"),jsmeApplet.readGenericMolecularInput(DEFAULT_SMILES),lastTextboxValue=DEFAULT_SMILES,setupTextboxEventListeners(),window.addEventListener("resize",handleResize)}catch(e){throw e}}function handleJSMEStructureChange(){try{updateGradioTextbox(jsmeApplet.smiles())}catch(e){}}function getJsmeGuiScale(){const e=getJsmeContainerWidthNumber();return e>460?1.3:e>420?1.1:e>370?1.05:e>300?.88:2}function getJsmeContainerWidthPx(){const e=getJsmeContainerWidthNumber();return null==e||e<=0?"100%":`${e}px`}function getJsmeContainerWidthNumber(){const e=document.getElementById("jsme_container");return e?e.parentNode.offsetWidth:null}function updateGradioTextbox(e){try{const t=document.querySelector(SMILES_INPUT_SELECTOR);if(!t||t.value===e)return;t.value=e,lastTextboxValue=e,GRADIO_CHANGE_EVENTS.forEach(e=>{const n=new Event(e,{bubbles:!0,cancelable:!0});t.dispatchEvent(n)})}catch(e){}}function updateJSMEFromTextbox(e){if(jsmeApplet)try{e&&""!==e.trim()?jsmeApplet.readGenericMolecularInput(e.trim()):jsmeApplet.reset(),lastTextboxValue=e}catch(e){}}function setupTextboxEventListeners(){const e=document.querySelector(SMILES_INPUT_SELECTOR);e&&(e.addEventListener("input",handleTextboxChange),e.addEventListener("change",handleTextboxChange),e.addEventListener("paste",handleTextboxPaste),e.addEventListener("keyup",handleTextboxChange))}function handleTextboxChange(e){e.target.value!==lastTextboxValue&&updateJSMEFromTextbox(e.target.value)}function handleTextboxPaste(e){setTimeout(()=>{updateJSMEFromTextbox(e.target.value)},PASTE_DELAY)}function handleResize(){if(jsmeApplet)try{jsmeApplet.setMenuScale(getJsmeGuiScale()),jsmeApplet.setWidth(getJsmeContainerWidthPx())}catch(e){}}function initializeWhenReady(){"undefined"!=typeof JSApplet&&JSApplet.JSME?initializeJSME():setTimeout(initializeWhenReady,INIT_RETRY_DELAY)}function startInitialization(){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{setTimeout(initializeWhenReady,INIT_RETRY_DELAY)}):setTimeout(initializeWhenReady,INIT_RETRY_DELAY)}let jsmeApplet=null,lastTextboxValue="";const DEFAULT_SMILES="CCO",CONTAINER_HEIGHT="450px",SMILES_INPUT_SELECTOR="#smiles_input textarea, #smiles_input input",PASTE_DELAY=50,INIT_RETRY_DELAY=2e3,GRADIO_CHANGE_EVENTS=["input","change","keyup"];window.setJSMESmiles=function(e){return jsmeApplet&&updateJSMEFromTextbox(e),updateGradioTextbox(e),e},window.clearJSME=function(){return jsmeApplet&&jsmeApplet.reset(),updateGradioTextbox(""),["",[],[],"Cleared - Draw a new molecule or enter SMILES"]},startInitialization();
src/service.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from typing import TypedDict
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import redis
8
+ from chem_mrl.molecular_fingerprinter import MorganFingerprinter
9
+ from dotenv import load_dotenv
10
+ from redis.commands.search.field import TextField, VectorField
11
+ from redis.commands.search.indexDefinition import IndexDefinition, IndexType
12
+ from redis.commands.search.query import Query
13
+ from sentence_transformers import SentenceTransformer
14
+
15
+ from constants import (
16
+ EMBEDDING_DIMENSION,
17
+ HNSW_K,
18
+ HNSW_PARAMETERS,
19
+ MODEL_NAME,
20
+ SUPPORTED_EMBEDDING_DIMENSIONS,
21
+ )
22
+ from data import DATASET_SMILES, ISOMER_DESIGN_SUBSET
23
+
24
+
25
+ def setup_logger(clear_handler=False):
26
+ if clear_handler:
27
+ for handler in logging.root.handlers[:]:
28
+ logging.root.removeHandler(handler) # issue with sentence-transformer's logging handler
29
+ logging.basicConfig(format="%(asctime)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO)
30
+ logger = logging.getLogger(__name__)
31
+ return logger
32
+
33
+
34
+ load_dotenv("../.env")
35
+ logger = setup_logger(clear_handler=True)
36
+
37
+
38
+ class SimilarMolecule(TypedDict):
39
+ smiles: str
40
+ name: str
41
+ category: str
42
+ score: float
43
+
44
+
45
+ class MolecularEmbeddingService:
46
+ def __init__(self):
47
+ self.model_name = MODEL_NAME
48
+ self.index_name = "molecule_embeddings"
49
+ self.model_embed_dim = EMBEDDING_DIMENSION
50
+
51
+ self.model = self._initialize_model()
52
+ self.redis_client = self._initialize_redis()
53
+ self._initialize_datastore()
54
+
55
+ def _initialize_model(self):
56
+ """Initialize the Hugging Face transformers model"""
57
+ try:
58
+ model = SentenceTransformer(self.model_name) # type: ignore
59
+ model.eval()
60
+ return model
61
+ except Exception as e:
62
+ logger.error(f"Failed to load model: {e}")
63
+ raise
64
+
65
+ def _initialize_redis(self):
66
+ """Initialize Redis connection"""
67
+ try:
68
+ redis_host = os.getenv("REDIS_HOST", "localhost")
69
+ redis_port = int(os.getenv("REDIS_PORT", 6379))
70
+ redis_password = os.getenv("REDIS_PASSWORD", None)
71
+ logger.info(
72
+ f"Connecting to Redis at {redis_host}:{redis_port} with password: {'***' if redis_password else 'None'}"
73
+ )
74
+ redis_client = redis.Redis(
75
+ host=redis_host,
76
+ port=redis_port,
77
+ password=redis_password,
78
+ decode_responses=True,
79
+ )
80
+ redis_client.ping()
81
+ return redis_client
82
+ except Exception as e:
83
+ logger.error(f"Failed to connect to Redis: {e}")
84
+ raise
85
+
86
+ def _initialize_datastore(self):
87
+ self.__create_hnsw_index()
88
+ self.__populate_sample_data(DATASET_SMILES)
89
+ self.__populate_sample_data(ISOMER_DESIGN_SUBSET)
90
+
91
+ def __create_hnsw_index(self):
92
+ """Create HNSW index for molecular embeddings"""
93
+ try:
94
+ self.redis_client.ft(self.index_name).info()
95
+ logger.info(f"Index {self.index_name} already exists")
96
+ return
97
+ except redis.exceptions.ResponseError:
98
+ pass
99
+
100
+ try:
101
+ schema: list[TextField | VectorField] = [
102
+ VectorField(
103
+ self.embedding_field_name(dim),
104
+ "HNSW",
105
+ {
106
+ **HNSW_PARAMETERS,
107
+ "DIM": dim,
108
+ },
109
+ )
110
+ for dim in SUPPORTED_EMBEDDING_DIMENSIONS
111
+ ]
112
+ schema.insert(0, TextField("smiles"))
113
+
114
+ self.redis_client.ft(self.index_name).create_index(
115
+ schema,
116
+ definition=IndexDefinition(prefix=[self.molecule_index_prefix("")], index_type=IndexType.HASH),
117
+ )
118
+
119
+ logger.info(f"Created HNSW index: {self.index_name}")
120
+
121
+ except Exception as e:
122
+ logger.error(f"Failed to create HNSW index: {e}")
123
+ raise
124
+
125
+ def __populate_sample_data(self, df: pd.DataFrame):
126
+ """Populate Redis with sample molecular data"""
127
+ logger.info("Populating Redis with sample molecular data...")
128
+ for _, row in df.iterrows():
129
+ try:
130
+ key = self.molecule_index_prefix(row["smiles"])
131
+ if self.redis_client.exists(key):
132
+ continue
133
+
134
+ mapping: dict[str, bytes | str] = {
135
+ self.embedding_field_name(embed_dim): self.get_molecular_embedding(
136
+ row["smiles"], embed_dim
137
+ ).tobytes()
138
+ for embed_dim in SUPPORTED_EMBEDDING_DIMENSIONS
139
+ }
140
+ mapping = {**mapping, **row.to_dict()}
141
+
142
+ self.redis_client.hset(
143
+ key,
144
+ mapping=mapping,
145
+ )
146
+
147
+ except Exception as e:
148
+ logger.error(f"Failed to process molecule {row}: {e}")
149
+ continue
150
+
151
+ logger.info(f"Populated {len(df)} sample molecules")
152
+
153
+ def get_molecular_embedding(self, smiles: str, embed_dim: int) -> np.ndarray:
154
+ """Generate molecular embedding using ChemMRL"""
155
+ try:
156
+ if embed_dim <= 0:
157
+ raise ValueError("embed_dim must be positive")
158
+
159
+ # Preprocess smiles similarly as training data for optimal performance
160
+ smiles = MorganFingerprinter.canonicalize_smiles(smiles) or smiles
161
+
162
+ embedding: np.ndarray = self.model.encode(
163
+ [smiles],
164
+ show_progress_bar=False,
165
+ convert_to_numpy=True,
166
+ )[0]
167
+
168
+ return self._truncate_and_normalize_embedding(embedding, embed_dim)
169
+
170
+ except Exception as e:
171
+ logger.error(f"Failed to generate embedding for {smiles}: {e}")
172
+ raise
173
+
174
+ def _truncate_and_normalize_embedding(self, embedding: np.ndarray, embed_dim: int) -> np.ndarray:
175
+ """Truncate and normalize embedding"""
176
+ if embed_dim < len(embedding):
177
+ embedding = embedding[:embed_dim]
178
+ norms = np.linalg.norm(embedding, ord=2, keepdims=True)
179
+ return embedding / np.where(norms == 0, 1, norms)
180
+
181
+ def find_similar_molecules(
182
+ self, query_embedding: np.ndarray, embed_dim: int, k: int = HNSW_K
183
+ ) -> list[SimilarMolecule]:
184
+ """Find k most similar molecules using HNSW"""
185
+ try:
186
+ query_vector = query_embedding.astype(np.float32).tobytes()
187
+ query = (
188
+ Query(f"*=>[KNN {k} @{self.embedding_field_name(embed_dim)} $vec AS score]")
189
+ .sort_by("score")
190
+ .return_fields("smiles", "name", "category", "score")
191
+ .dialect(2)
192
+ )
193
+
194
+ results = self.redis_client.ft(self.index_name).search(query, query_params={"vec": query_vector})
195
+
196
+ neighbors: list[SimilarMolecule] = [
197
+ {"smiles": doc.smiles, "name": doc.name, "category": doc.category, "score": float(doc.score)}
198
+ for doc in results.docs
199
+ ]
200
+
201
+ return neighbors
202
+
203
+ except Exception as e:
204
+ logger.error(f"Failed to find similar molecules: {e}")
205
+ return []
206
+
207
+ @staticmethod
208
+ def embedding_field_name(dim: int) -> str:
209
+ return f"embedding_{dim}"
210
+
211
+ @staticmethod
212
+ def molecule_index_prefix(smiles: str) -> str:
213
+ return f"mol:{smiles}"
src/src/app.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import pandas as pd
4
+ from rdkit import Chem
5
+ from rdkit.Chem import Draw
6
+ from rdkit.Chem.Draw import rdMolDraw2D
7
+
8
+ from constants import EMBEDDING_DIMENSION, LAUNCH_PARAMETERS, SUPPORTED_EMBEDDING_DIMENSIONS
9
+ from data import SAMPLE_SMILES
10
+ from service import MolecularEmbeddingService, SimilarMolecule, setup_logger
11
+
12
+ logger = setup_logger()
13
+
14
+
15
+ class App:
16
+ def __init__(self):
17
+ self.embedding_service = MolecularEmbeddingService()
18
+ self.demo = self.create_gradio_interface()
19
+
20
+ def molecule_similarity_search_pipeline(
21
+ self, smiles: str, embed_dim: int
22
+ ) -> tuple[list[float], list[SimilarMolecule], str]:
23
+ """Complete pipeline: SMILES -> Canonical SMILES -> Embedding -> Similar molecules"""
24
+ try:
25
+ if not smiles or smiles.strip() == "":
26
+ return [], [], "Please provide a valid SMILES string"
27
+
28
+ logger.info(f"Running similarity search: {smiles} - ({embed_dim})")
29
+ embedding = self.embedding_service.get_molecular_embedding(smiles, embed_dim)
30
+ neighbors = self.embedding_service.find_similar_molecules(embedding, embed_dim)
31
+
32
+ return embedding.tolist(), neighbors, "Search completed successfully"
33
+
34
+ except Exception as e:
35
+ error_msg = f"Search failed: {str(e)}"
36
+ logger.error(error_msg)
37
+ return [], [], error_msg
38
+
39
+ @staticmethod
40
+ def _truncated_attribute(obj, attr, max_len=45):
41
+ return f"{obj[attr][:max_len]}{'...' if len(obj[attr]) > max_len else ''}"
42
+
43
+ @classmethod
44
+ def _draw_molecule_grid(cls, similar: list[SimilarMolecule]) -> np.ndarray:
45
+ mols = [Chem.MolFromSmiles(m["smiles"]) for m in similar]
46
+ legends = [
47
+ f"{cls._truncated_attribute(m, 'name')}\n{m['category']}\n"
48
+ f"{cls._truncated_attribute(m, 'smiles')}\n({m['score']:.2E})"
49
+ for m in similar
50
+ ]
51
+
52
+ draw_options = rdMolDraw2D.MolDrawOptions()
53
+ draw_options.legendFontSize = 17
54
+ draw_options.legendFraction = 0.29
55
+ draw_options.drawMolsSameScale = False
56
+
57
+ img = Draw.MolsToGridImage(
58
+ mols,
59
+ legends=legends,
60
+ molsPerRow=2,
61
+ subImgSize=(250, 250),
62
+ drawOptions=draw_options,
63
+ )
64
+ return img
65
+
66
+ @staticmethod
67
+ def _display_sample_molecules(mols: pd.DataFrame):
68
+ for _, row in mols.iterrows():
69
+ with gr.Group():
70
+ gr.Textbox(value=row["smiles"], label=f"{row['name']} ({row['category']})", interactive=False, scale=3)
71
+ sample_btn = gr.Button(
72
+ f"Load {row['name']}",
73
+ scale=1,
74
+ size="sm",
75
+ variant="primary",
76
+ )
77
+ sample_btn.click(
78
+ fn=None,
79
+ js=f"() => {{window.setJSMESmiles('{row['smiles']}');}}",
80
+ )
81
+
82
+ @staticmethod
83
+ def clear_all():
84
+ return "", [], [], None, "Cleared - Draw a new molecule or enter SMILES"
85
+
86
+ def handle_search(self, smiles: str, embed_dim: int):
87
+ if not smiles.strip():
88
+ return (
89
+ [],
90
+ [],
91
+ None,
92
+ "Please draw a molecule or enter a SMILES string",
93
+ )
94
+ embedding, similar, status = self.molecule_similarity_search_pipeline(smiles, embed_dim)
95
+ img = self._draw_molecule_grid(similar)
96
+ return embedding, similar, img, status
97
+
98
+ def create_gradio_interface(self):
99
+ """Create the Gradio interface optimized for JavaScript client usage"""
100
+ head_scripts = """
101
+ <link rel="preconnect" href="https://jsme-editor.github.io">
102
+ <link rel="preload" href="https://jsme-editor.github.io/dist/jsme/jsme.nocache.js" as="script" crossorigin="anonymous">
103
+ <link rel="preload" href="gradio_api/file=src/main.min.js" as="script">
104
+ <script type="text/javascript" src="https://jsme-editor.github.io/dist/jsme/jsme.nocache.js" crossorigin="anonymous" defer></script>
105
+ <script type="text/javascript" src="gradio_api/file=src/main.min.js" defer></script>
106
+ """
107
+
108
+ with gr.Blocks(
109
+ title="Chem-MRL: Molecular Similarity Search Demo",
110
+ theme=gr.themes.Soft(),
111
+ head=head_scripts,
112
+ ) as demo:
113
+ gr.Markdown("""
114
+ # 🧪 Chem-MRL: Molecular Similarity Search Demo
115
+
116
+ Use the JSME editor to draw a molecule or input a SMILES string.
117
+ The backend encodes the molecule using the Chem-MRL model to produce a vector embedding.
118
+ Similarity search is performed via an HNSW-indexed Redis vector store to retrieve closest matches.<br/>
119
+
120
+ [Model Repo](https://github.com/emapco/chem-mrl) | [Demo Repo](https://github.com/emapco/chem-mrl-demo)
121
+ """)
122
+ with gr.Tab("🔬 Molecular Search"), gr.Row():
123
+ with gr.Column(scale=1):
124
+ gr.Markdown("### Molecule Input")
125
+ gr.HTML("<div id='jsme_container'></div>")
126
+
127
+ smiles_input = gr.Textbox(
128
+ label="SMILES String",
129
+ placeholder="Draw a molecule above or enter SMILES here (e.g., CCO for ethanol)",
130
+ lines=2,
131
+ elem_id="smiles_input",
132
+ )
133
+
134
+ embedding_dimension = gr.Dropdown(
135
+ choices=SUPPORTED_EMBEDDING_DIMENSIONS,
136
+ value=EMBEDDING_DIMENSION,
137
+ label="Embedding Dimension",
138
+ elem_id="embedding_dimension",
139
+ )
140
+
141
+ with gr.Row():
142
+ search_btn = gr.Button(
143
+ "🔍 Search Molecule Database",
144
+ variant="primary",
145
+ elem_id="search_btn",
146
+ )
147
+ clear_btn = gr.Button("🗑️ Clear All", variant="secondary")
148
+
149
+ with gr.Column(scale=1):
150
+ gr.Markdown("### Search Results")
151
+ status_output = gr.Textbox(
152
+ label="Status",
153
+ interactive=False,
154
+ elem_id="status_output",
155
+ value="Ready - Draw a molecule or enter SMILES",
156
+ )
157
+
158
+ with gr.Accordion("Molecular Embedding Vector", open=False):
159
+ embedding_output = gr.JSON(
160
+ label="Molecular Embedding",
161
+ elem_id="embedding_output",
162
+ )
163
+
164
+ with gr.Accordion("Similar Molecules Response", open=False):
165
+ similar_molecules_output = gr.JSON(
166
+ label="API Response",
167
+ elem_id="similar_molecules_output",
168
+ )
169
+
170
+ molecule_image = gr.Image(label="Similiar Molecules Grid", type="pil")
171
+
172
+ with gr.Tab("📊 Sample Molecules"):
173
+ gr.Markdown("""
174
+ ### Sample Molecules in Database
175
+ Click any button below to load the molecule into the JSME editor:
176
+ """)
177
+
178
+ with gr.Row():
179
+ with gr.Column(scale=1):
180
+ self._display_sample_molecules(SAMPLE_SMILES[::3])
181
+ with gr.Column(scale=1):
182
+ self._display_sample_molecules(SAMPLE_SMILES[1::3])
183
+ with gr.Column(scale=1):
184
+ self._display_sample_molecules(SAMPLE_SMILES[2::3])
185
+
186
+ search_btn.click(
187
+ fn=self.handle_search,
188
+ inputs=[smiles_input, embedding_dimension],
189
+ outputs=[
190
+ embedding_output,
191
+ similar_molecules_output,
192
+ molecule_image,
193
+ status_output,
194
+ ],
195
+ api_name="molecule_similarity_search_pipeline",
196
+ )
197
+
198
+ # Clear UI state
199
+ clear_btn.click(
200
+ fn=self.clear_all,
201
+ js="window.clearJSME",
202
+ outputs=[
203
+ smiles_input,
204
+ embedding_output,
205
+ similar_molecules_output,
206
+ molecule_image,
207
+ status_output,
208
+ ],
209
+ )
210
+
211
+ gr.set_static_paths(paths=["src/"])
212
+
213
+ return demo
214
+
215
+
216
+ if __name__ == "__main__":
217
+ app = App()
218
+ app.demo.launch(**LAUNCH_PARAMETERS)
src/src/constants.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model config
2
+ MODEL_NAME = "Derify/ChemMRL-alpha"
3
+ SUPPORTED_EMBEDDING_DIMENSIONS = [1024, 768, 512, 256, 128, 64, 32, 16, 8, 4, 2]
4
+ EMBEDDING_DIMENSION = max(SUPPORTED_EMBEDDING_DIMENSIONS)
5
+
6
+ # HNSW index parameters
7
+ HNSW_K = 6
8
+ HNSW_PARAMETERS = {
9
+ # Embedding vector dtype
10
+ "TYPE": "FLOAT32",
11
+ # Embedding vectors are normalized so COSINE and IP are equivalent
12
+ "DISTANCE_METRIC": "IP",
13
+ # Defines the initial capacity of the vector index. It helps in pre-allocating space for the index.
14
+ "INITIAL_CAP": 440,
15
+ # Max number of outgoing edges (connections) for each node in a graph layer.
16
+ "M": 32,
17
+ # Max number of connected neighbors to consider during graph building.
18
+ # Higher values increase accuracy, but also increase index build time.
19
+ "EF_CONSTRUCTION": 512,
20
+ # Max top candidates during KNN search. Higher values increase accuracy, but also increase search latency.
21
+ "EF_RUNTIME": 10,
22
+ }
23
+
24
+ # Gradio launch parameters
25
+ LAUNCH_PARAMETERS = {
26
+ "server_name": "0.0.0.0",
27
+ "server_port": 7860,
28
+ "share": True,
29
+ "debug": False,
30
+ "show_api": False,
31
+ "pwa": True,
32
+ "mcp_server": False,
33
+ }
src/src/data.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import pandas as pd
4
+
5
+ __data_dir = os.path.join(os.path.dirname(__file__), "data")
6
+
7
+ __dataset_smiles_file = os.path.join(__data_dir, "dataset_smiles.csv")
8
+ __sample_smiles_file = os.path.join(__data_dir, "sample_smiles.csv")
9
+ __isomer_design_subset_file = os.path.join(__data_dir, "isomer_design_subset.csv")
10
+
11
+ DATASET_SMILES = pd.read_csv(__dataset_smiles_file)
12
+ SAMPLE_SMILES = pd.read_csv(__sample_smiles_file)
13
+ ISOMER_DESIGN_SUBSET = pd.read_csv(__isomer_design_subset_file)
src/src/data/dataset_smiles.csv ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ smiles,name,category
2
+ CCO,Ethanol,Alcohol
3
+ CC(=O)O,Acetic acid,Carboxylic acid
4
+ c1ccccc1,Benzene,Aromatic hydrocarbon
5
+ CC(C)O,Isopropanol,Alcohol
6
+ CCN(CC)CC,Triethylamine,Amine
7
+ c1ccc(cc1)O,Phenol,Aromatic alcohol
8
+ CC(=O)OC1=CC=CC=C1C(=O)O,Aspirin,Carboxylic acid ester
9
+ CN1C=NC2=C1C(=O)N(C(=O)N2C)C,Caffeine,Alkaloid
10
+ CC(C)(C)OC(=O)NC1CCC(CC1)O,Boc-protected cyclohexanol,Protected alcohol
11
+ CCCCCCCCCCCCCCC(=O)O,Palmitic acid,Fatty acid
12
+ c1ccc2c(c1)cccn2,Quinoline,Aromatic heterocycle
13
+ CC1=CC=C(C=C1)C,p-Xylene,Aromatic hydrocarbon
14
+ CCCCO,Butanol,Alcohol
15
+ CC(C)C,Isobutane,Alkane
16
+ c1ccc(cc1)N,Aniline,Aromatic amine
17
+ CC(=O)N,Acetamide,Amide
18
+ CCCCCCCCCCCCCCCCCC(=O)O,Stearic acid,Fatty acid
19
+ c1ccc(cc1)C(=O)O,Benzoic acid,Aromatic carboxylic acid
20
+ CCc1ccccc1,Ethylbenzene,Aromatic hydrocarbon
21
+ CC(C)CC(C)(C)C,"2,2,4-Trimethylpentane",Branched alkane
22
+ O=C1c2ccccc2C(=O)N1C3CCC(=O)NC3=O,Thalidomide,Phthalimides
src/src/data/isomer_design_subset.csv ADDED
@@ -0,0 +1,415 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ smiles,name,category
2
+ O=C1CCCCC1(c1ccccc1Cl)N1CCCCC1,2-Cl-2'-Oxo-PCP,arylcycloalkylamine
3
+ CCCCNC1(c2ccccc2)CCCCC1,PCB,arylcycloalkylamine
4
+ COc1ccccc1C1(N2CCCCC2)CCCCC1,2-MeO-PCP,arylcycloalkylamine
5
+ c1ccc(C2(n3cccc3)CCCCC2)cc1,PCPyrrole,arylcycloalkylamine
6
+ Fc1cccc(C2(N3CCCC3)CC3CCC2C3)c1,3F-PBCHPy,arylcycloalkylamine
7
+ COc1ccc(C2(NCC3CCCO3)CCCCC2)cc1,1-(4-Methoxyphenyl)-N-[(oxolan-2-yl)methyl]cyclohexan-1-amine,arylcycloalkylamine
8
+ COc1ccc(C2(N3CCCC3)CC3CCC2C3)cc1,4-MeO-PBCHPy,arylcycloalkylamine
9
+ C=CCN(CC)C1(c2ccccc2)CCCCC1,N-Allyl-PCE,arylcycloalkylamine
10
+ CCCCCNC1(c2ccccc2)CCCCC1,PCPe,arylcycloalkylamine
11
+ OC1CCCCC1(c1ccccc1)N1CCCCC1,2'-HO-PCP,arylcycloalkylamine
12
+ Cc1ccccc1C1(N2CCCC(O)C2)CCCCC1,3″-HO-2-Me-PCP,arylcycloalkylamine
13
+ c1ccc(C2(N3CCCCC3)CCCC2)cc1,PCPEP,arylcycloalkylamine
14
+ CCN(C)C1(c2ccccc2C)CCCCC1,2-Me-PCEM,arylcycloalkylamine
15
+ Fc1ccccc1C1(N2CCCC2)CC2CCC1C2,2F-PBCHPy,arylcycloalkylamine
16
+ CC(C)OCCCNC1(c2ccccc2)CCCCC1,1-Phenyl-N-{3-[(propan-2-yl)oxy]propyl}cyclohexan-1-amine,arylcycloalkylamine
17
+ CCNC1(c2ccc(C)cc2)CCCCC1,4-Me-PCE,arylcycloalkylamine
18
+ CCNC1(c2cccc(OC)c2)CCCCC1=O,MXE,arylcycloalkylamine
19
+ CCOC(=O)CCCN(C)C1(c2ccccc2Cl)CCCCC1=O,Et-KE-Bu,arylcycloalkylamine
20
+ CCNC1(c2ccccc2)CCCCC1,PCE,arylcycloalkylamine
21
+ c1cc2c(cc1C1(N3CCOCC3)CCCCC1)OCO2,"3,4-MD-PCMo",arylcycloalkylamine
22
+ OCCNC1(c2ccccc2)CCCCC1,PCEOH,arylcycloalkylamine
23
+ c1ccc(C2(N3CCCCC3)CCCCCCC2)cc1,PCOP,arylcycloalkylamine
24
+ COc1ccc(C2(N3CCCCC3)CC3CCC2C3)cc1,4-MeO-PBCHP,arylcycloalkylamine
25
+ COc1cccc(C2(N3CCCCC3)CCCc3ccccc32)c1,"1-[1-(3-Methoxyphenyl)-1,2,3,4-tetrahydronaphthalen-1-yl]piperidine",arylcycloalkylamine
26
+ CCNC12CCCCC1CCc1ccccc12,"N-Ethyl-1,3,4,9,10,10a-hexahydrophenanthren-4a(2H)-amine",arylcycloalkylamine
27
+ c1ccc([C@]2(N3CCCCC3)C[C@H]3C[C@H]3C2)cc1,"1-[(1R,3r,5S)-3-Phenylbicyclo[3.1.0]hexan-3-yl]piperidine",arylcycloalkylamine
28
+ c1ccc(C2(N3CCCCC3)CN3CCC2CC3)cc1,P3QP,arylcycloalkylamine
29
+ COc1cccc(C2(N3CCCC3)CCCCC2=O)c1,3-MeO-2'-Oxo-PCPy,arylcycloalkylamine
30
+ c1cc2c(cc1C1(N3CCCCC3)CCCCC1)OCCO2,"3,4-ED-PCP",arylcycloalkylamine
31
+ NC1(c2ccccc2Cl)CCCNC1=O,3-Amino-3-(2-chlorophenyl)piperidin-2-one,arylcycloalkylamine
32
+ CC[C@]1(c2ccccc2)OC[C@H]([C@@H]2CCCCN2)O1,CL-1848C,arylcycloalkylamine
33
+ O=[N+]([O-])c1cccc(C2(N3CCCCC3)CCCCC2)c1,3-NO2-PCP,arylcycloalkylamine
34
+ Fc1cccc(C2(N3CCCCC3)CCCCCC2)c1,3F-PCHEP,arylcycloalkylamine
35
+ CCNC1(c2cccc(OC(C)C)c2)CCCCC1=O,iPXE,arylcycloalkylamine
36
+ COc1cc(C2(N3CCCCC3)CCCCC2)ccc1C,3-MeO-4-Me-PCP,arylcycloalkylamine
37
+ O=C1CCC(c2ccccc2)(N2CCCCC2)CC1,4'-Oxo-PCP,arylcycloalkylamine
38
+ CCNC1(c2ccc3c(c2)OCO3)CCCCC1,"3,4-MD-PCE",arylcycloalkylamine
39
+ CNC1(c2ccccc2OC)CCCCC1=O,2-MDCK,arylcycloalkylamine
40
+ CCOc1cccc(C2(N3CCCCC3)CCCCC2)c1,3-EtO-PCP,arylcycloalkylamine
41
+ CNC1(c2ccccc2C)CCCCC1=O,o-MDCK,arylcycloalkylamine
42
+ CNC1(c2cccc(Cl)c2)CCCCC1=O,meta-Ketamine,arylcycloalkylamine
43
+ CCNC1(c2cc(OC)ccc2Br)CCCCC1=O,Bromo-methoxetamine,arylcycloalkylamine
44
+ CNC1(c2cccc(OC)c2)CCCCC1=O,MXM,arylcycloalkylamine
45
+ CCCOC(=O)CCNC1(c2ccccc2Cl)CCCCC1=O,nPr-NKE-Et,arylcycloalkylamine
46
+ CC1CCCCC1(c1ccccc1)N1CCCCC1,2'-Me-PCP,arylcycloalkylamine
47
+ Cc1ccc(C2(N3CCC(O)CC3)CCCCC2O)cc1,"2',4″-HO-4-Me-PCP",arylcycloalkylamine
48
+ NC1(c2ccccc2Cl)CCC(O)CC1=O,"(2,5)-HNK",arylcycloalkylamine
49
+ Fc1cccc(C2(N3CCCCC3)CC3CCC2C3)c1,3F-PBCHP,arylcycloalkylamine
50
+ CC(C)NC1(c2ccccc2)CCCCC1,PCiP,arylcycloalkylamine
51
+ Fc1ccc(C2(N3CCCCC3)CCCCCC2)cc1,4F-PCHEP,arylcycloalkylamine
52
+ CCCNC1(c2ccccc2)CCCC1,PCPEPr,arylcycloalkylamine
53
+ CC(C)Oc1cccc(C2(N)CCCCC2)c1,3-IpO-PCA,arylcycloalkylamine
54
+ CC(O)CNC1(c2ccccc2)CCCCC1,1-[(1-Phenylcyclohexyl)amino]propan-2-ol,arylcycloalkylamine
55
+ Cc1ccc(C2(N(C)C)CCC(O)(CCc3ccccc3)CC2)cc1,MDPC,arylcycloalkylamine
56
+ Cc1cc(O)ccc1C1(N2CCOCC2)CCCCC1,4-HO-2-Me-PCMo,arylcycloalkylamine
57
+ O=C1CCCCC1(c1ccccc1)N1CCCC1,2-Phenyl-2-(pyrrolidin-1-yl)cyclohexan-1-one,arylcycloalkylamine
58
+ CNC1(c2ccccc2Cl)CCCCCC1=O,2-(2-Chlorophenyl)-2-(methylamino)cycloheptan-1-one,arylcycloalkylamine
59
+ CCN(CC)C1(c2ccccc2)CCCCC1,PCDE,arylcycloalkylamine
60
+ COc1cccc([C@@]2(O)CCN(C3(c4ccccc4)CCCCC3)C[C@@H]2CN(C)C)c1,US 7049327 #6,arylcycloalkylamine
61
+ Cc1cccc(C2(N3CCCC3)CC3CCC2C3)c1,3-Me-PBCHPy,arylcycloalkylamine
62
+ C#Cc1ccc2c(c1)C(c1ccccc1F)=N[C@@H](C)c1c(C(=O)N(C)C)ncn1-2,GL-i-54,aryldiazepine
63
+ O=C1CN=C(c2c(F)cccc2F)c2cc(Cl)ccc2N1,Ro-07-3953,aryldiazepine
64
+ O=C1CN=C(c2ccn[nH]2)c2cc(Cl)ccc2N1,SCHEMBL9684958,aryldiazepine
65
+ C#Cc1ccc2c(c1)C(c1ccccn1)=NCc1c(C(N)=O)ncn1-2,MP-ii-065,aryldiazepine
66
+ CN1C(=O)CN=C(c2ccccc2F)c2c(Cl)cccc21,Ro-13-0699,aryldiazepine
67
+ C#Cc1ccc2c(c1)C(c1ccccc1)=NCc1c(C(=O)OCC(F)(F)F)ncn1-2,DM-ii-20,aryldiazepine
68
+ O=C1OCCC2N=C(c3ccccc3)c3ccccc3-n3cnc1c32,"8-Phenyl-6,6a-dihydro-4-oxa-2,7,12b-triazabenzo[b]cyclopenta[kl]heptalen-3(5H)-one",aryldiazepine
69
+ CCC1C(C)=NN=C(c2ccc(OC)c(OC)c2)c2cc(OC)c(OC)cc21,Tofisopam,aryldiazepine
70
+ CN1C(=O)CN=C(c2ccc(F)cc2)c2cc(Cl)ccc21,4F-Diazepam,aryldiazepine
71
+ CC(C)COC(=O)c1ncn2c1C1CCCN1C(=O)c1c(Cl)cccc1-2,Ro-16-7082,aryldiazepine
72
+ CN1C(=O)CN=C(c2cccs2)c2cc(Cl)ccc21,WZ-113,aryldiazepine
73
+ CC(=O)c1ccc2c(c1)C(c1ccccc1)=NCC(=O)N2,Ro-20-3053,aryldiazepine
74
+ C#Cc1ccc2c(c1)C(=O)N(C)Cc1c(C(=O)OC(C)(C)C)ncn1-2,RY-24,aryldiazepine
75
+ CC(C)(C)OC(=O)c1ncn2c1C1CCCN1C(=O)c1c(F)cccc1-2,Ro-16-8912,aryldiazepine
76
+ O=C1CN=C(c2ccccc2F)c2cc(Cl)ccc2N1CCO,Ro-07-2750,aryldiazepine
77
+ CN1C(=O)CN=C(c2ccccc2Cl)c2cc([N+](=O)[O-])ccc21,Ro-05-4082,aryldiazepine
78
+ Cc1nnc2n1-c1sc(Cl)cc1C(c1ccccc1)=NC2,Deschloroclotizolam,aryldiazepine
79
+ CCOC(=O)c1ncn2c1C(C)N=C(c1ccc(F)cc1)c1cc(F)ccc1-2,"Ethyl 8-fluoro-6-(4-fluorophenyl)-4-methyl-4H-imidazo[1,5-a][1,4]benzodiazepine-3-carboxylate",aryldiazepine
80
+ O=C1CN=C(c2ccccc2F)c2cc(Cl)c(Cl)cc2N1,Ro-20-8065,aryldiazepine
81
+ CN1C(=O)CN=C(c2c(F)cccc2F)c2cc(Br)ccc21,Ro-13-3780,aryldiazepine
82
+ CN1C(=O)CC(=O)N(c2ccccc2)c2cc(Cl)ccc21,Clobazam,aryldiazepine
83
+ OCc1nnc2n1-c1ccc(Cl)cc1C(c1ccccc1)=NC2,alpha-Hydroxyalprazolam,aryldiazepine
84
+ O=C1Nc2ccc(Cl)cc2C(c2ccccc2)=NC1O,Oxazepam,aryldiazepine
85
+ CCOC(=O)c1ncn2c1CN=C(c1ccc([N+](=O)[O-])cc1)c1ccccc1-2,Ro-23-2896,aryldiazepine
86
+ CN1C(=O)CN=C(c2ccccc2F)c2cc(Br)ccc21,Flubrometazepam,aryldiazepine
87
+ CN(C)C(=O)c1nc2n(n1)-c1ccc(Cl)cc1C(c1ccccc1Cl)=NC2,Rilmazolam,aryldiazepine
88
+ CC1N=C(c2ccccc2F)c2cc(Cl)ccc2NC1=O,Ro-11-4878,aryldiazepine
89
+ CCOC(=O)c1ncn2c1C1CCCN1C(=O)c1cc(Br)ccc1-2,RY-054,aryldiazepine
90
+ CCOC(=O)c1ncn2c1C1CCN1C(=O)c1c(Cl)cccc1-2,Ro-16-0858,aryldiazepine
91
+ CN1C(=O)CN=C(c2ccc(Cl)cc2)c2cc(Cl)ccc21,Ro-05-4864,aryldiazepine
92
+ CN(C)CCc1nnc2n1-c1ccc(Cl)cc1C(c1ccccc1)=NC2,U-43465F,aryldiazepine
93
+ CN1C(=O)CN=C(c2ccccc2F)c2c(Cl)cc(Cl)cc21,Ro-13-0882,aryldiazepine
94
+ CCc1ccc2c(c1)C(c1ccccc1)=NCC(=O)N2,Ro-20-2533,aryldiazepine
95
+ CCOC(=O)c1ncn2c1CC=C(c1ccccc1F)c1ccccc1-2,Ro-15-2200,aryldiazepine
96
+ O=C1CC=C(c2ccccc2Cl)c2cc([N+](=O)[O-])ccc2N1,Ro-15-8867,aryldiazepine
97
+ Cc1cc2c(cc1Cl)NC(=O)CN=C2c1ccccc1F,Ro-20-8552,aryldiazepine
98
+ N#Cc1ncn2c1CN=C(c1ccc(Cl)cc1)c1cc(Cl)ccc1-2,"8-Chloro-6-(4-chlorophenyl)-4H-imidazo[1,5-a][1,4]benzodiazepine-3-carbonitrile",aryldiazepine
99
+ CC(C)c1nc(-c2ncn3c2CN(C)C(=O)c2c(Cl)cccc2-3)no1,FG-8205,aryldiazepine
100
+ Cc1nnc2n1-c1ccc([N+](=O)[O-])cc1C(c1ccccc1Cl)=NC2,Clonazolam,aryldiazepine
101
+ O=C1CN=C(c2ccccc2[N+](=O)[O-])c2cc(Br)ccc2N1,QH-II-067a,aryldiazepine
102
+ NC(=O)c1ncn2c1CC=C(c1ccccc1F)c1cc(Cl)ccc1-2,Ro-14-3930,aryldiazepine
103
+ COC(=O)CC[C@@H]1N=C(c2ccccn2)c2cc(Br)ccc2-n2c(C)cnc21,CNS-7056,aryldiazepine
104
+ CN1C(=O)CN=C(C2CCC2)c2cc(F)ccc21,"5-Cyclobutyl-7-fluoro-1-methyl-1,3-dihydro-2H-1,4-benzodiazepin-2-one",aryldiazepine
105
+ O=C1CN=C(c2c(F)cccc2Cl)c2cc(Cl)ccc2N1,Ro-07-5193,aryldiazepine
106
+ CN1C(=O)CN=C(c2ccccc2F)c2cc(I)ccc21,Ro-07-9957,aryldiazepine
107
+ O=C1CN=C(c2ccccc2)c2cc(Cl)ccc2N1CC1CC1,Prazepam,aryldiazepine
108
+ CCOC(=O)c1ncn2c1CN=C(c1cccc([N+](=O)[O-])c1)c1cc(F)ccc1-2,"Ethyl 8-fluoro-6-(3-nitrophenyl)-4H-imidazo[1,5-a][1,4]benzodiazepine-3-carboxylate",aryldiazepine
109
+ Clc1ccc2c(c1)-c1ncnn1Cc1c(Cl)ncn1-2,Ro4882224,aryldiazepine
110
+ [N-]=[N+]=Nc1ccc2c(c1)C(c1ccccc1F)=NCC(=O)N2,Ro-14-3074,aryldiazepine
111
+ Fc1ccccc1C1=NCC=Cc2ccc(Cl)cc21,Ro-22-1274,aryldiazepine
112
+ Nc1ncc2c(n1)-c1ccc(Cl)cc1C(c1ccccc1F)=NC2,Ro-22-2038,aryldiazepine
113
+ Clc1ccc2c(c1)C(c1ccccc1)=NCc1nncn1-2,Estazolam,aryldiazepine
114
+ Cc1nn(C)c2c1C(c1ccccc1F)=NCC(=O)N2C,Zolazepam,aryldiazepine
115
+ Cc1nnc2n1-c1ccc(Cl)cc1C(c1ccccn1)=NC2,Pyclazolam,aryldiazepine
116
+ S=C1CN=C(c2ccccc2)c2cc(Cl)ccc2N1,Thionordazepam,aryldiazepine
117
+ O=C1CN=C(c2ccccc2)c2cc(Cl)ccc2N1CC(F)(F)F,Halazepam,aryldiazepine
118
+ C#Cc1ccc2c(c1)C(c1ccccc1)=NCC1=N/C(=C\N3CCN(C)CC3)C(=O)N12,PS-i-37,aryldiazepine
119
+ C#Cc1ccc2c(c1)C(c1ccccc1F)=NCc1c(C(=O)OCC(F)(F)F)ncn1-2,JY-i-59,aryldiazepine
120
+ O=C1CN=C(c2ccccc2F)c2cc([N+](=O)[O-])ccc2N1,Fonazepam,aryldiazepine
121
+ CN1CCN(/C=C2\N=C3CN=C(c4ccccc4)c4cc(Br)ccc4N3C2=O)CC1,PS-1-35,aryldiazepine
122
+ CCCCCCC(C)(C)c1ccc([C@@H]2CCC[C@H](O)C2)c(O)c1,"(1R,3S) CP 47,497",cannabinoid
123
+ CCCc1ccc(C(=O)c2cn(CCCCCF)c3ccccc23)c2ccccc12,SGT-62,cannabinoid
124
+ CC(C)[C@H](NC(=O)c1cn(Cc2ccc(F)cc2)c2ccccc12)C(N)=O,AB-FUBICA,cannabinoid
125
+ CCCCCn1nc(C(=O)N[C@@H](Cc2ccccc2)C(=O)OC)c2ccccc21,MPP-PINACA,cannabinoid
126
+ O=C(Cc1cn(Cc2ccc(F)cc2)c2ccccc12)NC1C2CC3CC(C2)CC1C3,AFUBIATA,cannabinoid
127
+ CC(C)(C)c1nc(N2CCC(F)(F)C2)c2nnn(Cc3ccccc3S(C)(=O)=O)c2n1,"5-tert-Butyl-7-(3,3-difluoropyrrolidin-1-yl)-3-{[2-(methanesulfonyl)phenyl]methyl}-3H-[1,2,3]triazolo[4,5-d]pyrimidine",cannabinoid
128
+ CCC(C(N)=O)N(C)C(=O)c1nn(Cc2ccc(F)cc2)c2ccccc12,AB-FUBINACA isomer 5,cannabinoid
129
+ COc1cccc2c3c(=O)n([C@@H]4C(C)(C)[C@@H]5CC[C@@]4(C)C5)ccc3n(Cc3ccncc3)c12,WO 2001/058869 #190,cannabinoid
130
+ CCCC(F)Cn1cc(C(=O)C2C(C)(C)C2(C)C)c2ccccc21,(2-Fluoropentyl) XLR-11,cannabinoid
131
+ O=C(Nc1ccccc1)c1cn(CCCCCF)c2ccccc12,LTI-701,cannabinoid
132
+ C=CCCCn1nc(C(=O)N[C@H](C(=O)OC)C(C)C)c2ccccc21,MMB-4en-PINACA,cannabinoid
133
+ O=C(Nc1ccccc1)c1nn(CC2CCOCC2)c2ccccc12,SGT-224,cannabinoid
134
+ Cc1ccc(C(=O)NC(C)(C)c2ccccc2)cc1S(=O)(=O)N1CCC(F)(F)CC1,SGT-233,cannabinoid
135
+ CCCCCn1nc(C(=O)c2ccc(OC)c3ccccc23)c2ccccc21,SGT-35,cannabinoid
136
+ CC1(C)C(C(=O)c2cn(CC3CCCCC3)c3ccccc23)C1(C)C,(CHM) UR-144,cannabinoid
137
+ CN1CCCCC1Cn1cc(C(=O)c2ccc(N=C=S)c3ccccc23)c2ccc(N=C=S)cc21,AM-2215,cannabinoid
138
+ CCCCCCC1(c2ccc(-c3cc(C)cc(C)c3)c(O)c2)CC1,"4-(1-Hexylcyclopropyl)-3',5'-dimethyl[1,1'-biphenyl]-2-ol",cannabinoid
139
+ COC(=O)[C@@H](NC(=O)c1cn(Cc2ccc(F)cc2)c2ncccc12)C(C)(C)C,MDMB-FUB7AICA,cannabinoid
140
+ CN1CCCCC1Cn1cc(C(=O)c2ccccc2I)c2ccccc21,AM-2233,cannabinoid
141
+ O=C(c1cccc2ccccc12)n1c(-c2ccncc2)nc2ccccc21,(Naphthalen-1-yl)[2-(pyridin-4-yl)-1H-benzimidazol-1-yl]methanone,cannabinoid
142
+ C=CCCCn1nc(C(=O)N[C@H](C(=O)OC)C(C)(C)C)c2ccccc21,MDMB-4en-PINACA,cannabinoid
143
+ Oc1ccc(/C=C2\C=C(CCN3CCOCC3)c3ccccc32)c2ccccc12,US 5292736 #19,cannabinoid
144
+ CCc1c(C(=O)NN2CCCCC2)nn(-c2ccc(Cl)cc2Cl)c1-c1ccc(C#Cc2ccc(C(F)(F)F)cc2)s1,TM-38837,cannabinoid
145
+ COC(=O)[C@H](Cc1ccccc1)NC(=O)c1cn(CCCCCF)c2ccccc12,MPHP-2201,cannabinoid
146
+ Cc1ccc2c(C(C[N+](=O)[O-])c3ccccc3)c(-c3ccccc3)[nH]c2c1,GAT211,cannabinoid
147
+ CCCCCn1nc(C(=O)NC2CCCCC2)c2ccccc21,SGT-85,cannabinoid
148
+ CN1CCCCC1Cn1cc(C(=O)c2ccc([N+](=O)[O-])c3ccccc23)c2ccccc21,AM-1299,cannabinoid
149
+ CCc1c(C)cc(C(=O)NC2(C(=O)O)CCCCC2)c(=O)n1Cc1ccc(F)cc1,S-777469,cannabinoid
150
+ CCCCCC(C)NC(=O)c1nn(CCCCC)c2ccccc12,SGT-71,cannabinoid
151
+ CC1(C)Oc2cc(C34CC5CC(CC(C5)C3)C4)cc(O)c2[C@@H]2CC(O)CC[C@H]21,"(6aR,10aR)-3-(Adamantan-1-yl)-6,6-dimethyl-6a,7,8,9,10,10a-hexahydro-6H-dibenzo[b,d]pyran-1,9-diol",cannabinoid
152
+ C=C(C)[C@H]1CCC(CO)=C[C@@H]1c1c(O)cc(C(C)(C)CCCCN2CCOCC2)cc1O,"(1'S,2'S)-5'-(Hydroxymethyl)-4-[2-methyl-6-(morpholin-4-yl)hexan-2-yl]-2'-(prop-1-en-2-yl)-1',2',3',4'-tetrahydro[1,1'-biphenyl]-2,6-diol",cannabinoid
153
+ O=C(N/N=C1\C(=O)N(CCCCCF)c2ccccc21)c1ccccc1,BZO-5F-POXIZID,cannabinoid
154
+ CCCCCOc1c(OC)ccc2cc(C(=O)NCc3ccc4c(c3)OCO4)c(=O)[nH]c12,JTE-907,cannabinoid
155
+ CCCCn1nc(C(=O)N[C@@H](Cc2ccccc2)C(=O)OC)c2ccccc21,MPP(N)-073,cannabinoid
156
+ CCCCCCC(C)(C)c1ccc([C@@H]2CCC[C@@H](O)C2)c(O)c1,"(R,R)-epi-CP 47,497",cannabinoid
157
+ CCCCCOc1ccc(C(=O)c2cccc3ccccc23)c2ccccc12,CB-13,cannabinoid
158
+ COc1ccccc1OC(=O)c1ccc(C)c(S(=O)(=O)N2CCOCC2)c1,2-Methoxyphenyl 4-methyl-3-(morpholine-4-sulfonyl)benzoate,cannabinoid
159
+ CCCCCC#Cc1cc(O)c2c(c1)OC(C)(C)[C@@H]1CC=C(C)C[C@@H]21,AMG-1,cannabinoid
160
+ CC(C)[C@H](NC(=O)c1cn(CCCCCF)c2ccccc12)C(N)=O,5F-ABICA,cannabinoid
161
+ CCCCCn1cc(C(=O)NC23CC4CC(CC(C4)C2)C3)c(=O)c2ccc(F)cc21,"N-(Adamantan-1-yl)-7-fluoro-4-oxo-1-pentyl-1,4-dihydroquinoline-3-carboxamide",cannabinoid
162
+ CC1=CC[C@@H]2[C@@H](C1)c1c(O)cc(C(C)(C)CCCCCC#N)cc1OC2(C)C,O-774,cannabinoid
163
+ CC(C)(C)[C@H](NC(=O)n1c(=O)n(CCN2CCOCC2)c2ccccc21)C(N)=O,WO 2008/032164 #4,cannabinoid
164
+ COC(=O)[C@H](Cc1ccccc1)NC(=O)c1cn(CC2CCCCC2)c2ccccc12,MPP-CHMICA,cannabinoid
165
+ Fc1ccc2nc(-c3ccccn3)n(Cc3cccc4ccccc34)c2c1,6-Fluoro-1-[(naphthalen-1-yl)methyl]-2-(pyridin-2-yl)-1H-benzimidazole,cannabinoid
166
+ CCCCCn1cc(C(=O)N[C@@H](C)c2ccccc2)c2ccccc21,1-Pentyl-N-[(1S)-1-phenylethyl]-1H-indole-3-carboxamide,cannabinoid
167
+ CCCCCCCC(C)c1cc(OC(=O)CCCN(CC)CC)c2c(c1)OC(C)(C)C1=C2CC(C)CC1,SP-325,cannabinoid
168
+ CCCCCn1cc(C(=O)c2cccc3ccccc23)cc1-c1cccc(C)c1,JWH-346,cannabinoid
169
+ O=C(Cc1ccccc1)N/N=C1\C(=O)N(CC2CCCCC2)c2cc(OCCN3CCOCC3)ccc21,"N'-{1-(Cyclohexylmethyl)-6-[2-(morpholin-4-yl)ethoxy]-2-oxo-1,2-dihydro-3H-indol-3-ylidene}-2-phenylacetohydrazide",cannabinoid
170
+ Cc1c(C(=O)C2C(C)(C)C2(C)C)c2ccccc2n1CCCCCF,2-Me-XLR-11,cannabinoid
171
+ COc1ccc2c(c1)CCC2CNC(=O)c1cn(CCCCCF)c2ccccc12,SGT-105,cannabinoid
172
+ CCCCCc1cc(O)c2c(c1)OC(C)(C)C(CCC(C)=O)C2=O,CBCN,cannabinoid
173
+ CCCCCn1nc(C(=O)NC(C)(C)c2ccc(F)cc2)c2ccccc21,SGT-60,cannabinoid
174
+ CC(C)(C)[C@H](NC(=O)c1nn(CC2CCCCCC2)c2ccccc12)C(=O)NCCO,WO 2009/106980 #433,cannabinoid
175
+ CC(C)(NC(=O)c1cn(Cc2ccc(F)cc2)c2ccccc12)c1ccccc1,CUMYL-FUBICA,cannabinoid
176
+ COC(=O)[C@@H](NC(=O)c1nn(CC2CCCCC2)c2ccccc12)C(C)(C)C,MDMB(N)-CHM,cannabinoid
177
+ CCCCCn1nc(C(=O)c2cccc3ccccc23)c2ccccc21,SGT-17,cannabinoid
178
+ CCCCCn1cc(C(=O)N[C@H](C(N)=O)C(C)(C)C)c2ccccc21,ADBICA,cannabinoid
179
+ CN1CCCCC1Cn1cc(C(=O)c2cc(N=C=S)ccc2I)c2ccc(N=C=S)cc21,AM-2223,cannabinoid
180
+ CCCCCCCCCn1cc(C(=O)c2cccc3ccccc23)c2ccccc21,(Nonyl) JWH-018,cannabinoid
181
+ CCCCCCC(C)(C)c1cc(OC)c([C@@H]2C=C(CO)C3CC2C3(C)C)c(OC)c1,HU-433,cannabinoid
182
+ C=CCc1cc(OC)c(OC)c(OC)c1OC,"2,3,4,5-Tetramethoxyphenylprop-2-ene",essential oil
183
+ C/C=C\c1ccc(O)c(OC)c1,cis-4-Hydroxy-3-methoxyphenylprop-1-ene,essential oil
184
+ C/C=C/c1ccc2c(c1OC)OCO2,Isocroweacin,essential oil
185
+ C/C=C\c1cc(OC)c(O)c(OC)c1,"cis-4-Hydroxy-3,5-dimethoxyphenylprop-1-ene",essential oil
186
+ C=CCc1ccc2c(c1OC)OCO2,Croweacin,essential oil
187
+ C/C=C\c1cc2c(cc1OC)OCO2,"cis-2-Methoxy-4,5-methylenedioxyphenylprop-1-ene",essential oil
188
+ C=CCc1ccc2c(c1)OCO2,Safrole,essential oil
189
+ C/C=C\c1cc(OC)c2c(c1)OCO2,cis-Isomyristicin,essential oil
190
+ C/C=C\c1ccc(OC)cc1OC,"cis-2,4-Dimethoxyphenylprop-1-ene",essential oil
191
+ C/C=C\c1ccc2c(c1OC)OCO2,"cis-2-Methoxy-3,4-methylenedioxyphenylprop-1-ene",essential oil
192
+ C/C=C/c1ccc(OC)c(OC)c1,Methylisoeugenol,essential oil
193
+ C=CCc1ccc(OC)cc1OC,Osmorrhizole,essential oil
194
+ C=CCc1ccc(OC)c(OC)c1,Methyleugenol,essential oil
195
+ C=CCc1ccc(O)c(OC)c1,Eugenol,essential oil
196
+ C=CCc1cc2c(c(OC)c1OC)OCO2,Dillapiole,essential oil
197
+ C/C=C\c1ccc2c(c1)OCO2,alpha-Isosafrole,essential oil
198
+ C/C=C/c1cc(OC)c(OC)c(OC)c1,Isoelemicin,essential oil
199
+ C=CCc1ccc(OC)c(O)c1,Chavibetol,essential oil
200
+ C=CCc1cc(OC)c(OC)c(OC)c1,Elemicin,essential oil
201
+ C=CCc1cc(OC)cc(OC)c1,"3,5-Dimethoxyphenylprop-2-ene",essential oil
202
+ C/C=C\c1cc(OC)c(OC)c(OC)c1,cis-Isoelemicin,essential oil
203
+ C/C=C/c1cc(OC)c(OC)c(OC)c1OC,"trans-2,3,4,5-Tetramethoxyphenylprop-1-ene",essential oil
204
+ C/C=C/c1cc(OC)c2c(c1OC)OCO2,Isoapiole,essential oil
205
+ C/C=C\c1ccc(OC)c(O)c1,cis-3-Hydroxy-4-methoxyphenylprop-1-ene,essential oil
206
+ C=CCc1ccc(OC)cc1,Estragole,essential oil
207
+ C/C=C\c1cc(OC)c2c(c1OC)OCO2,"cis-2,5-Dimethoxy-3,4-methylenedioxyphenylprop-1-ene",essential oil
208
+ C=CCc1cc(OC)c2c(c1OC)OCO2,Apiole,essential oil
209
+ C/C=C/c1ccc(OC)cc1OC,Nothosmyrnol,essential oil
210
+ C/C=C/c1cc(OC)cc(OC)c1,"trans-3,5-Dimethoxyphenylprop-1-ene",essential oil
211
+ C/C=C\c1cc2c(c(OC)c1OC)OCO2,"cis-2,3-Dimethoxy-4,5-methylenedioxyphenylprop-1-ene",essential oil
212
+ C/C=C\c1ccc(OC)cc1,cis-4-Methoxyphenylprop-1-ene,essential oil
213
+ C/C=C/c1cc(OC)c(O)c(OC)c1,"2,6-Dimethoxy-4-[(1E)-prop-1-en-1-yl]phenol",essential oil
214
+ C=CCc1cc(OC)c(OC)cc1OC,γ-Asarone,essential oil
215
+ C/C=C/c1ccc(OC)cc1,Anethole,essential oil
216
+ C=CCc1cc2c(cc1OC)OCO2,Asaricin,essential oil
217
+ C/C=C/c1cc2c(c(OC)c1OC)OCO2,Isodillapiole,essential oil
218
+ C/C=C/c1cc(OC)c(OC)cc1OC,Asarone,essential oil
219
+ C/C=C/c1ccc(O)c(OC)c1,Isoeugenol,essential oil
220
+ C/C=C\c1cc(OC)cc(OC)c1,"cis-3,5-Dimethoxyphenylprop-1-ene",essential oil
221
+ C/C=C\c1cc(OC)c(OC)cc1OC,beta-Asarone,essential oil
222
+ C=CCc1cc(OC)c2c(c1)OCO2,Myristicin,essential oil
223
+ C/C=C/c1ccc(OC)c(O)c1,2-Methoxy-5-[(1E)-prop-1-en-1-yl]phenol,essential oil
224
+ C/C=C/c1cc(OC)c2c(c1)OCO2,Isomyristicin,essential oil
225
+ C/C=C\c1ccc(OC)c(OC)c1,"cis-3,4-Dimethoxyphenylprop-1-ene",essential oil
226
+ C=CCc1cc(OC)c(O)c(OC)c1,5-Methoxyeugenol,essential oil
227
+ C/C=C/c1ccc2c(c1)OCO2,beta-Isosafrole,essential oil
228
+ C/C=C\c1cc(OC)c(OC)c(OC)c1OC,"cis-2,3,4,5-Tetramethoxyphenylprop-1-ene",essential oil
229
+ C/C=C/c1cc2c(cc1OC)OCO2,Carpacin,essential oil
230
+ CCC(=O)N(c1ccccc1)C1(COC)CCN(CC(O)c2cccs2)CC1,beta-Hydroxy-sufentanil,fentanyl
231
+ CCC(=O)N(CCc1ccccc1)C1CCN(CCc2ccccc2)CC1,(ethylene) Fentanyl,fentanyl
232
+ CCC(=O)N(c1ccccc1F)C1(c2ccccc2)CCN(CCn2cccn2)CC1,N-(2-Fluorophenyl)-N-{4-phenyl-1-[2-(1H-pyrazol-1-yl)ethyl]piperidin-4-yl}propanamide,fentanyl
233
+ CCC(=O)N(c1ccccc1)C1CCN(C(C)Cc2cc(OC)c(I)cc2OC)CC1,N-(DOI) fentanyl,fentanyl
234
+ CCC(=O)N(c1ccccc1)C1(COC(=O)C(C)(C)C)CCN(CCN2C(=O)c3ccccc3C2=O)CC1,"{1-[2-(1,3-Dioxo-1,3-dihydro-2H-isoindol-2-yl)ethyl]-4-[phenyl(propanoyl)amino]piperidin-4-yl}methyl 2,2-dimethylpropanoate",fentanyl
235
+ CC(C)C(=O)N(c1cccc(F)c1)C1CCN(CCc2ccccc2)CC1,m-Fluoro-isobutyrylfentanyl,fentanyl
236
+ CCCC(=O)N(c1ccc(OC)cc1)C1CCN(CCc2ccccc2)CC1,p-MeO-BF,fentanyl
237
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(Cc2ccccc2)CC1,Benzylcarfentanil,fentanyl
238
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCc2ccsc2)CC1,Methyl 4-[phenyl(propanoyl)amino]-1-[2-(thiophen-3-yl)ethyl]piperidine-4-carboxylate,fentanyl
239
+ COCC(=O)N(c1ccc(C)cc1)C1CCN(CCc2ccccc2)CC1,p-Methyl-methoxyacetylfentanyl,fentanyl
240
+ CCCCC(=O)N(c1ccc(OC)cc1)C1CCN(CCc2ccccc2)CC1,p-Methoxy-valerylfentanyl,fentanyl
241
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)CC1F,NFEPP,fentanyl
242
+ CCC(=O)N(c1ccccc1)C1CCN(C(C)Cc2cc(OC)c(Br)cc2OC)CC1,N-(DOB) fentanyl,fentanyl
243
+ CCCC(=O)N(c1ccccc1)C1CCN(C)CC1,N-Methyl-butyrylfentanyl,fentanyl
244
+ O=C(c1ccco1)N(c1ccccc1)C1CCN(CCc2ccc(O)cc2)CC1,4'-Hydroxy-furanylfentanyl,fentanyl
245
+ CCC(=O)OCC1(N(C(=O)CC)c2ccccc2)CCN(CCN2C(=O)c3ccccc3C2=O)CC1,"{1-[2-(1,3-Dioxo-1,3-dihydro-2H-isoindol-2-yl)ethyl]-4-[phenyl(propanoyl)amino]piperidin-4-yl}methyl propanoate",fentanyl
246
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)C(C)C1,2-Methylfentanyl,fentanyl
247
+ CC(=O)N(c1ccccc1)C1CCN(CCCc2ccccc2)CC1,Phenylpropyl-acetyl-norfentanyl,fentanyl
248
+ CCC(=O)N(c1ccccc1)C1CCN(CCOc2ccccc2)CC1,POE-F,fentanyl
249
+ O=C(c1ccco1)N(c1ccccc1)C1CCNCC1,Furanyl-norfentanyl,fentanyl
250
+ CCC(=O)N(c1ccccc1)C1CCN(Cc2ccccc2)CC1,R-4129,fentanyl
251
+ Cc1ccc(NC2CCN(CCc3ccccc3)CC2)cc1,p-Me-4-ANPP,fentanyl
252
+ CCC(=O)N(c1ccccc1)C1(C(=O)O)CCN(CCc2ccccc2)C(O)C1,2-Hydroxycarfentanil acid,fentanyl
253
+ COCC(=O)N(c1ccc(F)cc1)C1CCN(CCc2ccccc2)CC1,p-Fluoro-methoxyacetylfentanyl,fentanyl
254
+ Cc1cccc(N(C(=O)c2ccco2)C2CCN(CCc3ccccc3)CC2)c1,m-Methyl-furanylfentanyl,fentanyl
255
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2F)CC1,2″-Fluorofentanyl,fentanyl
256
+ COc1ccccc1N(C(=O)c1ccco1)C1CCN(CCc2ccccc2)CC1,o-Methoxy-furanylfentanyl,fentanyl
257
+ CCC(=O)N(c1ccccc1)C1CCN(CC(O)c2ccc(F)cc2)CC1,N-{1-[2-(4-Fluorophenyl)-2-hydroxyethyl]piperidin-4-yl}-N-phenylpropanamide,fentanyl
258
+ CC(=O)N(c1ccccc1)C1CCN(CCc2cccs2)CC1,Acetylthiofentanyl,fentanyl
259
+ COCC(=O)N(c1cccc(F)c1)C1CCN(CCc2ccccc2)CC1,m-Fluoro-methoxyacetylfentanyl,fentanyl
260
+ COc1cc(CCN2CCC(N(C(=O)C(=O)CCC(=O)O)c3ccccc3)CC2)ccc1O,N-Phenyl-N-[1-(2-phenylethyl)piperidin-4-yl]-2-oxo-4-carboxybutanamide,fentanyl
261
+ CCC(=O)N(c1ccccc1)C1(COC)CCN(CCn2nnn(CC)c2=O)CC1,R-39209,fentanyl
262
+ CCC(=O)N(c1ccc(Cl)cc1)C1CCN(CCc2ccccc2)CC1,p-CF,fentanyl
263
+ CCC(=O)N(c1ccccc1)C1CCNCC1,Norfentanyl,fentanyl
264
+ COC(=O)CCN1CCC(Nc2ccccc2)(C(=O)OC)CC1,Despropionyl remifentanil,fentanyl
265
+ CCC(=O)N(c1ccccc1)C1(c2nc(C)cs2)CCN(CCc2ccccc2)CC1,"N-[4-(4-Methyl-1,3-thiazol-2-yl)-1-(2-phenylethyl)piperidin-4-yl]-N-phenylpropanamide",fentanyl
266
+ CCC(=O)N(c1ccccc1)C1(c2ccccc2)CCN(CCc2ccccc2)CC1,4-Phenylfentanyl,fentanyl
267
+ CCC(=O)N(c1ccccc1C)C1CCN(CCc2ccccc2)CC1,o-Methylfentanyl,fentanyl
268
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCCCCF)CC1,Fluoropentyl-norcarfentanil,fentanyl
269
+ O=C(c1ccco1)N(c1ccccc1)C1CCN(Cc2ccccc2)CC1,Furanylbenzylfentanyl,fentanyl
270
+ CCC(=O)N(c1ccc2ncoc2c1)C1CCN(CCc2ccccc2)CC1,N-Benzoxazolyl-fentanyl,fentanyl
271
+ COCC(=O)N(c1cccc(C)c1)C1CCN(CCc2ccccc2)CC1,m-Methyl-methoxyacetylfentanyl,fentanyl
272
+ CC(C)C(=O)OCC1(N(C(=O)C(C)C)c2ccccc2)CCN(CCN2C(=O)c3ccccc3C2=O)CC1,"{1-[2-(1,3-Dioxo-1,3-dihydro-2H-isoindol-2-yl)ethyl]-4-[(2-methylpropanoyl)(phenyl)amino]piperidin-4-yl}methyl 2-methylpropanoate",fentanyl
273
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCc2ccccn2)CC1,Methyl 4-[phenyl(propanoyl)amino]-1-[2-(pyridin-2-yl)ethyl]piperidine-4-carboxylate,fentanyl
274
+ c1ccc(CCN2CCC(Nc3ccccc3)CC2)cc1,ANPP,fentanyl
275
+ CCCc1cc(OC)c(CCN2CCC(N(C(=O)CC)c3ccccc3)CC2)cc1OC,N-(2C-P) fentanyl,fentanyl
276
+ CCC(=O)N(c1ccccc1)C1CCN(CC(O)c2ccncc2)CC1C,N-{1-[2-Hydroxy-2-(pyridin-4-yl)ethyl]-3-methylpiperidin-4-yl}-N-phenylpropanamide,fentanyl
277
+ CCC(=O)N(c1ccccc1)C1CCN(CC(=O)c2cccc(F)c2)CC1,N-{1-[2-(3-Fluorophenyl)-2-oxoethyl]piperidin-4-yl}-N-phenylpropanamide,fentanyl
278
+ CCCCc1cc(OC)c(CC(C)N2CCC(N(C(=O)CC)c3ccccc3)CC2)cc1OC,N-(DOBU) fentanyl,fentanyl
279
+ COCC(=O)N(c1ccccc1)C1C(C)CN(CCn2cccn2)CC1C,"N-{3,5-Dimethyl-1-[2-(1H-pyrazol-1-yl)ethyl]piperidin-4-yl}-2-methoxy-N-phenylacetamide",fentanyl
280
+ Cc1ccc(N(C(=O)C2CCCO2)C2CCN(CCc3ccccc3)CC2)cc1,p-Methyl-tetrahydrofuranylfentanyl,fentanyl
281
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2cc(OC)cc(OC)c2)CC1,"3″,5″-DiMeO-F",fentanyl
282
+ CC(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)CC1,Acetylfentanyl,fentanyl
283
+ CCC(=O)N(c1ccccc1)C1CCN(CCc2ccc(F)cc2)CC1,4″-Fluorofentanyl,fentanyl
284
+ CCC(=O)N(c1ccccc1)C1(COC(=O)OC)CCN(CCc2cccs2)CC1,Methyl {4-[phenyl(propanoyl)amino]-1-[2-(thiophen-2-yl)ethyl]piperidin-4-yl}methyl carbonate,fentanyl
285
+ CCC(=O)[N+]([O-])(c1ccccc1)C1(C(=O)OC)CCN(CCc2ccccc2)CC1,Carfentanil N-oxide,fentanyl
286
+ CCC(=O)N(c1ccccc1)C1(C(=O)OC)CCN(CCc2cccc(O)c2)CC1,3″-Hydroxycarfentanil,fentanyl
287
+ CCC(=O)N(c1ccccc1)C1CCN(C(C)C(=O)OC(C)C)CC1,Propan-2-yl 2-{4-[phenyl(propanoyl)amino]piperidin-1-yl}propanoate,fentanyl
288
+ O=C(C1CCC1)N(c1ccc(Cl)cc1)C1CCN(CCc2ccccc2)CC1,p-Chloro-cyclobutylfentanyl,fentanyl
289
+ CCC(C)C(=O)N(c1ccccc1)C1CCN(CCc2ccccc2)CC1,alpha'-Methyl-butyrylfentanyl,fentanyl
290
+ Oc1cc2c(cc1O)CNCC2,Norsalsolinol,neurotoxin
291
+ CC(N)Cc1ccc(Cl)cc1,PCA,neurotoxin
292
+ CC1NCCc2cc(O)c(O)cc21,Salsolinol,neurotoxin
293
+ CC(N)Cc1ccc(Br)cc1,PBA,neurotoxin
294
+ NCCc1cc(O)c(O)cc1O,6-OHDA,neurotoxin
295
+ COc1ccc(CCN)cc1OC,DMPEA,peyote alkaloid
296
+ CNCCc1cc(OC)c(OC)c(OC)c1,M-M,peyote alkaloid
297
+ COc1cc2c(c(OC)c1OC)C(C)N(C=O)CC2,N-Formyl-O-methylanhalonidine,peyote alkaloid
298
+ COc1cc2c(c3c1OCO3)C(C)[N+](C)(C)CC2,Lophotine,peyote alkaloid
299
+ COc1cc(CCN)ccc1O,GEA,peyote alkaloid
300
+ COc1cc(CCNCC(=O)O)cc(OC)c1OC,Mescaloxylic acid,peyote alkaloid
301
+ COc1cc2c(c(O)c1OC)C(C)N(C=O)CC2,N-Formylanhalonidine,peyote alkaloid
302
+ COc1cc(CCN2C(=O)CC(O)C2=O)cc(OC)c1OC,Mescaline malimide,peyote alkaloid
303
+ CNCCc1ccc(O)c(O)c1,Epinine,peyote alkaloid
304
+ COc1cc2c(c(O)c1OC)C(C)(C(=O)O)NCC2,Peyoruvic acid,peyote alkaloid
305
+ CCN1CCc2cc(OC)c3c(c2C1C)OCO3,Peyophorine,peyote alkaloid
306
+ COc1cc(CCN2C(=O)C=CC2=O)cc(OC)c1OC,Mescaline maleimide,peyote alkaloid
307
+ COc1c(O)cc2c(c1OC)CN(C)CC2,Isoanhalidine,peyote alkaloid
308
+ NCCc1ccc2c(c1)OCO2,MDPEA,peyote alkaloid
309
+ COc1cc2c(c(O)c1OC)C1CCC(=O)N1CC2,Peyoglutam,peyote alkaloid
310
+ COc1cc(CCN)cc(O)c1OC,3-DESMETHYL,peyote alkaloid
311
+ CCOc1ccc(CC(C)N(C)C)c(OCC)c1,"2,4-Diethoxy-N,N-dimethylamphetamine",peyote alkaloid
312
+ CN(C)CCc1ccc2c(c1)OCO2,Lobivine,peyote alkaloid
313
+ COc1c(O)cc2c(c1OC)C(C)N(C)CC2,Isopellotine,peyote alkaloid
314
+ COc1cc(CCNC(C)=O)cc(OC)c1OC,N-Acetylmescaline,peyote alkaloid
315
+ COc1cc2c(c3c1OCO3)C(C)N(C(C)=O)CC2,N-Acetylanhalonine,peyote alkaloid
316
+ COc1cc(CCN(C)C)cc(O)c1OC,"N,N-Me-3-DESMETHYL",peyote alkaloid
317
+ COc1c(O)cc2c(c1OC)C(C)NCC2,Isoanhalonidine,peyote alkaloid
318
+ COc1cc(CCn2cccc2C(=O)O)cc(OC)c1OC,Peyonine,peyote alkaloid
319
+ COc1cc2c(c(O)c1OC)CN(C(C)=O)CC2,N-Acetylanhalamine,peyote alkaloid
320
+ COc1cc2c(c(O)c1OC)C(C(=O)O)NCC2,Peyoxylic acid,peyote alkaloid
321
+ COc1cc(CCN(C)C)ccc1O,MM-GEA,peyote alkaloid
322
+ COc1cc2c(c(OC)c1OC)CNCC2,Anhalinine,peyote alkaloid
323
+ CNCCc1ccc(O)cc1,HMePEA,peyote alkaloid
324
+ COc1cc2c(c(O)c1OC)C[N+](C)(C)CC2,Anhalotine,peyote alkaloid
325
+ COc1c(O)cc2c(c1OC)CNCC2,Isoanhalamine,peyote alkaloid
326
+ COc1cc(CCN)cc(O)c1O,"3,4-DESMETHYL",peyote alkaloid
327
+ COc1cc2c(c(O)c1OC)CN(C=O)CC2,N-Formylanhalamine,peyote alkaloid
328
+ COc1cc(CCNC(C)C(=O)O)cc(OC)c1OC,Mescaloruvic acid,peyote alkaloid
329
+ C[N+](C)(C)CCc1ccc(O)cc1,Candicine,peyote alkaloid
330
+ COc1cc2c(c(O)c1OC)C(C)NCC2,Anhalonidine,peyote alkaloid
331
+ COc1cc2c(c(OC)c1OC)C1CCC(=O)N1CC2,Mescalotam,peyote alkaloid
332
+ COc1cc2c(c3c1OCO3)C(C)NCC2,Anhalonine,peyote alkaloid
333
+ COc1cc2c(c(O)c1OC)C(C)N(C)CC2,Pellotine,peyote alkaloid
334
+ COc1cc2c(c(O)c1OC)CN(C)CC2,Anhalidine,peyote alkaloid
335
+ COc1cc2c(c3c1OCO3)C(C)N(C)CC2,Lophophorine,peyote alkaloid
336
+ COc1cc(CCN)cc2c1OCO2,LOPHOPHINE,peyote alkaloid
337
+ COc1cc(CCNC(C)=O)cc(O)c1OC,N-Acetyl-3-demethymescaline,peyote alkaloid
338
+ COc1cc(CCN)cc(OC)c1OC,M,peyote alkaloid
339
+ COc1cc(CCN2C(=O)CCC2=O)cc(OC)c1OC,Mescaline succinimide,peyote alkaloid
340
+ COc1cc2c(c(O)c1OC)C(C)[N+](C)(C)CC2,Peyotine,peyote alkaloid
341
+ COc1cc2c(c(OC)c1OC)C(C)NCC2,O-Methylanhalonidine,peyote alkaloid
342
+ COc1cc2c(c(O)c1OC)CNCC2,Anhalamine,peyote alkaloid
343
+ COc1cc(CCN2C(=O)CC(O)(CC(=O)O)C2=O)cc(OC)c1OC,Mescaline citrimide,peyote alkaloid
344
+ CN(C)CCc1ccc(O)cc1,Hordenine,peyote alkaloid
345
+ COc1cc(CCNC=O)cc(OC)c1OC,N-Formylmescaline,peyote alkaloid
346
+ CNCCc1cc(O)c(OC)c(OC)c1,N-Me-3-DESMETHYL,peyote alkaloid
347
+ COc1cc(CCn2c(C=O)ccc2CO)cc(OC)c1OC,Peyoglunal,peyote alkaloid
348
+ COc1cc(CCNC=O)cc(O)c1OC,N-Formyl-3-demethylmescaline,peyote alkaloid
349
+ NCCc1ccc(O)c(O)c1,Dopamine,peyote alkaloid
350
+ COc1cc2c(c3c1OCO3)C(C)N(C=O)CC2,N-Formylanhalonine,peyote alkaloid
351
+ CNCCc1ccc(O)c(OC)c1,N-Me-GEA,peyote alkaloid
352
+ COc1cc2c(c(OC)c1OC)CN(C=O)CC2,N-Formylanhalinine,peyote alkaloid
353
+ COc1cc(CCN2C(=O)C3CC(=O)OC3C2=O)cc(OC)c1OC,Mescaline isocitrimide lactone,peyote alkaloid
354
+ COc1cc2c(c(OC)c1OC)C(C)N(C)CC2,O-Methylpellotine,peyote alkaloid
355
+ CCC(C)N(CCc1c[nH]c2ccc(F)cc12)C(C)C,5-Fluoro-IPSBT,tryptamine
356
+ CC(C)N(CCc1c[nH]c2ccc(F)cc12)CC1CC1,5-Fluoro-N-cyclopropylmethyl-NIPT,tryptamine
357
+ CCCCCCN(C)CCc1c[nH]c2ccc(OC)cc12,N-[2-(5-Methoxy-1H-indol-3-yl)ethyl]-N-methylhexan-1-amine,tryptamine
358
+ CN(C)CCc1c[nH]c2c(Br)ccc(O)c12,7-Bromopsilocin,tryptamine
359
+ CCCCN(CCCC)CCc1c[nH]c2cc(OC)c(OC)cc12,"5,6-MeO-DBT",tryptamine
360
+ CN(C/C=C/c1ccccc1)CCc1c[nH]c2ccccc12,N-Phenylpropenyl-NMT,tryptamine
361
+ COc1cc2[nH]cc(CCN3CCCC3)c2cc1OC,"5,6-MeO-pyr-T",tryptamine
362
+ Cn1cc(CCN)c2c3c(ccc21)OCCC3,"CP 132,484",tryptamine
363
+ C=CCN(CCc1c(C)[nH]c2ccc(OC)cc12)C1CCCCC1,2-Methyl-5-methoxy-N-allyl-N-cyclohexyltryptamine,tryptamine
364
+ Cc1cc(OP(=O)(O)O)c2c(CCN)c[nH]c2c1,6-Methyl-4-PO-T,tryptamine
365
+ CCCCCN(CCCCC)CCc1c[nH]c2ccccc12,"N,N-Dipentyltryptamine",tryptamine
366
+ COc1ccc2[nH]cc(CC3CCCN3C)c2c1,CP-108509,tryptamine
367
+ COc1ccc(OC)c(CCCN(C)CCc2c[nH]c3ccc(OC)cc23)c1,"3-(2,5-Dimethoxyphenyl)-N-[2-(5-methoxy-1H-indol-3-yl)ethyl]-N-methylpropan-1-amine",tryptamine
368
+ C=CCN(CCc1c[nH]c2ccc(F)cc12)C(C)C,5-Fluoro-ALIPT,tryptamine
369
+ NCCc1c[nH]c2ccc(OC3CCCC3)cc12,5-Cyclopentyloxy-T,tryptamine
370
+ COc1ccc(OC)c(CCN(C)CCc2c[nH]c3ccc(OC)cc23)c1,"N-(2,5-Dimethoxyphenylethyl)-5-MeO-NMT",tryptamine
371
+ Oc1cccc2[nH]cc(CCN3CCCCC3)c12,4-HO-pip-T,tryptamine
372
+ CN(C)CCc1c[nH]c2cccc(OCc3ccccc3)c12,4-Benzyloxy-DMT,tryptamine
373
+ CN(C)CCc1c[nH]c2cccc(OC(=O)SCc3ccccc3)c12,S-Benzyl O-{3-[2-(dimethylamino)ethyl]-1H-indol-4-yl} carbonothioate,tryptamine
374
+ COc1cc(OC)c2[nH]cc(CCNCc3ccccc3)c2c1,"5,7-MeO-T-NB",tryptamine
375
+ CNC(C)Cc1c[nH]c2ccc(OCc3ccccc3)cc12,5-Benzyloxy-alpha-methyl-NMT,tryptamine
376
+ CC(C)(C)CCCCCCCOc1ccc2[nH]cc(CCN)c2c1,"5-(8,8-Dimethylnonyloxy)-T",tryptamine
377
+ CCCOc1ccc2[nH]cc(CCN(CC)CC)c2c1,5-PrO-DET,tryptamine
378
+ COc1ccc2[nH]cc(CCN(C)CCCc3cc(OC)c(OC)c(OC)c3)c2c1,"N-(3,4,5-Trimethoxyphenylpropyl)-5-MeO-NMT",tryptamine
379
+ c1ccc2c(CCN3CCN(CCc4c[nH]c5ccccc45)CC3)c[nH]c2c1,"3,3'-[Piperazine-1,4-diyldi(ethane-2,1-diyl)]di(1H-indole)",tryptamine
380
+ CC(C)N(CCc1c[nH]c2cccc(OCc3ccccc3)c12)C(C)C,4-Benzyloxy-DIPT,tryptamine
381
+ CC(C)N(CCc1c[nH]c2ccc(F)cc12)C1CCC1,5-Fluoro-IPCBT,tryptamine
382
+ CCOc1ccc(CNCCc2c[nH]c3ccccc23)cc1,T-NB4OEt,tryptamine
383
+ O=C(O)CCNCCc1c[nH]c2cc([N+](=O)[O-])ccc12,6-Nitro-N-(2-carboxyethyl)tryptamine,tryptamine
384
+ CN1CCN(CCc2c[nH]c3cccc(O)c23)CC1,4'-Methyl-4-HO-piperazine-T,tryptamine
385
+ CN(CCC#N)CCc1c[nH]c2ccccc12,N-Cyanoethyl-NMT,tryptamine
386
+ COc1cc(F)c2[nH]cc(CCN(C)C)c2c1,7-Fluoro-5-MeO-DMT,tryptamine
387
+ CN(CCc1c[nH]c2ccc(F)cc12)C1CCC1,5-Fluoro-MCBT,tryptamine
388
+ CNCCc1c[nH]c2c(OC)cccc12,7-MeO-NMT,tryptamine
389
+ Cc1c(O)c(O)cc2c(CCN)c[nH]c12,"7-Methyl-5,6-HO-T",tryptamine
390
+ Oc1ccc(CNCCc2c[nH]c3ccccc23)cc1,T-NB4OH,tryptamine
391
+ COc1c(Br)cc(Br)cc1CNCCc1c[nH]c2ccccc12,T-NBOMe35Br,tryptamine
392
+ CCn1cc(CCN(C)C)c2c(OCc3ccccc3)cc(F)cc21,1-Ethyl-6-fluoro-4-benzyloxy-DMT,tryptamine
393
+ CN(C)CCc1c[nH]c2cccc(OC(=O)c3cccc(C(=O)Oc4cccc5[nH]cc(CCN(C)C)c45)c3)c12,"Bis{3-[2-(dimethylamino)ethyl]-1H-indol-4-yl} benzene-1,3-dicarboxylate",tryptamine
394
+ CCN(CC)C(=O)CCN(C)CCc1c[nH]c2ccc(OC)cc12,"N,N-Diethyl-N3-[2-(5-methoxy-1H-indol-3-yl)ethyl]-N3-methyl-beta-alaninamide",tryptamine
395
+ COc1ccc(CNCCc2c[nH]c3c(Br)cc(OC)cc23)cc1,7-Bromo-5-MeO-T-NB4OMe,tryptamine
396
+ CCCN(C)CCc1c[nH]c2ccc(F)cc12,5-Fluoro-MPT,tryptamine
397
+ CN(CCc1c[nH]c2cc3c(cc12)OCO3)Cc1ccccc1,"5,6-MDO-NMT-NB",tryptamine
398
+ Cc1c(OC(=O)CCC(=O)O)ccc2[nH]cc(CCN(C)C)c12,Psilocin-4-methyl-5-succinate,tryptamine
399
+ COc1ccc2[nH]cc(CC(C)N)c2c1Br,4-Bromo-5-MeO-AMT,tryptamine
400
+ CN(C)CC(=O)c1c[nH]c2cc(F)ccc12,beta-Oxo-6-fluoro-DMT,tryptamine
401
+ COc1ccc2[nH]cc(C(O)CN(C)C)c2c1,beta-HO-5-MeO-DMT,tryptamine
402
+ COc1cccc2c(CCN)c[nH]c12,7-MeO-T,tryptamine
403
+ COc1cc(I)c2[nH]cc(CCN(C)C)c2c1,7-Iodo-5-MeO-DMT,tryptamine
404
+ C[C@@H]1CC[C@H](C)N1CCc1c[nH]c2ccccc12,"(R,S)-Dimethyl-pyr-T",tryptamine
405
+ COc1ccc(Sn2cc(CCN(C)C)c3c(OC)cccc32)cc1,1-(4-Methoxyphenylthio)-4-MeO-DMT,tryptamine
406
+ CCCN(CCc1c[nH]c2c(F)cccc12)C1CCC1,7-Fluoro-PCBT,tryptamine
407
+ CC(=O)NCCc1c[nH]c2cc(F)cc(NC(C)=O)c12,6-Fluoro-4-acetamido-N-acetyltryptamine,tryptamine
408
+ CCCCS(=O)(=O)n1cc(CCN(C)C)c2c(OC)cccc21,1-Butylsulfonyl-4-MeO-DMT,tryptamine
409
+ CCCN(CCC)CCc1c[nH]c2ccc(OC(C)=O)cc12,5-AcO-DPT,tryptamine
410
+ CN(C)CCc1cn(C)c2ccccc12,1-TMT,tryptamine
411
+ CCN(CCc1c[nH]c2cc(F)c(F)cc12)C(C)C,"5,6-Difluoro-EIPT",tryptamine
412
+ CN(C)CC(=O)c1c[nH]c2c(F)cc(F)cc12,"beta-Oxo-5,7-difluoro-DMT",tryptamine
413
+ CN(C)CCc1cn(C)c2cc(F)cc(OCc3ccccc3)c12,1-Methyl-6-fluoro-4-benzyloxy-DMT,tryptamine
414
+ CCCc1[nH]c2ccc(OC)cc2c1CCN(C)C,2-Propyl-5-MeO-DMT,tryptamine
415
+ CC(=O)Oc2cccc1[nH]cc(CCN(C)C)c12,4-AcO-DMT,tryptamine
src/src/data/sample_smiles.csv ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ smiles,name,category
2
+ CCO,Ethanol,Alcohol
3
+ CC(=O)O,Acetic acid,Carboxylic acid
4
+ c1ccccc1,Benzene,Aromatic hydrocarbon
5
+ CC(C)O,Isopropanol,Alcohol
6
+ c1ccc(cc1)O,Phenol,Aromatic alcohol
7
+ CC(=O)OC1=CC=CC=C1C(=O)O,Aspirin,Carboxylic acid ester
8
+ CN1C=NC2=C1C(=O)N(C(=O)N2C)C,Caffeine,Alkaloid
9
+ CCN(CC)CC,Triethylamine,Amine
10
+ c1ccc2c(c1)cccn2,Quinoline,Aromatic heterocycle
11
+ c1ccc(cc1)N,Aniline,Aromatic amine
12
+ O=P(O)(O)OP(=O)(O)OP(=O)(O)OC[C@H]3O[C@@H](n2cnc1c(ncnc12)N)[C@H](O)[C@@H]3O,ATP,Nucleotide
13
+ CN(C)CCC1=CNC2=C1C(=CC=C2)OP(=O)(O)O,Psilocybin,Tryptamine
src/src/main.js ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @fileoverview JSME (JavaScript Molecule Editor) integration with Gradio interface
3
+ * Handles bidirectional synchronization between JSME applet and Gradio textbox
4
+ * @author Manny Cortes ('[email protected]')
5
+ * @version 0.2.0
6
+ */
7
+
8
+ // ============================================================================
9
+ // GLOBAL VARIABLES
10
+ // ============================================================================
11
+
12
+ /** @type {Object|null} The JSME applet instance */
13
+ let jsmeApplet = null;
14
+
15
+ /** @type {string} Last known value of the textbox to prevent infinite loops */
16
+ let lastTextboxValue = "";
17
+
18
+ // ============================================================================
19
+ // CONSTANTS
20
+ // ============================================================================
21
+
22
+ /** @const {string} Default SMILES for initial molecule (ethanol) */
23
+ const DEFAULT_SMILES = "CCO";
24
+
25
+ /** @const {string} Container height for JSME applet */
26
+ const CONTAINER_HEIGHT = "450px";
27
+
28
+ /** @const {string} CSS selector for the Gradio SMILES input element */
29
+ const SMILES_INPUT_SELECTOR = "#smiles_input textarea, #smiles_input input";
30
+
31
+ /** @const {number} Delay for paste event handling (ms) */
32
+ const PASTE_DELAY = 50;
33
+
34
+ /** @const {number} Delay for initialization retry (ms) */
35
+ const INIT_RETRY_DELAY = 2000;
36
+
37
+ /** @const {string[]} Events to trigger for Gradio change detection */
38
+ const GRADIO_CHANGE_EVENTS = ["input", "change", "keyup"];
39
+
40
+ // ============================================================================
41
+ // CORE INITIALIZATION
42
+ // ============================================================================
43
+
44
+ /**
45
+ * Initializes the JSME applet after the library has been loaded
46
+ * Sets up the molecular editor with default options and callbacks
47
+ * @throws {Error} When JSME initialization fails
48
+ */
49
+ function initializeJSME() {
50
+ try {
51
+ console.log("Initializing JSME...");
52
+ // https://github.com/jsme-editor/jsme-editor.github.io
53
+ // https://jsme-editor.github.io/dist/api_javadoc/index.html
54
+ // http://wiki.jmol.org/index.php/Jmol_JavaScript_Object/JME/Options
55
+ jsmeApplet = new JSApplet.JSME(
56
+ "jsme_container",
57
+ getJsmeContainerWidthPx(),
58
+ CONTAINER_HEIGHT,
59
+ {
60
+ options:
61
+ "rButton,zoom,zoomgui,newLook,star,multipart,polarnitro,NOexportInChI,NOexportInChIkey,NOsearchInChIkey,NOexportSVG,NOpaste",
62
+ }
63
+ );
64
+
65
+ jsmeApplet.setCallBack("AfterStructureModified", handleJSMEStructureChange);
66
+ jsmeApplet.setMenuScale(getJsmeGuiScale());
67
+ jsmeApplet.setUserInterfaceBackgroundColor("#adadad");
68
+
69
+ // Set initial molecule and sync state
70
+ jsmeApplet.readGenericMolecularInput(DEFAULT_SMILES);
71
+ lastTextboxValue = DEFAULT_SMILES;
72
+
73
+ setupTextboxEventListeners();
74
+ window.addEventListener("resize", handleResize);
75
+
76
+ console.log("JSME initialized successfully");
77
+ } catch (error) {
78
+ console.error("Error initializing JSME:", error);
79
+ throw error;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Handles structure changes in the JSME applet
85
+ * Converts the structure to SMILES and updates the Gradio textbox
86
+ * @param {Event} event - The JSME structure modification event
87
+ */
88
+ function handleJSMEStructureChange(event) {
89
+ try {
90
+ const smiles = jsmeApplet.smiles();
91
+ updateGradioTextbox(smiles);
92
+ } catch (error) {
93
+ console.error("Error getting SMILES from JSME:", error);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Calculates the appropriate GUI scale for the JSME applet based on container width
99
+ * Uses breakpoints to determine optimal scaling for different screen sizes
100
+ * @returns {number} The scale factor for the JSME GUI (0.88 to 2.0)
101
+ */
102
+ function getJsmeGuiScale() {
103
+ const width = getJsmeContainerWidthNumber();
104
+ let menuScale;
105
+ if (width > 460) {
106
+ menuScale = 1.3;
107
+ } else if (width > 420) {
108
+ menuScale = 1.1;
109
+ } else if (width > 370) {
110
+ menuScale = 1.05;
111
+ } else if (width > 300) {
112
+ menuScale = 0.88;
113
+ } else {
114
+ menuScale = 2;
115
+ }
116
+ return menuScale;
117
+ }
118
+
119
+ /**
120
+ * Gets the JSME container width as a CSS-compatible string value
121
+ * Returns either a pixel value or percentage based on available width
122
+ * @returns {string} Width as "100%" or "{width}px" format
123
+ */
124
+ function getJsmeContainerWidthPx() {
125
+ const parentWidth = getJsmeContainerWidthNumber();
126
+ if (parentWidth == null || parentWidth <= 0) {
127
+ return "100%";
128
+ }
129
+ return `${parentWidth}px`;
130
+ }
131
+
132
+ /**
133
+ * Gets the numeric width of the JSME container's parent element
134
+ * Used for responsive scaling calculations
135
+ * @returns {number|null} Width in pixels, or null if container not found
136
+ */
137
+ function getJsmeContainerWidthNumber() {
138
+ const container = document.getElementById("jsme_container");
139
+ if (!container) {
140
+ return null;
141
+ }
142
+ return container.parentNode.offsetWidth;
143
+ }
144
+
145
+ // ============================================================================
146
+ // GRADIO INTEGRATION
147
+ // ============================================================================
148
+
149
+ /**
150
+ * Updates the Gradio textbox with a SMILES string
151
+ * Triggers appropriate events to ensure Gradio detects the change
152
+ * @param {string} smiles - The SMILES string to set in the textbox
153
+ */
154
+ function updateGradioTextbox(smiles) {
155
+ try {
156
+ const textbox = document.querySelector(SMILES_INPUT_SELECTOR);
157
+
158
+ if (!textbox || textbox.value === smiles) {
159
+ return;
160
+ }
161
+
162
+ textbox.value = smiles;
163
+ lastTextboxValue = smiles;
164
+
165
+ // Trigger events to ensure Gradio detects the change
166
+ GRADIO_CHANGE_EVENTS.forEach((eventType) => {
167
+ const event = new Event(eventType, {
168
+ bubbles: true,
169
+ cancelable: true,
170
+ });
171
+ textbox.dispatchEvent(event);
172
+ });
173
+ } catch (error) {
174
+ console.error("Error updating Gradio textbox:", error);
175
+ }
176
+ }
177
+
178
+ // ============================================================================
179
+ // JSME UPDATE FUNCTIONS
180
+ // ============================================================================
181
+
182
+ /**
183
+ * Updates the JSME applet with a SMILES string from the textbox
184
+ * @param {string} smiles - The SMILES string to display in JSME
185
+ */
186
+ function updateJSMEFromTextbox(smiles) {
187
+ if (!jsmeApplet) {
188
+ return;
189
+ }
190
+
191
+ try {
192
+ if (smiles && smiles.trim() !== "") {
193
+ jsmeApplet.readGenericMolecularInput(smiles.trim());
194
+ } else {
195
+ jsmeApplet.reset();
196
+ }
197
+ lastTextboxValue = smiles;
198
+ } catch (error) {
199
+ console.error("Error updating JSME from textbox:", error);
200
+ }
201
+ }
202
+
203
+ // ============================================================================
204
+ // UI MONITORING
205
+ // ============================================================================
206
+
207
+ /**
208
+ * Finds the textbox element and sets up event listeners
209
+ */
210
+ function setupTextboxEventListeners() {
211
+ const textbox = document.querySelector(SMILES_INPUT_SELECTOR);
212
+ if (!textbox) {
213
+ return;
214
+ }
215
+
216
+ textbox.addEventListener("input", handleTextboxChange);
217
+ textbox.addEventListener("change", handleTextboxChange);
218
+ textbox.addEventListener("paste", handleTextboxPaste);
219
+ textbox.addEventListener("keyup", handleTextboxChange);
220
+ }
221
+
222
+ /**
223
+ * Handles textbox change events
224
+ * @param {Event} event - The change event
225
+ */
226
+ function handleTextboxChange(event) {
227
+ if (event.target.value !== lastTextboxValue) {
228
+ updateJSMEFromTextbox(event.target.value);
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Handles textbox paste events with a delay to ensure content is available
234
+ * @param {Event} event - The paste event
235
+ */
236
+ function handleTextboxPaste(event) {
237
+ setTimeout(() => {
238
+ updateJSMEFromTextbox(event.target.value);
239
+ }, PASTE_DELAY);
240
+ }
241
+
242
+ /**
243
+ * Handles window resize events and updates JSME applet width
244
+ */
245
+ function handleResize() {
246
+ if (!jsmeApplet) {
247
+ return;
248
+ }
249
+
250
+ try {
251
+ jsmeApplet.setMenuScale(getJsmeGuiScale());
252
+ jsmeApplet.setWidth(getJsmeContainerWidthPx());
253
+ } catch (error) {
254
+ console.error("Error resizing JSME applet:", error);
255
+ }
256
+ }
257
+
258
+ // ============================================================================
259
+ // PUBLIC API
260
+ // ============================================================================
261
+
262
+ /**
263
+ * Sets a SMILES string in both JSME and Gradio textbox
264
+ * @param {string} smiles - The SMILES string to set
265
+ * @returns {string} The SMILES string that was set
266
+ * @public
267
+ */
268
+ window.setJSMESmiles = function (smiles) {
269
+ if (jsmeApplet) {
270
+ updateJSMEFromTextbox(smiles);
271
+ }
272
+
273
+ updateGradioTextbox(smiles);
274
+ return smiles;
275
+ };
276
+
277
+ /**
278
+ * Clears both JSME and Gradio textbox
279
+ * @returns {Array} Array containing cleared state for Gradio components
280
+ * @public
281
+ */
282
+ window.clearJSME = function () {
283
+ if (jsmeApplet) {
284
+ jsmeApplet.reset();
285
+ }
286
+
287
+ updateGradioTextbox("");
288
+ return ["", [], [], "Cleared - Draw a new molecule or enter SMILES"];
289
+ };
290
+
291
+ // ============================================================================
292
+ // INITIALIZATION LOGIC
293
+ // ============================================================================
294
+
295
+ /**
296
+ * Checks if JSME library is loaded and initializes JSME applet
297
+ * Retries until the library becomes available
298
+ */
299
+ function initializeWhenReady() {
300
+ if (typeof JSApplet !== "undefined" && JSApplet.JSME) {
301
+ console.log("JSME library loaded, initializing...");
302
+ initializeJSME();
303
+ } else {
304
+ console.log("JSME library not ready, retrying...");
305
+ setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Starts the initialization process based on document ready state
311
+ */
312
+ function startInitialization() {
313
+ if (document.readyState === "loading") {
314
+ document.addEventListener("DOMContentLoaded", () => {
315
+ setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
316
+ });
317
+ } else {
318
+ setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
319
+ }
320
+ }
321
+
322
+ startInitialization();
src/src/main.min.js ADDED
@@ -0,0 +1 @@
 
 
1
+ function initializeJSME(){try{(jsmeApplet=new JSApplet.JSME("jsme_container",getJsmeContainerWidthPx(),CONTAINER_HEIGHT,{options:"rButton,zoom,zoomgui,newLook,star,multipart,polarnitro,NOexportInChI,NOexportInChIkey,NOsearchInChIkey,NOexportSVG,NOpaste"})).setCallBack("AfterStructureModified",handleJSMEStructureChange),jsmeApplet.setMenuScale(getJsmeGuiScale()),jsmeApplet.setUserInterfaceBackgroundColor("#adadad"),jsmeApplet.readGenericMolecularInput(DEFAULT_SMILES),lastTextboxValue=DEFAULT_SMILES,setupTextboxEventListeners(),window.addEventListener("resize",handleResize)}catch(e){throw e}}function handleJSMEStructureChange(){try{updateGradioTextbox(jsmeApplet.smiles())}catch(e){}}function getJsmeGuiScale(){const e=getJsmeContainerWidthNumber();return e>460?1.3:e>420?1.1:e>370?1.05:e>300?.88:2}function getJsmeContainerWidthPx(){const e=getJsmeContainerWidthNumber();return null==e||e<=0?"100%":`${e}px`}function getJsmeContainerWidthNumber(){const e=document.getElementById("jsme_container");return e?e.parentNode.offsetWidth:null}function updateGradioTextbox(e){try{const t=document.querySelector(SMILES_INPUT_SELECTOR);if(!t||t.value===e)return;t.value=e,lastTextboxValue=e,GRADIO_CHANGE_EVENTS.forEach(e=>{const n=new Event(e,{bubbles:!0,cancelable:!0});t.dispatchEvent(n)})}catch(e){}}function updateJSMEFromTextbox(e){if(jsmeApplet)try{e&&""!==e.trim()?jsmeApplet.readGenericMolecularInput(e.trim()):jsmeApplet.reset(),lastTextboxValue=e}catch(e){}}function setupTextboxEventListeners(){const e=document.querySelector(SMILES_INPUT_SELECTOR);e&&(e.addEventListener("input",handleTextboxChange),e.addEventListener("change",handleTextboxChange),e.addEventListener("paste",handleTextboxPaste),e.addEventListener("keyup",handleTextboxChange))}function handleTextboxChange(e){e.target.value!==lastTextboxValue&&updateJSMEFromTextbox(e.target.value)}function handleTextboxPaste(e){setTimeout(()=>{updateJSMEFromTextbox(e.target.value)},PASTE_DELAY)}function handleResize(){if(jsmeApplet)try{jsmeApplet.setMenuScale(getJsmeGuiScale()),jsmeApplet.setWidth(getJsmeContainerWidthPx())}catch(e){}}function initializeWhenReady(){"undefined"!=typeof JSApplet&&JSApplet.JSME?initializeJSME():setTimeout(initializeWhenReady,INIT_RETRY_DELAY)}function startInitialization(){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{setTimeout(initializeWhenReady,INIT_RETRY_DELAY)}):setTimeout(initializeWhenReady,INIT_RETRY_DELAY)}let jsmeApplet=null,lastTextboxValue="";const DEFAULT_SMILES="CCO",CONTAINER_HEIGHT="450px",SMILES_INPUT_SELECTOR="#smiles_input textarea, #smiles_input input",PASTE_DELAY=50,INIT_RETRY_DELAY=2e3,GRADIO_CHANGE_EVENTS=["input","change","keyup"];window.setJSMESmiles=function(e){return jsmeApplet&&updateJSMEFromTextbox(e),updateGradioTextbox(e),e},window.clearJSME=function(){return jsmeApplet&&jsmeApplet.reset(),updateGradioTextbox(""),["",[],[],"Cleared - Draw a new molecule or enter SMILES"]},startInitialization();
src/src/service.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import os
3
+ from typing import TypedDict
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import redis
8
+ from chem_mrl.molecular_fingerprinter import MorganFingerprinter
9
+ from dotenv import load_dotenv
10
+ from redis.commands.search.field import TextField, VectorField
11
+ from redis.commands.search.indexDefinition import IndexDefinition, IndexType
12
+ from redis.commands.search.query import Query
13
+ from sentence_transformers import SentenceTransformer
14
+
15
+ from constants import (
16
+ EMBEDDING_DIMENSION,
17
+ HNSW_K,
18
+ HNSW_PARAMETERS,
19
+ MODEL_NAME,
20
+ SUPPORTED_EMBEDDING_DIMENSIONS,
21
+ )
22
+ from data import DATASET_SMILES, ISOMER_DESIGN_SUBSET
23
+
24
+
25
+ def setup_logger(clear_handler=False):
26
+ if clear_handler:
27
+ for handler in logging.root.handlers[:]:
28
+ logging.root.removeHandler(handler) # issue with sentence-transformer's logging handler
29
+ logging.basicConfig(format="%(asctime)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO)
30
+ logger = logging.getLogger(__name__)
31
+ return logger
32
+
33
+
34
+ load_dotenv("../.env")
35
+ logger = setup_logger(clear_handler=True)
36
+
37
+
38
+ class SimilarMolecule(TypedDict):
39
+ smiles: str
40
+ name: str
41
+ category: str
42
+ score: float
43
+
44
+
45
+ class MolecularEmbeddingService:
46
+ def __init__(self):
47
+ self.model_name = MODEL_NAME
48
+ self.index_name = "molecule_embeddings"
49
+ self.model_embed_dim = EMBEDDING_DIMENSION
50
+
51
+ self.model = self._initialize_model()
52
+ self.redis_client = self._initialize_redis()
53
+ self._initialize_datastore()
54
+
55
+ def _initialize_model(self):
56
+ """Initialize the Hugging Face transformers model"""
57
+ try:
58
+ model = SentenceTransformer(self.model_name) # type: ignore
59
+ model.eval()
60
+ return model
61
+ except Exception as e:
62
+ logger.error(f"Failed to load model: {e}")
63
+ raise
64
+
65
+ def _initialize_redis(self):
66
+ """Initialize Redis connection"""
67
+ try:
68
+ redis_host = os.getenv("REDIS_HOST", "localhost")
69
+ redis_port = int(os.getenv("REDIS_PORT", 6379))
70
+ redis_password = os.getenv("REDIS_PASSWORD", None)
71
+ logger.info(
72
+ f"Connecting to Redis at {redis_host}:{redis_port} with password: {'***' if redis_password else 'None'}"
73
+ )
74
+ redis_client = redis.Redis(
75
+ host=redis_host,
76
+ port=redis_port,
77
+ password=redis_password,
78
+ decode_responses=True,
79
+ )
80
+ redis_client.ping()
81
+ return redis_client
82
+ except Exception as e:
83
+ logger.error(f"Failed to connect to Redis: {e}")
84
+ raise
85
+
86
+ def _initialize_datastore(self):
87
+ self.__create_hnsw_index()
88
+ self.__populate_sample_data(DATASET_SMILES)
89
+ self.__populate_sample_data(ISOMER_DESIGN_SUBSET)
90
+
91
+ def __create_hnsw_index(self):
92
+ """Create HNSW index for molecular embeddings"""
93
+ try:
94
+ self.redis_client.ft(self.index_name).info()
95
+ logger.info(f"Index {self.index_name} already exists")
96
+ return
97
+ except redis.exceptions.ResponseError:
98
+ pass
99
+
100
+ try:
101
+ schema: list[TextField | VectorField] = [
102
+ VectorField(
103
+ self.embedding_field_name(dim),
104
+ "HNSW",
105
+ {
106
+ **HNSW_PARAMETERS,
107
+ "DIM": dim,
108
+ },
109
+ )
110
+ for dim in SUPPORTED_EMBEDDING_DIMENSIONS
111
+ ]
112
+ schema.insert(0, TextField("smiles"))
113
+
114
+ self.redis_client.ft(self.index_name).create_index(
115
+ schema,
116
+ definition=IndexDefinition(prefix=[self.molecule_index_prefix("")], index_type=IndexType.HASH),
117
+ )
118
+
119
+ logger.info(f"Created HNSW index: {self.index_name}")
120
+
121
+ except Exception as e:
122
+ logger.error(f"Failed to create HNSW index: {e}")
123
+ raise
124
+
125
+ def __populate_sample_data(self, df: pd.DataFrame):
126
+ """Populate Redis with sample molecular data"""
127
+ logger.info("Populating Redis with sample molecular data...")
128
+ for _, row in df.iterrows():
129
+ try:
130
+ key = self.molecule_index_prefix(row["smiles"])
131
+ if self.redis_client.exists(key):
132
+ continue
133
+
134
+ mapping: dict[str, bytes | str] = {
135
+ self.embedding_field_name(embed_dim): self.get_molecular_embedding(
136
+ row["smiles"], embed_dim
137
+ ).tobytes()
138
+ for embed_dim in SUPPORTED_EMBEDDING_DIMENSIONS
139
+ }
140
+ mapping = {**mapping, **row.to_dict()}
141
+
142
+ self.redis_client.hset(
143
+ key,
144
+ mapping=mapping,
145
+ )
146
+
147
+ except Exception as e:
148
+ logger.error(f"Failed to process molecule {row}: {e}")
149
+ continue
150
+
151
+ logger.info(f"Populated {len(df)} sample molecules")
152
+
153
+ def get_molecular_embedding(self, smiles: str, embed_dim: int) -> np.ndarray:
154
+ """Generate molecular embedding using ChemMRL"""
155
+ try:
156
+ if embed_dim <= 0:
157
+ raise ValueError("embed_dim must be positive")
158
+
159
+ # Preprocess smiles similarly as training data for optimal performance
160
+ smiles = MorganFingerprinter.canonicalize_smiles(smiles) or smiles
161
+
162
+ embedding: np.ndarray = self.model.encode(
163
+ [smiles],
164
+ show_progress_bar=False,
165
+ convert_to_numpy=True,
166
+ )[0]
167
+
168
+ return self._truncate_and_normalize_embedding(embedding, embed_dim)
169
+
170
+ except Exception as e:
171
+ logger.error(f"Failed to generate embedding for {smiles}: {e}")
172
+ raise
173
+
174
+ def _truncate_and_normalize_embedding(self, embedding: np.ndarray, embed_dim: int) -> np.ndarray:
175
+ """Truncate and normalize embedding"""
176
+ if embed_dim < len(embedding):
177
+ embedding = embedding[:embed_dim]
178
+ norms = np.linalg.norm(embedding, ord=2, keepdims=True)
179
+ return embedding / np.where(norms == 0, 1, norms)
180
+
181
+ def find_similar_molecules(
182
+ self, query_embedding: np.ndarray, embed_dim: int, k: int = HNSW_K
183
+ ) -> list[SimilarMolecule]:
184
+ """Find k most similar molecules using HNSW"""
185
+ try:
186
+ query_vector = query_embedding.astype(np.float32).tobytes()
187
+ query = (
188
+ Query(f"*=>[KNN {k} @{self.embedding_field_name(embed_dim)} $vec AS score]")
189
+ .sort_by("score")
190
+ .return_fields("smiles", "name", "category", "score")
191
+ .dialect(2)
192
+ )
193
+
194
+ results = self.redis_client.ft(self.index_name).search(query, query_params={"vec": query_vector})
195
+
196
+ neighbors: list[SimilarMolecule] = [
197
+ {"smiles": doc.smiles, "name": doc.name, "category": doc.category, "score": float(doc.score)}
198
+ for doc in results.docs
199
+ ]
200
+
201
+ return neighbors
202
+
203
+ except Exception as e:
204
+ logger.error(f"Failed to find similar molecules: {e}")
205
+ return []
206
+
207
+ @staticmethod
208
+ def embedding_field_name(dim: int) -> str:
209
+ return f"embedding_{dim}"
210
+
211
+ @staticmethod
212
+ def molecule_index_prefix(smiles: str) -> str:
213
+ return f"mol:{smiles}"