chemstore 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chemstore-0.1.0/PKG-INFO +434 -0
- chemstore-0.1.0/README.md +410 -0
- chemstore-0.1.0/pyproject.toml +53 -0
- chemstore-0.1.0/pyproject.toml.orig +54 -0
- chemstore-0.1.0/src/chemstore/__init__.py +24 -0
- chemstore-0.1.0/src/chemstore/api/__init__.py +0 -0
- chemstore-0.1.0/src/chemstore/api/dependencies.py +17 -0
- chemstore-0.1.0/src/chemstore/api/main.py +185 -0
- chemstore-0.1.0/src/chemstore/api/models.py +31 -0
- chemstore-0.1.0/src/chemstore/cli/main.py +138 -0
- chemstore-0.1.0/src/chemstore/data/reaction_templates.json +67 -0
- chemstore-0.1.0/src/chemstore/domain/Equation.py +8 -0
- chemstore-0.1.0/src/chemstore/domain/__init__.py +0 -0
- chemstore-0.1.0/src/chemstore/domain/compound.py +29 -0
- chemstore-0.1.0/src/chemstore/domain/equation.py +135 -0
- chemstore-0.1.0/src/chemstore/domain/reaction.py +85 -0
- chemstore-0.1.0/src/chemstore/domain/repository.py +34 -0
- chemstore-0.1.0/src/chemstore/infrastructure/repository_impl.py +45 -0
- chemstore-0.1.0/src/chemstore/infrastructure/smarts_loader.py +103 -0
- chemstore-0.1.0/src/chemstore/infrastructure/storage/__init__.py +0 -0
- chemstore-0.1.0/src/chemstore/infrastructure/storage/append_log.py +49 -0
- chemstore-0.1.0/src/chemstore/infrastructure/storage/engine.py +69 -0
- chemstore-0.1.0/src/chemstore/infrastructure/template_updater.py +345 -0
- chemstore-0.1.0/src/chemstore/usecases/__init__.py +0 -0
- chemstore-0.1.0/src/chemstore/usecases/balance_equation.py +17 -0
- chemstore-0.1.0/src/chemstore/usecases/calculate_mass.py +25 -0
- chemstore-0.1.0/src/chemstore/usecases/predict_reaction.py +49 -0
chemstore-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chemstore
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: High-performance cheminformatics calculation and reaction prediction engine with embedded Bitcask key-value storage
|
|
5
|
+
Keywords: chemistry,cheminformatics,rdkit,smiles,smarts,reaction-prediction,equation-balancer,bitcask
|
|
6
|
+
Author: mark
|
|
7
|
+
Author-email: mark <pythondev677@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: fastapi>=0.141.1
|
|
14
|
+
Requires-Dist: pydantic>=2.13.5
|
|
15
|
+
Requires-Dist: rdkit>=2026.3.6
|
|
16
|
+
Requires-Dist: requests>=2.34.2
|
|
17
|
+
Requires-Dist: typer[all]>=0.27.2
|
|
18
|
+
Requires-Dist: uvicorn>=0.53.0
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Project-URL: Homepage, https://github.com/munenevictor577-blip/chemstore
|
|
21
|
+
Project-URL: Repository, https://github.com/munenevictor577-blip/chemstore
|
|
22
|
+
Project-URL: Issues, https://github.com/munenevictor577-blip/chemstore/issues
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# ChemStore
|
|
26
|
+
|
|
27
|
+
ChemStore is a fast, domain-driven chemical informatics toolkit and command-line application equipped with an embedded log-structured (Bitcask-style) storage engine. It provides exact molar mass calculations, stoichiometric chemical equation balancing via linear algebra, and automated organic reaction product prediction.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- **Molar Mass & Formula Calculation**:
|
|
34
|
+
- Validates and parses SMILES strings into molecular structures using RDKit.
|
|
35
|
+
- Computes exact molecular weight and Hill-system molecular formulas.
|
|
36
|
+
- **Stoichiometric Chemical Equation Balancing**:
|
|
37
|
+
- Supports reaction equations with `=` or `>>` operators.
|
|
38
|
+
- Automatically parses and expands nested polyatomic ion brackets (e.g., `Mg(OH)2` $\rightarrow$ `MgOHOH`).
|
|
39
|
+
- Solves the null space using exact rational arithmetic (`fractions.Fraction`) via Gaussian elimination, eliminating floating-point rounding errors.
|
|
40
|
+
- Derives the lowest positive whole-integer stoichiometric coefficients using Least Common Multiple (LCM) scaling.
|
|
41
|
+
- **Intelligent Organic Reaction Product Prediction**:
|
|
42
|
+
- Curated library of standard organic reaction templates (Amide coupling, Fischer esterification, Suzuki coupling, Diels-Alder, Williamson-style ether synthesis, Imine formation, Saponification, and Alkene hydrogenation).
|
|
43
|
+
- **Zero-Configuration Automatic Reaction Detection**: Intelligently identifies compatible reactions from input reactant SMILES without requiring the user to specify the reaction type.
|
|
44
|
+
- **Order-Independent Matching**: Permutes reactants to match template reaction centers regardless of the order provided (e.g., alcohol + acid vs. acid + alcohol).
|
|
45
|
+
- Custom Reaction SMARTS support for advanced user-defined reactions.
|
|
46
|
+
- **Embedded Bitcask Key-Value Cache Engine**:
|
|
47
|
+
- High-performance append-only binary log storage format with low overhead.
|
|
48
|
+
- In-memory hash indexing mapping compound keys to disk byte offsets for $O(1)$ random lookups.
|
|
49
|
+
- Automatic index reconstruction on startup from binary headers.
|
|
50
|
+
- Online compaction to prune obsolete records and reclaim disk space.
|
|
51
|
+
- **Clean Architecture / Domain-Driven Design (DDD)**:
|
|
52
|
+
- Clean separation into `domain`, `infrastructure`, `usecases`, and `cli` layers for high maintainability, modularity, and testability.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Architecture
|
|
57
|
+
|
|
58
|
+
The project adheres to Clean Architecture principles:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
src/chemstore/
|
|
62
|
+
├── domain/ # Enterprise business rules & entities (pure domain)
|
|
63
|
+
│ ├── compound.py # Compound entity (SMILES parsing, molecular mass & formula)
|
|
64
|
+
│ ├── Equation.py # Equation model, matrix composition, & rational Gaussian null-space solver
|
|
65
|
+
│ ├── reaction.py # ReactionPredictor (isolated domain logic)
|
|
66
|
+
│ └── repository.py # Abstract ChemicalRepository interface
|
|
67
|
+
├── data/
|
|
68
|
+
│ └── reaction_templates.json # Externalized JSON reaction SMARTS definitions
|
|
69
|
+
├── api/ # FastAPI HTTP REST API service
|
|
70
|
+
│ ├── main.py # Endpoint declarations & error handling
|
|
71
|
+
│ ├── models.py # Pydantic request & response schemas
|
|
72
|
+
│ └── dependencies.py # Use case dependency injection
|
|
73
|
+
├── infrastructure/ # External systems & persistence mechanisms
|
|
74
|
+
│ ├── smarts_loader.py # On-demand reaction SMARTS template loader
|
|
75
|
+
│ ├── storage/
|
|
76
|
+
│ │ ├── append_log.py # Low-level binary append-only disk logger
|
|
77
|
+
│ │ └── engine.py # ChemStoreEngine (Bitcask key-value store with compaction)
|
|
78
|
+
│ └── repository_impl.py # KVChemicalRepository implementation
|
|
79
|
+
├── usecases/ # Application use cases orchestrating domain models & cache
|
|
80
|
+
│ ├── calculate_mass.py # CalculateMassUseCase (cache-aside mass lookup)
|
|
81
|
+
│ ├── balance_equation.py # BalanceEquationUseCase (cache-aside equation balancing)
|
|
82
|
+
│ └── predict_reaction.py # PredictReactionUseCase (auto-detection & cached product prediction)
|
|
83
|
+
└── cli/
|
|
84
|
+
└── main.py # CLI entry point (argparse)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Storage Engine Architecture (Bitcask Log)
|
|
88
|
+
|
|
89
|
+
Every record is stored sequentially in an append-only binary file using an 8-byte little-endian header:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
+-------------------+---------------------+------------------+--------------------+
|
|
93
|
+
| Key Size (4 bytes)| Value Size (4 bytes)| Key UTF-8 Bytes | Value UTF-8 Bytes |
|
|
94
|
+
+-------------------+---------------------+------------------+--------------------+
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
1. **Write Path (`put`)**: Appends record to the end of the log file, returns the file offset, and updates the in-memory hash table: `index[key] = offset`.
|
|
98
|
+
2. **Read Path (`get`)**: Performs an $O(1)$ in-memory index lookup to get the byte offset, jumps (`seek`) directly to that offset in the log, unpacks the header, and reads the value.
|
|
99
|
+
3. **Recovery (`_build_index`)**: On startup, sequentially scans the log headers to reconstruct the in-memory hash index without loading payloads.
|
|
100
|
+
4. **Compaction (`compact`)**: Rewrites only the latest values of active keys to a fresh file, discarding dead and overwritten records.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
### Requirements
|
|
107
|
+
- Python `>= 3.12`
|
|
108
|
+
- `uv` (recommended) or `pip`
|
|
109
|
+
|
|
110
|
+
### Setup with `uv`
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git clone https://github.com/your-org/chemstore.git
|
|
114
|
+
cd chemstore
|
|
115
|
+
|
|
116
|
+
# Install dependencies and package in editable mode
|
|
117
|
+
uv pip install -e .
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Setup with `venv` & `pip`
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python3 -m venv .venv
|
|
124
|
+
source .venv/bin/activate
|
|
125
|
+
pip install -e .
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## CLI Usage
|
|
131
|
+
|
|
132
|
+
The package installs the `chemstore` command-line utility.
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
usage: chemstore [-h] {mass,balance,predict,admin} ...
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 1. Calculate Molar Mass (`mass`)
|
|
139
|
+
|
|
140
|
+
Calculates the molecular weight from a SMILES string:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Ethanol
|
|
144
|
+
chemstore mass "CCO"
|
|
145
|
+
# Output:
|
|
146
|
+
# 46.041864812
|
|
147
|
+
|
|
148
|
+
# Caffeine
|
|
149
|
+
chemstore mass "CN1C=NC2=C1C(=O)N(C(=O)N2C)C"
|
|
150
|
+
# Output:
|
|
151
|
+
# 194.08037556
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If cached, subsequent lookups retrieve the mass directly from the local Bitcask engine with near-zero latency.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 2. Balance Chemical Equations (`balance`)
|
|
159
|
+
|
|
160
|
+
Balances equations containing `=` or `>>`, automatically handling polyatomic groups and complex stoichiometries:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Simple combustion
|
|
164
|
+
chemstore balance "H2 + O2 = H2O"
|
|
165
|
+
# Output:
|
|
166
|
+
# 2H2 + O2 = 2H2O
|
|
167
|
+
|
|
168
|
+
# Alkane combustion
|
|
169
|
+
chemstore balance "C2H6 + O2 = CO2 + H2O"
|
|
170
|
+
# Output:
|
|
171
|
+
# 2C2H6 + 7O2 = 4CO2 + 6H2O
|
|
172
|
+
|
|
173
|
+
# Yield operator (>>)
|
|
174
|
+
chemstore balance "C2H6 + O2 >> CO2 + H2O"
|
|
175
|
+
# Output:
|
|
176
|
+
# 2C2H6 + 7O2 >> 4CO2 + 6H2O
|
|
177
|
+
|
|
178
|
+
# Polyatomic brackets
|
|
179
|
+
chemstore balance "Mg(OH)2 + HCl = MgCl2 + H2O"
|
|
180
|
+
# Output:
|
|
181
|
+
# Mg(OH)2 + 2HCl = MgCl2 + 2H2O
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### 3. Predict Reaction Products (`predict`)
|
|
187
|
+
|
|
188
|
+
#### Automatic Reaction Detection (No Reaction Name Needed)
|
|
189
|
+
Simply provide the reactant SMILES. ChemStore automatically identifies the matching reaction template and evaluates the products:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Esterification (acetic acid + ethanol)
|
|
193
|
+
chemstore predict "CC(=O)O" "CCO"
|
|
194
|
+
# Output:
|
|
195
|
+
# Reactants: CC(=O)O + CCO
|
|
196
|
+
# Reaction: esterification (auto-detected)
|
|
197
|
+
# Products: CCOC(C)=O
|
|
198
|
+
|
|
199
|
+
# Order-independent (ethanol first, acetic acid second)
|
|
200
|
+
chemstore predict "CCO" "CC(=O)O"
|
|
201
|
+
# Output:
|
|
202
|
+
# Reactants: CCO + CC(=O)O
|
|
203
|
+
# Reaction: esterification (auto-detected)
|
|
204
|
+
# Products: CCOC(C)=O
|
|
205
|
+
|
|
206
|
+
# Diels-Alder (butadiene + ethylene)
|
|
207
|
+
chemstore predict "C=CC=C" "C=C"
|
|
208
|
+
# Output:
|
|
209
|
+
# Reactants: C=CC=C + C=C
|
|
210
|
+
# Reaction: diels_alder (auto-detected)
|
|
211
|
+
# Products: C1=CCCCC1
|
|
212
|
+
|
|
213
|
+
# Alkene hydrogenation
|
|
214
|
+
chemstore predict "CC=CC"
|
|
215
|
+
# Output:
|
|
216
|
+
# Reactants: CC=CC
|
|
217
|
+
# Reaction: alkene_hydrogenation (auto-detected)
|
|
218
|
+
# Products: CCCC
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### List Available Reaction Templates (`--list` / `-l`)
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
chemstore predict --list
|
|
225
|
+
```
|
|
226
|
+
Output:
|
|
227
|
+
```
|
|
228
|
+
Available reactions:
|
|
229
|
+
amide_coupling : Amide coupling: carboxylic acid + amine -> amide
|
|
230
|
+
esterification : Fischer esterification: carboxylic acid + alcohol -> ester
|
|
231
|
+
suzuki_coupling : Suzuki coupling: aryl halide + boronic acid -> biaryl
|
|
232
|
+
diels_alder : Diels-Alder: diene + dienophile -> cyclohexene
|
|
233
|
+
ether_synthesis : Ether synthesis: alkyl halide + alcohol -> ether
|
|
234
|
+
imine_formation : Imine formation: carbonyl (aldehyde/ketone) + primary amine -> imine
|
|
235
|
+
saponification : Saponification / ester hydrolysis: ester -> acid + alcohol
|
|
236
|
+
alkene_hydrogenation : Alkene hydrogenation: alkene -> alkane
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Explicit Reaction Selection (`--reaction` / `-r`)
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
chemstore predict "CC(=O)O" "CCO" --reaction esterification
|
|
243
|
+
# Output:
|
|
244
|
+
# Reactants: CC(=O)O + CCO
|
|
245
|
+
# Reaction: esterification
|
|
246
|
+
# Products: CCOC(C)=O
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Custom SMARTS Rule (`--smarts` / `-s`)
|
|
250
|
+
|
|
251
|
+
You can provide custom RDKit reaction SMARTS to predict arbitrary transformations:
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
chemstore predict "CC(=O)O" "CN" --smarts "[O:2]=[C:1][OH:3].[N:4]>>[O:2]=[C:1][N:4]"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
### 4. Database Operations (`admin`)
|
|
260
|
+
|
|
261
|
+
Reclaim disk space by running log compaction on the cache database:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
chemstore admin --compact
|
|
265
|
+
# Output:
|
|
266
|
+
# Connecting to the embedded database...
|
|
267
|
+
# Compaction complete.
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Python API Usage
|
|
273
|
+
|
|
274
|
+
ChemStore can be integrated directly into Python scripts:
|
|
275
|
+
|
|
276
|
+
### Molecular Mass & Formulas
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
from chemstore.domain.compound import Compound
|
|
280
|
+
|
|
281
|
+
compound = Compound("CN1C=NC2=C1C(=O)N(C(=O)N2C)C")
|
|
282
|
+
print("Formula:", compound.formula) # C8H10N4O2
|
|
283
|
+
print("Molecular Weight:", compound.molecular_weight) # 194.0803...
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Chemical Equation Balancing
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
from chemstore.domain.Equation import Equation
|
|
290
|
+
|
|
291
|
+
eq = Equation("C2H6 + O2 = CO2 + H2O")
|
|
292
|
+
print(eq.balanced) # 2C2H6 + 7O2 = 4CO2 + 6H2O
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Reaction Prediction
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
from chemstore.domain.reaction import ReactionPredictor
|
|
299
|
+
|
|
300
|
+
# 1. Automatic reaction detection
|
|
301
|
+
matches = ReactionPredictor.auto_predict(["CC(=O)O", "CCO"])
|
|
302
|
+
for name, products in matches:
|
|
303
|
+
print(f"Reaction: {name}, Products: {products}")
|
|
304
|
+
# Reaction: esterification, Products: ['CCOC(C)=O']
|
|
305
|
+
|
|
306
|
+
# 2. Named reaction by factory
|
|
307
|
+
predictor = ReactionPredictor.from_name("diels_alder")
|
|
308
|
+
products = predictor.run(["C=CC=C", "C=C"])
|
|
309
|
+
print("Products:", products) # ['C1=CCCCC1']
|
|
310
|
+
|
|
311
|
+
# 3. Custom SMARTS rule
|
|
312
|
+
custom_predictor = ReactionPredictor("[C:1](=[O:2])[OH].[N:3]>>[C:1](=[O:2])[N:3]")
|
|
313
|
+
products = custom_predictor.run(["CC(=O)O", "CN"])
|
|
314
|
+
print("Products:", products) # ['CNC(C)=O']
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Using Cached Use Cases
|
|
318
|
+
|
|
319
|
+
```python
|
|
320
|
+
from chemstore.infrastructure.repository_impl import KVChemicalRepository
|
|
321
|
+
from chemstore.usecases.calculate_mass import CalculateMassUseCase
|
|
322
|
+
from chemstore.usecases.predict_reaction import PredictReactionUseCase
|
|
323
|
+
|
|
324
|
+
repo = KVChemicalRepository("chemistry_cache.db")
|
|
325
|
+
|
|
326
|
+
# Calculate mass with cache persistence
|
|
327
|
+
mass_calc = CalculateMassUseCase(repo)
|
|
328
|
+
mass = mass_calc.execute("CCO")
|
|
329
|
+
|
|
330
|
+
# Predict reaction with cache persistence (auto-detection)
|
|
331
|
+
rxn_calc = PredictReactionUseCase(repo)
|
|
332
|
+
products = rxn_calc.execute(None, ["CC(=O)O", "CCO"])
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## REST API Service (FastAPI)
|
|
338
|
+
|
|
339
|
+
ChemStore includes a FastAPI HTTP service exposing calculation and prediction endpoints. To support reverse-proxy routing (e.g. routing all `chemstore` traffic to `/chem`), endpoints are routed under `/chem/api/v1/...` while preserving `/api/v1/...` for direct calls and backward compatibility:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Start the API server
|
|
343
|
+
uvicorn chemstore.api.main:app --host 0.0.0.0 --port 8000 --reload
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Available Endpoints:
|
|
347
|
+
- `POST /chem/api/v1/mass` (or `/api/v1/mass`)
|
|
348
|
+
- `POST /chem/api/v1/balance` (or `/api/v1/balance`)
|
|
349
|
+
- `POST /chem/api/v1/predict` (or `/api/v1/predict`)
|
|
350
|
+
|
|
351
|
+
### Reaction Prediction Endpoint (`POST /chem/api/v1/predict`)
|
|
352
|
+
|
|
353
|
+
Supports explicit reaction names, custom SMARTS strings, or zero-configuration auto-detection:
|
|
354
|
+
|
|
355
|
+
#### With Reaction Name:
|
|
356
|
+
```bash
|
|
357
|
+
curl -X POST http://localhost:8000/chem/api/v1/predict \
|
|
358
|
+
-H "Content-Type: application/json" \
|
|
359
|
+
-d '{"reactants": ["CC(=O)O", "CCN"], "reaction_name": "amide_coupling"}'
|
|
360
|
+
```
|
|
361
|
+
Response:
|
|
362
|
+
```json
|
|
363
|
+
{
|
|
364
|
+
"reactants": ["CC(=O)O", "CCN"],
|
|
365
|
+
"reaction_name": "amide_coupling",
|
|
366
|
+
"reaction": "amide_coupling",
|
|
367
|
+
"products": ["CCNC(C)=O"]
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
#### With Automatic Detection:
|
|
372
|
+
```bash
|
|
373
|
+
curl -X POST http://localhost:8000/chem/api/v1/predict \
|
|
374
|
+
-H "Content-Type: application/json" \
|
|
375
|
+
-d '{"reactants": ["CC(=O)O", "CCO"]}'
|
|
376
|
+
```
|
|
377
|
+
Response:
|
|
378
|
+
```json
|
|
379
|
+
{
|
|
380
|
+
"reactants": ["CC(=O)O", "CCO"],
|
|
381
|
+
"reaction_name": "esterification",
|
|
382
|
+
"reaction": "esterification",
|
|
383
|
+
"products": ["CCOC(C)=O"]
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Predefined Reaction Catalog
|
|
390
|
+
|
|
391
|
+
| Identifier | Name | Reaction Transformation | SMARTS Rule |
|
|
392
|
+
| :--- | :--- | :--- | :--- |
|
|
393
|
+
| `amide_coupling` | Amide Coupling | Carboxylic Acid + Amine $\rightarrow$ Amide | `[O:2]=[C:1][OH:3].[N:4]>>[O:2]=[C:1][N:4]` |
|
|
394
|
+
| `esterification` | Fischer Esterification | Carboxylic Acid + Alcohol $\rightarrow$ Ester | `[C:1](=[O:2])[OH].[O:3][C:4]>>[C:1](=[O:2])[O:3][C:4]` |
|
|
395
|
+
| `suzuki_coupling` | Suzuki Coupling | Aryl Halide + Boronic Acid $\rightarrow$ Biaryl | `[c:1][Br,I,Cl].[c:2]B(O)O>>[c:1][c:2]` |
|
|
396
|
+
| `diels_alder` | Diels-Alder Cycloaddition | Conjugated Diene + Dienophile $\rightarrow$ Cyclohexene | `[C:1]=[C:2][C:3]=[C:4].[C:5]=[C:6]>>[C:1]1[C:2]=[C:3][C:4][C:5][C:6]1` |
|
|
397
|
+
| `ether_synthesis` | Ether Synthesis | Alkyl Halide + Alcohol $\rightarrow$ Ether | `[C:1][Br,I,Cl].[O:2][C:3]>>[C:1][O:2][C:3]` |
|
|
398
|
+
| `imine_formation` | Imine Formation | Carbonyl (Aldehyde/Ketone) + Primary Amine $\rightarrow$ Imine | `[C;!$(C[O,N,S,Cl,Br,I,F]):1]=[O:2].[N;H2:3]>>[C:1]=[N:3]` |
|
|
399
|
+
| `saponification` | Saponification | Ester $\rightarrow$ Carboxylic Acid + Alcohol | `[C:1](=[O:2])[O:3][C:4]>>[C:1](=[O:2])[OH].[O:3][C:4]` |
|
|
400
|
+
| `alkene_hydrogenation` | Alkene Hydrogenation | Alkene $\rightarrow$ Alkane | `[C:1]=[C:2]>>[C:1][C:2]` |
|
|
401
|
+
| `alkane_chlorination` | Radical Chlorination | Alkane + $\text{Cl}_2$ $\rightarrow$ Alkyl Chloride | `[CX4;!H0:1]>>[C:1]Cl` |
|
|
402
|
+
| `alkane_bromination_tertiary` | Tertiary Radical Bromination | 3° Alkane + $\text{Br}_2$ $\rightarrow$ Tertiary Alkyl Bromide | `[CX4;H1:1]>>[C:1]Br` |
|
|
403
|
+
| `alkane_dehydrogenation` | Alkane Dehydrogenation | Alkane $\rightarrow$ Alkene + $\text{H}_2$ | `[CX4;!H0:1]-[CX4;!H0:2]>>[C:1]=[C:2]` |
|
|
404
|
+
| `alkane_nitration` | Gas-Phase Nitration | Alkane + $\text{HNO}_3$ $\rightarrow$ Nitroalkane + $\text{H}_2\text{O}$ | `[CX4;!H0:1]>>[C:1][N+](=[O])[O-]` |
|
|
405
|
+
| `alkane_sulfoxidation` | Alkane Sulfoxidation | Alkane + $\text{SO}_2$ + $\text{O}_2$ $\rightarrow$ Alkanesulfonic Acid | `[CX4;!H0:1]>>[C:1]S(=O)(=O)O` |
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Testing
|
|
410
|
+
|
|
411
|
+
ChemStore includes an extensive suite of automated tests covering domain logic, storage persistence, repository caching, and CLI workflows.
|
|
412
|
+
|
|
413
|
+
Run the test suite using `pytest`:
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
# Run all tests
|
|
417
|
+
.venv/bin/pytest
|
|
418
|
+
|
|
419
|
+
# Run with verbose output
|
|
420
|
+
.venv/bin/pytest -v
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Test Coverage Highlights
|
|
424
|
+
- **Domain Tests** (`tests/domain/`): Valid/invalid SMILES parsing, polyatomic equation parsing, yield operator balancing, reaction templates, auto-prediction, order-independence.
|
|
425
|
+
- **Infrastructure Tests** (`tests/infrastructure/`): Low-level append log writes, byte offset seeks, index recovery on startup, compaction, tombstone eviction, and on-demand JSON SMARTS template loading.
|
|
426
|
+
- **API Tests** (`tests/test_api.py`): Mass calculation, chemical equation balancing, and reaction prediction with named reactions, custom SMARTS, auto-detection, and error responses.
|
|
427
|
+
- **Use Case Integration Tests** (`tests/test_repository.py`): Cache hits, cache writes, fallback lookups, and multi-round verification.
|
|
428
|
+
- **CLI Subprocess Tests** (`tests/test_cli.py`): Execution and error exits across `mass`, `balance`, `predict`, and `admin`.
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## License
|
|
433
|
+
|
|
434
|
+
This project is licensed under the MIT License.
|