LeonceNsh commited on
Commit
e287ecc
·
verified ·
1 Parent(s): 1a26f82

Upload folder using huggingface_hub

Browse files
__pycache__/app.cpython-311.pyc CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:a5a5f57c1929a7fa923f92f6a6522741c51bb6b424ff1abf62a5084a0f3d0d9e
3
- size 126179
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:64e05fdbfb34e223a6459477a52724bfa95d8ba16076b2527b84a60063adb015
3
+ size 123258
app.py CHANGED
@@ -1035,204 +1035,187 @@ def _create_error_figure(result: Dict[str, Any]) -> go.Figure:
1035
  return fig
1036
 
1037
  def _create_comprehensive_dashboard(result: Dict[str, Any]) -> go.Figure:
1038
- """Create comprehensive privacy dashboard with multiple visualizations"""
1039
  from plotly.subplots import make_subplots
1040
 
1041
- # Create subplot structure with better spacing
1042
  fig = make_subplots(
1043
- rows=2, cols=3,
1044
  subplot_titles=(
1045
- "Distance Distribution Analysis",
1046
- "Privacy Risk Assessment",
1047
- "Data Quality Indicators",
1048
- "Dataset Overview",
1049
- "Privacy Bounds Comparison",
1050
- "Processing Pipeline Status"
1051
  ),
1052
  specs=[
1053
- [{"type": "bar"}, {"type": "indicator"}, {"type": "scatter"}],
1054
- [{"type": "bar"}, {"type": "bar"}, {"type": "bar"}]
1055
  ],
1056
- vertical_spacing=0.15,
1057
- horizontal_spacing=0.1
1058
  )
1059
 
1060
- _add_distance_analysis(fig, result)
1061
- _add_risk_assessment(fig, result)
1062
- _add_quality_indicators(fig, result)
1063
- _add_dataset_overview(fig, result)
1064
- _add_privacy_bounds(fig, result)
1065
- _add_processing_status(fig, result)
1066
 
1067
- # Enhanced layout with professional styling
1068
  fig.update_layout(
1069
  title={
1070
- "text": "<b>Privacy Audit Dashboard</b><br><sub>Comprehensive Analysis of Synthetic Data Privacy</sub>",
1071
  "x": 0.5,
1072
  "xanchor": "center",
1073
- "font": {"size": 20, "color": "#2c3e50"}
1074
  },
1075
- height=700,
1076
  showlegend=False,
1077
  plot_bgcolor="white",
1078
- paper_bgcolor="#f8f9fa",
1079
- font=dict(family="Arial, sans-serif", size=11, color="#2c3e50"),
1080
- margin=dict(t=120, b=50, l=50, r=50)
1081
  )
1082
 
1083
  return fig
1084
 
1085
 
1086
- def _add_distance_analysis(fig, result: Dict[str, Any]):
1087
- """Add enhanced distance distribution analysis"""
1088
  stats = result.get("distance_statistics", {})
1089
 
1090
- # Create meaningful distance metrics with better labeling
1091
- metrics = ["Mean Distance", "Median Distance", "Standard Dev", "25th Percentile", "75th Percentile"]
1092
  values = [
1093
  stats.get("mean_nearest_distance", 0),
1094
  stats.get("median_nearest_distance", 0),
1095
- stats.get("std_nearest_distance", 0),
1096
- stats.get("q25_nearest_distance", 0),
1097
- stats.get("q75_nearest_distance", 0)
1098
  ]
1099
 
1100
- # Use colorblind-friendly palette with semantic meaning
1101
- colors = ['#3498db', '#2ecc71', '#f39c12', '#9b59b6', '#e74c3c']
1102
-
1103
  fig.add_trace(
1104
  go.Bar(
1105
  x=metrics,
1106
  y=values,
1107
- marker_color=colors,
1108
- text=[f"{v:.6f}" if v > 0 else "0" for v in values],
 
1109
  textposition='outside',
1110
- textfont=dict(size=10, color="#2c3e50"),
1111
- hovertemplate="<b>%{x}</b><br>Value: %{y:.6f}<extra></extra>",
1112
- name="Distance Metrics"
1113
  ),
1114
  row=1, col=1
1115
  )
1116
 
1117
- # Customize axes for better readability
1118
- fig.update_xaxes(title_text="Distance Metrics", row=1, col=1, tickangle=45)
1119
- fig.update_yaxes(title_text="Distance Value", row=1, col=1, tickformat=".2e")
1120
 
1121
- def _add_risk_assessment(fig, result: Dict[str, Any]):
1122
- """Add enhanced privacy risk assessment gauge"""
1123
  risk_level = result.get("privacy_assessment", {}).get("risk_level", "UNKNOWN")
1124
  epsilon = result.get("privacy_assessment", {}).get("primary_epsilon", 0)
1125
 
1126
- # Enhanced risk color palette with better accessibility
1127
  risk_colors = {
1128
- "EXCEPTIONAL": "#27ae60", "VERY LOW": "#2ecc71", "LOW": "#f1c40f",
1129
- "MEDIUM": "#e67e22", "HIGH": "#e74c3c", "VERY HIGH": "#c0392b",
1130
- "CRITICAL": "#8e44ad", "UNKNOWN": "#7f8c8d"
1131
  }
1132
 
1133
- # Determine gauge range based on epsilon value
1134
- max_range = max(5.0, epsilon * 1.5) if epsilon > 0 else 5.0
1135
-
1136
  fig.add_trace(
1137
  go.Indicator(
1138
- mode="gauge+number+delta",
1139
  value=epsilon,
1140
  title={
1141
- "text": f"<b>ε-DP Privacy Budget</b><br><span style='font-size:14px'>{risk_level} Risk</span>",
1142
- "font": {"size": 16}
1143
  },
1144
- number={"font": {"size": 24, "color": risk_colors.get(risk_level, "#7f8c8d")}},
1145
- delta={"reference": 1.0, "valueformat": ".6f"},
1146
  gauge={
1147
- "axis": {
1148
- "range": [0, max_range],
1149
- "tickwidth": 1,
1150
- "tickcolor": "#2c3e50",
1151
- "tickfont": {"size": 10}
1152
- },
1153
- "bar": {"color": risk_colors.get(risk_level, "#7f8c8d"), "thickness": 0.8},
1154
- "steps": [
1155
- {"range": [0, 0.01], "color": "#d5f4e6", "name": "Exceptional"},
1156
- {"range": [0.01, 0.1], "color": "#a9dfbf", "name": "Very Low"},
1157
- {"range": [0.1, 0.5], "color": "#fcf3cf", "name": "Low"},
1158
- {"range": [0.5, 1.0], "color": "#f8c471", "name": "Medium"},
1159
- {"range": [1.0, 2.0], "color": "#f1948a", "name": "High"},
1160
- {"range": [2.0, max_range], "color": "#e8daef", "name": "Critical"}
1161
- ],
1162
- "threshold": {
1163
- "line": {"color": "#2c3e50", "width": 3},
1164
- "thickness": 0.9,
1165
- "value": 1.0 # Reference line at ε = 1.0
1166
- }
1167
  }
1168
  ),
1169
  row=1, col=2
1170
  )
1171
 
1172
- def _add_quality_indicators(fig, result: Dict[str, Any]):
1173
- """Add data quality indicators with memorization detection"""
1174
  stats = result.get("distance_statistics", {})
1175
 
1176
- # Calculate meaningful quality percentages
1177
  total_samples = result.get("dataset_info", {}).get("real_samples_used", 1)
1178
  zero_distances = stats.get("zero_distance_count", 0)
1179
  small_distances = stats.get("small_distance_count", 0)
1180
 
1181
- # Create scatter plot showing memorization vs privacy
1182
- memorization_pct = (zero_distances / total_samples) * 100 if total_samples > 0 else 0
1183
- near_memorization_pct = ((small_distances - zero_distances) / total_samples) * 100 if total_samples > 0 else 0
1184
- safe_samples_pct = 100 - memorization_pct - near_memorization_pct
1185
-
1186
- categories = ["Safe Samples", "Near Matches", "Exact Matches"]
1187
- percentages = [safe_samples_pct, near_memorization_pct, memorization_pct]
1188
- colors = ['#27ae60', '#f39c12', '#e74c3c']
1189
 
1190
- # Create horizontal bar chart for better readability
1191
  fig.add_trace(
1192
  go.Bar(
1193
- y=categories,
1194
- x=percentages,
1195
- orientation='h',
1196
- marker_color=colors,
1197
- text=[f"{p:.1f}%" for p in percentages],
1198
- textposition='auto',
1199
- hovertemplate="<b>%{y}</b><br>Percentage: %{x:.1f}%<br>Count: %{customdata}<extra></extra>",
1200
- customdata=[total_samples - small_distances, small_distances - zero_distances, zero_distances],
1201
- name="Data Quality"
1202
  ),
1203
- row=1, col=3
1204
  )
1205
 
1206
- fig.update_xaxes(title_text="Percentage of Samples", row=1, col=3, range=[0, 100])
1207
- fig.update_yaxes(title_text="Sample Categories", row=1, col=3)
1208
 
1209
- def _add_dataset_overview(fig, result: Dict[str, Any]):
1210
- """Add dataset overview with key metrics"""
1211
  dataset_info = result.get("dataset_info", {})
 
 
 
 
 
 
 
 
 
 
 
 
1212
 
1213
- metrics = ["Real Samples", "Synthetic Samples", "Dimensions", "Common Features"]
1214
  values = [
1215
- dataset_info.get("real_samples_used", 0),
1216
- dataset_info.get("synthetic_samples", 0),
1217
- dataset_info.get("dimensions", 0),
1218
- dataset_info.get("common_features", 0)
 
 
1219
  ]
1220
 
1221
  fig.add_trace(
1222
- go.Bar(
1223
- x=metrics,
1224
- y=values,
1225
- marker_color=['#3498db', '#9b59b6', '#e74c3c', '#2ecc71'],
1226
- text=[f"{v:,}" for v in values],
1227
- textposition='outside',
1228
- hovertemplate="<b>%{x}</b><br>Count: %{y:,}<extra></extra>",
1229
- name="Dataset Metrics"
 
 
 
 
 
 
 
 
1230
  ),
1231
- row=2, col=1
1232
  )
1233
-
1234
- fig.update_xaxes(title_text="Dataset Characteristics", row=2, col=1, tickangle=45)
1235
- fig.update_yaxes(title_text="Count", row=2, col=1)
1236
 
1237
  def _add_privacy_bounds(fig, result: Dict[str, Any]):
1238
  """Add privacy bounds comparison across confidence levels"""
@@ -1295,81 +1278,46 @@ def _add_processing_status(fig, result: Dict[str, Any]):
1295
  fig.update_yaxes(title_text="Processing Completion %", row=2, col=3, range=[0, 100])
1296
 
1297
  def create_safe_epsilon_plot(result: Dict[str, Any]) -> go.Figure:
1298
- """Create safe epsilon plot with error handling"""
1299
  try:
1300
  if "error" in result:
1301
- fig = go.Figure()
1302
- fig.add_annotation(
1303
- text=f"Audit Error: {result.get('error', 'Unknown error')}",
1304
- x=0.5, y=0.5, showarrow=False,
1305
- font=dict(size=16, color="red")
1306
- )
1307
- return fig
1308
 
1309
  epsilon_bounds = result.get("epsilon_bounds", {})
1310
-
1311
  confidence_levels = [90, 95, 99]
1312
  epsilon_values = [epsilon_bounds.get(f"eps_lb_{conf}", 0) for conf in confidence_levels]
1313
 
1314
- # Risk level colors
1315
- risk_colors = []
1316
- risk_levels = []
1317
- for eps in epsilon_values:
1318
- risk = auditor.assess_privacy_risk(eps) if auditor else "UNKNOWN"
1319
- risk_levels.append(risk)
1320
- color_map = {
1321
- "EXCEPTIONAL": '#2ca02c', "VERY LOW": '#8dd3c7', "LOW": '#ffd92f',
1322
- "MEDIUM": '#ff7f0e', "HIGH": '#d62728', "VERY HIGH": '#8b0000',
1323
- "CRITICAL": '#4b0082', "UNKNOWN": '#gray'
1324
- }
1325
- risk_colors.append(color_map.get(risk, '#gray'))
1326
-
1327
  fig = go.Figure()
1328
 
1329
- # Bar chart with risk level annotations
1330
  fig.add_trace(go.Bar(
1331
  x=[f"{conf}%" for conf in confidence_levels],
1332
  y=epsilon_values,
1333
- marker_color=risk_colors,
1334
- text=[f"ε = {eps:.6f}<br>{risk}" for eps, risk in zip(epsilon_values, risk_levels)],
1335
- textposition='auto',
1336
- name="ε Lower Bounds",
1337
- hovertemplate="<b>Confidence: %{x}</b><br>ε Lower Bound: %{y:.6f}<br>Risk: %{text}<extra></extra>"
 
 
1338
  ))
1339
 
1340
- # Add reference lines for risk thresholds
1341
- fig.add_hline(y=0.1, line_dash="dash", line_color="green",
1342
- annotation_text="Low Risk Threshold")
1343
- fig.add_hline(y=1.0, line_dash="dash", line_color="orange",
1344
- annotation_text="Medium Risk Threshold")
1345
- fig.add_hline(y=2.0, line_dash="dash", line_color="red",
1346
- annotation_text="High Risk Threshold")
1347
-
1348
- # Use log scale if values span multiple orders of magnitude
1349
- use_log_scale = max(epsilon_values) > 0 and (max(epsilon_values) / max(min(epsilon_values), 1e-10)) > 100
1350
-
1351
  fig.update_layout(
1352
- title="Privacy Budget (ε) Analysis Across Confidence Levels",
1353
  xaxis_title="Confidence Level",
1354
- yaxis_title="ε Lower Bound" + (" (log scale)" if use_log_scale else ""),
1355
- yaxis_type="log" if use_log_scale else "linear",
1356
- template="plotly_white",
1357
- height=500,
1358
- showlegend=False
 
1359
  )
1360
 
1361
  return fig
1362
 
1363
  except Exception as e:
1364
  logger.error(f"Epsilon plot creation failed: {e}")
1365
- # Return error figure
1366
- fig = go.Figure()
1367
- fig.add_annotation(
1368
- text=f"Visualization Error: {str(e)}",
1369
- x=0.5, y=0.5, showarrow=False,
1370
- font=dict(size=16, color="red")
1371
- )
1372
- return fig
1373
 
1374
  def generate_safe_report(result: Dict[str, Any]) -> str:
1375
  """Generate safe executive report with error handling"""
@@ -2141,7 +2089,7 @@ Run a privacy audit to generate a comprehensive executive report including:
2141
  try:
2142
  # Update status to running
2143
  yield (
2144
- gr.update(value="**Audit in progress...**\n\nProcessing your datasets and running privacy analysis..."),
2145
  gr.update(), gr.update(), gr.update(), gr.update(), gr.update(visible=False)
2146
  )
2147
 
@@ -2152,10 +2100,10 @@ Run a privacy audit to generate a comprehensive executive report including:
2152
  if result[0] and "error" not in result[0]:
2153
  risk_level = result[0].get("privacy_assessment", {}).get("risk_level", "UNKNOWN")
2154
  epsilon = result[0].get("privacy_assessment", {}).get("primary_epsilon", 0)
2155
- status_msg = f"**Audit completed successfully!**\n\n**Risk Level:** {risk_level}\n**ε-DP Bound:** {epsilon:.6f}"
2156
  else:
2157
  error_msg = result[0].get("error", "Unknown error") if result[0] else "Unknown error"
2158
- status_msg = f"**Audit failed**\n\n{error_msg}"
2159
 
2160
  # Make export visible if successful
2161
  export_visible = result[4] is not None
@@ -2173,8 +2121,8 @@ Run a privacy audit to generate a comprehensive executive report including:
2173
  error_msg = f"Interface error: {str(e)}"
2174
  logger.error(error_msg)
2175
  yield (
2176
- gr.update(value=f"**Interface Error**\n\n{error_msg}"),
2177
- {"error": error_msg}, None, None, f"ERROR: {error_msg}", gr.update(visible=False)
2178
  )
2179
 
2180
  # Connect the interface - FIXED: Now returns 6 outputs
 
1035
  return fig
1036
 
1037
  def _create_comprehensive_dashboard(result: Dict[str, Any]) -> go.Figure:
1038
+ """Create simplified privacy dashboard focused on key metrics"""
1039
  from plotly.subplots import make_subplots
1040
 
1041
+ # Simplified 2x2 layout focusing on essential information
1042
  fig = make_subplots(
1043
+ rows=2, cols=2,
1044
  subplot_titles=(
1045
+ "Distance Statistics",
1046
+ "Privacy Risk Level",
1047
+ "Data Quality Assessment",
1048
+ "Key Metrics Summary"
 
 
1049
  ),
1050
  specs=[
1051
+ [{"type": "bar"}, {"type": "indicator"}],
1052
+ [{"type": "bar"}, {"type": "table"}]
1053
  ],
1054
+ vertical_spacing=0.2,
1055
+ horizontal_spacing=0.15
1056
  )
1057
 
1058
+ _add_simplified_distance_analysis(fig, result)
1059
+ _add_simplified_risk_assessment(fig, result)
1060
+ _add_simplified_quality_assessment(fig, result)
1061
+ _add_key_metrics_table(fig, result)
 
 
1062
 
1063
+ # Clean, minimal layout
1064
  fig.update_layout(
1065
  title={
1066
+ "text": "Privacy Audit Results",
1067
  "x": 0.5,
1068
  "xanchor": "center",
1069
+ "font": {"size": 18, "color": "#000000"}
1070
  },
1071
+ height=600,
1072
  showlegend=False,
1073
  plot_bgcolor="white",
1074
+ paper_bgcolor="white",
1075
+ font=dict(family="Arial, sans-serif", size=12, color="#000000"),
1076
+ margin=dict(t=80, b=50, l=60, r=60)
1077
  )
1078
 
1079
  return fig
1080
 
1081
 
1082
+ def _add_simplified_distance_analysis(fig, result: Dict[str, Any]):
1083
+ """Add simplified distance analysis focusing on key metrics"""
1084
  stats = result.get("distance_statistics", {})
1085
 
1086
+ # Focus on most important metrics
1087
+ metrics = ["Mean", "Median", "Max"]
1088
  values = [
1089
  stats.get("mean_nearest_distance", 0),
1090
  stats.get("median_nearest_distance", 0),
1091
+ stats.get("max_nearest_distance", 0)
 
 
1092
  ]
1093
 
1094
+ # Use simple, accessible colors
 
 
1095
  fig.add_trace(
1096
  go.Bar(
1097
  x=metrics,
1098
  y=values,
1099
+ marker_color='#2563eb',
1100
+ marker_line=dict(color='#1e40af', width=1),
1101
+ text=[f"{v:.4f}" if v > 0 else "0.0000" for v in values],
1102
  textposition='outside',
1103
+ textfont=dict(size=11, color="#000000"),
1104
+ hovertemplate="<b>%{x}</b><br>%{y:.6f}<extra></extra>",
1105
+ showlegend=False
1106
  ),
1107
  row=1, col=1
1108
  )
1109
 
1110
+ fig.update_xaxes(title_text="Distance Metric", row=1, col=1, title_font_size=12)
1111
+ fig.update_yaxes(title_text="Value", row=1, col=1, title_font_size=12)
 
1112
 
1113
+ def _add_simplified_risk_assessment(fig, result: Dict[str, Any]):
1114
+ """Add simplified risk assessment indicator"""
1115
  risk_level = result.get("privacy_assessment", {}).get("risk_level", "UNKNOWN")
1116
  epsilon = result.get("privacy_assessment", {}).get("primary_epsilon", 0)
1117
 
1118
+ # Simple risk color mapping
1119
  risk_colors = {
1120
+ "EXCEPTIONAL": "#059669", "VERY LOW": "#059669", "LOW": "#0891b2",
1121
+ "MEDIUM": "#ea580c", "HIGH": "#dc2626", "VERY HIGH": "#dc2626",
1122
+ "CRITICAL": "#991b1b", "UNKNOWN": "#6b7280"
1123
  }
1124
 
 
 
 
1125
  fig.add_trace(
1126
  go.Indicator(
1127
+ mode="number+gauge",
1128
  value=epsilon,
1129
  title={
1130
+ "text": f"Privacy Risk: {risk_level}<br>Epsilon Value",
1131
+ "font": {"size": 14, "color": "#000000"}
1132
  },
1133
+ number={"font": {"size": 20, "color": risk_colors.get(risk_level, "#6b7280")}},
 
1134
  gauge={
1135
+ "axis": {"range": [0, 5], "tickcolor": "#000000"},
1136
+ "bar": {"color": risk_colors.get(risk_level, "#6b7280")},
1137
+ "bgcolor": "white",
1138
+ "bordercolor": "#d1d5db",
1139
+ "borderwidth": 2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1140
  }
1141
  ),
1142
  row=1, col=2
1143
  )
1144
 
1145
+ def _add_simplified_quality_assessment(fig, result: Dict[str, Any]):
1146
+ """Add simplified quality assessment"""
1147
  stats = result.get("distance_statistics", {})
1148
 
 
1149
  total_samples = result.get("dataset_info", {}).get("real_samples_used", 1)
1150
  zero_distances = stats.get("zero_distance_count", 0)
1151
  small_distances = stats.get("small_distance_count", 0)
1152
 
1153
+ categories = ["Safe", "Near Match", "Exact Match"]
1154
+ counts = [total_samples - small_distances, small_distances - zero_distances, zero_distances]
 
 
 
 
 
 
1155
 
 
1156
  fig.add_trace(
1157
  go.Bar(
1158
+ x=categories,
1159
+ y=counts,
1160
+ marker_color=['#059669', '#ea580c', '#dc2626'],
1161
+ marker_line=dict(color='#000000', width=1),
1162
+ text=[f"{c:,}" for c in counts],
1163
+ textposition='outside',
1164
+ textfont=dict(size=11, color="#000000"),
1165
+ hovertemplate="<b>%{x}</b><br>Count: %{y:,}<extra></extra>",
1166
+ showlegend=False
1167
  ),
1168
+ row=2, col=1
1169
  )
1170
 
1171
+ fig.update_xaxes(title_text="Sample Type", row=2, col=1, title_font_size=12)
1172
+ fig.update_yaxes(title_text="Count", row=2, col=1, title_font_size=12)
1173
 
1174
+ def _add_key_metrics_table(fig, result: Dict[str, Any]):
1175
+ """Add key metrics summary table"""
1176
  dataset_info = result.get("dataset_info", {})
1177
+ stats = result.get("distance_statistics", {})
1178
+ risk_level = result.get("privacy_assessment", {}).get("risk_level", "UNKNOWN")
1179
+ epsilon = result.get("privacy_assessment", {}).get("primary_epsilon", 0)
1180
+
1181
+ metrics = [
1182
+ "Real Samples",
1183
+ "Synthetic Samples",
1184
+ "Dimensions",
1185
+ "Risk Level",
1186
+ "Epsilon Value",
1187
+ "Exact Matches"
1188
+ ]
1189
 
 
1190
  values = [
1191
+ f"{dataset_info.get('real_samples_used', 0):,}",
1192
+ f"{dataset_info.get('synthetic_samples', 0):,}",
1193
+ f"{dataset_info.get('dimensions', 0)}",
1194
+ risk_level,
1195
+ f"{epsilon:.6f}",
1196
+ f"{stats.get('zero_distance_count', 0):,}"
1197
  ]
1198
 
1199
  fig.add_trace(
1200
+ go.Table(
1201
+ header=dict(
1202
+ values=["<b>Metric</b>", "<b>Value</b>"],
1203
+ fill_color="#f3f4f6",
1204
+ font=dict(size=12, color="#000000"),
1205
+ align="left",
1206
+ line_color="#d1d5db"
1207
+ ),
1208
+ cells=dict(
1209
+ values=[metrics, values],
1210
+ fill_color="white",
1211
+ font=dict(size=11, color="#000000"),
1212
+ align="left",
1213
+ line_color="#d1d5db",
1214
+ height=30
1215
+ )
1216
  ),
1217
+ row=2, col=2
1218
  )
 
 
 
1219
 
1220
  def _add_privacy_bounds(fig, result: Dict[str, Any]):
1221
  """Add privacy bounds comparison across confidence levels"""
 
1278
  fig.update_yaxes(title_text="Processing Completion %", row=2, col=3, range=[0, 100])
1279
 
1280
  def create_safe_epsilon_plot(result: Dict[str, Any]) -> go.Figure:
1281
+ """Create simplified epsilon analysis plot"""
1282
  try:
1283
  if "error" in result:
1284
+ return _create_error_figure(result)
 
 
 
 
 
 
1285
 
1286
  epsilon_bounds = result.get("epsilon_bounds", {})
 
1287
  confidence_levels = [90, 95, 99]
1288
  epsilon_values = [epsilon_bounds.get(f"eps_lb_{conf}", 0) for conf in confidence_levels]
1289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1290
  fig = go.Figure()
1291
 
1292
+ # Simple bar chart
1293
  fig.add_trace(go.Bar(
1294
  x=[f"{conf}%" for conf in confidence_levels],
1295
  y=epsilon_values,
1296
+ marker_color='#2563eb',
1297
+ marker_line=dict(color='#1e40af', width=1),
1298
+ text=[f"{eps:.6f}" for eps in epsilon_values],
1299
+ textposition='outside',
1300
+ textfont=dict(size=11, color="#000000"),
1301
+ hovertemplate="<b>%{x} Confidence</b><br>Epsilon: %{y:.6f}<extra></extra>",
1302
+ showlegend=False
1303
  ))
1304
 
 
 
 
 
 
 
 
 
 
 
 
1305
  fig.update_layout(
1306
+ title="Privacy Budget Analysis",
1307
  xaxis_title="Confidence Level",
1308
+ yaxis_title="Epsilon Lower Bound",
1309
+ plot_bgcolor="white",
1310
+ paper_bgcolor="white",
1311
+ font=dict(family="Arial, sans-serif", size=12, color="#000000"),
1312
+ height=400,
1313
+ margin=dict(t=80, b=50, l=60, r=60)
1314
  )
1315
 
1316
  return fig
1317
 
1318
  except Exception as e:
1319
  logger.error(f"Epsilon plot creation failed: {e}")
1320
+ return _create_error_figure({"error": str(e)})
 
 
 
 
 
 
 
1321
 
1322
  def generate_safe_report(result: Dict[str, Any]) -> str:
1323
  """Generate safe executive report with error handling"""
 
2089
  try:
2090
  # Update status to running
2091
  yield (
2092
+ gr.update(value="Audit in progress. Processing your datasets and running privacy analysis."),
2093
  gr.update(), gr.update(), gr.update(), gr.update(), gr.update(visible=False)
2094
  )
2095
 
 
2100
  if result[0] and "error" not in result[0]:
2101
  risk_level = result[0].get("privacy_assessment", {}).get("risk_level", "UNKNOWN")
2102
  epsilon = result[0].get("privacy_assessment", {}).get("primary_epsilon", 0)
2103
+ status_msg = f"Audit completed successfully.\n\nRisk Level: {risk_level}\nEpsilon-DP Bound: {epsilon:.6f}"
2104
  else:
2105
  error_msg = result[0].get("error", "Unknown error") if result[0] else "Unknown error"
2106
+ status_msg = f"Audit failed: {error_msg}"
2107
 
2108
  # Make export visible if successful
2109
  export_visible = result[4] is not None
 
2121
  error_msg = f"Interface error: {str(e)}"
2122
  logger.error(error_msg)
2123
  yield (
2124
+ gr.update(value=f"Interface Error: {error_msg}"),
2125
+ {"error": error_msg}, None, None, f"Error: {error_msg}", gr.update(visible=False)
2126
  )
2127
 
2128
  # Connect the interface - FIXED: Now returns 6 outputs
logs/privacy_audit_detailed.log CHANGED
@@ -37,3 +37,9 @@
37
  2025-09-07 02:50:30,255 - app - INFO - __init__:265 - Initialized Privacy Auditor - Session: 2d9998de
38
  2025-09-07 02:50:30,255 - app - INFO - __init__:266 - Configuration: {'confidence_level': 0.95, 'subsample_size': None, 'categorical_encoding': 'onehot', 'numerical_scaling': 'standard', 'distance_metric': 'euclidean', 'enable_preprocessing_report': True, 'max_file_size_mb': 500, 'timeout_seconds': 300, 'enable_data_validation': True, 'chunk_size': 10000, 'max_categories_onehot': 50}
39
  2025-09-07 02:50:30,255 - app - INFO - <module>:999 - Privacy auditor initialized successfully
 
 
 
 
 
 
 
37
  2025-09-07 02:50:30,255 - app - INFO - __init__:265 - Initialized Privacy Auditor - Session: 2d9998de
38
  2025-09-07 02:50:30,255 - app - INFO - __init__:266 - Configuration: {'confidence_level': 0.95, 'subsample_size': None, 'categorical_encoding': 'onehot', 'numerical_scaling': 'standard', 'distance_metric': 'euclidean', 'enable_preprocessing_report': True, 'max_file_size_mb': 500, 'timeout_seconds': 300, 'enable_data_validation': True, 'chunk_size': 10000, 'max_categories_onehot': 50}
39
  2025-09-07 02:50:30,255 - app - INFO - <module>:999 - Privacy auditor initialized successfully
40
+ 2025-09-07 03:03:38,859 - app - INFO - <module>:51 - Privacy Auditor Starting - 2025-09-07 03:03:38
41
+ 2025-09-07 03:03:38,860 - app - INFO - __init__:265 - Initialized Privacy Auditor - Session: 852aeeb3
42
+ 2025-09-07 03:03:38,860 - app - INFO - __init__:266 - Configuration: {'confidence_level': 0.95, 'subsample_size': None, 'categorical_encoding': 'onehot', 'numerical_scaling': 'standard', 'distance_metric': 'euclidean', 'enable_preprocessing_report': True, 'max_file_size_mb': 500, 'timeout_seconds': 300, 'enable_data_validation': True, 'chunk_size': 10000, 'max_categories_onehot': 50}
43
+ 2025-09-07 03:03:38,860 - app - INFO - <module>:999 - Privacy auditor initialized successfully
44
+ 2025-09-07 03:03:39,448 - httpx - INFO - _send_single_request:1038 - HTTP Request: GET https://checkip.amazonaws.com/ "HTTP/1.1 200 "
45
+ 2025-09-07 03:03:39,804 - httpx - INFO - _send_single_request:1038 - HTTP Request: GET https://api.gradio.app/pkg-version "HTTP/1.1 200 OK"