Update app.py
Browse files
app.py
CHANGED
@@ -24,8 +24,119 @@ def extract_text_from_pdf(pdf_path):
|
|
24 |
except Exception as e:
|
25 |
return f"Error extracting text from PDF: {str(e)}"
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
# Function to interact with OpenAI API for systematic review
|
28 |
-
def generate_systematic_review(pdf_files, review_question, include_tables=True):
|
29 |
if not api_key:
|
30 |
return "Please enter your OpenAI API key first."
|
31 |
|
@@ -78,6 +189,8 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
|
|
78 |
Include a comprehensive reference list following a specific citation style (APA, Vancouver, etc.). Provide links to source papers when available.
|
79 |
|
80 |
Your response should be formatted in HTML (but avoid showing these tags ```html ```) but generate the content to look like a professional academic paper. Include proper section headers, abstracts, methodology sections, etc. Number all sections like an academic paper. Follow academic journal standards with double spacing, appropriate margins, and consistent formatting throughout.
|
|
|
|
|
81 |
"""
|
82 |
|
83 |
# Extract text from each PDF
|
@@ -100,8 +213,22 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
|
|
100 |
table_instruction = ""
|
101 |
if include_tables:
|
102 |
table_instruction = " Please include important new generated tables in your review."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
-
user_prompt = f"Please generate a systematic review of the following {len(pdf_files)} papers: {', '.join(pdf_names)}.{table_instruction}\n\nReview Question: {review_question}"
|
105 |
|
106 |
# Create the messages for the API call
|
107 |
messages = [
|
@@ -121,6 +248,41 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
|
|
121 |
# Get the AI response
|
122 |
review_content = response["choices"][0]["message"]["content"]
|
123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
# Apply professional academic paper styling
|
125 |
styled_html = f"""
|
126 |
<!DOCTYPE html>
|
@@ -244,6 +406,13 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
|
|
244 |
font-size: 12px;
|
245 |
color: #777;
|
246 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
@media print {{
|
248 |
body {{
|
249 |
background-color: white;
|
@@ -422,18 +591,36 @@ custom_css = """
|
|
422 |
border-radius: 8px;
|
423 |
}
|
424 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
/* Responsive adjustments */
|
426 |
@media screen and (max-width: 768px) {
|
427 |
.gradio-container {
|
428 |
padding: 10px;
|
429 |
}
|
|
|
|
|
|
|
430 |
}
|
431 |
</style>
|
432 |
"""
|
433 |
|
434 |
# Gradio UI Layout with improved styling
|
435 |
with gr.Blocks(css=custom_css) as demo:
|
436 |
-
gr.Markdown("# Systematic Review Generator
|
437 |
|
438 |
with gr.Accordion("How to Use This App", open=False):
|
439 |
gr.Markdown("""
|
@@ -441,9 +628,15 @@ with gr.Blocks(css=custom_css) as demo:
|
|
441 |
1. Enter your OpenAI API key in the field below and click "Set API Key"
|
442 |
2. Upload multiple PDF research papers (2 or more recommended)
|
443 |
3. Enter your review question or topic
|
444 |
-
4.
|
445 |
-
5.
|
446 |
-
6.
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
|
448 |
### Tips for Best Results:
|
449 |
- Upload papers that are related to the same research topic or field
|
@@ -472,6 +665,22 @@ with gr.Blocks(css=custom_css) as demo:
|
|
472 |
placeholder="e.g., What are the effects of mindfulness meditation on stress reduction?"
|
473 |
)
|
474 |
include_tables = gr.Checkbox(label="Include Comparison Tables", value=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
475 |
generate_button = gr.Button("Generate Systematic Review", elem_id="generate_button", size="large")
|
476 |
|
477 |
# Download link container
|
@@ -485,7 +694,10 @@ with gr.Blocks(css=custom_css) as demo:
|
|
485 |
api_key_button.click(set_api_key, inputs=[api_key_input], outputs=[api_key_output])
|
486 |
|
487 |
# Generate systematic review
|
488 |
-
def process_files_and_generate_review(files, question, include_tables
|
|
|
|
|
|
|
489 |
if not files:
|
490 |
return ("""
|
491 |
<div style="padding: 20px; border: 1px solid #e0e0e0; border-radius: 5px; background-color: #f9f9f9;">
|
@@ -500,7 +712,7 @@ with gr.Blocks(css=custom_css) as demo:
|
|
500 |
# Show loading message
|
501 |
loading_message = """
|
502 |
<div style="padding: 20px; text-align: center;">
|
503 |
-
<h3>Generating Systematic Review...</h3>
|
504 |
<p>This may take a few minutes depending on the number and size of papers.</p>
|
505 |
<div style="width: 100%; height: 4px; background-color: #f0f0f0; margin: 20px 0; border-radius: 2px; overflow: hidden;">
|
506 |
<div style="width: 30%; height: 100%; background: linear-gradient(90deg, #4a00e0, #8e2de2); animation: progress 2s infinite linear;"></div>
|
@@ -516,8 +728,19 @@ with gr.Blocks(css=custom_css) as demo:
|
|
516 |
|
517 |
yield loading_message, ""
|
518 |
|
519 |
-
#
|
520 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
521 |
|
522 |
# Create HTML download link
|
523 |
html_link = create_html_download_link(review)
|
@@ -543,7 +766,10 @@ with gr.Blocks(css=custom_css) as demo:
|
|
543 |
|
544 |
generate_button.click(
|
545 |
process_files_and_generate_review,
|
546 |
-
inputs=[pdf_files, review_question, include_tables
|
|
|
|
|
|
|
547 |
outputs=[review_output, download_html_output]
|
548 |
)
|
549 |
|
|
|
24 |
except Exception as e:
|
25 |
return f"Error extracting text from PDF: {str(e)}"
|
26 |
|
27 |
+
# Function to generate PRISMA flow chart SVG
|
28 |
+
def generate_prisma_flow_chart(records_db, records_other, duplicates, excluded_screening, excluded_fulltext, included_studies,
|
29 |
+
included_meta=None, fulltext_assessed=None):
|
30 |
+
# Calculate values if not provided
|
31 |
+
if fulltext_assessed is None:
|
32 |
+
fulltext_assessed = excluded_fulltext + included_studies
|
33 |
+
|
34 |
+
records_after_duplicates = records_db + records_other - duplicates
|
35 |
+
|
36 |
+
# Create SVG content for PRISMA flow chart
|
37 |
+
svg_content = f'''
|
38 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="700" height="700">
|
39 |
+
<style>
|
40 |
+
.box {{
|
41 |
+
fill: #f9f9f9;
|
42 |
+
stroke: #333;
|
43 |
+
stroke-width: 2;
|
44 |
+
}}
|
45 |
+
.arrow {{
|
46 |
+
stroke: #333;
|
47 |
+
stroke-width: 2;
|
48 |
+
marker-end: url(#arrowhead);
|
49 |
+
}}
|
50 |
+
text {{
|
51 |
+
font-family: Arial, sans-serif;
|
52 |
+
font-size: 14px;
|
53 |
+
text-anchor: middle;
|
54 |
+
}}
|
55 |
+
.box-title {{
|
56 |
+
font-weight: bold;
|
57 |
+
}}
|
58 |
+
</style>
|
59 |
+
|
60 |
+
<defs>
|
61 |
+
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
|
62 |
+
<polygon points="0 0, 10 3.5, 0 7" />
|
63 |
+
</marker>
|
64 |
+
</defs>
|
65 |
+
|
66 |
+
<!-- Identification Section -->
|
67 |
+
<rect x="250" y="30" width="300" height="60" class="box" />
|
68 |
+
<text x="400" y="50" class="box-title">Identification</text>
|
69 |
+
<text x="400" y="75">Records identified through database searching</text>
|
70 |
+
<text x="400" y="90">(n = {records_db})</text>
|
71 |
+
|
72 |
+
<rect x="600" y="30" width="150" height="60" class="box" />
|
73 |
+
<text x="675" y="50" class="box-title">Additional</text>
|
74 |
+
<text x="675" y="75">Other sources</text>
|
75 |
+
<text x="675" y="90">(n = {records_other})</text>
|
76 |
+
|
77 |
+
<!-- Arrows -->
|
78 |
+
<line x1="400" y1="90" x2="400" y2="130" class="arrow" />
|
79 |
+
<line x1="675" y1="90" x2="675" y2="110" class="arrow" />
|
80 |
+
<line x1="675" y1="110" x2="400" y2="110" class="arrow" />
|
81 |
+
|
82 |
+
<!-- Screening Section -->
|
83 |
+
<rect x="250" y="130" width="300" height="60" class="box" />
|
84 |
+
<text x="400" y="150" class="box-title">Screening</text>
|
85 |
+
<text x="400" y="175">Records after duplicates removed</text>
|
86 |
+
<text x="400" y="190">(n = {records_after_duplicates})</text>
|
87 |
+
|
88 |
+
<line x1="400" y1="190" x2="400" y2="230" class="arrow" />
|
89 |
+
|
90 |
+
<rect x="250" y="230" width="300" height="60" class="box" />
|
91 |
+
<text x="400" y="250" class="box-title">Title/Abstract Screening</text>
|
92 |
+
<text x="400" y="275">Records screened</text>
|
93 |
+
<text x="400" y="290">(n = {records_after_duplicates})</text>
|
94 |
+
|
95 |
+
<rect x="600" y="230" width="150" height="60" class="box" />
|
96 |
+
<text x="675" y="255">Records excluded</text>
|
97 |
+
<text x="675" y="275">(n = {excluded_screening})</text>
|
98 |
+
|
99 |
+
<line x1="400" y1="290" x2="400" y2="330" class="arrow" />
|
100 |
+
<line x1="550" y1="260" x2="600" y2="260" class="arrow" />
|
101 |
+
|
102 |
+
<!-- Eligibility Section -->
|
103 |
+
<rect x="250" y="330" width="300" height="60" class="box" />
|
104 |
+
<text x="400" y="350" class="box-title">Eligibility</text>
|
105 |
+
<text x="400" y="375">Full-text articles assessed for eligibility</text>
|
106 |
+
<text x="400" y="390">(n = {fulltext_assessed})</text>
|
107 |
+
|
108 |
+
<rect x="600" y="330" width="150" height="60" class="box" />
|
109 |
+
<text x="675" y="350">Full-text articles</text>
|
110 |
+
<text x="675" y="370">excluded, with reasons</text>
|
111 |
+
<text x="675" y="390">(n = {excluded_fulltext})</text>
|
112 |
+
|
113 |
+
<line x1="400" y1="390" x2="400" y2="430" class="arrow" />
|
114 |
+
<line x1="550" y1="360" x2="600" y2="360" class="arrow" />
|
115 |
+
|
116 |
+
<!-- Included Section -->
|
117 |
+
<rect x="250" y="430" width="300" height="60" class="box" />
|
118 |
+
<text x="400" y="450" class="box-title">Included</text>
|
119 |
+
<text x="400" y="475">Studies included in qualitative synthesis</text>
|
120 |
+
<text x="400" y="490">(n = {included_studies})</text>
|
121 |
+
|
122 |
+
<!-- Optional Meta-Analysis Box -->
|
123 |
+
{f'''
|
124 |
+
<line x1="400" y1="490" x2="400" y2="530" class="arrow" />
|
125 |
+
<rect x="250" y="530" width="300" height="60" class="box" />
|
126 |
+
<text x="400" y="550" class="box-title">Meta-Analysis</text>
|
127 |
+
<text x="400" y="575">Studies included in quantitative synthesis</text>
|
128 |
+
<text x="400" y="590">(n = {included_meta})</text>
|
129 |
+
''' if included_meta is not None else ''}
|
130 |
+
|
131 |
+
<!-- PRISMA Title -->
|
132 |
+
<text x="150" y="25" style="font-size: 18px; font-weight: bold; text-anchor: start;">PRISMA Flow Diagram</text>
|
133 |
+
</svg>
|
134 |
+
'''
|
135 |
+
|
136 |
+
return svg_content
|
137 |
+
|
138 |
# Function to interact with OpenAI API for systematic review
|
139 |
+
def generate_systematic_review(pdf_files, review_question, prisma_numbers, include_tables=True):
|
140 |
if not api_key:
|
141 |
return "Please enter your OpenAI API key first."
|
142 |
|
|
|
189 |
Include a comprehensive reference list following a specific citation style (APA, Vancouver, etc.). Provide links to source papers when available.
|
190 |
|
191 |
Your response should be formatted in HTML (but avoid showing these tags ```html ```) but generate the content to look like a professional academic paper. Include proper section headers, abstracts, methodology sections, etc. Number all sections like an academic paper. Follow academic journal standards with double spacing, appropriate margins, and consistent formatting throughout.
|
192 |
+
|
193 |
+
Make sure to include that you conducted a PRISMA flow diagram as part of the methodology section. Reference the PRISMA diagram in your methodology section and explain the numbers used in the diagram.
|
194 |
"""
|
195 |
|
196 |
# Extract text from each PDF
|
|
|
213 |
table_instruction = ""
|
214 |
if include_tables:
|
215 |
table_instruction = " Please include important new generated tables in your review."
|
216 |
+
|
217 |
+
# Add PRISMA flow information
|
218 |
+
prisma_info = f"""
|
219 |
+
Additionally, I have conducted a PRISMA flow diagram with the following data:
|
220 |
+
- Records identified through database searching: {prisma_numbers['records_db']}
|
221 |
+
- Additional records identified through other sources: {prisma_numbers['records_other']}
|
222 |
+
- Records after duplicates removed: {int(prisma_numbers['records_db']) + int(prisma_numbers['records_other']) - int(prisma_numbers['duplicates'])}
|
223 |
+
- Records excluded during title/abstract screening: {prisma_numbers['excluded_screening']}
|
224 |
+
- Full-text articles excluded with reasons: {prisma_numbers['excluded_fulltext']}
|
225 |
+
- Studies included in qualitative synthesis: {prisma_numbers['included_studies']}
|
226 |
+
"""
|
227 |
+
|
228 |
+
if prisma_numbers.get('included_meta') and prisma_numbers['included_meta'].strip():
|
229 |
+
prisma_info += f"- Studies included in quantitative synthesis (meta-analysis): {prisma_numbers['included_meta']}\n"
|
230 |
|
231 |
+
user_prompt = f"Please generate a systematic review of the following {len(pdf_files)} papers: {', '.join(pdf_names)}.{table_instruction}\n\nReview Question: {review_question}\n\n{prisma_info}"
|
232 |
|
233 |
# Create the messages for the API call
|
234 |
messages = [
|
|
|
248 |
# Get the AI response
|
249 |
review_content = response["choices"][0]["message"]["content"]
|
250 |
|
251 |
+
# Generate PRISMA flow chart SVG
|
252 |
+
prisma_svg = generate_prisma_flow_chart(
|
253 |
+
int(prisma_numbers['records_db']),
|
254 |
+
int(prisma_numbers['records_other']),
|
255 |
+
int(prisma_numbers['duplicates']),
|
256 |
+
int(prisma_numbers['excluded_screening']),
|
257 |
+
int(prisma_numbers['excluded_fulltext']),
|
258 |
+
int(prisma_numbers['included_studies']),
|
259 |
+
int(prisma_numbers['included_meta']) if prisma_numbers.get('included_meta') and prisma_numbers['included_meta'].strip() else None
|
260 |
+
)
|
261 |
+
|
262 |
+
# Find a suitable place to insert the PRISMA flow chart
|
263 |
+
# Look for the methodology section or PRISMA mentions
|
264 |
+
prisma_html = f'''
|
265 |
+
<div class="prisma-flow-chart">
|
266 |
+
<h3>Figure 1: PRISMA Flow Diagram</h3>
|
267 |
+
{prisma_svg}
|
268 |
+
</div>
|
269 |
+
'''
|
270 |
+
|
271 |
+
# Try to insert PRISMA diagram after methodology section or before results
|
272 |
+
if "<h2>3. Methodology" in review_content:
|
273 |
+
parts = review_content.split("<h2>3. Methodology", 1)
|
274 |
+
if len(parts) > 1:
|
275 |
+
# Find the next h2 section after methodology
|
276 |
+
next_section = parts[1].find("<h2>")
|
277 |
+
if next_section > -1:
|
278 |
+
review_content = parts[0] + "<h2>3. Methodology" + parts[1][:next_section] + prisma_html + parts[1][next_section:]
|
279 |
+
else:
|
280 |
+
review_content = parts[0] + "<h2>3. Methodology" + parts[1] + prisma_html
|
281 |
+
else:
|
282 |
+
# If methodology section not found, insert before results or at the end
|
283 |
+
insert_pos = review_content.find("<h2>4.") if "<h2>4." in review_content else len(review_content) - 100
|
284 |
+
review_content = review_content[:insert_pos] + prisma_html + review_content[insert_pos:]
|
285 |
+
|
286 |
# Apply professional academic paper styling
|
287 |
styled_html = f"""
|
288 |
<!DOCTYPE html>
|
|
|
406 |
font-size: 12px;
|
407 |
color: #777;
|
408 |
}}
|
409 |
+
.prisma-flow-chart {{
|
410 |
+
margin: 30px 0;
|
411 |
+
text-align: center;
|
412 |
+
}}
|
413 |
+
.prisma-flow-chart h3 {{
|
414 |
+
margin-bottom: 15px;
|
415 |
+
}}
|
416 |
@media print {{
|
417 |
body {{
|
418 |
background-color: white;
|
|
|
591 |
border-radius: 8px;
|
592 |
}
|
593 |
|
594 |
+
/* PRISMA Flow Chart Container */
|
595 |
+
.prisma-section {
|
596 |
+
background-color: white;
|
597 |
+
padding: 20px;
|
598 |
+
border-radius: 8px;
|
599 |
+
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
600 |
+
margin-bottom: 20px;
|
601 |
+
}
|
602 |
+
|
603 |
+
.prisma-form {
|
604 |
+
display: grid;
|
605 |
+
grid-template-columns: 1fr 1fr;
|
606 |
+
gap: 15px;
|
607 |
+
}
|
608 |
+
|
609 |
/* Responsive adjustments */
|
610 |
@media screen and (max-width: 768px) {
|
611 |
.gradio-container {
|
612 |
padding: 10px;
|
613 |
}
|
614 |
+
.prisma-form {
|
615 |
+
grid-template-columns: 1fr;
|
616 |
+
}
|
617 |
}
|
618 |
</style>
|
619 |
"""
|
620 |
|
621 |
# Gradio UI Layout with improved styling
|
622 |
with gr.Blocks(css=custom_css) as demo:
|
623 |
+
gr.Markdown("# Systematic Review Generator with PRISMA Flow Chart")
|
624 |
|
625 |
with gr.Accordion("How to Use This App", open=False):
|
626 |
gr.Markdown("""
|
|
|
628 |
1. Enter your OpenAI API key in the field below and click "Set API Key"
|
629 |
2. Upload multiple PDF research papers (2 or more recommended)
|
630 |
3. Enter your review question or topic
|
631 |
+
4. Fill in the PRISMA flow chart information (numbers at each stage of your review)
|
632 |
+
5. Check the "Include Tables" option if you want the review to include comparison tables
|
633 |
+
6. Click "Generate Systematic Review" to start the process
|
634 |
+
7. After generation, you can download the review as HTML
|
635 |
+
|
636 |
+
### PRISMA Flow Chart:
|
637 |
+
- The PRISMA (Preferred Reporting Items for Systematic Reviews and Meta-Analyses) flow diagram shows the flow of information through the different phases of your systematic review
|
638 |
+
- Fill in the numbers for each stage to generate an accurate diagram
|
639 |
+
- The diagram will be embedded in your systematic review
|
640 |
|
641 |
### Tips for Best Results:
|
642 |
- Upload papers that are related to the same research topic or field
|
|
|
665 |
placeholder="e.g., What are the effects of mindfulness meditation on stress reduction?"
|
666 |
)
|
667 |
include_tables = gr.Checkbox(label="Include Comparison Tables", value=True)
|
668 |
+
|
669 |
+
# PRISMA Flow Chart inputs
|
670 |
+
with gr.Row(elem_classes="prisma-section"):
|
671 |
+
with gr.Column():
|
672 |
+
gr.Markdown("### PRISMA Flow Chart Information")
|
673 |
+
gr.Markdown("Enter the numbers for each stage of your systematic review process:")
|
674 |
+
|
675 |
+
with gr.Row(elem_classes="prisma-form"):
|
676 |
+
prisma_records_db = gr.Textbox(label="Records from database searching", value="100", placeholder="e.g., 100")
|
677 |
+
prisma_records_other = gr.Textbox(label="Records from other sources", value="20", placeholder="e.g., 20")
|
678 |
+
prisma_duplicates = gr.Textbox(label="Duplicates removed", value="15", placeholder="e.g., 15")
|
679 |
+
prisma_excluded_screening = gr.Textbox(label="Records excluded at screening", value="60", placeholder="e.g., 60")
|
680 |
+
prisma_excluded_fulltext = gr.Textbox(label="Full-text articles excluded", value="30", placeholder="e.g., 30")
|
681 |
+
prisma_included_studies = gr.Textbox(label="Studies included in synthesis", value="15", placeholder="e.g., 15")
|
682 |
+
prisma_included_meta = gr.Textbox(label="Studies in meta-analysis (optional)", value="10", placeholder="e.g., 10")
|
683 |
+
|
684 |
generate_button = gr.Button("Generate Systematic Review", elem_id="generate_button", size="large")
|
685 |
|
686 |
# Download link container
|
|
|
694 |
api_key_button.click(set_api_key, inputs=[api_key_input], outputs=[api_key_output])
|
695 |
|
696 |
# Generate systematic review
|
697 |
+
def process_files_and_generate_review(files, question, include_tables,
|
698 |
+
records_db, records_other, duplicates,
|
699 |
+
excluded_screening, excluded_fulltext,
|
700 |
+
included_studies, included_meta):
|
701 |
if not files:
|
702 |
return ("""
|
703 |
<div style="padding: 20px; border: 1px solid #e0e0e0; border-radius: 5px; background-color: #f9f9f9;">
|
|
|
712 |
# Show loading message
|
713 |
loading_message = """
|
714 |
<div style="padding: 20px; text-align: center;">
|
715 |
+
<h3>Generating Systematic Review with PRISMA Flow Chart...</h3>
|
716 |
<p>This may take a few minutes depending on the number and size of papers.</p>
|
717 |
<div style="width: 100%; height: 4px; background-color: #f0f0f0; margin: 20px 0; border-radius: 2px; overflow: hidden;">
|
718 |
<div style="width: 30%; height: 100%; background: linear-gradient(90deg, #4a00e0, #8e2de2); animation: progress 2s infinite linear;"></div>
|
|
|
728 |
|
729 |
yield loading_message, ""
|
730 |
|
731 |
+
# Collect PRISMA flow chart data
|
732 |
+
prisma_numbers = {
|
733 |
+
'records_db': records_db,
|
734 |
+
'records_other': records_other,
|
735 |
+
'duplicates': duplicates,
|
736 |
+
'excluded_screening': excluded_screening,
|
737 |
+
'excluded_fulltext': excluded_fulltext,
|
738 |
+
'included_studies': included_studies,
|
739 |
+
'included_meta': included_meta
|
740 |
+
}
|
741 |
+
|
742 |
+
# Generate review with PRISMA flow chart
|
743 |
+
review = generate_systematic_review(saved_paths, question, prisma_numbers, include_tables)
|
744 |
|
745 |
# Create HTML download link
|
746 |
html_link = create_html_download_link(review)
|
|
|
766 |
|
767 |
generate_button.click(
|
768 |
process_files_and_generate_review,
|
769 |
+
inputs=[pdf_files, review_question, include_tables,
|
770 |
+
prisma_records_db, prisma_records_other, prisma_duplicates,
|
771 |
+
prisma_excluded_screening, prisma_excluded_fulltext,
|
772 |
+
prisma_included_studies, prisma_included_meta],
|
773 |
outputs=[review_output, download_html_output]
|
774 |
)
|
775 |
|