Переработан интерфейс программы, расчёт занчений в процессе исправления.
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
"""
|
||||
Расчёт питательных сред
|
||||
|
||||
Этот модуль содержит функции для расчёта состава питательных сред
|
||||
на основе процентов, коэффициентов конверсии и разбавления.
|
||||
|
||||
Основная функция: calculate_medium_composition()
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Tuple
|
||||
|
||||
# Константы для конверсии единиц измерения
|
||||
# Базовые единицы: мкл для объёма, мг для массы
|
||||
VOLUME_UNITS = {
|
||||
'нл': 0.001, # нанолитры -> микролитры
|
||||
'мкл': 1.0, # микролитры (база)
|
||||
'мл': 1000.0, # миллилитры -> микролитры
|
||||
'л': 1000000.0, # литры -> микролитры
|
||||
}
|
||||
|
||||
MASS_UNITS = {
|
||||
'нг': 0.000001, # нанограммы -> миллиграммы
|
||||
'мкг': 0.001, # микрограммы -> миллиграммы
|
||||
'мг': 1.0, # миллиграммы (база)
|
||||
'г': 1000.0, # граммы -> миллиграммы
|
||||
'кг': 1000000.0, # килограммы -> миллиграммы
|
||||
}
|
||||
|
||||
|
||||
def convert_units(value: float, from_unit: str, to_unit: str = None) -> float:
|
||||
"""
|
||||
Конвертирует значение между единицами объёма или массы
|
||||
|
||||
Параметры:
|
||||
value: числовое значение
|
||||
from_unit: исходная единица (например "мл" или "мг")
|
||||
to_unit: целевая единица (если None, конвертирует в базовую)
|
||||
|
||||
Возвращает:
|
||||
float: сконвертированное значение
|
||||
|
||||
Пример:
|
||||
>>> convert_units(100, 'мл') # конвертирует в базовую (мкл)
|
||||
100000.0
|
||||
>>> convert_units(500, 'мкл', 'мл')
|
||||
0.5
|
||||
"""
|
||||
# Определяем тип единицы (объём или масса)
|
||||
if from_unit in VOLUME_UNITS:
|
||||
units_map = VOLUME_UNITS
|
||||
elif from_unit in MASS_UNITS:
|
||||
units_map = MASS_UNITS
|
||||
else:
|
||||
raise ValueError(f"Неизвестная единица измерения: {from_unit}")
|
||||
|
||||
# Конвертируем в базовую единицу (мкл для объёма, мг для массы)
|
||||
value_in_base = value * units_map[from_unit]
|
||||
|
||||
# Если нужна конвертация в другую единицу
|
||||
if to_unit and to_unit in units_map:
|
||||
return value_in_base / units_map[to_unit]
|
||||
|
||||
return value_in_base
|
||||
|
||||
|
||||
def calculate_medium_composition(
|
||||
total_volume: float,
|
||||
volume_unit: str,
|
||||
reagents: List[Dict],
|
||||
solvent_name: str = "Вода"
|
||||
) -> Dict:
|
||||
"""
|
||||
РАССЧИТЫВАЕТ СОСТАВ ПИТАТЕЛЬНОЙ СРЕДЫ
|
||||
|
||||
Эта функция является основной для расчёта питательных сред.
|
||||
|
||||
ВХОДНЫЕ ПАРАМЕТРЫ:
|
||||
---------------
|
||||
total_volume : float
|
||||
Общий объём/количество среды (например 1000)
|
||||
|
||||
volume_unit : str
|
||||
Единица измерения общего объёма: "нл", "мкл", "мл", "л"
|
||||
|
||||
reagents : List[Dict]
|
||||
Список реагентов. Каждый реагент - словарь с ключами:
|
||||
- name (str): название реагента
|
||||
- percentage (float): процентное содержание в среде (0-100)
|
||||
- unit (str): единица измерения реагента (нг, мкг, мг, г, кг, нл, мкл, мл, л)
|
||||
- dilution_factor (float): фактор разбавления (необяз., по умолч. 1.0)
|
||||
|
||||
Пример реагента:
|
||||
{
|
||||
'name': 'Глюкоза',
|
||||
'percentage': 2.5,
|
||||
'unit': 'г',
|
||||
'dilution_factor': 1.0
|
||||
}
|
||||
|
||||
solvent_name : str, optional
|
||||
Название растворителя (по умолчанию "Вода")
|
||||
|
||||
ВОЗВРАЩАЕМЫЙ СЛОВАРЬ:
|
||||
--------------------
|
||||
{
|
||||
'total_volume': float, # Исходный объём
|
||||
'total_unit': str, # Единица измерения
|
||||
'solvent_name': str, # Название растворителя
|
||||
'solvent_volume': float, # Объём растворителя
|
||||
'solvent_percentage': float, # Процент растворителя
|
||||
'reagents': List[Dict] # Список реагентов с рассчитанными количествами
|
||||
}
|
||||
|
||||
Каждый реагент в возвращаемом списке содержит:
|
||||
- все исходные поля
|
||||
- calculated_amount (float): рассчитанное количество реагента
|
||||
- undiluted_amount (float): количество до разбавления
|
||||
- amount_unit (str): единица измерения (скопирована из unit)
|
||||
|
||||
ПРИМЕР ИСПОЛЬЗОВАНИЯ (в CLI):
|
||||
-----------------------------
|
||||
>>> reagents = [
|
||||
... {'name': 'Глюкоза', 'percentage': 2.0, 'unit': 'г', 'conversion_factor': 1.0},
|
||||
... {'name': 'Пептон', 'percentage': 1.0, 'unit': 'г', 'conversion_factor': 1.0}
|
||||
... ]
|
||||
>>> result = calculate_medium_composition(1000, 'мл', reagents)
|
||||
>>> print(f"Растворитель: {result['solvent_volume']} мл")
|
||||
Растворитель: 970.0 мл
|
||||
>>> for r in result['reagents']:
|
||||
... print(f"{r['name']}: {r['calculated_amount']} {r['unit']}")
|
||||
Глюкоза: 20.0 г
|
||||
Пептон: 10.0 г
|
||||
"""
|
||||
|
||||
# Проверка входных данных
|
||||
|
||||
if total_volume <= 0:
|
||||
raise ValueError(f"Общий объём должен быть положительным: {total_volume}")
|
||||
|
||||
if volume_unit not in VOLUME_UNITS:
|
||||
raise ValueError(f"Неизвестная единица объёма: {volume_unit}")
|
||||
|
||||
# Суммируем проценты всех реагентов
|
||||
total_percentage = sum(r.get('percentage', 0) for r in reagents)
|
||||
|
||||
if total_percentage > 100:
|
||||
raise ValueError(
|
||||
f"Сумма процентов ({total_percentage:.2f}%) превышает 100%"
|
||||
)
|
||||
|
||||
# Конвертируем общий объём в базовую единицу (мкл)
|
||||
total_base = convert_units(total_volume, volume_unit)
|
||||
|
||||
results = []
|
||||
total_diluted_volume_base = 0 # объём разбавленных реагентов в мкл
|
||||
|
||||
for reagent in reagents:
|
||||
# Извлекаем параметры с значениями по умолчанию
|
||||
percentage = reagent.get('percentage', 0)
|
||||
unit = reagent.get('unit', 'мг')
|
||||
# print ("unit = ",unit)
|
||||
# conversion_factor = reagent.get('conversion_factor', 1.0)
|
||||
dilution_factor = reagent.get('dilution_factor', 1.0)
|
||||
|
||||
# Проверяем, является ли реагент жидкостью (объём) или твёрдым веществом (масса)
|
||||
is_volume = unit in VOLUME_UNITS
|
||||
|
||||
# 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, 'мкл', unit)
|
||||
# print ("volume_unit = ",volume_unit)
|
||||
|
||||
# 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)
|
||||
total_diluted_volume_base += reagent_volume_base
|
||||
|
||||
# Сохраняем результат
|
||||
reagent_result = reagent.copy()
|
||||
reagent_result['calculated_amount'] = diluted_amount
|
||||
reagent_result['undiluted_amount'] = undiluted_amount
|
||||
reagent_result['amount_unit'] = unit
|
||||
results.append(reagent_result)
|
||||
|
||||
# Рассчитываем объём растворителя
|
||||
solvent_volume_base = total_base - total_diluted_volume_base
|
||||
if solvent_volume_base < 0:
|
||||
solvent_volume_base = 0
|
||||
|
||||
solvent_volume = convert_units(solvent_volume_base, 'мкл', volume_unit)
|
||||
solvent_percentage = 100 - total_percentage
|
||||
|
||||
return {
|
||||
'total_volume': total_volume,
|
||||
'total_unit': volume_unit,
|
||||
'solvent_name': solvent_name,
|
||||
'solvent_volume': solvent_volume,
|
||||
'solvent_percentage': solvent_percentage,
|
||||
'reagents': results
|
||||
}
|
||||
Reference in New Issue
Block a user