from database.database import db class Training(db.Model): __tablename__ = 'training' id = db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True) exp_name = db.Column(db.String(255)) max_epoch = db.Column(db.Integer) depth = db.Column(db.Float) width = db.Column(db.Float) activation = db.Column(db.String(255)) warmup_epochs = db.Column(db.Integer) warmup_lr = db.Column(db.Float) basic_lr_per_img = db.Column(db.Float) scheduler = db.Column(db.String(255)) no_aug_epochs = db.Column(db.Integer) min_lr_ratio = db.Column(db.Float) ema = db.Column(db.Boolean) weight_decay = db.Column(db.Float) momentum = db.Column(db.Float) # input_size moved to TrainingSize table print_interval = db.Column(db.Integer) eval_interval = db.Column(db.Integer) save_history_ckpt = db.Column(db.Boolean) # test_size moved to TrainingSize table test_conf = db.Column(db.Float) nms_thre = db.Column(db.Float) multiscale_range = db.Column(db.Integer) enable_mixup = db.Column(db.Boolean) mosaic_prob = db.Column(db.Float) mixup_prob = db.Column(db.Float) hsv_prob = db.Column(db.Float) flip_prob = db.Column(db.Float) degrees = db.Column(db.Float) # mosaic_scale moved to TrainingSize table # mixup_scale moved to TrainingSize table translate = db.Column(db.Float) shear = db.Column(db.Float) training_name = db.Column(db.String(255)) project_details_id = db.Column(db.Integer, db.ForeignKey('training_project_details.id', ondelete='CASCADE'), nullable=False) seed = db.Column(db.Integer) train = db.Column(db.Integer) valid = db.Column(db.Integer) test = db.Column(db.Integer) selected_model = db.Column(db.String(255)) transfer_learning = db.Column(db.String(255)) model_upload = db.Column(db.LargeBinary) # Relationship to size configurations (3NF) size_configs = db.relationship('TrainingSize', backref='training', lazy=True, cascade='all, delete-orphan') def to_dict(self, include_sizes=True): result = { 'id': self.id, 'exp_name': self.exp_name, 'max_epoch': self.max_epoch, 'depth': self.depth, 'width': self.width, 'activation': self.activation, 'warmup_epochs': self.warmup_epochs, 'warmup_lr': self.warmup_lr, 'basic_lr_per_img': self.basic_lr_per_img, 'scheduler': self.scheduler, 'no_aug_epochs': self.no_aug_epochs, 'min_lr_ratio': self.min_lr_ratio, 'ema': self.ema, 'weight_decay': self.weight_decay, 'momentum': self.momentum, 'print_interval': self.print_interval, 'eval_interval': self.eval_interval, 'save_history_ckpt': self.save_history_ckpt, 'test_conf': self.test_conf, 'nms_thre': self.nms_thre, 'multiscale_range': self.multiscale_range, 'enable_mixup': self.enable_mixup, 'mosaic_prob': self.mosaic_prob, 'mixup_prob': self.mixup_prob, 'hsv_prob': self.hsv_prob, 'flip_prob': self.flip_prob, 'degrees': self.degrees, 'translate': self.translate, 'shear': self.shear, 'training_name': self.training_name, 'project_details_id': self.project_details_id, 'seed': self.seed, 'train': self.train, 'valid': self.valid, 'test': self.test, 'selected_model': self.selected_model, 'transfer_learning': self.transfer_learning } # Include size arrays for backwards compatibility if include_sizes: from models.TrainingSize import TrainingSize def get_size_array(size_type): sizes = TrainingSize.query.filter_by( training_id=self.id, size_type=size_type ).order_by(TrainingSize.value_order).all() return [s.value for s in sizes] if sizes else None result['input_size'] = get_size_array('input_size') result['test_size'] = get_size_array('test_size') result['mosaic_scale'] = get_size_array('mosaic_scale') result['mixup_scale'] = get_size_array('mixup_scale') return result