11// Copyright (C) 2022-2025 Intel Corporation
22// LIMITED EDGE SOFTWARE DISTRIBUTION LICENSE
33
4- import { FC , useState } from 'react' ;
4+ import { FC , useRef , useState } from 'react' ;
55
6- import { Flex , Grid , minmax , Text , View } from '@geti/ui' ;
6+ import { Content , Flex , Grid , Heading , InlineAlert , minmax , Text , View } from '@geti/ui' ;
7+ import { isEqual } from 'lodash-es' ;
78
89import {
910 ConfigurationParameter ,
@@ -13,7 +14,7 @@ import {
1314import { Accordion } from '../../ui/accordion/accordion.component' ;
1415import { ResetButton } from '../../ui/reset-button.component' ;
1516import { SubsetsDistributionSlider } from './subsets-distribution-slider/subsets-distribution-slider.component' ;
16- import { getSubsetsSizes } from './utils' ;
17+ import { areSubsetsSizesValid , getSubsetsSizes , MAX_RATIO_VALUE } from './utils' ;
1718
1819import styles from './training-subsets.module.scss' ;
1920
@@ -85,17 +86,7 @@ const SubsetsDistribution: FC<SubsetsDistributionProps> = ({
8586} ) => {
8687 const handleSubsetDistributionChange = ( values : number [ ] | number ) : void => {
8788 if ( Array . isArray ( values ) ) {
88- const [ startRange , endRange ] = values ;
89-
90- const newSubsetSizes = getSubsetsSizes ( subsetParameters , endRange - startRange , MAX_RATIO_VALUE - endRange ) ;
91-
92- if (
93- [
94- newSubsetSizes . trainingSubsetSize ,
95- newSubsetSizes . validationSubsetSize ,
96- newSubsetSizes . testSubsetSize ,
97- ] . some ( ( size ) => size === 0 )
98- ) {
89+ if ( ! areSubsetsSizesValid ( subsetParameters , values ) ) {
9990 return ;
10091 }
10192
@@ -105,17 +96,7 @@ const SubsetsDistribution: FC<SubsetsDistributionProps> = ({
10596
10697 const handleSubsetDistributionChangeEnd = ( values : number [ ] | number ) : void => {
10798 if ( Array . isArray ( values ) ) {
108- const [ startRange , endRange ] = values ;
109-
110- const newSubsetSizes = getSubsetsSizes ( subsetParameters , endRange - startRange , MAX_RATIO_VALUE - endRange ) ;
111-
112- if (
113- [
114- newSubsetSizes . trainingSubsetSize ,
115- newSubsetSizes . validationSubsetSize ,
116- newSubsetSizes . testSubsetSize ,
117- ] . some ( ( size ) => size === 0 )
118- ) {
99+ if ( ! areSubsetsSizesValid ( subsetParameters , values ) ) {
119100 return ;
120101 }
121102
@@ -156,11 +137,10 @@ const SubsetsDistribution: FC<SubsetsDistributionProps> = ({
156137 ) ;
157138} ;
158139
159- const MAX_RATIO_VALUE = 100 ;
160-
161140type SubsetsParameters = TrainingConfiguration [ 'datasetPreparation' ] [ 'subsetSplit' ] ;
162141
163142interface TrainingSubsetsProps {
143+ hasSupportedModels : boolean ;
164144 subsetsParameters : SubsetsParameters ;
165145 onUpdateTrainingConfiguration : (
166146 updateFunction : ( config : TrainingConfiguration | undefined ) => TrainingConfiguration | undefined
@@ -185,9 +165,44 @@ const getSubsets = (subsetsParameters: SubsetsParameters) => {
185165 } ;
186166} ;
187167
188- export const TrainingSubsets : FC < TrainingSubsetsProps > = ( { subsetsParameters, onUpdateTrainingConfiguration } ) => {
168+ const TrainingSubsetsUnavailable = ( ) => {
169+ return (
170+ < InlineAlert variant = { 'notice' } >
171+ < Heading > Training subsets configuration unavailable</ Heading >
172+ < Content >
173+ The training, validation, and testing subsets are currently unavailable because the project does not
174+ contain enough media items to support a proper split.
175+ < br />
176+ To enable subset configuration, please add more media items so that each subset contains at least one
177+ item.
178+ </ Content >
179+ </ InlineAlert >
180+ ) ;
181+ } ;
182+
183+ const TrainingSubsetsChangedDistributionWarning = ( ) => {
184+ return (
185+ < InlineAlert variant = { 'notice' } >
186+ < Heading > Additional configuration change required to apply new training subsets distribution</ Heading >
187+ < Content >
188+ To apply the updated distribution of training, validation, and testing subsets, please go to{ ' ' }
189+ { '"Training"' } tab, choose { '"Pre-trained weights"' } , and enable { '"Reshuffle subsets"' } .
190+ < br />
191+ This will reset your data splits and begin a new training process, replacing the current model.
192+ </ Content >
193+ </ InlineAlert >
194+ ) ;
195+ } ;
196+
197+ export const TrainingSubsets : FC < TrainingSubsetsProps > = ( {
198+ hasSupportedModels,
199+ subsetsParameters,
200+ onUpdateTrainingConfiguration,
201+ } ) => {
189202 const { trainingSubset, validationSubset } = getSubsets ( subsetsParameters ) ;
190203
204+ const prevSubsetParameters = useRef ( subsetsParameters ) ;
205+
191206 const [ subsetsDistribution , setSubsetsDistribution ] = useState < number [ ] > ( [
192207 trainingSubset . value ,
193208 trainingSubset . value + validationSubset . value ,
@@ -259,6 +274,10 @@ export const TrainingSubsets: FC<TrainingSubsetsProps> = ({ subsetsParameters, o
259274 testSubsetRatio
260275 ) ;
261276
277+ const subsetsSizesValid = areSubsetsSizesValid ( subsetsParameters , subsetsDistribution ) ;
278+ const isChangedDistributionWarningVisible =
279+ hasSupportedModels && ! isEqual ( prevSubsetParameters . current , subsetsParameters ) ;
280+
262281 return (
263282 < Accordion >
264283 < Accordion . Title >
@@ -269,21 +288,30 @@ export const TrainingSubsets: FC<TrainingSubsetsProps> = ({ subsetsParameters, o
269288 </ Accordion . Title >
270289 < Accordion . Content >
271290 < Accordion . Description >
272- Specify the distribution of annotated samples over the training, validation and test subsets. Note:
273- items that have already been used for training will stay in the same subset even if these parameters
274- are changed.
291+ Specify the distribution of annotated samples over the training, validation and test subsets. < br />
292+ Note: items that have already been used for training will stay in the same subset even if these
293+ parameters are changed.
294+ < br />
295+ Each subset must have at least one media item.
275296 </ Accordion . Description >
276297 < Accordion . Divider marginY = { 'size-250' } />
277- < SubsetsDistribution
278- subsetParameters = { subsetsParameters }
279- subsetsDistribution = { subsetsDistribution }
280- onSubsetsDistributionChange = { setSubsetsDistribution }
281- testSubsetSize = { testSubsetSize }
282- trainingSubsetSize = { trainingSubsetSize }
283- validationSubsetSize = { validationSubsetSize }
284- onSubsetsDistributionChangeEnd = { handleUpdateSubsetsConfiguration }
285- onSubsetsDistributionReset = { handleSubsetsConfigurationReset }
286- />
298+ < View UNSAFE_className = { subsetsSizesValid ? undefined : styles . disabled } >
299+ < SubsetsDistribution
300+ subsetParameters = { subsetsParameters }
301+ subsetsDistribution = { subsetsDistribution }
302+ onSubsetsDistributionChange = { setSubsetsDistribution }
303+ testSubsetSize = { testSubsetSize }
304+ trainingSubsetSize = { trainingSubsetSize }
305+ validationSubsetSize = { validationSubsetSize }
306+ onSubsetsDistributionChangeEnd = { handleUpdateSubsetsConfiguration }
307+ onSubsetsDistributionReset = { handleSubsetsConfigurationReset }
308+ />
309+ </ View >
310+
311+ < Flex direction = { 'column' } gap = { 'size-200' } marginTop = { 'size-200' } >
312+ { ! subsetsSizesValid && < TrainingSubsetsUnavailable /> }
313+ { isChangedDistributionWarningVisible && < TrainingSubsetsChangedDistributionWarning /> }
314+ </ Flex >
287315 </ Accordion . Content >
288316 </ Accordion >
289317 ) ;
0 commit comments