Maritime Per Week

Lado Ok
4 min readJan 17, 2025

--

My code generates a PDF report with a well-structured layout using data and images. It employs tools like Jinja2 templates for rendering HTML, WeasyPrint for PDF generation, and Python for handling the data and images.

Initial image of the rendered map + one of the first iterations of the report

Contents
- Intro
- Key Features
- Challenges
- How it’s done
- TOOLS

Transitioning from traditional tools like MS word to automated solutions is a huge step for me. For the Maritime Per Week report, I decided to leverage programming skills to automate PDF generation. Ensuring consistency, scalability and pro Presenting.

Key Features and Innovations

  1. PDF Automation: My code generates a well-structured PDF report with dynamic data and images. It utilizes:
  • Jinja2: Dynamically fills placeholders in an HTML template with real-time data.
  • WeasyPrint: Converts the styled HTML template into visually appealing PDFs.
  • Base64 Encoding: Embeds images directly into the HTML for seamless integration.

2. Machine Learning Integration: Predictive models analyze trends and forecast tanker route profitability, such as estimating TCE (Time Charter Equivalent) changes based on historical data and market dynamics. This empowers stakeholders to make informed decisions.

Additional Aspects of the Project:

The project also incorporates advanced features that will be expanded in a separate initiative including:

  • Sentiment Analysis for Maritime News: Using tools like NLTK and VADER to analyse market sentiment from news articles across global shipping and trade topics.
  • Data Integration: Fetching and storing macroeconomic data (e.g. oil prices, inflation rates) and freight rates from APIs like Alpha Vantage and Baltic Exchange
  • Real-Time Data Pipelines: Automating updates with APIs and scheduling tools for consistent and timely insights.
Iterations of different versions of styling.

Challenges and Solutions

The first iteration was the most challenging. Integrating Baltic data into a clean, automated process required designing reusable templates, handling various data formats, and ensuring the PDF layout met professional standards. Journaling my process kept me focused and helped break the complexity into manageable steps.

html instruction to add colour to the arrows depicrting change in the tables

Tools and Tech

  • WeasyPrint: Converts HTML and CSS to PDF’s. It’s used to create visually appealing documents programmatically.
HTML (string-rendered_html).write_pdf(output_pdf_path)

This converts the rendered HTML to a PDF.

  • Jinja2: A templating engine for Python, used to dynamically generate HTML with placeholders and logic.
    Fills placeholders in the HTML template with actual data
Template(compact_table_template).render(...)
  • Base64: Encodes binary data (like images) into text, making it easy to include images directly in the HTML as strings.
    Converts the image into a Base64 string:
base64.b64encode(image_file.read()).decode('utf-8')
  • os: Provides functions to interact with the file system, like building absolute paths to files.
    Constructs paths that work across different Operating System
os.path.join(base_dir, "images/...")

Step-by-Step

  1. Image Handling: Images like route maps and charts are converted to Base64 strings for embedding directly into the HTML.
def encode_base64(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')

2. HTML Template: Defines layout and styles of the PDF.

  • Dynamic placeholders like {{ title }} , {{ map_image }} and {{ highest_changes }} are replaced with data using Jinja2 template engine
  • CSS Styles — Define the appearance of text, tables and images (margins, fonts, colours.

2. Data Handling

  • Route Data: Contains shipping route details, including descriptions, world-scale values, TCE rates, and changes
full_routes = [
{"Route": "TD27", "Description": "130k Guyana to ARA", "Worldscale": 71.11, "TCE": 23150, "Change (TCE)": 2138},
Charts and graphs are embedded using absolute paths to ensure portability.
  • Updating the report data: All dynamic content is organised in a dictionary.
updated_report_data_with_all_routes = {
"title": "Maritime Per Week",
"date": "13 January 2025",
"highest_changes": ...,
"remaining_routes": ...,
"refinery_images": [...],
"market_images": [...],
}

3. Rendering HTML

  • Template Rendering:
    - compact_template: the HTML structure (template)
    - .render(…): Fills placeholders with values from updated_report
template = Template(compact_template)
rendered_html= template.render(**updated_data_with_routes)

4. Generating the PDF

  • WeasyPrint: — Converts the rendered HTML (with styles and data) into a PDF.
    - Output_path : Location to save the generated PDF.
HTML(string=rendered_html).write_pdf(output_path)

Automating Maritime Per Week’s production has transformed a once-manual process into a scalable, proffessional workflow. Moving forward, I plan to refine the automation pipeline and deepen the use of real time updates with APIs for even greater efficiency.

--

--

No responses yet