From f1a812b8005f0e541d585313aa51659c7299118a Mon Sep 17 00:00:00 2001 From: Fiedler Date: Wed, 24 Sep 2025 14:28:18 +0200 Subject: [PATCH] added txt, data and scripts --- Data/Avata_ConvAI_Links.txt | 58 +++++++++++++++++++++++ Data/scripts/evaluate_distances.py | 49 +++++++++++++++++++ Data/scripts/fix_decimal_csv.py | 38 +++++++++++++++ Data/scripts/plot_boxplots.py | 75 +++++++++++++++++++++++++++++ Data/scripts/plot_distances.py | 76 ++++++++++++++++++++++++++++++ 5 files changed, 296 insertions(+) create mode 100644 Data/Avata_ConvAI_Links.txt create mode 100644 Data/scripts/evaluate_distances.py create mode 100644 Data/scripts/fix_decimal_csv.py create mode 100644 Data/scripts/plot_boxplots.py create mode 100644 Data/scripts/plot_distances.py diff --git a/Data/Avata_ConvAI_Links.txt b/Data/Avata_ConvAI_Links.txt new file mode 100644 index 0000000..1702945 --- /dev/null +++ b/Data/Avata_ConvAI_Links.txt @@ -0,0 +1,58 @@ + + + +Avatare - Conversational AI + +Luisa 1 (Kopfhörer) +https://x.convai.com/?xpid=65b0cc0b-3f12-478c-94c4-49824bdb2de5&type=unlisted + +Luisa 2 (Tastatur) +https://x.convai.com/?xpid=752c0f31-8572-4aa9-9b14-c99a90e7c7b2&type=unlisted + +Luisa 3 (Maus-Tastatur-Kombi) +https://x.convai.com/?xpid=759a4548-6e50-4e3d-af0b-43b38128bf13&type=unlisted + +Luisa 4 (LED Lampe) +https://x.convai.com/?xpid=12478e65-6fea-4472-950e-540b6df8a4a7&type=unlisted + + + +Robot 1 (Kopfhörer) +https://x.convai.com/?xpid=ffca4f69-9e28-41ce-a3c6-67f3c0663205&type=unlisted + +Robot 2 (Tastatur) +https://x.convai.com/?xpid=f529a1eb-c641-4e0c-863d-225857407011&type=unlisted + +Robot 3 (Maus-Tastatur-Kombi) +https://x.convai.com/?xpid=a465d0c9-451d-4b52-998f-082249eccdcb&type=draft + +Robot 4 (LED Lampe) +https://x.convai.com/?xpid=a465d0c9-451d-4b52-998f-082249eccdcb&type=draft + + + +Abstract 1 (Kopfhörer) +https://x.convai.com/?xpid=09252c2a-a1ba-46ba-b8a4-82ccee898eb8&type=unlisted + +Abstract 2 (Tastatur) +https://x.convai.com/?xpid=ed05c1c7-03d5-4d53-b9db-bcf87b62767e&type=unlisted + +Abstract 3 (Maus-Tastatur-Kombi) +https://x.convai.com/?xpid=d51e34b0-2f23-4388-b98f-b75eae220889&type=unlisted + +Abstract 4 (LED Lampe) +https://x.convai.com/?xpid=21802cc4-1717-4b17-9f29-2d47fc48d4d4&type=unlisted + + + +Particle 1 (Kopfhörer) +https://x.convai.com/?xpid=0249ffab-4ec6-4527-9271-b346297d65f2&type=unlisted + +Particle 2 (Tastatur) +https://x.convai.com/?xpid=775ef04c-973a-4796-b377-d71465fc8e37&type=unlisted + +Particle 3 (Maus-Tastatur-Kombi) +https://x.convai.com/?xpid=5a107a6c-380a-433e-8002-441d5edfcce1&type=draft + +Particle 4 (LED Lampe) +https://x.convai.com/?xpid=606ccce7-3edd-4e28-a502-19361e6b1fd9&type=unlisted \ No newline at end of file diff --git a/Data/scripts/evaluate_distances.py b/Data/scripts/evaluate_distances.py new file mode 100644 index 0000000..029b042 --- /dev/null +++ b/Data/scripts/evaluate_distances.py @@ -0,0 +1,49 @@ +import pandas as pd +import numpy as np +from pathlib import Path + +def load_csv_with_standard_decimal(file_path): + with open(file_path, 'r') as f: + scene_line = f.readline().strip() + scene_name = scene_line.split(': ')[1].split('_')[0] + df = pd.read_csv(file_path, skiprows=1) + return df, scene_name + +def calculate_distance(row): + origin = np.array([row['XR_Origin_X'], row['XR_Origin_Y'], row['XR_Origin_Z']]) + tracked = np.array([row['TrackedObject_X'], row['TrackedObject_Y'], row['TrackedObject_Z']]) + return np.linalg.norm(tracked - origin) + +def process_position_data(data_dir): + data_by_scene = {} + all_distances = [] + csv_files = list(Path(data_dir).glob('**/P*_PositionData*.csv')) + for file_path in csv_files: + df, scene_name = load_csv_with_standard_decimal(str(file_path)) + df['Distance'] = df.apply(calculate_distance, axis=1) + all_distances.extend(df['Distance']) + if scene_name not in data_by_scene: + data_by_scene[scene_name] = [] + data_by_scene[scene_name].extend(df['Distance']) + return all_distances, data_by_scene + +def print_stats(distances, label): + distances = np.array(distances) + print(f"\n--- {label} ---") + print(f"Count: {len(distances)}") + print(f"Mean: {np.mean(distances):.4f}") + print(f"Std: {np.std(distances):.4f}") + print(f"Min: {np.min(distances):.4f}") + print(f"Max: {np.max(distances):.4f}") + print(f"25th percentile: {np.percentile(distances, 25):.4f}") + print(f"50th percentile (median): {np.percentile(distances, 50):.4f}") + print(f"75th percentile: {np.percentile(distances, 75):.4f}") + +def main(): + all_distances, data_by_scene = process_position_data('Recordings') + print_stats(all_distances, 'All Scenes Combined') + for scene, distances in data_by_scene.items(): + print_stats(distances, f'Scene: {scene}') + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Data/scripts/fix_decimal_csv.py b/Data/scripts/fix_decimal_csv.py new file mode 100644 index 0000000..8bd656a --- /dev/null +++ b/Data/scripts/fix_decimal_csv.py @@ -0,0 +1,38 @@ +import sys +import csv +from pathlib import Path + +def fix_decimal_csv(input_path, output_path): + with open(input_path, 'r', newline='', encoding='utf-8') as infile, \ + open(output_path, 'w', newline='', encoding='utf-8') as outfile: + reader = csv.reader(infile) + writer = csv.writer(outfile) + # Write the first line (scene name) as is + scene_line = next(reader) + writer.writerow(scene_line) + # Write the header as is (if present) + header = next(reader) + writer.writerow(header) + for row in reader: + # Keep first two columns as is + fixed_row = row[:2] + # Join every pair of columns from the third onward + for i in range(2, len(row), 2): + if i+1 < len(row): + fixed_val = f'{row[i]}.{row[i+1]}' + fixed_row.append(fixed_val) + writer.writerow(fixed_row) + +if __name__ == '__main__': + # Find all matching CSVs recursively + root = Path('.') + out_root = root / 'Recordings' + out_root.mkdir(exist_ok=True) + csv_files = list(root.rglob('P*_PositionData*.csv')) + for csv_file in csv_files: + # Compute output path in Recordings dir, preserving subdirs + rel_path = csv_file.relative_to(root) + out_path = out_root / rel_path + out_path.parent.mkdir(parents=True, exist_ok=True) + fix_decimal_csv(csv_file, out_path) + print(f'Corrected file written to: {out_path}') \ No newline at end of file diff --git a/Data/scripts/plot_boxplots.py b/Data/scripts/plot_boxplots.py new file mode 100644 index 0000000..3d770ed --- /dev/null +++ b/Data/scripts/plot_boxplots.py @@ -0,0 +1,75 @@ +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from pathlib import Path + +plt.rcParams.update({ + 'font.size': 16, + 'font.family': 'serif', + 'axes.labelsize': 18, + 'axes.titlesize': 20, + 'xtick.labelsize': 14, + 'ytick.labelsize': 14, + 'legend.fontsize': 14, + 'figure.dpi': 300, + 'axes.linewidth': 1.5, + 'xtick.direction': 'in', + 'ytick.direction': 'in', + 'xtick.major.size': 6, + 'ytick.major.size': 6, + 'xtick.minor.size': 3, + 'ytick.minor.size': 3, +}) + + +def load_csv_with_standard_decimal(file_path): + with open(file_path, 'r') as f: + scene_line = f.readline().strip() + scene_name = scene_line.split(': ')[1].split('_')[0] + df = pd.read_csv(file_path, skiprows=1) + return df, scene_name + +def calculate_distance(row): + origin = np.array([row['XR_Origin_X'], row['XR_Origin_Y'], row['XR_Origin_Z']]) + tracked = np.array([row['TrackedObject_X'], row['TrackedObject_Y'], row['TrackedObject_Z']]) + return np.linalg.norm(tracked - origin) + +def process_position_data(data_dir): + data_by_scene = {} + all_distances = [] + csv_files = list(Path(data_dir).glob('**/P*_PositionData*.csv')) + for file_path in csv_files: + df, scene_name = load_csv_with_standard_decimal(str(file_path)) + df['Distance'] = df.apply(calculate_distance, axis=1) + all_distances.extend(df['Distance']) + if scene_name not in data_by_scene: + data_by_scene[scene_name] = [] + data_by_scene[scene_name].extend(df['Distance']) + return all_distances, data_by_scene + +def plot_boxplots(all_distances, data_by_scene): + plt.figure(figsize=(10, 7)) + data = [distances for _, distances in sorted(data_by_scene.items())] + labels = [scene for scene in sorted(data_by_scene.keys())] + data = [all_distances] + data + labels = ['All Scenes'] + labels + box = plt.boxplot( + data, labels=labels, showmeans=True, meanline=True, showfliers=False, + boxprops=dict(linewidth=2), whiskerprops=dict(linewidth=2), capprops=dict(linewidth=2), + medianprops=dict(linewidth=2, color='black'), meanprops=dict(linewidth=2, color='C1') + ) + plt.ylabel('Distance to Tracked Object (units)') + plt.xlabel('Scene') + plt.title('Distribution of Distances to Tracked Objects by Scene') + plt.xticks(rotation=20) + plt.grid(axis='y', linestyle='--', linewidth=1, alpha=0.7) + plt.tight_layout() + plt.savefig('boxplot_distances.png', dpi=600) + plt.close() + +def main(): + all_distances, data_by_scene = process_position_data('Recordings') + plot_boxplots(all_distances, data_by_scene) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Data/scripts/plot_distances.py b/Data/scripts/plot_distances.py new file mode 100644 index 0000000..dd86b57 --- /dev/null +++ b/Data/scripts/plot_distances.py @@ -0,0 +1,76 @@ +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from pathlib import Path + +def load_csv_with_standard_decimal(file_path): + with open(file_path, 'r') as f: + scene_line = f.readline().strip() + scene_name = scene_line.split(': ')[1].split('_')[0] + df = pd.read_csv(file_path, skiprows=1) + return df, scene_name + +def process_position_data(data_dir): + # Group by scene + scene_data = {} + csv_files = list(Path(data_dir).glob('**/P*_PositionData*.csv')) + for file_path in csv_files: + df, scene_name = load_csv_with_standard_decimal(str(file_path)) + if scene_name not in scene_data: + scene_data[scene_name] = [] + scene_data[scene_name].append(df) + return scene_data + +def plot_relative_positions(scene_data): + scenes = list(scene_data.keys()) + # Create one figure with 4 subplots + fig, axes = plt.subplots(2, 2, figsize=(16, 14)) + axes = axes.flatten() + for idx, (scene, recordings) in enumerate(scene_data.items()): + all_rel_x = [] + all_rel_z = [] + avg_obj_xs = [] + avg_obj_zs = [] + for df in recordings: + obj_x = df['TrackedObject_X'].values + obj_z = df['TrackedObject_Z'].values + avg_obj_x = np.mean(obj_x) + avg_obj_z = np.mean(obj_z) + avg_obj_xs.append(avg_obj_x) + avg_obj_zs.append(avg_obj_z) + rel_x = df['XR_Origin_X'].values - avg_obj_x + rel_z = df['XR_Origin_Z'].values - avg_obj_z + all_rel_x.extend(rel_x) + all_rel_z.extend(rel_z) + ax = axes[idx] + ax.scatter(all_rel_x, all_rel_z, alpha=0.2, c='blue', label='Player Positions (relative)') + ax.scatter(0, 0, c='red', s=800, marker='*', label='Agent', edgecolor='black', linewidths=2, zorder=10) + ax.set_title(f'Scene: {scene}') + ax.set_xlabel('X Position (relative to Agent)') + ax.set_ylabel('Z Position (relative to Agent)') + ax.legend() + ax.axis('equal') + ax.grid(True, linestyle='--', alpha=0.7) + # Also save individual images + plt.figure(figsize=(8, 8)) + plt.scatter(all_rel_x, all_rel_z, alpha=0.2, c='blue', label='Player Positions (relative)') + plt.scatter(0, 0, c='red', s=800, marker='*', label='Agent', edgecolor='black', linewidths=2, zorder=10) + plt.title(f'Player Positions Relative to Agent\nScene: {scene}') + plt.xlabel('X Position (relative to Agent)') + plt.ylabel('Z Position (relative to Agent)') + plt.legend() + plt.axis('equal') + plt.grid(True, linestyle='--', alpha=0.7) + plt.tight_layout() + plt.savefig(f'room_layout_{scene}.png', dpi=300) + plt.close() + plt.tight_layout() + plt.savefig('room_layout_all_scenes.png', dpi=300) + plt.close() + +def main(): + scene_data = process_position_data('Recordings') + plot_relative_positions(scene_data) + +if __name__ == "__main__": + main() \ No newline at end of file