Update app.py
Browse files
app.py
CHANGED
|
@@ -156,7 +156,13 @@ def safe_get(row, key, default="N/A"):
|
|
| 156 |
'Countries': ['Country', 'Location'],
|
| 157 |
'Companies': ['Company', 'Business'],
|
| 158 |
'Phone#': ['Phone', 'Telephone', 'Contact_Phone'],
|
| 159 |
-
'Linked To': ['Organization', 'Terror_Organization', 'Group']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
}
|
| 161 |
|
| 162 |
val = None
|
|
@@ -529,14 +535,46 @@ with tab3:
|
|
| 529 |
mime="text/csv"
|
| 530 |
)
|
| 531 |
|
| 532 |
-
#
|
| 533 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 534 |
|
| 535 |
# Apply filters
|
| 536 |
filtered_vessels = data['vessels'].copy()
|
|
|
|
| 537 |
if name_filter:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 538 |
filtered_vessels = filtered_vessels[
|
| 539 |
-
filtered_vessels['
|
| 540 |
]
|
| 541 |
|
| 542 |
# Display vessels
|
|
@@ -544,15 +582,28 @@ with tab3:
|
|
| 544 |
status_value = safe_get(vessel, 'Status')
|
| 545 |
status_class = "status-inactive" if status_value == 'AIS Off' else "status-active"
|
| 546 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 547 |
st.markdown(f"""
|
| 548 |
<div class="entity-card">
|
| 549 |
<h3>{safe_get(vessel, 'Name')}</h3>
|
| 550 |
-
<p><strong>
|
| 551 |
-
<p><strong>IMO:</strong>
|
| 552 |
-
<p><strong>
|
| 553 |
-
<p><strong>
|
|
|
|
|
|
|
|
|
|
| 554 |
<p><strong>Status:</strong> <span class="{status_class}">{status_value}</span></p>
|
| 555 |
<p><strong>Insurance:</strong> {safe_get(vessel, 'Insurance')}</p>
|
|
|
|
|
|
|
| 556 |
</div>
|
| 557 |
""", unsafe_allow_html=True)
|
| 558 |
|
|
|
|
| 156 |
'Countries': ['Country', 'Location'],
|
| 157 |
'Companies': ['Company', 'Business'],
|
| 158 |
'Phone#': ['Phone', 'Telephone', 'Contact_Phone'],
|
| 159 |
+
'Linked To': ['Organization', 'Terror_Organization', 'Group'],
|
| 160 |
+
'IMO': ['IMO_Number', 'IMO_No', 'International_Maritime_Organization'],
|
| 161 |
+
'Flag': ['Flag_State', 'Flag_Country'],
|
| 162 |
+
'DWT': ['Deadweight', 'Dead_Weight_Tonnage'],
|
| 163 |
+
'Built_Year': ['Year_Built', 'Construction_Year', 'DOB'],
|
| 164 |
+
'Status': ['Vessel_Status', 'Ship_Status', 'AIS_Status'],
|
| 165 |
+
'Insurance': ['Insurer', 'Insurance_Company']
|
| 166 |
}
|
| 167 |
|
| 168 |
val = None
|
|
|
|
| 535 |
mime="text/csv"
|
| 536 |
)
|
| 537 |
|
| 538 |
+
# Filters for vessels
|
| 539 |
+
col1, col2, col3 = st.columns([3, 2, 2])
|
| 540 |
+
|
| 541 |
+
with col1:
|
| 542 |
+
name_filter = st.text_input("Search vessels", placeholder="Enter vessel name or IMO...", key="search_vessels")
|
| 543 |
+
|
| 544 |
+
with col2:
|
| 545 |
+
flag_options = ["All Flags"]
|
| 546 |
+
if len(data['vessels']) > 0 and 'Flag' in data['vessels'].columns:
|
| 547 |
+
flags = data['vessels']['Flag'].dropna().astype(str).unique()
|
| 548 |
+
flag_options += sorted([f for f in flags if f and f.lower() != 'nan'])
|
| 549 |
+
flag_filter = st.selectbox("Flag State", flag_options, key="flag_vessels")
|
| 550 |
+
|
| 551 |
+
with col3:
|
| 552 |
+
status_options = ["All Status"]
|
| 553 |
+
if len(data['vessels']) > 0 and 'Status' in data['vessels'].columns:
|
| 554 |
+
statuses = data['vessels']['Status'].dropna().astype(str).unique()
|
| 555 |
+
status_options += sorted([s for s in statuses if s and s.lower() != 'nan'])
|
| 556 |
+
status_filter = st.selectbox("Status", status_options, key="status_vessels")
|
| 557 |
|
| 558 |
# Apply filters
|
| 559 |
filtered_vessels = data['vessels'].copy()
|
| 560 |
+
|
| 561 |
if name_filter:
|
| 562 |
+
# Search in Name, IMO, and other relevant fields
|
| 563 |
+
mask = (
|
| 564 |
+
filtered_vessels['Name'].str.contains(name_filter, case=False, na=False) |
|
| 565 |
+
filtered_vessels.get('IMO', pd.Series()).astype(str).str.contains(name_filter, case=False, na=False) |
|
| 566 |
+
filtered_vessels.get('Owner', pd.Series()).astype(str).str.contains(name_filter, case=False, na=False)
|
| 567 |
+
)
|
| 568 |
+
filtered_vessels = filtered_vessels[mask]
|
| 569 |
+
|
| 570 |
+
if flag_filter != "All Flags":
|
| 571 |
+
filtered_vessels = filtered_vessels[
|
| 572 |
+
filtered_vessels['Flag'].str.contains(flag_filter, case=False, na=False)
|
| 573 |
+
]
|
| 574 |
+
|
| 575 |
+
if status_filter != "All Status":
|
| 576 |
filtered_vessels = filtered_vessels[
|
| 577 |
+
filtered_vessels['Status'] == status_filter
|
| 578 |
]
|
| 579 |
|
| 580 |
# Display vessels
|
|
|
|
| 582 |
status_value = safe_get(vessel, 'Status')
|
| 583 |
status_class = "status-inactive" if status_value == 'AIS Off' else "status-active"
|
| 584 |
|
| 585 |
+
# Get vessel-specific information
|
| 586 |
+
imo = safe_get(vessel, 'IMO')
|
| 587 |
+
flag = safe_get(vessel, 'Flag')
|
| 588 |
+
vessel_type = safe_get(vessel, 'Sub_Category')
|
| 589 |
+
owner = safe_get(vessel, 'Owner')
|
| 590 |
+
built_year = safe_get(vessel, 'Built_Year', safe_get(vessel, 'DOB')) # Sometimes vessel age is in DOB
|
| 591 |
+
dwt = safe_get(vessel, 'DWT')
|
| 592 |
+
|
| 593 |
st.markdown(f"""
|
| 594 |
<div class="entity-card">
|
| 595 |
<h3>{safe_get(vessel, 'Name')}</h3>
|
| 596 |
+
<p><strong>DC_ID:</strong> {safe_get(vessel, 'DC_ID')}</p>
|
| 597 |
+
<p><strong>IMO Number:</strong> <span style="color: #2B6CB0; font-weight: bold;">{imo}</span></p>
|
| 598 |
+
<p><strong>Vessel Type:</strong> {vessel_type}</p>
|
| 599 |
+
<p><strong>Flag State:</strong> {flag}</p>
|
| 600 |
+
<p><strong>Owner:</strong> {owner}</p>
|
| 601 |
+
<p><strong>Built Year:</strong> {built_year}</p>
|
| 602 |
+
<p><strong>DWT:</strong> {dwt}</p>
|
| 603 |
<p><strong>Status:</strong> <span class="{status_class}">{status_value}</span></p>
|
| 604 |
<p><strong>Insurance:</strong> {safe_get(vessel, 'Insurance')}</p>
|
| 605 |
+
<p><strong>Countries:</strong> {safe_get(vessel, 'Countries')}</p>
|
| 606 |
+
<p><strong>Information:</strong> {safe_get(vessel, 'Information')}</p>
|
| 607 |
</div>
|
| 608 |
""", unsafe_allow_html=True)
|
| 609 |
|