prithivMLmods commited on
Commit
3f5a8a6
·
verified ·
1 Parent(s): eaa26b4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -97
app.py CHANGED
@@ -177,7 +177,6 @@ def infer(
177
 
178
  # --- FastAPI Endpoints ---
179
  def get_example_items():
180
- # Defined exactly to support single and multi-image examples.
181
  return [
182
  {
183
  "urls": ["/example-file/I1.jpg", "/example-file/I2.jpg"],
@@ -345,8 +344,8 @@ async def homepage(request: Request):
345
  display: grid;
346
  grid-template-columns: 420px 1fr;
347
  gap: 24px;
348
- align-items: stretch; /* Forces both panels to be equal height */
349
- height: 650px; /* Locked maximum height */
350
  }}
351
 
352
  .panel {{
@@ -365,10 +364,9 @@ async def homepage(request: Request):
365
  border-bottom: 1px solid var(--ub-border);
366
  font-weight: 500;
367
  font-size: 1.1rem;
368
- flex-shrink: 0; /* Header won't shrink */
369
  }}
370
 
371
- /* Scrollable inner body for Settings */
372
  .panel-body-scroll {{
373
  flex: 1;
374
  padding: 20px;
@@ -441,30 +439,73 @@ async def homepage(request: Request):
441
 
442
  /* The (+) Button */
443
  .add-more-btn {{
444
- display: flex;
445
- align-items: center;
446
- justify-content: center;
447
- border: 2px dashed var(--ub-muted);
448
- border-radius: 4px;
449
- color: var(--ub-muted);
450
- font-size: 26px;
451
- cursor: pointer;
452
- aspect-ratio: 1;
453
- transition: all 0.2s;
454
- background: transparent;
455
  }}
456
  .add-more-btn:hover {{
457
- border-color: var(--ub-orange);
458
- color: var(--ub-orange);
459
  background: rgba(233,84,32,0.05);
460
  }}
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  /* Buttons */
463
  .btn {{
464
  width: 100%; padding: 14px; border: none; border-radius: 4px;
465
  font-size: 16px; font-weight: 700; cursor: pointer;
466
  transition: opacity 0.2s, background 0.2s;
467
- margin-top: auto; /* Pushes button to bottom if space exists */
468
  flex-shrink: 0;
469
  }}
470
  .btn-primary {{
@@ -474,24 +515,12 @@ async def homepage(request: Request):
474
  .btn-primary:hover {{ background: var(--ub-orange-hover); }}
475
  .btn:disabled {{ opacity: 0.6; cursor: not-allowed; }}
476
 
477
- /* Advanced Accordion (+/-) */
478
- .advanced-toggle {{
479
- width: 100%; background: none; border: none; color: var(--ub-orange);
480
- text-align: left; padding: 10px 0; font-weight: 500; cursor: pointer;
481
- display: flex; justify-content: space-between; align-items: center;
482
- flex-shrink: 0;
483
- }}
484
- .advanced-icon {{ font-weight: bold; font-size: 18px; line-height: 1; }}
485
- .advanced-body {{ display: none; padding-top: 10px; flex-shrink: 0; }}
486
- .advanced-body.open {{ display: block; }}
487
- .grid-2 {{ display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }}
488
-
489
  /* SLIDER CONTAINER */
490
  .panel-body-slider {{
491
  flex: 1;
492
  display: flex;
493
  flex-direction: column;
494
- padding: 0; /* Remove padding to let stage fill perfectly */
495
  position: relative;
496
  }}
497
  .slider-stage {{
@@ -503,80 +532,48 @@ async def homepage(request: Request):
503
  align-items: center;
504
  justify-content: center;
505
  }}
506
- .slider-empty {{
507
- color: var(--ub-muted);
508
- text-align: center;
509
- z-index: 1;
510
- }}
511
 
512
  .slider-img {{
513
- position: absolute;
514
- top: 0; left: 0;
515
- width: 100%; height: 100%;
516
- object-fit: contain;
517
- display: none;
518
- user-select: none;
519
- -webkit-user-drag: none;
520
  }}
521
-
522
- /* The Small Decoder image sits on top and gets clipped */
523
  #imgSmall {{ clip-path: inset(0 50% 0 0); }}
524
 
525
  .slider-handle {{
526
- position: absolute;
527
- left: 50%;
528
- top: 0; bottom: 0;
529
- width: 4px;
530
- background: var(--ub-orange);
531
- cursor: ew-resize;
532
- display: none;
533
- z-index: 10;
534
  }}
535
  .slider-handle::after {{
536
- content: '◀ ▶';
537
- position: absolute;
538
- top: 50%; left: 50%;
539
  transform: translate(-50%, -50%);
540
- width: 40px; height: 30px;
541
- background: var(--ub-orange);
542
- color: white;
543
- border-radius: 15px;
544
  display: flex; align-items: center; justify-content: center;
545
- font-size: 10px; font-weight: bold;
546
- box-shadow: 0 2px 6px rgba(0,0,0,0.5);
547
  }}
548
 
549
  .slider-labels {{
550
- position: absolute;
551
- top: 15px; left: 15px; right: 15px;
552
- display: none;
553
- justify-content: space-between;
554
- pointer-events: none;
555
- z-index: 5;
556
  }}
557
  .badge {{
558
- background: rgba(0,0,0,0.6);
559
- color: white;
560
- padding: 6px 12px;
561
- border-radius: 20px;
562
- font-size: 13px;
563
- backdrop-filter: blur(4px);
564
  }}
565
 
566
  .loader {{
567
- position: absolute; inset: 0;
568
- background: rgba(0,0,0,0.7);
569
  display: none; flex-direction: column;
570
- align-items: center; justify-content: center;
571
- z-index: 20;
572
  }}
573
  .spinner {{
574
- width: 40px; height: 40px;
575
- border: 4px solid rgba(255,255,255,0.2);
576
- border-top-color: var(--ub-orange);
577
- border-radius: 50%;
578
- animation: spin 1s linear infinite;
579
- margin-bottom: 15px;
580
  }}
581
 
582
  /* Examples */
@@ -591,14 +588,8 @@ async def homepage(request: Request):
591
  }}
592
  .ex-card:hover {{ transform: translateY(-3px); box-shadow: 0 6px 16px rgba(0,0,0,0.3); }}
593
 
594
- .ex-card-img-wrap {{
595
- width: 100%; aspect-ratio: 1;
596
- display: flex; background: #000;
597
- }}
598
- .ex-card-img-wrap img {{
599
- height: 100%; object-fit: cover;
600
- }}
601
-
602
  .ex-card p {{ padding: 12px; margin: 0; font-size: 13px; color: var(--ub-muted); line-height: 1.4; }}
603
 
604
  @keyframes spin {{ to {{ transform: rotate(360deg); }} }}
@@ -672,8 +663,14 @@ async def homepage(request: Request):
672
  </div>
673
  </div>
674
 
675
- <div style="flex:1;"></div>
676
- <button class="btn btn-primary" id="runBtn" style="margin-top: 20px;">Run Comparison</button>
 
 
 
 
 
 
677
  </div>
678
  </div>
679
 
@@ -725,6 +722,17 @@ async def homepage(request: Request):
725
  const promptInput = document.getElementById('promptInput');
726
  const runBtn = document.getElementById('runBtn');
727
 
 
 
 
 
 
 
 
 
 
 
 
728
  // Slider Elements
729
  const sliderStage = document.getElementById('sliderStage');
730
  const imgStd = document.getElementById('imgStd');
@@ -788,6 +796,7 @@ async def homepage(request: Request):
788
  filesState = [];
789
  renderPreviews();
790
  promptInput.value = text;
 
791
 
792
  try {{
793
  for(let i=0; i<urls.length; i++) {{
@@ -797,8 +806,20 @@ async def homepage(request: Request):
797
  filesState.push(new File([blob], filename, {{type: blob.type}}));
798
  }}
799
  renderPreviews();
 
 
800
  window.scrollTo({{top: 0, behavior: 'smooth'}});
801
- }} catch (e) {{ alert('Failed to load example image.'); }}
 
 
 
 
 
 
 
 
 
 
802
  }}
803
 
804
  const exGrid = document.getElementById('examplesGrid');
@@ -853,7 +874,12 @@ async def homepage(request: Request):
853
  // --- Form Submission ---
854
  runBtn.onclick = async () => {{
855
  const prompt = promptInput.value.trim();
856
- if(!prompt) return alert("Enter a prompt");
 
 
 
 
 
857
 
858
  const fd = new FormData();
859
  fd.append('prompt', prompt);
@@ -869,11 +895,15 @@ async def homepage(request: Request):
869
  loader.style.display = 'flex';
870
  runBtn.disabled = true;
871
 
 
 
872
  try {{
873
  const res = await fetch('/api/compare', {{ method: 'POST', body: fd }});
874
  const data = await res.json();
875
 
876
  if(data.success) {{
 
 
877
  imgStd.src = data.std_url;
878
  imgSmall.src = data.small_url;
879
 
@@ -889,13 +919,16 @@ async def homepage(request: Request):
889
  updateSlider(rect.left + rect.width / 2);
890
  }};
891
  }} else {{
 
892
  alert('Error: ' + data.error);
893
  }}
894
  }} catch(e) {{
 
895
  alert('Failed to connect to server.');
896
  }} finally {{
897
  loader.style.display = 'none';
898
  runBtn.disabled = false;
 
899
  }}
900
  }};
901
  </script>
 
177
 
178
  # --- FastAPI Endpoints ---
179
  def get_example_items():
 
180
  return [
181
  {
182
  "urls": ["/example-file/I1.jpg", "/example-file/I2.jpg"],
 
344
  display: grid;
345
  grid-template-columns: 420px 1fr;
346
  gap: 24px;
347
+ align-items: stretch;
348
+ height: 650px;
349
  }}
350
 
351
  .panel {{
 
364
  border-bottom: 1px solid var(--ub-border);
365
  font-weight: 500;
366
  font-size: 1.1rem;
367
+ flex-shrink: 0;
368
  }}
369
 
 
370
  .panel-body-scroll {{
371
  flex: 1;
372
  padding: 20px;
 
439
 
440
  /* The (+) Button */
441
  .add-more-btn {{
442
+ display: flex; align-items: center; justify-content: center;
443
+ border: 2px dashed var(--ub-muted); border-radius: 4px;
444
+ color: var(--ub-muted); font-size: 26px; cursor: pointer;
445
+ aspect-ratio: 1; transition: all 0.2s; background: transparent;
 
 
 
 
 
 
 
446
  }}
447
  .add-more-btn:hover {{
448
+ border-color: var(--ub-orange); color: var(--ub-orange);
 
449
  background: rgba(233,84,32,0.05);
450
  }}
451
 
452
+ /* Advanced Accordion */
453
+ .advanced-toggle {{
454
+ width: 100%; background: none; border: none; color: var(--ub-orange);
455
+ text-align: left; padding: 10px 0; font-weight: 500; cursor: pointer;
456
+ display: flex; justify-content: space-between; align-items: center;
457
+ flex-shrink: 0;
458
+ }}
459
+ .advanced-icon {{ font-weight: bold; font-size: 18px; line-height: 1; }}
460
+ .advanced-body {{ display: none; padding-top: 10px; flex-shrink: 0; }}
461
+ .advanced-body.open {{ display: block; }}
462
+ .grid-2 {{ display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }}
463
+
464
+ /* Status Container (Execution Log) */
465
+ .status-container {{
466
+ margin-top: 20px;
467
+ margin-bottom: 20px;
468
+ border: 1px solid var(--ub-border);
469
+ border-radius: 4px;
470
+ background: #200014; /* deep ubuntu terminal background */
471
+ display: flex;
472
+ flex-direction: column;
473
+ flex: 1;
474
+ min-height: 100px;
475
+ max-height: 200px; /* limits expansion if advanced is closed */
476
+ }}
477
+ .status-header {{
478
+ padding: 8px 12px;
479
+ font-size: 11px;
480
+ font-weight: 700;
481
+ color: var(--ub-muted);
482
+ background: rgba(0,0,0,0.4);
483
+ border-bottom: 1px solid var(--ub-border);
484
+ text-transform: uppercase;
485
+ letter-spacing: 0.5px;
486
+ flex-shrink: 0;
487
+ }}
488
+ .status-log {{
489
+ padding: 10px;
490
+ font-family: 'Courier New', Courier, monospace;
491
+ font-size: 12px;
492
+ color: #eeeeee;
493
+ overflow-y: auto;
494
+ flex: 1;
495
+ display: flex;
496
+ flex-direction: column;
497
+ gap: 4px;
498
+ }}
499
+ .log-time {{ color: #777; margin-right: 8px; }}
500
+ .log-info {{ color: #5bc0eb; }}
501
+ .log-success {{ color: #9bc53d; }}
502
+ .log-error {{ color: #ff5e5b; }}
503
+
504
  /* Buttons */
505
  .btn {{
506
  width: 100%; padding: 14px; border: none; border-radius: 4px;
507
  font-size: 16px; font-weight: 700; cursor: pointer;
508
  transition: opacity 0.2s, background 0.2s;
 
509
  flex-shrink: 0;
510
  }}
511
  .btn-primary {{
 
515
  .btn-primary:hover {{ background: var(--ub-orange-hover); }}
516
  .btn:disabled {{ opacity: 0.6; cursor: not-allowed; }}
517
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  /* SLIDER CONTAINER */
519
  .panel-body-slider {{
520
  flex: 1;
521
  display: flex;
522
  flex-direction: column;
523
+ padding: 0;
524
  position: relative;
525
  }}
526
  .slider-stage {{
 
532
  align-items: center;
533
  justify-content: center;
534
  }}
535
+ .slider-empty {{ color: var(--ub-muted); text-align: center; z-index: 1; }}
 
 
 
 
536
 
537
  .slider-img {{
538
+ position: absolute; top: 0; left: 0;
539
+ width: 100%; height: 100%; object-fit: contain;
540
+ display: none; user-select: none; -webkit-user-drag: none;
 
 
 
 
541
  }}
 
 
542
  #imgSmall {{ clip-path: inset(0 50% 0 0); }}
543
 
544
  .slider-handle {{
545
+ position: absolute; left: 50%; top: 0; bottom: 0;
546
+ width: 4px; background: var(--ub-orange);
547
+ cursor: ew-resize; display: none; z-index: 10;
 
 
 
 
 
548
  }}
549
  .slider-handle::after {{
550
+ content: '◀ ▶'; position: absolute; top: 50%; left: 50%;
 
 
551
  transform: translate(-50%, -50%);
552
+ width: 40px; height: 30px; background: var(--ub-orange);
553
+ color: white; border-radius: 15px;
 
 
554
  display: flex; align-items: center; justify-content: center;
555
+ font-size: 10px; font-weight: bold; box-shadow: 0 2px 6px rgba(0,0,0,0.5);
 
556
  }}
557
 
558
  .slider-labels {{
559
+ position: absolute; top: 15px; left: 15px; right: 15px;
560
+ display: none; justify-content: space-between;
561
+ pointer-events: none; z-index: 5;
 
 
 
562
  }}
563
  .badge {{
564
+ background: rgba(0,0,0,0.6); color: white; padding: 6px 12px;
565
+ border-radius: 20px; font-size: 13px; backdrop-filter: blur(4px);
 
 
 
 
566
  }}
567
 
568
  .loader {{
569
+ position: absolute; inset: 0; background: rgba(0,0,0,0.7);
 
570
  display: none; flex-direction: column;
571
+ align-items: center; justify-content: center; z-index: 20;
 
572
  }}
573
  .spinner {{
574
+ width: 40px; height: 40px; border: 4px solid rgba(255,255,255,0.2);
575
+ border-top-color: var(--ub-orange); border-radius: 50%;
576
+ animation: spin 1s linear infinite; margin-bottom: 15px;
 
 
 
577
  }}
578
 
579
  /* Examples */
 
588
  }}
589
  .ex-card:hover {{ transform: translateY(-3px); box-shadow: 0 6px 16px rgba(0,0,0,0.3); }}
590
 
591
+ .ex-card-img-wrap {{ width: 100%; aspect-ratio: 1; display: flex; background: #000; }}
592
+ .ex-card-img-wrap img {{ height: 100%; object-fit: cover; }}
 
 
 
 
 
 
593
  .ex-card p {{ padding: 12px; margin: 0; font-size: 13px; color: var(--ub-muted); line-height: 1.4; }}
594
 
595
  @keyframes spin {{ to {{ transform: rotate(360deg); }} }}
 
663
  </div>
664
  </div>
665
 
666
+ <div class="status-container">
667
+ <div class="status-header">Execution Log</div>
668
+ <div class="status-log" id="statusLog">
669
+ <div><span class="log-time">[{DEVICE_LABEL}]</span><span>System Ready...</span></div>
670
+ </div>
671
+ </div>
672
+
673
+ <button class="btn btn-primary" id="runBtn">Run Comparison</button>
674
  </div>
675
  </div>
676
 
 
722
  const promptInput = document.getElementById('promptInput');
723
  const runBtn = document.getElementById('runBtn');
724
 
725
+ // Status Log
726
+ const statusLog = document.getElementById('statusLog');
727
+
728
+ function logMsg(msg, styleClass="") {{
729
+ const div = document.createElement('div');
730
+ const timeStr = new Date().toLocaleTimeString('en-US', {{hour12:false}});
731
+ div.innerHTML = `<span class="log-time">[${{timeStr}}]</span><span class="${{styleClass}}">${{msg}}</span>`;
732
+ statusLog.appendChild(div);
733
+ statusLog.scrollTop = statusLog.scrollHeight; // auto-scroll to bottom
734
+ }}
735
+
736
  // Slider Elements
737
  const sliderStage = document.getElementById('sliderStage');
738
  const imgStd = document.getElementById('imgStd');
 
796
  filesState = [];
797
  renderPreviews();
798
  promptInput.value = text;
799
+ logMsg("Loading example: " + text, "log-info");
800
 
801
  try {{
802
  for(let i=0; i<urls.length; i++) {{
 
806
  filesState.push(new File([blob], filename, {{type: blob.type}}));
807
  }}
808
  renderPreviews();
809
+
810
+ // Scroll to top
811
  window.scrollTo({{top: 0, behavior: 'smooth'}});
812
+
813
+ // Wait a tiny bit for UI update, then trigger generation
814
+ setTimeout(() => {{
815
+ logMsg("Example loaded. Starting comparison...", "log-info");
816
+ runBtn.click();
817
+ }}, 500);
818
+
819
+ }} catch (e) {{
820
+ logMsg("Failed to load example images.", "log-error");
821
+ alert('Failed to load example image.');
822
+ }}
823
  }}
824
 
825
  const exGrid = document.getElementById('examplesGrid');
 
874
  // --- Form Submission ---
875
  runBtn.onclick = async () => {{
876
  const prompt = promptInput.value.trim();
877
+ if(!prompt) {{
878
+ logMsg("Validation failed: Prompt is empty.", "log-error");
879
+ return alert("Enter a prompt");
880
+ }}
881
+
882
+ logMsg("Initializing generation sequence...", "log-info");
883
 
884
  const fd = new FormData();
885
  fd.append('prompt', prompt);
 
895
  loader.style.display = 'flex';
896
  runBtn.disabled = true;
897
 
898
+ logMsg("Sending request to backend. Running both VAE models...", "log-info");
899
+
900
  try {{
901
  const res = await fetch('/api/compare', {{ method: 'POST', body: fd }});
902
  const data = await res.json();
903
 
904
  if(data.success) {{
905
+ logMsg(`Success! Inference completed. Used seed: ${{data.seed}}`, "log-success");
906
+
907
  imgStd.src = data.std_url;
908
  imgSmall.src = data.small_url;
909
 
 
919
  updateSlider(rect.left + rect.width / 2);
920
  }};
921
  }} else {{
922
+ logMsg("Error processing request: " + data.error, "log-error");
923
  alert('Error: ' + data.error);
924
  }}
925
  }} catch(e) {{
926
+ logMsg("Network or server connection failed.", "log-error");
927
  alert('Failed to connect to server.');
928
  }} finally {{
929
  loader.style.display = 'none';
930
  runBtn.disabled = false;
931
+ logMsg("Sequence finished. Ready for next input.", "");
932
  }}
933
  }};
934
  </script>