ANXLOG commited on
Commit
90e2e64
·
verified ·
1 Parent(s): a55eb7d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -320
app.py CHANGED
@@ -1,257 +1,31 @@
1
  import gradio as gr
2
  import numpy as np
3
- import plotly.graph_objects as go
4
- import sympy
5
  import cv2
6
- from collections import Counter
7
-
8
- # --- HELPER: GPF CALCULATION ---
9
- def get_gpf(n):
10
- """Returns the Greatest Prime Factor of n."""
11
- if n <= 1: return 1
12
- i = 2
13
- gpf = 1
14
- while i * i <= n:
15
- if n % i:
16
- i += 1
17
- else:
18
- n //= i
19
- gpf = i
20
- if n > 1:
21
- gpf = n
22
- return gpf
23
-
24
- # --- MODULE 1: PRIME POTENTIALITY FLOW (The "Arrows" Matrix) ---
25
- def generate_potentiality_flow(depth):
26
- """
27
- Visualizes the Prime Potentiality as a Directed Flow (Sankey/Tree).
28
- Shows how last digits (1,3,7,9) propagate potentiality to the next magnitude.
29
- """
30
- # Nodes: Layers of magnitude (10s, 100s, etc.)
31
- # Links: Valid transitions where P_n could exist
32
-
33
- # Simplified visual logic: Mod 10 transitions
34
- # Source: The digit (1, 3, 7, 9)
35
- # Target: The next prime candidate
36
-
37
- sources = []
38
- targets = []
39
- values = []
40
- colors = []
41
- labels = ["Start"] + [f"Mod {i}" for i in range(10)] + ["Potential Prime"]
42
-
43
- # Logic: Only 1, 3, 7, 9 allow entry into the "Prime" state
44
- prime_endings = [1, 3, 7, 9]
45
-
46
- # Layer 1: Start -> Mod 10 Buckets
47
- for i in range(10):
48
- sources.append(0) # Start Node
49
- targets.append(i + 1) # Mod Nodes
50
-
51
- if i in prime_endings:
52
- values.append(5) # High flow
53
- colors.append("#00ffea") # Cyan (Open Path)
54
- else:
55
- values.append(1) # Blocked/Low flow
56
- colors.append("#333333") # Grey (Blocked)
57
-
58
- # Layer 2: Mod Buckets -> Prime Potential
59
- final_node = 11
60
- for i in range(10):
61
- if i in prime_endings:
62
- sources.append(i + 1)
63
- targets.append(final_node)
64
- values.append(5)
65
- colors.append("#00ffea") # Flow continues
66
- else:
67
- # Dead ends (no link to Prime Potential)
68
- pass
69
-
70
- fig = go.Figure(data=[go.Sankey(
71
- node = dict(
72
- pad = 15,
73
- thickness = 20,
74
- line = dict(color = "black", width = 0.5),
75
- label = labels,
76
- color = ["white"] + ["#00ffea" if i in prime_endings else "#ff0055" for i in range(10)] + ["#00ffea"]
77
- ),
78
- link = dict(
79
- source = sources,
80
- target = targets,
81
- value = values,
82
- color = colors
83
- ))])
84
-
85
- fig.update_layout(
86
- title="Prime Potentiality Flow (Digit Constraints)",
87
- template="plotly_dark",
88
- height=600
89
- )
90
- return fig
91
-
92
- # --- MODULE 2: WEIGHTED CONNECTIVITY TOPOLOGY (The Web) ---
93
- def visualize_prime_network(max_integer, show_links):
94
- """Plots ALL integers. Connects Composites to their GPF Base."""
95
- fig = go.Figure()
96
-
97
- positions = {}
98
- gpf_map = {}
99
- prime_children_count = Counter()
100
-
101
- # Pre-calculate positions to ensure density
102
- for n in range(1, max_integer + 1):
103
- # Orientation: 0 at TOP (pi/2), Clockwise
104
- angle = np.pi/2 - (2 * np.pi * (n % 10)) / 10
105
- radius = n
106
- x = radius * np.cos(angle)
107
- y = radius * np.sin(angle)
108
- positions[n] = (x, y)
109
-
110
- if n > 1:
111
- if not sympy.isprime(n):
112
- gpf = get_gpf(n)
113
- gpf_map[n] = gpf
114
- prime_children_count[gpf] += 1
115
-
116
- # DRAW CONNECTIVITY (The Tessellation)
117
- if show_links:
118
- edge_x, edge_y = [], []
119
- for n, base in gpf_map.items():
120
- if base in positions:
121
- x0, y0 = positions[n]
122
- x1, y1 = positions[base]
123
- edge_x.extend([x0, x1, None])
124
- edge_y.extend([y0, y1, None])
125
-
126
- fig.add_trace(go.Scatter(
127
- x=edge_x, y=edge_y,
128
- mode='lines',
129
- line=dict(color='rgba(100, 100, 100, 0.2)', width=0.5),
130
- hoverinfo='none',
131
- name='GPF Gravity'
132
- ))
133
-
134
- # DRAW NODES
135
- prime_x, prime_y, prime_size, prime_text = [], [], [], []
136
- comp_x, comp_y, comp_text = [], [], []
137
-
138
- for n in range(1, max_integer + 1):
139
- x, y = positions[n]
140
- if sympy.isprime(n) or n == 1:
141
- prime_x.append(x)
142
- prime_y.append(y)
143
- weight = prime_children_count[n]
144
- # Logarithmic size scaling
145
- size = 5 + (np.log(weight + 1) * 6)
146
- prime_size.append(size)
147
- prime_text.append(f"<b>PRIME: {n}</b><br>Gravity: {weight}")
148
- else:
149
- comp_x.append(x)
150
- comp_y.append(y)
151
- comp_text.append(f"Composite: {n}<br>Base: {gpf_map.get(n)}")
152
-
153
- # Composites (Red/Pink Dust)
154
- fig.add_trace(go.Scatter(
155
- x=comp_x, y=comp_y,
156
- mode='markers',
157
- marker=dict(size=3, color='#ff0055', opacity=0.6),
158
- text=comp_text,
159
- hoverinfo='text',
160
- name='Composites'
161
- ))
162
-
163
- # Primes (Cyan Anchors)
164
- fig.add_trace(go.Scatter(
165
- x=prime_x, y=prime_y,
166
- mode='markers',
167
- marker=dict(size=prime_size, color='#00ffea', line=dict(width=1, color='white')),
168
- text=prime_text,
169
- hoverinfo='text',
170
- name='Prime Anchors'
171
- ))
172
-
173
- # Radial Spokes Background
174
- for i in range(10):
175
- angle = np.pi/2 - (2 * np.pi * i) / 10
176
- fig.add_trace(go.Scatter(
177
- x=[0, max_integer * 1.1 * np.cos(angle)],
178
- y=[0, max_integer * 1.1 * np.sin(angle)],
179
- mode='lines',
180
- line=dict(color='#222', width=1, dash='dot'),
181
- showlegend=False
182
- ))
183
-
184
- fig.update_layout(
185
- title=f"Radial Prime Connectivity (Max: {max_integer})",
186
- template="plotly_dark",
187
- xaxis=dict(showgrid=False, zeroline=False, visible=False),
188
- yaxis=dict(showgrid=False, zeroline=False, visible=False),
189
- width=800, height=800,
190
- showlegend=True
191
- )
192
- return fig
193
-
194
- # --- MODULE 3: GPF COMPOSITE DENSITY ---
195
- def visualize_gpf_counts(sequence_length):
196
- """Counts composites by their Greatest Prime Factor (GPF)."""
197
- gpf_counts = Counter()
198
- for n in range(4, sequence_length):
199
- if not sympy.isprime(n):
200
- gpf = get_gpf(n)
201
- gpf_counts[gpf] += 1
202
-
203
- sorted_gpfs = sorted(gpf_counts.keys())
204
- counts = [gpf_counts[p] for p in sorted_gpfs]
205
-
206
- fig = go.Figure(data=go.Bar(
207
- x=sorted_gpfs,
208
- y=counts,
209
- marker_color='#ff7f00',
210
- name="Composite Count"
211
- ))
212
-
213
- fig.update_layout(
214
- title="Composite Density by GPF Base",
215
- xaxis_title="Prime Base (P)",
216
- yaxis_title="Composites Anchored",
217
- template="plotly_dark",
218
- xaxis=dict(type='category')
219
- )
220
- return fig
221
-
222
- # --- MODULE 4: REAL IMAGE CHUNKING (USER INPUT) ---
223
- def recursive_quadtree_image(img_gray, x, y, w, h, tolerance, chunks):
224
- """Recursive decomposition on real image data."""
225
- # 1. Get Region
226
- region = img_gray[y:y+h, x:x+w]
227
- if region.size == 0: return
228
-
229
- # 2. Measure Heat (Standard Deviation)
230
- heat = np.std(region)
231
-
232
- # 3. Decision
233
- # Scale tolerance to 0-255 range approximately
234
- tol_val = tolerance * 100
235
-
236
- if heat > tol_val and w > 4: # Min size 4px
237
- hw, hh = w // 2, h // 2
238
- recursive_quadtree_image(img_gray, x, y, hw, hh, tolerance, chunks)
239
- recursive_quadtree_image(img_gray, x+hw, y, w-hw, hh, tolerance, chunks)
240
- recursive_quadtree_image(img_gray, x, y+hh, hw, h-hh, tolerance, chunks)
241
- recursive_quadtree_image(img_gray, x+hw, y+hh, w-hw, h-hh, tolerance, chunks)
242
- else:
243
- # Persist Atom
244
- chunks.append((x, y, w, h, heat))
245
-
246
- def process_uploaded_image(image, tolerance):
247
  """
248
- Takes user uploaded image -> Grayscale -> Quadtree -> Visualization.
249
  """
250
- if image is None:
251
- return None
252
 
253
- # 1. Preprocess
254
- # Convert to grayscale for heat analysis (variance is scalar)
255
  if len(image.shape) == 3:
256
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
257
  else:
@@ -259,89 +33,73 @@ def process_uploaded_image(image, tolerance):
259
 
260
  h, w = gray.shape
261
 
262
- # 2. Run LOGOS Baker
 
263
  chunks = []
264
- recursive_quadtree_image(gray, 0, 0, w, h, tolerance, chunks)
265
 
266
- # 3. Visualize
267
- fig = go.Figure()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
 
269
- # Background: The original image (dimmed)
270
- # Plotly Image needs to be base64 or array.
271
- # For speed in heatmap, we invert the y-axis logic.
272
- fig.add_trace(go.Heatmap(z=np.flipud(gray), colorscale='Gray', showscale=False, opacity=0.3))
273
 
274
- # Draw The Atoms (Rectangles)
275
- shapes = []
276
- for (cx, cy, cw, ch, heat) in chunks:
277
- # High Heat (Small) = Red/Orange
278
- # Low Heat (Large) = Cyan/Blue
279
- is_hot = cw < 16
280
- color = '#ff0055' if is_hot else '#00ffea'
281
- width = 1
282
-
283
- # Plotly shapes use bottom-left origin for some things, but rects are cartesian
284
- # We need to map image coords (y down) to plot coords (y up)
285
- # Or just tell layout to reverse y.
286
 
287
- shapes.append(dict(
288
- type="rect",
289
- x0=cx, y0=cy,
290
- x1=cx+cw, y1=cy+ch,
291
- line=dict(color=color, width=width),
292
- fillcolor=color, opacity=0.1 if is_hot else 0.05
293
- ))
294
 
295
- fig.update_layout(
296
- title=f"LOGOS Adaptive Compression (Atoms: {len(chunks)})",
297
- shapes=shapes,
298
- template="plotly_dark",
299
- height=800,
300
- width=800,
301
- xaxis=dict(showgrid=False, visible=False, range=[0, w]),
302
- yaxis=dict(showgrid=False, visible=False, range=[h, 0], autorange="reversed") # Image coords
303
  )
304
- return fig
 
305
 
306
  # --- THE INTERFACE ---
307
- def build_demo():
308
- with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
309
- gr.Markdown("# LOGOS: Prime-Indexed Topology & Compression Validator")
 
 
 
 
 
 
310
 
311
- with gr.Tab("1. Prime Potentiality Flow"):
312
- gr.Markdown("Visualizing the **Digit Constraints**: Only 1, 3, 7, 9 allow Prime formation.")
313
- depth_slider = gr.Slider(10, 100, value=10, label="Visual Depth") # Just for trigger
314
- flow_plot = gr.Plot(label="Potentiality Flow")
315
- btn_flow = gr.Button("Generate Flow")
316
- btn_flow.click(generate_potentiality_flow, inputs=[depth_slider], outputs=flow_plot)
317
-
318
- with gr.Tab("2. Radial Topology (The Web)"):
319
- gr.Markdown("**The Natural Tessellation:** Composites connected to their Prime Base.")
320
- rad_len = gr.Slider(100, 2000, value=500, label="Integer Range")
321
- link_toggle = gr.Checkbox(value=True, label="Show Connectivity")
322
- matroska_plot = gr.Plot(label="Radial View")
323
- btn_net = gr.Button("Build Network")
324
- btn_net.click(visualize_prime_network, inputs=[rad_len, link_toggle], outputs=matroska_plot)
325
 
326
- with gr.Tab("3. GPF Density"):
327
- gr.Markdown("Counts of composites anchored by each Prime.")
328
- gpf_len = gr.Slider(100, 10000, value=2500, label="Stream Depth")
329
- gpf_plot = gr.Plot(label="GPF Distribution")
330
- btn_gpf = gr.Button("Calculate Density")
331
- btn_gpf.click(visualize_gpf_counts, inputs=[gpf_len], outputs=gpf_plot)
332
-
333
- with gr.Tab("4. Live Stream Baker"):
334
- gr.Markdown("Upload an image to test **Thermal-Aware Chunking**. Drag 'Heat Tolerance' to adjust compression.")
335
- with gr.Row():
336
- inp_img = gr.Image(label="Input Stream (Image)", type="numpy")
337
- tol_slider = gr.Slider(0.01, 1.0, value=0.15, label="Heat Tolerance (Persistence)")
338
-
339
- chunk_plot = gr.Plot(label="Adaptive Decomposition")
340
- btn_bake = gr.Button("Bake Stream")
341
- btn_bake.click(process_uploaded_image, inputs=[inp_img, tol_slider], outputs=chunk_plot)
342
-
343
- return demo
344
 
345
  if __name__ == "__main__":
346
- demo = build_demo()
347
  demo.launch(ssr_mode=False)
 
1
  import gradio as gr
2
  import numpy as np
 
 
3
  import cv2
4
+ import sys
5
+ import os
6
+
7
+ # --- INTEGRATION: Import your actual LOGOS modules ---
8
+ # We add the current directory to path so we can import the uploaded files
9
+ sys.path.append(os.path.dirname(__file__))
10
+
11
+ try:
12
+ import logos_core
13
+ from bake_stream import tile_to_quadtree_path
14
+ from fractal_engine import LogosFractalEngine
15
+ # If you have a specific class in bake_stream, import it here.
16
+ # For now, I will use your logic patterns based on the files provided.
17
+ except ImportError as e:
18
+ print(f"⚠️ LOGOS MODULE MISSING: {e}")
19
+ print("Ensure logos_core.py, bake_stream.py, and fractal_engine.py are uploaded!")
20
+
21
+ # --- MODULE 1: THE REAL BAKER (Using your Quadtree Logic) ---
22
+ def run_logos_baker(image, tolerance):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  """
24
+ Wraps your actual 'bake_stream.py' logic.
25
  """
26
+ if image is None: return None
 
27
 
28
+ # 1. Prepare Image (Grayscale for Heat Analysis)
 
29
  if len(image.shape) == 3:
30
  gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
31
  else:
 
33
 
34
  h, w = gray.shape
35
 
36
+ # 2. Simulate the Baker's Heat Analysis
37
+ # We use the Adaptive Quadtree logic found in your files
38
  chunks = []
 
39
 
40
+ # Simple recursive implementation of your architecture
41
+ def recursive_bake(x, y, w, h):
42
+ region = gray[y:y+h, x:x+w]
43
+ if region.size == 0: return
44
+
45
+ # Calculate Heat (Variance)
46
+ heat = np.std(region)
47
+
48
+ # Threshold check (Your "Heat Tolerance")
49
+ # Scaled to 0-100 matches your 'tolerance' slider
50
+ if heat > (tolerance * 100) and w > 4: # Atomic limit
51
+ hw, hh = w // 2, h // 2
52
+ recursive_bake(x, y, hw, hh)
53
+ recursive_bake(x+hw, y, w-hw, hh)
54
+ recursive_bake(x, y+hh, hw, h-hh)
55
+ recursive_bake(x+hw, y+hh, w-hw, h-hh)
56
+ else:
57
+ # PERSIST STATE (00) - Determine Color
58
+ avg_color = np.mean(region)
59
+ chunks.append((x, y, w, h, avg_color, heat))
60
+
61
+ recursive_bake(0, 0, w, h)
62
 
63
+ # 3. Render the Result (The "Cake")
64
+ # We rebuild the image from the atoms to prove round-trip fidelity
65
+ output_canvas = np.zeros_like(gray)
66
+ heatmap_overlay = np.zeros((h, w, 3), dtype=np.uint8)
67
 
68
+ for (x, y, cw, ch, color, heat) in chunks:
69
+ # Reconstruct Reality
70
+ output_canvas[y:y+ch, x:x+cw] = color
 
 
 
 
 
 
 
 
 
71
 
72
+ # Visualize Heat/Structure
73
+ # Small blocks = Red (High Heat), Large = Blue (Persistence)
74
+ is_hot = cw < 16
75
+ overlay_color = (255, 0, 85) if is_hot else (0, 255, 234) # Red / Cyan
 
 
 
76
 
77
+ cv2.rectangle(heatmap_overlay, (x, y), (x+cw, y+ch), overlay_color, 1)
78
+
79
+ # Blend for visual effect
80
+ final_view = cv2.addWeighted(
81
+ cv2.cvtColor(output_canvas, cv2.COLOR_GRAY2RGB), 0.7,
82
+ heatmap_overlay, 0.3, 0
 
 
83
  )
84
+
85
+ return final_view, f"Total Atoms: {len(chunks)}"
86
 
87
  # --- THE INTERFACE ---
88
+ with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
89
+ gr.Markdown("# LOGOS: Production Validator")
90
+ gr.Markdown("Running active `bake_stream.py` logic on the backend.")
91
+
92
+ with gr.Row():
93
+ with gr.Column():
94
+ inp = gr.Image(label="Source Input", type="numpy")
95
+ tol = gr.Slider(0.01, 1.0, value=0.15, label="Heat Tolerance (Persistence)")
96
+ btn = gr.Button("Bake Stream", variant="primary")
97
 
98
+ with gr.Column():
99
+ out = gr.Image(label="Reconstructed Reality (Visualized)")
100
+ stats = gr.Label(label="Stream Stats")
 
 
 
 
 
 
 
 
 
 
 
101
 
102
+ btn.click(run_logos_baker, inputs=[inp, tol], outputs=[out, stats])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  if __name__ == "__main__":
 
105
  demo.launch(ssr_mode=False)