Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -682,6 +682,7 @@ def view_image():
|
|
682 |
|
683 |
|
684 |
|
|
|
685 |
# Профиль питательного раствора (ppm = мг/литр)
|
686 |
TOMATO_PROFILE = {
|
687 |
'N (NO3-)': 200,
|
@@ -717,29 +718,42 @@ fertilizers_db = {
|
|
717 |
}
|
718 |
}
|
719 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
720 |
class NutrientCalculator:
|
721 |
def __init__(self, volume_liters=1.0):
|
722 |
self.volume = volume_liters # Объем раствора в литрах
|
723 |
self.results = {}
|
724 |
-
|
|
|
725 |
def calculate(self, profile):
|
726 |
"""Основной расчет"""
|
727 |
-
|
728 |
self._calc_single_component(profile)
|
729 |
-
# Затем комплексные удобрения
|
730 |
self._calc_complex(profile)
|
731 |
return self.results
|
732 |
|
|
|
|
|
|
|
|
|
|
|
733 |
def _calc_single_component(self, profile):
|
734 |
-
"""Расчет для простых солей"""
|
735 |
-
# Сульфат магния (Mg + S)
|
736 |
if 'Mg' in profile and 'S' in profile:
|
737 |
mg_needed = profile['Mg']
|
738 |
s_needed = profile['S']
|
739 |
|
740 |
-
# Вычисляем через Mg
|
741 |
mg_grams = (mg_needed * self.volume) / (fertilizers_db["Сульфат магния"]["Mg"] * 1000)
|
742 |
-
# Пересчитываем сколько S мы получим
|
743 |
s_from_mg = mg_grams * fertilizers_db["Сульфат магния"]["S"] * 1000 / self.volume
|
744 |
|
745 |
self.results["Сульфат магния"] = {
|
@@ -748,10 +762,10 @@ class NutrientCalculator:
|
|
748 |
'внесет S': round(s_from_mg, 1)
|
749 |
}
|
750 |
profile['S'] -= s_from_mg
|
|
|
|
|
751 |
|
752 |
def _calc_complex(self, profile):
|
753 |
-
"""Расчет для комплексных удобрений"""
|
754 |
-
# Кальциевая селитра (Ca + NO3)
|
755 |
if 'Ca' in profile and 'N (NO3-)' in profile:
|
756 |
ca_grams = (profile['Ca'] * self.volume) / (fertilizers_db["Кальциевая селитра"]["Ca"] * 1000)
|
757 |
no3_from_ca = ca_grams * fertilizers_db["Кальциевая селитра"]["N (NO3-)"] * 1000 / self.volume
|
@@ -762,8 +776,9 @@ class NutrientCalculator:
|
|
762 |
'внесет NO3': round(no3_from_ca, 1)
|
763 |
}
|
764 |
profile['N (NO3-)'] -= no3_from_ca
|
|
|
|
|
765 |
|
766 |
-
# Монофосфат калия (P + K)
|
767 |
if 'P' in profile and 'K' in profile:
|
768 |
p_grams = (profile['P'] * self.volume) / (fertilizers_db["Монофосфат калия"]["P"] * 1000)
|
769 |
k_from_p = p_grams * fertilizers_db["Монофосфат калия"]["K"] * 1000 / self.volume
|
@@ -774,8 +789,9 @@ class NutrientCalculator:
|
|
774 |
'внесет K': round(k_from_p, 1)
|
775 |
}
|
776 |
profile['K'] -= k_from_p
|
|
|
|
|
777 |
|
778 |
-
# Калий азотнокислый (K + NO3)
|
779 |
if 'K' in profile and profile['K'] > 0 and 'N (NO3-)' in profile:
|
780 |
k_grams = (profile['K'] * self.volume) / (fertilizers_db["Калий азотнокислый"]["K"] * 1000)
|
781 |
no3_from_k = k_grams * fertilizers_db["Калий азотнокислый"]["N (NO3-)"] * 1000 / self.volume
|
@@ -786,8 +802,9 @@ class NutrientCalculator:
|
|
786 |
'внесет NO3': round(no3_from_k, 1)
|
787 |
}
|
788 |
profile['N (NO3-)'] -= no3_from_k
|
|
|
|
|
789 |
|
790 |
-
# Аммоний азотнокислый (NH4 + NO3)
|
791 |
if 'N (NH4+)' in profile and profile['N (NH4+)'] > 0:
|
792 |
nh4_grams = (profile['N (NH4+)'] * self.volume) / (fertilizers_db["Аммоний азотнокислый"]["N (NH4+)"] * 1000)
|
793 |
no3_from_nh4 = nh4_grams * fertilizers_db["Аммоний азотнокислый"]["N (NO3-)"] * 1000 / self.volume
|
@@ -798,17 +815,26 @@ class NutrientCalculator:
|
|
798 |
'внесет NO3': round(no3_from_nh4, 1)
|
799 |
}
|
800 |
profile['N (NO3-)'] -= no3_from_nh4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
801 |
|
802 |
def print_report(self, profile):
|
803 |
"""Красивый вывод результатов"""
|
804 |
print("\n" + "="*50)
|
805 |
print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
|
806 |
print("="*50)
|
807 |
-
|
808 |
print("\nЦЕЛЕВОЙ ПРОФИЛЬ (ppm):")
|
809 |
print(tabulate([(k, v) for k, v in profile.items()],
|
810 |
headers=["Элемент", "Концентрация"]))
|
811 |
-
|
812 |
print("\nРЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:")
|
813 |
table = []
|
814 |
for fert, data in self.results.items():
|
@@ -820,8 +846,14 @@ class NutrientCalculator:
|
|
820 |
])
|
821 |
print(tabulate(table,
|
822 |
headers=["Удобрение", "Граммы", "Миллиграммы", "Дополнительно"]))
|
823 |
-
|
824 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
825 |
|
826 |
# Пример использования
|
827 |
calc = NutrientCalculator(volume_liters=10) # Для 10 литров раствора
|
|
|
682 |
|
683 |
|
684 |
|
685 |
+
|
686 |
# Профиль питательного раствора (ppm = мг/литр)
|
687 |
TOMATO_PROFILE = {
|
688 |
'N (NO3-)': 200,
|
|
|
718 |
}
|
719 |
}
|
720 |
|
721 |
+
# Приблизительный вклад элементов в электропроводимость, мСм/см на 100 ppm
|
722 |
+
# Источник: усреднённые данные по литературе (можно адаптировать)
|
723 |
+
EC_CONTRIBUTION = {
|
724 |
+
'N (NO3-)': 0.06,
|
725 |
+
'N (NH4+)': 0.07,
|
726 |
+
'P': 0.02,
|
727 |
+
'K': 0.08,
|
728 |
+
'Mg': 0.05,
|
729 |
+
'Ca': 0.04,
|
730 |
+
'S': 0.04
|
731 |
+
}
|
732 |
+
|
733 |
class NutrientCalculator:
|
734 |
def __init__(self, volume_liters=1.0):
|
735 |
self.volume = volume_liters # Объем раствора в литрах
|
736 |
self.results = {}
|
737 |
+
self.total_ppm = {} # накопленные ppm по каждому элементу
|
738 |
+
|
739 |
def calculate(self, profile):
|
740 |
"""Основной расчет"""
|
741 |
+
self.total_ppm = {key: 0 for key in profile} # начальная инициализация
|
742 |
self._calc_single_component(profile)
|
|
|
743 |
self._calc_complex(profile)
|
744 |
return self.results
|
745 |
|
746 |
+
def _add_to_total(self, element, ppm):
|
747 |
+
"""Добавляет ppm вещества к общему количеству для расчета EC"""
|
748 |
+
if element in self.total_ppm:
|
749 |
+
self.total_ppm[element] += ppm
|
750 |
+
|
751 |
def _calc_single_component(self, profile):
|
|
|
|
|
752 |
if 'Mg' in profile and 'S' in profile:
|
753 |
mg_needed = profile['Mg']
|
754 |
s_needed = profile['S']
|
755 |
|
|
|
756 |
mg_grams = (mg_needed * self.volume) / (fertilizers_db["Сульфат магния"]["Mg"] * 1000)
|
|
|
757 |
s_from_mg = mg_grams * fertilizers_db["Сульфат магния"]["S"] * 1000 / self.volume
|
758 |
|
759 |
self.results["Сульфат магния"] = {
|
|
|
762 |
'внесет S': round(s_from_mg, 1)
|
763 |
}
|
764 |
profile['S'] -= s_from_mg
|
765 |
+
self._add_to_total('Mg', mg_needed)
|
766 |
+
self._add_to_total('S', s_from_mg)
|
767 |
|
768 |
def _calc_complex(self, profile):
|
|
|
|
|
769 |
if 'Ca' in profile and 'N (NO3-)' in profile:
|
770 |
ca_grams = (profile['Ca'] * self.volume) / (fertilizers_db["Кальциевая селитра"]["Ca"] * 1000)
|
771 |
no3_from_ca = ca_grams * fertilizers_db["Кальциевая селитра"]["N (NO3-)"] * 1000 / self.volume
|
|
|
776 |
'внесет NO3': round(no3_from_ca, 1)
|
777 |
}
|
778 |
profile['N (NO3-)'] -= no3_from_ca
|
779 |
+
self._add_to_total('Ca', profile['Ca'])
|
780 |
+
self._add_to_total('N (NO3-)', no3_from_ca)
|
781 |
|
|
|
782 |
if 'P' in profile and 'K' in profile:
|
783 |
p_grams = (profile['P'] * self.volume) / (fertilizers_db["Монофосфат калия"]["P"] * 1000)
|
784 |
k_from_p = p_grams * fertilizers_db["Монофосфат калия"]["K"] * 1000 / self.volume
|
|
|
789 |
'внесет K': round(k_from_p, 1)
|
790 |
}
|
791 |
profile['K'] -= k_from_p
|
792 |
+
self._add_to_total('P', profile['P'])
|
793 |
+
self._add_to_total('K', k_from_p)
|
794 |
|
|
|
795 |
if 'K' in profile and profile['K'] > 0 and 'N (NO3-)' in profile:
|
796 |
k_grams = (profile['K'] * self.volume) / (fertilizers_db["Калий азотнокислый"]["K"] * 1000)
|
797 |
no3_from_k = k_grams * fertilizers_db["Калий азотнокислый"]["N (NO3-)"] * 1000 / self.volume
|
|
|
802 |
'внесет NO3': round(no3_from_k, 1)
|
803 |
}
|
804 |
profile['N (NO3-)'] -= no3_from_k
|
805 |
+
self._add_to_total('K', profile['K'])
|
806 |
+
self._add_to_total('N (NO3-)', no3_from_k)
|
807 |
|
|
|
808 |
if 'N (NH4+)' in profile and profile['N (NH4+)'] > 0:
|
809 |
nh4_grams = (profile['N (NH4+)'] * self.volume) / (fertilizers_db["Аммоний азотнокислый"]["N (NH4+)"] * 1000)
|
810 |
no3_from_nh4 = nh4_grams * fertilizers_db["Аммоний азотнокислый"]["N (NO3-)"] * 1000 / self.volume
|
|
|
815 |
'внесет NO3': round(no3_from_nh4, 1)
|
816 |
}
|
817 |
profile['N (NO3-)'] -= no3_from_nh4
|
818 |
+
self._add_to_total('N (NH4+)', profile['N (NH4+)'])
|
819 |
+
self._add_to_total('N (NO3-)', no3_from_nh4)
|
820 |
+
|
821 |
+
def _calculate_ec(self):
|
822 |
+
"""Расчет электропроводимости на основе накопленных ppm"""
|
823 |
+
ec = 0.0
|
824 |
+
for elem, ppm in self.total_ppm.items():
|
825 |
+
ec += EC_CONTRIBUTION.get(elem, 0) * (ppm / 100)
|
826 |
+
return round(ec, 2)
|
827 |
|
828 |
def print_report(self, profile):
|
829 |
"""Красивый вывод результатов"""
|
830 |
print("\n" + "="*50)
|
831 |
print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
|
832 |
print("="*50)
|
833 |
+
|
834 |
print("\nЦЕЛЕВОЙ ПРОФИЛЬ (ppm):")
|
835 |
print(tabulate([(k, v) for k, v in profile.items()],
|
836 |
headers=["Элемент", "Концентрация"]))
|
837 |
+
|
838 |
print("\nРЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:")
|
839 |
table = []
|
840 |
for fert, data in self.results.items():
|
|
|
846 |
])
|
847 |
print(tabulate(table,
|
848 |
headers=["Удобрение", "Граммы", "Миллиграммы", "Дополнительно"]))
|
|
|
849 |
|
850 |
+
print("\nОСТАТОЧНЫЙ ДЕФИЦИТ:")
|
851 |
+
print(tabulate([(k, v) for k, v in profile.items() if v > 0.1],
|
852 |
+
headers=["Элемент", "Недостача (ppm)"]))
|
853 |
+
|
854 |
+
# Электропроводимость
|
855 |
+
ec_value = self._calculate_ec()
|
856 |
+
print(f"\nПРИБЛИЗИТЕЛЬНАЯ ЭЛЕКТРОПРОВОДИМОСТЬ (EC): {ec_value} мСм/см")
|
857 |
|
858 |
# Пример использования
|
859 |
calc = NutrientCalculator(volume_liters=10) # Для 10 литров раствора
|