Skip to content
Merged
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
153 changes: 129 additions & 24 deletions backend/poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dependencies = [
"fastapi",
"uvicorn",
"requests",
"types-requests",
"httpx",
"pyjwt",
"crypto",
Expand Down
51 changes: 49 additions & 2 deletions backend/src/acidwatch_api/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from collections import defaultdict
from typing import Annotated
from typing import Annotated, Any
from uuid import UUID, uuid4
from acidwatch_api.models.datamodel import (
ModelInfo,
Expand All @@ -14,7 +14,7 @@
from fastapi.middleware.cors import CORSMiddleware
from traceback import format_exception, print_exception
from pydantic import ValidationError

import requests
from opentelemetry import trace
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
Expand All @@ -26,6 +26,7 @@
confidential_app,
swagger_ui_init_oauth_config,
get_jwt_token,
acquire_token_for_downstream_api,
)
from acidwatch_api.models.base import (
BaseAdapter,
Expand Down Expand Up @@ -87,6 +88,52 @@ def get_models(
return models


@fastapi_app.get("/oasis")
async def get_oasis(
jwt_token: str = Depends(get_jwt_token),
) -> list[dict[str, Any]]:
token = acquire_token_for_downstream_api(
f"{SETTINGS.oasis_uri}/.default", jwt_token
)
response = requests.get(
f"{SETTINGS.oasis_uri}/CO2LabResults",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status()

return format_lab_data(response.json())


def format_lab_data(response: list[dict[str, Any]]) -> list[dict[str, Any]]:
lab_data = []

for item in response:
for entry in item["data"]["labData"]["concentrations"]["entries"]:
initial_concentrations = {
key[len("In_") :].upper(): value
for key, value in entry["species"].items()
if key.startswith("In_")
}
final_concentrations = {
key[len("Out_") :].upper(): value
for key, value in entry["species"].items()
if key.startswith("Out_")
}

lab_data.append(
{
"name": f"{item['data']['general']['name']}-{entry['step']}",
"initialConcentrations": initial_concentrations,
"finalConcentrations": final_concentrations,
"pressure": entry.get("pressure"),
"temperature": entry.get("temperature"),
"time": entry.get("time"),
}
)

return lab_data


RESULTS: dict[UUID, RunResponse | BaseException] = {}


Expand Down
2 changes: 2 additions & 0 deletions backend/src/acidwatch_api/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class Settings(BaseSettings):

applicationinsights_connection_string: str | None = None

oasis_uri: str = "https://api-oasis-test.radix.equinor.com"

@property
def authority(self) -> str:
return f"https://login.microsoftonline.com/{self.tenant_id}"
Expand Down
1 change: 0 additions & 1 deletion frontend/env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ VITE_TENANT_ID=3aa4a235-b6e2-48d5-9195-7fcf05b459b0
VITE_APPINSIGHTS_CONNECTIONSTRING=<leave empty for local development>
VITE_BACKEND_CLIENT_ID=456cc109-08d7-4c11-bf2e-a7b26660f99e
VITE_BACKEND_CLIENT_SECRET=<get from azure portal, acidwatch_backend_dev>
VITE_OASIS_URL=https://api-oasis-test.radix.equinor.com/
1 change: 0 additions & 1 deletion frontend/nginx-conf/injectEnvVars.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
envsubst < /app/www/inject-env-template.js > /app/www/inject-env.js
envsubst '${OASIS_URL} ${OASIS_HOST}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
echo "===== Rendered /etc/nginx/conf.d/default.conf ====="
cat /etc/nginx/conf.d/default.conf
echo "===================================================="
Expand Down
8 changes: 1 addition & 7 deletions frontend/nginx-conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,5 @@ server {
location / {
try_files $uri $uri/ /index.html;
}
location /oasis/ {
proxy_pass ${OASIS_URL};
proxy_set_header Host ${OASIS_HOST};
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

}
68 changes: 2 additions & 66 deletions frontend/src/api/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Project } from "../dto/Project";
import { Simulation } from "../dto/Simulation";
import { ModelConfig } from "../dto/FormConfig";
import { ExperimentResult } from "../dto/ExperimentResult";
import { getUserToken } from "../services/auth";
import { getAccessToken } from "../services/auth";
import { ModelInput } from "../dto/ModelInput";

Expand Down Expand Up @@ -199,70 +198,7 @@ export async function switchPublicity(projectId: string): Promise<any> {
}
}

export const extractAndReplaceKeys = (pattern: string, replacement: string, dictionary: Record<string, any>) => {
return Object.keys(dictionary)
.filter((key) => key.startsWith(pattern))
.reduce<Record<string, number>>((acc, key) => {
acc[key.replace(pattern, replacement)] = dictionary[key];
return acc;
}, {});
};

const processData = (response: any): ExperimentResult[] => {
const experimentResults: ExperimentResult[] = response.flatMap((item: any) => {
const experimentResult = item.data.labData.concentrations.entries.map((entry: any) => {
const species = entry.species;

const inputConcentrations = extractAndReplaceKeys("In_", "", species);
const inputConcentrationsCapitalized = Object.fromEntries(
Object.entries(inputConcentrations).map(([key, value]) => [key.toUpperCase(), value])
);
const outputConcentrations = extractAndReplaceKeys("Out_", "", species);
const outputConcentrationsCapitalized = Object.fromEntries(
Object.entries(outputConcentrations).map(([key, value]) => [key.toUpperCase(), value])
);
const experimentResult: ExperimentResult = {
name: item.data.general.name + "-" + entry.step,
initialConcentrations: inputConcentrationsCapitalized,
finalConcentrations: outputConcentrationsCapitalized,
pressure: entry.pressure ?? null,
temperature: entry.temperature ?? null,
time: entry.time ?? null,
};
return experimentResult;
});

return experimentResult;
});

return experimentResults;
};
export async function getLabResults(): Promise<ExperimentResult[]> {
const token = await getUserToken(config.OASIS_SCOPE);
const response = await apiRequest(
"GET",
"/oasis/CO2LabResults",
{
headers: {
Authorization: `Bearer ${token}`,
},
},
true
);

if (!response.ok) {
if (response.status === 401) {
throw new Error("Unauthorized: Apply for access to CO2 lab results in AccessIT");
} else if (response.status === 403) {
throw new Error(
"You do not have permission to access this resource. Apply for access to CO2 lab results in AccessIT"
);
} else {
throw new Error("Network response was not ok");
}
}
const data = await response.json();

const transformedData = processData(data);
return transformedData;
const data = await apiRequest<any[]>("GET", "/oasis");
return data;
}
2 changes: 0 additions & 2 deletions frontend/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ interface Configuration {
APPINSIGHTS_CONNECTIONSTRING: string;
REDIRECT_URI: string;
AUTHORITY: string;
OASIS_SCOPE: string;
}

declare global {
Expand All @@ -26,7 +25,6 @@ function getEnvVars(): Configuration {
APPINSIGHTS_CONNECTIONSTRING: import.meta.env.VITE_APPINSIGHTS_CONNECTIONSTRING,
REDIRECT_URI: window.location.origin,
AUTHORITY: "https://login.microsoftonline.com/3aa4a235-b6e2-48d5-9195-7fcf05b459b0",
OASIS_SCOPE: import.meta.env.VITE_OASIS_SCOPE,
};
return config;
}
Expand Down
1 change: 0 additions & 1 deletion frontend/src/inject-env-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ window.injectEnv = {
CLIENT_ID: "${CLIENT_ID}",
TENANT_ID: "${TENANT_ID}",
APPINSIGHTS_CONNECTIONSTRING: "${APPINSIGHTS_CONNECTIONSTRING}",
OASIS_SCOPE: "${OASIS_SCOPE}",
};
32 changes: 1 addition & 31 deletions frontend/tests/functions/Formatting.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, expect, it } from "vitest";
import { convertSimulationToChartData, convertToSubscripts } from "../../src/functions/Formatting";
import { extractAndReplaceKeys } from "../../src/api/api";
import { convertToSubscripts, convertSimulationToChartData } from "../../src/functions/Formatting";
import { SimulationResults } from "../../src/dto/SimulationResults";
import { ModelInput } from "../../src/dto/ModelInput";

Expand Down Expand Up @@ -28,35 +27,6 @@ describe("convertToSubscripts", () => {
});
});

describe("extractAndReplaceKeys", () => {
it("should extract entries with given prefix and replace it with empty string", () => {
const prefix_1 = "foo";
const prefix_2 = "bar";
const inputDict = {
[`${prefix_1}A`]: 1,
[`${prefix_1}B`]: 2,
[`${prefix_2}A`]: 3,
[`${prefix_2}B`]: 4,
};

let res = extractAndReplaceKeys(prefix_1, "", inputDict);
let expectedOutput = {
A: 1,
B: 2,
};

expect(expectedOutput).toEqual(res);

res = extractAndReplaceKeys(prefix_2, "", inputDict);
expectedOutput = {
A: 3,
B: 4,
};

expect(expectedOutput).toEqual(res);
});
});

describe("convertingSimulationToChartData", () => {
const simulation: SimulationResults = {
modelInput: { concentrations: { CO: 0.5, H20: 0.7 }, parameters: {}, modelId: "Narnia" } as ModelInput,
Expand Down
10 changes: 1 addition & 9 deletions frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@ export default defineConfig({
esbuild: {
target: "esnext",
},
server: {
proxy: {
"/oasis": {
target: "https://api-oasis-prod.radix.equinor.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/oasis/, ""),
},
},
},

build: {
target: "esnext",
},
Expand Down
Loading