Исправлен расчёт +1 и -1 факторов эксперимента
This commit is contained in:
+49
-35
@@ -13,7 +13,13 @@
|
||||
from typing import List, Dict, Tuple, Optional
|
||||
import random
|
||||
import numpy as np
|
||||
|
||||
from calculations.medium import (
|
||||
calculate_medium_composition,
|
||||
convert_units,
|
||||
VOLUME_UNITS,
|
||||
MASS_UNITS
|
||||
)
|
||||
from calculations.models.project_data import FactorData
|
||||
# Типы расчёта шага
|
||||
FACTOR_TYPES = {
|
||||
'absolute': 'ед.', # абсолютный шаг
|
||||
@@ -22,41 +28,49 @@ FACTOR_TYPES = {
|
||||
|
||||
|
||||
def calculate_factor_levels(
|
||||
center_value: float,
|
||||
step_value: float,
|
||||
step_type: str,
|
||||
base_value: float = None
|
||||
) -> Tuple[float, float]:
|
||||
"""
|
||||
РАССЧИТЫВАЕТ ВЕРХНИЙ И НИЖНИЙ УРОВНИ ФАКТОРА
|
||||
|
||||
Параметры:
|
||||
center_value: нулевой уровень фактора (центральная точка)
|
||||
step_value: значение шага
|
||||
step_type: тип шага ("ед." - абсолютный, "%" - относительный)
|
||||
base_value: базовое значение для относительного шага (если None, используется center_value)
|
||||
|
||||
Возвращает:
|
||||
(high_level, low_level): верхний и нижний уровни
|
||||
|
||||
Пример:
|
||||
>>> calculate_factor_levels(100, 10, "%")
|
||||
(110.0, 90.0)
|
||||
>>> calculate_factor_levels(100, 20, "ед.")
|
||||
(120.0, 80.0)
|
||||
"""
|
||||
# Определяем абсолютное значение шага
|
||||
if step_type == "%":
|
||||
base = base_value if base_value is not None else center_value
|
||||
step_abs = center_value * step_value / 100
|
||||
else: # "ед." или "absolute"
|
||||
step_abs = step_value
|
||||
|
||||
high_level = center_value + step_abs
|
||||
low_level = center_value - step_abs
|
||||
|
||||
return high_level, low_level
|
||||
factor: 'FactorData',
|
||||
total_volume: float = 1000,
|
||||
volume_unit: str = "мл"
|
||||
) -> 'FactorData':
|
||||
"""Рассчитывает high/low уровни фактора через калькулятор сред"""
|
||||
|
||||
# Функция для расчёта количества реагента при заданном проценте
|
||||
def calc_amount(percentage: float) -> float:
|
||||
reagents = [{
|
||||
'name': factor.name,
|
||||
'percentage': max(0, percentage),
|
||||
'unit': factor.unit,
|
||||
'dilution_factor': factor.dilution_factor or 1.0
|
||||
}]
|
||||
result = calculate_medium_composition(total_volume, volume_unit, reagents)
|
||||
return result['reagents'][0]['calculated_amount']
|
||||
|
||||
|
||||
# Определяем проценты для верхнего и нижнего уровней
|
||||
if factor.step_type == "%":
|
||||
low = calc_amount(factor.percentage - factor.step) # low - нижний уровень
|
||||
high = calc_amount(factor.percentage + factor.step) # high - верхний уровень
|
||||
else: # "ед."
|
||||
# Конвертируем абсолютный шаг в проценты
|
||||
low = calc_amount(factor.percentage) - factor.step
|
||||
high = calc_amount(factor.percentage) + factor.step
|
||||
|
||||
# ВОЗВРАЩАЕМ НОВЫЙ ОБЪЕКТ FactorData
|
||||
return FactorData(
|
||||
name=factor.name,
|
||||
center=factor.center,
|
||||
low=low, # low - нижний уровень
|
||||
high=high, # high - верхний уровень
|
||||
step=factor.step,
|
||||
step_type=factor.step_type,
|
||||
unit=factor.unit,
|
||||
percentage=factor.percentage or factor.center,
|
||||
dilution_factor=factor.dilution_factor
|
||||
)
|
||||
|
||||
def calculate_all_factors_levels(factors: List['FactorData'], **kwargs) -> List['FactorData']:
|
||||
"""Рассчитывает уровни для всех факторов"""
|
||||
return [calculate_factor_levels(f, **kwargs) for f in factors]
|
||||
|
||||
def generate_factorial_design(
|
||||
factors: List[Dict],
|
||||
|
||||
@@ -52,11 +52,8 @@ def convert_units(value: float, from_unit: str, to_unit: str = None) -> float:
|
||||
units_map = MASS_UNITS
|
||||
else:
|
||||
raise ValueError(f"Неизвестная единица измерения: {from_unit}")
|
||||
print("units_map = ",units_map)
|
||||
# Конвертируем в базовую единицу (мкл для объёма, мг для массы)
|
||||
value_in_base = value * units_map[from_unit]
|
||||
print ("units_map[$from_unit]",units_map[from_unit])
|
||||
print ("value_in_base = ",value_in_base)
|
||||
# Если нужна конвертация в другую единицу
|
||||
if from_unit and to_unit in units_map:
|
||||
return value_in_base / units_map[to_unit]
|
||||
@@ -165,7 +162,6 @@ def calculate_medium_composition(
|
||||
base_unit = "мг"
|
||||
else:
|
||||
raise ValueError(f"Неизвестная единица измерения: {from_unit}")
|
||||
print ("unit = ",unit)
|
||||
# conversion_factor = reagent.get('conversion_factor', 1.0)
|
||||
dilution_factor = reagent.get('dilution_factor', 1.0)
|
||||
|
||||
@@ -174,19 +170,16 @@ def calculate_medium_composition(
|
||||
|
||||
# 1. Объём реагента в среде (исходя из процента)
|
||||
amount_in_base = (percentage / 100) * total_base
|
||||
print ("amount_in_base = ",amount_in_base)
|
||||
# 2. Применяем коэффициент конверсии
|
||||
# adjusted_amount_base = amount_in_base * conversion_factor
|
||||
|
||||
# 3. Конвертируем в нужную единицу (без учёта разбавления)
|
||||
# undiluted_amount = convert_units(adjusted_amount_base, volume_unit, unit)
|
||||
undiluted_amount = convert_units(amount_in_base, base_unit, unit)
|
||||
print ("undiluted_amount = ",undiluted_amount)
|
||||
# 4. Применяем разбавление
|
||||
if dilution_factor <= 0:
|
||||
dilution_factor = 1.0
|
||||
diluted_amount = undiluted_amount * dilution_factor
|
||||
print ("diluted_amount = ", diluted_amount)
|
||||
# 5. Для объёмных реагентов учитываем в расчёте растворителя
|
||||
if is_volume:
|
||||
reagent_volume_base = convert_units(diluted_amount, unit)
|
||||
|
||||
Reference in New Issue
Block a user