Skip to content

Commit

Permalink
Merge branch 'develop' into mk/redis-migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
Marishka17 authored Jan 30, 2025
2 parents f08bd9b + 2ca90b0 commit 4d5f70c
Show file tree
Hide file tree
Showing 49 changed files with 2,726 additions and 231 deletions.
4 changes: 2 additions & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ disable=raw-checker-failed,
raise-missing-from,
raising-format-tuple,
wrong-exception-operation,
wildcard-import,
deprecated-module,
import-self,
preferred-module,
Expand Down Expand Up @@ -516,7 +515,8 @@ enable=singleton-comparison,
logging-unsupported-format,
logging-format-truncated,
logging-too-many-args,
logging-too-few-args
logging-too-few-args,
wildcard-import


[BASIC]
Expand Down
4 changes: 4 additions & 0 deletions changelog.d/20250113_203431_mzhiltso_consensus_tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Added

- An option to create tasks with consensus jobs
(<https://github.com/cvat-ai/cvat/pull/8939>)
1 change: 1 addition & 0 deletions cvat-core/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export enum JobState {
export enum JobType {
ANNOTATION = 'annotation',
GROUND_TRUTH = 'ground_truth',
CONSENSUS_REPLICA = 'consensus_replica',
}

export enum DimensionType {
Expand Down
3 changes: 3 additions & 0 deletions cvat-core/src/server-response-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export interface SerializedTask {
subset: string;
updated_date: string;
url: string;
consensus_enabled: boolean;
}

export interface SerializedJob {
Expand All @@ -147,6 +148,8 @@ export interface SerializedJob {
url: string;
source_storage: SerializedStorage | null;
target_storage: SerializedStorage | null;
parent_job_id: number | null;
consensus_replicas: number;
}

export type AttrInputType = 'select' | 'radio' | 'checkbox' | 'number' | 'text';
Expand Down
4 changes: 4 additions & 0 deletions cvat-core/src/session-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,10 @@ export function implementTask(Task: typeof TaskClass): typeof TaskClass {
taskSpec.source_storage = this.sourceStorage.toJSON();
}

if (fields.consensus_replicas) {
taskSpec.consensus_replicas = fields.consensus_replicas;
}

const taskDataSpec = {
client_files: this.clientFiles,
server_files: this.serverFiles,
Expand Down
25 changes: 23 additions & 2 deletions cvat-core/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ export class Job extends Session {
frame_count?: number;
project_id: number | null;
guide_id: number | null;
task_id: number | null;
task_id: number;
labels: Label[];
dimension?: DimensionType;
data_compressed_chunk_type?: ChunkType;
Expand All @@ -505,6 +505,8 @@ export class Job extends Session {
updated_date?: string,
source_storage: Storage,
target_storage: Storage,
parent_job_id: number | null;
consensus_replicas: number;
};

constructor(initialData: InitializerType) {
Expand Down Expand Up @@ -532,6 +534,8 @@ export class Job extends Session {
updated_date: undefined,
source_storage: undefined,
target_storage: undefined,
parent_job_id: null,
consensus_replicas: undefined,
};

this.#data.id = initialData.id ?? this.#data.id;
Expand All @@ -546,6 +550,8 @@ export class Job extends Session {
this.#data.data_chunk_size = initialData.data_chunk_size ?? this.#data.data_chunk_size;
this.#data.mode = initialData.mode ?? this.#data.mode;
this.#data.created_date = initialData.created_date ?? this.#data.created_date;
this.#data.parent_job_id = initialData.parent_job_id ?? this.#data.parent_job_id;
this.#data.consensus_replicas = initialData.consensus_replicas ?? this.#data.consensus_replicas;

if (Array.isArray(initialData.labels)) {
this.#data.labels = initialData.labels.map((labelData) => {
Expand Down Expand Up @@ -641,14 +647,22 @@ export class Job extends Session {
return this.#data.guide_id;
}

public get taskId(): number | null {
public get taskId(): number {
return this.#data.task_id;
}

public get dimension(): DimensionType {
return this.#data.dimension;
}

public get parentJobId(): number | null {
return this.#data.parent_job_id;
}

public get consensusReplicas(): number {
return this.#data.consensus_replicas;
}

public get dataChunkType(): ChunkType {
return this.#data.data_compressed_chunk_type;
}
Expand Down Expand Up @@ -751,6 +765,7 @@ export class Task extends Session {
public readonly organization: number | null;
public readonly progress: { count: number; completed: number };
public readonly jobs: Job[];
public readonly consensusEnabled: boolean;

public readonly startFrame: number;
public readonly stopFrame: number;
Expand Down Expand Up @@ -810,6 +825,7 @@ export class Task extends Session {
cloud_storage_id: undefined,
sorting_method: undefined,
files: undefined,
consensus_enabled: undefined,

validation_mode: null,
};
Expand Down Expand Up @@ -887,6 +903,8 @@ export class Task extends Session {
data_chunk_size: data.data_chunk_size,
target_storage: initialData.target_storage,
source_storage: initialData.source_storage,
parent_job_id: job.parent_job_id,
consensus_replicas: job.consensus_replicas,
});
data.jobs.push(jobInstance);
}
Expand Down Expand Up @@ -994,6 +1012,9 @@ export class Task extends Session {
copyData: {
get: () => data.copy_data,
},
consensusEnabled: {
get: () => data.consensus_enabled,
},
labels: {
get: () => [...data.labels],
set: (labels: Label[]) => {
Expand Down
3 changes: 2 additions & 1 deletion cvat-sdk/cvat_sdk/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
#
# SPDX-License-Identifier: MIT

from cvat_sdk.api_client.models import * # pylint: disable=unused-import,redefined-builtin
# Reexport symbols for public SDK API
from cvat_sdk.api_client.models import * # pylint: disable=wildcard-import
21 changes: 13 additions & 8 deletions cvat-ui/src/actions/tasks-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,20 +262,25 @@ ThunkAction {
if (data.cloudStorageId) {
description.cloud_storage_id = data.cloudStorageId;
}
if (data.advanced.consensusReplicas) {
description.consensus_replicas = +data.advanced.consensusReplicas;
}

let extras = {};
const extras: Record<string, any> = {};

if (data.quality.validationMode !== ValidationMode.NONE) {
extras = {
validation_params: {
mode: data.quality.validationMode,
frame_selection_method: data.quality.frameSelectionMethod,
frame_share: data.quality.validationFramesPercent,
frames_per_job_share: data.quality.validationFramesPerJobPercent,
},
extras.validation_params = {
mode: data.quality.validationMode,
frame_selection_method: data.quality.frameSelectionMethod,
frame_share: data.quality.validationFramesPercent,
frames_per_job_share: data.quality.validationFramesPerJobPercent,
};
}

if (data.advanced.consensusReplicas) {
extras.consensus_replicas = description.consensus_replicas;
}

const taskInstance = new cvat.classes.Task(description);
taskInstance.clientFiles = data.files.local;
taskInstance.serverFiles = data.files.share.concat(data.files.cloudStorage);
Expand Down
30 changes: 30 additions & 0 deletions cvat-ui/src/components/common/cvat-tag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import Tag from 'antd/lib/tag';

export enum TagType {
GROUND_TRUTH = 'ground_truth',
CONSENSUS = 'consensus',
}

interface TagProps {
type: TagType;
}

function CVATTag(props: TagProps): JSX.Element | null {
const { type } = props;

switch (type) {
case TagType.GROUND_TRUTH:
return <Tag className='cvat-tag-ground-truth' color='#ED9C00'>Ground truth</Tag>;
case TagType.CONSENSUS:
return <Tag className='cvat-tag-consensus' color='#1890FF'>Consensus</Tag>;
default:
return null;
}
}

export default React.memo(CVATTag);
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Text from 'antd/lib/typography/Text';
import { Store } from 'antd/lib/form/interface';
import CVATTooltip from 'components/common/cvat-tooltip';
import patterns from 'utils/validation-patterns';
import { isInteger } from 'utils/validate-integer';
import { StorageLocation } from 'reducers';
import SourceStorageField from 'components/storage/source-storage-field';
import TargetStorageField from 'components/storage/target-storage-field';
Expand Down Expand Up @@ -47,6 +48,7 @@ export interface AdvancedConfiguration {
sortingMethod: SortingMethod;
useProjectSourceStorage: boolean;
useProjectTargetStorage: boolean;
consensusReplicas: number;
sourceStorage: StorageData;
targetStorage: StorageData;
}
Expand All @@ -59,6 +61,7 @@ const initialValues: AdvancedConfiguration = {
sortingMethod: SortingMethod.LEXICOGRAPHICAL,
useProjectSourceStorage: true,
useProjectTargetStorage: true,
consensusReplicas: 0,

sourceStorage: {
location: StorageLocation.LOCAL,
Expand Down Expand Up @@ -93,30 +96,6 @@ function validateURL(_: RuleObject, value: string): Promise<void> {
return Promise.resolve();
}

const isInteger = ({ min, max }: { min?: number; max?: number }) => (
_: RuleObject,
value?: number | string,
): Promise<void> => {
if (typeof value === 'undefined' || value === '') {
return Promise.resolve();
}

const intValue = +value;
if (Number.isNaN(intValue) || !Number.isInteger(intValue)) {
return Promise.reject(new Error('Value must be a positive integer'));
}

if (typeof min !== 'undefined' && intValue < min) {
return Promise.reject(new Error(`Value must be more than ${min}`));
}

if (typeof max !== 'undefined' && intValue > max) {
return Promise.reject(new Error(`Value must be less than ${max}`));
}

return Promise.resolve();
};

const validateOverlapSize: RuleRender = ({ getFieldValue }): RuleObject => ({
validator(_: RuleObject, value?: string | number): Promise<void> {
if (typeof value !== 'undefined' && value !== '') {
Expand Down Expand Up @@ -405,6 +384,32 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
);
}

private renderConsensusReplicas(): JSX.Element {
return (
<Form.Item
label='Consensus Replicas'
name='consensusReplicas'
rules={[
{
validator: isInteger({
min: 0,
max: 10,
filter: (intValue: number): boolean => intValue !== 1,
}),
},
]}
>
<Input
size='large'
type='number'
min={0}
max={10}
step={1}
/>
</Form.Item>
);
}

private renderSourceStorage(): JSX.Element {
const {
projectId,
Expand Down Expand Up @@ -486,6 +491,11 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
<Row justify='start'>
<Col span={7}>{this.renderChunkSize()}</Col>
</Row>
<Row justify='start'>
<Col span={7}>
{this.renderConsensusReplicas()}
</Col>
</Row>

<Row>
<Col span={24}>{this.renderBugTracker()}</Col>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const defaultState: State = {
},
useProjectSourceStorage: true,
useProjectTargetStorage: true,
consensusReplicas: 0,
},
quality: {
validationMode: ValidationMode.NONE,
Expand Down
Loading

0 comments on commit 4d5f70c

Please sign in to comment.