import csv from os import write from pathlib import Path import right_tree.api.data from .filters import * from .wms_utils import get_address_from_coordinates, get_point_from_coordinates import pdfkit import pandas as pd from PyPDF2 import PdfFileMerger CSV_FILENAME = 'plants.csv' PLANTING_GUIDE_PDF_FILENAME = 'planting_guide.pdf' HEADER_FIELDS = ['Names', 'Growth Form / Max Height (m) / Spacing (m) / Forest Position', 'Moisture Preferences', 'Tolerances (Water / Drought / Frost / Salinity)', 'Ecosystem Services', 'Carbon Sequestration Rate', 'Planting Stage'] def get_plant_resource_filepath(filename=CSV_FILENAME, resource_dir='generated_resources'): """ Retrives the filepath for the plant csv file. """ return Path(right_tree.api.data.__file__).resolve().parent / resource_dir / filename def get_location_filters(request): """ Retrives the selected location data from the request. """ filter_rows = [['LOCATION FILTERS:', ' ']] coordinates = request.query_params.get('coordinates') if coordinates is not None: eco_district_layer = ecological_district_coordinate_filter( coordinates).first() point = get_point_from_coordinates(coordinates) address = get_address_from_coordinates(coordinates) filter_rows.append(['Point coordinates:', point]) filter_rows.append(['Ecological region:', eco_district_layer.ecologic_1 or '' ]) filter_rows.append(['Ecological district:', eco_district_layer.ecologic_2 or ' ']) filter_rows.append(['Property address:', address['full_address'] if address is not None else ' ']) else: filter_rows.append(["None specified", " "]) return filter_rows def get_soil_filters(request): """ Retrives the selected soil type data from the request. """ filter_rows = [['SOIL FILTERS:', ' ']] soil_variant = request.query_params.get('soilVariant') coordinates = request.query_params.get('coordinates') if soil_variant is not None and coordinates is not None: soil_order_obj = soil_order_coordinate_filter(coordinates).first() filter_rows.append(['Soil Order:', f"{soil_order_obj.name or ' '} ({soil_order_obj.code or ' '})"]) filter_rows.append(['Soil Variant:', soil_variant]) else: filter_rows.append(["None specified", " "]) return filter_rows def get_site_filters(request): """ Retrives the selected site data from the request. """ filter_rows = [['SITE FILTERS:', ' ']] habitat = request.query_params.get('habitat') zone = request.query_params.get('zone') if zone is not None and habitat is not None: habitat_json = json.loads(habitat) zone_json = json.loads(zone) filter_rows.append(['Habitat:', habitat_json.get("name", " ")]) filter_rows.append(['Zone Name:', zone_json.get("name", " ")]) filter_rows.append(['Zone Variant:', zone_json.get("variant", " ")]) filter_rows.append(['Zone Refined Variant:', zone_json.get("refined_variant", " ")]) else: filter_rows.append(["None specified", " "]) return filter_rows def get_filter_values(request): """ Retrives all selected values/filters from the request. """ filter_rows = [] # Add all the location filters filter_rows += get_location_filters(request) filter_rows.append([' ', ' ']) # Add the soil filters filter_rows += get_soil_filters(request) filter_rows.append([' ', ' ']) # Add the project site filters filter_rows += get_site_filters(request) filter_rows.append([' ', ' ']) return filter_rows def write_csv_filter_info(request, writer): """ Retrieves and writes filter information to a CSV file given a writer. """ for filter_row in get_filter_values(request): writer.writerow(filter_row) def write_csv_plant_info(plant_data, writer): """ Writes plant list information to a CSV file given a writer. """ writer.writerow(HEADER_FIELDS) for plant in plant_data: plant_data_row = [ plant.display_name, plant.display_growth_form, plant.moisture_preferences, plant.plant_tolerances, plant.ecosystem_services, plant.carbon_sequestration, plant.stage ] writer.writerow(plant_data_row) def create_plant_csv_file(request, plant_data): """ Constructs a csv file that contains selected filter values and the resulting plant list. """ with open(get_plant_resource_filepath(), 'w', encoding='UTF8') as f: writer = csv.writer(f) # Write filter/selected values write_csv_filter_info(request, writer) # Write the plant data write_csv_plant_info(plant_data, writer) def generate_pdf(data_name, data, csv_generation_function): """ Generates a pdf from a csv given data and a csv generation method. Requires an html file to be generated as an intermediate step. """ # Define filepaths - some are required as intermediate files csv_filepath = get_plant_resource_filepath(f'{data_name}.csv') html_filepath = get_plant_resource_filepath(f'{data_name}.html') pdf_filepath = get_plant_resource_filepath(f'{data_name}.pdf') # Create an initial csv file with the data with open(csv_filepath, 'w', encoding='UTF8') as f: writer = csv.writer(f) csv_generation_function(data, writer) # Convert the csv to and html file then to a pdf CSV = pd.read_csv(csv_filepath) CSV.to_html(html_filepath) pdfkit.from_file(str(html_filepath), str(pdf_filepath)) def create_planting_guide_pdf(request, plant_data): """ Creates a planting guide pdf document with a pre-generated planting guide with filter and plant list tabular informtation appended. """ # Define the names of the resource files as used in multiple places filter_file_prefix = "filters" plant_list_file_prefix = "plant_list" # Generate the filters and plant list pdf files generate_pdf(filter_file_prefix, request, write_csv_filter_info) # TODO: space values appear as NaN... this should be fixed generate_pdf(plant_list_file_prefix, plant_data, write_csv_plant_info) # Create a list of pdfs that need to be merged planting_guide_pdf_filepath = get_plant_resource_filepath(PLANTING_GUIDE_PDF_FILENAME, 'resources') filter_pdf_filepath = get_plant_resource_filepath(f'{filter_file_prefix}.pdf') plant_list_pdf_filepath = get_plant_resource_filepath(f'{plant_list_file_prefix}.pdf') pdfs = [planting_guide_pdf_filepath, filter_pdf_filepath, plant_list_pdf_filepath] # Merge pdfs merger = PdfFileMerger() for pdf in pdfs: merger.append(str(pdf)) # Create the final output pdf with all merged documents output_pdf_filepath = get_plant_resource_filepath(PLANTING_GUIDE_PDF_FILENAME) merger.write(str(output_pdf_filepath)) merger.close()