Skip to content
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

feature to download the spectrum file (.spec) #619

Merged
merged 30 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d6c78fe
create the .spec file -->>"/dowload"
arunavabasucom Aug 3, 2022
8cf0a5b
correct variable name
arunavabasucom Aug 3, 2022
da0a8e2
Merge branch 'main' into download_molecule
arunavabasucom Aug 4, 2022
1f965af
adding download .spec files as as background task
arunavabasucom Aug 7, 2022
0728221
adding the .spec to logic to `download_spec func`
arunavabasucom Aug 7, 2022
9b74cab
removing unnecessary code
arunavabasucom Aug 7, 2022
80eefd1
fixing up the function
arunavabasucom Aug 8, 2022
2d7e3ac
Merge branch 'main' into download_molecule
arunavabasucom Aug 8, 2022
cdac922
sperate the `generate and return file function `
arunavabasucom Aug 8, 2022
237986a
modified
arunavabasucom Aug 13, 2022
8a4ca30
server setup complete 😎
arunavabasucom Aug 14, 2022
873446b
frontend setup complete
arunavabasucom Aug 14, 2022
0352695
remove the size from `CALCULATE SPECTRUM button`
arunavabasucom Aug 14, 2022
3d56338
change the folder name
arunavabasucom Aug 14, 2022
f09d854
change the `http` method
arunavabasucom Aug 14, 2022
06ff1cc
correct the `endpoint` name
arunavabasucom Aug 14, 2022
fb2523f
fixed the `main.py`
arunavabasucom Aug 14, 2022
33e1419
make a common function for `submit and download`
arunavabasucom Aug 14, 2022
5955c2b
add delete script && fix naming of the hooks
arunavabasucom Aug 15, 2022
ef6e1de
use the specrate function in calculate-spectrum endpoint
arunavabasucom Aug 15, 2022
80aec4f
Merge branch 'main' into download_molecule
arunavabasucom Aug 15, 2022
e2f4437
remove emoji
arunavabasucom Aug 15, 2022
bd4dbb1
fix label and eqilibrium bug
arunavabasucom Aug 15, 2022
b51a09b
fix the naming conventions
arunavabasucom Aug 15, 2022
7eca8ec
fix the type of simulate_slit
arunavabasucom Aug 15, 2022
3bb2779
working on download
arunavabasucom Aug 16, 2022
486908c
fix the auto downloading
arunavabasucom Aug 17, 2022
6e437f1
done with download feature 😀 || remove nan values form json
arunavabasucom Aug 19, 2022
d0116a4
remove `submitcount`😎
arunavabasucom Aug 19, 2022
de597dd
fixing download button
arunavabasucom Aug 22, 2022
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
93 changes: 74 additions & 19 deletions frontend/src/components/CalcSpectrum.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Controller, useForm } from "react-hook-form";
import Switch from "@mui/material/Switch";
import FormControlLabel from "@mui/material/FormControlLabel";
import CircularProgress from "@mui/material/CircularProgress";
import Button from "@mui/material/Button";
import { CalcSpectrumPlotData, CalcSpectrumResponseData } from "../constants";
import { FormValues } from "./types";
import { Database } from "./fields/Database";
Expand Down Expand Up @@ -41,6 +42,7 @@ export const CalcSpectrum: React.FC = () => {
const [useGesia, setUseGesia] = useState(false);
const [useSlit, setUseSlit] = useState(false); // checking that user wants to apply the slit function or not in available modes
const [useSimulateSlitFunction, setUseSimulateSlitFunction] = useState(false); // checking the mode and enable or disable slit feature
const [downloadButton, setDownloadButton] = useState(false);
const Schema = yup.object().shape({
useNonEqi: yup.boolean(),
use_simulate_slit: yup.boolean(),
Expand Down Expand Up @@ -125,7 +127,10 @@ export const CalcSpectrum: React.FC = () => {
setCalcSpectrumResponse(undefined);
setError(message);
};
const onSubmit = async (data: FormValues): Promise<void> => {
const onSubmit = async (
data: FormValues,
endpoint: string
): Promise<void> => {
if (useSlit == true) {
if (data.mode === "radiance_noslit") {
data.mode = "radiance";
Expand All @@ -136,6 +141,7 @@ export const CalcSpectrum: React.FC = () => {
}

setLoading(true);
setDownloadButton(true);
console.log(data);
setError(undefined);

Expand All @@ -146,26 +152,56 @@ export const CalcSpectrum: React.FC = () => {
species: data.species,
});
import(/* webpackIgnore: true */ "./config.js").then(async (module) => {
const rawResponse = await axios.post(
module.apiEndpoint + `calculate-spectrum`,
data
);
if (
rawResponse.data.data === undefined &&
rawResponse.data.error === undefined
) {
handleBadResponse("Bad response from backend!");
} else {
const response = await rawResponse.data;
if (response.error) {
handleBadResponse(response.error);
if (endpoint === "calculate-spectrum") {
console.log("calculate-spectrum");
const rawResponse = await axios.post(
module.apiEndpoint + endpoint,
data
);
if (
rawResponse.data.data === undefined &&
rawResponse.data.error === undefined
) {
handleBadResponse("Bad response from backend!");
} else {
setCalcSpectrumResponse(response);
const response = await rawResponse.data;
if (response.error) {
handleBadResponse(response.error);
} else {
setCalcSpectrumResponse(response);
}
}
setLoading(false);
}
if (endpoint === "download-spectrum") {
setLoading(false);
console.log("Download spectrum");
await axios({
url: module.apiEndpoint + `download-spectrum`,
method: "POST",
responseType: "blob",
data: data,
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "radis.spec");
document.body.appendChild(link);
link.click();
})
.catch((error) => {
handleBadResponse(error);
});
arunavabasucom marked this conversation as resolved.
Show resolved Hide resolved

setDownloadButton(false);
}
setLoading(false); //setLoading(false) is called after the response is received
});
};

const databaseWatch = watch("database");
const modeWatch = watch("mode");

Expand All @@ -187,6 +223,20 @@ export const CalcSpectrum: React.FC = () => {
}
}, [databaseWatch, modeWatch]);

const DownloadSpectrum: React.FC = () => (
<Button
id="down-spectrum-button"
disabled={downloadButton}
variant="contained"
color="primary"
onClick={handleSubmit((data) => {
console.table(data);
onSubmit(data, `download-spectrum`);
})}
>
Download spectrum
arunavabasucom marked this conversation as resolved.
Show resolved Hide resolved
</Button>
);
const UseNonEquilibriumCalculations = () => (
<Controller
name="useNonEqi"
Expand Down Expand Up @@ -242,7 +292,9 @@ export const CalcSpectrum: React.FC = () => {
/>
);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<form
onSubmit={handleSubmit((data) => onSubmit(data, `calculate-spectrum`))}
>
{error ? <ErrorAlert message={error} /> : null}
<Grid container spacing={2}>
<Grid item xs={12} sm={8} md={5} lg={4}>
Expand Down Expand Up @@ -287,9 +339,9 @@ export const CalcSpectrum: React.FC = () => {

<Grid item xs={12}>
<Species
isNonEquilibrium={false}
isNonEquilibrium={isNonEquilibrium}
control={control}
isGeisa={false}
isGeisa={useGesia}
/>
</Grid>

Expand All @@ -315,6 +367,9 @@ export const CalcSpectrum: React.FC = () => {
<Grid item xs={12}>
<CalcSpectrumButton />
</Grid>
<Grid item xs={12}>
<DownloadSpectrum />
</Grid>
</Grid>
</Grid>

Expand Down
123 changes: 96 additions & 27 deletions server/main.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import radis
import os
from typing import List, Optional
from fastapi import FastAPI
from fastapi import BackgroundTasks, FastAPI
from pydantic import BaseModel
import radis
from fastapi.middleware.cors import CORSMiddleware
from pydantic.typing import Literal
from fastapi.responses import FileResponse


# for high resolution
radis.config["GRIDPOINTS_PER_LINEWIDTH_WARN_THRESHOLD"] = 7
app = FastAPI()

app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


# structure of the request
class Species(BaseModel):
molecule: str
mole_fraction: float
Expand All @@ -32,36 +35,72 @@ class Payload(BaseModel):
trot: Optional[float] = None
path_length: float
simulate_slit: Optional[int] = None
mode: Literal["absorbance", "transmittance_noslit", "radiance_noslit", "transmittance", "radiance"]
use_simulate_slit: bool
mode: Literal[
"absorbance",
"transmittance_noslit",
"radiance_noslit",
"transmittance",
"radiance",
]
database: Literal["hitran", "geisa"]
use_simulate_slit: bool = False


# calculating the spectrum return back the spectrum
def calculate_spectrum(payload):
print(">> Payload : ")
print(payload)
spectrum = radis.calc_spectrum(
payload.min_wavenumber_range,
payload.max_wavenumber_range,
molecule=[species.molecule for species in payload.species],
mole_fraction={
species.molecule: species.mole_fraction for species in payload.species
},
# TODO: Hard-coding "1,2,3" as the isotopologue for the time-being
isotope={species.molecule: "1,2,3" for species in payload.species},
pressure=payload.pressure,
Tgas=payload.tgas,
Tvib=payload.tvib,
Trot=payload.trot,
path_length=payload.path_length,
export_lines=False,
wstep="auto",
databank=payload.database,
use_cached=True,
)
return spectrum


# create the folder in server for better organization
def create_download_directory():
if os.path.exists("DOWNLOADED_SPECFILES"):
arunavabasucom marked this conversation as resolved.
Show resolved Hide resolved
print(" >> Folder already exists ")
else:
print(">> creating DOWNLOADED_SPECFILES folder")
os.mkdir("DOWNLOADED_SPECFILES")


# delete the file after giving the file response back to the user
def delete_spec(file_path: str):

if os.path.exists(file_path):
print(" >> Removing file......")
os.remove(file_path)
print(" >> File removed")
else:
print(" >> File is not found ")


# "/calculate-spectrum " --> to calculate the spectrum and return back the x and y coordinates
@app.post("/calculate-spectrum")
async def calculate_spectrum(payload: Payload):
async def calc_spectrum(payload: Payload):
print(payload)

try:
spectrum = radis.calc_spectrum(
payload.min_wavenumber_range,
payload.max_wavenumber_range,
molecule=[species.molecule for species in payload.species],
mole_fraction={
species.molecule: species.mole_fraction for species in payload.species
},
# TODO: Hard-coding "1,2,3" as the isotopologue for the time-being
isotope={species.molecule: "1,2,3" for species in payload.species},
pressure=payload.pressure,
Tgas=payload.tgas,
Tvib=payload.tvib,
Trot=payload.trot,
path_length=payload.path_length,
export_lines=False,
wstep="auto",
databank=payload.database,
use_cached=True,
)
spectrum = calculate_spectrum(payload)
if payload.use_simulate_slit is True:
print("Applying simulate slit")
spectrum.apply_slit(payload.simulate_slit, "nm")

except radis.misc.warning.EmptyDatabaseError:
Expand Down Expand Up @@ -94,3 +133,33 @@ async def calculate_spectrum(payload: Payload):
"units": spectrum.units[payload.mode],
},
}


# "/download-spectrum"--> to return back the .spec file and delete that file after giving the fileresponse back
@app.post("/download-spectrum")
async def download_spec(payload: Payload, background_tasks: BackgroundTasks):

try:
create_download_directory()
spectrum = calculate_spectrum(payload)
file_name_spec= spectrum.get_name()
file_name = f"{file_name_spec}.spec"
file_path = f"DOWNLOADED_SPECFILES/{file_name}"
if payload.use_simulate_slit is True:
print(" >> Applying simulate slit")
spectrum.apply_slit(payload.simulate_slit, "nm")
# returning the error response
except radis.misc.warning.EmptyDatabaseError:
return {"error": "No line in the specified wavenumber range"}
except Exception as exc:
print("Error", exc)
return {"error": str(exc)}
else:
spectrum.store(file_path, compress=True, if_exists_then="replace")
# running as a background task to delete the .spec file after giving the file response back
background_tasks.add_task(delete_spec, file_path)
return FileResponse(
file_path, media_type="application/octet-stream", filename=file_name
)