updates
This commit is contained in:
Binary file not shown.
@@ -11,18 +11,20 @@ Usage:
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import html
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import anthropic
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv(Path(__file__).parent / ".env")
|
||||
|
||||
from csv_preprocessor import analyze_file, analyze_lp_file, group_captures, ChannelMetrics, LPMetrics
|
||||
|
||||
DATA_DIR = Path(__file__).parent / "data"
|
||||
ANALYSIS_LOG = Path(__file__).parent / "analysis_log.txt"
|
||||
DISPLAY_URL = "http://192.168.45.8:5000/display"
|
||||
DATA_DIR = Path(__file__).parent / "data"
|
||||
REPORTS_DIR = Path(__file__).parent / "reports"
|
||||
|
||||
CLAUDE_MODEL = "claude-opus-4-6"
|
||||
SYSTEM_PROMPT = (
|
||||
@@ -86,10 +88,83 @@ def build_prompt(all_summaries: list[str]) -> str:
|
||||
"1. Identify any consistent spec concerns (HS voltage, LP-11 voltage, LP-low timing).\n"
|
||||
"2. Highlight any trends over captures (amplitude drift, jitter, LP-11 voltage, etc.).\n"
|
||||
"3. Flag anomalies — missing LP transitions, short LP-low, unexpected burst counts.\n"
|
||||
"4. Summarise overall signal health in 2–3 sentences."
|
||||
"4. For any ERROR or WARNING lines in the summaries, explain the most likely cause "
|
||||
" (e.g. missing file, bad trigger, signal absent, probe issue) and what to check.\n"
|
||||
"5. Provide specific, actionable recommendations to address all identified issues and anomalies.\n"
|
||||
"6. Summarise overall signal health in 2–3 sentences."
|
||||
)
|
||||
|
||||
|
||||
def save_html_report(analysis: str, token_line: str, keys: list) -> Path:
|
||||
"""Write a timestamped HTML report to the reports/ directory."""
|
||||
REPORTS_DIR.mkdir(exist_ok=True)
|
||||
now = datetime.now()
|
||||
filename = now.strftime("%Y%m%d_%H%M%S_analysis.html")
|
||||
path = REPORTS_DIR / filename
|
||||
|
||||
cap_range = (
|
||||
f"Capture {keys[0][1]:04d}"
|
||||
if len(keys) == 1
|
||||
else f"Captures {keys[0][1]:04d}–{keys[-1][1]:04d}"
|
||||
)
|
||||
date_str = now.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# Convert plain text analysis to basic HTML (preserve line breaks, bold **)
|
||||
def text_to_html(text: str) -> str:
|
||||
escaped = html.escape(text)
|
||||
# **bold**
|
||||
import re
|
||||
escaped = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', escaped)
|
||||
# Blank lines → paragraph breaks
|
||||
paragraphs = re.split(r'\n{2,}', escaped)
|
||||
parts = []
|
||||
for para in paragraphs:
|
||||
lines = para.strip().splitlines()
|
||||
if not lines:
|
||||
continue
|
||||
# Numbered or bullet list
|
||||
if lines[0].lstrip().startswith(('1.', '2.', '3.', '-', '*')):
|
||||
items = ''.join(f'<li>{l.lstrip("0123456789.-* ")}</li>' for l in lines if l.strip())
|
||||
tag = 'ol' if lines[0].lstrip()[0].isdigit() else 'ul'
|
||||
parts.append(f'<{tag}>{items}</{tag}>')
|
||||
else:
|
||||
parts.append('<p>' + '<br>'.join(lines) + '</p>')
|
||||
return '\n'.join(parts)
|
||||
|
||||
body_html = text_to_html(analysis)
|
||||
|
||||
html_content = f"""<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>MIPI Analysis — {cap_range}</title>
|
||||
<style>
|
||||
body {{ font-family: Arial, sans-serif; max-width: 900px; margin: 40px auto; padding: 0 20px; color: #222; }}
|
||||
h1 {{ color: #1a3a5c; border-bottom: 2px solid #1a3a5c; padding-bottom: 8px; }}
|
||||
.meta {{ color: #555; font-size: 0.95em; margin-top: -8px; margin-bottom: 24px; }}
|
||||
p {{ line-height: 1.6; }}
|
||||
ol, ul {{ line-height: 1.8; padding-left: 24px; }}
|
||||
li {{ margin: 4px 0; }}
|
||||
.tokens {{ color: #888; font-size: 0.8em; margin-top: 32px; border-top: 1px solid #ddd; padding-top: 8px; }}
|
||||
@media print {{ body {{ margin: 20px; }} }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>MIPI D-PHY Analysis Report</h1>
|
||||
<p class="meta">
|
||||
<strong>Generated:</strong> {date_str} |
|
||||
<strong>Scope:</strong> {cap_range} |
|
||||
<strong>Model:</strong> {CLAUDE_MODEL}
|
||||
</p>
|
||||
{body_html}
|
||||
<p class="tokens">{html.escape(token_line)}</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
path.write_text(html_content, encoding="utf-8")
|
||||
return path
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -122,7 +197,7 @@ def run_analysis(last: int = 10) -> None:
|
||||
system = SYSTEM_PROMPT,
|
||||
messages = [{"role": "user", "content": prompt}],
|
||||
)
|
||||
analysis = message.content[0].text
|
||||
analysis = message.content[0].text
|
||||
token_line = f"Tokens: {message.usage.input_tokens} in / {message.usage.output_tokens} out"
|
||||
|
||||
# ── Console ───────────────────────────────────────────────────────────
|
||||
@@ -134,20 +209,9 @@ def run_analysis(last: int = 10) -> None:
|
||||
print(f"({token_line})")
|
||||
print(separator + "\n")
|
||||
|
||||
# ── Append to log file ────────────────────────────────────────────────
|
||||
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
with open(ANALYSIS_LOG, "a", encoding="utf-8") as f:
|
||||
f.write(f"\n{'='*60}\n{ts} — captures {keys[0][1]:04d}–{keys[-1][1]:04d}\n{'='*60}\n")
|
||||
f.write(analysis)
|
||||
f.write(f"\n({token_line})\n")
|
||||
print(f"[ANALYSIS] Report appended to {ANALYSIS_LOG}")
|
||||
|
||||
# ── Send to display ───────────────────────────────────────────────────
|
||||
try:
|
||||
requests.post(DISPLAY_URL, json={"text": analysis}, timeout=5)
|
||||
print("[ANALYSIS] Report sent to display.")
|
||||
except Exception as e:
|
||||
print(f"[ANALYSIS] Display send failed: {e}")
|
||||
# ── HTML report ───────────────────────────────────────────────────────
|
||||
report_path = save_html_report(analysis, token_line, keys)
|
||||
print(f"[ANALYSIS] Report saved to {report_path}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@@ -210,7 +274,6 @@ def main() -> None:
|
||||
analysis = message.content[0].text
|
||||
token_line = f"Tokens: {message.usage.input_tokens} in / {message.usage.output_tokens} out"
|
||||
separator = "=" * 60
|
||||
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# Console
|
||||
print(f"\n{separator}\nCLAUDE ANALYSIS\n{separator}")
|
||||
@@ -218,19 +281,9 @@ def main() -> None:
|
||||
print(f"({token_line})")
|
||||
print(separator)
|
||||
|
||||
# Log file
|
||||
with open(ANALYSIS_LOG, "a", encoding="utf-8") as f:
|
||||
f.write(f"\n{separator}\n{ts}\n{separator}\n")
|
||||
f.write(analysis)
|
||||
f.write(f"\n({token_line})\n")
|
||||
print(f"\nReport appended to {ANALYSIS_LOG}")
|
||||
|
||||
# Display
|
||||
try:
|
||||
requests.post(DISPLAY_URL, json={"text": analysis}, timeout=5)
|
||||
print("Report sent to display.")
|
||||
except Exception as e:
|
||||
print(f"Display send failed: {e}")
|
||||
# HTML report
|
||||
report_path = save_html_report(analysis, token_line, keys)
|
||||
print(f"\nReport saved to {report_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
10
mipi_test.py
10
mipi_test.py
@@ -364,11 +364,17 @@ def test_worker():
|
||||
resume_event.wait() # block here while mgmt_worker is running
|
||||
if not test_running:
|
||||
break
|
||||
requests.put(URL, json={"state": "on"}, timeout=2)
|
||||
try:
|
||||
requests.put(URL, json={"state": "on"}, timeout=2)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f" WARNING: display ON failed: {e}")
|
||||
time.sleep(DISPLAY_SETTLE_S)
|
||||
dual_capture(count)
|
||||
count += 1
|
||||
requests.put(URL, json={"state": "off"}, timeout=2)
|
||||
try:
|
||||
requests.put(URL, json={"state": "off"}, timeout=2)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f" WARNING: display OFF failed: {e}")
|
||||
time.sleep(1.0)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user