DmitrMakeev commited on
Commit
21f1a9f
·
verified ·
1 Parent(s): be7ca79

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -0
app.py CHANGED
@@ -729,6 +729,124 @@ EC_COEFFICIENTS = {
729
 
730
 
731
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
732
  class NutrientCalculator:
733
  def __init__(self, volume_liters=1.0):
734
  self.volume = volume_liters
@@ -751,6 +869,7 @@ class NutrientCalculator:
751
  # Целевой профиль как объект Composition
752
  self.target_composition = Composition('Target Profile', list(self.target_profile.values()))
753
 
 
754
  def calculate(self):
755
  try:
756
  self.actual_profile = {k: 0.0 for k in self.target_profile}
 
729
 
730
 
731
 
732
+ # Список питательных веществ
733
+ nutrients_stencil = [
734
+ 'N (NO3-)',
735
+ 'N (NH4+)',
736
+ 'P',
737
+ 'K',
738
+ 'Mg',
739
+ 'Ca',
740
+ 'S',
741
+ 'Fe',
742
+ 'Zn',
743
+ 'B',
744
+ 'Mn',
745
+ 'Cu',
746
+ 'Mo',
747
+ ]
748
+
749
+
750
+ class Composition:
751
+ def __init__(self, name='', vector=None):
752
+ self.name = name
753
+ if vector is None:
754
+ self.vector = np.zeros(len(nutrients_stencil))
755
+ else:
756
+ if len(vector) != len(nutrients_stencil):
757
+ raise ValueError(f"Vector length ({len(vector)}) does not match "
758
+ f"nutrients stencil length ({len(nutrients_stencil)}).")
759
+ self.vector = np.array(vector)
760
+
761
+ @classmethod
762
+ def from_dict(cls, composition_dict):
763
+ if not composition_dict:
764
+ raise ValueError("Empty composition dictionary provided.")
765
+ name, nutrients_dict = tuple(composition_dict.items())[0]
766
+ vector = np.zeros(len(nutrients_stencil))
767
+ for i, nutrient in enumerate(nutrients_stencil):
768
+ if nutrient in nutrients_dict:
769
+ vector[i] = nutrients_dict[nutrient]
770
+ return cls(name, vector)
771
+
772
+ def __add__(self, composition):
773
+ if not isinstance(composition, Composition):
774
+ raise TypeError("Can only add Composition objects.")
775
+ name = f'{self.name} + {composition.name}'
776
+ vector = self.vector + composition.vector
777
+ return Composition(name, vector)
778
+
779
+ def __neg__(self):
780
+ return Composition(f'- ({self.name})', -self.vector)
781
+
782
+ def __sub__(self, composition):
783
+ if not isinstance(composition, Composition):
784
+ raise TypeError("Can only subtract Composition objects.")
785
+ name = f'{self.name} - {composition.name}'
786
+ vector = self.vector - composition.vector
787
+ return Composition(name, vector)
788
+
789
+ def __eq__(self, other):
790
+ if not isinstance(other, Composition):
791
+ return False
792
+ return np.all(self.vector == other.vector)
793
+
794
+ def __repr__(self):
795
+ return self.table()
796
+
797
+ def __str__(self):
798
+ return f'{self.name} :: ' + ', '.join(
799
+ f'{nutrient}: {amount_ppm:.2f}'
800
+ for nutrient, amount_ppm
801
+ in zip(nutrients_stencil, 10**6 * self.vector)
802
+ )
803
+
804
+ def __rmul__(self, number):
805
+ if not isinstance(number, (int, float)):
806
+ raise TypeError("Can only multiply by a scalar.")
807
+ name = f'{number} * ({self.name})'
808
+ vector = self.vector * number
809
+ return Composition(name, vector)
810
+
811
+ def __len__(self):
812
+ return len(self.vector)
813
+
814
+ def as_dict(self):
815
+ nutrients_dict = {
816
+ nutrient: float(value)
817
+ for nutrient, value in zip(nutrients_stencil, self.vector)
818
+ if value != 0
819
+ }
820
+ return {self.name: nutrients_dict}
821
+
822
+ def table(self, sparse=True, ref=None, tablefmt='simple'):
823
+ description = f'Composition: {self.name}'
824
+ nutrients = np.array(nutrients_stencil)
825
+ vector = self.vector
826
+ if ref is not None:
827
+ if not isinstance(ref, Composition):
828
+ raise TypeError("Reference must be a Composition object.")
829
+ vector_ref = ref.vector
830
+ else:
831
+ vector_ref = np.zeros(len(nutrients_stencil))
832
+ if sparse:
833
+ mask_nonzero = (vector != 0) | (vector_ref != 0)
834
+ nutrients = nutrients[mask_nonzero]
835
+ vector = vector[mask_nonzero]
836
+ vector_ref = vector_ref[mask_nonzero]
837
+ table_dict = {
838
+ 'Nutrient': nutrients,
839
+ 'Ratio': vector,
840
+ 'Amount mg/kg': 10**6 * vector,
841
+ }
842
+ if ref is not None:
843
+ description += f'\nReference: {ref.name}'
844
+ table_dict['Diff mg/kg'] = 10**6 * (vector - vector_ref)
845
+ table = tabulate(table_dict, headers='keys', tablefmt=tablefmt)
846
+ return '\n\n'.join((description, table))
847
+
848
+
849
+ # Ваш калькулятор удобрений
850
  class NutrientCalculator:
851
  def __init__(self, volume_liters=1.0):
852
  self.volume = volume_liters
 
869
  # Целевой профиль как объект Composition
870
  self.target_composition = Composition('Target Profile', list(self.target_profile.values()))
871
 
872
+
873
  def calculate(self):
874
  try:
875
  self.actual_profile = {k: 0.0 for k in self.target_profile}