Добавленна поддержка отображения, сохранинения, и загрузки растворителя во вкладке факторнго эксперимента. Убрана галочка рАндомизировать по умолчанию
This commit is contained in:
Binary file not shown.
@@ -7,7 +7,13 @@ from dataclasses import dataclass, asdict
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
|
||||
VERSION="alpha_0.3"
|
||||
"""
|
||||
Условно
|
||||
0.1 - Разработка калькулятора сред
|
||||
0.2 - Разработка факторов эксперимента
|
||||
0.3 - разработка матрицы планирования
|
||||
"""
|
||||
@dataclass
|
||||
class ReagentData:
|
||||
"""Данные реагента"""
|
||||
@@ -111,7 +117,7 @@ class ProjectData:
|
||||
project_name: str
|
||||
created_at: str
|
||||
modified_at: str
|
||||
version: str = "1.0"
|
||||
version: str = VERSION
|
||||
|
||||
# Данные калькулятора сред
|
||||
medium_total_volume: float = 1000.0
|
||||
@@ -120,6 +126,9 @@ class ProjectData:
|
||||
medium_reagents: List[ReagentData] = None
|
||||
|
||||
# Данные эксперимента
|
||||
experiment_total_volume: float = 1000.0
|
||||
experiment_volume_unit: str = "мл"
|
||||
experiment_solvent: str = "Вода"
|
||||
experiment_factors: List[FactorData] = None
|
||||
experiment_responses: List[ResponseData] = None
|
||||
experiment_center_points: int = 3
|
||||
@@ -150,6 +159,9 @@ class ProjectData:
|
||||
'reagents': [r.to_dict() for r in self.medium_reagents]
|
||||
},
|
||||
'experiment': {
|
||||
'total_volume': self.medium_total_volume,
|
||||
'volume_unit': self.medium_volume_unit,
|
||||
'solvent': self.medium_solvent,
|
||||
'factors': [f.to_dict() for f in self.experiment_factors],
|
||||
'responses': [r.to_dict() for r in self.experiment_responses],
|
||||
'center_points': self.experiment_center_points,
|
||||
@@ -175,6 +187,9 @@ class ProjectData:
|
||||
medium_volume_unit=medium.get('volume_unit', 'мл'),
|
||||
medium_solvent=medium.get('solvent', 'Вода'),
|
||||
medium_reagents=[ReagentData.from_dict(r) for r in medium.get('reagents', [])],
|
||||
experiment_total_volume=experiment.get('total_volume', 1000.0),
|
||||
experiment_volume_unit=experiment.get('volume_unit', 'мл'),
|
||||
experiment_solvent=experiment.get('solvent', 'Вода'),
|
||||
experiment_factors=[FactorData.from_dict(f) for f in experiment.get('factors', [])],
|
||||
experiment_responses=[ResponseData.from_dict(r) for r in experiment.get('responses', [])],
|
||||
experiment_center_points=experiment.get('center_points', 3),
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
"""
|
||||
Единый графический интерфейс для калькулятора сред и DoE
|
||||
"""
|
||||
from theme import Colors, Fonts, Spacing, ButtonStyles, get_full_stylesheet, apply_theme
|
||||
from theme import Colors, Fonts, Spacing, ButtonStyles, get_full_stylesheet, apply_theme, TitleStyles
|
||||
import sys
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QTabWidget, QGroupBox, QLabel, QPushButton, QTableWidget,
|
||||
@@ -86,12 +85,8 @@ class MainWindow(QMainWindow):
|
||||
|
||||
# Заголовок
|
||||
title = QLabel("Цифровой помощник биохимика")
|
||||
title_font = QFont()
|
||||
title_font.setPointSize(18)
|
||||
title_font.setBold(True)
|
||||
title.setFont(title_font)
|
||||
title.setObjectName("mainTitle") # Стиль подтянется из theme
|
||||
title.setAlignment(Qt.AlignCenter)
|
||||
title.setStyleSheet("color: #2c3e50; padding: 10px;")
|
||||
layout.addWidget(title)
|
||||
|
||||
# Вкладки
|
||||
@@ -275,7 +270,7 @@ class MainWindow(QMainWindow):
|
||||
)
|
||||
self.info_label.setText(solvent_text)
|
||||
self.info_label.setStyleSheet("background-color: #d5f5e3; padding: 8px; border-radius: 5px;")
|
||||
|
||||
print(result)
|
||||
# Сохраняем результаты для передачи в DoE
|
||||
self.last_medium_result = result
|
||||
|
||||
@@ -329,23 +324,47 @@ class MainWindow(QMainWindow):
|
||||
factors_layout.addLayout(btn_layout)
|
||||
factors_box.setLayout(factors_layout)
|
||||
layout.addWidget(factors_box)
|
||||
|
||||
|
||||
# Настройки эксперимента
|
||||
settings_box = QGroupBox("Настройки эксперимента")
|
||||
settings_layout = QHBoxLayout()
|
||||
|
||||
settings_layout.addWidget(QLabel("Центральных точек:"))
|
||||
settings_layout = QVBoxLayout()
|
||||
|
||||
# Параметры среды (из калькулятора)
|
||||
env_layout = QHBoxLayout()
|
||||
env_layout.addWidget(QLabel("Общий объём:"))
|
||||
self.exp_total_volume = QDoubleSpinBox()
|
||||
self.exp_total_volume.setRange(0.001, 1000000)
|
||||
self.exp_total_volume.setValue(100)
|
||||
self.exp_total_volume.setSuffix(" ")
|
||||
env_layout.addWidget(self.exp_total_volume)
|
||||
|
||||
self.exp_volume_unit = QComboBox()
|
||||
self.exp_volume_unit.addItems(["мл", "л", "мкл", "нл"])
|
||||
self.exp_volume_unit.setCurrentText("мл")
|
||||
env_layout.addWidget(self.exp_volume_unit)
|
||||
|
||||
env_layout.addSpacing(20)
|
||||
env_layout.addWidget(QLabel("Растворитель:"))
|
||||
self.exp_solvent = QLineEdit("Вода")
|
||||
env_layout.addWidget(self.exp_solvent)
|
||||
env_layout.addStretch()
|
||||
settings_layout.addLayout(env_layout)
|
||||
|
||||
# Настройки эксперимента
|
||||
exp_layout = QHBoxLayout()
|
||||
exp_layout.addWidget(QLabel("Центральных точек:"))
|
||||
self.center_points_spin = QSpinBox()
|
||||
self.center_points_spin.setRange(0, 10)
|
||||
self.center_points_spin.setValue(3)
|
||||
settings_layout.addWidget(self.center_points_spin)
|
||||
settings_layout.addSpacing(20)
|
||||
|
||||
self.randomize_check = QCheckBox("Рэндомизировать порядок")
|
||||
self.randomize_check.setChecked(True)
|
||||
settings_layout.addWidget(self.randomize_check)
|
||||
settings_layout.addStretch()
|
||||
exp_layout.addWidget(self.center_points_spin)
|
||||
exp_layout.addSpacing(20)
|
||||
|
||||
self.randomize_check = QCheckBox("Рандомизировать порядок")
|
||||
self.randomize_check.setChecked(False)
|
||||
exp_layout.addWidget(self.randomize_check)
|
||||
exp_layout.addStretch()
|
||||
settings_layout.addLayout(exp_layout)
|
||||
|
||||
settings_box.setLayout(settings_layout)
|
||||
layout.addWidget(settings_box)
|
||||
|
||||
@@ -414,7 +433,11 @@ class MainWindow(QMainWindow):
|
||||
|
||||
# Очищаем таблицу факторов
|
||||
self.factors_table.setRowCount(0)
|
||||
|
||||
|
||||
|
||||
self.exp_total_volume.setValue(result['total_volume'])
|
||||
self.exp_volume_unit.setCurrentText(result['total_unit'])
|
||||
self.exp_solvent.setText(result['solvent_name'])
|
||||
for reagent in result['reagents']:
|
||||
name = reagent['name']
|
||||
if reagent.get('dilution_factor', 1.0) != 1.0:
|
||||
@@ -906,7 +929,12 @@ class MainWindow(QMainWindow):
|
||||
self.reagents_table.setItem(row, 4, QTableWidgetItem(str(reagent.dilution_factor)))
|
||||
self.reagents_table.setItem(row, 5, QTableWidgetItem(""))
|
||||
|
||||
|
||||
|
||||
# Применяем данные факторов эксперимента
|
||||
self.exp_total_volume.setValue(project.experiment_total_volume)
|
||||
self.exp_volume_unit.setCurrentText(project.experiment_volume_unit)
|
||||
self.exp_solvent.setText(project.experiment_solvent)
|
||||
self.factors_table.setRowCount(0)
|
||||
for factor in project.experiment_factors:
|
||||
if factor.percentage is not None:
|
||||
|
||||
@@ -14,6 +14,7 @@ from PyQt5.QtWidgets import QApplication
|
||||
from gui import MainWindow
|
||||
from theme import Fonts, setup_emoji_support
|
||||
|
||||
|
||||
# Добавляем текущую директорию в путь
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class Colors:
|
||||
"""Цветовая палитра приложения"""
|
||||
|
||||
# Основные цвета (Primary)
|
||||
PRIMARY = "#999999" # Синий - основной акцент
|
||||
PRIMARY = "#3498db" # Синий - основной акцент
|
||||
PRIMARY_DARK = "#777777" # Тёмно-синий (наведение)
|
||||
PRIMARY_LIGHT = "#5dade2" # Светло-синий
|
||||
PRIMARY_BG = "#ebf5fb" # Фоновый для primary элементов
|
||||
@@ -69,6 +69,9 @@ class Colors:
|
||||
BORDER_DEFAULT = GRAY_400
|
||||
BORDER_DARK = GRAY_600
|
||||
|
||||
# Цвет для заголовка
|
||||
TITLE_COLOR = "#2c3e50"
|
||||
|
||||
# Прозрачность
|
||||
TRANSPARENT = "transparent"
|
||||
OVERLAY = "rgba(0, 0, 0, 0.5)"
|
||||
@@ -100,7 +103,7 @@ class Fonts:
|
||||
def get_title_font(cls):
|
||||
"""Возвращает шрифт для заголовков"""
|
||||
font = QFont(cls.FAMILY_PRIMARY.split(',')[0])
|
||||
font.setPointSize(cls.SIZE_XLARGE)
|
||||
font.setPointSize(cls.SIZE_XXLARGE)
|
||||
font.setBold(True)
|
||||
return font
|
||||
|
||||
@@ -192,6 +195,21 @@ class Spacing:
|
||||
BORDER_RADIUS_LG = 8
|
||||
BORDER_RADIUS_XL = 12
|
||||
|
||||
|
||||
|
||||
|
||||
# ========== СТИЛЬ ЗАГОЛОВКА ==========
|
||||
|
||||
class TitleStyles:
|
||||
@staticmethod
|
||||
def main_title():
|
||||
return f"""
|
||||
color: {Colors.TITLE_COLOR};
|
||||
padding: {Spacing.XL}px;
|
||||
font-size: {Fonts.SIZE_XLARGE}px;
|
||||
font-weight: {Fonts.WEIGHT_BOLD};
|
||||
"""
|
||||
|
||||
# ========== СТИЛИ КНОПОК ==========
|
||||
class ButtonStyles:
|
||||
"""Стили для разных типов кнопок"""
|
||||
@@ -464,9 +482,10 @@ class GroupBoxStyles:
|
||||
font-size: {Fonts.SIZE_MEDIUM}px;
|
||||
}}
|
||||
QGroupBox::title {{
|
||||
|
||||
subcontrol-origin: margin;
|
||||
left: {Spacing.LG}px;
|
||||
padding: 0 {Spacing.MD}px;
|
||||
padding: 10 {Spacing.MD}px;
|
||||
color: {Colors.INFO};
|
||||
}}
|
||||
"""
|
||||
@@ -485,7 +504,7 @@ class GroupBoxStyles:
|
||||
QGroupBox::title {{
|
||||
subcontrol-origin: margin;
|
||||
left: {Spacing.LG}px;
|
||||
padding: 0 {Spacing.MD}px;
|
||||
padding: 10 {Spacing.MD}px;
|
||||
color: {Colors.PRIMARY};
|
||||
}}
|
||||
"""
|
||||
@@ -566,8 +585,29 @@ def get_full_stylesheet():
|
||||
"""
|
||||
Возвращает полную таблицу стилей для приложения
|
||||
"""
|
||||
|
||||
return f"""
|
||||
/* СТИЛИ ДЛЯ ВСЕХ КНОПОК ПО УМОЛЧАНИЮ */
|
||||
QPushButton {{
|
||||
background-color: {Colors.PRIMARY};
|
||||
color: {Colors.TEXT_ON_PRIMARY};
|
||||
border: none;
|
||||
border-radius: {Spacing.BORDER_RADIUS_MD}px;
|
||||
padding: {Spacing.SM}px {Spacing.LG}px;
|
||||
font-weight: {Fonts.WEIGHT_SEMIBOLD};
|
||||
font-size: {Fonts.SIZE_NORMAL}px;
|
||||
}}
|
||||
QPushButton:hover {{
|
||||
background-color: {Colors.PRIMARY_LIGHT};
|
||||
}}
|
||||
QPushButton:pressed {{
|
||||
background-color: {Colors.PRIMARY_DARK};
|
||||
}}
|
||||
|
||||
/* Глобальные стили */
|
||||
QLabel#mainTitle {{
|
||||
{TitleStyles.main_title()}
|
||||
}}
|
||||
QMainWindow {{
|
||||
background-color: {Colors.GRAY_200};
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user