Severian commited on
Commit
ac2f3db
·
verified ·
1 Parent(s): 2f69c82

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -43
app.py CHANGED
@@ -130,7 +130,6 @@ df_human["source"] = "Human"
130
  df_combined = pd.concat([df_dog, df_human], ignore_index=True)
131
  print(f"Loaded {len(df_dog)} dog rows and {len(df_human)} human rows")
132
 
133
-
134
  # ---------------------------------------------------------------
135
  # Feature preparation and UMAP embedding
136
  # ---------------------------------------------------------------
@@ -155,29 +154,42 @@ df_combined["cluster"] = kmeans.fit_predict(features if feature_cols else df_com
155
  # Cross-Species Analysis Functions
156
  # ---------------------------------------------------------------
157
  def find_nearest_cross_species_neighbor(selected_row, df_combined, n_neighbors=5):
158
- """Find closest neighbor from opposite species using feature similarity."""
 
 
 
 
 
 
159
  selected_source = selected_row['source']
160
  opposite_source = 'Human' if selected_source == 'Dog' else 'Dog'
161
-
162
- feature_cols = [c for c in df_combined.columns if c.startswith("feature_")]
163
- if not feature_cols:
164
- opposite_data = df_combined[df_combined['source'] == opposite_source]
165
- return opposite_data.iloc[0] if len(opposite_data) > 0 else None
166
-
167
- selected_features = selected_row[feature_cols].values.reshape(1, -1)
168
- selected_features = np.nan_to_num(selected_features)
169
-
170
  opposite_data = df_combined[df_combined['source'] == opposite_source]
171
  if len(opposite_data) == 0:
172
  return None
173
-
174
- opposite_features = opposite_data[feature_cols].values
175
- opposite_features = np.nan_to_num(opposite_features)
176
-
177
- similarities = cosine_similarity(selected_features, opposite_features)[0]
178
- most_similar_idx = np.argmax(similarities)
179
-
180
- return opposite_data.iloc[most_similar_idx]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
  # Cache for performance
183
  _audio_path_cache = {}
@@ -439,7 +451,7 @@ def create_enhanced_manifold_plot(df_filtered, lens_selected, color_scheme, poin
439
 
440
  fig.update_layout(
441
  title={
442
- 'text': "🌌 Universal Interspecies Communication Manifold",
443
  'x': 0.5,
444
  'xanchor': 'center'
445
  },
@@ -598,7 +610,7 @@ def create_dual_holography_plot(z1, phi1, z2, phi2, resolution, wavelength, titl
598
  ), row=1, col=2)
599
 
600
  fig.update_layout(
601
- title="Side-by-Side Cross-Species Holographic Comparison",
602
  scene=dict(
603
  xaxis_title="Re(z)", yaxis_title="Im(z)", zaxis_title="|Φ|",
604
  camera=dict(eye=dict(x=1.5, y=1.5, z=1.5))
@@ -664,7 +676,7 @@ def create_entropy_geometry_plot(phi: np.ndarray):
664
  fig.add_trace(go.Histogram(x=phases, name='Phase', nbinsx=50), row=1, col=2)
665
 
666
  fig.update_layout(
667
- title_text="Informational-Entropy Geometry",
668
  showlegend=False,
669
  bargap=0.1,
670
  margin=dict(l=20, r=20, t=60, b=20)
@@ -1074,24 +1086,35 @@ def export_filtered_data(species_selection, emotion_selection, lens_selection,
1074
  # ---------------------------------------------------------------
1075
  with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1076
  gr.Markdown("""
1077
- # **Entronaut Holographic Information Geometry Engine**
1078
- *Revolutionary interspecies communication analysis platform*
 
 
1079
 
1080
- **Enhanced Features:**
1081
- - **Universal Manifold Explorer**: Multi-dimensional visualization suite with live statistics
1082
- - **Interactive Holography**: Cross-species communication mapping with mathematical precision
1083
- - **Real-time Analytics**: Dynamic filtering, clustering, and similarity analysis
1084
- - **Rich Visualizations**: 2D/3D plots, density heatmaps, feature distributions
1085
- - **Data Export**: Export filtered datasets for external analysis
1086
- - **⚡ Auto-loading**: Manifold visualizations load automatically on startup
1087
 
1088
- ---
1089
- **🎯 Goal**: Map the geometric structure of communication to reveal universal patterns across species
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1090
  """)
1091
 
1092
  with gr.Tabs():
1093
- with gr.TabItem("🌌 Universal Manifold Explorer"):
1094
- gr.Markdown("# 🎯 **Interspecies Communication Map**")
1095
 
1096
  with gr.Row():
1097
  with gr.Column(scale=1):
@@ -1233,7 +1256,7 @@ with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1233
  def update_cross_species_view(species, primary_file, neighbor_file, lens, resolution, wavelength):
1234
  if not primary_file:
1235
  empty_fig = go.Figure(layout={"title": "Select a primary file"})
1236
- return empty_fig, empty_fig, empty_fig, "", ""
1237
 
1238
  primary_row = df_combined[
1239
  (df_combined["filepath"] == primary_file) &
@@ -1247,8 +1270,10 @@ with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1247
  empty_fig = go.Figure(layout={"title": "Primary file not found"})
1248
  return empty_fig, empty_fig, empty_fig, "", ""
1249
 
1250
- if not neighbor_file:
1251
- neighbor_row = find_nearest_cross_species_neighbor(primary_row, df_combined)
 
 
1252
  else:
1253
  opposite_species = 'Human' if species == 'Dog' else 'Dog'
1254
  neighbor_row = df_combined[
@@ -1301,16 +1326,27 @@ with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1301
  else:
1302
  neighbor_info = ""
1303
 
1304
- return dual_holo, diag, entropy, primary_info, neighbor_info
 
 
1305
 
1306
  def update_dropdowns_on_species_change(species):
1307
  species_files = df_combined[df_combined["source"] == species]["filepath"].tolist()
1308
  opposite_species = 'Human' if species == 'Dog' else 'Dog'
1309
  neighbor_files = df_combined[df_combined["source"] == opposite_species]["filepath"].tolist()
1310
-
 
 
 
 
 
 
 
 
 
1311
  return (
1312
- gr.Dropdown(choices=species_files, value=species_files[0] if species_files else ""),
1313
- gr.Dropdown(choices=neighbor_files, value=neighbor_files[0] if neighbor_files else "")
1314
  )
1315
 
1316
  species_dropdown.change(
@@ -1326,7 +1362,8 @@ with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1326
 
1327
  cross_species_outputs = [
1328
  dual_holography_plot, diagnostic_plot, entropy_plot,
1329
- primary_info_html, neighbor_info_html
 
1330
  ]
1331
 
1332
  for input_component in cross_species_inputs:
@@ -1336,6 +1373,17 @@ with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1336
  outputs=cross_species_outputs
1337
  )
1338
 
 
 
 
 
 
 
 
 
 
 
 
1339
  # Auto-load manifold visualizations on startup
1340
  demo.load(
1341
  update_manifold_visualization,
 
130
  df_combined = pd.concat([df_dog, df_human], ignore_index=True)
131
  print(f"Loaded {len(df_dog)} dog rows and {len(df_human)} human rows")
132
 
 
133
  # ---------------------------------------------------------------
134
  # Feature preparation and UMAP embedding
135
  # ---------------------------------------------------------------
 
154
  # Cross-Species Analysis Functions
155
  # ---------------------------------------------------------------
156
  def find_nearest_cross_species_neighbor(selected_row, df_combined, n_neighbors=5):
157
+ """Find closest neighbor from opposite species using information geometry.
158
+
159
+ Priority order:
160
+ 1) Use Euclidean distance in learned manifold coordinates (x, y, z) if available
161
+ 2) Fallback to cosine similarity on feature vectors
162
+ 3) Fallback to first available opposite-species row
163
+ """
164
  selected_source = selected_row['source']
165
  opposite_source = 'Human' if selected_source == 'Dog' else 'Dog'
166
+
 
 
 
 
 
 
 
 
167
  opposite_data = df_combined[df_combined['source'] == opposite_source]
168
  if len(opposite_data) == 0:
169
  return None
170
+
171
+ # 1) Prefer geometry in manifold if available
172
+ if all(col in selected_row.index for col in ['x', 'y', 'z']) and \
173
+ all(col in opposite_data.columns for col in ['x', 'y', 'z']):
174
+ sx, sy, sz = float(selected_row['x']), float(selected_row['y']), float(selected_row['z'])
175
+ coords = opposite_data[['x', 'y', 'z']].to_numpy(dtype=float)
176
+ diffs = coords - np.array([sx, sy, sz], dtype=float)
177
+ dists = np.sqrt(np.sum(diffs * diffs, axis=1))
178
+ nearest_idx = int(np.argmin(dists))
179
+ return opposite_data.iloc[nearest_idx]
180
+
181
+ # 2) Fallback to feature-space cosine similarity
182
+ feature_cols = [c for c in df_combined.columns if c.startswith("feature_")]
183
+ if feature_cols:
184
+ selected_features = selected_row[feature_cols].values.reshape(1, -1)
185
+ selected_features = np.nan_to_num(selected_features)
186
+ opposite_features = np.nan_to_num(opposite_data[feature_cols].values)
187
+ similarities = cosine_similarity(selected_features, opposite_features)[0]
188
+ most_similar_idx = int(np.argmax(similarities))
189
+ return opposite_data.iloc[most_similar_idx]
190
+
191
+ # 3) Fallback: first available
192
+ return opposite_data.iloc[0]
193
 
194
  # Cache for performance
195
  _audio_path_cache = {}
 
451
 
452
  fig.update_layout(
453
  title={
454
+ 'text': "Shared Pattern Space of Audio Signals",
455
  'x': 0.5,
456
  'xanchor': 'center'
457
  },
 
610
  ), row=1, col=2)
611
 
612
  fig.update_layout(
613
+ title="Side-by-Side Geometric Comparison",
614
  scene=dict(
615
  xaxis_title="Re(z)", yaxis_title="Im(z)", zaxis_title="|Φ|",
616
  camera=dict(eye=dict(x=1.5, y=1.5, z=1.5))
 
676
  fig.add_trace(go.Histogram(x=phases, name='Phase', nbinsx=50), row=1, col=2)
677
 
678
  fig.update_layout(
679
+ title_text="Information-Entropy Geometry",
680
  showlegend=False,
681
  bargap=0.1,
682
  margin=dict(l=20, r=20, t=60, b=20)
 
1086
  # ---------------------------------------------------------------
1087
  with gr.Blocks(theme='Nymbo/Alyx_Theme') as demo:
1088
  gr.Markdown("""
1089
+ # **Entronaut: A Visual Explorer for Information Geometry**
1090
+ *Turn complex data into visible patterns.*
1091
+
1092
+ ---
1093
 
1094
+ ### What is Entronaut?
 
 
 
 
 
 
1095
 
1096
+ Entronaut is a tool that transforms complex data—like audio signals, financial data, or text—into geometric shapes. Think of it like a mathematical prism: just as a prism splits a beam of light into a rainbow of colors, Entronaut splits a data stream into its fundamental patterns, making hidden structures visible and explorable.
1097
+
1098
+ This demo applies Entronaut to audio recordings of human and dog sounds to reveal their underlying mathematical similarities.
1099
+
1100
+ ### How is this different from tools like FFT?
1101
+
1102
+ Traditional tools like Fast Fourier Transform (FFT) or Wavelets are excellent for breaking down a signal into its basic frequencies. They can tell you *what* notes are in a piece of music, but not how they are arranged into a melody or harmony.
1103
+
1104
+ Entronaut goes a step further. It uses **Information Geometry** to analyze the *relationships* between data points. This allows it to capture not just the components, but the intricate structure of the data itself. It reveals the 'shape' of the information, showing you how patterns are organized and connected.
1105
+
1106
+ ### What is Information Geometry?
1107
+
1108
+ In simple terms, Information Geometry is a field of math that lets us measure the "distance" and "shape" of information.
1109
+
1110
+ Imagine you have two different news articles. You could count the words, but that wouldn't tell you how similar their meaning is. Information Geometry provides tools to define a meaningful distance between them based on the information they contain. Entronaut makes this concept visual, creating a 3D map where you can see how close or far different data points are in this abstract "information space".
1111
+
1112
+ **This App's Goal**: To demonstrate how Entronaut can map sounds from different sources into a shared geometric space. By exploring this space, you can see how Entronaut reveals underlying structural patterns in sound data.
1113
  """)
1114
 
1115
  with gr.Tabs():
1116
+ with gr.TabItem("🎵 Audio Pattern Explorer"):
1117
+ gr.Markdown("## Exploring the Geometric Patterns in Sound")
1118
 
1119
  with gr.Row():
1120
  with gr.Column(scale=1):
 
1256
  def update_cross_species_view(species, primary_file, neighbor_file, lens, resolution, wavelength):
1257
  if not primary_file:
1258
  empty_fig = go.Figure(layout={"title": "Select a primary file"})
1259
+ return empty_fig, empty_fig, empty_fig, "", "", gr.Dropdown()
1260
 
1261
  primary_row = df_combined[
1262
  (df_combined["filepath"] == primary_file) &
 
1270
  empty_fig = go.Figure(layout={"title": "Primary file not found"})
1271
  return empty_fig, empty_fig, empty_fig, "", ""
1272
 
1273
+ auto_neighbor_row = find_nearest_cross_species_neighbor(primary_row, df_combined)
1274
+
1275
+ if not neighbor_file and auto_neighbor_row is not None:
1276
+ neighbor_row = auto_neighbor_row
1277
  else:
1278
  opposite_species = 'Human' if species == 'Dog' else 'Dog'
1279
  neighbor_row = df_combined[
 
1326
  else:
1327
  neighbor_info = ""
1328
 
1329
+ # If we used auto neighbor, preselect it in the dropdown
1330
+ neighbor_dropdown_value = gr.Dropdown(value=(neighbor_row['filepath'] if neighbor_row is not None else None))
1331
+ return dual_holo, diag, entropy, primary_info, neighbor_info, neighbor_dropdown_value
1332
 
1333
  def update_dropdowns_on_species_change(species):
1334
  species_files = df_combined[df_combined["source"] == species]["filepath"].tolist()
1335
  opposite_species = 'Human' if species == 'Dog' else 'Dog'
1336
  neighbor_files = df_combined[df_combined["source"] == opposite_species]["filepath"].tolist()
1337
+
1338
+ # Preselect first file for species and auto-pick nearest neighbor for that primary if available
1339
+ primary_value = species_files[0] if species_files else ""
1340
+ if primary_value:
1341
+ primary_row = df_combined[(df_combined["filepath"] == primary_value) & (df_combined["source"] == species)].iloc[0]
1342
+ neighbor_row = find_nearest_cross_species_neighbor(primary_row, df_combined)
1343
+ neighbor_value = neighbor_row['filepath'] if neighbor_row is not None else (neighbor_files[0] if neighbor_files else "")
1344
+ else:
1345
+ neighbor_value = neighbor_files[0] if neighbor_files else ""
1346
+
1347
  return (
1348
+ gr.Dropdown(choices=species_files, value=primary_value),
1349
+ gr.Dropdown(choices=neighbor_files, value=neighbor_value)
1350
  )
1351
 
1352
  species_dropdown.change(
 
1362
 
1363
  cross_species_outputs = [
1364
  dual_holography_plot, diagnostic_plot, entropy_plot,
1365
+ primary_info_html, neighbor_info_html,
1366
+ neighbor_dropdown
1367
  ]
1368
 
1369
  for input_component in cross_species_inputs:
 
1373
  outputs=cross_species_outputs
1374
  )
1375
 
1376
+ # When the primary file changes, auto-update neighbor selection to nearest geometry match
1377
+ def on_primary_change(species, primary_value, neighbor_value, lens, resolution, wavelength):
1378
+ # Reuse update_cross_species_view to recompute plots and auto neighbor
1379
+ return update_cross_species_view(species, primary_value, None, lens, resolution, wavelength)
1380
+
1381
+ primary_dropdown.change(
1382
+ on_primary_change,
1383
+ inputs=cross_species_inputs,
1384
+ outputs=cross_species_outputs
1385
+ )
1386
+
1387
  # Auto-load manifold visualizations on startup
1388
  demo.load(
1389
  update_manifold_visualization,