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

FIX : Bug in validation #94

Merged
merged 4 commits into from
Apr 10, 2023
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
8 changes: 8 additions & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ def create(self, validated_data):
existing_trainings = Training.objects.filter(model_id=model_id).exclude(
status__in=["FINISHED", "FAILED"]
)
model = get_object_or_404(Model, id=model_id)
if not Label.objects.filter(
aoi__in=AOI.objects.filter(dataset=model.dataset)
).exists():
raise ValidationError(
"Error: No labels associated with the model, Create AOI & Labels for Dataset"
)

if existing_trainings.exists():
raise ValidationError(
"Another training is already running or submitted for this model."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { useNavigate, useParams } from "react-router-dom";
import { modelStatus } from "../../../../utils";
import axios from "../../../../axios";
import { useMutation, useQuery } from "react-query";
import Popup from "./Popup";

import OSMUser from "../../../Shared/OSMUser";
import SaveIcon from "@material-ui/icons/Save";
import { Checkbox, FormControlLabel } from "@mui/material";
Expand All @@ -25,6 +27,8 @@ const AIModelEditor = (props) => {
const [error, setError] = useState(null);
const [epochs, setEpochs] = useState(20);
const [zoomLevel, setZoomLevel] = useState([19]);
const [popupOpen, setPopupOpen] = useState(false);
const [popupRowData, setPopupRowData] = useState(null);

const [random, setRandom] = useState(Math.random());
const [batchSize, setBatchSize] = useState(8);
Expand All @@ -45,6 +49,20 @@ const AIModelEditor = (props) => {
} finally {
}
};
const openPopupWithTrainingId = async (trainingId) => {
try {
const response = await axios.get(`/training/${trainingId}/`);
setPopupRowData(response.data);
setPopupOpen(true);
} catch (error) {
console.error("Error fetching training information:", error);
}
};
const handlePopupOpen = (row) => {
setPopupRowData(row);
setPopupOpen(true);
};

const { data, isLoading, refetch } = useQuery("getModelById", getModelById, {
refetchInterval: 60000,
});
Expand Down Expand Up @@ -92,23 +110,43 @@ const AIModelEditor = (props) => {
<Typography variant="h6" component="div">
Model ID: {data.id}
</Typography>
<Typography variant="h6" component="div">
Status: {modelStatus(data.status)}
{data.published_training &&
", training: " + data.published_training + ", "}
<Typography
variant="h6"
component="div"
style={{ display: "flex", justifyContent: "space-between" }}
>
<div>
Status: <b>{modelStatus(data.status)}</b>
{data.published_training && (
<>
,
<Link
href="#"
onClick={(e) => {
e.preventDefault();
openPopupWithTrainingId(data.published_training);
}}
color="inherit"
>
<b>Training: {data.published_training}</b>
</Link>
</>
)}
</div>
{data.status === 0 && (
<Link
href="#"
<Button
variant="contained"
color="primary"
onClick={(e) => {
e.preventDefault();
navigate("/start-mapping/" + data.id);
}}
color="inherit"
>
Start mapping
</Link>
</Button>
)}
</Typography>

<Typography variant="h6" component="div">
<Link
href="#"
Expand Down Expand Up @@ -257,6 +295,13 @@ const AIModelEditor = (props) => {
</Grid>
</Grid>
)}
{popupRowData && (
<Popup
open={popupOpen}
handleClose={() => setPopupOpen(false)}
row={popupRowData}
/>
)}
</>
);
};
Expand Down
69 changes: 47 additions & 22 deletions frontend/src/components/Layout/AIModels/AIModelEditor/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import {
DialogContent,
DialogActions,
Button,
CircularProgress,
} from "@mui/material";
import axios from "../../../../axios";

const Popup = ({ open, handleClose, row }) => {
const [error, setError] = useState(null);
const [traceback, setTraceback] = useState(null);
const [imageUrl, setImageUrl] = useState(null);
const [loading, setLoading] = useState(false);

const getTrainingStatus = async (taskId) => {
try {
Expand Down Expand Up @@ -60,10 +62,13 @@ const Popup = ({ open, handleClose, row }) => {
};

useEffect(() => {
setLoading(true);
if (row.status === "FAILED" || row.status === "RUNNING") {
getTrainingStatus(row.task_id);
getTrainingStatus(row.task_id).finally(() => setLoading(false));
} else if (row.status === "FINISHED") {
getDatasetId(row.model);
getDatasetId(row.model).finally(() => setLoading(false));
} else {
setLoading(false);
}
}, [row.status, row.task_id, row.model]);

Expand Down Expand Up @@ -95,32 +100,52 @@ const Popup = ({ open, handleClose, row }) => {
<p>
<b>Accuracy:</b> {row.accuracy}
</p>
<p>
<b>Status:</b> {row.status}
</p>
{(row.status === "FAILED" || row.status === "RUNNING") && (
<>
<p>
<b>Status:</b> {row.status}
</p>
{traceback && (
<div
style={{
backgroundColor: "black",
color: "white",
padding: "10px",
fontSize: "12px",
whiteSpace: "pre-wrap",
fontFamily: "monospace",
overflow: "auto",
}}
>
{renderTraceback()}
{loading ? (
<div style={{ display: "flex", justifyContent: "center" }}>
<CircularProgress />
</div>
) : (
traceback && (
<div
style={{
backgroundColor: "black",
color: "white",
padding: "10px",
fontSize: "12px",
whiteSpace: "pre-wrap",
fontFamily: "monospace",
overflow: "auto",
}}
>
{renderTraceback()}
</div>
)
)}
</>
)}
{row.status === "FINISHED" && imageUrl && (
<div style={{ display: "flex", justifyContent: "center" }}>
<img src={imageUrl} alt="training graph" style={{ width: "98%" }} />
</div>
{row.status === "FINISHED" && (
<>
{loading ? (
<div style={{ display: "flex", justifyContent: "center" }}>
<CircularProgress />
</div>
) : (
imageUrl && (
<div style={{ display: "flex", justifyContent: "center" }}>
<img
src={imageUrl}
alt="training graph"
style={{ width: "98%" }}
/>
</div>
)
)}
</>
)}
</DialogContent>

Expand Down
28 changes: 25 additions & 3 deletions frontend/src/components/Layout/AIModels/AIModelEditor/Trainings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React, { useContext, useEffect, useState } from "react";
import { DataGrid } from "@mui/x-data-grid";
import { Grid, IconButton, Tooltip, Typography } from "@mui/material";
import {
Grid,
IconButton,
Tooltip,
Typography,
CircularProgress,
} from "@mui/material";

import { useMutation, useQuery } from "react-query";
import axios from "../../../../axios";
import Alert from "@material-ui/lab/Alert";
Expand All @@ -23,6 +30,8 @@ const DEFAULT_FILTER = {
const AIModelsList = (props) => {
const [error, setError] = useState(null);
const [popupOpen, setPopupOpen] = useState(false);
const [publishing, setPublishing] = useState(false);

const [popupRow, setPopupRow] = useState(null);

const handlePopupOpen = (row) => {
Expand Down Expand Up @@ -61,6 +70,13 @@ const AIModelsList = (props) => {
field: "description",
headerName: "Description",
flex: 1,
renderCell: (params) => {
return (
<Tooltip title={params.value} placement="right">
<span>{params.value}</span>
</Tooltip>
);
},
},
{
field: "epochs",
Expand Down Expand Up @@ -172,13 +188,16 @@ const AIModelsList = (props) => {
mutate(params.row.id);
}}
>
<PublishIcon />
{publishing ? (
<CircularProgress size={24} />
) : (
<PublishIcon />
)}
</IconButton>
</Tooltip>
)}
</>
);
// <p>{`${params.row.status} and id ${params.row.id}`}</p>;
},
},
];
Expand All @@ -191,6 +210,7 @@ const AIModelsList = (props) => {

const { accessToken } = useContext(AuthContext);
const publishModel = async (trainingId) => {
setPublishing(true);
try {
const headers = {
"access-token": accessToken,
Expand All @@ -213,8 +233,10 @@ const AIModelsList = (props) => {
console.log("isError");
setError(JSON.stringify(e));
} finally {
setPublishing(false);
}
};

const { mutate } = useMutation(publishModel);
return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ const AIModelsList = (props) => {
{
field: "name",
headerName: "Name",
width: 250,
renderCell: (params) => {
return (
<Tooltip title={params.value} placement="right">
<span>{params.value}</span>
</Tooltip>
);
},
},
{
field: "created_at",
Expand Down Expand Up @@ -79,6 +87,7 @@ const AIModelsList = (props) => {
{
field: "dataset",
headerName: "Dataset ID",
width: 150,

renderCell: (params) => {
return <span> {params.value}</span>;
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/components/Layout/Start/ModelsMap/ModelsMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,18 @@ const PublishedAIModelsList = (props) => {
);
},
},
{ field: "name", headerName: "Name" },
{
field: "name",
headerName: "Name",
width: 250,
renderCell: (params) => {
return (
<Tooltip title={params.value} placement="right">
<span>{params.value}</span>
</Tooltip>
);
},
},
{
field: "last_modified",
headerName: "Last Modified",
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/components/Layout/Start/Prediction/Prediction.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { GeoJSON } from "react-leaflet";
const Prediction = () => {
const { id } = useParams();
const [error, setError] = useState(false);
const [apiCallInProgress, setApiCallInProgress] = useState(false);

const [map, setMap] = useState(null);
const [zoom, setZoom] = useState(0);
const [responseTime, setResponseTime] = useState(0);
Expand All @@ -28,6 +30,20 @@ const Prediction = () => {
]);
const [josmEnabled, setJosmEnabled] = useState(false);

useEffect(() => {
if (!apiCallInProgress) {
return;
}

const timer = setInterval(() => {
setResponseTime((prevResponseTime) => prevResponseTime + 1);
}, 1000);

return () => {
clearInterval(timer);
};
}, [apiCallInProgress]);

useEffect(() => {
getModel();
}, []);
Expand Down Expand Up @@ -80,6 +96,7 @@ const Prediction = () => {
data: predictions,
isLoading: predictionLoading,
} = useMutation(async () => {
setApiCallInProgress(true);
const headers = {
"access-token": accessToken,
};
Expand All @@ -98,6 +115,7 @@ const Prediction = () => {
const res = await axios.post(`/prediction/`, body, { headers });
const endTime = new Date().getTime(); // measure end time
setResponseTime((endTime - startTime) / 1000); // calculate and store response time in seconds
setApiCallInProgress(false);
if (res.error) {
setError(
`${res.error.response.statusText}, ${JSON.stringify(
Expand Down
Loading