Neurasense / app.py
Sephfox's picture
Update app.py
d9be852 verified
raw
history blame
8.26 kB
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
from streamlit_drawable_canvas import st_canvas
import time
from PIL import Image, ImageDraw
import io
from transformers import AutoModelForCausalLM, AutoTokenizer
# Constants
WIDTH, HEIGHT = 1000, 600
AVATAR_WIDTH, AVATAR_HEIGHT = 400, 600
# Set up DialoGPT model
@st.cache_resource
def load_model():
tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-medium")
model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-medium")
return tokenizer, model
tokenizer, model = load_model()
# Simulated Sensor Classes
class PressureSensor:
def __init__(self, sensitivity=1.0):
self.sensitivity = sensitivity
def measure(self, pressure):
return pressure * self.sensitivity
class TemperatureSensor:
def __init__(self, base_temp=37.0):
self.base_temp = base_temp
def measure(self, touch_temp):
return self.base_temp + (touch_temp - self.base_temp) * 0.1
class TextureSensor:
def __init__(self):
self.textures = ["smooth", "rough", "bumpy", "silky", "grainy"]
def measure(self, x, y):
return self.textures[hash((x, y)) % len(self.textures)]
class EMFieldSensor:
def measure(self, x, y):
return np.sin(x/50) * np.cos(y/50) * 10 # simulated EM field
# Create sensation map for the avatar
def create_sensation_map(width, height):
sensation_map = np.zeros((height, width, 7)) # RGBPVTE channels for pain, pleasure, neutral, pressure, velocity, temperature, and EM sensitivity
for y in range(height):
for x in range(width):
pain = np.exp(-((x-100)**2 + (y-150)**2) / 5000) + np.exp(-((x-300)**2 + (y-450)**2) / 5000)
pleasure = np.exp(-((x-200)**2 + (y-300)**2) / 5000) + np.exp(-((x-100)**2 + (y-500)**2) / 5000)
neutral = 1 - (pain + pleasure)
pressure = np.exp(-((x-50)**2 + (y-150)**2) / 2000) + np.exp(-((x-350)**2 + (y-150)**2) / 2000) + \
np.exp(-((x-100)**2 + (y-550)**2) / 2000) + np.exp(-((x-300)**2 + (y-550)**2) / 2000)
velocity = np.exp(-((x-200)**2 + (y-100)**2) / 5000) + np.exp(-((x-200)**2 + (y-300)**2) / 5000)
temperature = np.exp(-((x-200)**2 + (y-200)**2) / 10000) # more sensitive in the core
em_sensitivity = np.exp(-((x-200)**2 + (y-100)**2) / 8000) # more sensitive in the head
sensation_map[y, x] = [pain, pleasure, neutral, pressure, velocity, temperature, em_sensitivity]
return sensation_map
avatar_sensation_map = create_sensation_map(AVATAR_WIDTH, AVATAR_HEIGHT)
# Initialize sensors
pressure_sensor = PressureSensor()
temp_sensor = TemperatureSensor()
texture_sensor = TextureSensor()
em_sensor = EMFieldSensor()
# Create human-like avatar (same as before)
def create_avatar():
img = Image.new('RGB', (AVATAR_WIDTH, AVATAR_HEIGHT), color='white')
draw = ImageDraw.Draw(img)
# Head
draw.ellipse([150, 50, 250, 150], fill='beige', outline='black')
# Body
draw.rectangle([175, 150, 225, 400], fill='beige', outline='black')
# Arms
draw.rectangle([125, 150, 175, 350], fill='beige', outline='black')
draw.rectangle([225, 150, 275, 350], fill='beige', outline='black')
# Legs
draw.rectangle([175, 400, 200, 550], fill='beige', outline='black')
draw.rectangle([200, 400, 225, 550], fill='beige', outline='black')
return img
avatar_image = create_avatar()
# Streamlit app
st.title("Advanced Humanoid Techno-Sensory Simulation")
# Create two columns
col1, col2 = st.columns(2)
# Avatar column
with col1:
st.subheader("Humanoid Avatar")
st.image(avatar_image, use_column_width=True)
# Touch interface column
with col2:
st.subheader("Touch Interface")
canvas_result = st_canvas(
fill_color="rgba(255, 165, 0, 0.3)",
stroke_width=3,
stroke_color="#e00",
background_color="#eee",
background_image=avatar_image,
update_streamlit=True,
height=AVATAR_HEIGHT,
width=AVATAR_WIDTH,
drawing_mode="freedraw",
key="canvas",
)
def calculate_sensation(x, y, pressure, velocity):
sensation = avatar_sensation_map[int(y), int(x)]
pain, pleasure, neutral, pressure_sensitivity, velocity_sensitivity, temp_sensitivity, em_sensitivity = sensation
measured_pressure = pressure_sensor.measure(pressure * pressure_sensitivity)
measured_temp = temp_sensor.measure(37 + pressure * 5) # Simulating temperature increase with pressure
measured_texture = texture_sensor.measure(x, y)
measured_em = em_sensor.measure(x, y) * em_sensitivity
modified_pain = pain * measured_pressure / 10
modified_pleasure = pleasure * velocity * velocity_sensitivity
modified_neutral = neutral * (1 - (measured_pressure + velocity) / 2)
return modified_pain, modified_pleasure, modified_neutral, measured_pressure, measured_temp, measured_texture, measured_em
def generate_description(x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em):
prompt = f"""Human: Describe the sensation when touched at ({x:.1f}, {y:.1f}) with these measurements:
Pressure: {measured_pressure:.2f}
Temperature: {measured_temp:.2f}°C
Texture: {measured_texture}
Electromagnetic field: {measured_em:.2f}
Resulting in:
Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}
Avatar:"""
input_ids = tokenizer.encode(prompt, return_tensors="pt")
output = model.generate(input_ids, max_length=200, num_return_sequences=1, no_repeat_ngram_size=2, top_k=50, top_p=0.95, temperature=0.7)
return tokenizer.decode(output[0], skip_special_tokens=True).split("Avatar: ")[-1].strip()
# Initialize session state
if 'touch_history' not in st.session_state:
st.session_state.touch_history = []
# Handle touch events
if canvas_result.json_data is not None:
objects = canvas_result.json_data["objects"]
if len(objects) > 0:
new_points = objects[-1].get("points", [])
if new_points:
for i in range(1, len(new_points)):
x1, y1 = new_points[i-1]["x"], new_points[i-1]["y"]
x2, y2 = new_points[i]["x"], new_points[i]["y"]
# Calculate pressure and velocity
distance = np.sqrt((x2-x1)**2 + (y2-y1)**2)
velocity = distance / 0.01 # Assuming 10ms between points
pressure = 1 + velocity / 100 # Simple pressure model
x, y = (x1 + x2) / 2, (y1 + y2) / 2
pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em = calculate_sensation(x, y, pressure, velocity)
st.session_state.touch_history.append((x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em))
# Display touch history and generate descriptions
if st.session_state.touch_history:
st.subheader("Touch History and Sensations")
for x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em in st.session_state.touch_history[-5:]:
st.write(f"Touch at ({x:.1f}, {y:.1f})")
st.write(f"Pressure: {measured_pressure:.2f}, Temperature: {measured_temp:.2f}°C")
st.write(f"Texture: {measured_texture}, EM Field: {measured_em:.2f}")
st.write(f"Sensations - Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}")
description = generate_description(x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em)
st.write("Avatar's response:")
st.write(description)
st.write("---")
st.write("Draw on the avatar to simulate touch. The simulation will process pressure, temperature, texture, and electromagnetic sensations.")
# Add a button to clear the touch history
if st.button("Clear Touch History"):
st.session_state.touch_history = []
st.experimental_rerun()