Spaces:
Sleeping
Sleeping
| from io import BytesIO | |
| from reportlab.lib.pagesizes import A4 | |
| from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle | |
| from reportlab.lib.units import inch | |
| from reportlab.lib import colors | |
| from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle | |
| def export_blast_pdf(result: dict, sequence: str = "") -> bytes: | |
| buffer = BytesIO() | |
| doc = SimpleDocTemplate(buffer, pagesize=A4, topMargin=0.75 * inch, bottomMargin=0.75 * inch) | |
| styles = getSampleStyleSheet() | |
| elements = [] | |
| title_style = ParagraphStyle("Title2", parent=styles["Title"], fontSize=16, spaceAfter=12) | |
| heading_style = ParagraphStyle("Heading", parent=styles["Heading2"], fontSize=12, spaceAfter=6, textColor=colors.HexColor("#16a34a")) | |
| body_style = ParagraphStyle("Body", parent=styles["BodyText"], fontSize=10, spaceAfter=6) | |
| elements.append(Paragraph("Bio Nexus \u2014 BLAST Results", title_style)) | |
| elements.append(Spacer(1, 12)) | |
| if sequence: | |
| preview = sequence[:100] + ("..." if len(sequence) > 100 else "") | |
| elements.append(Paragraph(f"<b>Query:</b> {preview}", body_style)) | |
| elements.append(Paragraph(f"<b>Hits found:</b> {result.get('count', 0)}", body_style)) | |
| elements.append(Spacer(1, 12)) | |
| hits = result.get("hits", []) | |
| if not hits: | |
| elements.append(Paragraph("No hits found.", body_style)) | |
| doc.build(elements) | |
| return buffer.getvalue() | |
| table_data = [["#", "Accession", "Description", "E-value", "Identity", "Coverage"]] | |
| for i, hit in enumerate(hits[:20], 1): | |
| desc = (hit.get("description", "")[:60] + "...") if len(hit.get("description", "")) > 60 else hit.get("description", "") | |
| table_data.append([ | |
| str(i), | |
| hit.get("accession", ""), | |
| desc, | |
| f"{hit.get('evalue', 0):.1e}", | |
| f"{hit.get('identity_pct', 0)}%", | |
| f"{hit.get('coverage_pct', 0)}%", | |
| ]) | |
| col_widths = [0.4 * inch, 1.0 * inch, 2.5 * inch, 1.0 * inch, 0.8 * inch, 0.8 * inch] | |
| t = Table(table_data, colWidths=col_widths, repeatRows=1) | |
| t.setStyle(TableStyle([ | |
| ("BACKGROUND", (0, 0), (-1, 0), colors.HexColor("#16a34a")), | |
| ("TEXTCOLOR", (0, 0), (-1, 0), colors.white), | |
| ("FONTSIZE", (0, 0), (-1, 0), 9), | |
| ("FONTSIZE", (0, 1), (-1, -1), 8), | |
| ("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"), | |
| ("ALIGN", (0, 0), (-1, -1), "LEFT"), | |
| ("VALIGN", (0, 0), (-1, -1), "TOP"), | |
| ("GRID", (0, 0), (-1, -1), 0.5, colors.HexColor("#e5e7eb")), | |
| ("ROWBACKGROUNDS", (0, 1), (-1, -1), [colors.white, colors.HexColor("#f9fafb")]), | |
| ("TOPPADDING", (0, 0), (-1, -1), 4), | |
| ("BOTTOMPADDING", (0, 0), (-1, -1), 4), | |
| ("LEFTPADDING", (0, 0), (-1, -1), 4), | |
| ("RIGHTPADDING", (0, 0), (-1, -1), 4), | |
| ])) | |
| elements.append(t) | |
| elements.append(Spacer(1, 16)) | |
| elements.append(Paragraph("Significance Guide", heading_style)) | |
| elements.append(Paragraph("\u2022 <b>E-value < 1e-50</b>: Highly significant match", body_style)) | |
| elements.append(Paragraph("\u2022 <b>E-value 1e-5 to 1e-50</b>: Significant match", body_style)) | |
| elements.append(Paragraph("\u2022 <b>E-value > 1e-5</b>: Weak or non-significant", body_style)) | |
| elements.append(Spacer(1, 8)) | |
| elements.append(Paragraph(f"<i>Generated by Bio Nexus Platform \u2014 {result.get('count', 0)} hits</i>", body_style)) | |
| doc.build(elements) | |
| return buffer.getvalue() | |
| def export_uniprot_pdf(data: dict) -> bytes: | |
| buffer = BytesIO() | |
| doc = SimpleDocTemplate(buffer, pagesize=A4, topMargin=0.75 * inch, bottomMargin=0.75 * inch) | |
| styles = getSampleStyleSheet() | |
| elements = [] | |
| title_style = ParagraphStyle("Title2", parent=styles["Title"], fontSize=16, spaceAfter=12) | |
| heading_style = ParagraphStyle("Heading", parent=styles["Heading2"], fontSize=12, spaceAfter=6, textColor=colors.HexColor("#16a34a")) | |
| body_style = ParagraphStyle("Body", parent=styles["BodyText"], fontSize=10, spaceAfter=6) | |
| elements.append(Paragraph("Bio Nexus \u2014 UniProt Annotation", title_style)) | |
| elements.append(Spacer(1, 12)) | |
| elements.append(Paragraph(f"<b>Protein:</b> {data.get('full_name', 'Unknown')}", body_style)) | |
| elements.append(Paragraph(f"<b>Accession:</b> {data.get('accession', '')}", body_style)) | |
| elements.append(Paragraph(f"<b>Organism:</b> {data.get('organism', 'Unknown')}", body_style)) | |
| genes = data.get("gene_names", []) | |
| if genes: | |
| elements.append(Paragraph(f"<b>Gene:</b> {', '.join(genes)}", body_style)) | |
| ec = data.get("ec_number", "") | |
| if ec: | |
| elements.append(Paragraph(f"<b>EC Number:</b> {ec}", body_style)) | |
| elements.append(Paragraph(f"<b>Sequence Length:</b> {data.get('sequence_length', 0)} amino acids", body_style)) | |
| elements.append(Spacer(1, 12)) | |
| functions = data.get("functions", []) | |
| if functions: | |
| elements.append(Paragraph("Function", heading_style)) | |
| for f in functions: | |
| elements.append(Paragraph(f, body_style)) | |
| locations = data.get("subcellular_locations", []) | |
| if locations: | |
| elements.append(Paragraph("Subcellular Location", heading_style)) | |
| elements.append(Paragraph(", ".join(locations), body_style)) | |
| pdb_ids = data.get("pdb_ids", []) | |
| if pdb_ids: | |
| elements.append(Paragraph("PDB Structures", heading_style)) | |
| elements.append(Paragraph(", ".join(pdb_ids), body_style)) | |
| keywords = data.get("keywords", []) | |
| if keywords: | |
| elements.append(Paragraph("Keywords", heading_style)) | |
| elements.append(Paragraph(", ".join(keywords[:10]), body_style)) | |
| elements.append(Spacer(1, 12)) | |
| elements.append(Paragraph("<i>Generated by Bio Nexus Platform</i>", body_style)) | |
| doc.build(elements) | |
| return buffer.getvalue() | |