Теперь фактор, шаг которого равен нулю, не учитывается, но отображается отдельным столбцом с однаковым значением.

This commit is contained in:
2026-05-27 12:40:47 +05:00
parent f479674332
commit a2bc606336
3 changed files with 42 additions and 17 deletions
+8 -1
View File
@@ -53,7 +53,7 @@ def calculate_factor_levels(
else: # "ед." else: # "ед."
# Конвертируем абсолютный шаг в проценты # Конвертируем абсолютный шаг в проценты
low = calc_amount(factor.percentage) - factor.step low = calc_amount(factor.percentage) - factor.step
high = calc_amount(factor.percentage) + factor.step high = calc_amount(factor.center) + factor.step
# ВОЗВРАЩАЕМ НОВЫЙ ОБЪЕКТ FactorData # ВОЗВРАЩАЕМ НОВЫЙ ОБЪЕКТ FactorData
return FactorData( return FactorData(
@@ -72,6 +72,12 @@ def calculate_all_factors_levels(factors: List['FactorData'], **kwargs) -> List[
"""Рассчитывает уровни для всех факторов""" """Рассчитывает уровни для всех факторов"""
return [calculate_factor_levels(f, **kwargs) for f in factors] return [calculate_factor_levels(f, **kwargs) for f in factors]
def get_active_factors(factors):
return [f for f in factors if f['step'] != 0]
def get_inactive_factors(factors):
return [f for f in factors if f['step'] == 0]
def generate_factorial_design( def generate_factorial_design(
factors: List[Dict], factors: List[Dict],
center_points: int = 3, center_points: int = 3,
@@ -159,6 +165,7 @@ def generate_factorial_design(
# Добавление центральных точек # Добавление центральных точек
for i in range(center_points): for i in range(center_points):
center_experiment = {} center_experiment = {}
for j in range(k): for j in range(k):
center_experiment[f"Фактор_{j+1}"] = { center_experiment[f"Фактор_{j+1}"] = {
'coded': 0, 'coded': 0,
+26 -13
View File
@@ -28,6 +28,8 @@ from calculations.doe import (
generate_factorial_design, generate_factorial_design,
analyze_experiment, analyze_experiment,
calculate_factor_levels, calculate_factor_levels,
get_active_factors,
get_inactive_factors,
FACTOR_TYPES FACTOR_TYPES
) )
# Импорт моделей для JSON # Импорт моделей для JSON
@@ -439,7 +441,7 @@ class MainWindow(QMainWindow):
step_item = self.factors_table.item(row, 4) step_item = self.factors_table.item(row, 4)
high_item = self.factors_table.item(row, 6) high_item = self.factors_table.item(row, 6)
low_item = self.factors_table.item(row, 7) low_item = self.factors_table.item(row, 7)
unit_item = self.factors_table.item(row, 8) unit_item = self.factors_table.cellWidget(row, 8)
step_combo = self.factors_table.cellWidget(row, 5) step_combo = self.factors_table.cellWidget(row, 5)
if not all([name_item, center_item, high_item, low_item]): if not all([name_item, center_item, high_item, low_item]):
@@ -457,7 +459,7 @@ class MainWindow(QMainWindow):
'center': float(center_text), 'center': float(center_text),
'high': float(high_text), 'high': float(high_text),
'low': float(low_text), 'low': float(low_text),
'unit': unit_item.text() if unit_item else "", 'unit': unit_item.currentText() if unit_item else "г",
'step': float(step_item.text()) if step_item and step_item.text() else 0, 'step': float(step_item.text()) if step_item and step_item.text() else 0,
'step_type': step_combo.currentText() if step_combo else "ед." 'step_type': step_combo.currentText() if step_combo else "ед."
} }
@@ -527,8 +529,11 @@ class MainWindow(QMainWindow):
def _generate_design(self): def _generate_design(self):
"""Генерирует план эксперимента""" """Генерирует план эксперимента"""
factors = self._get_factors_from_table() all_factors = self._get_factors_from_table()
factors = get_active_factors(all_factors)
# Выбираем только те факторы, шаг которых не равен нулю
i_factors = get_inactive_factors(all_factors)
# Отдельно сохраняем неактивные факторы
if len(factors) == 0: if len(factors) == 0:
QMessageBox.warning(self, "Предупреждение", "Добавьте хотя бы один фактор!") QMessageBox.warning(self, "Предупреждение", "Добавьте хотя бы один фактор!")
return return
@@ -539,19 +544,17 @@ class MainWindow(QMainWindow):
center_points=self.center_points_spin.value(), center_points=self.center_points_spin.value(),
randomize=self.randomize_check.isChecked() randomize=self.randomize_check.isChecked()
) )
self.generated_design = design self.generated_design = design
n_exp = len(design) n_exp = len(design)
n_factors = len(factors) n_factors = len(factors)
n_i_factors = len(i_factors)
self.design_matrix.setRowCount(n_exp) self.design_matrix.setRowCount(n_exp)
self.design_matrix.setColumnCount(n_factors + 2) self.design_matrix.setColumnCount(n_factors + 3)
headers = [""] + [f['name'] for f in factors] + ["Тип"] headers = [f['name'] for f in factors] + [f['name'] for f in i_factors] + ["Растворитель"] +["Тип"] +["Отклик"]
self.design_matrix.setHorizontalHeaderLabels(headers) self.design_matrix.setHorizontalHeaderLabels(headers)
for exp_idx, exp in enumerate(design): for exp_idx, exp in enumerate(design):
self.design_matrix.setItem(exp_idx, 0, QTableWidgetItem(str(exp_idx + 1)))
for f_idx in range(n_factors): for f_idx in range(n_factors):
key = f"Фактор_{f_idx+1}" key = f"Фактор_{f_idx+1}"
@@ -559,7 +562,6 @@ class MainWindow(QMainWindow):
continue continue
value = exp[key]['natural'] value = exp[key]['natural']
unit = factors[f_idx]['unit'] unit = factors[f_idx]['unit']
display = self._format_number(value) display = self._format_number(value)
if unit: if unit:
display += f" {unit}" display += f" {unit}"
@@ -567,14 +569,25 @@ class MainWindow(QMainWindow):
item = QTableWidgetItem(display) item = QTableWidgetItem(display)
if exp.get('is_center', False): if exp.get('is_center', False):
item.setBackground(QColor(255, 255, 200)) item.setBackground(QColor(255, 255, 200))
self.design_matrix.setItem(exp_idx, f_idx + 1, item) self.design_matrix.setItem(exp_idx, f_idx, item)
if n_i_factors>0:
for f_idx in range(n_i_factors):
value = i_factors[f_idx]['center']
unit = i_factors[f_idx]['unit']
display = self._format_number(value)
if unit:
display += f" {unit}"
item = QTableWidgetItem(display)
item.setBackground(QColor(255, 255, 200))
self.design_matrix.setItem(exp_idx, n_factors + f_idx, item)
if exp.get('is_center', False): if exp.get('is_center', False):
type_item = QTableWidgetItem(f"Центр #{exp['center_num']}") type_item = QTableWidgetItem(f"Центр #{exp['center_num']}")
type_item.setBackground(QColor(255, 255, 200)) type_item.setBackground(QColor(255, 255, 200))
else: else:
type_item = QTableWidgetItem("Факторная") type_item = QTableWidgetItem("Факторная")
self.design_matrix.setItem(exp_idx, n_factors + 1, type_item) self.design_matrix.setItem(exp_idx, n_factors+n_i_factors, type_item)
self.design_matrix.resizeColumnsToContents() self.design_matrix.resizeColumnsToContents()
@@ -600,7 +613,7 @@ class MainWindow(QMainWindow):
self.results_table.setHorizontalHeaderLabels(["№ опыта", "Результат"]) self.results_table.setHorizontalHeaderLabels(["№ опыта", "Результат"])
for i in range(n_experiments): for i in range(n_experiments):
self.results_table.setItem(i, 0, QTableWidgetItem(str(i + 1))) self.results_table.setItem(i, 0, QTableWidgetItem(str(i)))
def _export_design_csv(self): def _export_design_csv(self):
"""Экспортирует матрицу планирования в CSV""" """Экспортирует матрицу планирования в CSV"""
+5
View File
@@ -1,6 +1,11 @@
# main.py # main.py
""" """
Биохимический помощник - точка входа в приложение Биохимический помощник - точка входа в приложение
TODO:
- Добавить информацию о количестве раствора в DOE
- Не считать фактор, если его шаг 0 ОК
- Добавить столбец в матрицу планирования с информацией о количестве добавленного растворителя, учитывая все реагенты
- Начать делать анализ
""" """
import sys import sys