Vaishnav14220 commited on
Commit
b489aa1
·
1 Parent(s): 62825c2

Add FastAPI endpoints for NIST kinetics data access

Browse files
Files changed (3) hide show
  1. API_README.md +255 -0
  2. __pycache__/app.cpython-311.pyc +0 -0
  3. app.py +205 -5
API_README.md ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NIST Chemical Kinetics API
2
+
3
+ This application provides both a web interface (Gradio) and a REST API (FastAPI) for searching and analyzing the NIST Chemical Kinetics Database.
4
+
5
+ ## Access Points
6
+
7
+ - **Web Interface**: `http://localhost:7860/` (or your deployed URL)
8
+ - **API Documentation**: `http://localhost:7860/docs` (Swagger UI)
9
+ - **Alternative API Docs**: `http://localhost:7860/redoc` (ReDoc)
10
+
11
+ ## API Endpoints
12
+
13
+ ### 1. Root Information
14
+ ```
15
+ GET /
16
+ ```
17
+ Returns basic API information and available endpoints.
18
+
19
+ **Response:**
20
+ ```json
21
+ {
22
+ "name": "NIST Chemical Kinetics API",
23
+ "version": "1.0.0",
24
+ "endpoints": {
25
+ "/search": "Search NIST kinetics database",
26
+ "/reaction/{url}": "Get detailed reaction information",
27
+ "/thermodynamic/{formula}": "Get thermodynamic data for a compound",
28
+ "/nist-reactions": "Get list of NIST reactions",
29
+ "/docs": "API documentation"
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### 2. Search Reactions
35
+ ```
36
+ POST /search
37
+ ```
38
+ Search the NIST Chemical Kinetics Database.
39
+
40
+ **Parameters:**
41
+ - `query` (required): Search query string (e.g., "CH4", "benzene")
42
+ - `filters` (optional): Array of filter objects
43
+
44
+ **Request Body Example:**
45
+ ```json
46
+ {
47
+ "query": "CH4",
48
+ "filters": [
49
+ {
50
+ "field": "reactants",
51
+ "relation": "contains",
52
+ "value": "CH4"
53
+ }
54
+ ]
55
+ }
56
+ ```
57
+
58
+ **Response Example:**
59
+ ```json
60
+ {
61
+ "query": "CH4",
62
+ "count": 10,
63
+ "results": [
64
+ {
65
+ "reaction": "CH4 + OH → CH3 + H2O",
66
+ "k_298": "6.3e-15",
67
+ "a": "2.45e-12",
68
+ "n": "0.0",
69
+ "ea": "1710",
70
+ "t_range": "200-500 K",
71
+ "p_range": "0.001-100 atm",
72
+ "bath_gas": "He",
73
+ "url": "https://kinetics.nist.gov/..."
74
+ }
75
+ ]
76
+ }
77
+ ```
78
+
79
+ ### 3. Get Reaction Detail
80
+ ```
81
+ GET /reaction?url={nist_url}
82
+ ```
83
+ Get detailed information for a specific reaction.
84
+
85
+ **Parameters:**
86
+ - `url` (required): NIST reaction URL
87
+
88
+ **Response Example:**
89
+ ```json
90
+ {
91
+ "reaction": "CH4 + OH → CH3 + H2O",
92
+ "reactants": ["CH4", "OH"],
93
+ "products": ["CH3", "H2O"],
94
+ "rate_data": [
95
+ {
96
+ "k_298": "6.3e-15",
97
+ "a": "2.45e-12",
98
+ "n": "0.0",
99
+ "ea": "1710",
100
+ "t_range": "200-500 K",
101
+ "p_range": "0.001-100 atm",
102
+ "bath_gas": "He",
103
+ "reference": "Atkinson et al., 2004",
104
+ "squib": "2004ATK/BAU8400-8468"
105
+ }
106
+ ]
107
+ }
108
+ ```
109
+
110
+ ### 4. Get Thermodynamic Data
111
+ ```
112
+ GET /thermodynamic/{formula}?database={db_type}
113
+ ```
114
+ Get thermodynamic data for a compound from NIST WebBook.
115
+
116
+ **Parameters:**
117
+ - `formula` (required): Chemical formula or name (e.g., "CH3", "benzene")
118
+ - `database` (optional): Database type - "gas-phase", "ion-energetics", or "condensed-phase" (default: "gas-phase")
119
+
120
+ **Response Example:**
121
+ ```json
122
+ {
123
+ "formula": "CH3",
124
+ "database": "gas-phase",
125
+ "data": [
126
+ {
127
+ "Temperature (K)": 298.15,
128
+ "Cp (J/mol*K)": 38.70,
129
+ "S (J/mol*K)": 194.20,
130
+ "H-H298 (kJ/mol)": 0.0
131
+ }
132
+ ],
133
+ "summary": "# Thermodynamic Data for CH3\n..."
134
+ }
135
+ ```
136
+
137
+ ### 5. Get NIST Reactions List
138
+ ```
139
+ GET /nist-reactions?limit={number}
140
+ ```
141
+ Get a list of reactions from the NIST database.
142
+
143
+ **Parameters:**
144
+ - `limit` (optional): Maximum number of reactions to return (default: 200)
145
+
146
+ **Response Example:**
147
+ ```json
148
+ {
149
+ "count": 200,
150
+ "reactions": [
151
+ {
152
+ "label": "CH4 + OH → CH3 + H2O",
153
+ "reaction": "CH4 + OH → CH3 + H2O"
154
+ }
155
+ ]
156
+ }
157
+ ```
158
+
159
+ ## Using the API
160
+
161
+ ### cURL Examples
162
+
163
+ **Search for reactions:**
164
+ ```bash
165
+ curl -X POST "http://localhost:7860/search?query=CH4" \
166
+ -H "Content-Type: application/json"
167
+ ```
168
+
169
+ **Get reaction details:**
170
+ ```bash
171
+ curl "http://localhost:7860/reaction?url=https://kinetics.nist.gov/kinetics/Detail?id=1993DEA/SIB4517-4529:4"
172
+ ```
173
+
174
+ **Get thermodynamic data:**
175
+ ```bash
176
+ curl "http://localhost:7860/thermodynamic/CH3?database=gas-phase"
177
+ ```
178
+
179
+ **Get NIST reactions list:**
180
+ ```bash
181
+ curl "http://localhost:7860/nist-reactions?limit=50"
182
+ ```
183
+
184
+ ### Python Example
185
+
186
+ ```python
187
+ import requests
188
+
189
+ # Search for reactions
190
+ response = requests.post(
191
+ "http://localhost:7860/search",
192
+ params={"query": "CH4"}
193
+ )
194
+ data = response.json()
195
+ print(f"Found {data['count']} reactions")
196
+
197
+ # Get thermodynamic data
198
+ response = requests.get(
199
+ "http://localhost:7860/thermodynamic/benzene",
200
+ params={"database": "gas-phase"}
201
+ )
202
+ thermo_data = response.json()
203
+ print(thermo_data)
204
+ ```
205
+
206
+ ### JavaScript Example
207
+
208
+ ```javascript
209
+ // Search for reactions
210
+ fetch('http://localhost:7860/search?query=CH4', {
211
+ method: 'POST',
212
+ headers: {
213
+ 'Content-Type': 'application/json'
214
+ }
215
+ })
216
+ .then(response => response.json())
217
+ .then(data => console.log(`Found ${data.count} reactions`));
218
+
219
+ // Get thermodynamic data
220
+ fetch('http://localhost:7860/thermodynamic/benzene?database=gas-phase')
221
+ .then(response => response.json())
222
+ .then(data => console.log(data));
223
+ ```
224
+
225
+ ## Running the Application
226
+
227
+ ```bash
228
+ # Install dependencies
229
+ pip install -r requirements.txt
230
+
231
+ # Run the application
232
+ python app.py
233
+ ```
234
+
235
+ The application will start on `http://0.0.0.0:7860` by default. You can change the port by setting the `PORT` environment variable:
236
+
237
+ ```bash
238
+ PORT=8000 python app.py
239
+ ```
240
+
241
+ ## Deployment
242
+
243
+ For production deployment, consider using:
244
+ - **Gunicorn** with Uvicorn workers
245
+ - **Docker** for containerization
246
+ - **Nginx** as a reverse proxy
247
+
248
+ Example with Gunicorn:
249
+ ```bash
250
+ gunicorn app:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:7860
251
+ ```
252
+
253
+ ## License
254
+
255
+ Please refer to the NIST data usage policies and licensing terms when using this API.
__pycache__/app.cpython-311.pyc ADDED
Binary file (85.7 kB). View file
 
app.py CHANGED
@@ -1639,12 +1639,212 @@ def build_interface() -> gr.Blocks:
1639
  return demo
1640
 
1641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1642
  demo = build_interface()
 
1643
 
1644
  if __name__ == "__main__":
1645
- demo.launch(
1646
- server_name="0.0.0.0",
1647
- server_port=int(os.environ.get("PORT", 7860)),
1648
- show_error=True,
1649
- share=False
1650
  )
 
1639
  return demo
1640
 
1641
 
1642
+ # Create FastAPI app
1643
+ app = FastAPI(
1644
+ title="NIST Chemical Kinetics API",
1645
+ description="API for searching and analyzing NIST Chemical Kinetics Database",
1646
+ version="1.0.0"
1647
+ )
1648
+
1649
+ # Add CORS middleware
1650
+ app.add_middleware(
1651
+ CORSMiddleware,
1652
+ allow_origins=["*"],
1653
+ allow_credentials=True,
1654
+ allow_methods=["*"],
1655
+ allow_headers=["*"],
1656
+ )
1657
+
1658
+ # API Endpoints
1659
+ @app.get("/")
1660
+ async def root():
1661
+ """Root endpoint with API information"""
1662
+ return {
1663
+ "name": "NIST Chemical Kinetics API",
1664
+ "version": "1.0.0",
1665
+ "endpoints": {
1666
+ "/search": "Search NIST kinetics database",
1667
+ "/reaction/{url}": "Get detailed reaction information",
1668
+ "/thermodynamic/{formula}": "Get thermodynamic data for a compound",
1669
+ "/nist-reactions": "Get list of NIST reactions",
1670
+ "/docs": "API documentation"
1671
+ }
1672
+ }
1673
+
1674
+ @app.post("/search")
1675
+ async def search_nist(
1676
+ query: str = Query(..., description="Search query (e.g., CH4, benzene)"),
1677
+ filters: Optional[List[Dict[str, Any]]] = None
1678
+ ):
1679
+ """
1680
+ Search the NIST Chemical Kinetics Database
1681
+
1682
+ Args:
1683
+ query: Search query string
1684
+ filters: Optional list of search filters
1685
+
1686
+ Returns:
1687
+ List of search results with reaction details
1688
+ """
1689
+ try:
1690
+ # Build search filters
1691
+ search_filters = []
1692
+ if filters:
1693
+ for f in filters[:MAX_FILTERS]:
1694
+ search_filters.append(SearchFilter(
1695
+ field=FieldName(f.get("field", "reactants")),
1696
+ relation=Relation(f.get("relation", "contains")),
1697
+ value=f.get("value", "")
1698
+ ))
1699
+
1700
+ # Perform search
1701
+ request = SearchRequest(
1702
+ category=Category.search,
1703
+ filters=search_filters if search_filters else [
1704
+ SearchFilter(
1705
+ field=FieldName.reactants,
1706
+ relation=Relation.contains,
1707
+ value=query
1708
+ )
1709
+ ]
1710
+ )
1711
+
1712
+ results = client.search_reactions(request)
1713
+
1714
+ return {
1715
+ "query": query,
1716
+ "count": len(results),
1717
+ "results": [
1718
+ {
1719
+ "reaction": r.reaction,
1720
+ "k_298": r.k_298,
1721
+ "a": r.a,
1722
+ "n": r.n,
1723
+ "ea": r.ea,
1724
+ "t_range": r.t_range,
1725
+ "p_range": r.p_range,
1726
+ "bath_gas": r.bath_gas,
1727
+ "url": r.url
1728
+ }
1729
+ for r in results
1730
+ ]
1731
+ }
1732
+ except Exception as e:
1733
+ raise HTTPException(status_code=500, detail=str(e))
1734
+
1735
+ @app.get("/reaction")
1736
+ async def get_reaction_detail(url: str = Query(..., description="NIST reaction URL")):
1737
+ """
1738
+ Get detailed information for a specific reaction
1739
+
1740
+ Args:
1741
+ url: NIST reaction URL
1742
+
1743
+ Returns:
1744
+ Detailed reaction information including rate data and references
1745
+ """
1746
+ try:
1747
+ detail = client.fetch_reaction_detail(url)
1748
+
1749
+ if not detail:
1750
+ raise HTTPException(status_code=404, detail="Reaction not found")
1751
+
1752
+ return {
1753
+ "reaction": detail.reaction,
1754
+ "reactants": detail.reactants,
1755
+ "products": detail.products,
1756
+ "rate_data": [
1757
+ {
1758
+ "k_298": rd.k_298,
1759
+ "a": rd.a,
1760
+ "n": rd.n,
1761
+ "ea": rd.ea,
1762
+ "t_range": rd.t_range,
1763
+ "p_range": rd.p_range,
1764
+ "bath_gas": rd.bath_gas,
1765
+ "reference": rd.reference,
1766
+ "squib": rd.squib
1767
+ }
1768
+ for rd in detail.rate_data
1769
+ ]
1770
+ }
1771
+ except HTTPException:
1772
+ raise
1773
+ except Exception as e:
1774
+ raise HTTPException(status_code=500, detail=str(e))
1775
+
1776
+ @app.get("/thermodynamic/{formula}")
1777
+ async def get_thermodynamic_data(
1778
+ formula: str,
1779
+ database: str = Query("gas-phase", description="Database type: gas-phase, ion-energetics, or condensed-phase")
1780
+ ):
1781
+ """
1782
+ Get thermodynamic data for a compound from NIST WebBook
1783
+
1784
+ Args:
1785
+ formula: Chemical formula or name (e.g., CH3, benzene)
1786
+ database: Database to search (gas-phase, ion-energetics, condensed-phase)
1787
+
1788
+ Returns:
1789
+ Thermodynamic data including enthalpy, entropy, heat capacity
1790
+ """
1791
+ try:
1792
+ if database == "gas-phase":
1793
+ url = _build_webbook_url(formula, "gas-phase")
1794
+ elif database == "ion-energetics":
1795
+ url = _build_webbook_url(formula, "ion-energetics")
1796
+ elif database == "condensed-phase":
1797
+ url = _build_webbook_url(formula, "condensed-phase")
1798
+ else:
1799
+ raise HTTPException(status_code=400, detail="Invalid database type")
1800
+
1801
+ md_content, df, plot_html = _fetch_and_parse_webbook(url, formula, database)
1802
+
1803
+ if df is not None and not df.empty:
1804
+ return {
1805
+ "formula": formula,
1806
+ "database": database,
1807
+ "data": df.to_dict(orient="records"),
1808
+ "summary": md_content
1809
+ }
1810
+ else:
1811
+ raise HTTPException(status_code=404, detail=f"No data found for {formula} in {database}")
1812
+ except HTTPException:
1813
+ raise
1814
+ except Exception as e:
1815
+ raise HTTPException(status_code=500, detail=str(e))
1816
+
1817
+ @app.get("/nist-reactions")
1818
+ async def get_nist_reactions(limit: int = Query(200, description="Maximum number of reactions to return")):
1819
+ """
1820
+ Get a list of reactions from the NIST database
1821
+
1822
+ Args:
1823
+ limit: Maximum number of reactions to return (default: 200)
1824
+
1825
+ Returns:
1826
+ List of reactions with labels
1827
+ """
1828
+ try:
1829
+ reactions = _fetch_all_nist_reactions(limit=limit)
1830
+ return {
1831
+ "count": len(reactions),
1832
+ "reactions": [
1833
+ {"label": label, "reaction": reaction}
1834
+ for label, reaction in reactions
1835
+ ]
1836
+ }
1837
+ except Exception as e:
1838
+ raise HTTPException(status_code=500, detail=str(e))
1839
+
1840
+ # Mount Gradio app
1841
  demo = build_interface()
1842
+ app = gr.mount_gradio_app(app, demo, path="/")
1843
 
1844
  if __name__ == "__main__":
1845
+ import uvicorn
1846
+ uvicorn.run(
1847
+ app,
1848
+ host="0.0.0.0",
1849
+ port=int(os.environ.get("PORT", 7860))
1850
  )