Add report generation with PDF output and respiratory chart
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from weasyprint import HTML
|
||||
import matplotlib.pyplot as plt
|
||||
import os
|
||||
|
||||
# 1. Generate a chart with matplotlib
|
||||
os.makedirs("static/charts", exist_ok=True)
|
||||
chart_path = "static/charts/resp_chart.png"
|
||||
|
||||
plt.plot([1, 2, 3, 4], [1, 4, 2, 5], label="Breath Volume")
|
||||
plt.legend()
|
||||
plt.title("Respiratory Chart")
|
||||
plt.savefig(chart_path)
|
||||
plt.close()
|
||||
|
||||
# 2. Patient data (this would usually come from your DB)
|
||||
patient_data = {
|
||||
"name": "Keirstyn Moran",
|
||||
"age": 34,
|
||||
"height": 163,
|
||||
"weight": 56
|
||||
}
|
||||
|
||||
context = {
|
||||
"patient": patient_data,
|
||||
"indications": "No Respiratory Capacity Limitation",
|
||||
"chart_path": chart_path
|
||||
}
|
||||
|
||||
# 3. Render Jinja2 template
|
||||
env = Environment(loader=FileSystemLoader("templates"))
|
||||
template = env.get_template("report.html")
|
||||
html_out = template.render(context)
|
||||
|
||||
# 4. Generate PDF
|
||||
HTML(string=html_out, base_url=".").write_pdf("lung_report.pdf")
|
||||
|
||||
print("✅ Report generated: lung_report.pdf")
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "6eee3ddd",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import camelot\n",
|
||||
"import pandas as pd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "d95cd8b1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tables = camelot.read_pdf('data/KM6479696509 _ Keirstyn_Moran_SingleViewWithExplanation_2025-07-29.pdf')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "759fd46e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"all_dfs = []\n",
|
||||
"\n",
|
||||
"# Append each table's dataframe to the list\n",
|
||||
"for table in tables:\n",
|
||||
" all_dfs.append(table.df)\n",
|
||||
"\n",
|
||||
"# Concatenate all dataframes into one\n",
|
||||
"combined_df = pd.concat(all_dfs, ignore_index=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"id": "e9c3b9f0",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" 0 1 2 3 \\\n",
|
||||
"0 ← FM →\\nLow Fat\\nHigh Fat\\nBody Composition Ch... \n",
|
||||
"1 \n",
|
||||
"2 \n",
|
||||
"3 \n",
|
||||
"4 \n",
|
||||
"5 \n",
|
||||
"6 \n",
|
||||
"\n",
|
||||
" 4 5 \n",
|
||||
"0 muscle mass in a coordinate system. A d... \n",
|
||||
"1 \n",
|
||||
"2 \n",
|
||||
"3 \n",
|
||||
"4 \n",
|
||||
"5 \n",
|
||||
"6 \n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(combined_df)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "6bbc907f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "report_generation",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Lung Report</title>
|
||||
<!-- TailwindCSS via CDN -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="p-10 font-sans">
|
||||
<div class="bg-black text-white p-4 rounded-lg mb-6">
|
||||
<h1 class="text-2xl font-bold">Lung Analysis Report</h1>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4 mb-6">
|
||||
<div><b>Name:</b> {{ patient.name }}</div>
|
||||
<div><b>Age:</b> {{ patient.age }}</div>
|
||||
<div><b>Height:</b> {{ patient.height }} cm</div>
|
||||
<div><b>Weight:</b> {{ patient.weight }} kg</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-6">
|
||||
<h2 class="text-xl font-semibold mb-2">Lung Function</h2>
|
||||
<div class="w-full h-6 bg-gradient-to-r from-red-500 via-yellow-300 to-green-400 relative">
|
||||
<div class="absolute top-[-5px] left-1/2 transform -translate-x-1/2
|
||||
w-0 h-0 border-l-[7px] border-r-[7px] border-b-[10px] border-black"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-100 p-4 rounded-lg mb-6">
|
||||
<b>Indications:</b> {{ indications }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold mb-2">Respiratory Chart</h2>
|
||||
<img src="{{ chart_path }}" class="border rounded-lg shadow">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user