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 random_per_job option on create job page #8623

Merged
merged 6 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 4 additions & 0 deletions changelog.d/20241031_152803_klakhov_fix_create_job.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Error after creating GT job on Create job page with frame selection method `random_per_job`
(<https://github.com/cvat-ai/cvat/pull/8623>)
2 changes: 1 addition & 1 deletion cvat-core/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ export class Session {
}
}

type InitializerType = Readonly<Omit<SerializedJob, 'labels'> & { labels?: SerializedLabel[] }>;
type InitializerType = Readonly<Partial<Omit<SerializedJob, 'labels'> & { labels?: SerializedLabel[] }>>;

export class Job extends Session {
#data: {
Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.66.3",
"version": "1.66.4",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
18 changes: 14 additions & 4 deletions cvat-ui/src/actions/jobs-actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2022 Intel Corporation
// Copyright (C) 2023 CVAT.ai Corporation
// Copyright (C) 2023-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -96,10 +96,20 @@ export const getJobPreviewAsync = (job: Job): ThunkAction => async (dispatch) =>
}
};

export const createJobAsync = (data: JobData): ThunkAction => async (dispatch) => {
const jobInstance = new cvat.classes.Job(data);
export const createJobAsync = (data: JobData): ThunkAction<Promise<Job>> => async (dispatch) => {
const initialData = {
type: data.type,
task_id: data.taskID,
};
const jobInstance = new cvat.classes.Job(initialData);
try {
const savedJob = await jobInstance.save(data);
const extras = {
frame_selection_method: data.frameSelectionMethod,
seed: data.seed,
frame_count: data.frameCount,
frames_per_job_count: data.framesPerJobCount,
};
const savedJob = await jobInstance.save(extras);
return savedJob;
} catch (error) {
dispatch(jobsActions.createJobFailed(error));
Expand Down
7 changes: 3 additions & 4 deletions cvat-ui/src/components/create-job-page/create-job-page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 CVAT.ai Corporation
// Copyright (C) 2023-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -10,9 +10,8 @@ import { Row, Col } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text';
import Spin from 'antd/lib/spin';
import notification from 'antd/lib/notification';
import { Task } from 'reducers';
import { useIsMounted } from 'utils/hooks';
import { getCore } from 'cvat-core-wrapper';
import { getCore, Task } from 'cvat-core-wrapper';
import JobForm from './job-form';

const core = getCore();
Expand Down Expand Up @@ -58,7 +57,7 @@ function CreateJobPage(): JSX.Element {
</Col>
</Row>
{
fetchingTask ? (
fetchingTask || !taskInstance ? (
<div className='cvat-create-job-loding'>
klakhov marked this conversation as resolved.
Show resolved Hide resolved
<Spin size='large' className='cvat-spinner' />
</div>
Expand Down
66 changes: 44 additions & 22 deletions cvat-ui/src/components/create-job-page/job-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import './styles.scss';

import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { useHistory } from 'react-router';
import { useDispatch } from 'react-redux';
import { Row, Col } from 'antd/lib/grid';
Expand All @@ -26,19 +26,20 @@ export enum FrameSelectionMethod {
}

interface JobDataMutual {
task_id: number;
frame_selection_method: FrameSelectionMethod;
taskID: number;
frameSelectionMethod: FrameSelectionMethod;
type: JobType;
seed?: number;
}

export interface JobData extends JobDataMutual {
frame_count: number;
frameCount?: number;
framesPerJobCount?: number;
}

export interface JobFormData extends JobDataMutual {
quantity: number;
frame_count: number;
frameCount: number;
}

interface Props {
Expand All @@ -49,21 +50,24 @@ const defaultQuantity = 5;

function JobForm(props: Props): JSX.Element {
const { task } = props;
const { size: taskSize } = task;
const { size: taskSize, segmentSize } = task;
const [form] = Form.useForm();
const dispatch = useDispatch();
const history = useHistory();
const [fetching, setFetching] = useState(false);
const [frameSelectionMethod, setFrameSelectionMethod] = useState(FrameSelectionMethod.RANDOM);

const submit = useCallback(async (): Promise<any> => {
try {
const values: JobFormData = await form.validateFields();
const data: JobData = {
frame_selection_method: values.frame_selection_method,
taskID: task.id,
frameSelectionMethod: values.frameSelectionMethod,
type: values.type,
seed: values.seed,
frame_count: values.frame_count,
task_id: task.id,
...(values.frameSelectionMethod === FrameSelectionMethod.RANDOM ?
{ frameCount: values.frameCount } : { framesPerJobCount: values.frameCount }
),
};

const createdJob = await dispatch(createJobAsync(data));
Expand All @@ -86,24 +90,40 @@ function JobForm(props: Props): JSX.Element {
}
};

const sizeBase = useCallback(() => {
if (frameSelectionMethod === FrameSelectionMethod.RANDOM) {
return taskSize;
}
return segmentSize;
}, [frameSelectionMethod, segmentSize, taskSize]);
klakhov marked this conversation as resolved.
Show resolved Hide resolved

const quantityFromFrameCount = (value: number): number => Math.floor((value / sizeBase()) * 100);
const frameCountFromQuantity = (value: number): number => Math.round((value * sizeBase()) / 100);
klakhov marked this conversation as resolved.
Show resolved Hide resolved

const onQuantityChange = useCallback((value: number | null) => {
if (value) {
const newFrameCount = Math.round((value * taskSize) / 100);
const newFrameCount = frameCountFromQuantity(value);
form.setFieldsValue({
frame_count: newFrameCount,
frameCount: newFrameCount,
});
}
}, [taskSize]);
}, [taskSize, frameSelectionMethod, segmentSize]);

const onFrameCountChange = useCallback((value: number | null) => {
if (value) {
const newQuantity = Math.floor((value / taskSize) * 100);
const newQuantity = quantityFromFrameCount(value);
form.setFieldsValue({
quantity: newQuantity,
});
}
}, [taskSize]);
const frameCountDescription = 'A representative set, 5-15% of randomly chosen frames is recommended';
}, [taskSize, frameSelectionMethod, segmentSize]);

useEffect(() => {
const currentQuantity = form.getFieldValue('quantity');
onQuantityChange(currentQuantity);
}, [form, frameSelectionMethod]);

const setDescription = 'A representative set, 5-15% of randomly chosen frames is recommended';
klakhov marked this conversation as resolved.
Show resolved Hide resolved

return (
<Row className='cvat-create-job-form-wrapper'>
Expand All @@ -113,9 +133,9 @@ function JobForm(props: Props): JSX.Element {
layout='vertical'
initialValues={{
type: JobType.GROUND_TRUTH,
frame_selection_method: FrameSelectionMethod.RANDOM,
frameSelectionMethod: FrameSelectionMethod.RANDOM,
quantity: defaultQuantity,
frame_count: Math.floor((defaultQuantity * taskSize) / 100),
frameCount: frameCountFromQuantity(defaultQuantity),
}}
>
<Col>
Expand All @@ -134,13 +154,14 @@ function JobForm(props: Props): JSX.Element {
</Select>
</Form.Item>
<Form.Item
name='frame_selection_method'
name='frameSelectionMethod'
label='Frame selection method'
rules={[{ required: true, message: 'Please, specify frame selection method' }]}
>
<Select
virtual={false}
className='cvat-select-frame-selection-method'
onChange={setFrameSelectionMethod}
>
<Select.Option value={FrameSelectionMethod.RANDOM}>
Random
Expand All @@ -158,8 +179,9 @@ function JobForm(props: Props): JSX.Element {
name='quantity'
label={(
<Space>
Quantity %
<CVATTooltip title={frameCountDescription}>
{frameSelectionMethod === FrameSelectionMethod.RANDOM ?
'Quantity' : 'Quantity per job'}
<CVATTooltip title={setDescription}>
<QuestionCircleOutlined
style={{ opacity: 0.5 }}
/>
Expand All @@ -182,11 +204,11 @@ function JobForm(props: Props): JSX.Element {
<Row>
<Col>
<Form.Item
name='frame_count'
name='frameCount'
label={(
<Space>
Frame count
<CVATTooltip title={frameCountDescription}>
<CVATTooltip title={setDescription}>
<QuestionCircleOutlined
style={{ opacity: 0.5 }}
/>
Expand Down
Loading