"""
This file contains the functions needed in order to generate an automatic report.
"""
#Imports
import os
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Table, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet
from .Basic_functions import make_solution
from .Solutions_Solubility import plot_graph, data4graph
from .PH_Approximation_0 import *
from .pH_graph_0 import *
# Auxiliar functions
[docs]
def merge_dicts(dict1, dict2, ions_of_interest = "all"):
# Get the union of keys from both dictionaries
all_ions = set(dict1.keys()) | set(dict2.keys())
# Create lists to store ion names, values from dict1, and values from dict2
ion_names = []
values_dict1 = []
values_dict2 = []
# Iterate over ion names
for ion in all_ions:
# Append ion name to ion_names list
if ion in ions_of_interest or ions_of_interest == "all":
ion_names.append(ion)
# Append value from dict1 or None if key does not exist
if ion in dict1 and ion in ion_names:
values_dict1.append(round(dict1[ion],4))
elif ion in ion_names:
values_dict1.append(0)
# Append value from dict2 or None if key does not exist
if ion in dict2 and ion in ion_names:
values_dict2.append(round(dict2[ion],4))
elif ion in ion_names:
values_dict2.append(0)
return [ion_names, values_dict1, values_dict2]
#---------- Main function ---------------------------------
[docs]
def generate_report(
plant_name: str,
required_nutriments: dict,
growth_time: float,
ions_of_interest: list,
solution_composition: dict,
solution_volume: float,
forbidden_ions: list = [],
) -> None:
"""
Generates a simulation report in PDF format based on the provided parameters.
Args:
plant_name (str): The name of the plant for which the hydroponic solution simulation is conducted.
required_nutriments (dict): A dictionary containing the required nutriments (ions) for the specified plant for a full growth [g].
solution_composition (dict): A dictionary representing the composition of the hydroponic solution [g/L] for each ion.
solution_volume (float): The volume of the hydroponic solution [L].
ions_of_interest (list): A list of ions for which the concentration is of interest.
growth_time (float): The duration of the growth of the plant [days].
forbidden_ions (list, default): A list of ions that are forbidden in the solution.
Returns:
None: a pdf is created in the folder of this file
"""
print("Generating report...")
# PageTemplate of the document
doc = SimpleDocTemplate("hydroponic_report.pdf", pagesize=letter)
story = []
interest_ions = ", ".join(ions_of_interest)
nono_ions = ", ".join(forbidden_ions)
# Title
title_style = getSampleStyleSheet()["Title"]
title = Paragraph("Hydroponic Farming Simulation Report", title_style)
story.append(title)
story.append(Spacer(1, 12))
# 1 .Simulation conditions ---------------------------------------------------------
subtitle_style = getSampleStyleSheet()['Heading2']
subtitle = Paragraph(" 1. Simulation Conditions", subtitle_style)
story.append(subtitle)
story.append(Spacer(1, 6))
paragraph_style = getSampleStyleSheet()["Normal"]
conditions_text = f"This report summarizes the simulation of the growth of a {plant_name} in a hydroponic solution.<br/>"\
f"The volume of the solution used in the simulation is {solution_volume} L. "\
f"The simulation was done for a duration of {growth_time} days and the followig ions were analysed: {interest_ions}.<br/> <br/>"\
f"The following assumptions were made for the simulation:<br/>"\
f" - The plant consumes a constant amount of nutriments each day <br/>"\
f" - The temperature is assumed to be constant at 25 °C and the pressure at 1 atm. <br/>"\
f" - The effect of the sun exposure and light conditions was neglected. <br/> <br/>"\
f"The following elements were simulated and analysed:<br/>"\
f" - The amount of salts to add to the solution. <br/>"\
f" - The evolution of the concentration of the ions of interest in the solution. <br/>"\
f" - The pH of the solution. <br/>"\
f"<br/> <br/>"\
f" The table below shows the provided optimal concentrations of the ions in the hydroponic solution and "\
f"the nutritional needs of the {plant_name} plant (fully grown):"
story.append(Paragraph(conditions_text, paragraph_style))
story.append(Spacer(1, 12))
#Table
data = merge_dicts(solution_composition, required_nutriments, ions_of_interest)
headers = ["Ions",'Hydroponic solution [g/L]', f'{plant_name} nutriments requirements[g]']
table_data = [[elem] + sublist for elem, sublist in zip(headers, data)]
# Transpose the data (swap rows and columns)
table_data = list(map(list, zip(*table_data)))
table = Table(table_data)
table.setStyle([('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('BOTTOMPADDING', (0, 0), (-1, 0), 12)])
# Calculate required size for the table
table.wrap(doc.width, doc.height)
# Add the table to the story
story.append(table)
story.append(Spacer(1, 12))
print("Collecting the data ...")
# 2. Preparation of the solution ---------------------------------------------------------
subtitle = Paragraph(" 2. Preparation of the solution", subtitle_style)
story.append(subtitle)
story.append(Spacer(1, 6))
preparation_text = f"The table below shows the mass of salts to add the the {solution_volume} L solution" \
f" to obtain the desired concentrations of the ions for the {plant_name} plant.<br/>"\
f" The following restrictions were given for the preparation of the solution:<br/>"\
f" - Forbidden ions: {nono_ions} <br/>"\
f" - All the salts must be soluble. <br/>"\
f" - The salts come from a list of commercially available salts. <br/>"
story.append(Paragraph(preparation_text, paragraph_style))
story.append(Spacer(1, 12))
#Add table: "salts to add in the solution"
salt_composition = make_solution(solution_composition, forbidden_ions ,solution_volume)
headers = ["Salts"]+list(salt_composition.keys())
data = list(salt_composition.values())
data = [round(float(elem), 4) for elem in data]
data = [f"Mass [g] for {solution_volume} L solution"]+data
table_data = [[elem] + [sublist] for elem, sublist in zip(headers, data)]
table = Table(table_data)
table.setStyle([('BACKGROUND', (0, 0), (-1, 0), colors.grey),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('BOTTOMPADDING', (0, 0), (-1, 0), 12)])
# Calculate required size for the table
table.wrap(doc.width, doc.height)
story.append(table)
story.append(Spacer(1, 12))
# 3. Ion concentration elvolution ---------------------------------------------------------
subtitle = Paragraph(" 3. Evolution of the concentration of ions", subtitle_style)
story.append(subtitle)
story.append(Spacer(1, 6))
ion_figure_text = f"The Figure below shows the concentration of the ions of interest ({interest_ions}) " \
f"as a function of the days of growth of the plant."
story.append(Paragraph(ion_figure_text, paragraph_style))
story.append(Spacer(1, 12))
# Make the graph
plot_graph(solution_composition, "ion", required_nutriments, growth_time, solution_volume, ions_of_interest)
# Get the path of the graph
current_dir = os.path.dirname(os.path.realpath(__file__))
file_name = "graph_"
for ion in ions_of_interest:
file_name += str(ion) + "_"
file_name += ".png"
file_path = os.path.join(current_dir, file_name)
# Add the image to the story and center it
image = Image(file_path, width=600, height=300)
image.hAlign = 'CENTER'
story.append(image)
story.append(Spacer(1, 12))
print("Simulating the plant growth...")
# 4. pH of the solution ---------------------------------------------------------
subtitle = Paragraph(" 4. pH of the solution", subtitle_style)
story.append(subtitle)
story.append(Spacer(1, 6))
pH_text = f"The Figure below shows the pH of the solution as a function of the growth of the plant."\
f"The pH limits are shown in the graph."
story.append(Paragraph(pH_text, paragraph_style))
story.append(Spacer(1, 12))
#Generate the data
solution_pH = data4graph(solution_composition,solution_volume,required_nutriments,growth_time)[1]
temp = int(25)
pH_part_of_report_generation(solution_pH, temp, plant_name) #create images
# Get the path of the pH_graph
current_dir = os.path.dirname(os.path.realpath(__file__))
file_name = "graph_pH.png"
file_path = os.path.join(current_dir, file_name)
# Add the image to the story and center it
image = Image(file_path, width=600, height=300)
image.hAlign = 'CENTER'
story.append(image)
story.append(Spacer(1, 12))
# Get the path of the pH_table
current_dir = os.path.dirname(os.path.realpath(__file__))
file_name = "Table_pH.png"
file_path = os.path.join(current_dir, file_name)
# Add the image to the story and center it
image = Image(file_path, width=300, height=300)
image.hAlign = 'CENTER'
story.append(image)
story.append(Spacer(1, 12))
# Build the PDF
doc.build(story)
print("Report generated successfully!")