Теперь подсветка факторов эксперимента подсвечиваются соответственно значениям: + зелёным - красным, 0 (факторы с шагом в 0) - светлосерым. Убран лишний столбец в матрице факторного эксперимента
This commit is contained in:
@@ -553,13 +553,12 @@ class MainWindow(QMainWindow):
|
||||
"""Генерирует план эксперимента"""
|
||||
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 not factors:
|
||||
QMessageBox.warning(self, "Предупреждение", "Добавьте хотя бы один фактор!")
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
design = generate_factorial_design(
|
||||
factors=factors,
|
||||
@@ -567,74 +566,13 @@ class MainWindow(QMainWindow):
|
||||
randomize=self.randomize_check.isChecked()
|
||||
)
|
||||
self.generated_design = design
|
||||
|
||||
n_exp = len(design)
|
||||
n_factors = len(factors)
|
||||
n_i_factors = len(i_factors)
|
||||
solvent_name = self.exp_solvent.text()
|
||||
total_volume = self.exp_total_volume.value()
|
||||
solvent_unit = self.exp_volume_unit.currentText()
|
||||
self.design_matrix.setRowCount(n_exp)
|
||||
self.design_matrix.setColumnCount(n_factors + 4)
|
||||
headers = [f['name'] for f in factors] + [f['name'] for f in i_factors] + [solvent_name] +["Тип"] +["Отклик"]
|
||||
self.design_matrix.setHorizontalHeaderLabels(headers)
|
||||
|
||||
for exp_idx, exp in enumerate(design):
|
||||
solvent = convert_units(total_volume,solvent_unit)
|
||||
for f_idx in range(n_factors):
|
||||
key = f"Фактор_{f_idx+1}"
|
||||
if key not in exp:
|
||||
continue
|
||||
value = exp[key]['natural']
|
||||
unit = factors[f_idx]['unit']
|
||||
solvent -= convert_units(value,unit)
|
||||
display = self._format_number(value)
|
||||
if unit:
|
||||
display += f" {unit}"
|
||||
|
||||
item = QTableWidgetItem(display)
|
||||
if exp.get('is_center', False):
|
||||
item.setBackground(QColor(255, 255, 200))
|
||||
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)
|
||||
self._fill_design_matrix(design, factors, i_factors)
|
||||
|
||||
item.setBackground(QColor(255, 255, 200))
|
||||
self.design_matrix.setItem(exp_idx, n_factors + f_idx, item)
|
||||
solvent = convert_units(solvent, "мкл", solvent_unit)
|
||||
display = self._format_number(solvent)
|
||||
if solvent_unit:
|
||||
display += f" {solvent_unit}"
|
||||
item = QTableWidgetItem(display)
|
||||
self.design_matrix.setItem(exp_idx, n_factors+n_i_factors, item)
|
||||
if exp.get('is_center', False):
|
||||
type_item = QTableWidgetItem(f"Центр #{exp['center_num']}")
|
||||
type_item.setBackground(QColor(255, 255, 200))
|
||||
else:
|
||||
type_item = QTableWidgetItem("Факторная")
|
||||
self.design_matrix.setItem(exp_idx, n_factors+n_i_factors + 1, type_item)
|
||||
|
||||
self.design_matrix.resizeColumnsToContents()
|
||||
|
||||
n_factorial = 2 ** n_factors
|
||||
n_center = self.center_points_spin.value()
|
||||
self.design_info.setText(
|
||||
f"📊 Факторных точек: {n_factorial}, Центральных: {n_center}, Всего: {n_exp}"
|
||||
)
|
||||
|
||||
self.export_csv_btn.setEnabled(True)
|
||||
self._setup_results_table(n_exp)
|
||||
|
||||
QMessageBox.information(self, "Успех",
|
||||
f"Сгенерирован план для {n_factors} факторов ({n_exp} опытов)")
|
||||
QMessageBox.information(self, "Успех", f"Сгенерирован план для {len(factors)} факторов ({len(design)} опытов)")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Ошибка", f"Ошибка генерации плана: {str(e)}")
|
||||
|
||||
|
||||
def _setup_results_table(self, n_experiments: int):
|
||||
"""Настраивает таблицу результатов для ввода данных"""
|
||||
@@ -978,47 +916,19 @@ class MainWindow(QMainWindow):
|
||||
"""Обновляет отображение матрицы планирования"""
|
||||
if not self.generated_design:
|
||||
return
|
||||
|
||||
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)
|
||||
|
||||
self._fill_design_matrix(self.generated_design, factors, i_factors)
|
||||
|
||||
n_exp = len(self.generated_design)
|
||||
n_factors = len(factors)
|
||||
|
||||
self.design_matrix.setRowCount(n_exp)
|
||||
self.design_matrix.setColumnCount(n_factors + 2)
|
||||
headers = ["№"] + [f['name'] for f in factors] + ["Тип"]
|
||||
self.design_matrix.setHorizontalHeaderLabels(headers)
|
||||
|
||||
for exp_idx, exp in enumerate(self.generated_design):
|
||||
self.design_matrix.setItem(exp_idx, 0, QTableWidgetItem(str(exp_idx + 1)))
|
||||
|
||||
for f_idx in range(n_factors):
|
||||
key = f"Фактор_{f_idx + 1}"
|
||||
if key not in exp:
|
||||
continue
|
||||
value = exp[key]['natural']
|
||||
unit = factors[f_idx]['unit']
|
||||
|
||||
display = self._format_number(value)
|
||||
if unit:
|
||||
display += f" {unit}"
|
||||
|
||||
item = QTableWidgetItem(display)
|
||||
if exp.get('is_center', False):
|
||||
item.setBackground(QColor(255, 255, 200))
|
||||
self.design_matrix.setItem(exp_idx, f_idx + 1, item)
|
||||
|
||||
if exp.get('is_center', False):
|
||||
type_item = QTableWidgetItem(f"Центр #{exp['center_num']}")
|
||||
type_item.setBackground(QColor(255, 255, 200))
|
||||
else:
|
||||
type_item = QTableWidgetItem("Факторная")
|
||||
self.design_matrix.setItem(exp_idx, n_factors + 1, type_item)
|
||||
|
||||
self.design_matrix.resizeColumnsToContents()
|
||||
|
||||
|
||||
if hasattr(self, 'export_csv_btn'):
|
||||
self.export_csv_btn.setEnabled(True)
|
||||
|
||||
|
||||
n_factorial = 2 ** n_factors
|
||||
n_center = self.center_points_spin.value()
|
||||
self.design_info.setText(
|
||||
@@ -1027,6 +937,74 @@ class MainWindow(QMainWindow):
|
||||
self._setup_results_table(n_exp)
|
||||
|
||||
# ========== ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ ==========
|
||||
|
||||
def _fill_design_matrix(self, design, factors, i_factors):
|
||||
"""Заполняет матрицу планирования (общая логика)"""
|
||||
n_exp = len(design)
|
||||
n_factors = len(factors)
|
||||
n_i_factors = len(i_factors)
|
||||
solvent_name = self.exp_solvent.text()
|
||||
total_volume = self.exp_total_volume.value()
|
||||
solvent_unit = self.exp_volume_unit.currentText()
|
||||
|
||||
self.design_matrix.setRowCount(n_exp)
|
||||
self.design_matrix.setColumnCount(n_factors + n_i_factors + 3)
|
||||
headers = [f['name'] for f in factors] + [f['name'] for f in i_factors] + [solvent_name] + ["Тип"] + ["Отклик"]
|
||||
self.design_matrix.setHorizontalHeaderLabels(headers)
|
||||
|
||||
for exp_idx, exp in enumerate(design):
|
||||
remaining = convert_units(total_volume, solvent_unit)
|
||||
|
||||
# Активные факторы
|
||||
for f_idx in range(n_factors):
|
||||
value = exp[f"Фактор_{f_idx+1}"]['natural']
|
||||
unit = factors[f_idx]['unit']
|
||||
remaining -= convert_units(value, unit)
|
||||
item = self._create_item(value, unit, exp.get('is_center', False))
|
||||
if value == factors[f_idx]['high']:
|
||||
item.setBackground(QColor(200, 250, 200))
|
||||
elif value ==factors[f_idx]['low']:
|
||||
item.setBackground(QColor(250, 200, 200))
|
||||
else:
|
||||
item.setBackground(QColor(230, 230, 230))
|
||||
self.design_matrix.setItem(exp_idx, f_idx, item)
|
||||
|
||||
# Неактивные факторы
|
||||
for f_idx in range(n_i_factors):
|
||||
value = i_factors[f_idx]['center']
|
||||
unit = i_factors[f_idx]['unit']
|
||||
remaining -= convert_units(value, unit)
|
||||
item = self._create_item(value, unit, True)
|
||||
item.setBackground(QColor(230, 230, 230))
|
||||
self.design_matrix.setItem(exp_idx, n_factors + f_idx, item)
|
||||
|
||||
# Растворитель
|
||||
remaining = convert_units(remaining, 'мкл', solvent_unit)
|
||||
item = self._create_item(remaining, solvent_unit, False)
|
||||
item.setBackground(QColor(200, 200, 255))
|
||||
self.design_matrix.setItem(exp_idx, n_factors + n_i_factors, item)
|
||||
|
||||
# Тип опыта
|
||||
type_item = QTableWidgetItem(f"Центр #{exp['center_num']}" if exp.get('is_center') else "Факторная")
|
||||
if exp.get('is_center'):
|
||||
type_item.setBackground(QColor(200, 200, 200))
|
||||
self.design_matrix.setItem(exp_idx, n_factors + n_i_factors + 1, type_item)
|
||||
|
||||
# Отклик
|
||||
self.design_matrix.setItem(exp_idx, n_factors + n_i_factors + 2, QTableWidgetItem(""))
|
||||
|
||||
self.design_matrix.resizeColumnsToContents()
|
||||
|
||||
def _create_item(self, value, unit, is_center):
|
||||
"""Создаёт QTableWidgetItem с форматированием"""
|
||||
display = self._format_number(value)
|
||||
if unit:
|
||||
display += f" {unit}"
|
||||
item = QTableWidgetItem(display)
|
||||
if is_center:
|
||||
item.setBackground(QColor(255, 255, 200))
|
||||
return item
|
||||
|
||||
|
||||
def _format_number(self, value: float) -> str:
|
||||
"""Форматирует число для отображения"""
|
||||
|
||||
Reference in New Issue
Block a user