Skip to content

feat:backend updates #703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,5 @@ cdk.out
*.d.ts
# !frontend/src/radis.d.ts
frontend/coverage
frontend/html
frontend/html
backend/.coverage
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
## 🌱 Radis App

[![Production deployment](https://github.com/suzil/radis-app/actions/workflows/cd.yml/badge.svg)](https://github.com/suzil/radis-app/actions/workflows/cd.yml)

Expand Down
31 changes: 31 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# FROM python:3.10.13-slim
# LABEL maintainer="Arunava Basu <[email protected]>"
# LABEL org.opencontainers.image.source="https://github.com/arunavauni-03/radis_backend_container_test"


# WORKDIR /app
# COPY . /app
# RUN pip install --upgrade pip
# RUN pip install -r requirements.txt
# EXPOSE 8080
# CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8080"]

FROM python:3.10.13-slim

LABEL maintainer="Arunava Basu <[email protected]>"
LABEL org.opencontainers.image.source="https://github.com/arunavauni-03/radis_backend_container_test"

# Install Redis
RUN apt-get update && apt-get install -y redis-server && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY . /app
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

# Expose ports
EXPOSE 8080
EXPOSE 6379

# Start Redis server and FastAPI app
CMD ["bash", "-c", "service redis-server start && uvicorn src.main:app --host 0.0.0.0 --port 8080"]
42 changes: 42 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
### request

```json
{
"species": [
{
"molecule": "CO",
"mole_fraction": 0.2
}
],
"mode": "absorbance",
"database": "hitran",
"tgas": 300,
"min_wavenumber_range": 1900,
"max_wavenumber_range": 2300,
"pressure": 1.01325,
"path_length": 1,
"use_simulate_slit": true,
"simulate_slit": 5,
"path_length_units": "u.cm",
"pressure_units": "u.bar",
"wavelength_units":"1/u.cm"
}
```

to run the srever
`uvicorn src.main:app --reload`

we need to start redis cli to get the keys and all the values
`redis-cli -h localhost -p 6379`

to start redis server
`redis-server`

`rm -rf radis.json .radisdb`

info about the file
`ls -lh CO.hdf5`

# getting the coverage information

coverage run --source=src -m pytest -v __tests__/ && coverage report -m && coverage html && coverage xml
45 changes: 32 additions & 13 deletions backend/__tests__/src/test_calculateSpectrum.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
from src.main import app # assuming your FastAPI app instance is named 'app'
import pytest
from src.main import app
from fastapi.testclient import TestClient
from __tests__.helpers.payload_data import payload_data
client = TestClient(app)

def test_calc_spectrum():

response = client.post("/calculate-spectrum", json=payload_data)

data = response.json()["data"]
assert response.status_code == 200
assert "x" in data
assert "y" in data
assert "units" in data

@pytest.fixture
def client():
return TestClient(app)

def test_calculate_spectrum(client):
payload = {
"species": [
{
"molecule": "CO",
"mole_fraction": 0.2
}
],
"mode": "absorbance",
"database": "hitran",
"tgas": 300,
"min_wavenumber_range": 1900,
"max_wavenumber_range": 2300,
"pressure": 1.01325,
"path_length": 1,
"use_simulate_slit": True,
"simulate_slit": 5,
"path_length_units": "u.cm",
"pressure_units": "u.bar",
"wavelength_units":"1/u.cm"
}
response = client.post("/calculate-spectrum", json=payload)
assert response.status_code == 200
assert "data" in response.json()
assert "x" in response.json()["data"]
assert "y" in response.json()["data"]
assert "units" in response.json()["data"]
28 changes: 28 additions & 0 deletions backend/cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os
import shutil

def delete_folders(folder_path, folders_to_delete):
"""
Deletes specified folders within a directory.

:param folder_path: Path to the directory where folders are to be deleted.
:param folders_to_delete: List of folder names to delete.
"""
for root, dirs, files in os.walk(folder_path, topdown=True):
for folder in dirs:
if folder in folders_to_delete:
folder_to_delete = os.path.join(root, folder)
print(f"Deleting folder: {folder_to_delete}")
try:
shutil.rmtree(folder_to_delete)
print(f"Folder '{folder}' deleted successfully.")
except OSError as e:
print(f"Error: {e.strerror}")

# List of folders to delete
folders_to_delete = ['__pycache__', '.pytest_cache','DOWNLOADED_SPECFILES','DOWNLOADED_TXT']

# Path to the directory containing the folders to delete
directory_path = '.'
# Call the function to delete folders
delete_folders(directory_path, folders_to_delete)
1 change: 1 addition & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
aioredis
pandas==2.0.3
numpy==1.22.3
radis==0.14
Expand Down
6 changes: 4 additions & 2 deletions backend/src/main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from src.routes import calculateSpectrum ,downloadSpectrum,downloadTxt,root
import astropy.units as u
from astropy.units import cds
# import astropy.units as u
# from astropy.units import cds




# for high resolution
Expand Down
69 changes: 51 additions & 18 deletions backend/src/routes/calculateSpectrum.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,87 @@
import json
import radis
import logging
import aioredis
import numpy as np
from fastapi import APIRouter
import astropy.units as u
from fastapi import APIRouter, Depends
from src.models.payload import Payload
from src.helpers.calculateSpectrum import calculate_spectrum

router = APIRouter()

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

async def get_redis_client():
# Create a Redis client
redis = await aioredis.from_url('redis://localhost:6379')
return redis

def serialize_payload(payload: Payload):
'''
convert to payload to string
'''
return json.dumps(payload.dict())

@router.post("/calculate-spectrum")
async def calc_spectrum(payload: Payload):
print(payload)
async def calc_spectrum(
payload: Payload,
redis: aioredis.Redis = Depends(get_redis_client)
):
# Serialize the payload for use in the key
serialized_payload = serialize_payload(payload)

# Check if the request is already in the cache
cached_result = await redis.get(f"calc_spectrum:{serialized_payload}")
if cached_result:
# If cached result exists, log a hit and return it
logger.info("Cache hit for payload: %s", serialized_payload)
return json.loads(cached_result)
else:
# Log a cache miss
logger.info("Cache miss for payload: %s", serialized_payload)

try:
spectrum = calculate_spectrum(payload)
if payload.use_simulate_slit is True:
if(payload.wavelength_units=="1/u.cm"):
slit_unit="cm-1"
if payload.wavelength_units == "1/u.cm":
slit_unit = "cm-1"
else:
slit_unit="nm"
print("Applying simulate slit")
slit_unit = "nm"
logger.info("Applying simulate slit")
spectrum.apply_slit(payload.simulate_slit, slit_unit)

except radis.misc.warning.EmptyDatabaseError:
return {"error": "No line in the specified wavenumber range"}
except Exception as exc:
print("Error", exc)
logger.error("Error: %s", exc)
return {"error": str(exc)}
else:

wunit = spectrum.get_waveunit()
iunit = "default"
xNan, yNan = spectrum.get(payload.mode, wunit=wunit, Iunit=iunit)
# to remove the nan values from x and y
x = xNan[~np.isnan(xNan)]
y = yNan[~np.isnan(yNan)]
# Reduce payload size

threshold = 5e7
if len(spectrum) * 8 * 2 > threshold:
print("Reducing the payload size")
# Setting return payload size limit of 50 MB
# one float is about 8 bytes
# we return 2 arrays (w, I)
# (note: we could avoid returning the full w-range, and recompute it on the client
# from the x min, max and step --> less data transfer. TODO )
logger.info("Reducing the payload size")
resample = int(len(spectrum) * 8 * 2 // threshold)
x, y = x[::resample], y[::resample]

return {
result = {
"data": {
"x": list(x),
"y": list(y),
"units": spectrum.units[payload.mode],
},
}

# Use Redis for caching if the connection is available
if redis:

await redis.setex(f"calc_spectrum:{serialized_payload}", 1800, json.dumps(result))

return result
Binary file added dump.rdb
Binary file not shown.