Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -683,7 +683,6 @@ def view_image():
|
|
683 |
|
684 |
|
685 |
|
686 |
-
# Профиль питательного раствора (ppm = мг/литр)
|
687 |
TOMATO_PROFILE = {
|
688 |
'N (NO3-)': 200,
|
689 |
'N (NH4+)': 20,
|
@@ -694,154 +693,113 @@ TOMATO_PROFILE = {
|
|
694 |
'S': 100
|
695 |
}
|
696 |
|
697 |
-
# База данных удобрений (монокомпоненты)
|
698 |
fertilizers_db = {
|
699 |
"Кальциевая селитра": {
|
700 |
-
"N (NO3-)": 0.118,
|
701 |
-
"Ca": 0.169
|
|
|
702 |
},
|
703 |
"Калий азотнокислый": {
|
704 |
-
"N (NO3-)": 0.138,
|
705 |
-
"K": 0.387
|
|
|
706 |
},
|
707 |
"Аммоний азотнокислый": {
|
708 |
-
"N (NO3-)": 0.175,
|
709 |
-
"N (NH4+)": 0.175
|
|
|
710 |
},
|
711 |
"Сульфат магния": {
|
712 |
-
"Mg": 0.098,
|
713 |
-
"S": 0.13
|
|
|
714 |
},
|
715 |
"Монофосфат калия": {
|
716 |
-
"P": 0.227,
|
717 |
-
"K": 0.287
|
|
|
718 |
}
|
719 |
}
|
720 |
|
721 |
-
# Приблизительный вклад элементов в электропроводимость, мСм/см на 100 ppm
|
722 |
-
# Источник: усреднённые данные по литературе (можно адаптировать)
|
723 |
-
EC_CONTRIBUTION = {
|
724 |
-
'N (NO3-)': 0.6,
|
725 |
-
'N (NH4+)': 0.7,
|
726 |
-
'P': 0.2,
|
727 |
-
'K': 0.8,
|
728 |
-
'Mg': 0.5,
|
729 |
-
'Ca': 0.4,
|
730 |
-
'S': 0.4
|
731 |
-
}
|
732 |
-
|
733 |
class NutrientCalculator:
|
734 |
def __init__(self, volume_liters=1.0):
|
735 |
-
self.volume = volume_liters
|
736 |
self.results = {}
|
737 |
-
self.
|
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
|
747 |
-
|
748 |
-
|
749 |
-
|
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["Сульфат магния"] = {
|
760 |
'граммы': round(mg_grams, 3),
|
761 |
'миллиграммы': int(mg_grams * 1000),
|
762 |
'внесет S': round(s_from_mg, 1)
|
763 |
}
|
764 |
profile['S'] -= s_from_mg
|
765 |
-
self.
|
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
|
772 |
-
|
773 |
self.results["Кальциевая селитра"] = {
|
774 |
'граммы': round(ca_grams, 3),
|
775 |
'миллиграммы': int(ca_grams * 1000),
|
776 |
'внесет NO3': round(no3_from_ca, 1)
|
777 |
}
|
778 |
profile['N (NO3-)'] -= no3_from_ca
|
779 |
-
self.
|
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
|
785 |
-
|
786 |
self.results["Монофосфат калия"] = {
|
787 |
'граммы': round(p_grams, 3),
|
788 |
'миллиграммы': int(p_grams * 1000),
|
789 |
'вне��ет K': round(k_from_p, 1)
|
790 |
}
|
791 |
profile['K'] -= k_from_p
|
792 |
-
self.
|
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
|
798 |
-
|
799 |
self.results["Калий азотнокислый"] = {
|
800 |
'граммы': round(k_grams, 3),
|
801 |
'миллиграммы': int(k_grams * 1000),
|
802 |
'внесет NO3': round(no3_from_k, 1)
|
803 |
}
|
804 |
profile['N (NO3-)'] -= no3_from_k
|
805 |
-
self.
|
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
|
811 |
-
|
812 |
self.results["Аммоний азотнокислый"] = {
|
813 |
'граммы': round(nh4_grams, 3),
|
814 |
'миллиграммы': int(nh4_grams * 1000),
|
815 |
'внесет NO3': round(no3_from_nh4, 1)
|
816 |
}
|
817 |
profile['N (NO3-)'] -= no3_from_nh4
|
818 |
-
self.
|
819 |
-
self._add_to_total('N (NO3-)', no3_from_nh4)
|
820 |
-
|
821 |
-
def calculate_ec(self):
|
822 |
-
ppm = self.calculate_ppm()
|
823 |
-
ec = 0.0
|
824 |
-
EC_COEFFICIENTS = {
|
825 |
-
'N (NO3-)': 0.6,
|
826 |
-
'N (NH4+)': 0.4,
|
827 |
-
'K': 0.7,
|
828 |
-
'Ca': 0.75,
|
829 |
-
'Mg': 0.6,
|
830 |
-
'S': 0.3,
|
831 |
-
'P': 0.1,
|
832 |
-
}
|
833 |
-
for element, value in ppm.items():
|
834 |
-
if element in EC_COEFFICIENTS:
|
835 |
-
ec += value * EC_COEFFICIENTS[element]
|
836 |
-
return ec / 100
|
837 |
-
|
838 |
|
839 |
def print_report(self, profile):
|
840 |
-
"""Красивый вывод результатов"""
|
841 |
print("\n" + "="*50)
|
842 |
print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
|
843 |
print("="*50)
|
844 |
-
|
845 |
print("\nЦЕЛЕВОЙ ПРОФИЛЬ (ppm):")
|
846 |
print(tabulate([(k, v) for k, v in profile.items()],
|
847 |
headers=["Элемент", "Концентрация"]))
|
@@ -855,19 +813,16 @@ class NutrientCalculator:
|
|
855 |
f"{data['миллиграммы']} мг",
|
856 |
f"+{list(data.keys())[2]} {data[list(data.keys())[2]]} ppm"
|
857 |
])
|
858 |
-
print(tabulate(table,
|
859 |
-
|
|
|
860 |
|
861 |
print("\nОСТАТОЧНЫЙ ДЕФИЦИТ:")
|
862 |
print(tabulate([(k, v) for k, v in profile.items() if v > 0.1],
|
863 |
headers=["Элемент", "Недостача (ppm)"]))
|
864 |
|
865 |
-
# Электропроводимость
|
866 |
-
ec_value = self._calculate_ec()
|
867 |
-
print(f"\nПРИБЛИЗИТЕЛЬНАЯ ЭЛЕКТРОПРОВОДИМОСТЬ (EC): {ec_value} мСм/см")
|
868 |
-
|
869 |
# Пример использования
|
870 |
-
calc = NutrientCalculator(volume_liters=10)
|
871 |
results = calc.calculate(TOMATO_PROFILE.copy())
|
872 |
calc.print_report(TOMATO_PROFILE.copy())
|
873 |
|
|
|
683 |
|
684 |
|
685 |
|
|
|
686 |
TOMATO_PROFILE = {
|
687 |
'N (NO3-)': 200,
|
688 |
'N (NH4+)': 20,
|
|
|
693 |
'S': 100
|
694 |
}
|
695 |
|
|
|
696 |
fertilizers_db = {
|
697 |
"Кальциевая селитра": {
|
698 |
+
"N (NO3-)": 0.118,
|
699 |
+
"Ca": 0.169,
|
700 |
+
"EC_factor": 1.2 # мСм/см на 1 г/л
|
701 |
},
|
702 |
"Калий азотнокислый": {
|
703 |
+
"N (NO3-)": 0.138,
|
704 |
+
"K": 0.387,
|
705 |
+
"EC_factor": 1.4
|
706 |
},
|
707 |
"Аммоний азотнокислый": {
|
708 |
+
"N (NO3-)": 0.175,
|
709 |
+
"N (NH4+)": 0.175,
|
710 |
+
"EC_factor": 1.5
|
711 |
},
|
712 |
"Сульфат магния": {
|
713 |
+
"Mg": 0.098,
|
714 |
+
"S": 0.13,
|
715 |
+
"EC_factor": 1.0
|
716 |
},
|
717 |
"Монофосфат калия": {
|
718 |
+
"P": 0.227,
|
719 |
+
"K": 0.287,
|
720 |
+
"EC_factor": 0.7
|
721 |
}
|
722 |
}
|
723 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
class NutrientCalculator:
|
725 |
def __init__(self, volume_liters=1.0):
|
726 |
+
self.volume = volume_liters
|
727 |
self.results = {}
|
728 |
+
self.ec_total = 0.0
|
729 |
+
|
730 |
def calculate(self, profile):
|
|
|
|
|
731 |
self._calc_single_component(profile)
|
732 |
self._calc_complex(profile)
|
733 |
return self.results
|
734 |
|
735 |
+
def _add_ec(self, fert_name, grams):
|
736 |
+
ec_factor = fertilizers_db[fert_name].get("EC_factor", 0)
|
737 |
+
ec_contrib = ec_factor * (grams / self.volume)
|
738 |
+
self.ec_total += ec_contrib
|
739 |
|
740 |
def _calc_single_component(self, profile):
|
741 |
if 'Mg' in profile and 'S' in profile:
|
742 |
mg_needed = profile['Mg']
|
|
|
|
|
743 |
mg_grams = (mg_needed * self.volume) / (fertilizers_db["Сульфат магния"]["Mg"] * 1000)
|
744 |
s_from_mg = mg_grams * fertilizers_db["Сульфат магния"]["S"] * 1000 / self.volume
|
|
|
745 |
self.results["Сульфат магния"] = {
|
746 |
'граммы': round(mg_grams, 3),
|
747 |
'миллиграммы': int(mg_grams * 1000),
|
748 |
'внесет S': round(s_from_mg, 1)
|
749 |
}
|
750 |
profile['S'] -= s_from_mg
|
751 |
+
self._add_ec("Сульфат магния", mg_grams)
|
|
|
752 |
|
753 |
def _calc_complex(self, profile):
|
754 |
if 'Ca' in profile and 'N (NO3-)' in profile:
|
755 |
ca_grams = (profile['Ca'] * self.volume) / (fertilizers_db["Кальциевая селитра"]["Ca"] * 1000)
|
756 |
no3_from_ca = ca_grams * fertilizers_db["Кальциевая селитра"]["N (NO3-)"] * 1000 / self.volume
|
|
|
757 |
self.results["Кальциевая селитра"] = {
|
758 |
'граммы': round(ca_grams, 3),
|
759 |
'миллиграммы': int(ca_grams * 1000),
|
760 |
'внесет NO3': round(no3_from_ca, 1)
|
761 |
}
|
762 |
profile['N (NO3-)'] -= no3_from_ca
|
763 |
+
self._add_ec("Кальциевая селитра", ca_grams)
|
|
|
764 |
|
765 |
if 'P' in profile and 'K' in profile:
|
766 |
p_grams = (profile['P'] * self.volume) / (fertilizers_db["Монофосфат калия"]["P"] * 1000)
|
767 |
k_from_p = p_grams * fertilizers_db["Монофосфат калия"]["K"] * 1000 / self.volume
|
|
|
768 |
self.results["Монофосфат калия"] = {
|
769 |
'граммы': round(p_grams, 3),
|
770 |
'миллиграммы': int(p_grams * 1000),
|
771 |
'вне��ет K': round(k_from_p, 1)
|
772 |
}
|
773 |
profile['K'] -= k_from_p
|
774 |
+
self._add_ec("Монофосфат калия", p_grams)
|
|
|
775 |
|
776 |
if 'K' in profile and profile['K'] > 0 and 'N (NO3-)' in profile:
|
777 |
k_grams = (profile['K'] * self.volume) / (fertilizers_db["Калий азотнокислый"]["K"] * 1000)
|
778 |
no3_from_k = k_grams * fertilizers_db["Калий азотнокислый"]["N (NO3-)"] * 1000 / self.volume
|
|
|
779 |
self.results["Калий азотнокислый"] = {
|
780 |
'граммы': round(k_grams, 3),
|
781 |
'миллиграммы': int(k_grams * 1000),
|
782 |
'внесет NO3': round(no3_from_k, 1)
|
783 |
}
|
784 |
profile['N (NO3-)'] -= no3_from_k
|
785 |
+
self._add_ec("Калий азотнокислый", k_grams)
|
|
|
786 |
|
787 |
if 'N (NH4+)' in profile and profile['N (NH4+)'] > 0:
|
788 |
nh4_grams = (profile['N (NH4+)'] * self.volume) / (fertilizers_db["Аммоний азотнокислый"]["N (NH4+)"] * 1000)
|
789 |
no3_from_nh4 = nh4_grams * fertilizers_db["Аммоний азотнокислый"]["N (NO3-)"] * 1000 / self.volume
|
|
|
790 |
self.results["Аммоний азотнокислый"] = {
|
791 |
'граммы': round(nh4_grams, 3),
|
792 |
'миллиграммы': int(nh4_grams * 1000),
|
793 |
'внесет NO3': round(no3_from_nh4, 1)
|
794 |
}
|
795 |
profile['N (NO3-)'] -= no3_from_nh4
|
796 |
+
self._add_ec("Аммоний азотнокислый", nh4_grams)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
797 |
|
798 |
def print_report(self, profile):
|
|
|
799 |
print("\n" + "="*50)
|
800 |
print(f"РАСЧЕТ ДЛЯ {self.volume} ЛИТРОВ РАСТВОРА")
|
801 |
print("="*50)
|
802 |
+
|
803 |
print("\nЦЕЛЕВОЙ ПРОФИЛЬ (ppm):")
|
804 |
print(tabulate([(k, v) for k, v in profile.items()],
|
805 |
headers=["Элемент", "Концентрация"]))
|
|
|
813 |
f"{data['миллиграммы']} мг",
|
814 |
f"+{list(data.keys())[2]} {data[list(data.keys())[2]]} ppm"
|
815 |
])
|
816 |
+
print(tabulate(table, headers=["Удобрение", "Граммы", "Миллиграммы", "Дополнительно"]))
|
817 |
+
|
818 |
+
print(f"\n🌊 Примерная электропроводимость (EC): {round(self.ec_total, 2)} мСм/см")
|
819 |
|
820 |
print("\nОСТАТОЧНЫЙ ДЕФИЦИТ:")
|
821 |
print(tabulate([(k, v) for k, v in profile.items() if v > 0.1],
|
822 |
headers=["Элемент", "Недостача (ppm)"]))
|
823 |
|
|
|
|
|
|
|
|
|
824 |
# Пример использования
|
825 |
+
calc = NutrientCalculator(volume_liters=10)
|
826 |
results = calc.calculate(TOMATO_PROFILE.copy())
|
827 |
calc.print_report(TOMATO_PROFILE.copy())
|
828 |
|