Tonic commited on
Commit
5aec14b
·
unverified ·
1 Parent(s): 26ac540

add new version

Browse files
Files changed (6) hide show
  1. app.py +17 -10
  2. old/app.py +82 -0
  3. old/oneclick.py +153 -0
  4. requirements.txt +2 -1
  5. templates/oneclick.html +28 -3
  6. utils/oneclick.py +93 -143
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from flask import Flask, render_template, request, send_file, redirect, url_for
2
  import os
3
  import logging
@@ -32,10 +33,9 @@ def index():
32
  def auth():
33
  if request.method == 'POST':
34
  auth_code = request.form.get('auth_code')
35
- if auth_code:
36
- if meldrx_api.authenticate_with_code(auth_code):
37
- return redirect(url_for('dashboard'))
38
- return render_template('auth.html', auth_url=meldrx_api.get_authorization_url(), auth_result="Authentication failed")
39
  return render_template('auth.html', auth_url=meldrx_api.get_authorization_url())
40
 
41
  @app.route('/auth/callback', methods=['GET'])
@@ -59,10 +59,11 @@ def dashboard():
59
  def one_click():
60
  if not meldrx_api.access_token:
61
  return redirect(url_for('auth'))
 
62
  if request.method == 'POST':
63
- patient_id = request.form.get('patient_id', '')
64
- first_name = request.form.get('first_name', '')
65
- last_name = request.form.get('last_name', '')
66
  action = request.form.get('action', '')
67
 
68
  pdf_path, status, display_summary = generate_discharge_paper_one_click(
@@ -70,10 +71,16 @@ def one_click():
70
  )
71
 
72
  if action == "Display Summary" and display_summary:
73
- return render_template('oneclick.html', status=status, summary=display_summary)
 
 
74
  elif action == "Generate PDF" and pdf_path:
75
- return send_file(pdf_path, as_attachment=True, download_name="discharge_summary.pdf")
76
- return render_template('oneclick.html', status=status, summary=display_summary)
 
 
 
 
77
 
78
  return render_template('oneclick.html')
79
 
 
1
+ # app.py
2
  from flask import Flask, render_template, request, send_file, redirect, url_for
3
  import os
4
  import logging
 
33
  def auth():
34
  if request.method == 'POST':
35
  auth_code = request.form.get('auth_code')
36
+ if auth_code and meldrx_api.authenticate_with_code(auth_code):
37
+ return redirect(url_for('dashboard'))
38
+ return render_template('auth.html', auth_url=meldrx_api.get_authorization_url(), auth_result="Authentication failed")
 
39
  return render_template('auth.html', auth_url=meldrx_api.get_authorization_url())
40
 
41
  @app.route('/auth/callback', methods=['GET'])
 
59
  def one_click():
60
  if not meldrx_api.access_token:
61
  return redirect(url_for('auth'))
62
+
63
  if request.method == 'POST':
64
+ patient_id = request.form.get('patient_id', '').strip()
65
+ first_name = request.form.get('first_name', '').strip()
66
+ last_name = request.form.get('last_name', '').strip()
67
  action = request.form.get('action', '')
68
 
69
  pdf_path, status, display_summary = generate_discharge_paper_one_click(
 
71
  )
72
 
73
  if action == "Display Summary" and display_summary:
74
+ return render_template('oneclick.html',
75
+ status=status,
76
+ summary=display_summary.replace('\n', '<br>'))
77
  elif action == "Generate PDF" and pdf_path:
78
+ return send_file(pdf_path,
79
+ as_attachment=True,
80
+ download_name=f"discharge_summary_{patient_id or 'patient'}.pdf")
81
+ return render_template('oneclick.html',
82
+ status=status,
83
+ summary=display_summary.replace('\n', '<br>') if display_summary else None)
84
 
85
  return render_template('oneclick.html')
86
 
old/app.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request, send_file, redirect, url_for
2
+ import os
3
+ import logging
4
+ from utils.meldrx import MeldRxAPI
5
+ from old.oneclick import generate_discharge_paper_one_click
6
+
7
+ logging.basicConfig(level=logging.INFO)
8
+ logger = logging.getLogger(__name__)
9
+
10
+ app = Flask(__name__)
11
+
12
+ # Configuration from environment variables
13
+ CLIENT_ID = os.getenv("MELDRX_CLIENT_ID", "04bdc9f9a23d488a868b93d594ee5a4a")
14
+ CLIENT_SECRET = os.getenv("MELDRX_CLIENT_SECRET", None)
15
+ WORKSPACE_ID = os.getenv("MELDRX_WORKSPACE_ID", "09ed4f76-b5ac-42bf-92d5-496933203dbe")
16
+ SPACE_URL = os.getenv("SPACE_URL", "https://multitransformer-tonic-discharge-guard.hf.space")
17
+ REDIRECT_URI = f"{SPACE_URL}/auth/callback"
18
+
19
+ # Initialize MeldRx API
20
+ meldrx_api = MeldRxAPI(
21
+ client_id=CLIENT_ID,
22
+ client_secret=CLIENT_SECRET,
23
+ workspace_id=WORKSPACE_ID,
24
+ redirect_uri=REDIRECT_URI
25
+ )
26
+
27
+ @app.route('/')
28
+ def index():
29
+ return render_template('index.html')
30
+
31
+ @app.route('/auth', methods=['GET', 'POST'])
32
+ def auth():
33
+ if request.method == 'POST':
34
+ auth_code = request.form.get('auth_code')
35
+ if auth_code:
36
+ if meldrx_api.authenticate_with_code(auth_code):
37
+ return redirect(url_for('dashboard'))
38
+ return render_template('auth.html', auth_url=meldrx_api.get_authorization_url(), auth_result="Authentication failed")
39
+ return render_template('auth.html', auth_url=meldrx_api.get_authorization_url())
40
+
41
+ @app.route('/auth/callback', methods=['GET'])
42
+ def auth_callback():
43
+ auth_code = request.args.get('code')
44
+ if auth_code and meldrx_api.authenticate_with_code(auth_code):
45
+ return redirect(url_for('dashboard'))
46
+ return render_template('auth.html', auth_url=meldrx_api.get_authorization_url(), auth_result="Callback failed")
47
+
48
+ @app.route('/dashboard', methods=['GET'])
49
+ def dashboard():
50
+ if not meldrx_api.access_token:
51
+ return redirect(url_for('auth'))
52
+ patients_data = meldrx_api.get_patients()
53
+ if not patients_data or "entry" not in patients_data:
54
+ return render_template('dashboard.html', error="Failed to fetch patient data")
55
+ patients = [entry['resource'] for entry in patients_data.get('entry', [])]
56
+ return render_template('dashboard.html', patients=patients, authenticated=True)
57
+
58
+ @app.route('/oneclick', methods=['GET', 'POST'])
59
+ def one_click():
60
+ if not meldrx_api.access_token:
61
+ return redirect(url_for('auth'))
62
+ if request.method == 'POST':
63
+ patient_id = request.form.get('patient_id', '')
64
+ first_name = request.form.get('first_name', '')
65
+ last_name = request.form.get('last_name', '')
66
+ action = request.form.get('action', '')
67
+
68
+ pdf_path, status, display_summary = generate_discharge_paper_one_click(
69
+ meldrx_api, patient_id, first_name, last_name
70
+ )
71
+
72
+ if action == "Display Summary" and display_summary:
73
+ return render_template('oneclick.html', status=status, summary=display_summary)
74
+ elif action == "Generate PDF" and pdf_path:
75
+ return send_file(pdf_path, as_attachment=True, download_name="discharge_summary.pdf")
76
+ return render_template('oneclick.html', status=status, summary=display_summary)
77
+
78
+ return render_template('oneclick.html')
79
+
80
+ if __name__ == '__main__':
81
+ port = int(os.getenv("PORT", 7860))
82
+ app.run(debug=False, host='0.0.0.0', port=port)
old/oneclick.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ import traceback
4
+ from typing import Optional, Dict, Any, Tuple
5
+ from huggingface_hub import InferenceClient
6
+ from utils.meldrx import MeldRxAPI
7
+ from utils.pdfutils import PDFGenerator
8
+ from utils.responseparser import PatientDataExtractor
9
+ from datetime import datetime
10
+
11
+ # Set up logging with detailed output
12
+ logging.basicConfig(
13
+ level=logging.INFO,
14
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
15
+ )
16
+ logger = logging.getLogger(__name__)
17
+
18
+ HF_TOKEN = os.getenv("HF_TOKEN")
19
+ if not HF_TOKEN:
20
+ raise ValueError("HF_TOKEN environment variable not set.")
21
+ client = InferenceClient(api_key=HF_TOKEN)
22
+ MODEL_NAME = "meta-llama/Llama-3.3-70B-Instruct"
23
+
24
+ def generate_ai_discharge_summary(patient_dict: Dict[str, str]) -> Optional[str]:
25
+ """Generate a discharge summary using AI based on extracted patient data."""
26
+ try:
27
+ patient_info = (
28
+ f"Patient Name: {patient_dict['first_name']} {patient_dict['last_name']}\n"
29
+ f"Gender: {patient_dict['sex']}\n"
30
+ f"Age: {patient_dict['age']}\n"
31
+ f"Date of Birth: {patient_dict['dob']}\n"
32
+ f"Admission Date: {patient_dict['admission_date']}\n"
33
+ f"Discharge Date: {patient_dict['discharge_date']}\n\n"
34
+ f"Diagnosis:\n{patient_dict['diagnosis']}\n\n"
35
+ f"Medications:\n{patient_dict['medications']}\n\n"
36
+ f"Discharge Instructions:\n[Generated based on available data]"
37
+ )
38
+
39
+ logger.info("Generating AI discharge summary with patient info: %s", patient_info)
40
+
41
+ messages = [
42
+ {
43
+ "role": "assistant",
44
+ "content": (
45
+ "You are a senior medical practitioner tasked with creating discharge summaries. "
46
+ "Generate a complete discharge summary based on the provided patient information."
47
+ )
48
+ },
49
+ {"role": "user", "content": patient_info}
50
+ ]
51
+
52
+ stream = client.chat.completions.create(
53
+ model=MODEL_NAME,
54
+ messages=messages,
55
+ temperature=0.4,
56
+ max_tokens=3584,
57
+ top_p=0.7,
58
+ stream=True
59
+ )
60
+
61
+ discharge_summary = ""
62
+ for chunk in stream:
63
+ content = chunk.choices[0].delta.content
64
+ if content:
65
+ discharge_summary += content
66
+
67
+ logger.info("AI discharge summary generated successfully")
68
+ return discharge_summary.strip()
69
+
70
+ except Exception as e:
71
+ logger.error("Error generating AI discharge summary: %s\n%s", str(e), traceback.format_exc())
72
+ return None
73
+
74
+ def generate_discharge_paper_one_click(
75
+ meldrx_api: MeldRxAPI,
76
+ patient_id: str = None,
77
+ first_name: str = None,
78
+ last_name: str = None
79
+ ) -> Tuple[Optional[str], str, Optional[str]]:
80
+ """Generate a discharge paper with AI content in one click."""
81
+ try:
82
+ if not meldrx_api.access_token:
83
+ if not meldrx_api.authenticate():
84
+ return None, "Error: Authentication failed. Please authenticate first.", None
85
+
86
+ logger.info("Fetching patient data from MeldRx API")
87
+ patient_data = meldrx_api.get_patients()
88
+ if not patient_data:
89
+ return None, "Error: No patient data returned from MeldRx API.", None
90
+ if "entry" not in patient_data:
91
+ logger.error("Invalid patient data format: %s", patient_data)
92
+ return None, "Error: Patient data is not in expected FHIR Bundle format.", None
93
+
94
+ logger.info("Extracting patient data")
95
+ extractor = PatientDataExtractor(patient_data, format_type="json")
96
+ patients = extractor.get_all_patients()
97
+
98
+ if not patients:
99
+ return None, "Error: No patients found in the workspace.", None
100
+
101
+ patient_dict = None
102
+ if patient_id:
103
+ for p in patients:
104
+ extractor.set_patient_by_index(patients.index(p))
105
+ if extractor.get_id() == patient_id:
106
+ patient_dict = p
107
+ break
108
+ if not patient_dict:
109
+ return None, f"Error: Patient with ID {patient_id} not found.", None
110
+ elif first_name and last_name:
111
+ patient_dict = next(
112
+ (p for p in patients if
113
+ p["first_name"].lower() == first_name.lower() and
114
+ p["last_name"].lower() == last_name.lower()),
115
+ None
116
+ )
117
+ if not patient_dict:
118
+ return None, f"Error: Patient with name {first_name} {last_name} not found.", None
119
+ else:
120
+ patient_dict = patients[0]
121
+
122
+ logger.info("Selected patient: %s %s", patient_dict['first_name'], patient_dict['last_name'])
123
+
124
+ ai_content = generate_ai_discharge_summary(patient_dict)
125
+ if not ai_content:
126
+ return None, "Error: Failed to generate AI discharge summary.", None
127
+
128
+ display_summary = (
129
+ f"<div style='color:#00FFFF; font-family: monospace;'>"
130
+ f"<strong>Discharge Summary Preview</strong><br>"
131
+ f"- Name: {patient_dict['first_name']} {patient_dict['last_name']}<br>"
132
+ f"- DOB: {patient_dict['dob']}, Age: {patient_dict['age']}, Sex: {patient_dict['sex']}<br>"
133
+ f"- Address: {patient_dict['address']}, {patient_dict['city']}, {patient_dict['state']} {patient_dict['zip_code']}<br>"
134
+ f"- Admission Date: {patient_dict['admission_date']}<br>"
135
+ f"- Discharge Date: {patient_dict['discharge_date']}<br>"
136
+ f"- Diagnosis: {patient_dict['diagnosis']}<br>"
137
+ f"- Medications: {patient_dict['medications']}<br>"
138
+ f"</div>"
139
+ )
140
+
141
+ pdf_generator = PDFGenerator()
142
+ pdf_path = pdf_generator.generate_pdf_from_text(
143
+ ai_content,
144
+ f"discharge_summary_{patient_id or 'unknown'}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf"
145
+ )
146
+
147
+ if pdf_path:
148
+ return pdf_path, f"Success: Discharge paper generated for {patient_dict['first_name']} {patient_dict['last_name']}", display_summary
149
+ return None, "Error: Failed to generate PDF.", display_summary
150
+
151
+ except Exception as e:
152
+ logger.error("Error in one-click discharge generation: %s\n%s", str(e), traceback.format_exc())
153
+ return None, f"Error: {str(e)}", None
requirements.txt CHANGED
@@ -11,4 +11,5 @@ pypdf
11
  flask
12
  gradio
13
  huggingface_hub
14
- lxml
 
 
11
  flask
12
  gradio
13
  huggingface_hub
14
+ lxml
15
+ reportlab
templates/oneclick.html CHANGED
@@ -4,14 +4,39 @@
4
  <form method="POST">
5
  <input type="text" name="patient_id" placeholder="Patient ID (Optional)">
6
  <input type="text" name="first_name" placeholder="First Name (Optional)">
7
- <input type="text" name="last_name" placeholder="Last Name (Optional)"><br>
8
  <input type="submit" name="action" value="Display Summary" class="cyberpunk-button">
9
  <input type="submit" name="action" value="Generate PDF" class="cyberpunk-button">
10
  </form>
 
11
  {% if status %}
12
- <div>{{ status }}</div>
13
  {% endif %}
 
14
  {% if summary %}
15
- <div>{{ summary | safe }}</div>
 
 
 
16
  {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  {% endblock %}
 
4
  <form method="POST">
5
  <input type="text" name="patient_id" placeholder="Patient ID (Optional)">
6
  <input type="text" name="first_name" placeholder="First Name (Optional)">
7
+ <input type="text" name="last_name" placeholder="Last Name (Optional)"><br><br>
8
  <input type="submit" name="action" value="Display Summary" class="cyberpunk-button">
9
  <input type="submit" name="action" value="Generate PDF" class="cyberpunk-button">
10
  </form>
11
+
12
  {% if status %}
13
+ <div class="status-message">{{ status }}</div>
14
  {% endif %}
15
+
16
  {% if summary %}
17
+ <div class="summary-container">
18
+ <h3>Discharge Summary Preview</h3>
19
+ <div class="summary-content">{{ summary | safe }}</div>
20
+ </div>
21
  {% endif %}
22
+
23
+ <style>
24
+ .status-message {
25
+ margin: 20px 0;
26
+ padding: 10px;
27
+ border: 1px solid #ccc;
28
+ border-radius: 5px;
29
+ }
30
+ .summary-container {
31
+ margin: 20px 0;
32
+ padding: 15px;
33
+ border: 1px solid #ddd;
34
+ border-radius: 5px;
35
+ background-color: #f9f9f9;
36
+ }
37
+ .summary-content {
38
+ white-space: pre-wrap;
39
+ font-family: 'Courier New', Courier, monospace;
40
+ }
41
+ </style>
42
  {% endblock %}
utils/oneclick.py CHANGED
@@ -1,153 +1,103 @@
1
- import os
 
 
 
 
2
  import logging
3
- import traceback
4
- from typing import Optional, Dict, Any, Tuple
5
- from huggingface_hub import InferenceClient
6
- from utils.meldrx import MeldRxAPI
7
- from utils.pdfutils import PDFGenerator
8
- from utils.responseparser import PatientDataExtractor
9
- from datetime import datetime
10
 
11
- # Set up logging with detailed output
12
- logging.basicConfig(
13
- level=logging.INFO,
14
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
15
- )
16
  logger = logging.getLogger(__name__)
17
 
18
- HF_TOKEN = os.getenv("HF_TOKEN")
19
- if not HF_TOKEN:
20
- raise ValueError("HF_TOKEN environment variable not set.")
21
- client = InferenceClient(api_key=HF_TOKEN)
22
- MODEL_NAME = "meta-llama/Llama-3.3-70B-Instruct"
23
-
24
- def generate_ai_discharge_summary(patient_dict: Dict[str, str]) -> Optional[str]:
25
- """Generate a discharge summary using AI based on extracted patient data."""
26
- try:
27
- patient_info = (
28
- f"Patient Name: {patient_dict['first_name']} {patient_dict['last_name']}\n"
29
- f"Gender: {patient_dict['sex']}\n"
30
- f"Age: {patient_dict['age']}\n"
31
- f"Date of Birth: {patient_dict['dob']}\n"
32
- f"Admission Date: {patient_dict['admission_date']}\n"
33
- f"Discharge Date: {patient_dict['discharge_date']}\n\n"
34
- f"Diagnosis:\n{patient_dict['diagnosis']}\n\n"
35
- f"Medications:\n{patient_dict['medications']}\n\n"
36
- f"Discharge Instructions:\n[Generated based on available data]"
37
- )
38
-
39
- logger.info("Generating AI discharge summary with patient info: %s", patient_info)
40
-
41
- messages = [
42
- {
43
- "role": "assistant",
44
- "content": (
45
- "You are a senior medical practitioner tasked with creating discharge summaries. "
46
- "Generate a complete discharge summary based on the provided patient information."
47
- )
48
- },
49
- {"role": "user", "content": patient_info}
50
- ]
51
-
52
- stream = client.chat.completions.create(
53
- model=MODEL_NAME,
54
- messages=messages,
55
- temperature=0.4,
56
- max_tokens=3584,
57
- top_p=0.7,
58
- stream=True
59
- )
60
-
61
- discharge_summary = ""
62
- for chunk in stream:
63
- content = chunk.choices[0].delta.content
64
- if content:
65
- discharge_summary += content
66
-
67
- logger.info("AI discharge summary generated successfully")
68
- return discharge_summary.strip()
69
-
70
- except Exception as e:
71
- logger.error("Error generating AI discharge summary: %s\n%s", str(e), traceback.format_exc())
72
- return None
73
-
74
  def generate_discharge_paper_one_click(
75
- meldrx_api: MeldRxAPI,
76
- patient_id: str = None,
77
- first_name: str = None,
78
- last_name: str = None
79
  ) -> Tuple[Optional[str], str, Optional[str]]:
80
- """Generate a discharge paper with AI content in one click."""
 
 
 
 
 
 
 
 
 
 
 
81
  try:
82
- if not meldrx_api.access_token:
83
- if not meldrx_api.authenticate():
84
- return None, "Error: Authentication failed. Please authenticate first.", None
85
-
86
- logger.info("Fetching patient data from MeldRx API")
87
- patient_data = meldrx_api.get_patients()
88
- if not patient_data:
89
- return None, "Error: No patient data returned from MeldRx API.", None
90
- if "entry" not in patient_data:
91
- logger.error("Invalid patient data format: %s", patient_data)
92
- return None, "Error: Patient data is not in expected FHIR Bundle format.", None
93
-
94
- logger.info("Extracting patient data")
95
- extractor = PatientDataExtractor(patient_data, format_type="json")
96
- patients = extractor.get_all_patients()
97
-
98
- if not patients:
99
- return None, "Error: No patients found in the workspace.", None
100
-
101
- patient_dict = None
102
- if patient_id:
103
- for p in patients:
104
- extractor.set_patient_by_index(patients.index(p))
105
- if extractor.get_id() == patient_id:
106
- patient_dict = p
107
- break
108
- if not patient_dict:
109
- return None, f"Error: Patient with ID {patient_id} not found.", None
110
- elif first_name and last_name:
111
- patient_dict = next(
112
- (p for p in patients if
113
- p["first_name"].lower() == first_name.lower() and
114
- p["last_name"].lower() == last_name.lower()),
115
- None
116
- )
117
- if not patient_dict:
118
- return None, f"Error: Patient with name {first_name} {last_name} not found.", None
119
- else:
120
- patient_dict = patients[0]
121
-
122
- logger.info("Selected patient: %s %s", patient_dict['first_name'], patient_dict['last_name'])
123
-
124
- ai_content = generate_ai_discharge_summary(patient_dict)
125
- if not ai_content:
126
- return None, "Error: Failed to generate AI discharge summary.", None
127
-
128
- display_summary = (
129
- f"<div style='color:#00FFFF; font-family: monospace;'>"
130
- f"<strong>Discharge Summary Preview</strong><br>"
131
- f"- Name: {patient_dict['first_name']} {patient_dict['last_name']}<br>"
132
- f"- DOB: {patient_dict['dob']}, Age: {patient_dict['age']}, Sex: {patient_dict['sex']}<br>"
133
- f"- Address: {patient_dict['address']}, {patient_dict['city']}, {patient_dict['state']} {patient_dict['zip_code']}<br>"
134
- f"- Admission Date: {patient_dict['admission_date']}<br>"
135
- f"- Discharge Date: {patient_dict['discharge_date']}<br>"
136
- f"- Diagnosis: {patient_dict['diagnosis']}<br>"
137
- f"- Medications: {patient_dict['medications']}<br>"
138
- f"</div>"
139
- )
140
-
141
- pdf_generator = PDFGenerator()
142
- pdf_path = pdf_generator.generate_pdf_from_text(
143
- ai_content,
144
- f"discharge_summary_{patient_id or 'unknown'}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf"
145
- )
146
-
147
  if pdf_path:
148
- return pdf_path, f"Success: Discharge paper generated for {patient_dict['first_name']} {patient_dict['last_name']}", display_summary
149
- return None, "Error: Failed to generate PDF.", display_summary
150
 
151
  except Exception as e:
152
- logger.error("Error in one-click discharge generation: %s\n%s", str(e), traceback.format_exc())
153
- return None, f"Error: {str(e)}", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # utils/oneclick.py
2
+ from typing import Tuple, Optional
3
+ from .meldrx import MeldRxAPI
4
+ from .responseparser import PatientDataExtractor
5
+ from .pdfutils import PDFGenerator
6
  import logging
 
 
 
 
 
 
 
7
 
 
 
 
 
 
8
  logger = logging.getLogger(__name__)
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def generate_discharge_paper_one_click(
11
+ api: MeldRxAPI,
12
+ patient_id: str = "",
13
+ first_name: str = "",
14
+ last_name: str = ""
15
  ) -> Tuple[Optional[str], str, Optional[str]]:
16
+ """
17
+ Generate a discharge summary PDF with one click using MeldRx API data.
18
+
19
+ Args:
20
+ api: Initialized MeldRxAPI instance
21
+ patient_id: Optional patient ID filter
22
+ first_name: Optional first name filter
23
+ last_name: Optional last name filter
24
+
25
+ Returns:
26
+ Tuple of (pdf_path, status_message, display_summary)
27
+ """
28
  try:
29
+ # Get patient data from MeldRx API
30
+ patients_data = api.get_patients()
31
+ if not patients_data or "entry" not in patients_data:
32
+ return None, "Failed to fetch patient data", None
33
+
34
+ # Create PatientDataExtractor instance
35
+ extractor = PatientDataExtractor(patients_data, "json")
36
+
37
+ # Filter patients based on input
38
+ matching_patients = []
39
+ for i in range(len(extractor.patients)):
40
+ extractor.set_patient_by_index(i)
41
+ patient_data = extractor.get_patient_dict()
42
+
43
+ if (not patient_id or patient_data["id"] == patient_id) and \
44
+ (not first_name or patient_data["first_name"].lower() == first_name.lower()) and \
45
+ (not last_name or patient_data["last_name"].lower() == last_name.lower()):
46
+ matching_patients.append(patient_data)
47
+
48
+ if not matching_patients:
49
+ return None, "No matching patients found", None
50
+
51
+ # Use the first matching patient
52
+ patient_data = matching_patients[0]
53
+ extractor.set_patient_by_index(0) # Reset to first patient for consistency
54
+
55
+ # Format the discharge summary text
56
+ summary_text = format_discharge_summary(patient_data)
57
+
58
+ # Generate PDF
59
+ pdf_gen = PDFGenerator()
60
+ filename = f"discharge_{patient_data['id'] or 'summary'}_{patient_data['last_name']}.pdf"
61
+ pdf_path = pdf_gen.generate_pdf_from_text(summary_text, filename)
62
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  if pdf_path:
64
+ return pdf_path, "Discharge summary generated successfully", summary_text
65
+ return None, "Failed to generate PDF", summary_text
66
 
67
  except Exception as e:
68
+ logger.error(f"Error in one-click discharge generation: {str(e)}")
69
+ return None, f"Error: {str(e)}", None
70
+
71
+ def format_discharge_summary(patient_data: dict) -> str:
72
+ """Format patient data into a discharge summary text."""
73
+ summary = [
74
+ "DISCHARGE SUMMARY",
75
+ "",
76
+ "PATIENT INFORMATION",
77
+ f"Name: {patient_data['name_prefix']} {patient_data['first_name']} {patient_data['last_name']}",
78
+ f"Date of Birth: {patient_data['dob']}",
79
+ f"Age: {patient_data['age']}",
80
+ f"Gender: {patient_data['sex']}",
81
+ f"Patient ID: {patient_data['id']}",
82
+ "",
83
+ "CONTACT INFORMATION",
84
+ f"Address: {patient_data['address']}",
85
+ f"City: {patient_data['city']}, {patient_data['state']} {patient_data['zip_code']}",
86
+ f"Phone: {patient_data['phone']}",
87
+ "",
88
+ "ADMISSION INFORMATION",
89
+ f"Admission Date: {patient_data['admission_date']}",
90
+ f"Discharge Date: {patient_data['discharge_date']}",
91
+ f"Diagnosis: {patient_data['diagnosis']}",
92
+ "",
93
+ "MEDICATIONS",
94
+ f"{patient_data['medications']}",
95
+ "",
96
+ "PHYSICIAN INFORMATION",
97
+ f"Physician: Dr. {patient_data['doctor_first_name']} {patient_data['doctor_last_name']}",
98
+ f"Hospital: {patient_data['hospital_name']}",
99
+ f"Address: {patient_data['doctor_address']}",
100
+ f"City: {patient_data['doctor_city']}, {patient_data['doctor_state']} {patient_data['doctor_zip']}",
101
+ ]
102
+
103
+ return "\n".join(line for line in summary if line.strip() or line == "")