Skip to content

Commit 745bb4c

Browse files
committed
Fix: Correct format specifier syntax in SIP stats display
Fixed ValueError: Invalid format specifier in SIP stats output. Issue: - Cannot use format specifier (.2f) inside conditional expression in f-string - Syntax: {value:.2f if condition else 'N/A'} is invalid Fix: ✅ Format values BEFORE inserting into f-string ✅ Use separate variables for formatted strings Before (broken): print(f"Std Dev: {stats['std']:.2f if stats['std'] is not None else 'N/A'}") After (working): min_str = f"{stats['min']:.2f}" if stats['min'] is not None else 'N/A' max_str = f"{stats['max']:.2f}" if stats['max'] is not None else 'N/A' std_str = f"{stats['std']:.2f}" if stats['std'] is not None else 'N/A' print(f"Range: {min_str} - {max_str}") print(f"Std Dev: {std_str}") This properly handles None values while maintaining clean numeric formatting.
1 parent 5e12203 commit 745bb4c

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

‎POC_Nov20_BITE_PANCAKE.ipynb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3351,7 +3351,7 @@
33513351
}
33523352
],
33533353
"source": [
3354-
"def sip_query_latest(sensor_id: str) -> Dict[str, Any]:\n \"\"\"\n GET_LATEST: Retrieve most recent sensor reading\n Fast query (<10ms) for dashboards/real-time monitoring\n \"\"\"\n if not pancake_ready or not sips_loaded:\n return None\n \n try:\n conn = psycopg2.connect(PANCAKE_DB)\n cur = conn.cursor()\n \n start_time = time.time()\n \n cur.execute(\"\"\"\n SELECT time, value, unit\n FROM sips\n WHERE sensor_id = %s\n ORDER BY time DESC\n LIMIT 1\n \"\"\", (sensor_id,))\n \n result = cur.fetchone()\n cur.close()\n conn.close()\n \n elapsed_ms = (time.time() - start_time) * 1000\n \n if result:\n return {\n \"sensor_id\": sensor_id,\n \"time\": result[0].isoformat(),\n \"value\": result[1],\n \"unit\": result[2],\n \"query_time_ms\": elapsed_ms\n }\n return None\n except Exception as e:\n print(f\"\u26a0\ufe0f SIP query error: {e}\")\n return None\n\ndef sip_query_stats(sensor_id: str, hours_back: int = 24) -> Dict[str, Any]:\n \"\"\"\n GET_STATS: Aggregate statistics for time range\n Efficient for summaries/alerts\n \"\"\"\n if not pancake_ready or not sips_loaded:\n return None\n \n try:\n conn = psycopg2.connect(PANCAKE_DB)\n cur = conn.cursor()\n \n start_time = time.time()\n \n cur.execute(\"\"\"\n SELECT \n COUNT(*) as count,\n AVG(value) as mean,\n MIN(value) as min,\n MAX(value) as max,\n STDDEV(value) as std\n FROM sips\n WHERE sensor_id = %s\n AND time >= NOW() - INTERVAL '%s hours'\n \"\"\", (sensor_id, hours_back))\n \n result = cur.fetchone()\n cur.close()\n conn.close()\n \n elapsed_ms = (time.time() - start_time) * 1000\n \n if result and result[0] > 0:\n return {\n \"sensor_id\": sensor_id,\n \"time_range_hours\": hours_back,\n \"count\": result[0],\n \"mean\": float(result[1]) if result[1] else None,\n \"min\": float(result[2]) if result[2] else None,\n \"max\": float(result[3]) if result[3] else None,\n \"std\": float(result[4]) if result[4] else None,\n \"query_time_ms\": elapsed_ms\n }\n return None\n except Exception as e:\n print(f\"\u26a0\ufe0f SIP stats query error: {e}\")\n return None\n\n# Demo: SIP Queries\nprint(\"\ud83d\ude80 SIP Query Demonstrations:\\n\")\n\n# 1. GET_LATEST (real-time dashboard use case)\nprint(\"1\ufe0f\u20e3 GET_LATEST (Real-time Dashboard)\")\nprint(\" Use case: 'What is the current soil moisture?'\\n\")\n\ntest_sensor = \"SOIL_MOISTURE-01\"\nlatest = sip_query_latest(test_sensor)\n\nif latest:\n print(f\" Sensor: {latest['sensor_id']}\")\n print(f\" Value: {latest['value']:.2f} {latest['unit']}\")\n print(f\" Time: {latest['time']}\")\n print(f\" \u26a1 Query latency: {latest['query_time_ms']:.2f} ms (<10ms target!)\\n\")\nelse:\n print(\" \u26a0\ufe0f No data available\\n\")\n\n# 2. GET_STATS (summary/alert use case)\nprint(\"2\ufe0f\u20e3 GET_STATS (Last 24 Hours)\")\nprint(\" Use case: 'Has soil moisture dropped below threshold?'\\n\")\n\nstats = sip_query_stats(test_sensor, hours_back=24)\n\nif stats:\n print(f\" Sensor: {stats['sensor_id']}\")\n print(f\" Readings: {stats['count']}\")\n print(f\" Mean: {stats['mean']:.2f}\")\n print(f\" Range: {stats['min'] if stats['min'] is not None else 'N/A'} - {stats['max'] if stats['max'] is not None else 'N/A'}\")\n print(f\" Std Dev: {stats['std']:.2f if stats['std'] is not None else 'N/A'}\")\n print(f\" \u26a1 Query latency: {stats['query_time_ms']:.2f} ms\\n\")\n \n # Alert logic example\n if stats['min'] is not None and stats['min'] < 15.0:\n print(\" \ud83d\udea8 ALERT: Soil moisture dropped below 15% (irrigation needed!)\")\n else:\n print(\" \u2713 Status: Soil moisture within normal range\")\nelse:\n print(\" \u26a0\ufe0f No data available\\n\")\n\nprint(\"\\n\" + \"=\"*70)\nprint(\"\ud83d\udca1 SIP vs BITE Comparison:\")\nprint(\"=\"*70)\nprint(\"SIP Queries (time-series):\")\nprint(\" \u2713 Latency: <10ms (indexed, no embedding)\")\nprint(\" \u2713 Use case: Real-time dashboards, alerts, current values\")\nprint(\" \u2713 Storage: Lightweight (60 bytes/reading)\")\nprint(\"\\nBITE Queries (intelligence):\")\nprint(\" \u2713 Latency: 50-100ms (semantic search, multi-pronged)\")\nprint(\" \u2713 Use case: 'Why?' questions, historical context, recommendations\")\nprint(\" \u2713 Storage: Rich (500 bytes, with embeddings)\")\nprint(\"\\n\ud83e\udd5e PANCAKE uses BOTH (dual-agent architecture)!\")\nprint(\"=\"*70)\n"
3354+
"def sip_query_latest(sensor_id: str) -> Dict[str, Any]:\n \"\"\"\n GET_LATEST: Retrieve most recent sensor reading\n Fast query (<10ms) for dashboards/real-time monitoring\n \"\"\"\n if not pancake_ready or not sips_loaded:\n return None\n \n try:\n conn = psycopg2.connect(PANCAKE_DB)\n cur = conn.cursor()\n \n start_time = time.time()\n \n cur.execute(\"\"\"\n SELECT time, value, unit\n FROM sips\n WHERE sensor_id = %s\n ORDER BY time DESC\n LIMIT 1\n \"\"\", (sensor_id,))\n \n result = cur.fetchone()\n cur.close()\n conn.close()\n \n elapsed_ms = (time.time() - start_time) * 1000\n \n if result:\n return {\n \"sensor_id\": sensor_id,\n \"time\": result[0].isoformat(),\n \"value\": result[1],\n \"unit\": result[2],\n \"query_time_ms\": elapsed_ms\n }\n return None\n except Exception as e:\n print(f\"\u26a0\ufe0f SIP query error: {e}\")\n return None\n\ndef sip_query_stats(sensor_id: str, hours_back: int = 24) -> Dict[str, Any]:\n \"\"\"\n GET_STATS: Aggregate statistics for time range\n Efficient for summaries/alerts\n \"\"\"\n if not pancake_ready or not sips_loaded:\n return None\n \n try:\n conn = psycopg2.connect(PANCAKE_DB)\n cur = conn.cursor()\n \n start_time = time.time()\n \n cur.execute(\"\"\"\n SELECT \n COUNT(*) as count,\n AVG(value) as mean,\n MIN(value) as min,\n MAX(value) as max,\n STDDEV(value) as std\n FROM sips\n WHERE sensor_id = %s\n AND time >= NOW() - INTERVAL '%s hours'\n \"\"\", (sensor_id, hours_back))\n \n result = cur.fetchone()\n cur.close()\n conn.close()\n \n elapsed_ms = (time.time() - start_time) * 1000\n \n if result and result[0] > 0:\n return {\n \"sensor_id\": sensor_id,\n \"time_range_hours\": hours_back,\n \"count\": result[0],\n \"mean\": float(result[1]) if result[1] else None,\n \"min\": float(result[2]) if result[2] else None,\n \"max\": float(result[3]) if result[3] else None,\n \"std\": float(result[4]) if result[4] else None,\n \"query_time_ms\": elapsed_ms\n }\n return None\n except Exception as e:\n print(f\"\u26a0\ufe0f SIP stats query error: {e}\")\n return None\n\n# Demo: SIP Queries\nprint(\"\ud83d\ude80 SIP Query Demonstrations:\\n\")\n\n# 1. GET_LATEST (real-time dashboard use case)\nprint(\"1\ufe0f\u20e3 GET_LATEST (Real-time Dashboard)\")\nprint(\" Use case: 'What is the current soil moisture?'\\n\")\n\ntest_sensor = \"SOIL_MOISTURE-01\"\nlatest = sip_query_latest(test_sensor)\n\nif latest:\n print(f\" Sensor: {latest['sensor_id']}\")\n print(f\" Value: {latest['value']:.2f} {latest['unit']}\")\n print(f\" Time: {latest['time']}\")\n print(f\" \u26a1 Query latency: {latest['query_time_ms']:.2f} ms (<10ms target!)\\n\")\nelse:\n print(\" \u26a0\ufe0f No data available\\n\")\n\n# 2. GET_STATS (summary/alert use case)\nprint(\"2\ufe0f\u20e3 GET_STATS (Last 24 Hours)\")\nprint(\" Use case: 'Has soil moisture dropped below threshold?'\\n\")\n\nstats = sip_query_stats(test_sensor, hours_back=24)\n\nif stats:\n print(f\" Sensor: {stats['sensor_id']}\")\n print(f\" Readings: {stats['count']}\")\n print(f\" Mean: {stats['mean']:.2f}\")\n min_str = f\"{stats['min']:.2f}\" if stats['min'] is not None else 'N/A'\n max_str = f\"{stats['max']:.2f}\" if stats['max'] is not None else 'N/A'\n std_str = f\"{stats['std']:.2f}\" if stats['std'] is not None else 'N/A'\n print(f\" Range: {min_str} - {max_str}\")\n print(f\" Std Dev: {std_str}\")\n print(f\" \u26a1 Query latency: {stats['query_time_ms']:.2f} ms\\n\")\n \n # Alert logic example\n if stats['min'] is not None and stats['min'] < 15.0:\n print(\" \ud83d\udea8 ALERT: Soil moisture dropped below 15% (irrigation needed!)\")\n else:\n print(\" \u2713 Status: Soil moisture within normal range\")\nelse:\n print(\" \u26a0\ufe0f No data available\\n\")\n\nprint(\"\\n\" + \"=\"*70)\nprint(\"\ud83d\udca1 SIP vs BITE Comparison:\")\nprint(\"=\"*70)\nprint(\"SIP Queries (time-series):\")\nprint(\" \u2713 Latency: <10ms (indexed, no embedding)\")\nprint(\" \u2713 Use case: Real-time dashboards, alerts, current values\")\nprint(\" \u2713 Storage: Lightweight (60 bytes/reading)\")\nprint(\"\\nBITE Queries (intelligence):\")\nprint(\" \u2713 Latency: 50-100ms (semantic search, multi-pronged)\")\nprint(\" \u2713 Use case: 'Why?' questions, historical context, recommendations\")\nprint(\" \u2713 Storage: Rich (500 bytes, with embeddings)\")\nprint(\"\\n\ud83e\udd5e PANCAKE uses BOTH (dual-agent architecture)!\")\nprint(\"=\"*70)\n"
33553355
]
33563356
},
33573357
{

0 commit comments

Comments
 (0)