usamaalam Claude Opus 4.8 commited on
Commit
d7ae285
Β·
1 Parent(s): 68cf859

Switch to complete dark professional theme

Browse files

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files changed (2) hide show
  1. .streamlit/config.toml +7 -0
  2. app.py +123 -96
.streamlit/config.toml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ [theme]
2
+ base = "dark"
3
+ primaryColor = "#4a9fd4"
4
+ backgroundColor = "#0e1b2e"
5
+ secondaryBackgroundColor = "#17283f"
6
+ textColor = "#e6eef7"
7
+ font = "sans serif"
app.py CHANGED
@@ -24,44 +24,47 @@ st.set_page_config(
24
  initial_sidebar_state="collapsed",
25
  )
26
 
27
- # ── Global CSS ────────────────────────────────────────────────────────────────
28
  st.markdown("""
29
  <style>
30
- /* ── Full-bleed page background to tie header/footer to body ── */
31
- html, body, [data-testid="stAppViewContainer"] {
32
- background-color: #f0f4f9 !important;
33
  }
 
34
  [data-testid="stHeader"] {
35
- background-color: #1a2e50 !important;
36
  }
37
 
38
- /* ── Remove default top padding so our header sits flush ── */
39
  .block-container {
40
- padding-top: 0 !important;
41
- padding-bottom: 2rem;
42
- max-width: 1200px;
43
  }
44
 
45
- /* ── Full-width header banner ── */
46
  .ned-header {
47
- background: linear-gradient(90deg, #1a2e50 0%, #1e3a6e 60%, #1a5276 100%);
48
  color: #ffffff;
49
- padding: 20px 36px 16px 36px;
50
- margin: -1rem -1rem 24px -1rem; /* bleed beyond block-container padding */
51
- border-bottom: 3px solid #4a9fd4;
 
 
52
  }
53
  .ned-header .university {
54
- font-size: 1.2rem;
55
  font-weight: 700;
56
  letter-spacing: 0.4px;
57
  color: #ffffff;
58
  }
59
  .ned-header .meta {
60
- font-size: 0.85rem;
61
- color: #90bfe0;
62
- margin-top: 4px;
63
  display: flex;
64
- gap: 24px;
65
  flex-wrap: wrap;
66
  }
67
  .ned-header .meta span::before {
@@ -69,101 +72,115 @@ html, body, [data-testid="stAppViewContainer"] {
69
  color: #4a9fd4;
70
  }
71
 
72
- /* ── Full-width footer banner ── */
73
  .ned-footer {
74
- background: linear-gradient(90deg, #1a2e50 0%, #1e3a6e 60%, #1a5276 100%);
75
- color: #90bfe0;
76
- padding: 14px 36px;
77
- margin: 32px -1rem -2rem -1rem; /* bleed beyond block-container padding */
78
- border-top: 3px solid #4a9fd4;
 
 
79
  display: flex;
80
  justify-content: space-between;
81
  align-items: center;
82
  flex-wrap: wrap;
83
- gap: 8px;
84
  font-size: 0.82rem;
85
  }
86
- .ned-footer strong { color: #c8dff0; }
87
  .ned-footer .ned-footer-right {
88
- color: #6a9bbf;
89
- font-size: 0.75rem;
90
  text-align: right;
91
  }
92
 
93
- /* ── Content card / white surface ── */
94
- .content-surface {
95
- background: #ffffff;
96
- border-radius: 10px;
97
- padding: 24px 28px;
98
- margin-bottom: 20px;
99
- box-shadow: 0 1px 4px rgba(26,46,80,0.08);
100
- border: 1px solid #dce8f5;
101
- }
102
-
103
  /* ── Metric card ── */
104
  .metric-card {
105
- background: #ffffff;
106
- border: 1px solid #c5d9f0;
107
  border-top: 3px solid #4a9fd4;
108
  border-radius: 8px;
109
  padding: 18px 16px;
110
  text-align: center;
111
- box-shadow: 0 1px 3px rgba(26,46,80,0.07);
112
  }
113
  .metric-card .metric-value {
114
- font-size: 1.9rem;
115
  font-weight: 700;
116
- color: #1a2e50;
117
  }
118
  .metric-card .metric-label {
119
- font-size: 0.78rem;
120
- color: #5a7a9a;
121
  margin-top: 5px;
122
  text-transform: uppercase;
123
- letter-spacing: 0.4px;
124
  }
125
 
126
  /* ── Section headers ── */
127
  .section-header {
128
  font-size: 1.05rem;
129
  font-weight: 700;
130
- color: #1a2e50;
131
  border-bottom: 2px solid #4a9fd4;
132
  padding-bottom: 6px;
133
- margin: 26px 0 14px 0;
134
  text-transform: uppercase;
135
- letter-spacing: 0.5px;
136
  }
137
 
138
  /* ── Info pill ── */
139
  .info-pill {
140
  display: inline-block;
141
- background: #deedf8;
142
- color: #1a4a8a;
143
  border-radius: 20px;
144
  padding: 3px 12px;
145
  font-size: 0.78rem;
146
  font-weight: 600;
147
  margin: 3px 4px 3px 0;
148
- border: 1px solid #b8d4ec;
149
  }
150
 
151
- /* ── Streamlit tab strip β€” match the palette ── */
152
  [data-testid="stTabs"] [data-baseweb="tab-list"] {
153
- background-color: #e8f0f9;
154
  border-radius: 8px 8px 0 0;
155
- padding: 4px 8px 0 8px;
156
  gap: 4px;
 
157
  }
158
  [data-testid="stTabs"] [data-baseweb="tab"] {
159
- color: #4a6a8a;
160
  font-weight: 600;
161
  border-radius: 6px 6px 0 0;
162
  }
163
  [data-testid="stTabs"] [aria-selected="true"] {
164
- color: #1a2e50 !important;
165
  border-bottom: 3px solid #4a9fd4 !important;
166
- background: #ffffff !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
  </style>
169
  """, unsafe_allow_html=True)
@@ -295,12 +312,12 @@ def make_architecture_figure():
295
  ax.set_xlim(0, 11)
296
  ax.set_ylim(0, 5.5)
297
  ax.axis('off')
298
- fig.patch.set_facecolor('#f8fbff')
299
 
300
  def box(x, y, w, h, label, sub="", color="#2c4a7c", text_color="white", fontsize=9):
301
  rect = FancyBboxPatch((x - w/2, y - h/2), w, h,
302
  boxstyle="round,pad=0.08", linewidth=1.2,
303
- edgecolor=color, facecolor=color)
304
  ax.add_patch(rect)
305
  ax.text(x, y + (0.12 if sub else 0), label, ha='center', va='center',
306
  color=text_color, fontsize=fontsize, fontweight='bold')
@@ -318,21 +335,21 @@ def make_architecture_figure():
318
  box(0.8, 1.5, 1.3, 0.65, "ELA Input", "224Γ—224Γ—3", color="#4a9fd4")
319
 
320
  # RGB branch
321
- box(2.8, 4.0, 1.5, 0.65, "ResNet50", "frozen, ImageNet", color="#1a5276")
322
- box(4.5, 4.0, 1.5, 0.65, "GlobalAvgPool", "β†’ 2048-d", color="#1a5276")
323
 
324
  # ELA branch
325
- box(2.8, 2.8, 1.5, 0.65, "Conv2D 32", "3Γ—3, ReLU+BN+Pool", color="#145a32")
326
- box(2.8, 1.9, 1.5, 0.65, "Conv2D 64", "3Γ—3, ReLU+BN+Pool", color="#145a32")
327
- box(2.8, 1.0, 1.5, 0.65, "Conv2D 128", "3Γ—3, ReLU+BN+Pool", color="#145a32")
328
- box(4.5, 1.5, 1.5, 0.65, "GlobalAvgPool", "β†’ 128-d", color="#145a32")
329
 
330
  # Concat
331
- box(6.4, 2.75, 1.3, 0.65, "Concatenate", "2176-d", color="#6e2f8a")
332
 
333
  # Dense head
334
- box(8.0, 2.75, 1.3, 0.65, "Dense 256", "ReLU + Drop 0.5", color="#7d3c98")
335
- box(9.8, 2.75, 1.1, 0.65, "Dense 1", "Sigmoid", color="#922b21")
336
 
337
  # Arrows β€” RGB branch
338
  arrow(1.45, 4.0, 2.05, 4.0)
@@ -365,18 +382,20 @@ def make_architecture_figure():
365
 
366
  # Output label
367
  ax.text(10.6, 2.75, "0 / 1\nAuth /\nForged",
368
- ha='center', va='center', fontsize=8, color="#922b21", fontweight='bold')
369
 
370
  # Legend
371
  legend_items = [
372
  mpatches.Patch(color="#4a9fd4", label="Input"),
373
- mpatches.Patch(color="#1a5276", label="RGB Branch (ResNet50)"),
374
- mpatches.Patch(color="#145a32", label="ELA Branch (Custom CNN)"),
375
- mpatches.Patch(color="#6e2f8a", label="Fusion"),
376
- mpatches.Patch(color="#922b21", label="Output Head"),
377
  ]
378
- ax.legend(handles=legend_items, loc='lower center', ncol=5,
379
- fontsize=7.5, framealpha=0.85, bbox_to_anchor=(0.48, -0.02))
 
 
380
 
381
  fig.tight_layout(pad=0.4)
382
  buf = io.BytesIO()
@@ -638,8 +657,8 @@ Tampered pixels were re-saved at a different quality level; the diff reveals tho
638
  with perf_col2:
639
  # Score distribution bar chart
640
  fig2, ax2 = plt.subplots(figsize=(5, 2.8))
641
- fig2.patch.set_facecolor('#f8fbff')
642
- ax2.set_facecolor('#f8fbff')
643
 
644
  bins = np.linspace(0, 1, 21)
645
  au_scores = np.concatenate([
@@ -650,14 +669,17 @@ Tampered pixels were re-saved at a different quality level; the diff reveals tho
650
  np.random.default_rng(2).beta(30, 0.4, 100),
651
  np.random.default_rng(2).uniform(0.0, 0.5, 10),
652
  ])
653
- ax2.hist(au_scores, bins=bins, alpha=0.75, color='#2ecc71', label='Authentic')
654
- ax2.hist(tp_scores, bins=bins, alpha=0.75, color='#e74c3c', label='Forged')
655
- ax2.axvline(0.5, color='#1a2a4a', lw=1.5, linestyle='--', label='Threshold 0.5')
656
- ax2.set_xlabel("Model score", fontsize=8)
657
- ax2.set_ylabel("Count", fontsize=8)
658
- ax2.set_title("Illustrative score distribution", fontsize=8.5, fontweight='bold')
659
- ax2.legend(fontsize=7.5)
660
- ax2.tick_params(labelsize=7)
 
 
 
661
  fig2.tight_layout(pad=0.5)
662
 
663
  buf2 = io.BytesIO()
@@ -690,20 +712,25 @@ ResNet50 backbone provides complementary texture context but does not dominate.
690
 
691
  with abl_col2:
692
  fig3, ax3 = plt.subplots(figsize=(4.5, 2.6))
693
- fig3.patch.set_facecolor('#f8fbff')
694
- ax3.set_facecolor('#f8fbff')
695
  variants = ['M1\nRGB only', 'M2\nELA only', 'M3\nDual-branch']
696
  aucs = [0.5822, 0.9807, 0.9774]
697
- colors = ['#95a5a6', '#27ae60', '#2980b9']
698
- bars = ax3.bar(variants, aucs, color=colors, width=0.5, edgecolor='white', linewidth=0.8)
 
699
  ax3.set_ylim(0.4, 1.05)
700
- ax3.axhline(1.0, color='#bdc3c7', lw=0.8, linestyle=':')
701
  for bar, val in zip(bars, aucs):
702
  ax3.text(bar.get_x() + bar.get_width()/2, val + 0.01,
703
- f"{val:.4f}", ha='center', va='bottom', fontsize=8, fontweight='bold')
704
- ax3.set_ylabel("AUC-ROC", fontsize=8)
705
- ax3.set_title("Branch Ablation β€” AUC-ROC", fontsize=8.5, fontweight='bold')
706
- ax3.tick_params(labelsize=7.5)
 
 
 
 
707
  fig3.tight_layout(pad=0.5)
708
  buf3 = io.BytesIO()
709
  fig3.savefig(buf3, format='png', dpi=120, bbox_inches='tight',
 
24
  initial_sidebar_state="collapsed",
25
  )
26
 
27
+ # ── Global CSS β€” complete dark professional theme ────────────────────────────
28
  st.markdown("""
29
  <style>
30
+ /* ── Base surfaces ── */
31
+ [data-testid="stAppViewContainer"], .main, .stApp {
32
+ background-color: #0e1b2e !important;
33
  }
34
+ /* Streamlit's own fixed top header β€” make it match so nothing clashes */
35
  [data-testid="stHeader"] {
36
+ background-color: #0e1b2e !important;
37
  }
38
 
39
+ /* Keep clear of Streamlit's fixed top header so our banner isn't clipped */
40
  .block-container {
41
+ padding-top: 2.2rem !important;
42
+ padding-bottom: 1rem;
43
+ max-width: 1180px;
44
  }
45
 
46
+ /* ── Header banner ── */
47
  .ned-header {
48
+ background: linear-gradient(90deg, #122842 0%, #1a3a63 55%, #155674 100%);
49
  color: #ffffff;
50
+ padding: 20px 32px 18px 32px;
51
+ margin: 0 0 22px 0;
52
+ border-radius: 10px;
53
+ border-left: 5px solid #4a9fd4;
54
+ box-shadow: 0 2px 10px rgba(0,0,0,0.35);
55
  }
56
  .ned-header .university {
57
+ font-size: 1.25rem;
58
  font-weight: 700;
59
  letter-spacing: 0.4px;
60
  color: #ffffff;
61
  }
62
  .ned-header .meta {
63
+ font-size: 0.86rem;
64
+ color: #8fc1e6;
65
+ margin-top: 6px;
66
  display: flex;
67
+ gap: 26px;
68
  flex-wrap: wrap;
69
  }
70
  .ned-header .meta span::before {
 
72
  color: #4a9fd4;
73
  }
74
 
75
+ /* ── Footer banner ── */
76
  .ned-footer {
77
+ background: linear-gradient(90deg, #122842 0%, #1a3a63 55%, #155674 100%);
78
+ color: #8fc1e6;
79
+ padding: 16px 32px;
80
+ margin: 30px 0 8px 0;
81
+ border-radius: 10px;
82
+ border-left: 5px solid #4a9fd4;
83
+ box-shadow: 0 2px 10px rgba(0,0,0,0.35);
84
  display: flex;
85
  justify-content: space-between;
86
  align-items: center;
87
  flex-wrap: wrap;
88
+ gap: 10px;
89
  font-size: 0.82rem;
90
  }
91
+ .ned-footer strong { color: #d7e8f6; }
92
  .ned-footer .ned-footer-right {
93
+ color: #6a93b8;
94
+ font-size: 0.74rem;
95
  text-align: right;
96
  }
97
 
 
 
 
 
 
 
 
 
 
 
98
  /* ── Metric card ── */
99
  .metric-card {
100
+ background: #17283f;
101
+ border: 1px solid #2a435f;
102
  border-top: 3px solid #4a9fd4;
103
  border-radius: 8px;
104
  padding: 18px 16px;
105
  text-align: center;
106
+ box-shadow: 0 2px 8px rgba(0,0,0,0.3);
107
  }
108
  .metric-card .metric-value {
109
+ font-size: 1.95rem;
110
  font-weight: 700;
111
+ color: #6fb8e8;
112
  }
113
  .metric-card .metric-label {
114
+ font-size: 0.76rem;
115
+ color: #9fb6cf;
116
  margin-top: 5px;
117
  text-transform: uppercase;
118
+ letter-spacing: 0.5px;
119
  }
120
 
121
  /* ── Section headers ── */
122
  .section-header {
123
  font-size: 1.05rem;
124
  font-weight: 700;
125
+ color: #cfe4f6;
126
  border-bottom: 2px solid #4a9fd4;
127
  padding-bottom: 6px;
128
+ margin: 28px 0 14px 0;
129
  text-transform: uppercase;
130
+ letter-spacing: 0.6px;
131
  }
132
 
133
  /* ── Info pill ── */
134
  .info-pill {
135
  display: inline-block;
136
+ background: #1c3a59;
137
+ color: #8fc1e6;
138
  border-radius: 20px;
139
  padding: 3px 12px;
140
  font-size: 0.78rem;
141
  font-weight: 600;
142
  margin: 3px 4px 3px 0;
143
+ border: 1px solid #2f5478;
144
  }
145
 
146
+ /* ── Tab strip ── */
147
  [data-testid="stTabs"] [data-baseweb="tab-list"] {
148
+ background-color: #142336;
149
  border-radius: 8px 8px 0 0;
150
+ padding: 5px 8px 0 8px;
151
  gap: 4px;
152
+ border-bottom: 1px solid #2a435f;
153
  }
154
  [data-testid="stTabs"] [data-baseweb="tab"] {
155
+ color: #8da7c2;
156
  font-weight: 600;
157
  border-radius: 6px 6px 0 0;
158
  }
159
  [data-testid="stTabs"] [aria-selected="true"] {
160
+ color: #6fb8e8 !important;
161
  border-bottom: 3px solid #4a9fd4 !important;
162
+ background: #17283f !important;
163
+ }
164
+
165
+ /* ── Tables ── */
166
+ .stMarkdown table {
167
+ border-collapse: collapse;
168
+ width: 100%;
169
+ }
170
+ .stMarkdown table th {
171
+ background-color: #1a3050 !important;
172
+ color: #cfe4f6 !important;
173
+ border: 1px solid #2a435f !important;
174
+ }
175
+ .stMarkdown table td {
176
+ background-color: #142336 !important;
177
+ color: #d3e0ee !important;
178
+ border: 1px solid #2a435f !important;
179
+ }
180
+
181
+ /* ── Code blocks ── */
182
+ .stCodeBlock, pre {
183
+ background-color: #0a1626 !important;
184
  }
185
  </style>
186
  """, unsafe_allow_html=True)
 
312
  ax.set_xlim(0, 11)
313
  ax.set_ylim(0, 5.5)
314
  ax.axis('off')
315
+ fig.patch.set_facecolor('#0e1b2e')
316
 
317
  def box(x, y, w, h, label, sub="", color="#2c4a7c", text_color="white", fontsize=9):
318
  rect = FancyBboxPatch((x - w/2, y - h/2), w, h,
319
  boxstyle="round,pad=0.08", linewidth=1.2,
320
+ edgecolor="#4a9fd4", facecolor=color)
321
  ax.add_patch(rect)
322
  ax.text(x, y + (0.12 if sub else 0), label, ha='center', va='center',
323
  color=text_color, fontsize=fontsize, fontweight='bold')
 
335
  box(0.8, 1.5, 1.3, 0.65, "ELA Input", "224Γ—224Γ—3", color="#4a9fd4")
336
 
337
  # RGB branch
338
+ box(2.8, 4.0, 1.5, 0.65, "ResNet50", "frozen, ImageNet", color="#2e7bb0")
339
+ box(4.5, 4.0, 1.5, 0.65, "GlobalAvgPool", "β†’ 2048-d", color="#2e7bb0")
340
 
341
  # ELA branch
342
+ box(2.8, 2.8, 1.5, 0.65, "Conv2D 32", "3Γ—3, ReLU+BN+Pool", color="#2a8f56")
343
+ box(2.8, 1.9, 1.5, 0.65, "Conv2D 64", "3Γ—3, ReLU+BN+Pool", color="#2a8f56")
344
+ box(2.8, 1.0, 1.5, 0.65, "Conv2D 128", "3Γ—3, ReLU+BN+Pool", color="#2a8f56")
345
+ box(4.5, 1.5, 1.5, 0.65, "GlobalAvgPool", "β†’ 128-d", color="#2a8f56")
346
 
347
  # Concat
348
+ box(6.4, 2.75, 1.3, 0.65, "Concatenate", "2176-d", color="#9b59b6")
349
 
350
  # Dense head
351
+ box(8.0, 2.75, 1.3, 0.65, "Dense 256", "ReLU + Drop 0.5", color="#8e44ad")
352
+ box(9.8, 2.75, 1.1, 0.65, "Dense 1", "Sigmoid", color="#c0392b")
353
 
354
  # Arrows β€” RGB branch
355
  arrow(1.45, 4.0, 2.05, 4.0)
 
382
 
383
  # Output label
384
  ax.text(10.6, 2.75, "0 / 1\nAuth /\nForged",
385
+ ha='center', va='center', fontsize=8, color="#e8a0a0", fontweight='bold')
386
 
387
  # Legend
388
  legend_items = [
389
  mpatches.Patch(color="#4a9fd4", label="Input"),
390
+ mpatches.Patch(color="#2e7bb0", label="RGB Branch (ResNet50)"),
391
+ mpatches.Patch(color="#2a8f56", label="ELA Branch (Custom CNN)"),
392
+ mpatches.Patch(color="#9b59b6", label="Fusion"),
393
+ mpatches.Patch(color="#c0392b", label="Output Head"),
394
  ]
395
+ leg = ax.legend(handles=legend_items, loc='lower center', ncol=5,
396
+ fontsize=7.5, framealpha=0.0, bbox_to_anchor=(0.48, -0.02),
397
+ labelcolor='#c8dff0')
398
+ leg.get_frame().set_edgecolor('#2a435f')
399
 
400
  fig.tight_layout(pad=0.4)
401
  buf = io.BytesIO()
 
657
  with perf_col2:
658
  # Score distribution bar chart
659
  fig2, ax2 = plt.subplots(figsize=(5, 2.8))
660
+ fig2.patch.set_facecolor('#0e1b2e')
661
+ ax2.set_facecolor('#142336')
662
 
663
  bins = np.linspace(0, 1, 21)
664
  au_scores = np.concatenate([
 
669
  np.random.default_rng(2).beta(30, 0.4, 100),
670
  np.random.default_rng(2).uniform(0.0, 0.5, 10),
671
  ])
672
+ ax2.hist(au_scores, bins=bins, alpha=0.8, color='#2ecc71', label='Authentic')
673
+ ax2.hist(tp_scores, bins=bins, alpha=0.8, color='#e74c3c', label='Forged')
674
+ ax2.axvline(0.5, color='#e6eef7', lw=1.5, linestyle='--', label='Threshold 0.5')
675
+ ax2.set_xlabel("Model score", fontsize=8, color='#c8dff0')
676
+ ax2.set_ylabel("Count", fontsize=8, color='#c8dff0')
677
+ ax2.set_title("Illustrative score distribution", fontsize=8.5,
678
+ fontweight='bold', color='#cfe4f6')
679
+ leg2 = ax2.legend(fontsize=7.5, framealpha=0.0, labelcolor='#c8dff0')
680
+ ax2.tick_params(labelsize=7, colors='#9fb6cf')
681
+ for spine in ax2.spines.values():
682
+ spine.set_color('#2a435f')
683
  fig2.tight_layout(pad=0.5)
684
 
685
  buf2 = io.BytesIO()
 
712
 
713
  with abl_col2:
714
  fig3, ax3 = plt.subplots(figsize=(4.5, 2.6))
715
+ fig3.patch.set_facecolor('#0e1b2e')
716
+ ax3.set_facecolor('#142336')
717
  variants = ['M1\nRGB only', 'M2\nELA only', 'M3\nDual-branch']
718
  aucs = [0.5822, 0.9807, 0.9774]
719
+ colors = ['#7f8c9a', '#2ecc71', '#4a9fd4']
720
+ bars = ax3.bar(variants, aucs, color=colors, width=0.5,
721
+ edgecolor='#0e1b2e', linewidth=0.8)
722
  ax3.set_ylim(0.4, 1.05)
723
+ ax3.axhline(1.0, color='#3a5575', lw=0.8, linestyle=':')
724
  for bar, val in zip(bars, aucs):
725
  ax3.text(bar.get_x() + bar.get_width()/2, val + 0.01,
726
+ f"{val:.4f}", ha='center', va='bottom', fontsize=8,
727
+ fontweight='bold', color='#cfe4f6')
728
+ ax3.set_ylabel("AUC-ROC", fontsize=8, color='#c8dff0')
729
+ ax3.set_title("Branch Ablation β€” AUC-ROC", fontsize=8.5,
730
+ fontweight='bold', color='#cfe4f6')
731
+ ax3.tick_params(labelsize=7.5, colors='#9fb6cf')
732
+ for spine in ax3.spines.values():
733
+ spine.set_color('#2a435f')
734
  fig3.tight_layout(pad=0.5)
735
  buf3 = io.BytesIO()
736
  fig3.savefig(buf3, format='png', dpi=120, bbox_inches='tight',