Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,810 +1,897 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
-
import
|
| 3 |
-
import
|
| 4 |
-
import
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
#
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
#
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
#
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
#
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
#
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
#
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
# --- 6. PAGE LAYOUT FUNCTIONS ---
|
| 160 |
-
|
| 161 |
-
def render_navbar():
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
|
| 191 |
-
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
def auth_page():
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
def render_dashboard_navigation():
|
| 258 |
-
|
| 259 |
|
| 260 |
-
|
| 261 |
|
| 262 |
-
|
| 263 |
-
|
| 264 |
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
|
| 286 |
-
|
| 287 |
-
|
| 288 |
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
|
| 294 |
-
|
| 295 |
|
| 296 |
-
def render_dashboard_content(section_key):
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
|
| 301 |
-
|
| 302 |
|
| 303 |
-
|
| 304 |
-
|
| 305 |
|
| 306 |
-
|
| 307 |
-
|
| 308 |
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
|
| 313 |
-
|
| 314 |
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
|
| 334 |
-
|
| 335 |
-
|
| 336 |
|
| 337 |
-
|
| 338 |
-
|
| 339 |
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
def dashboard_page():
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
|
| 357 |
-
|
| 358 |
-
|
| 359 |
|
| 360 |
-
|
| 361 |
-
|
| 362 |
|
| 363 |
|
| 364 |
-
def render_item_details(item):
|
| 365 |
-
|
| 366 |
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
|
| 371 |
-
|
| 372 |
|
| 373 |
-
|
| 374 |
|
| 375 |
-
|
| 376 |
-
|
| 377 |
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
|
| 389 |
-
|
| 390 |
|
| 391 |
-
|
| 392 |
-
|
| 393 |
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
|
| 402 |
-
|
| 403 |
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
|
| 429 |
-
|
| 430 |
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
|
| 443 |
|
| 444 |
-
def bio_ds_page():
|
| 445 |
-
|
| 446 |
|
| 447 |
-
|
| 448 |
|
| 449 |
-
|
| 450 |
-
|
| 451 |
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
|
| 466 |
-
|
| 467 |
-
|
| 468 |
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
|
| 475 |
-
|
| 476 |
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
|
| 481 |
-
|
| 482 |
|
| 483 |
-
|
| 484 |
-
|
| 485 |
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
|
| 506 |
-
|
| 507 |
-
|
| 508 |
|
| 509 |
-
|
| 510 |
-
|
| 511 |
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
| 515 |
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
|
| 534 |
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
# --- 7. MAIN APPLICATION ROUTER ---
|
| 558 |
-
|
| 559 |
-
def main_app():
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
| 575 |
|
| 576 |
-
|
| 577 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
|
| 604 |
-
|
| 605 |
|
| 606 |
-
|
| 607 |
-
|
| 608 |
-
|
| 609 |
-
|
| 610 |
-
|
| 611 |
-
|
| 612 |
-
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
| 616 |
-
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
| 620 |
-
|
| 621 |
-
|
| 622 |
-
|
| 623 |
-
|
| 624 |
-
|
| 625 |
-
|
| 626 |
-
|
| 627 |
-
|
| 628 |
-
|
| 629 |
-
|
| 630 |
-
|
| 631 |
-
|
| 632 |
-
|
| 633 |
-
|
| 634 |
-
|
| 635 |
-
|
| 636 |
-
|
| 637 |
-
|
| 638 |
-
|
| 639 |
-
|
| 640 |
-
|
| 641 |
-
|
| 642 |
-
|
| 643 |
-
|
| 644 |
-
|
| 645 |
-
|
| 646 |
|
| 647 |
-
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
|
| 651 |
-
|
| 652 |
-
|
| 653 |
-
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
-
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
|
| 662 |
-
|
| 663 |
-
|
| 664 |
-
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
|
| 671 |
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
|
| 694 |
-
|
| 695 |
-
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
|
| 705 |
-
|
| 706 |
-
|
| 707 |
-
|
| 708 |
-
|
| 709 |
-
|
| 710 |
-
|
| 711 |
|
| 712 |
-
|
| 713 |
-
|
| 714 |
-
|
| 715 |
-
|
| 716 |
-
|
| 717 |
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
| 721 |
-
|
| 722 |
-
|
| 723 |
-
|
| 724 |
-
|
| 725 |
-
|
| 726 |
-
|
| 727 |
-
|
| 728 |
-
|
| 729 |
-
|
| 730 |
|
| 731 |
-
|
| 732 |
-
|
| 733 |
-
|
| 734 |
-
|
| 735 |
-
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
|
| 741 |
-
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
|
| 761 |
-
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
| 769 |
|
| 770 |
-
|
| 771 |
-
|
| 772 |
-
|
| 773 |
-
|
| 774 |
-
|
| 775 |
-
|
| 776 |
-
|
| 777 |
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
|
| 784 |
-
|
| 785 |
-
|
| 786 |
-
|
| 787 |
-
|
| 788 |
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
|
| 794 |
-
|
| 795 |
-
|
| 796 |
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
|
| 803 |
|
| 804 |
-
|
| 805 |
-
|
| 806 |
-
|
| 807 |
|
| 808 |
|
| 809 |
-
if __name__ == "__main__":
|
| 810 |
-
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
|
| 6 |
+
# Set page config
|
| 7 |
+
st.set_page_config(page_title="BioDS - Space Biology Dashboard", layout="wide")
|
| 8 |
+
|
| 9 |
+
# Sidebar Navigation
|
| 10 |
+
menu = ["Home", "Research Data", "About"]
|
| 11 |
+
choice = st.sidebar.selectbox("Navigate", menu)
|
| 12 |
+
|
| 13 |
+
# Home Section
|
| 14 |
+
if choice == "Home":
|
| 15 |
+
st.title("🌌 BioDS: Space Biology Data Visualization Dashboard")
|
| 16 |
+
st.write("""
|
| 17 |
+
Welcome to **BioDS**, a data visualization and analytics dashboard designed
|
| 18 |
+
to explore the fascinating effects of **space environments on biological systems**.
|
| 19 |
+
Use the sidebar to explore different datasets and insights.
|
| 20 |
+
""")
|
| 21 |
+
|
| 22 |
+
# Example data summary
|
| 23 |
+
st.subheader("Quick Stats")
|
| 24 |
+
col1, col2, col3 = st.columns(3)
|
| 25 |
+
col1.metric("Active Experiments", "15")
|
| 26 |
+
col2.metric("Species Studied", "7")
|
| 27 |
+
col3.metric("Avg. Microgravity Hours", "2400+")
|
| 28 |
+
|
| 29 |
+
st.markdown("---")
|
| 30 |
+
st.subheader("Example Visualization")
|
| 31 |
+
x = np.linspace(0, 10, 100)
|
| 32 |
+
y = np.sin(x)
|
| 33 |
+
fig, ax = plt.subplots()
|
| 34 |
+
ax.plot(x, y, label='Biological Rhythm under Microgravity', color='purple')
|
| 35 |
+
ax.legend()
|
| 36 |
+
st.pyplot(fig)
|
| 37 |
+
|
| 38 |
+
# Research Data Section
|
| 39 |
+
elif choice == "Research Data":
|
| 40 |
+
st.title("🧬 Space Biology Experiment Data")
|
| 41 |
+
st.write("Explore sample data on biological changes during spaceflight.")
|
| 42 |
+
|
| 43 |
+
data = pd.DataFrame({
|
| 44 |
+
"Experiment": ["E1", "E2", "E3", "E4"],
|
| 45 |
+
"Organism": ["Yeast", "Mouse", "Human Cells", "Plant Roots"],
|
| 46 |
+
"Duration (Days)": [12, 45, 30, 25],
|
| 47 |
+
"Gravity Effect (%)": [5.2, 12.7, 8.4, 10.1],
|
| 48 |
+
})
|
| 49 |
+
|
| 50 |
+
st.dataframe(data, use_container_width=True)
|
| 51 |
+
|
| 52 |
+
st.bar_chart(data.set_index("Organism")["Gravity Effect (%)"])
|
| 53 |
+
|
| 54 |
+
# About Section
|
| 55 |
+
elif choice == "About":
|
| 56 |
+
st.title("ℹ️ About BioDS")
|
| 57 |
+
st.write("""
|
| 58 |
+
**BioDS (Biological Data System)** is a lightweight demo built with
|
| 59 |
+
**Streamlit** to visualize and analyze biological experiment data
|
| 60 |
+
from space missions.
|
| 61 |
+
|
| 62 |
+
**Developed by:** Aqsa Abbasi
|
| 63 |
+
**Tech Stack:** Python, Streamlit, Pandas, Matplotlib
|
| 64 |
+
""")
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
# import streamlit as st
|
| 89 |
+
# import json
|
| 90 |
+
# import os
|
| 91 |
+
# import hashlib
|
| 92 |
+
# import time
|
| 93 |
+
|
| 94 |
+
# # --- 1. DATA STRUCTURE FOR BioDS CONTENT (Massive Expansion) ---
|
| 95 |
+
# # Expanded to include more celestial bodies, stars, and black holes as requested.
|
| 96 |
+
# SPACE_DATA = {
|
| 97 |
+
# "MilkyWayGalaxy": {
|
| 98 |
+
# "title": "Milky Way Galaxy: Local Celestial Bodies & Stars",
|
| 99 |
+
# "items": [
|
| 100 |
+
# {"id": "MW_JUPITER", "name": "Jupiter Planet", "color": "0xDDAA00", "detail": "Giant gas planet. Key focus in astrobiology for its moon Europa. Its massive radiation belts make life challenging. Features complex atmospheric biology models.",
|
| 101 |
+
# "health_pct": 85, "moons": 95, "direction": "North-East Ecliptic", "surface": "Gaseous/Icy", "air_index": "N/A (Gas Giant)", "human_like": "None", "perplexity": 0.98},
|
| 102 |
+
# {"id": "MW_SATURN", "name": "Saturn Moon Titan", "color": "0xAAAAFF", "detail": "Titan has a dense atmosphere and stable liquid methane on its surface. Considered highly promising for exotic life forms, utilizing non-water solvents.",
|
| 103 |
+
# "health_pct": 92, "moons": 0, "direction": "South Celestial Pole", "surface": "Icy/Liquid Methane", "air_index": "High Methane/Nitrogen", "human_like": "Low Probability", "perplexity": 0.95},
|
| 104 |
+
# {"id": "MW_ORION", "name": "Orion Nebula (M42)", "color": "0xFF5555", "detail": "Massive star formation region, a cosmic lab for pre-biotic chemistry. Intense UV radiation shapes the biology of dust grains and molecular clouds.",
|
| 105 |
+
# "health_pct": 78, "moons": "N/A", "direction": "Galactic Center", "surface": "Gas/Dust Cloud", "air_index": "Molecular Hydrogen", "human_like": "Zero", "perplexity": 0.88},
|
| 106 |
+
# {"id": "MW_SUN", "name": "The Sun (G2V Star)", "color": "0xFFFF55", "detail": "Our star, the ultimate source of energy for terrestrial life. Its habitable zone is the core region for Earth-based biology. Future research focuses on solar flare resilience.",
|
| 107 |
+
# "health_pct": 99, "moons": "N/A", "direction": "Sol Centerpoint", "surface": "Plasma", "air_index": "Hydrogen/Helium", "human_like": "Zero", "perplexity": 0.99},
|
| 108 |
+
# {"id": "MW_EARTH", "name": "Earth's Biosphere", "color": "0x00FF00", "detail": "A control point for all space biology: the only known planet to harbor life. Its complex ecosystem is a benchmark for evaluating life signatures elsewhere.",
|
| 109 |
+
# "health_pct": 65, "moons": 1, "direction": "Local Arm Segment", "surface": "Solid/Liquid Water", "air_index": "Excellent (N2/O2)", "human_like": "Benchmark", "perplexity": 0.65},
|
| 110 |
+
# {"id": "MW_MARS", "name": "Mars Planet (Terraforming)", "color": "0xFF5500", "detail": "A prime target for terraforming and searching for past microbial life. Current biology focuses on permafrost extremophiles and atmospheric oxygenation projects.",
|
| 111 |
+
# "health_pct": 75, "moons": 2, "direction": "Inner Solar System", "surface": "Rocky (Iron Oxide)", "air_index": "High CO2", "human_like": "Low, potential for settlement", "perplexity": 0.70},
|
| 112 |
+
# {"id": "MW_VENUS", "name": "Venus Atmosphere", "color": "0xFF88CC", "detail": "A highly acidic and hot surface, but the upper atmosphere is temperate. Hypothesized cloud-based extremophile life forms utilizing sulfur compounds are a key research topic.",
|
| 113 |
+
# "health_pct": 55, "moons": 0, "direction": "Inner Solar System", "surface": "Molten/Volcanic", "air_index": "Sulfuric Acid/CO2", "human_like": "Zero", "perplexity": 0.85},
|
| 114 |
+
# {"id": "MW_URANUS", "name": "Uranus Ice Giant", "color": "0x00AAFF", "detail": "An ice giant with a complex, cold atmosphere. Its unique axial tilt presents challenges for modeling internal heat and potential deep-atmospheric biological zones.",
|
| 115 |
+
# "health_pct": 82, "moons": 27, "direction": "Outer Solar System", "surface": "Gas/Ice", "air_index": "Hydrogen/Helium/Methane", "human_like": "None", "perplexity": 0.90},
|
| 116 |
+
# {"id": "MW_NEPTUNE", "name": "Neptune Triton Moon", "color": "0x0055FF", "detail": "Neptune's largest moon, Triton, is geologically active with cryovolcanoes. Subsurface liquid nitrogen or water oceans make it a candidate for exotic subsurface life.",
|
| 117 |
+
# "health_pct": 88, "moons": 14, "direction": "Outer Solar System", "surface": "Nitrogen Ice", "air_index": "Trace Nitrogen/Methane", "human_like": "Extremophiles", "perplexity": 0.93},
|
| 118 |
+
# {"id": "MW_ALPHACEN", "name": "Alpha Centauri A", "color": "0xFFFF00", "detail": "The nearest star system. Centauri A is a G-type star, similar to the Sun, making its habitable zone a high-priority target for exoplanetary exploration.",
|
| 119 |
+
# "health_pct": 94, "moons": "Unknown", "direction": "Proxima Vicinity", "surface": "Plasma", "air_index": "Hydrogen/Helium", "human_like": "Medium Probability", "perplexity": 0.75},
|
| 120 |
+
# {"id": "MW_BETELG", "name": "Betelgeuse (Red Supergiant)", "color": "0xFF0000", "detail": "A massive, dying star. Its current instability and eventual supernova will sterilize a vast volume of space, but its outer regions currently host dense dust clouds for chemistry.",
|
| 121 |
+
# "health_pct": 20, "moons": "N/A", "direction": "Orion Constellation", "surface": "Supergiant Plasma", "air_index": "Heavy Elements", "human_like": "Zero", "perplexity": 0.99},
|
| 122 |
+
# {"id": "MW_TRAPPIST", "name": "TRAPPIST-1 System", "color": "0xAA00FF", "detail": "A system of seven Earth-sized planets orbiting an ultra-cool dwarf star. Multiple planets are within the theoretical habitable zone, making it a primary focus for atmospheric analysis.",
|
| 123 |
+
# "health_pct": 85, "moons": "Varies", "direction": "Aquarius Constellation", "surface": "Rocky/Water-World", "air_index": "Complex, analyzing", "human_like": "High Probability", "perplexity": 0.60},
|
| 124 |
+
# ]
|
| 125 |
+
# },
|
| 126 |
+
# "AndromedaGalaxy": {
|
| 127 |
+
# "title": "Andromeda Galaxy (M31): Neighboring Mysteries",
|
| 128 |
+
# "items": [
|
| 129 |
+
# {"id": "AND_CORE", "name": "Andromeda Core Region", "color": "0xFFFFFF", "detail": "A dense, high-metallicity environment with rapid star birth. High stellar density increases the chances of close-proximity gravitational events, impacting planetary stability.",
|
| 130 |
+
# "health_pct": 70, "moons": "Unknown", "direction": "Approaching MW", "surface": "Dense Stellar", "air_index": "Very Low", "human_like": "Very Low", "perplexity": 0.93},
|
| 131 |
+
# {"id": "AND_HALO", "name": "Dark Matter Halo Density", "color": "0x555555", "detail": "The invisible gravitational structure. Interaction between dark matter and regular matter is theorized to influence planetary thermal gradients and internal heat.",
|
| 132 |
+
# "health_pct": 50, "moons": "N/A", "direction": "Perpendicular Spin", "surface": "Non-Baryonic", "air_index": "Vacuum", "human_like": "Zero", "perplexity": 0.99},
|
| 133 |
+
# {"id": "AND_CANDIDATE_P", "name": "Candidate Exoplanet System", "color": "0xAAFFFF", "detail": "Hypothetical system in M31's spiral arms. Search for radio signals (SETI) from Andromeda is ongoing, providing key data points for non-local biology.",
|
| 134 |
+
# "health_pct": 88, "moons": 4, "direction": "M31 Outer Arm", "surface": "Rocky/Super-Earth", "air_index": "Argon/CO2", "human_like": "Possible", "perplexity": 0.77},
|
| 135 |
+
# ]
|
| 136 |
+
# },
|
| 137 |
+
# "Interstellar": {
|
| 138 |
+
# "title": "Interstellar Medium & Boundary Layers",
|
| 139 |
+
# "items": [
|
| 140 |
+
# {"id": "INT_OORT", "name": "Oort Cloud", "color": "0x00AAFF", "detail": "The most distant region of our Solar System, a reservoir of comets. Contains pristine biological precursors (ices, hydrocarbons) crucial for studying panspermia theories.",
|
| 141 |
+
# "health_pct": 80, "moons": "N/A", "direction": "Solar System Edge", "surface": "Water Ice/Rock", "air_index": "Vacuum", "human_like": "Zero", "perplexity": 0.96},
|
| 142 |
+
# {"id": "INT_KUIPER", "name": "Kuiper Belt Objects", "color": "0x55FFAA", "detail": "Region beyond Neptune, home to dwarf planets and small bodies. Its objects (like Pluto) show cryovolcanism, suggesting subsurface oceans—potential habitats for extremophiles.",
|
| 143 |
+
# "health_pct": 90, "moons": "Varies", "direction": "Ecliptic Plane", "surface": "Methane/Nitrogen Ice", "air_index": "Trace Methane", "human_like": "Extremophiles", "perplexity": 0.89},
|
| 144 |
+
# {"id": "INT_MEDIUM", "name": "Interstellar Medium (ISM)", "color": "0xAA55FF", "detail": "The gas and dust between star systems. Site of complex molecule synthesis, including amino acids, which are then delivered to protoplanetary disks.",
|
| 145 |
+
# "health_pct": 75, "moons": "N/A", "direction": "Between Stars", "surface": "Atomic Gas/Dust", "air_index": "Atomic/Molecular H", "human_like": "Zero", "perplexity": 0.92},
|
| 146 |
+
# {"id": "INT_HELIO", "name": "Heliopause Boundary", "color": "0xCCCCFF", "detail": "The magnetic boundary where the solar wind meets the interstellar medium. This shield protects the solar system's inner biology from the majority of galactic cosmic rays.",
|
| 147 |
+
# "health_pct": 98, "moons": "N/A", "direction": "Outbound Velocity Vector", "surface": "Plasma/Magnetic Field", "air_index": "Very Low Density", "human_like": "Indirect Shielding", "perplexity": 0.97},
|
| 148 |
+
# ]
|
| 149 |
+
# },
|
| 150 |
+
# "OtherGalaxies": {
|
| 151 |
+
# "title": "Other Galaxies: Diverse Cosmic Habitats",
|
| 152 |
+
# "items": [
|
| 153 |
+
# {"id": "OG_TRIANGULUM", "name": "Triangulum Galaxy (M33)", "color": "0xFF00AA", "detail": "The third largest galaxy in the Local Group. High rate of star formation, leading to a younger population of potentially habitable exoplanets.",
|
| 154 |
+
# "health_pct": 88, "moons": "Unknown", "direction": "Local Group Edge", "surface": "Spiral Arms", "air_index": "High Star Gas", "human_like": "Medium", "perplexity": 0.70},
|
| 155 |
+
# {"id": "OG_WHIRLPOOL", "name": "Whirlpool Galaxy (M51)", "color": "0xAAFF00", "detail": "A classic interacting spiral galaxy. Merging creates shockwaves and intense compression, triggering stellar explosions that sterilize local star systems.",
|
| 156 |
+
# "health_pct": 68, "moons": "Unknown", "direction": "Interacting", "surface": "Dense Dust", "air_index": "Low", "human_like": "Low", "perplexity": 0.95},
|
| 157 |
+
# {"id": "OG_CARTWHEEL", "name": "Cartwheel Galaxy", "color": "0x00FFAA", "detail": "A lenticular galaxy that was ringed by a high-speed collision. The expanding ring is a transient region of intense star birth and high-energy events.",
|
| 158 |
+
# "health_pct": 72, "moons": "Unknown", "direction": "Expanding Ring", "surface": "High Energy", "air_index": "Ionized Gas", "human_like": "Very Low", "perplexity": 0.90},
|
| 159 |
+
# ]
|
| 160 |
+
# },
|
| 161 |
+
# "BlackHoles": {
|
| 162 |
+
# "title": "Black Holes: Gravity's Biological Frontiers",
|
| 163 |
+
# "items": [
|
| 164 |
+
# {"id": "BH_SAG_A", "name": "Sagittarius A* (Supermassive)", "color": "0xFF8888", "detail": "The supermassive black hole at the center of our galaxy. Its radiation effects and gravitational influence shape the stellar orbits and dust cloud chemistry nearby.",
|
| 165 |
+
# "health_pct": 40, "moons": "N/A", "direction": "Galactic Center", "surface": "Singularity", "air_index": "Accretion Disk", "human_like": "Zero", "perplexity": 0.99},
|
| 166 |
+
# {"id": "BH_M87", "name": "M87's Black Hole (Supermassive)", "color": "0xAAAAAA", "detail": "The first black hole imaged. Its massive jets extend for thousands of light-years, impacting the entire M87 cluster's biology by stripping gas from forming galaxies.",
|
| 167 |
+
# "health_pct": 30, "moons": "N/A", "direction": "Active Jetting", "surface": "Event Horizon", "air_index": "Relativistic Plasma", "human_like": "Zero", "perplexity": 0.99},
|
| 168 |
+
# {"id": "BH_V404CYGNI", "name": "V404 Cygni (Stellar Mass)", "color": "0x00FFFF", "detail": "A highly active stellar-mass black hole in a binary system, known for frequent X-ray flares. The intense burst radiation is highly mutagenic to any biological neighbors.",
|
| 169 |
+
# "health_pct": 55, "moons": "N/A", "direction": "Local Source", "surface": "Binary System", "air_index": "High X-ray Flux", "human_like": "Zero", "perplexity": 0.97},
|
| 170 |
+
# {"id": "BH_GROJ1655", "name": "GRO J1655-40 (Stellar Mass)", "color": "0xCC00AA", "detail": "An exceptionally fast-spinning black hole. The frame-dragging effect (Lense-Thirring effect) around it creates unique environmental physics that could theoretically affect orbiting matter.",
|
| 171 |
+
# "health_pct": 45, "moons": "N/A", "direction": "Rapid Spin", "surface": "Accretion Disk", "air_index": "X-ray/Gamma", "human_like": "Zero", "perplexity": 0.98},
|
| 172 |
+
# {"id": "BH_PRIMORDIAL", "name": "Theoretic Primordial BH", "color": "0x333333", "detail": "Hypothesized to have formed in the early universe. Could potentially be a component of dark matter, and their minimal interaction makes them irrelevant to biological systems.",
|
| 173 |
+
# "health_pct": 5, "moons": "N/A", "direction": "Randomized", "surface": "Theoretic", "air_index": "Vacuum", "human_like": "Zero", "perplexity": 1.00},
|
| 174 |
+
# ]
|
| 175 |
+
# }
|
| 176 |
+
# }
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
# # --- 2. STREAMLIT PAGE CONFIGURATION (MUST BE FIRST) ---
|
| 180 |
+
# st.set_page_config(page_title="BioDS. - Authenticated", page_icon="🔭", layout="wide")
|
| 181 |
+
|
| 182 |
+
# # --- 3. FILE PATHS AND CONSTANTS ---
|
| 183 |
+
# # USER_DATA_FILE = "user_data.json"
|
| 184 |
+
# # PASSWORD_SALT = "random_salt_for_security" # In a real app, this should be unique and secret
|
| 185 |
+
|
| 186 |
+
# # --- 4. STREAMLIT SESSION STATE INITIALIZATION (MUST BE SECOND) ---
|
| 187 |
+
# if 'authenticated' not in st.session_state:
|
| 188 |
+
# st.session_state.authenticated = False
|
| 189 |
+
# if 'username' not in st.session_state:
|
| 190 |
+
# st.session_state.username = None
|
| 191 |
+
# if 'page' not in st.session_state:
|
| 192 |
+
# # Default page is 'auth' if not authenticated, otherwise 'app'
|
| 193 |
+
# st.session_state.page = "auth" if not st.session_state.authenticated else "app"
|
| 194 |
+
|
| 195 |
+
# # Initialize states specific to BioDS page if not already present
|
| 196 |
+
# if 'current_section' not in st.session_state:
|
| 197 |
+
# # SPACE_DATA is now defined,so this line will work
|
| 198 |
+
# st.session_state.current_section = list(SPACE_DATA.keys())[0] if SPACE_DATA else None
|
| 199 |
+
# if 'selected_item' not in st.session_state:
|
| 200 |
+
# st.session_state.selected_item = None
|
| 201 |
+
# # New state for Dashboard navigation
|
| 202 |
+
# if 'dashboard_section' not in st.session_state:
|
| 203 |
+
# st.session_state.dashboard_section = 'MilkyWayGalaxy'
|
| 204 |
+
|
| 205 |
+
# # --- 5. AUTHENTICATION HELPER FUNCTIONS (Simulated Database) ---
|
| 206 |
+
# def get_hashed_password(password):
|
| 207 |
+
# """Hash the password using SHA256 and a salt."""
|
| 208 |
+
# return hashlib.sha256((password + PASSWORD_SALT).encode('utf-8')).hexdigest()
|
| 209 |
+
|
| 210 |
+
# def load_users():
|
| 211 |
+
# """Load user data from the local JSON file."""
|
| 212 |
+
# if os.path.exists(USER_DATA_FILE):
|
| 213 |
+
# with open(USER_DATA_FILE, 'r') as f:
|
| 214 |
+
# return json.load(f)
|
| 215 |
+
# return {}
|
| 216 |
+
|
| 217 |
+
# def save_users(users):
|
| 218 |
+
# """Save user data to the local JSON file."""
|
| 219 |
+
# with open(USER_DATA_FILE, 'w') as f:
|
| 220 |
+
# json.dump(users, f, indent=4)
|
| 221 |
+
|
| 222 |
+
# def authenticate_user(username, password):
|
| 223 |
+
# """Check credentials against the stored user data."""
|
| 224 |
+
# users = load_users()
|
| 225 |
+
# hashed_password = get_hashed_password(password)
|
| 226 |
+
# if username in users and users[username]['password'] == hashed_password:
|
| 227 |
+
# return True
|
| 228 |
+
# return False
|
| 229 |
+
|
| 230 |
+
# def register_user(username, password, email):
|
| 231 |
+
# """Register a new user."""
|
| 232 |
+
# users = load_users()
|
| 233 |
+
# if username in users:
|
| 234 |
+
# return False, "Username already exists."
|
| 235 |
|
| 236 |
+
# users[username] = {
|
| 237 |
+
# 'password': get_hashed_password(password),
|
| 238 |
+
# 'email': email,
|
| 239 |
+
# 'created_at': str(time.strftime("%Y-%m-%d %H:%M:%S")),
|
| 240 |
+
# 'is_admin': False
|
| 241 |
+
# }
|
| 242 |
+
# save_users(users)
|
| 243 |
+
# return True, "Registration successful! You can now log in."
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
# # --- 6. PAGE LAYOUT FUNCTIONS ---
|
| 247 |
+
|
| 248 |
+
# def render_navbar():
|
| 249 |
+
# """Renders the fixed Navbar with a centered navigation block."""
|
| 250 |
+
# if st.session_state.authenticated:
|
| 251 |
+
# # Use two columns for Logo (Left) and Logout (Right)
|
| 252 |
+
# col_logo, col_logout = st.columns([8, 1])
|
| 253 |
+
|
| 254 |
+
# with col_logo:
|
| 255 |
+
# # Logo is positioned absolutely to the left
|
| 256 |
+
# st.markdown(f"""
|
| 257 |
+
# <div style="position: absolute; left: 0; padding-left: 2rem; display: flex; align-items: center; height: 50px;">
|
| 258 |
+
# <div style="font-family: 'Inter', sans-serif; font-size: 24px; font-weight: bold; color: #FFFFFF;">BioDS.</div>
|
| 259 |
+
# </div>
|
| 260 |
+
# """, unsafe_allow_html=True)
|
| 261 |
|
| 262 |
+
# with col_logout:
|
| 263 |
+
# # Logout button on the right
|
| 264 |
+
# if st.button("Logout", key="logout_btn_top", use_container_width=True):
|
| 265 |
+
# st.session_state.authenticated = False
|
| 266 |
+
# st.session_state.username = None
|
| 267 |
+
# st.session_state.page = "auth"
|
| 268 |
+
# st.toast("Logged out successfully!")
|
| 269 |
+
# st.rerun()
|
| 270 |
|
| 271 |
+
# # New Central Navigation Container using custom HTML and CSS
|
| 272 |
+
# # We must use Streamlit columns inside this container for the buttons to be functional
|
| 273 |
+
# st.markdown("""
|
| 274 |
+
# <div class="centered-navbar-container">
|
| 275 |
+
# <div class="centered-navbar-items">
|
| 276 |
+
# """, unsafe_allow_html=True)
|
| 277 |
|
| 278 |
+
# cols_nav = st.columns([1, 1]) # Two navigation items
|
| 279 |
|
| 280 |
+
# # Navigation buttons placed inside the centered block
|
| 281 |
+
# if cols_nav[0].button("🧬 App View", key="nav_app_view_center"):
|
| 282 |
+
# st.session_state.page = "app"
|
| 283 |
+
# st.rerun()
|
| 284 |
+
# if cols_nav[1].button("🔭 Dashboard", key="nav_dashboard_center"):
|
| 285 |
+
# st.session_state.page = "dashboard"
|
| 286 |
+
# st.rerun()
|
| 287 |
+
|
| 288 |
+
# st.markdown("""
|
| 289 |
+
# </div>
|
| 290 |
+
# </div>
|
| 291 |
+
# """, unsafe_allow_html=True)
|
| 292 |
|
| 293 |
+
# # Horizontal Divider
|
| 294 |
+
# st.markdown("<hr class='navbar-divider'>", unsafe_allow_html=True)
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
# def auth_page():
|
| 298 |
+
# """Renders the Sign In and Sign Up interface."""
|
| 299 |
+
# st.markdown('<div class="header-text-auth">BioDS<span style="color: #4b5563;">.</span> Authentication</div>', unsafe_allow_html=True)
|
| 300 |
+
# st.markdown("<h2 style='text-align: center; color: #ccc;'>Space Biology Data System</h2>", unsafe_allow_html=True)
|
| 301 |
+
|
| 302 |
+
# tab1, tab2 = st.tabs(["Sign In", "Sign Up"])
|
| 303 |
+
|
| 304 |
+
# with tab1:
|
| 305 |
+
# with st.form("signin_form"):
|
| 306 |
+
# st.subheader("Sign In")
|
| 307 |
+
# login_username = st.text_input("Username", key="login_username")
|
| 308 |
+
# login_password = st.text_input("Password", type="password", key="login_password")
|
| 309 |
+
# submitted = st.form_submit_button("Log In", use_container_width=True)
|
| 310 |
+
|
| 311 |
+
# if submitted:
|
| 312 |
+
# if authenticate_user(login_username, login_password):
|
| 313 |
+
# st.session_state.authenticated = True
|
| 314 |
+
# st.session_state.username = login_username
|
| 315 |
+
# st.session_state.page = "app"
|
| 316 |
+
# st.toast(f"Welcome back, {login_username}!")
|
| 317 |
+
# st.rerun()
|
| 318 |
+
# else:
|
| 319 |
+
# st.error("Invalid Username or Password.")
|
| 320 |
+
|
| 321 |
+
# with tab2:
|
| 322 |
+
# with st.form("signup_form"):
|
| 323 |
+
# st.subheader("Sign Up")
|
| 324 |
+
# reg_username = st.text_input("New Username", key="reg_username")
|
| 325 |
+
# reg_email = st.text_input("Email (Optional)", key="reg_email")
|
| 326 |
+
# reg_password = st.text_input("Password", type="password", key="reg_password")
|
| 327 |
+
# reg_password_confirm = st.text_input("Confirm Password", type="password", key="reg_password_confirm")
|
| 328 |
|
| 329 |
+
# signup_submitted = st.form_submit_button("Create Account", use_container_width=True)
|
| 330 |
+
|
| 331 |
+
# if signup_submitted:
|
| 332 |
+
# if not reg_username or not reg_password or not reg_password_confirm:
|
| 333 |
+
# st.error("Username and Password are required.")
|
| 334 |
+
# elif reg_password != reg_password_confirm:
|
| 335 |
+
# st.error("Passwords do not match.")
|
| 336 |
+
# else:
|
| 337 |
+
# success, message = register_user(reg_username, reg_password, reg_email)
|
| 338 |
+
# if success:
|
| 339 |
+
# st.success(message)
|
| 340 |
+
# # Optionally switch to login tab
|
| 341 |
+
# else:
|
| 342 |
+
# st.error(message)
|
| 343 |
+
|
| 344 |
+
# def render_dashboard_navigation():
|
| 345 |
+
# """Renders the animated navigation tabs for the dashboard."""
|
| 346 |
|
| 347 |
+
# NAV_KEYS = ['MilkyWayGalaxy', 'AndromedaGalaxy', 'Interstellar', 'OtherGalaxies', 'BlackHoles']
|
| 348 |
|
| 349 |
+
# st.markdown("<div class='dashboard-nav-container'>", unsafe_allow_html=True)
|
| 350 |
+
# cols = st.columns(len(NAV_KEYS))
|
| 351 |
|
| 352 |
+
# for i, key in enumerate(NAV_KEYS):
|
| 353 |
+
# # Use more descriptive but shorter title for the navbar tab
|
| 354 |
+
# title_map = {
|
| 355 |
+
# 'MilkyWayGalaxy': 'Milky Way',
|
| 356 |
+
# 'AndromedaGalaxy': 'Andromeda',
|
| 357 |
+
# 'Interstellar': 'Interstellar',
|
| 358 |
+
# 'OtherGalaxies': 'Galaxies',
|
| 359 |
+
# 'BlackHoles': 'Black Holes'
|
| 360 |
+
# }
|
| 361 |
+
# title = title_map.get(key, key)
|
| 362 |
+
# is_active = (key == st.session_state.dashboard_section)
|
| 363 |
|
| 364 |
+
# # Use custom HTML for animated button appearance
|
| 365 |
+
# # Note: We must wrap the title in a container to capture the click event over the entire area
|
| 366 |
+
# button_html = f"""
|
| 367 |
+
# <div class='dashboard-nav-item {"active" if is_active else ""}'
|
| 368 |
+
# data-key='{key}'>
|
| 369 |
+
# {title}
|
| 370 |
+
# </div>
|
| 371 |
+
# """
|
| 372 |
|
| 373 |
+
# # Place HTML in the column
|
| 374 |
+
# cols[i].markdown(button_html, unsafe_allow_html=True)
|
| 375 |
|
| 376 |
+
# # Capture click event using a hidden Streamlit button over the custom HTML
|
| 377 |
+
# if cols[i].button(title, key=f"dash_nav_{key}", use_container_width=True):
|
| 378 |
+
# st.session_state.dashboard_section = key
|
| 379 |
+
# st.rerun()
|
| 380 |
|
| 381 |
+
# st.markdown("</div>", unsafe_allow_html=True)
|
| 382 |
|
| 383 |
+
# def render_dashboard_content(section_key):
|
| 384 |
+
# """Renders dynamic content for the selected dashboard section with more detail."""
|
| 385 |
+
# data = SPACE_DATA[section_key]
|
| 386 |
+
# num_items = len(data['items'])
|
| 387 |
|
| 388 |
+
# st.markdown(f"<div class='dashboard-content-box'>", unsafe_allow_html=True)
|
| 389 |
|
| 390 |
+
# st.markdown(f"### {data['title']}")
|
| 391 |
+
# st.markdown("---")
|
| 392 |
|
| 393 |
+
# # 1. Key Metrics (Dynamically generated stats)
|
| 394 |
+
# col1, col2, col3 = st.columns(3)
|
| 395 |
|
| 396 |
+
# col1.metric("Total Bodies Tracked", str(num_items), delta=f"+{num_items*3}% Potential Habitability")
|
| 397 |
+
# col2.metric("Dominant Element", "Carbon", "98% Confidence")
|
| 398 |
+
# col3.metric("Latest Entry", data['items'][0]['name'], "Updated 2h ago")
|
| 399 |
|
| 400 |
+
# st.markdown("---")
|
| 401 |
|
| 402 |
+
# # 2. Summary Analysis based on the section
|
| 403 |
+
# summary_analysis = {
|
| 404 |
+
# 'MilkyWayGalaxy': "Local systems show high concentration of water-based life candidates, especially around icy moons and newly discovered exoplanet systems (like TRAPPIST-1). Radiation levels from active stars are the primary biological stressor. Stellar-mass bodies (Sun, Betelgeuse) dictate regional life viability.",
|
| 405 |
+
# 'AndromedaGalaxy': "Intergalactic analysis points to high gravitational perturbations, suggesting life would need to be resilient to frequent, high-energy events. Low-mass, cool stars dominate bio-candidates. Ongoing SETI efforts target Candidate Exoplanet System for radio signatures.",
|
| 406 |
+
# 'Interstellar': "The interstellar medium is a reservoir of complex organic molecules (e.g., Glycine precursors). Research focuses on cryo-protection for panspermia viability and radiation shielding effectiveness, especially near the Heliopause Boundary.",
|
| 407 |
+
# 'OtherGalaxies': "Highly diverse ecosystems. Interacting galaxies (like Whirlpool) indicate transient periods of sterilization followed by rapid chemical rejuvenation. Triangulum Galaxy (M33) is a key region for studying younger, dynamic biospheres.",
|
| 408 |
+
# 'BlackHoles': "These regions are primarily studied for their energy output's impact on distant habitable zones. Direct life near the event horizon is theoretically impossible due to tidal forces and high-energy radiation jets, like those from M87's Black Hole. Stellar-mass black holes (V404 Cygni) pose localized threats.",
|
| 409 |
+
# }
|
| 410 |
|
| 411 |
+
# st.markdown(f"""
|
| 412 |
+
# <div class='animated-text'>
|
| 413 |
+
# <p style='font-size: 1.1rem; font-style: italic; color: #9B9B9B;'>
|
| 414 |
+
# **Section Analysis:** {summary_analysis.get(section_key, "No analysis available.")}
|
| 415 |
+
# </p>
|
| 416 |
+
# </div>
|
| 417 |
+
# """, unsafe_allow_html=True)
|
| 418 |
+
|
| 419 |
+
# st.markdown("---")
|
| 420 |
|
| 421 |
+
# # 3. Item List with simulated data
|
| 422 |
+
# st.subheader("Biological Profile Overview")
|
| 423 |
|
| 424 |
+
# item_names = [item['name'] for item in data['items']]
|
| 425 |
+
# item_details = [item['detail'] for item in data['items']]
|
| 426 |
|
| 427 |
+
# for name, detail in zip(item_names, item_details):
|
| 428 |
+
# st.markdown(f"""
|
| 429 |
+
# <div class='item-summary-card'>
|
| 430 |
+
# <span style='color: #4CAF50; font-weight: bold;'>{name}</span>
|
| 431 |
+
# <p style='font-size: 0.85rem; color: #ccc; margin-top: 5px;'>{detail[:80]}...</p>
|
| 432 |
+
# </div>
|
| 433 |
+
# """, unsafe_allow_html=True)
|
| 434 |
+
|
| 435 |
+
# st.markdown("</div>", unsafe_allow_html=True)
|
| 436 |
+
|
| 437 |
+
|
| 438 |
+
# def dashboard_page():
|
| 439 |
+
# """Renders the user's main application Dashboard with new navigation."""
|
| 440 |
+
# st.markdown(f'<div class="header-text">BioDS<span style="color: #4b5563;">.</span></div>', unsafe_allow_html=True)
|
| 441 |
+
# st.subheader(f"Welcome to the BioDS Dashboard, {st.session_state.username}!")
|
| 442 |
+
# st.markdown("---")
|
| 443 |
|
| 444 |
+
# # RENDER NEW ANIMATED NAVBAR
|
| 445 |
+
# render_dashboard_navigation()
|
| 446 |
|
| 447 |
+
# # RENDER DYNAMIC CONTENT
|
| 448 |
+
# render_dashboard_content(st.session_state.dashboard_section)
|
| 449 |
|
| 450 |
|
| 451 |
+
# def render_item_details(item):
|
| 452 |
+
# """Renders the new, detailed metrics for the selected item."""
|
| 453 |
|
| 454 |
+
# st.markdown(f"<h2 style='color:#{item['color'].replace('0x', '')}; font-weight: 700; border-bottom: 2px solid #333; padding-bottom: 0.5rem;'>{item['name']}</h2>", unsafe_allow_html=True)
|
| 455 |
+
# st.markdown(f"<p style='font-size: 0.9rem; color: #ccc;'>**Context:** {st.session_state.current_section}</p>", unsafe_allow_html=True)
|
| 456 |
+
# st.markdown(f"<p style='margin-top: 1rem; line-height: 1.6;'>{item['detail']}</p>", unsafe_allow_html=True)
|
| 457 |
|
| 458 |
+
# st.markdown("---")
|
| 459 |
|
| 460 |
+
# st.subheader("Biological & Celestial Metrics")
|
| 461 |
|
| 462 |
+
# # 1. Detailed Health & Perplexity
|
| 463 |
+
# st.markdown("**1. Health and System Integrity**")
|
| 464 |
|
| 465 |
+
# # Use st.progress for a visual graph representation of health
|
| 466 |
+
# health_progress = item['health_pct'] / 100.0
|
| 467 |
+
# st.progress(health_progress, text=f"System Health: **{item['health_pct']}%**")
|
| 468 |
|
| 469 |
+
# st.markdown(f"""
|
| 470 |
+
# <div style="display: flex; justify-content: space-between; font-size: 0.9rem; color: #ccc; margin-top: -10px;">
|
| 471 |
+
# <span>Standard Compliance: 99.5%</span>
|
| 472 |
+
# <span>Perplexity Index: **{item['perplexity']}**</span>
|
| 473 |
+
# </div>
|
| 474 |
+
# """, unsafe_allow_html=True)
|
| 475 |
|
| 476 |
+
# st.markdown("<br>", unsafe_allow_html=True)
|
| 477 |
|
| 478 |
+
# # 2. Celestial Data & Condition
|
| 479 |
+
# col_l, col_r = st.columns(2)
|
| 480 |
|
| 481 |
+
# with col_l:
|
| 482 |
+
# st.markdown(f"<p style='font-weight: bold; color: #00AAFF;'>Moons/Satellites:</p> <p style='margin-left: 10px;'>{item['moons']}</p>", unsafe_allow_html=True)
|
| 483 |
+
# st.markdown(f"<p style='font-weight: bold; color: #00AAFF;'>Current Direction:</p> <p style='margin-left: 10px;'>{item['direction']}</p>", unsafe_allow_html=True)
|
| 484 |
|
| 485 |
+
# with col_r:
|
| 486 |
+
# st.markdown(f"<p style='font-weight: bold; color: #00AAFF;'>Surface Condition:</p> <p style='margin-left: 10px;'>{item['surface']}</p>", unsafe_allow_html=True)
|
| 487 |
+
# st.markdown(f"<p style='font-weight: bold; color: #00AAFF;'>Air Index/Atmosphere:</p> <p style='margin-left: 10px;'>{item['air_index']}</p>", unsafe_allow_html=True)
|
| 488 |
|
| 489 |
+
# st.markdown("---")
|
| 490 |
|
| 491 |
+
# # 3. Simulated Directory Usage / Simple Graph Visualization
|
| 492 |
+
# st.markdown("""
|
| 493 |
+
# **3. Current Directory / Resource Usage** <div style="font-size: 0.9rem; color: #aaa; margin-bottom: 10px;">(Simulated System Load Graph)</div>
|
| 494 |
+
# """, unsafe_allow_html=True)
|
| 495 |
|
| 496 |
+
# # Simulated Load Data
|
| 497 |
+
# simulated_load = {
|
| 498 |
+
# "Bio-Scans (35%)": "#00FF00",
|
| 499 |
+
# "Gravimetric Data (45%)": "#FF5555",
|
| 500 |
+
# "Unallocated (20%)": "#444444"
|
| 501 |
+
# }
|
| 502 |
+
|
| 503 |
+
# st.markdown(f"""
|
| 504 |
+
# <div style='display: flex; width: 100%; height: 20px; border-radius: 5px; overflow: hidden; margin-top: 5px;'>
|
| 505 |
+
# <div style='width: 35%; background-color: {simulated_load['Bio-Scans (35%)']};' title='Bio-Scans (35%)'></div>
|
| 506 |
+
# <div style='width: 45%; background-color: {simulated_load['Gravimetric Data (45%)']};' title='Gravimetric Data (45%)'></div>
|
| 507 |
+
# <div style='width: 20%; background-color: {simulated_load['Unallocated (20%)']};' title='Unallocated (20%)'></div>
|
| 508 |
+
# </div>
|
| 509 |
+
# <div style='margin-top: 10px; font-size: 0.8rem; display: flex; flex-wrap: wrap; gap: 10px;'>
|
| 510 |
+
# <span style='color: #00FF00;'>● Bio-Scans (35%)</span>
|
| 511 |
+
# <span style='color: #FF5555;'>● Gravimetric (45%)</span>
|
| 512 |
+
# <span style='color: #444444;'>● Unallocated (20%)</span>
|
| 513 |
+
# </div>
|
| 514 |
+
# """, unsafe_allow_html=True)
|
| 515 |
|
| 516 |
+
# st.markdown("---")
|
| 517 |
|
| 518 |
+
# # 4. Human-like Probability
|
| 519 |
+
# human_like_color = "#00FF00" if item['human_like'] == "Possible" or item['human_like'] == "Benchmark" or item['human_like'] == "High Probability" else ("#FFAA00" if item['human_like'] == "Low Probability" or item['human_like'] == "Medium Probability" else "#FF5555")
|
| 520 |
+
# st.markdown(f"""
|
| 521 |
+
# **4. Human-Like Viability**
|
| 522 |
+
# <h3 style='color: {human_like_color}; font-size: 1.5rem; margin-top: 5px;'>
|
| 523 |
+
# {item['human_like']}
|
| 524 |
+
# </h3>
|
| 525 |
+
# <p style='font-size: 0.8rem; color: #aaa;'>
|
| 526 |
+
# The probability of carbon-based, water-dependent life forms surviving/thriving here.
|
| 527 |
+
# </p>
|
| 528 |
+
# """, unsafe_allow_html=True)
|
| 529 |
|
| 530 |
|
| 531 |
+
# def bio_ds_page():
|
| 532 |
+
# """Renders the core BioDS content (from previous versions)."""
|
| 533 |
|
| 534 |
+
# # --- CONTENT RENDERER FUNCTIONS ---
|
| 535 |
|
| 536 |
+
# def render_navigation_content():
|
| 537 |
+
# """Renders the liquid glass style navigation bar for content sections."""
|
| 538 |
|
| 539 |
+
# # Custom CSS to contain the buttons within the column
|
| 540 |
+
# st.markdown("""
|
| 541 |
+
# <style>
|
| 542 |
+
# .nav-button-container {
|
| 543 |
+
# display: flex;
|
| 544 |
+
# flex-wrap: wrap; /* Allows wrapping on smaller screens */
|
| 545 |
+
# gap: 10px;
|
| 546 |
+
# margin-bottom: 2rem;
|
| 547 |
+
# }
|
| 548 |
+
# </style>
|
| 549 |
+
# """, unsafe_allow_html=True)
|
| 550 |
+
|
| 551 |
+
# st.markdown("<div class='nav-button-container'>", unsafe_allow_html=True)
|
| 552 |
|
| 553 |
+
# for key, data in SPACE_DATA.items():
|
| 554 |
+
# css_class = 'content-nav-item active' if key == st.session_state.current_section else 'content-nav-item'
|
| 555 |
|
| 556 |
+
# # Use Streamlit's native button wrapped in custom styling
|
| 557 |
+
# if st.button(data['title'].split(':')[0], key=f"content_nav_{key}"):
|
| 558 |
+
# st.session_state.current_section = key
|
| 559 |
+
# st.session_state.selected_item = None
|
| 560 |
+
# st.rerun()
|
| 561 |
|
| 562 |
+
# st.markdown("</div>", unsafe_allow_html=True)
|
| 563 |
|
| 564 |
+
# # Ensure current_section is initialized when navigating back to this page
|
| 565 |
+
# if st.session_state.current_section is None and SPACE_DATA:
|
| 566 |
+
# st.session_state.current_section = list(SPACE_DATA.keys())[0]
|
| 567 |
|
| 568 |
+
# st.markdown('<div class="header-text">BioDS<span style="color: #4b5563;">.</span></div>', unsafe_allow_html=True)
|
| 569 |
|
| 570 |
+
# # RENDER CONTENT NAVIGATION
|
| 571 |
+
# render_navigation_content()
|
| 572 |
|
| 573 |
+
# # MAIN CONTENT AREA (Grid of Crystals + Info Panel)
|
| 574 |
+
# col_content, col_panel = st.columns([2, 1])
|
| 575 |
+
|
| 576 |
+
# # --- Content Area (Simulated 3D Crystals) ---
|
| 577 |
+
# with col_content:
|
| 578 |
+
# current_data = SPACE_DATA[st.session_state.current_section]
|
| 579 |
+
# st.subheader(current_data['title'])
|
| 580 |
+
# st.markdown("---")
|
| 581 |
|
| 582 |
+
# items_per_row = 3
|
| 583 |
+
# num_items = len(current_data['items'])
|
| 584 |
+
# num_rows = (num_items + items_per_row - 1) // items_per_row
|
| 585 |
|
| 586 |
+
# for row in range(num_rows):
|
| 587 |
+
# row_cols = st.columns(items_per_row)
|
| 588 |
+
# for i in range(items_per_row):
|
| 589 |
+
# item_index = row * items_per_row + i
|
| 590 |
+
# if item_index < num_items:
|
| 591 |
+
# item = current_data['items'][item_index]
|
| 592 |
|
| 593 |
+
# # Highlight selected item
|
| 594 |
+
# border_style = "border: 2px solid #00FF00;" if st.session_state.selected_item and st.session_state.selected_item['id'] == item['id'] else ""
|
| 595 |
|
| 596 |
+
# # Create a unique key for the click event
|
| 597 |
+
# click_key = f"crystal_click_{item['id']}"
|
| 598 |
|
| 599 |
+
# # Use a custom container for card styling and click handling
|
| 600 |
+
# container = row_cols[i].container(border=False)
|
| 601 |
+
# with container:
|
| 602 |
|
| 603 |
+
# # Custom HTML for the card appearance
|
| 604 |
+
# card_html = f"""
|
| 605 |
+
# <div class='crystal-card' style='{border_style}'>
|
| 606 |
+
# <p style='color:#{item['color'].replace('0x', '')}; font-size: 2rem; text-align: center; margin-bottom: 0.5rem;'>
|
| 607 |
+
# ✶
|
| 608 |
+
# </p>
|
| 609 |
+
# <p style='font-weight: 600; text-align: center;'>{item['name']}</p>
|
| 610 |
+
# <p style='font-size: 0.75rem; color: #aaa; text-align: center;'>Click for Bio Profile</p>
|
| 611 |
+
# </div>
|
| 612 |
+
# """
|
| 613 |
+
# # Display the HTML card. We use a hidden Streamlit button for the click event.
|
| 614 |
+
# st.markdown(card_html, unsafe_allow_html=True)
|
| 615 |
|
| 616 |
+
# # Hidden button to capture the click event
|
| 617 |
+
# if st.button(item['name'], key=click_key, help=item['name']):
|
| 618 |
+
# st.session_state.selected_item = item
|
| 619 |
+
# st.rerun()
|
| 620 |
|
| 621 |
|
| 622 |
+
# # --- Information Panel ---
|
| 623 |
+
# with col_panel:
|
| 624 |
+
# # Use the custom CSS class for the panel
|
| 625 |
+
# st.markdown('<div class="info-panel">', unsafe_allow_html=True)
|
| 626 |
|
| 627 |
+
# if st.session_state.selected_item:
|
| 628 |
+
# # Display NEW detailed metrics
|
| 629 |
+
# render_item_details(st.session_state.selected_item)
|
| 630 |
|
| 631 |
+
# else:
|
| 632 |
+
# # Display initial welcome message
|
| 633 |
+
# st.markdown(f"<h2 style='font-weight: 700; border-bottom: 2px solid #333; padding-bottom: 0.5rem;'>Select a Celestial Body</h2>", unsafe_allow_html=True)
|
| 634 |
+
# st.markdown(f"""
|
| 635 |
+
# <p style='margin-top: 1rem; color: #aaa;'>
|
| 636 |
+
# Click on any of the **star-shaped crystals** (the cards on the left)
|
| 637 |
+
# to view its complete Space Biology profile and detailed metrics.
|
| 638 |
+
# </p>
|
| 639 |
+
# """, unsafe_allow_html=True)
|
| 640 |
|
| 641 |
+
# st.markdown('</div>', unsafe_allow_html=True)
|
| 642 |
+
|
| 643 |
+
|
| 644 |
+
# # --- 7. MAIN APPLICATION ROUTER ---
|
| 645 |
+
|
| 646 |
+
# def main_app():
|
| 647 |
+
|
| 648 |
+
# # Custom CSS for the entire app layout and styling
|
| 649 |
+
# st.markdown("""
|
| 650 |
+
# <style>
|
| 651 |
+
# /* Global Streamlit Overrides */
|
| 652 |
+
# .stApp {
|
| 653 |
+
# background-color: #0d0d0d; /* Deep Dark Background */
|
| 654 |
+
# color: #ffffff;
|
| 655 |
+
# font-family: 'Inter', sans-serif;
|
| 656 |
+
# /* Adjust padding to handle absolute/fixed elements */
|
| 657 |
+
# padding-top: 0 !important;
|
| 658 |
+
# padding-bottom: 2rem;
|
| 659 |
+
# padding-left: 0 !important;
|
| 660 |
+
# padding-right: 0 !important;
|
| 661 |
+
# }
|
| 662 |
|
| 663 |
+
# .stApp > header {
|
| 664 |
+
# /* Hide default Streamlit header bar */
|
| 665 |
+
# display: none;
|
| 666 |
+
# }
|
| 667 |
+
|
| 668 |
+
# /* Adjust Streamlit main content block for full width and padding */
|
| 669 |
+
# .main {
|
| 670 |
+
# padding: 2rem 2rem 0 2rem;
|
| 671 |
+
# }
|
| 672 |
+
|
| 673 |
+
# /* Auth Page specific styling */
|
| 674 |
+
# .header-text-auth {
|
| 675 |
+
# font-size: 3rem;
|
| 676 |
+
# font-weight: 800;
|
| 677 |
+
# letter-spacing: 0.1em;
|
| 678 |
+
# color: #ffffff;
|
| 679 |
+
# text-align: center;
|
| 680 |
+
# margin-top: 50px;
|
| 681 |
+
# margin-bottom: 10px;
|
| 682 |
+
# }
|
| 683 |
+
|
| 684 |
+
# /* App Page specific styling */
|
| 685 |
+
# .header-text {
|
| 686 |
+
# font-size: 3rem;
|
| 687 |
+
# font-weight: 800;
|
| 688 |
+
# letter-spacing: 0.1em;
|
| 689 |
+
# color: #ffffff;
|
| 690 |
+
# margin-bottom: 0.5rem;
|
| 691 |
+
# }
|
| 692 |
|
| 693 |
+
# /* === NEW CENTERING CSS FOR NAVBAR === */
|
| 694 |
+
# /* Logo is handled with absolute position in render_navbar function */
|
| 695 |
+
# .centered-navbar-container {
|
| 696 |
+
# /* This div contains the centered items and spans the width */
|
| 697 |
+
# display: flex;
|
| 698 |
+
# justify-content: center;
|
| 699 |
+
# width: 100%;
|
| 700 |
+
# margin-top: -30px; /* Adjust vertical position to overlay/align */
|
| 701 |
+
# position: relative;
|
| 702 |
+
# z-index: 100;
|
| 703 |
+
# }
|
| 704 |
+
|
| 705 |
+
# .centered-navbar-items {
|
| 706 |
+
# display: flex;
|
| 707 |
+
# gap: 20px;
|
| 708 |
+
# padding: 10px 20px;
|
| 709 |
+
# background-color: rgba(255, 255, 255, 0.05); /* Background for the center block */
|
| 710 |
+
# border-radius: 10px;
|
| 711 |
+
# border: 1px solid rgba(255, 255, 255, 0.1);
|
| 712 |
+
# box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
| 713 |
+
# width: fit-content;
|
| 714 |
+
# }
|
| 715 |
+
|
| 716 |
+
# /* Style the buttons inside the centered navigation specifically */
|
| 717 |
+
# .centered-navbar-items .stButton > button {
|
| 718 |
+
# background-color: transparent !important;
|
| 719 |
+
# color: #fff !important;
|
| 720 |
+
# border: none !important;
|
| 721 |
+
# padding: 8px 15px !important;
|
| 722 |
+
# font-weight: 600 !important;
|
| 723 |
+
# transition: all 0.3s;
|
| 724 |
+
# line-height: 1; /* Ensure text is vertically centered */
|
| 725 |
+
# }
|
| 726 |
+
|
| 727 |
+
# .centered-navbar-items .stButton > button:hover {
|
| 728 |
+
# background-color: rgba(0, 255, 0, 0.1) !important;
|
| 729 |
+
# color: #00FF00 !important;
|
| 730 |
+
# box-shadow: none !important;
|
| 731 |
+
# transform: translateY(-2px);
|
| 732 |
+
# }
|
| 733 |
|
| 734 |
+
# .navbar-divider {
|
| 735 |
+
# border: 1px solid rgba(255, 255, 255, 0.1);
|
| 736 |
+
# margin-top: 20px;
|
| 737 |
+
# margin-bottom: 20px;
|
| 738 |
+
# }
|
| 739 |
+
# /* END NEW CENTERING CSS */
|
| 740 |
+
|
| 741 |
+
|
| 742 |
+
# /* Crystal Card (Simulated 3D item) */
|
| 743 |
+
# .crystal-card {
|
| 744 |
+
# background-color: rgba(255, 255, 255, 0.05);
|
| 745 |
+
# border: 1px solid rgba(255, 255, 255, 0.1);
|
| 746 |
+
# border-radius: 1rem;
|
| 747 |
+
# padding: 1.5rem;
|
| 748 |
+
# cursor: pointer;
|
| 749 |
+
# transition: all 0.3s;
|
| 750 |
+
# height: 100%;
|
| 751 |
+
# animation: fadeIn 0.8s ease-out;
|
| 752 |
+
# }
|
| 753 |
+
# .crystal-card:hover {
|
| 754 |
+
# background-color: rgba(255, 255, 255, 0.1);
|
| 755 |
+
# transform: translateY(-5px);
|
| 756 |
+
# box-shadow: 0 5px 20px rgba(0, 255, 0, 0.2);
|
| 757 |
+
# }
|
| 758 |
|
| 759 |
+
# /* Info Panel Style */
|
| 760 |
+
# .info-panel {
|
| 761 |
+
# background-color: rgba(255, 255, 255, 0.05);
|
| 762 |
+
# backdrop-filter: blur(8px);
|
| 763 |
+
# border: 1px solid rgba(255, 255, 255, 0.1);
|
| 764 |
+
# border-radius: 1rem;
|
| 765 |
+
# padding: 1.5rem;
|
| 766 |
+
# height: 100%;
|
| 767 |
+
# overflow-y: auto;
|
| 768 |
+
# animation: fadeIn 0.5s ease-out;
|
| 769 |
+
# }
|
| 770 |
+
|
| 771 |
+
# /* Dashboard Navigation Styling */
|
| 772 |
+
# .dashboard-nav-container {
|
| 773 |
+
# display: flex;
|
| 774 |
+
# justify-content: space-between;
|
| 775 |
+
# margin-bottom: 2rem;
|
| 776 |
+
# padding: 0 1rem;
|
| 777 |
+
# border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
| 778 |
+
# margin-top: 1rem;
|
| 779 |
+
# }
|
| 780 |
|
| 781 |
+
# .dashboard-nav-item {
|
| 782 |
+
# cursor: pointer;
|
| 783 |
+
# padding: 10px 15px;
|
| 784 |
+
# font-weight: 600;
|
| 785 |
+
# color: #AAAAAA;
|
| 786 |
+
# border-bottom: 3px solid transparent;
|
| 787 |
+
# transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
|
| 788 |
+
# text-align: center;
|
| 789 |
+
# width: 100%;
|
| 790 |
+
# }
|
| 791 |
|
| 792 |
+
# .dashboard-nav-item:hover {
|
| 793 |
+
# color: #FFFFFF;
|
| 794 |
+
# border-bottom: 3px solid #00AAFF;
|
| 795 |
+
# transform: translateY(-2px);
|
| 796 |
+
# text-shadow: 0 0 5px rgba(0, 170, 255, 0.5);
|
| 797 |
+
# }
|
| 798 |
|
| 799 |
+
# .dashboard-nav-item.active {
|
| 800 |
+
# color: #00FF00;
|
| 801 |
+
# border-bottom: 3px solid #00FF00;
|
| 802 |
+
# font-weight: 700;
|
| 803 |
+
# }
|
| 804 |
|
| 805 |
+
# /* Dashboard Content Animation */
|
| 806 |
+
# .dashboard-content-box {
|
| 807 |
+
# background-color: rgba(255, 255, 255, 0.03);
|
| 808 |
+
# border-radius: 1rem;
|
| 809 |
+
# padding: 2rem;
|
| 810 |
+
# animation: fadeIn 0.8s ease-out;
|
| 811 |
+
# }
|
| 812 |
+
|
| 813 |
+
# @keyframes fadeIn {
|
| 814 |
+
# from { opacity: 0; transform: translateY(20px); }
|
| 815 |
+
# to { opacity: 1; transform: translateY(0); }
|
| 816 |
+
# }
|
| 817 |
|
| 818 |
+
# /* Item Summary Card for Dashboard content */
|
| 819 |
+
# .item-summary-card {
|
| 820 |
+
# background-color: rgba(255, 255, 255, 0.05);
|
| 821 |
+
# padding: 10px;
|
| 822 |
+
# margin-bottom: 8px;
|
| 823 |
+
# border-left: 4px solid #00FF00;
|
| 824 |
+
# border-radius: 4px;
|
| 825 |
+
# transition: background-color 0.2s;
|
| 826 |
+
# }
|
| 827 |
+
# .item-summary-card:hover {
|
| 828 |
+
# background-color: rgba(255, 255, 255, 0.1);
|
| 829 |
+
# }
|
| 830 |
+
|
| 831 |
+
|
| 832 |
+
# /* Hide the Streamlit button visual for the custom HTML cards and Dashboard nav */
|
| 833 |
+
# div[data-testid="stVerticalBlock"] > div > div > button {
|
| 834 |
+
# opacity: 0;
|
| 835 |
+
# position: absolute;
|
| 836 |
+
# top: 0;
|
| 837 |
+
# left: 0;
|
| 838 |
+
# width: 100%;
|
| 839 |
+
# height: 100%;
|
| 840 |
+
# cursor: pointer;
|
| 841 |
+
# z-index: 10;
|
| 842 |
+
# }
|
| 843 |
+
|
| 844 |
+
# /* Ensure Streamlit columns for dashboard nav contain buttons properly */
|
| 845 |
+
# div[data-testid^="stColumn"] {
|
| 846 |
+
# padding: 0;
|
| 847 |
+
# display: flex;
|
| 848 |
+
# align-items: stretch;
|
| 849 |
+
# position: relative;
|
| 850 |
+
# }
|
| 851 |
+
# .stButton {
|
| 852 |
+
# height: 100%;
|
| 853 |
+
# padding: 0;
|
| 854 |
+
# margin: 0;
|
| 855 |
+
# }
|
| 856 |
|
| 857 |
+
# /* Reset for the inner block containing the custom HTML to ensure alignment */
|
| 858 |
+
# div[data-testid="stVerticalBlock"] > div > div > div:first-child > div:first-child {
|
| 859 |
+
# display: flex;
|
| 860 |
+
# align-items: center;
|
| 861 |
+
# justify-content: center;
|
| 862 |
+
# height: 100%;
|
| 863 |
+
# }
|
| 864 |
|
| 865 |
+
# /* Style for st.progress bar */
|
| 866 |
+
# .stProgress > div > div > div > div {
|
| 867 |
+
# background-color: #00FF00;
|
| 868 |
+
# }
|
| 869 |
+
# .stProgress > div > div > div {
|
| 870 |
+
# background-color: #333333;
|
| 871 |
+
# }
|
| 872 |
+
|
| 873 |
+
# </style>
|
| 874 |
+
# """, unsafe_allow_html=True)
|
| 875 |
|
| 876 |
+
# # ROUTING LOGIC
|
| 877 |
+
# if st.session_state.authenticated:
|
| 878 |
+
# # Render the custom navigation layout
|
| 879 |
+
# render_navbar()
|
| 880 |
|
| 881 |
+
# # All main content now needs padding since the navbar is fixed/absolute at the top
|
| 882 |
+
# st.markdown("<div class='main'>", unsafe_allow_html=True)
|
| 883 |
|
| 884 |
+
# if st.session_state.page == "app":
|
| 885 |
+
# bio_ds_page()
|
| 886 |
+
# elif st.session_state.page == "dashboard":
|
| 887 |
+
# dashboard_page()
|
| 888 |
+
# else:
|
| 889 |
+
# bio_ds_page()
|
| 890 |
|
| 891 |
+
# st.markdown("</div>", unsafe_allow_html=True) # Close the main content wrapper
|
| 892 |
+
# else:
|
| 893 |
+
# auth_page()
|
| 894 |
|
| 895 |
|
| 896 |
+
# if __name__ == "__main__":
|
| 897 |
+
# main_app()
|