Files
help_lab/model.py
T

151 lines
6.6 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
VOLUME_UNITS = {
'нл': 0.001, # 1 нл = 0.001 мкл
'мкл': 1.0, # базовая единица объёма
'мл': 1000.0, # 1 мл = 1000 мкл
'л': 1000000.0 # 1 л = 1 000 000 мкл
}
MASS_UNITS = {
'нг': 0.000001, # 1 нг = 0.001 мкг
'мкг': 0.001, # базовая единица массы
'мг': 1.0, # 1 мг = 1000 мкг
'г': 1000.0, # 1 г = 1 000 000 мкг
'кг': 1000000.0 # 1 кг = 1 000 000 000 мкг
}
class Reagent:
def __init__(self, name: str, percentage: float, unit: str, conversion_factor: float = 1.0):
self.name = name
self.percentage = percentage
self.unit = unit
self.conversion_factor = conversion_factor
def to_dict(self):
"""Преобразует реагент в словарь для сохранения в JSON"""
return {
'name': self.name,
'percentage': self.percentage,
'unit': self.unit,
'conversion_factor': self.conversion_factor
}
@classmethod
def from_dict(cls, data):
"""Создаёт реагент из словаря, загруженного из JSON"""
return cls(
name=data['name'],
percentage=data['percentage'],
unit=data['unit'],
conversion_factor=data['conversion_factor']
)
class Model:
def __init__(self):
self.reagents = []
self.total_amount = 1000.0 # по умолчанию 1000 мл
self.amount_unit = "мл"
self.solvent = "Вода"
def convert_amount(self, amount_mkl_or_mkg: float, target_unit: str, is_volume: bool) -> float:
"""
Пересчитывает количество из базовых единиц (мкл/мкг) в целевую единицу.
Args:
amount_mkl_or_mkg: количество в базовых единицах (мкл или мкг)
target_unit: целевая единица измерения
is_volume: True — объём, False — масса
Returns:
Количество в целевой единице
"""
if is_volume:
conversion_factor = VOLUME_UNITS.get(target_unit, 1.0)
else:
conversion_factor = MASS_UNITS.get(target_unit, 1.0)
return amount_mkl_or_mkg / conversion_factor
def add_reagent(self, reagent: Reagent):
"""Добавляет реагент в список"""
self.reagents.append(reagent)
def calculate_amounts(self) -> list:
"""
Рассчитывает абсолютное количество каждого реагента с учётом единиц измерения.
Возвращает список количеств в единицах измерения реагента.
"""
results = []
for reagent in self.reagents:
# Базовый расчёт в процентах от общего количества
base_amount = (reagent.percentage / 100) * self.total_amount
# Определяем, объём или масса
is_volume = reagent.unit in VOLUME_UNITS
is_mass = reagent.unit in MASS_UNITS
if is_volume:
# Переводим общее количество среды в мкл для расчёта
total_in_mkl = self.total_amount * VOLUME_UNITS[self.amount_unit]
# Расчёт в мкл
amount_in_mkl = (reagent.percentage / 100) * total_in_mkl
# Переводим обратно в единицы реагента
final_amount = self.convert_amount(amount_in_mkl, reagent.unit, True)
elif is_mass:
# Переводим общее количество среды в мкг для расчёта (если среда в единицах объёма,
# предполагаем плотность = 1 г/мл)
if self.amount_unit in VOLUME_UNITS:
# Предполагаем плотность 1 г/мл: 1 мл ≈ 1 г
total_in_mkg = self.total_amount * VOLUME_UNITS[self.amount_unit] # в мкл
total_in_mkg *= 1000 # переводим в мкг (1 мкл воды ≈ 1 мкг)
else:
total_in_mkg = self.total_amount * MASS_UNITS[self.amount_unit]
# Расчёт в мкг
amount_in_mkg = (reagent.percentage / 100) * total_in_mkg
# Переводим в единицы реагента
final_amount = self.convert_amount(amount_in_mkg, reagent.unit, False)
else:
# Если единица неизвестна, возвращаем базовый расчёт
final_amount = base_amount
results.append(final_amount)
return results
def get_solvent_info(self) -> dict:
"""Возвращает информацию о растворителе: процент и количество"""
total_percentage = sum(r.percentage for r in self.reagents)
solvent_percentage = max(0, 100 - total_percentage) # не меньше 0%
solvent_amount = (solvent_percentage / 100) * self.total_amount
return {
'percentage': solvent_percentage,
'amount': solvent_amount,
'unit': self.amount_unit
}
def save_to_file(self, filename: str):
"""Сохраняет состав среды в JSON‑файл"""
data = {
'total_amount': self.total_amount,
'amount_unit': self.amount_unit,
'solvent': self.solvent,
'reagents': [r.to_dict() for r in self.reagents]
}
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def load_from_file(self, filename: str):
"""Загружает состав среды из JSON‑файла"""
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
# Восстанавливаем данные модели
self.total_amount = data['total_amount']
self.amount_unit = data['amount_unit']
self.solvent = data['solvent']
# Очищаем и заполняем список реагентов
self.reagents.clear()
for reagent_data in data['reagents']:
reagent = Reagent.from_dict(reagent_data)
self.reagents.append(reagent)