{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T16:36:18.287412Z",
     "iopub.status.busy": "2025-11-20T16:36:18.287091Z",
     "iopub.status.idle": "2025-11-20T16:36:18.300245Z",
     "shell.execute_reply": "2025-11-20T16:36:18.299820Z",
     "shell.execute_reply.started": "2025-11-20T16:36:18.287395Z"
    }
   },
   "outputs": [],
   "source": [
    "# setup autoload\n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:58:21.040680Z",
     "start_time": "2024-05-16T13:58:19.777010Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T16:36:18.301858Z",
     "iopub.status.busy": "2025-11-20T16:36:18.301739Z",
     "iopub.status.idle": "2025-11-20T16:36:20.401546Z",
     "shell.execute_reply": "2025-11-20T16:36:20.400983Z",
     "shell.execute_reply.started": "2025-11-20T16:36:18.301844Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The autoreload extension is already loaded. To reload it, use:\n",
      "  %reload_ext autoreload\n"
     ]
    }
   ],
   "source": [
    "import ast\n",
    "import os\n",
    "import shutil\n",
    "import sys\n",
    "from collections import defaultdict\n",
    "\n",
    "import json\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from preference_data_preparation_auk import *\n",
    "from preference_helper import *\n",
    "from sklearn.model_selection import train_test_split\n",
    "from suno_utils.utils.s3 import download_s3_files\n",
    "from suno_utils.utils.text import read_json, read_jsonl, write_json, write_jsonl\n",
    "from tqdm import tqdm\n",
    "\n",
    "pd.set_option(\"display.max_rows\", 500)\n",
    "pd.set_option(\"display.max_columns\", 500)\n",
    "pd.set_option(\"display.width\", 1000)\n",
    "\n",
    "# setup autoload\n",
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "\n",
    "def custom_parse(x):\n",
    "    try:\n",
    "        return json.loads(x)\n",
    "    except:\n",
    "        return {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:58:21.082172Z",
     "start_time": "2024-05-16T13:58:21.041926Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T16:36:20.404429Z",
     "iopub.status.busy": "2025-11-20T16:36:20.404287Z",
     "iopub.status.idle": "2025-11-20T16:36:20.463062Z",
     "shell.execute_reply": "2025-11-20T16:36:20.462594Z",
     "shell.execute_reply.started": "2025-11-20T16:36:20.404414Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "N_TOKENS_AUDIO 12000\n"
     ]
    }
   ],
   "source": [
    "OUT_DATA_DIR = \"/app2/suno/data/dpo/bluejay_t1_v101\"\n",
    "os.makedirs(OUT_DATA_DIR, exist_ok=True)\n",
    "shutil.copyfile(\n",
    "    \"/app/suno/data/dpo/7v_v20_full/tokenizer_60k.json\",\n",
    "    os.path.join(OUT_DATA_DIR, \"tokenizer_60k.json\"),\n",
    ")\n",
    "NPZ_DIR = \"/app2/suno/data/dpo/bluejay_t1_npz\"\n",
    "N_TOKENS_AUDIO = 25 * 8 * 60\n",
    "print(\"N_TOKENS_AUDIO\", N_TOKENS_AUDIO)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T16:36:20.464817Z",
     "iopub.status.busy": "2025-11-20T16:36:20.464679Z",
     "iopub.status.idle": "2025-11-20T16:48:12.245508Z",
     "shell.execute_reply": "2025-11-20T16:48:12.244850Z",
     "shell.execute_reply.started": "2025-11-20T16:36:20.464802Z"
    }
   },
   "outputs": [],
   "source": [
    "df = pd.read_pickle(\n",
    "    \"/home/tony/Data/Preference/bluejay_t1/fully_merged_bluejay_t1_20251119.pkl\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T16:48:12.247607Z",
     "iopub.status.busy": "2025-11-20T16:48:12.247474Z",
     "iopub.status.idle": "2025-11-20T16:49:22.034487Z",
     "shell.execute_reply": "2025-11-20T16:49:22.033866Z",
     "shell.execute_reply.started": "2025-11-20T16:48:12.247592Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "after dropna (25940162, 89)\n"
     ]
    }
   ],
   "source": [
    "df = df.dropna(axis=1, how=\"all\")\n",
    "print(\"after dropna\", df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:58:56.199480Z",
     "start_time": "2024-05-16T13:58:53.963687Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T16:49:22.036582Z",
     "iopub.status.busy": "2025-11-20T16:49:22.036453Z",
     "iopub.status.idle": "2025-11-20T16:56:52.045867Z",
     "shell.execute_reply": "2025-11-20T16:56:52.045214Z",
     "shell.execute_reply.started": "2025-11-20T16:49:22.036567Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13793150\n",
      "13793150\n",
      "pre-downloaded df (25940162, 89)\n",
      "downloaded df (25937601, 89)\n"
     ]
    }
   ],
   "source": [
    "converted_paths = os.listdir(NPZ_DIR)\n",
    "print(len(converted_paths))\n",
    "\n",
    "converted_paths = set([f.replace(\".npz\", \"\") for f in converted_paths])\n",
    "print(len(converted_paths))\n",
    "\n",
    "print(\"pre-downloaded df\", df.shape)\n",
    "df[df[\"s3_id\"].isin(converted_paths)].shape\n",
    "df = df[df[\"s3_id\"].isin(converted_paths)].copy()\n",
    "print(\"downloaded df\", df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:58:56.467253Z",
     "start_time": "2024-05-16T13:58:56.207647Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T16:56:52.047123Z",
     "iopub.status.busy": "2025-11-20T16:56:52.046608Z",
     "iopub.status.idle": "2025-11-20T16:56:54.154826Z",
     "shell.execute_reply": "2025-11-20T16:56:54.154153Z",
     "shell.execute_reply.started": "2025-11-20T16:56:52.047106Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "task\n",
       "                      15780266\n",
       "cover                  5975938\n",
       "artist_consistency     1844254\n",
       "artist_cover            965706\n",
       "extend                  435276\n",
       "playlist_condition      381997\n",
       "upload_extend           250684\n",
       "overpainting             95986\n",
       "infill                   94992\n",
       "artist_extend            72048\n",
       "underpainting            40454\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"task\"].value_counts()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LET's do the data prep"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:58:56.592883Z",
     "start_time": "2024-05-16T13:58:56.470781Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T16:56:54.155847Z",
     "iopub.status.busy": "2025-11-20T16:56:54.155564Z",
     "iopub.status.idle": "2025-11-20T16:57:20.461018Z",
     "shell.execute_reply": "2025-11-20T16:57:20.460270Z",
     "shell.execute_reply.started": "2025-11-20T16:56:54.155831Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "preference  model_name      \n",
      "False       chirp-bluejay-t2    12175015\n",
      "            chirp-bluejay-t1      792743\n",
      "True        chirp-bluejay-t2    12177126\n",
      "            chirp-bluejay-t1      792717\n",
      "Name: count, dtype: int64\n",
      "before filter on model name (25937601, 89)\n",
      "after filter on model name (25937601, 89)\n",
      "is_public\n",
      "False    24520071\n",
      "True      1417530\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "## for 13b this is easy for now\n",
    "print(df.groupby([\"preference\"])[\"model_name\"].value_counts())\n",
    "print(\"before filter on model name\", df.shape)\n",
    "df = df[df[\"model_name\"].isin([\"chirp-bluejay-t1\", \"chirp-bluejay-t2\"])]\n",
    "# df = df[df[\"model_name\"].isin([\"chirp-v3p5-engine-t-6\"])]\n",
    "print(\"after filter on model name\", df.shape)\n",
    "print(df[\"is_public\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:58:56.909539Z",
     "start_time": "2024-05-16T13:58:56.595736Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T16:57:20.462077Z",
     "iopub.status.busy": "2025-11-20T16:57:20.461779Z",
     "iopub.status.idle": "2025-11-20T16:58:44.462129Z",
     "shell.execute_reply": "2025-11-20T16:58:44.461350Z",
     "shell.execute_reply.started": "2025-11-20T16:57:20.462060Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before filter on request id pairs (25937601, 89)\n",
      "after filter on request id pairs (7315566, 89)\n",
      "preference  model_name      \n",
      "False       chirp-bluejay-t2    3622985\n",
      "            chirp-bluejay-t1      33834\n",
      "True        chirp-bluejay-t2    3624925\n",
      "            chirp-bluejay-t1      33822\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print(\"before filter on request id pairs\", df.shape)\n",
    "df = df[\n",
    "    df[\"request_id\"].isin(\n",
    "        df[\"request_id\"].value_counts().index[df[\"request_id\"].value_counts() == 2]\n",
    "    )\n",
    "]\n",
    "print(\"after filter on request id pairs\", df.shape)\n",
    "print(df.groupby([\"preference\"])[\"model_name\"].value_counts())\n",
    "assert df.shape[0] == df[\"request_id\"].nunique() * 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T16:58:44.491632Z",
     "iopub.status.busy": "2025-11-20T16:58:44.491412Z",
     "iopub.status.idle": "2025-11-20T17:25:38.742674Z",
     "shell.execute_reply": "2025-11-20T17:25:38.741979Z",
     "shell.execute_reply.started": "2025-11-20T16:58:44.491616Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unique_requests 3657783\n",
      "before removing duplicates (7315566, 203)\n",
      "after removing duplicates (7315566, 196)\n"
     ]
    }
   ],
   "source": [
    "# Let's use the old selection for now -- for quality assurance\n",
    "# expand the metadata columns -- this takes forever...~ 6 mins\n",
    "# test_slice = df[\"metadata\"].apply(lambda x: ast.literal_eval(str(x)))\n",
    "# test_slice = df[\"metadata\"].apply(lambda x: custom_parse(x))\n",
    "test_slice = df[\"metadata\"]  # .apply(lambda x: custom_parse(x))\n",
    "test_slice_series = test_slice.apply(pd.Series)\n",
    "df = pd.concat([df, test_slice_series], axis=1, join=\"inner\")\n",
    "print(\"unique_requests\", df[\"request_id\"].nunique())\n",
    "# remove the duplicates\n",
    "print(\"before removing duplicates\", df.shape)\n",
    "df = df.loc[:, ~df.columns.duplicated()].copy()\n",
    "print(\"after removing duplicates\", df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T17:25:39.129753Z",
     "iopub.status.busy": "2025-11-20T17:25:39.129495Z",
     "iopub.status.idle": "2025-11-20T17:26:15.760705Z",
     "shell.execute_reply": "2025-11-20T17:26:15.760125Z",
     "shell.execute_reply.started": "2025-11-20T17:25:39.129736Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "pos_diff_preference\n",
       " 1.0    2481436\n",
       " 2.0    1175174\n",
       " 0.0       1998\n",
       "-1.0        139\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = df.sort_values(by=[\"request_id\", \"preference\", \"diff_preference\"])\n",
    "df[\"pos_diff_preference\"] = df[\"diff_preference\"].diff()\n",
    "# df[\"cer_diff_preference\"] = df[\"cer\"].diff()\n",
    "df[df[\"preference\"]][\"pos_diff_preference\"].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T17:26:15.762448Z",
     "iopub.status.busy": "2025-11-20T17:26:15.762185Z",
     "iopub.status.idle": "2025-11-20T17:26:25.248085Z",
     "shell.execute_reply": "2025-11-20T17:26:25.247437Z",
     "shell.execute_reply.started": "2025-11-20T17:26:15.762433Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive param_experiment\n",
      "mask_control_slider    170102\n",
      "cfg_steps_240           58774\n",
      "cfg_steps_60            58003\n",
      "n_tag_3                 57804\n",
      "temp_s_80               57796\n",
      "n_tag_1                 57712\n",
      "temp_s_85               57585\n",
      "temp_s_95               57504\n",
      "cfg_steps_10            57067\n",
      "tag_cfg_05              56973\n",
      "tag_cfg_20              56236\n",
      "tag_cfg_1                 400\n",
      "tag_cfg_15                363\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    print(\"positive\", df[df[\"preference\"]][\"param_experiment\"].value_counts())\n",
    "except:\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T17:26:25.250078Z",
     "iopub.status.busy": "2025-11-20T17:26:25.249805Z",
     "iopub.status.idle": "2025-11-20T17:28:32.148021Z",
     "shell.execute_reply": "2025-11-20T17:28:32.147467Z",
     "shell.execute_reply.started": "2025-11-20T17:26:25.250063Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 439718 duplicated prompts 219974 unique requests\n",
      "Found 116092 request_ids with duplicate prompts but not highest play counts in their group\n",
      "['edcdb55c-95b2-4ed4-b556-bb445fd314dc', '0be30ee8-fcb6-4f33-98fd-81bc2d5d040f', '59e89d78-3eff-4511-aa7a-01397ad69cbc', '8ce2acc8-0ecf-4cec-ba34-abb72e31460a', 'da384cd9-d227-483e-9032-e75267d94c4e', 'de2ca319-c624-4f0d-b064-311ff0a923d6', 'e9cc36cc-6ba0-43bd-91d7-0d2c3a9c2f96', 'edd7d5c8-5f35-4ac3-90dc-25002aebf3cb', '22fd8141-a962-4896-a747-286e8fc8123b', '267d0ba1-19ab-41bb-902b-f2810c50e562']\n",
      "Before dedup user gen requests 7315566\n",
      "After dedup user gen requests 7315566\n"
     ]
    }
   ],
   "source": [
    "# Find duplicated prompts with count > 2\n",
    "duplicate_entries = df.groupby(\n",
    "    [\"user_id\", \"prompt_text\", \"tags\", \"task\", \"edited_clip_id\"]\n",
    ").filter(lambda x: len(x) > 2)\n",
    "print(\n",
    "    \"Found\",\n",
    "    len(duplicate_entries),\n",
    "    \"duplicated prompts\",\n",
    "    len(duplicate_entries[\"request_id\"].unique()),\n",
    "    \"unique requests\",\n",
    ")\n",
    "\n",
    "# Group by user_id, prompt_text, and tags to find duplicate prompt groups\n",
    "prompt_groups = duplicate_entries.groupby(\n",
    "    [\"user_id\", \"prompt_text\", \"tags\", \"task\", \"edited_clip_id\"]\n",
    ")\n",
    "\n",
    "# For each prompt group, find the request_id with the highest total reaction_play_count\n",
    "low_play_count_request_ids = []\n",
    "for prompt_key, prompt_group in prompt_groups:\n",
    "    # Get the sum of reaction_play_count for each request_id in this group\n",
    "    request_play_counts = prompt_group.groupby(\"request_id\")[\n",
    "        \"reaction_play_count\"\n",
    "    ].sum()\n",
    "\n",
    "    # Find the max play count in this group\n",
    "    max_play_count = request_play_counts.max()\n",
    "\n",
    "    # Add request_ids that don't have the max play count to our filter list\n",
    "    lower_play_count_request_ids = request_play_counts[\n",
    "        request_play_counts < max_play_count\n",
    "    ].index.tolist()\n",
    "    low_play_count_request_ids.extend(lower_play_count_request_ids)\n",
    "\n",
    "# Display the filtered request IDs\n",
    "print(\n",
    "    f\"Found {len(low_play_count_request_ids)} request_ids with duplicate prompts but not highest play counts in their group\"\n",
    ")\n",
    "print(\n",
    "    low_play_count_request_ids[:10]\n",
    "    if len(low_play_count_request_ids) > 10\n",
    "    else low_play_count_request_ids\n",
    ")\n",
    "print(\"Before dedup user gen requests\", df.shape[0])\n",
    "# df = df[~df[\"request_id\"].isin(low_play_count_request_ids)]\n",
    "print(\"After dedup user gen requests\", df.shape[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:40.799375Z",
     "start_time": "2024-05-16T13:59:36.394236Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T17:28:32.149519Z",
     "iopub.status.busy": "2025-11-20T17:28:32.149363Z",
     "iopub.status.idle": "2025-11-20T17:29:36.872580Z",
     "shell.execute_reply": "2025-11-20T17:29:36.871982Z",
     "shell.execute_reply.started": "2025-11-20T17:28:32.149504Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "93976\n",
      "good_continue_at\n",
      "True     7306390\n",
      "False       9176\n",
      "Name: count, dtype: int64\n",
      "\n",
      " Check some basics... \n",
      " preference\n",
      "True     3658747\n",
      "False    3656819\n",
      "Name: count, dtype: int64 model_name\n",
      "chirp-bluejay-t2    7247910\n",
      "chirp-bluejay-t1      67656\n",
      "Name: count, dtype: int64 preference  model_name      \n",
      "False       chirp-bluejay-t2    3622985\n",
      "            chirp-bluejay-t1      33834\n",
      "True        chirp-bluejay-t2    3624925\n",
      "            chirp-bluejay-t1      33822\n",
      "Name: count, dtype: int64\n",
      "task\n",
      "                      4467830\n",
      "cover                 1740330\n",
      "artist_consistency     480514\n",
      "artist_cover           270842\n",
      "extend                 118782\n",
      "playlist_condition      83522\n",
      "upload_extend           60580\n",
      "infill                  31944\n",
      "overpainting            29646\n",
      "artist_extend           19038\n",
      "underpainting           12538\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "df[\"id\"] = df[\"str_id\"]\n",
    "# get the original duration of the clips, if they are concacted\n",
    "df[\"original_duration_s\"] = df[\"total_start_s\"] + df[\"duration\"]\n",
    "# classify the continue at behavoirs by the duration choice\n",
    "audio_prompt_id_to_continue_at = {}\n",
    "\n",
    "for _, row in df[~df[\"continued_parent\"].isna()].iterrows():\n",
    "    audio_prompt_id = row[\"continued_parent\"]\n",
    "    if audio_prompt_id not in audio_prompt_id_to_continue_at:\n",
    "        audio_prompt_id_to_continue_at[audio_prompt_id] = row[\"continue_at\"]\n",
    "    else:\n",
    "        # pick the max\n",
    "        audio_prompt_id = max(\n",
    "            audio_prompt_id_to_continue_at[audio_prompt_id], row[\"continue_at\"]\n",
    "        )\n",
    "print(len(audio_prompt_id_to_continue_at))\n",
    "df[\"has_continue_and_start_continue_at\"] = df[\"id\"].apply(\n",
    "    lambda x: audio_prompt_id_to_continue_at.get(x)\n",
    ")\n",
    "# we want continue at to be at most of the clip...\n",
    "df[\"good_continue_at\"] = (\n",
    "    (df[\"has_continue_and_start_continue_at\"] / df[\"duration\"]) > 0.9\n",
    ") | df[\"has_continue_and_start_continue_at\"].isna()\n",
    "print(df[\"good_continue_at\"].value_counts())\n",
    "\n",
    "\n",
    "print(\n",
    "    \"\\n Check some basics... \\n\",\n",
    "    df[\"preference\"].value_counts(),\n",
    "    df[\"model_name\"].value_counts(),\n",
    "    df.groupby([\"preference\"])[\"model_name\"].value_counts(),\n",
    ")\n",
    "\n",
    "df = df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "df[\"duration_rel_diff\"] = df[\"duration\"].diff()\n",
    "df[\"play_rel_diff\"] = df[\"reaction_play_count\"].diff()\n",
    "print(df[\"task\"].value_counts())\n",
    "\n",
    "df[\"post_infill_duration\"] = (\n",
    "    df[\"duration\"]\n",
    "    + df[\"infill_context_end_s\"]\n",
    "    - df[\"infill_context_start_s\"]\n",
    "    - df[\"include_future_s\"]\n",
    "    - df[\"include_history_s\"]\n",
    "    - df[\"infill_dur_s\"]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T17:29:36.874401Z",
     "iopub.status.busy": "2025-11-20T17:29:36.874203Z",
     "iopub.status.idle": "2025-11-20T17:30:00.893340Z",
     "shell.execute_reply": "2025-11-20T17:30:00.892757Z",
     "shell.execute_reply.started": "2025-11-20T17:29:36.874383Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(7315566, 203)\n",
      "(7312962, 204)\n"
     ]
    }
   ],
   "source": [
    "# sth maybe happening with clip_id duplication?\n",
    "print(df.shape)\n",
    "df[\"request_sum\"] = df.groupby(\"request_id\")[\"preference\"].transform(\"sum\")\n",
    "# creation of interesting_clips\n",
    "df = df[(df[\"request_sum\"] == 1)]\n",
    "print(df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T17:30:00.894914Z",
     "iopub.status.busy": "2025-11-20T17:30:00.894753Z",
     "iopub.status.idle": "2025-11-20T17:30:20.025439Z",
     "shell.execute_reply": "2025-11-20T17:30:20.024876Z",
     "shell.execute_reply.started": "2025-11-20T17:30:00.894899Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive preference_score\n",
      "1    1935479\n",
      "2    1027185\n",
      "0     473816\n",
      "3     205171\n",
      "4      13966\n",
      "5        864\n",
      "Name: count, dtype: int64\n",
      "negative preference_score\n",
      "0    3572852\n",
      "1      75997\n",
      "2       7083\n",
      "3        524\n",
      "4         24\n",
      "5          1\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "df[\"preference_score\"] = (\n",
    "    df[\"upvoted\"].astype(int)\n",
    "    + df[\"has_action\"].astype(int)\n",
    "    + df[\"part_of_concat\"].astype(int)\n",
    "    + df[\"is_in_playlist\"].astype(int)\n",
    "    + (df[\"n_edits\"] >= 10).astype(int)\n",
    ")\n",
    "print(\"positive\", df[df[\"preference\"]][\"preference_score\"].value_counts())\n",
    "print(\"negative\", df[~df[\"preference\"]][\"preference_score\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.035167Z",
     "start_time": "2024-05-16T13:59:40.801098Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T18:33:42.421917Z",
     "iopub.status.busy": "2025-11-20T18:33:42.421496Z",
     "iopub.status.idle": "2025-11-20T18:34:20.881336Z",
     "shell.execute_reply": "2025-11-20T18:34:20.880553Z",
     "shell.execute_reply.started": "2025-11-20T18:33:42.421896Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "after duration 0.999206887715265\n",
      "after infill duration 0.999878161543845\n",
      "neg_filter_reaction_play_count 1.0\n",
      "neg_filter_upvote_count 0.9889\n",
      "neg_filter_norm_play_frac 1.0\n",
      "neg_filter_continues 0.9999\n",
      "neg_filter_preference_score 0.9771\n",
      "----------------\n",
      "pos_filter_continues 0.9975\n",
      "pos_filter_reaction_play_count 1.0\n",
      "pos_filter_relative_play_count 0.9733\n",
      "pos_filter_cer_diff_preference 1.0\n",
      "pos_filter_bad_flags 0.9998\n",
      "after filter on play counts 0.7367\n",
      "after filter on higher quality 0.3139\n",
      "pos_filter_preference_score 0.3411\n",
      "----------------\n",
      "negative 3567825 positive 396806\n",
      "----------------\n",
      "total pair requests 3656481  --> selected pair requests 384673 frac 0.105  --> total intitial users 441466\n"
     ]
    }
   ],
   "source": [
    "normal_pos_play_count = 5\n",
    "# this is lower, cause a concat is probably already ensuring that it is good\n",
    "concat_pos_play_count = 2\n",
    "# this is a filter on the concated clip\n",
    "concat_total_play_count = 5\n",
    "\n",
    "all_fitlers = (df[\"duration\"] >= 10) & (df[\"duration\"] <= 480)\n",
    "print(\"after duration\", all_fitlers.sum() / df.shape[0])\n",
    "infill_duration_filter = ~df[\"task\"].isin(\n",
    "    [\n",
    "        \"infill\",\n",
    "        \"infill_intro\",\n",
    "        \"infill_outro\",\n",
    "    ]\n",
    ")  | (df[\"post_infill_duration\"] <= 239)\n",
    "print(\"after infill duration\", infill_duration_filter.sum() / df.shape[0])\n",
    "# negative fitlers\n",
    "total_negative = df[~df[\"preference\"]].shape[0]\n",
    "neg_filter_reaction_play_count = (~df[\"preference\"]) & (df[\"reaction_play_count\"] >= 1)\n",
    "print(\n",
    "    \"neg_filter_reaction_play_count\",\n",
    "    round(neg_filter_reaction_play_count.sum() / total_negative, 4),\n",
    ")\n",
    "neg_filter_upvote_count = (~df[\"preference\"]) & (df[\"upvote_count\"] == 0)\n",
    "print(\n",
    "    \"neg_filter_upvote_count\",\n",
    "    round(neg_filter_upvote_count.sum() / total_negative, 4),\n",
    ")\n",
    "neg_filter_norm_play_frac = (~df[\"preference\"]) & (df[\"norm_play_frac\"] <= 3.1)\n",
    "print(\n",
    "    \"neg_filter_norm_play_frac\",\n",
    "    round(neg_filter_norm_play_frac.sum() / total_negative, 4),\n",
    ")\n",
    "neg_filter_continues = (~df[\"preference\"]) & (\n",
    "    df[\"has_continue_and_start_continue_at\"].isna()\n",
    ")\n",
    "print(\n",
    "    \"neg_filter_continues\",\n",
    "    round(neg_filter_continues.sum() / total_negative, 4),\n",
    ")\n",
    "neg_filter_preference_score = (~df[\"preference\"]) & (\n",
    "    df[\"preference_score\"] == 0\n",
    ")\n",
    "print(\n",
    "    \"neg_filter_preference_score\",\n",
    "    round(neg_filter_preference_score.sum() / total_negative, 4),\n",
    ")\n",
    "\n",
    "neg_filter_selection_mask = (\n",
    "    all_fitlers\n",
    "    & infill_duration_filter\n",
    "    & neg_filter_reaction_play_count\n",
    "    & neg_filter_upvote_count\n",
    "    & neg_filter_norm_play_frac\n",
    "    & neg_filter_continues\n",
    "    & neg_filter_preference_score\n",
    ")\n",
    "\n",
    "print(\"----------------\")\n",
    "total_positive = df[df[\"preference\"]].shape[0]\n",
    "assert total_positive == total_negative\n",
    "pos_filter_continues = (df[\"preference\"]) & (df[\"good_continue_at\"])\n",
    "print(\"pos_filter_continues\", round(pos_filter_continues.sum() / total_positive, 4))\n",
    "pos_filter_reaction_play_count = (df[\"preference\"]) & (df[\"reaction_play_count\"] >= 1)\n",
    "print(\n",
    "    \"pos_filter_reaction_play_count\",\n",
    "    round(pos_filter_reaction_play_count.sum() / total_positive, 4),\n",
    ")\n",
    "pos_filter_relative_play_count = (df[\"preference\"]) & (df[\"play_rel_diff\"] >= 0)\n",
    "print(\n",
    "    \"pos_filter_relative_play_count\",\n",
    "    round(pos_filter_relative_play_count.sum() / total_positive, 4),\n",
    ")\n",
    "pos_filter_cer_diff_preference = (\n",
    "    df[\n",
    "        \"preference\"\n",
    "    ]  # & (df[\"pos_diff_preference\"] == 2) # & (df[\"cer_diff_preference\"] < 0.5) & (df[\"cer\"] < 0.99)\n",
    ")\n",
    "print(\n",
    "    \"pos_filter_cer_diff_preference\",\n",
    "    round(pos_filter_cer_diff_preference.sum() / total_positive, 4),\n",
    ")\n",
    "pos_filter_bad_flags = (\n",
    "    (df[\"preference\"]) & (df[\"flag_count\"] == 0) & (df[\"dislike_count\"] == 0)\n",
    ")\n",
    "print(\n",
    "    \"pos_filter_bad_flags\",\n",
    "    round(pos_filter_bad_flags.sum() / total_positive, 4),\n",
    ")\n",
    "pos_filter_play_counts = (df[\"preference\"]) & (\n",
    "    (\n",
    "        (df[\"part_of_concat\"])\n",
    "        & (df[\"reaction_play_count\"] >= concat_pos_play_count)\n",
    "        & (df[\"concat_play_counts\"] >= concat_total_play_count)\n",
    "    )\n",
    "    | (\n",
    "        (~df[\"part_of_concat\"]) & (df[\"reaction_play_count\"] >= normal_pos_play_count)\n",
    "        # & (df[\"norm_play_frac\"] >= 2.1)  # this is a bit of a luxury cut...\n",
    "    )\n",
    "    | (df[\"task\"].isin([\"infill\", \"infill_intro\", \"infill_outro\"]))\n",
    ")\n",
    "print(\n",
    "    \"after filter on play counts\",\n",
    "    round(pos_filter_play_counts.sum() / total_positive, 4),\n",
    ")\n",
    "high_quality_tasks_filter = (\n",
    "    (\n",
    "        df[\"task\"].isin(\n",
    "            [\n",
    "                \"cover\",\n",
    "                \"upload_extend\",\n",
    "                \"cover_extend\",\n",
    "                \"artist_cover\",\n",
    "                \"extend\",\n",
    "                \"artist_consistency\",\n",
    "                \"artist_extend\",\n",
    "                \"\",\n",
    "            ]\n",
    "        )\n",
    "    )\n",
    "    & (\n",
    "        (df[\"upvote_count\"] >= 1)  # (df[\"upvote_count\"] >= 1)\n",
    "        | (df[\"reaction_play_count\"] >= 5)\n",
    "        | (df[\"concat_play_counts\"] >= 5)\n",
    "    )\n",
    "    & (\n",
    "        (df[\"part_of_concat\"])\n",
    "        | (\n",
    "            (~df[\"part_of_concat\"])\n",
    "            & (df[\"norm_play_frac\"] >= 5.1)  # this is a bit of a luxury cut...\n",
    "            & (\n",
    "                df[\"norm_play_frac\"] >= df[\"reaction_play_count\"] / 3\n",
    "            )  # play duration is not low on average\n",
    "        )\n",
    "    )\n",
    ")\n",
    "medium_quality_tasks_filter = (\n",
    "    df[\"task\"].isin(\n",
    "        [\n",
    "            \"infill\",\n",
    "            \"infill_intro\",\n",
    "            \"infill_outro\",\n",
    "            \"overpainting\",\n",
    "            \"underpainting\",\n",
    "            \"playlist_condition\",\n",
    "        ]\n",
    "    )\n",
    ") & (  # let more infill through only in this case...\n",
    "    (\n",
    "        df[\"upvote_count\"] >= 1\n",
    "    )  # (df[\"upvote_count\"] >= 1)  (df[\"pos_diff_preference\"] == 2)\n",
    "    | (df[\"reaction_play_count\"] >= 1)\n",
    "    | (df[\"concat_play_counts\"] >= 1)\n",
    ")\n",
    "pos_filter_higher_quality = (df[\"preference\"]) & (\n",
    "    high_quality_tasks_filter | medium_quality_tasks_filter\n",
    ")\n",
    "print(\n",
    "    \"after filter on higher quality\",\n",
    "    round(pos_filter_higher_quality.sum() / total_positive, 4),\n",
    ")\n",
    "\n",
    "user_gen_filter = (\n",
    "    df[\"user_n_clips\"] >= 20\n",
    ")  # user needs to have genereated at least 100 over the time period\n",
    "\n",
    "pos_filter_preference_score = (df[\"preference\"]) & (\n",
    "    df[\"preference_score\"] >= 2\n",
    ")\n",
    "print(\n",
    "    \"pos_filter_preference_score\",\n",
    "    round(pos_filter_preference_score.sum() / total_positive, 4),\n",
    ")\n",
    "\n",
    "print(\"----------------\")\n",
    "pos_filter_selectin_mask = (\n",
    "    (df[\"preference\"])  # get basics aligned\n",
    "    & all_fitlers\n",
    "    & infill_duration_filter\n",
    "    & pos_filter_continues\n",
    "    & pos_filter_reaction_play_count\n",
    "    & pos_filter_relative_play_count\n",
    "    & pos_filter_cer_diff_preference\n",
    "    & pos_filter_bad_flags\n",
    "    & pos_filter_play_counts\n",
    "    & pos_filter_higher_quality\n",
    "    & user_gen_filter\n",
    "    & pos_filter_preference_score\n",
    ")\n",
    "print(\n",
    "    \"negative\",\n",
    "    sum(neg_filter_selection_mask),\n",
    "    \"positive\",\n",
    "    sum(pos_filter_selectin_mask),\n",
    ")\n",
    "\n",
    "neg_filter_requests = df[neg_filter_selection_mask][\"request_id\"].unique()\n",
    "pos_filter_requests = df[pos_filter_selectin_mask][\"request_id\"].unique()\n",
    "# looking for very strong signal here:\n",
    "# listen to the positive/negative more than once\n",
    "# disliked one of the clips\n",
    "unique_requests = set(pos_filter_requests).intersection(neg_filter_requests)\n",
    "print(\"----------------\")\n",
    "print(\n",
    "    \"total pair requests\",\n",
    "    df[\"request_id\"].nunique(),\n",
    "    \" --> selected pair requests\",\n",
    "    len(unique_requests),\n",
    "    f\"frac {len(unique_requests) / df['request_id'].nunique():.3f}\",\n",
    "    \" --> total intitial users\",\n",
    "    df[\"user_id\"].nunique(),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.250737Z",
     "start_time": "2024-05-16T13:59:41.036434Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T18:34:20.883382Z",
     "iopub.status.busy": "2025-11-20T18:34:20.883088Z",
     "iopub.status.idle": "2025-11-20T18:34:29.223369Z",
     "shell.execute_reply": "2025-11-20T18:34:29.222626Z",
     "shell.execute_reply.started": "2025-11-20T18:34:20.883363Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "task\n",
      "                      462712\n",
      "cover                 161220\n",
      "artist_consistency     61532\n",
      "artist_cover           31804\n",
      "playlist_condition     23878\n",
      "extend                 10906\n",
      "overpainting            5316\n",
      "infill                  4444\n",
      "upload_extend           3816\n",
      "artist_extend           1948\n",
      "underpainting           1770\n",
      "Name: count, dtype: int64\n",
      "bluejay_t1_v101 requests 384673 clips 769346 total khrs 44.782; N gpus for 1000 iters 48.084; 16 gpus for x iters 751.314; n unique users 128412 n pro users 126914\n"
     ]
    }
   ],
   "source": [
    "df_slice = df[df[\"request_id\"].isin(set(unique_requests))].copy()\n",
    "print(df_slice[\"task\"].value_counts())\n",
    "print(\n",
    "    f\"{os.path.basename(OUT_DATA_DIR)} requests\",\n",
    "    df_slice[\"request_id\"].nunique(),\n",
    "    \"clips\",\n",
    "    df_slice.shape[0],\n",
    "    f\"total khrs {sum(df_slice['duration'] / 3600 / 1000):.3f};\",\n",
    "    f\"N gpus for 1000 iters {df_slice.shape[0] / 8 / 2 / 1000:.3f};\",\n",
    "    f\"16 gpus for x iters {df_slice.shape[0] / 8 / 8 / 16:.3f};\",\n",
    "    f\"n unique users {df_slice['user_id'].nunique()}\",\n",
    "    f\"n pro users {df_slice[df_slice['is_pro_user']]['user_id'].nunique()}\",\n",
    ")\n",
    "# auk_mix_t1_v2 requests 102002 clips 204004 total khrs 9.191; N gpus for 1000 iters 12.750; 4 gpus for x iters 3187.562; n unique users 36408 n pro users 34038\n",
    "# auk_t1_v1 requests 9179 clips 18358 total khrs 0.854; N gpus for 1000 iters 1.147; 4 gpus for x iters 286.844; n unique users 6288 n pro users 6275\n",
    "# auk_t1_v2 requests 40903 clips 81806 total khrs 3.864; N gpus for 1000 iters 5.113; 4 gpus for x iters 1278.219; n unique users 21079 n pro users 20966\n",
    "# auk_t1_v3 requests 102015 clips 204030 total khrs 9.703; N gpus for 1000 iters 12.752; 4 gpus for x iters 3187.969; n unique users 42837 n pro users 42462\n",
    "# auk_t1_v4 requests 211452 clips 422904 total khrs 20.216; N gpus for 1000 iters 26.431; 4 gpus for x iters 6607.875; n unique users 71182 n pro users 70059\n",
    "# auk_t1_v9 requests 547743 clips 1095486 total khrs 56.567; N gpus for 1000 iters 68.468; 4 gpus for x iters 17116.969; n unique users 129354 n pro users 125126\n",
    "# auk_t1_v13 requests 627646 clips 1255292 total khrs 64.530; N gpus for 1000 iters 78.456; 4 gpus for x iters 19613.938; n unique users 139873 n pro users 134738\n",
    "# auk_t1_v17 requests 494902 clips 989804 total khrs 51.445; N gpus for 1000 iters 61.863; 4 gpus for x iters 15465.688; n unique users 114240 n pro users 109708\n",
    "# auk_t1_v19 requests 740881 clips 1481762 total khrs 76.133; N gpus for 1000 iters 92.610; 4 gpus for x iters 23152.531; n unique users 154570 n pro users 147261\n",
    "# auk_t1_v24 requests 717745 clips 1435490 total khrs 74.515; N gpus for 1000 iters 89.718; 4 gpus for x iters 22429.531; n unique users 139344 n pro users 130740\n",
    "# auk_t1_v29 requests 1097586 clips 2195172 total khrs 112.614; N gpus for 1000 iters 137.198; 4 gpus for x iters 34299.562; n unique users 193138 n pro users 179429\n",
    "# auk_t1_v30 requests 1224422 clips 2448844 total khrs 125.330; N gpus for 1000 iters 153.053; 4 gpus for x iters 38263.188; n unique users 203138 n pro users 186758\n",
    "# auk_t1_v31 requests 389265 clips 778530 total khrs 40.761; N gpus for 1000 iters 48.658; 4 gpus for x iters 12164.531; n unique users 85198 n pro users 78445\n",
    "# auk_t1_v33 requests 1285261 clips 2570522 total khrs 131.585; N gpus for 1000 iters 160.658; 4 gpus for x iters 40164.406; n unique users 208932 n pro users 191380\n",
    "# auk_t1_v33 requests 1086639 clips 2173278 total khrs 110.641; N gpus for 1000 iters 135.830; 4 gpus for x iters 33957.469; n unique users 197293 n pro users 180968 -- play dur from /3 to /2\n",
    "# auk_t1_v33 requests 806877 clips 1613754 total khrs 81.964; N gpus for 1000 iters 100.860; 4 gpus for x iters 25214.906; n unique users 156679 n pro users 144253 -- filter to web\n",
    "# auk_t1_v37 requests 1339132 clips 2678264 total khrs 137.055; N gpus for 1000 iters 167.392; 4 gpus for x iters 41847.875; n unique users 214313 n pro users 196815\n",
    "# auk_t1_v38 requests 979451 clips 1958902 total khrs 102.038; N gpus for 1000 iters 122.431; 4 gpus for x iters 30607.844; n unique users 170773 n pro users 156737\n",
    "# auk_t1_v43 requests 184775 clips 369550 total khrs 19.089; N gpus for 1000 iters 23.097; 4 gpus for x iters 5774.219; n unique users 60652 n pro users 59126\n",
    "# auk_t1_v45 requests 1176216 clips 2352432 total khrs 122.102; N gpus for 1000 iters 147.027; 4 gpus for x iters 36756.750; n unique users 176751 n pro users 163097\n",
    "# auk_t1_v48 requests 294407 clips 588814 total khrs 29.992; N gpus for 1000 iters 36.801; 4 gpus for x iters 9200.219; n unique users 80991 n pro users 78825\n",
    "# bluejay_t1_v1 requests 47405 clips 94810 total khrs 5.515; N gpus for 1000 iters 5.926; 4 gpus for x iters 1481.406; n unique users 24344 n pro users 24194\n",
    "# bluejay_t1_v2 requests 101265 clips 202530 total khrs 11.753; N gpus for 1000 iters 12.658; 4 gpus for x iters 3164.531; n unique users 44574 n pro users 44024\n",
    "# bluejay_t1_v3 requests 144765 clips 289530 total khrs 16.756; N gpus for 1000 iters 18.096; 4 gpus for x iters 4523.906; n unique users 58421 n pro users 57449\n",
    "# bluejay_t1_v5 requests 179289 clips 358578 total khrs 20.764; N gpus for 1000 iters 22.411; 4 gpus for x iters 5602.781; n unique users 67850 n pro users 66572\n",
    "# bluejay_t1_v7 requests 282305 clips 564610 total khrs 32.692; N gpus for 1000 iters 35.288; 4 gpus for x iters 8822.031; n unique users 93023 n pro users 90936\n",
    "# bluejay_t1_v9 requests 540570 clips 1081140 total khrs 62.455; N gpus for 1000 iters 67.571; 4 gpus for x iters 16892.812; n unique users 145720 n pro users 142027\n",
    "# bluejay_t1_v11 requests 184433 clips 368866 total khrs 20.955; N gpus for 1000 iters 23.054; 4 gpus for x iters 5763.531; n unique users 52149 n pro users 51402\n",
    "# bluejay_t1_v12 requests 293821 clips 587642 total khrs 33.820; N gpus for 1000 iters 36.728; 4 gpus for x iters 9181.906; n unique users 98138 n pro users 95838\n",
    "# bluejay_t1_v13 requests 355678 clips 711356 total khrs 40.908; N gpus for 1000 iters 44.460; 4 gpus for x iters 11114.938; n unique users 111544 n pro users 108497\n",
    "# bluejay_t1_v17 requests 415411 clips 830822 total khrs 48.043; N gpus for 1000 iters 51.926; 4 gpus for x iters 12981.594; n unique users 124572 n pro users 120683\n",
    "# bluejay_t1_v24 requests 486884 clips 973768 total khrs 56.292; N gpus for 1000 iters 60.861; 4 gpus for x iters 15215.125; n unique users 138727 n pro users 133829\n",
    "# bluejay_t1_v26 requests 336220 clips 672440 total khrs 38.800; N gpus for 1000 iters 42.028; 4 gpus for x iters 10506.875; n unique users 80832 n pro users 78854\n",
    "# bluejay_t1_v28 requests 683709 clips 1367418 total khrs 78.507; N gpus for 1000 iters 85.464; 4 gpus for x iters 21365.906; n unique users 172776 n pro users 164584\n",
    "# bluejay_t1_v28 requests 662650 clips 1325300 total khrs 76.539; N gpus for 1000 iters 82.831; 4 gpus for x iters 20707.812; n unique users 170192 n pro users 162222\n",
    "# bluejay_t1_v31 requests 855246 clips 1710492 total khrs 97.846; N gpus for 1000 iters 106.906; 4 gpus for x iters 26726.438; n unique users 198438 n pro users 186068\n",
    "# bluejay_t1_v31 requests 829339 clips 1658678 total khrs 95.430; N gpus for 1000 iters 103.667; 4 gpus for x iters 25916.844; n unique users 195575 n pro users 183523\n",
    "# bluejay_t1_v31 requests 932058 clips 1864116 total khrs 107.136; N gpus for 1000 iters 116.507; 4 gpus for x iters 29126.812; n unique users 203738 n pro users 190639\n",
    "# bluejay_t1_v41 requests 1122075 clips 2244150 total khrs 128.936; N gpus for 1000 iters 140.259; 4 gpus for x iters 35064.844; n unique users 232511 n pro users 214225\n",
    "# bluejay_t1_v42 requests 1234273 clips 2468546 total khrs 140.767; N gpus for 1000 iters 154.284; 4 gpus for x iters 38571.031; n unique users 246967 n pro users 226020\n",
    "# bluejay_t1_v101 requests 384673 clips 769346 total khrs 44.782; N gpus for 1000 iters 48.084; 16 gpus for x iters 751.314; n unique users 128412 n pro users 126914"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T17:31:23.140946Z",
     "iopub.status.busy": "2025-11-20T17:31:23.140352Z",
     "iopub.status.idle": "2025-11-20T17:31:23.521447Z",
     "shell.execute_reply": "2025-11-20T17:31:23.520798Z",
     "shell.execute_reply.started": "2025-11-20T17:31:23.140928Z"
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'BREAK' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[19], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mBREAK\u001b[49m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'BREAK' is not defined"
     ]
    }
   ],
   "source": [
    "# BREAK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:37:39.624595Z",
     "iopub.status.busy": "2025-11-20T18:37:39.624172Z",
     "iopub.status.idle": "2025-11-20T18:50:41.283189Z",
     "shell.execute_reply": "2025-11-20T18:50:41.282479Z",
     "shell.execute_reply.started": "2025-11-20T18:37:39.624575Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total hoot cer scores: 3888085\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 168439/168439 [12:49<00:00, 218.78it/s]\n"
     ]
    }
   ],
   "source": [
    "# Load existing hoot CER cache\n",
    "with open(\"/home/tony/Data/Preference/bluejay_t1/hoot_cer.json\", \"r\") as file:\n",
    "    clip_id_to_cer = json.load(file)\n",
    "print(\"Total hoot cer scores:\", len(clip_id_to_cer))\n",
    "\n",
    "JSON_DIR = \"/app2/suno/data/dpo/bluejay_t1_json/\"\n",
    "\n",
    "# Extract unique s3_ids from df_slice that are not already in the cache\n",
    "clip_ids = set(df_slice[\"s3_id\"]) - set(clip_id_to_cer.keys())\n",
    "\n",
    "for clip_id in tqdm(clip_ids):\n",
    "    hoot_json_path = os.path.join(JSON_DIR, f\"{clip_id}_hoot.json\")\n",
    "    if not os.path.exists(hoot_json_path):\n",
    "        clip_id_to_cer[clip_id] = 1.0\n",
    "        continue\n",
    "    with open(hoot_json_path, \"r\") as f:\n",
    "        data = json.load(f)\n",
    "    for data_dict in data:\n",
    "        if \"hoot_cer\" in data_dict:\n",
    "            clip_id_to_cer[clip_id] = data_dict[\"hoot_cer\"]\n",
    "            break\n",
    "\n",
    "# Update the hoot CER cache\n",
    "with open(\"/home/tony/Data/Preference/bluejay_t1/hoot_cer.json\", \"w\") as file:\n",
    "    json.dump(clip_id_to_cer, file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:50:41.285827Z",
     "iopub.status.busy": "2025-11-20T18:50:41.285536Z",
     "iopub.status.idle": "2025-11-20T18:50:57.841840Z",
     "shell.execute_reply": "2025-11-20T18:50:57.841165Z",
     "shell.execute_reply.started": "2025-11-20T18:50:41.285810Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count    384673.000000\n",
      "mean         -0.003903\n",
      "std           0.119354\n",
      "min          -1.000000\n",
      "10%          -0.088215\n",
      "50%           0.000000\n",
      "90%           0.072653\n",
      "95%           0.144039\n",
      "96%           0.170099\n",
      "97%           0.208130\n",
      "98%           0.274614\n",
      "99%           0.409823\n",
      "max           1.000000\n",
      "Name: cer_diff, dtype: float64\n",
      "bluejay_t1_v101 requests 377984 clips 755968 total khrs 44.133; N gpus for 1000 iters 47.248; 4 gpus for x iters 11812.000; n unique users 127141 n pro users 125669\n"
     ]
    }
   ],
   "source": [
    "# # add the cer to the df\n",
    "df_slice[\"cer\"] = df_slice[\"s3_id\"].map(clip_id_to_cer)\n",
    "df_slice = df_slice.fillna({\"cer\": 1})\n",
    "df_slice[\"cer_diff\"] = df_slice[\"cer\"].diff()\n",
    "df_slice = df_slice.fillna({\"cer_diff\": 0})\n",
    "print(df_slice[df_slice[\"preference\"]][\"cer_diff\"].describe(percentiles=[0.1, 0.5, 0.9, 0.95, 0.96, 0.97, 0.98, 0.99]))\n",
    "\n",
    "# just trimming off tail is fine and safe. Used to be 0.2. Multiple rounds now so probably 0.3 is still fine.\n",
    "cer_mask = (df_slice[\"preference\"]) & (df_slice[\"cer_diff\"] < 0.3)\n",
    "pos_cer_filter_requests = df_slice[cer_mask][\"request_id\"].unique()\n",
    "df_slice = df_slice[df_slice[\"request_id\"].isin(set(pos_cer_filter_requests))].copy()\n",
    "print(\n",
    "    f\"{os.path.basename(OUT_DATA_DIR)} requests\",\n",
    "    df_slice[\"request_id\"].nunique(),\n",
    "    \"clips\",\n",
    "    df_slice.shape[0],\n",
    "    f\"total khrs {sum(df_slice['duration'] / 3600 / 1000):.3f};\",\n",
    "    f\"N gpus for 1000 iters {df_slice.shape[0] / 8 / 2 / 1000:.3f};\",\n",
    "    f\"4 gpus for x iters {df_slice.shape[0] / 8 / 2 / 4:.3f};\",\n",
    "    f\"n unique users {df_slice['user_id'].nunique()}\",\n",
    "    f\"n pro users {df_slice[df_slice['is_pro_user']]['user_id'].nunique()}\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:50:57.843981Z",
     "iopub.status.busy": "2025-11-20T18:50:57.843706Z",
     "iopub.status.idle": "2025-11-20T18:50:58.081908Z",
     "shell.execute_reply": "2025-11-20T18:50:58.081388Z",
     "shell.execute_reply.started": "2025-11-20T18:50:57.843966Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "source\n",
       "web        596324\n",
       "android     90106\n",
       "ios         69538\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_slice[\"source\"].value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.277006Z",
     "start_time": "2024-05-16T13:59:41.252105Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T18:50:58.084391Z",
     "iopub.status.busy": "2025-11-20T18:50:58.084137Z",
     "iopub.status.idle": "2025-11-20T18:50:58.717567Z",
     "shell.execute_reply": "2025-11-20T18:50:58.716930Z",
     "shell.execute_reply.started": "2025-11-20T18:50:58.084376Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive in playlist (186279, 207)\n",
      "task\n",
      "                      453624\n",
      "cover                 159184\n",
      "artist_consistency     60676\n",
      "artist_cover           31382\n",
      "playlist_condition     23526\n",
      "extend                 10676\n",
      "overpainting            5166\n",
      "infill                  4350\n",
      "upload_extend           3708\n",
      "artist_extend           1918\n",
      "underpainting           1758\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "test_mask = (df_slice[\"preference\"]) & (\n",
    "    (df_slice[\"is_in_playlist\"]) | (df_slice[\"concat_in_playlist\"])\n",
    ")\n",
    "print(\"positive in playlist\", df_slice[test_mask].shape)\n",
    "print(df_slice[\"task\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:50:58.719372Z",
     "iopub.status.busy": "2025-11-20T18:50:58.719091Z",
     "iopub.status.idle": "2025-11-20T18:50:58.740307Z",
     "shell.execute_reply": "2025-11-20T18:50:58.739730Z",
     "shell.execute_reply.started": "2025-11-20T18:50:58.719356Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "is_public\n",
      "False    661435\n",
      "True      94533\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "print(df_slice[\"is_public\"].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:50:58.742609Z",
     "iopub.status.busy": "2025-11-20T18:50:58.742301Z",
     "iopub.status.idle": "2025-11-20T18:50:59.063435Z",
     "shell.execute_reply": "2025-11-20T18:50:59.062864Z",
     "shell.execute_reply.started": "2025-11-20T18:50:58.742595Z"
    }
   },
   "outputs": [],
   "source": [
    "df_slice[\"npz_path\"] = df_slice[\"s3_id\"].map(lambda x: f\"{NPZ_DIR}/{x}.npz\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:50:59.064595Z",
     "iopub.status.busy": "2025-11-20T18:50:59.064447Z",
     "iopub.status.idle": "2025-11-20T18:51:02.954115Z",
     "shell.execute_reply": "2025-11-20T18:51:02.953460Z",
     "shell.execute_reply.started": "2025-11-20T18:50:59.064581Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(755968, 208)\n"
     ]
    }
   ],
   "source": [
    "df_total = df_slice.copy()\n",
    "print(df_total.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SOME SNOWFLAKE LYRICS SHIT YOU DON\"T WNAT TO KNOW"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:51:02.955893Z",
     "iopub.status.busy": "2025-11-20T18:51:02.955619Z",
     "iopub.status.idle": "2025-11-20T18:51:08.692527Z",
     "shell.execute_reply": "2025-11-20T18:51:08.691927Z",
     "shell.execute_reply.started": "2025-11-20T18:51:02.955878Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PROD\n"
     ]
    }
   ],
   "source": [
    "home_dir = os.path.expanduser(\"~\")\n",
    "snow_password_path = os.path.join(home_dir, \".aws\", \"snow_pw.txt\")\n",
    "if os.path.exists(snow_password_path):\n",
    "    # !pip install snowflake\n",
    "    from snowflake.core import Root\n",
    "    from snowflake.snowpark import Session\n",
    "\n",
    "    with open(snow_password_path, \"r\") as fp:\n",
    "        fp_lines = fp.readlines()\n",
    "        snow_password = fp_lines[0].strip()\n",
    "        snow_username = fp_lines[1].strip()\n",
    "\n",
    "    CONNECTION_PARAMETERS = {\n",
    "        \"account\": \"fu90569.us-east-2.aws\",\n",
    "        \"user\": snow_username,\n",
    "        \"private_key_file\": \"/home/tony/.aws/rsa_key.p8\",\n",
    "        \"role\": \"ACCOUNTADMIN\",\n",
    "        \"database\": \"SUNO_PROD\",\n",
    "        \"warehouse\": \"SUNO_PROD_LARGE\",\n",
    "        \"schema\": \"PROD\",\n",
    "    }\n",
    "\n",
    "if not os.path.exists(snow_password_path):\n",
    "    raise Exception(\"you are not authorized to access snowflake -- please setup\")\n",
    "\n",
    "snow_session = Session.builder.configs(CONNECTION_PARAMETERS).create()\n",
    "\n",
    "snow_root = Root(snow_session)\n",
    "snow_schema = snow_root.databases[\"SUNO_PROD\"].schemas[\"PROD\"]\n",
    "print(snow_schema.name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:51:08.693572Z",
     "iopub.status.busy": "2025-11-20T18:51:08.693410Z",
     "iopub.status.idle": "2025-11-20T18:54:41.251274Z",
     "shell.execute_reply": "2025-11-20T18:54:41.250655Z",
     "shell.execute_reply.started": "2025-11-20T18:51:08.693556Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  0%|                                                                                                                           | 0/2 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of new clip IDs in this chunk: 100000\n",
      "Length of the ID query string: 3899999\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 50%|█████████████████████████████████████████████████████████▌                                                         | 1/2 [01:12<01:12, 72.63s/it]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of new clip IDs in this chunk: 54288\n",
      "Length of the ID query string: 2117231\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [02:15<00:00, 67.63s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of new result batches: 2\n",
      "Shape of df_snow_prompt:\n",
      "Rows: 3907562\n",
      "Columns: 2\n",
      "False    686467\n",
      "True      69501\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "import pickle\n",
    "from tqdm import tqdm\n",
    "from typing import List\n",
    "\n",
    "PROMPT_PATH = \"/home/tony/Data/Preference/bluejay_t1/clip_prompt.pkl\"\n",
    "\n",
    "# Load existing prompts if available\n",
    "df_existing_prompts = pd.read_pickle(PROMPT_PATH)\n",
    "df_existing_prompts[\"id\"] = df_existing_prompts[\"id\"].astype(str)\n",
    "\n",
    "df_total[\"id\"] = df_total[\"id\"].astype(str)\n",
    "# Only query for new clip ids not already in the prompt cache\n",
    "existing_ids = set(df_existing_prompts[\"id\"])\n",
    "all_clip_ids = set(df_total[\"id\"].unique())\n",
    "new_clip_ids = list(all_clip_ids - existing_ids)\n",
    "\n",
    "snow_batch_size = 100_000\n",
    "snow_results: List[pd.DataFrame] = []\n",
    "\n",
    "if new_clip_ids:\n",
    "    for clip_ids_chunk in tqdm(\n",
    "        [new_clip_ids[i : i + snow_batch_size] for i in range(0, len(new_clip_ids), snow_batch_size)]\n",
    "    ):\n",
    "        id_query_str = \",\".join(\"'\" + x + \"'\" for x in clip_ids_chunk)\n",
    "        print(f\"Number of new clip IDs in this chunk: {len(clip_ids_chunk)}\")\n",
    "        print(f\"Length of the ID query string: {len(id_query_str)}\")\n",
    "\n",
    "        session_query = snow_session.sql(\n",
    "            f\"\"\"select ID, PROMPT_TEXT\n",
    "            from DDB_CLIP_META_HEAVY\n",
    "            where ID in ({id_query_str})\n",
    "            order by p_hour desc;\"\"\"\n",
    "        )\n",
    "        temp_df_snow = pd.DataFrame(session_query.collect())\n",
    "        snow_results.append(temp_df_snow)\n",
    "    print(f\"Number of new result batches: {len(snow_results)}\")\n",
    "    df_snow_new = pd.concat(snow_results, ignore_index=True)\n",
    "    df_snow_new = df_snow_new.rename(columns=lambda x: x.lower())\n",
    "    # Combine with existing prompts and drop duplicates (keep latest)\n",
    "    df_snow_prompt = pd.concat([df_existing_prompts, df_snow_new], ignore_index=True)\n",
    "    df_snow_prompt = df_snow_prompt.drop_duplicates(subset=[\"id\"], keep=\"last\")\n",
    "else:\n",
    "    print(\"No new clip IDs to query.\")\n",
    "    df_snow_prompt = df_existing_prompts\n",
    "\n",
    "# Save the updated prompt DataFrame every time\n",
    "df_snow_prompt.to_pickle(PROMPT_PATH)\n",
    "\n",
    "print(\"Shape of df_snow_prompt:\")\n",
    "print(f\"Rows: {df_snow_prompt.shape[0]}\")\n",
    "print(f\"Columns: {df_snow_prompt.shape[1]}\")\n",
    "\n",
    "df_total = df_total.rename(columns={'prompt_text': 'prompt_text_old'})\n",
    "df_total = df_total.merge(df_snow_prompt, on=\"id\", how=\"left\")\n",
    "print((df_total[\"prompt_text\"] == df_total[\"prompt_text_old\"]).value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fetch inference parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T18:54:41.253175Z",
     "iopub.status.busy": "2025-11-20T18:54:41.253004Z",
     "iopub.status.idle": "2025-11-20T19:06:49.354858Z",
     "shell.execute_reply": "2025-11-20T19:06:49.354109Z",
     "shell.execute_reply.started": "2025-11-20T18:54:41.253159Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-11-20 18:57:30,649 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "missing 152430\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025-11-20 18:57:32,472 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 520.28it/s]\n",
      "2025-11-20 18:57:51,695 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 18:57:51,735 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 18:57:52,102 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:18<00:00, 532.92it/s]\n",
      "2025-11-20 18:58:10,869 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 18:58:10,912 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 18:58:11,740 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:18<00:00, 546.61it/s]\n",
      "2025-11-20 18:58:30,036 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 18:58:30,074 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 18:58:30,426 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 516.21it/s]\n",
      "2025-11-20 18:58:49,801 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 18:58:49,838 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 18:58:50,637 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 518.71it/s]\n",
      "2025-11-20 18:59:09,918 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 18:59:09,957 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 18:59:10,320 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:58<00:00, 172.05it/s]\n",
      "2025-11-20 19:00:08,445 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:00:08,487 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:00:09,269 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 520.71it/s]\n",
      "2025-11-20 19:00:28,476 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:00:28,519 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:00:28,866 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:20<00:00, 494.51it/s]\n",
      "2025-11-20 19:00:49,090 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:00:49,136 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:00:49,496 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:20<00:00, 495.86it/s]\n",
      "2025-11-20 19:01:09,665 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:01:09,710 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:01:10,531 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:20<00:00, 499.01it/s]\n",
      "2025-11-20 19:01:30,573 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:01:30,615 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:01:30,971 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:20<00:00, 495.35it/s]\n",
      "2025-11-20 19:01:51,161 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:01:51,205 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:01:51,566 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 518.57it/s]\n",
      "2025-11-20 19:02:10,851 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:02:10,898 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:02:11,719 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 504.71it/s]\n",
      "2025-11-20 19:02:31,535 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:02:31,574 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:02:31,944 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 516.75it/s]\n",
      "2025-11-20 19:02:51,298 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:02:51,338 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:02:51,697 - INFO - Starting parallel query for 10000 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|███████████████████████████████████████████████████████████████████████████████████████| 10000/10000 [00:19<00:00, 511.14it/s]\n",
      "2025-11-20 19:03:11,263 - INFO - Retrieved 20000 total records from DynamoDB\n",
      "2025-11-20 19:03:11,302 - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n",
      "2025-11-20 19:03:12,101 - INFO - Starting parallel query for 2430 UUIDs with 50 workers\n",
      "Querying DynamoDB: 100%|█████████████████████████████████████████████████████████████████████████████████████████| 2430/2430 [00:06<00:00, 403.08it/s]\n",
      "2025-11-20 19:03:18,131 - INFO - Retrieved 4860 total records from DynamoDB\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(9610912, 72)\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import pandas as pd\n",
    "from fetch_gen_config import query_dynamodb_by_uuids_optimized\n",
    "\n",
    "DYNAMO_PATH = \"/home/tony/Data/Preference/bluejay_t1/clip_dynamo.pkl\"\n",
    "\n",
    "# Load existing DynamoDB records if available\n",
    "if os.path.exists(DYNAMO_PATH):\n",
    "    df_dynamo = pd.read_pickle(DYNAMO_PATH)\n",
    "    existing_ids = set(df_dynamo[\"clipId\"].tolist())\n",
    "else:\n",
    "    df_dynamo = pd.DataFrame()\n",
    "    existing_ids = set()\n",
    "\n",
    "total_s3_ids = set(df_total[\"id\"].tolist())\n",
    "missing_ids = list(total_s3_ids - existing_ids)\n",
    "print(\"missing\", len(missing_ids))\n",
    "chunk_size = 10_000\n",
    "all_records = []\n",
    "\n",
    "for i in range(0, len(missing_ids), chunk_size):\n",
    "    chunk = missing_ids[i:i + chunk_size]\n",
    "    try:\n",
    "        records = query_dynamodb_by_uuids_optimized(chunk, profile_name=\"default\")\n",
    "        all_records.extend(records)\n",
    "    except Exception as e:\n",
    "        # Log and continue with next chunk\n",
    "        print(f\"Error querying DynamoDB for chunk {i // chunk_size}: {e}\")\n",
    "\n",
    "if all_records:\n",
    "    df_new = pd.DataFrame(all_records)\n",
    "    df_dynamo = pd.concat([df_dynamo, df_new], ignore_index=True)\n",
    "\n",
    "print(df_dynamo.shape)\n",
    "df_dynamo[df_dynamo[\"type\"] == \"gpt\"].to_pickle(DYNAMO_PATH)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:49.355834Z",
     "iopub.status.busy": "2025-11-20T19:06:49.355655Z",
     "iopub.status.idle": "2025-11-20T19:06:50.623340Z",
     "shell.execute_reply": "2025-11-20T19:06:50.622601Z",
     "shell.execute_reply.started": "2025-11-20T19:06:49.355817Z"
    }
   },
   "outputs": [],
   "source": [
    "# df_total.to_pickle(\"/home/tony/Data/Preference/bluejay_t1/interesting_clips_bluejay_t1_20250817_subset_total.pkl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:50.624367Z",
     "iopub.status.busy": "2025-11-20T19:06:50.624089Z",
     "iopub.status.idle": "2025-11-20T19:06:50.645471Z",
     "shell.execute_reply": "2025-11-20T19:06:50.644923Z",
     "shell.execute_reply.started": "2025-11-20T19:06:50.624347Z"
    }
   },
   "outputs": [],
   "source": [
    "# OUT_DATA_DIR = \"/app2/suno/data/dpo/bluejay_t1_v63\"\n",
    "# os.makedirs(OUT_DATA_DIR, exist_ok=True)\n",
    "# shutil.copyfile(\n",
    "#     \"/app/suno/data/dpo/7v_v20_full/tokenizer_60k.json\",\n",
    "#     os.path.join(OUT_DATA_DIR, \"tokenizer_60k.json\"),\n",
    "# )\n",
    "# NPZ_DIR = \"/app2/suno/data/dpo/bluejay_t1_npz\"\n",
    "# N_TOKENS_AUDIO = 25 * 8 * 60\n",
    "# print(\"N_TOKENS_AUDIO\", N_TOKENS_AUDIO)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:50.646414Z",
     "iopub.status.busy": "2025-11-20T19:06:50.646112Z",
     "iopub.status.idle": "2025-11-20T19:06:50.664006Z",
     "shell.execute_reply": "2025-11-20T19:06:50.663457Z",
     "shell.execute_reply.started": "2025-11-20T19:06:50.646399Z"
    }
   },
   "outputs": [],
   "source": [
    "# # # v18 # 07-22\n",
    "# # # v19 # 07-26\n",
    "# # # v20 # 07-29\n",
    "# # # v21 # 08-01\n",
    "# # # v22 # 08-04\n",
    "# # # v23 # 08-09\n",
    "# # # v24 07-30\n",
    "# # # v28 # 07-29\n",
    "# # # v29 # 08-07\n",
    "# # # v30 # \n",
    "# # # v32 # 07-22\n",
    "# # # v33 # 07-26\n",
    "# # # v34 # 07-29\n",
    "# # # v35 # 08-04 342386\n",
    "# # # v36 # 08-10 337956\n",
    "# # # v37 # 08-16 321330\n",
    "# # # v39 # 08-16 on 371610\n",
    "# # # # \n",
    "# # # v42 # 07-22 170036\n",
    "# # # v43 # 07-26 181850\n",
    "# # # v44 # 07-29 176956\n",
    "# # # v45 # 08-04 360168\n",
    "# # # v46 # 08-10 360288\n",
    "# # # v47 # 08-16 351520\n",
    "# # # v48 # 08-22 351814\n",
    "# # # v49 # 08-29 366208\n",
    "# # # v50 \n",
    "# # # v59 # 08-29 349396\n",
    "# # # v60 # 09-05 354426\n",
    "# # # v61 # 09-12 335234\n",
    "# # # v62 # rest and everything\n",
    "# df_total[\"created_at\"] = pd.to_datetime(df_total[\"created_at\"], utc=True)\n",
    "# start_cutoff_date = pd.to_datetime(\"2025-09-05\", utc=True)\n",
    "# end_cutoff_date = pd.to_datetime(\"2025-09-12\", utc=True)\n",
    "# date_mask = (df_total[\"created_at\"] < end_cutoff_date) & (df_total[\"created_at\"] >= start_cutoff_date)\n",
    "# print(df_total.shape, df_total[date_mask].shape)\n",
    "# df_slice = df_total[date_mask].copy()\n",
    "# print(\"after date cut\", df_slice.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:50.664905Z",
     "iopub.status.busy": "2025-11-20T19:06:50.664754Z",
     "iopub.status.idle": "2025-11-20T19:06:54.871965Z",
     "shell.execute_reply": "2025-11-20T19:06:54.871211Z",
     "shell.execute_reply.started": "2025-11-20T19:06:50.664892Z"
    }
   },
   "outputs": [],
   "source": [
    "df_slice = df_total.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:54.873040Z",
     "iopub.status.busy": "2025-11-20T19:06:54.872744Z",
     "iopub.status.idle": "2025-11-20T19:06:54.895476Z",
     "shell.execute_reply": "2025-11-20T19:06:54.894915Z",
     "shell.execute_reply.started": "2025-11-20T19:06:54.873023Z"
    }
   },
   "outputs": [],
   "source": [
    "# from tqdm import tqdm\n",
    "\n",
    "# list_of_past_data = [\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v42\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v43\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v44\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v45\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v46\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v47\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v48\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v59\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v60\",\n",
    "#     \"/app2/suno/data/dpo/bluejay_t1_v61\",\n",
    "# ]\n",
    "\n",
    "# # Collect all known train IDs from previous meta_tr.jsonl files, showing progress and set growth\n",
    "# known_train_ids = set()\n",
    "# for data_dir in tqdm(list_of_past_data, desc=\"Collecting known train IDs\"):\n",
    "#     metas = read_jsonl(os.path.join(data_dir, \"meta_tr.jsonl\"))\n",
    "#     before = len(known_train_ids)\n",
    "#     known_train_ids.update(meta[\"id\"] for meta in metas)\n",
    "#     after = len(known_train_ids)\n",
    "#     tqdm.write(f\"Added {after - before} new IDs from {data_dir} (total: {after})\")\n",
    "\n",
    "# print(f\"Total known train IDs: {len(known_train_ids)}\")\n",
    "# print(f\"Original df_slice shape: {df_slice.shape}\")\n",
    "# df_slice = df_slice[~df_slice[\"id\"].isin(known_train_ids)].copy()\n",
    "# print(f\"Filtered df_slice shape: {df_slice.shape}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:54.896267Z",
     "iopub.status.busy": "2025-11-20T19:06:54.896114Z",
     "iopub.status.idle": "2025-11-20T19:06:54.915153Z",
     "shell.execute_reply": "2025-11-20T19:06:54.914628Z",
     "shell.execute_reply.started": "2025-11-20T19:06:54.896253Z"
    }
   },
   "outputs": [],
   "source": [
    "# from collections import Counter, defaultdict\n",
    "# from typing import List, Dict, Set\n",
    "\n",
    "# # Read all meta files\n",
    "# meta_files: List[str] = [\n",
    "#     \"/app/suno/data/dpo/30b_t1_v23/meta_tr.jsonl\",\n",
    "#     \"/app/suno/data/dpo/30b_t6_v35/meta_tr.jsonl\",\n",
    "#     \"/app/suno/data/dpo/13b_s32_v34/meta_tr.jsonl\",\n",
    "#     \"/app/suno/data/dpo/auk_mix_t1_v6/meta_tr.jsonl\",\n",
    "#     \"/app/suno/data/dpo/auk_mix_t1_v14/meta_tr.jsonl\",\n",
    "#     \"/app2/suno/data/dpo/auk_t1_v6/meta_tr.jsonl\",\n",
    "#     \"/app2/suno/data/dpo/auk_t1_v7/meta_tr.jsonl\",\n",
    "#     \"/app2/suno/data/dpo/auk_t1_v19/meta_tr.jsonl\",\n",
    "#     \"/app2/suno/data/dpo/auk_t1_v29/meta_tr.jsonl\",\n",
    "# ]\n",
    "\n",
    "# user_id_counter: Counter[str] = Counter()\n",
    "# for meta_file in tqdm(meta_files):\n",
    "#     metas = read_jsonl(meta_file)\n",
    "#     # Count each user_id once per dataset\n",
    "#     user_ids: Set[str] = {meta[\"user_id\"] for meta in metas if \"user_id\" in meta}\n",
    "#     user_id_counter.update(user_ids)\n",
    "\n",
    "# # Map from count to set of user_ids\n",
    "# count_to_users: Dict[int, Set[str]] = defaultdict(set)\n",
    "# for user_id, count in user_id_counter.items():\n",
    "#     count_to_users[count].add(user_id)\n",
    "\n",
    "# for count in sorted(count_to_users):\n",
    "#     users = count_to_users[count]\n",
    "#     print(f\"Count {count}: {len(users)} users\")\n",
    "\n",
    "# # with open(\"/home/tony/Data/top_user_8.json\", \"w\") as fp:\n",
    "# #     json.dump(list(count_to_users[8]) , fp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:54.916030Z",
     "iopub.status.busy": "2025-11-20T19:06:54.915745Z",
     "iopub.status.idle": "2025-11-20T19:06:54.930960Z",
     "shell.execute_reply": "2025-11-20T19:06:54.930428Z",
     "shell.execute_reply.started": "2025-11-20T19:06:54.916016Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/top_user/mask_control_low.json\", \"r\") as fp:\n",
    "#     very_good_users = json.load(fp)\n",
    "# # very_good_users = count_to_users[5]\n",
    "# very_good_users_mask = df_total[\"user_id\"].isin(very_good_users)\n",
    "# print(df_total[very_good_users_mask].shape, df_total.shape)\n",
    "# print(df_total[very_good_users_mask][\"user_id\"].nunique(), df_total[\"user_id\"].nunique())\n",
    "# # df_total[very_good_users_mask][\"task\"].value_counts()\n",
    "# df_slice = df_total[very_good_users_mask].copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:54.931644Z",
     "iopub.status.busy": "2025-11-20T19:06:54.931507Z",
     "iopub.status.idle": "2025-11-20T19:06:54.946918Z",
     "shell.execute_reply": "2025-11-20T19:06:54.946391Z",
     "shell.execute_reply.started": "2025-11-20T19:06:54.931631Z"
    }
   },
   "outputs": [],
   "source": [
    "# print(\n",
    "#     \"Before filtering by user_id and task\",\n",
    "#     df_slice.shape[0],\n",
    "#     \"user_id unique:\",\n",
    "#     df_slice[\"user_id\"].nunique(),\n",
    "# )\n",
    "\n",
    "# # Create a copy to avoid fragmentation warning\n",
    "# df_slice = df_slice.copy()\n",
    "\n",
    "# # Calculate score for each row: reaction_play_count + 5 if preference is True, else 0\n",
    "# score_values = (\n",
    "#     df_slice[\"reaction_play_count\"] + (5 * df_slice[\"upvote_count\"].astype(int))\n",
    "# ) * df_slice[\"preference\"].astype(int)\n",
    "\n",
    "# # Use pd.concat to add the score column efficiently\n",
    "# df_slice = pd.concat(\n",
    "#     [df_slice, pd.DataFrame({\"score\": score_values}, index=df_slice.index)], axis=1\n",
    "# )\n",
    "\n",
    "# # Group by user_id and task, then for each group find the request_id with highest score\n",
    "# best_request_ids = []\n",
    "# for (user_id, task), group in tqdm(\n",
    "#     df_slice.groupby([\"user_id\", \"task\"]), desc=\"Processing user_id and task groups\"\n",
    "# ):\n",
    "#     # Get the request_id with the highest score in this group\n",
    "#     best_request_id = group.loc[group[\"score\"].idxmax(), \"request_id\"]\n",
    "#     best_request_ids.append(best_request_id)\n",
    "\n",
    "# # Filter df_slice to keep only the best request_ids for each user_id, task combination\n",
    "# df_slice = df_slice[df_slice[\"request_id\"].isin(best_request_ids)].copy()\n",
    "\n",
    "# print(\n",
    "#     \"After filtering by user_id and task\",\n",
    "#     df_slice.shape[0],\n",
    "#     \"user_id unique:\",\n",
    "#     df_slice[\"user_id\"].nunique(),\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:09:42.136270Z",
     "iopub.status.busy": "2025-11-20T19:09:42.135826Z",
     "iopub.status.idle": "2025-11-20T19:10:11.817269Z",
     "shell.execute_reply": "2025-11-20T19:10:11.816604Z",
     "shell.execute_reply.started": "2025-11-20T19:09:42.136249Z"
    }
   },
   "outputs": [],
   "source": [
    "# df_total.to_pickle(\"/home/tony/Data/Preference/bluejay_t1/fully_merged_bluejay_t1_20251119_super_v101.pkl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T14:00:20.866354Z",
     "start_time": "2024-05-16T14:00:12.443344Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:06:54.947779Z",
     "iopub.status.busy": "2025-11-20T19:06:54.947506Z",
     "iopub.status.idle": "2025-11-20T19:06:55.085252Z",
     "shell.execute_reply": "2025-11-20T19:06:55.084536Z",
     "shell.execute_reply.started": "2025-11-20T19:06:54.947765Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(755968, 209)\n",
      "task\n",
      "                      453624\n",
      "cover                 159184\n",
      "artist_consistency     60676\n",
      "artist_cover           31382\n",
      "playlist_condition     23526\n",
      "extend                 10676\n",
      "overpainting            5166\n",
      "infill                  4350\n",
      "upload_extend           3708\n",
      "artist_extend           1918\n",
      "underpainting           1758\n",
      "Name: count, dtype: int64\n"
     ]
    },
    {
     "ename": "NameError",
     "evalue": "name 'BREAK' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[48], line 6\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;28mprint\u001b[39m(df_slice\u001b[38;5;241m.\u001b[39mshape)\n\u001b[1;32m      5\u001b[0m \u001b[38;5;28mprint\u001b[39m(df_slice[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtask\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39mvalue_counts())\n\u001b[0;32m----> 6\u001b[0m \u001b[43mBREAK\u001b[49m\n\u001b[1;32m      7\u001b[0m \u001b[38;5;66;03m# (269282, 199)\u001b[39;00m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'BREAK' is not defined"
     ]
    }
   ],
   "source": [
    "# df_slice.to_pickle(\n",
    "#     \"/home/tony/Data/Preference/30b_v6/interesting_clips_v4_h_t_6_20250426_full_long_slice.pkl\"\n",
    "# )\n",
    "print(df_slice.shape)\n",
    "print(df_slice[\"task\"].value_counts())\n",
    "BREAK\n",
    "# (269282, 199)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Need to kick out the ones has gpt prompt -- these are pairs with different text inputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:13:31.803780Z",
     "iopub.status.busy": "2025-11-20T19:13:31.803419Z",
     "iopub.status.idle": "2025-11-20T19:13:35.096949Z",
     "shell.execute_reply": "2025-11-20T19:13:35.095950Z",
     "shell.execute_reply.started": "2025-11-20T19:13:31.803763Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(755968, 209)\n",
      "(755968, 209)\n",
      "(755968, 209)\n"
     ]
    }
   ],
   "source": [
    "print(df_slice.shape)\n",
    "df_slice = df_slice[df_slice[\"request_id\"].apply(lambda x: len(x) > 3)]\n",
    "print(df_slice.shape)\n",
    "# df_slice = df_slice[df_slice[\"is_pro_user\"]].copy()\n",
    "print(df_slice.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.932296Z",
     "start_time": "2024-05-16T13:59:41.932287Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:13:35.098003Z",
     "iopub.status.busy": "2025-11-20T19:13:35.097830Z",
     "iopub.status.idle": "2025-11-20T19:13:35.165539Z",
     "shell.execute_reply": "2025-11-20T19:13:35.165009Z",
     "shell.execute_reply.started": "2025-11-20T19:13:35.097987Z"
    }
   },
   "outputs": [],
   "source": [
    "# don't have continue at\n",
    "df_slice[\"request_id\"] = df_slice[\"request_id\"].astype(str)\n",
    "# df_slice[\"npz_path\"] = df_slice[\"npz_path\"].apply(lambda x: str(x).replace(\"_npz\", \"_npz/\"))\n",
    "# df_slice[df_slice[\"continue_at\"].isna()][\"request_id\"].nunique(), df_slice[\"request_id\"].nunique()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.932966Z",
     "start_time": "2024-05-16T13:59:41.932957Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:13:35.166377Z",
     "iopub.status.busy": "2025-11-20T19:13:35.166230Z",
     "iopub.status.idle": "2025-11-20T19:13:35.405058Z",
     "shell.execute_reply": "2025-11-20T19:13:35.404478Z",
     "shell.execute_reply.started": "2025-11-20T19:13:35.166362Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "377984\n"
     ]
    }
   ],
   "source": [
    "final_filtered_requests = df_slice[\"request_id\"].astype(str).unique()\n",
    "# final_filtered_requests = df_slice[df_slice[\"is_pro_user\"]][\"request_id\"].astype(str).unique()\n",
    "print(len(final_filtered_requests))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.934277Z",
     "start_time": "2024-05-16T13:59:41.934268Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:13:35.406296Z",
     "iopub.status.busy": "2025-11-20T19:13:35.406132Z",
     "iopub.status.idle": "2025-11-20T19:13:45.698110Z",
     "shell.execute_reply": "2025-11-20T19:13:45.697534Z",
     "shell.execute_reply.started": "2025-11-20T19:13:35.406281Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "374204 3780\n",
      "(748408, 209) (7560, 209)\n"
     ]
    }
   ],
   "source": [
    "train_requests, val_requests = train_test_split(\n",
    "    sorted(list(final_filtered_requests)), test_size=0.01, random_state=42\n",
    ")\n",
    "print(len(train_requests), len(val_requests))\n",
    "\n",
    "train_df = df_slice[df_slice[\"request_id\"].astype(str).isin(set(train_requests))].copy()\n",
    "val_df = df_slice[df_slice[\"request_id\"].astype(str).isin(set(val_requests))].copy()\n",
    "train_df = train_df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "train_df = train_df  # .reset_index()\n",
    "val_df = val_df.sort_values(by=[\"request_id\", \"preference\"])\n",
    "val_df = val_df  # .reset_index()\n",
    "train_df = train_df.reset_index(drop=True)\n",
    "val_df = val_df.reset_index(drop=True)\n",
    "print(train_df.shape, val_df.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Actually make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.935620Z",
     "start_time": "2024-05-16T13:59:41.935613Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:13:45.698832Z",
     "iopub.status.busy": "2025-11-20T19:13:45.698681Z",
     "iopub.status.idle": "2025-11-20T19:14:13.741131Z",
     "shell.execute_reply": "2025-11-20T19:14:13.740613Z",
     "shell.execute_reply.started": "2025-11-20T19:13:45.698817Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 748408/748408 [00:28<00:00, 26710.93it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "43,691 hours of 748408 clips, 46.7755 nodes, 974.4895833333334 iters\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "total_duration = 0\n",
    "for i, row in tqdm(train_df.iterrows(), total=len(train_df)):\n",
    "    # we need to alternate between preference: neg, pos\n",
    "    # print(i, row)\n",
    "    try:\n",
    "        assert row[\"preference\"] == (i % 2 == 1)\n",
    "        total_duration += row[\"duration\"]\n",
    "    except Exception as E:\n",
    "        print(i, row)\n",
    "        print(E)\n",
    "        raise ValueError()\n",
    "\n",
    "print(\n",
    "    f\"{round(total_duration / 60 / 60):,} hours of {train_df.shape[0]} clips, {train_df.shape[0] / 8 / 2 / 1000} nodes, {train_df.shape[0] / 8 / 6 / 16} iters\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.936268Z",
     "start_time": "2024-05-16T13:59:41.936260Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:14:13.741867Z",
     "iopub.status.busy": "2025-11-20T19:14:13.741708Z",
     "iopub.status.idle": "2025-11-20T19:16:03.295560Z",
     "shell.execute_reply": "2025-11-20T19:16:03.294945Z",
     "shell.execute_reply.started": "2025-11-20T19:14:13.741852Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t_data_memmap is set to: 12000\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████| 7560/7560 [01:49<00:00, 69.04it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 7560 clips, 3 different prompts, 0 different tags, 0 different negative tags\n",
      "293 hours of False\n",
      "292 hours of True\n",
      "gen: 271.0 hours\n",
      "cover: 159.2 hours\n",
      "artist_consistency: 72.4 hours\n",
      "extend: 8.4 hours\n",
      "overpainting: 6.7 hours\n",
      "artist_cover: 38.5 hours\n",
      "infill: 1.2 hours\n",
      "playlist_condition: 23.7 hours\n",
      "underpainting: 1.8 hours\n",
      "artist_extend: 2.8 hours\n",
      "\n",
      "--- Gender Distribution ---\n",
      "  female: 784 (10.4%)\n",
      "  male: 978 (12.9%)\n",
      "  unspecified: 5,798 (76.7%)\n",
      "\n",
      "--- Negative Tags Usage ---\n",
      "  has_neg_tags: 516 (6.8%)\n",
      "  no_neg_tags: 7,044 (93.2%)\n",
      "\n",
      "--- Control Slider Usage ---\n",
      "  has_control_slider: 2,884 (38.1% of clips)\n",
      "  no_control_slider: 4,676 (61.9% of clips)\n",
      "Done\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "make_dataset(\n",
    "    val_df, OUT_DATA_DIR, is_val=True, npz_dir=NPZ_DIR, t_data_memmap=N_TOKENS_AUDIO\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T19:16:03.296534Z",
     "iopub.status.busy": "2025-11-20T19:16:03.296273Z",
     "iopub.status.idle": "2025-11-20T19:16:04.497610Z",
     "shell.execute_reply": "2025-11-20T19:16:04.496902Z",
     "shell.execute_reply.started": "2025-11-20T19:16:03.296517Z"
    }
   },
   "outputs": [],
   "source": [
    "# test_npz = np.load(\"/app/suno/data/dpo/30b_npz/26d19085-18da-4701-af43-122684543891.npz\")\n",
    "# for k in test_npz.keys():\n",
    "#     print(k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.936964Z",
     "start_time": "2024-05-16T13:59:41.936957Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T19:16:04.498387Z",
     "iopub.status.busy": "2025-11-20T19:16:04.498230Z",
     "iopub.status.idle": "2025-11-20T22:01:55.677610Z",
     "shell.execute_reply": "2025-11-20T22:01:55.676692Z",
     "shell.execute_reply.started": "2025-11-20T19:16:04.498372Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "t_data_memmap is set to: 12000\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  3%|███▌                                                                                                    | 25509/748408 [05:22<2:18:54, 86.73it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overflow at 25498: 12749 > 12000\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      " 76%|██████████████████████████████████████████████████████████████████████████████▌                        | 570993/748408 [2:04:16<41:55, 70.54it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overflow at 570986: 12749 > 12000\n",
      "Overflow at 570987: 12749 > 12000\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████| 748408/748408 [2:45:49<00:00, 75.22it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total 748408 clips, 134 different prompts, 2 different tags, 0 different negative tags\n",
      "29,039 hours of False\n",
      "28,966 hours of True\n",
      "cover: 16469.9 hours\n",
      "artist_consistency: 6622.0 hours\n",
      "gen: 26718.5 hours\n",
      "artist_cover: 3724.1 hours\n",
      "extend: 977.4 hours\n",
      "playlist_condition: 2496.6 hours\n",
      "overpainting: 534.9 hours\n",
      "artist_extend: 214.4 hours\n",
      "underpainting: 158.3 hours\n",
      "infill: 89.0 hours\n",
      "\n",
      "--- Gender Distribution ---\n",
      "  female: 77,474 (10.4%)\n",
      "  male: 101,862 (13.6%)\n",
      "  unspecified: 569,072 (76.0%)\n",
      "\n",
      "--- Negative Tags Usage ---\n",
      "  has_neg_tags: 51,064 (6.8%)\n",
      "  no_neg_tags: 697,344 (93.2%)\n",
      "\n",
      "--- Control Slider Usage ---\n",
      "  has_control_slider: 275,292 (36.8% of clips)\n",
      "  no_control_slider: 473,116 (63.2% of clips)\n",
      "Done\n"
     ]
    }
   ],
   "source": [
    "make_dataset(\n",
    "    train_df, OUT_DATA_DIR, is_val=False, npz_dir=NPZ_DIR, t_data_memmap=N_TOKENS_AUDIO\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-29T19:46:47.549860Z",
     "start_time": "2024-01-29T19:46:47.548015Z"
    }
   },
   "source": [
    "# Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.937879Z",
     "start_time": "2024-05-16T13:59:41.937870Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:55.678704Z",
     "iopub.status.busy": "2025-11-20T22:01:55.678548Z",
     "iopub.status.idle": "2025-11-20T22:01:57.049644Z",
     "shell.execute_reply": "2025-11-20T22:01:57.048964Z",
     "shell.execute_reply.started": "2025-11-20T22:01:55.678688Z"
    }
   },
   "outputs": [],
   "source": [
    "# verify\n",
    "mm = np.memmap(os.path.join(OUT_DATA_DIR, f\"data_val.bin\"), dtype=np.uint16, mode=\"r\")\n",
    "test_metas = read_jsonl(os.path.join(OUT_DATA_DIR, f\"meta_val.jsonl\"))\n",
    "test_info = read_json(os.path.join(OUT_DATA_DIR, f\"info_val.json\"))\n",
    "mm = mm.reshape(-1, N_TOKENS_AUDIO, 1)\n",
    "assert len(mm) == len(test_metas)\n",
    "assert mm[:100, :, 0].min() >= 0\n",
    "assert mm[:100, :, 0].max() <= 4000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.051816Z",
     "iopub.status.busy": "2025-11-20T22:01:57.051622Z",
     "iopub.status.idle": "2025-11-20T22:01:57.080852Z",
     "shell.execute_reply": "2025-11-20T22:01:57.080281Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.051799Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counter({None: 4538, 'cover': 1524, 'artist_consistency': 652, 'artist_cover': 322, 'playlist_condition': 232, 'extend': 134, 'overpainting': 68, 'infill': 50, 'artist_extend': 22, 'underpainting': 18})\n"
     ]
    }
   ],
   "source": [
    "task_counts = Counter()\n",
    "for test_meta in test_metas:\n",
    "    task_counts[test_meta.get(\"task\")] += 1\n",
    "print(task_counts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.938629Z",
     "start_time": "2024-05-16T13:59:41.938621Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.081637Z",
     "iopub.status.busy": "2025-11-20T22:01:57.081478Z",
     "iopub.status.idle": "2025-11-20T22:01:57.103638Z",
     "shell.execute_reply": "2025-11-20T22:01:57.103094Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.081621Z"
    }
   },
   "outputs": [],
   "source": [
    "# # randomly listen to some stuff\n",
    "# from suno_utils.tasks.dac_2c_12cb import preload_models as preload_codec_models\n",
    "# from suno_utils.tasks.dac_2c_12cb import (\n",
    "#     encode as codec_encode,\n",
    "#     decode_stream_to_full_audio as codec_decode,\n",
    "#     EMBEDDING_RATE as CODEC_EMBEDDING_RATE,\n",
    "#     decode as decode\n",
    "# )\n",
    "# os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"0\"\n",
    "# _ = preload_codec_models(\"/app/suno/data/dpo/models/dac_2c_25x12.pt\", device=\"cuda\")\n",
    "# assert len(test_metas) == len(mm)\n",
    "# idx_list = list(range(len(test_metas)))\n",
    "# # random.shuffle(idx_list)\n",
    "# # idx_list = [idx for idx in idx_list if \"text\" in test_metas[idx]]\n",
    "# print(len(mm))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.939205Z",
     "start_time": "2024-05-16T13:59:41.939198Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.104419Z",
     "iopub.status.busy": "2025-11-20T22:01:57.104257Z",
     "iopub.status.idle": "2025-11-20T22:01:57.125578Z",
     "shell.execute_reply": "2025-11-20T22:01:57.125085Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.104403Z"
    }
   },
   "outputs": [],
   "source": [
    "# import random\n",
    "# idx = random.choice(test_info[\"perference_0\"][\"idx_list\"])\n",
    "# assert \"original_duration_s\" in test_metas[idx]\n",
    "# # positive index should be shifted by 1\n",
    "# pos_idx = idx + 1\n",
    "# print(\n",
    "#     \"tags:\",\n",
    "#     test_metas[idx].get(\"tags\") == test_metas[pos_idx].get(\"tags\"),\n",
    "#     test_metas[idx].get(\"tags\"),\n",
    "# )\n",
    "# arr = mm[idx, 1:].copy().astype(np.int16)[:, 1:]\n",
    "# pos_arr = mm[pos_idx, 1:].copy().astype(np.int16)[:, 1:]\n",
    "# pad_idx_arr = np.where(arr == COARSE_PAD_TOKEN)[0]\n",
    "# if len(pad_idx_arr) > 0:\n",
    "#     arr = arr[: pad_idx_arr[0], :]\n",
    "# pos_pad_idx_arr = np.where(pos_arr == COARSE_PAD_TOKEN)[0]\n",
    "# if len(pos_pad_idx_arr) > 0:\n",
    "#     pos_arr = pos_arr[: pos_pad_idx_arr[0], :]\n",
    "# a = decode(arr)\n",
    "# print(\"\\n negative example \\n\", test_metas[idx])\n",
    "# a.play(compress=False)\n",
    "# pos_a = decode(pos_arr)\n",
    "# print(\"\\n positive example \\n\", test_metas[pos_idx])\n",
    "# pos_a.play(compress=False)\n",
    "# print(\n",
    "#     \"text:\",\n",
    "#     test_metas[idx].get(\"text\") == test_metas[pos_idx].get(\"text\"),\n",
    "#     test_metas[idx].get(\"text\"),\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.939977Z",
     "start_time": "2024-05-16T13:59:41.939969Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.126278Z",
     "iopub.status.busy": "2025-11-20T22:01:57.126128Z",
     "iopub.status.idle": "2025-11-20T22:01:57.145378Z",
     "shell.execute_reply": "2025-11-20T22:01:57.144925Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.126263Z"
    }
   },
   "outputs": [],
   "source": [
    "# val_df[val_df[\"tags\"] == 'a vibrant blend of experimental jazz fusion, drum-and-bass and swagger fuzzed-out guitars']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.940610Z",
     "start_time": "2024-05-16T13:59:41.940603Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.146022Z",
     "iopub.status.busy": "2025-11-20T22:01:57.145888Z",
     "iopub.status.idle": "2025-11-20T22:01:57.161612Z",
     "shell.execute_reply": "2025-11-20T22:01:57.161181Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.146008Z"
    }
   },
   "outputs": [],
   "source": [
    "# from collections import Counter\n",
    "# c = Counter()\n",
    "# for _, row in df_slice.iterrows():\n",
    "#     # print(row[\"metadata\"])\n",
    "#     for k in ast.literal_eval(row[\"metadata\"]).keys():\n",
    "#         c[k] += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.941167Z",
     "start_time": "2024-05-16T13:59:41.941159Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.162263Z",
     "iopub.status.busy": "2025-11-20T22:01:57.162121Z",
     "iopub.status.idle": "2025-11-20T22:01:57.177280Z",
     "shell.execute_reply": "2025-11-20T22:01:57.176843Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.162250Z"
    }
   },
   "outputs": [],
   "source": [
    "# original_npz_path = f\"/app/suno/data/dpo/7b_npz/{test_metas[idx]['id']}.npz\"\n",
    "# original_npz_path = \"/app/suno/data/dpo/7b_npz/729c3011-f672-4ccd-8d82-1cbf2b52ff69.npz\"\n",
    "# original_arr = np.load(original_npz_path)[\"v2_raw\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.941801Z",
     "start_time": "2024-05-16T13:59:41.941793Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.177879Z",
     "iopub.status.busy": "2025-11-20T22:01:57.177743Z",
     "iopub.status.idle": "2025-11-20T22:01:57.204911Z",
     "shell.execute_reply": "2025-11-20T22:01:57.204443Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.177866Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3780 0\n"
     ]
    }
   ],
   "source": [
    "def validation_on_metas(input_metas):\n",
    "    total_bad = 0\n",
    "    total_good = 0\n",
    "    for idx in range(len(input_metas)):\n",
    "        if idx % 2 == 0:\n",
    "            pos_idx = idx + 1\n",
    "            if input_metas[idx].get(\"tags\") != input_metas[pos_idx].get(\"tags\"):\n",
    "                print(\n",
    "                    input_metas[idx].get(\"id\"),\n",
    "                    input_metas[idx].get(\"tags\"),\n",
    "                    input_metas[pos_idx].get(\"id\"),\n",
    "                    input_metas[pos_idx].get(\"tags\"),\n",
    "                )\n",
    "                # print(test_metas[idx].get(\"text\") == test_metas[pos_idx].get(\"text\"), test_metas[idx].get(\"tags\"), test_metas[pos_idx].get(\"tags\"))\n",
    "                total_bad += 1\n",
    "            elif input_metas[idx].get(\"text\") != input_metas[pos_idx].get(\"text\"):\n",
    "                # print(test_metas[idx].get(\"text\") == test_metas[pos_idx].get(\"text\"), test_metas[idx].get(\"tags\"), test_metas[pos_idx].get(\"tags\"))\n",
    "                total_bad += 1\n",
    "            else:\n",
    "                total_good += 1\n",
    "    print(total_good, total_bad)\n",
    "    return\n",
    "\n",
    "\n",
    "validation_on_metas(test_metas)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.942520Z",
     "start_time": "2024-05-16T13:59:41.942511Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.205555Z",
     "iopub.status.busy": "2025-11-20T22:01:57.205416Z",
     "iopub.status.idle": "2025-11-20T22:01:57.288201Z",
     "shell.execute_reply": "2025-11-20T22:01:57.287642Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.205542Z"
    }
   },
   "outputs": [],
   "source": [
    "train_info = read_json(os.path.join(OUT_DATA_DIR, f\"info_tr.json\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.943072Z",
     "start_time": "2024-05-16T13:59:41.943065Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.288943Z",
     "iopub.status.busy": "2025-11-20T22:01:57.288793Z",
     "iopub.status.idle": "2025-11-20T22:01:57.355940Z",
     "shell.execute_reply": "2025-11-20T22:01:57.355247Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.288929Z"
    }
   },
   "outputs": [],
   "source": [
    "n_neg_tr = train_info[\"perference_0\"][\"idx_list\"]\n",
    "n_pos_tr = train_info[\"perference_1\"][\"idx_list\"]\n",
    "assert len(n_pos_tr) == len(n_neg_tr)\n",
    "# make sure they are offset by 1 and exactly 1\n",
    "for i, j in zip(n_neg_tr, n_pos_tr):\n",
    "    assert i == j - 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.944246Z",
     "start_time": "2024-05-16T13:59:41.944237Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.356702Z",
     "iopub.status.busy": "2025-11-20T22:01:57.356549Z",
     "iopub.status.idle": "2025-11-20T22:01:57.377123Z",
     "shell.execute_reply": "2025-11-20T22:01:57.376619Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.356686Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total samples 748408 (748408, 209)\n"
     ]
    }
   ],
   "source": [
    "total_iters = len(n_neg_tr) + len(n_pos_tr)\n",
    "print(\"total samples\", total_iters, train_df.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:01:57.377804Z",
     "iopub.status.busy": "2025-11-20T22:01:57.377658Z",
     "iopub.status.idle": "2025-11-20T22:02:13.522045Z",
     "shell.execute_reply": "2025-11-20T22:02:13.521328Z",
     "shell.execute_reply.started": "2025-11-20T22:01:57.377790Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "374204 0\n"
     ]
    }
   ],
   "source": [
    "metas_tr = read_jsonl(os.path.join(OUT_DATA_DIR, \"meta_tr.jsonl\"))\n",
    "validation_on_metas(metas_tr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.522925Z",
     "iopub.status.busy": "2025-11-20T22:02:13.522755Z",
     "iopub.status.idle": "2025-11-20T22:02:13.544512Z",
     "shell.execute_reply": "2025-11-20T22:02:13.543961Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.522910Z"
    }
   },
   "outputs": [],
   "source": [
    "# new_metas_tr = []\n",
    "# for index, l in enumerate(metas_tr):\n",
    "#     if index % 2 == 1:\n",
    "#         last_l = new_metas_tr[-1]\n",
    "#         if l[\"tags\"] != last_l[\"tags\"]:\n",
    "#             print(l[\"tags\"], last_l[\"tags\"])\n",
    "#             l[\"tags\"] = last_l[\"tags\"]\n",
    "#     new_metas_tr.append(l)\n",
    "# validation_on_metas(new_metas_tr)\n",
    "# write_jsonl(new_metas_tr, os.path.join(OUT_DATA_DIR, \"meta_tr.jsonl\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.945249Z",
     "start_time": "2024-05-16T13:59:41.945241Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.545277Z",
     "iopub.status.busy": "2025-11-20T22:02:13.545124Z",
     "iopub.status.idle": "2025-11-20T22:02:13.564324Z",
     "shell.execute_reply": "2025-11-20T22:02:13.563768Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.545263Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 epoch per batch 4, total 2923.46875\n",
      "1 epoch per batch 6, total 974.4895833333334\n",
      "1 epoch per batch 8, total 730.8671875\n"
     ]
    }
   ],
   "source": [
    "print(\"1 epoch per batch 4, total\", total_iters / 8 / 8 / 4)\n",
    "print(\"1 epoch per batch 6, total\", total_iters / 16 / 8 / 6)\n",
    "print(\"1 epoch per batch 8, total\", total_iters / 16 / 8 / 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.565221Z",
     "iopub.status.busy": "2025-11-20T22:02:13.564936Z",
     "iopub.status.idle": "2025-11-20T22:02:13.579744Z",
     "shell.execute_reply": "2025-11-20T22:02:13.579229Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.565207Z"
    }
   },
   "outputs": [],
   "source": [
    "# import time\n",
    "# time.sleep(60 * 60 * 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.945972Z",
     "start_time": "2024-05-16T13:59:41.945964Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.580424Z",
     "iopub.status.busy": "2025-11-20T22:02:13.580286Z",
     "iopub.status.idle": "2025-11-20T22:02:13.595415Z",
     "shell.execute_reply": "2025-11-20T22:02:13.594846Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.580411Z"
    }
   },
   "outputs": [],
   "source": [
    "# !cd /home/tony/Work/tony/slurm/bluejay && sbatch sbatch_ipo_bluejay"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-21T02:39:05.622439Z",
     "iopub.status.busy": "2025-11-21T02:39:05.622071Z",
     "iopub.status.idle": "2025-11-21T02:39:06.887110Z",
     "shell.execute_reply": "2025-11-21T02:39:06.886508Z",
     "shell.execute_reply.started": "2025-11-21T02:39:05.622422Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cache kept!\n"
     ]
    }
   ],
   "source": [
    "import shutil\n",
    "\n",
    "# Basic file copy\n",
    "shutil.copy(\n",
    "    \"/home/tony/Work/tony/Preference/make_dataset_bluejay_t1_super.ipynb\",\n",
    "    os.path.join(OUT_DATA_DIR, \"make_dataset.ipynb\"),\n",
    ")\n",
    "print(\"Cache kept!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# some gymathtics loading prev data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-05-16T13:59:41.946562Z",
     "start_time": "2024-05-16T13:59:41.946555Z"
    },
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.625569Z",
     "iopub.status.busy": "2025-11-20T22:02:13.625428Z",
     "iopub.status.idle": "2025-11-20T22:02:13.640481Z",
     "shell.execute_reply": "2025-11-20T22:02:13.639968Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.625555Z"
    }
   },
   "outputs": [],
   "source": [
    "# prev_v3_data = \"/app/suno/data/dpo/7v_v20_full/\"\n",
    "\n",
    "# test_val_metas = read_jsonl(os.path.join(prev_v3_data, f\"meta_val.jsonl\"))\n",
    "# test_tr_metas = read_jsonl(os.path.join(prev_v3_data, f\"meta_tr.jsonl\"))\n",
    "\n",
    "# all_ids = set()\n",
    "# for meta in test_val_metas:\n",
    "#     all_ids.add(meta[\"id\"])\n",
    "# for meta in test_tr_metas:\n",
    "#     all_ids.add(meta[\"id\"])\n",
    "# print(len(all_ids), len(test_val_metas) + len(test_tr_metas))\n",
    "\n",
    "# all_ids = list(all_ids)\n",
    "# with open(\"/home/tony/Data/Preference/7b_v2/7v_v20_full_recut_id.json\", \"w\") as fp:\n",
    "#     json.dump(all_ids, fp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.641325Z",
     "iopub.status.busy": "2025-11-20T22:02:13.641044Z",
     "iopub.status.idle": "2025-11-20T22:02:13.656513Z",
     "shell.execute_reply": "2025-11-20T22:02:13.655996Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.641311Z"
    }
   },
   "outputs": [],
   "source": [
    "# x_data = train_df[train_df[\"preference\"]][\"similarity\"]\n",
    "# y_data = train_df[~train_df[\"preference\"]][\"similarity\"]\n",
    "# from matplotlib.colors import LogNorm\n",
    "\n",
    "# fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 10))\n",
    "\n",
    "# # 2D Histogram\n",
    "# h = ax1.hist2d(\n",
    "#     x_data,\n",
    "#     y_data,\n",
    "#     bins=(50, 50),\n",
    "#     cmap=\"coolwarm\",\n",
    "#     range=[[0, 1], [0, 1]],\n",
    "#     norm=LogNorm(),\n",
    "# )\n",
    "\n",
    "# ax1.set_xlabel(\"Semantic Distance (Preferred)\")\n",
    "# ax1.set_ylabel(\"Semantic Distance (Non-Preferred)\")\n",
    "# ax1.set_title(\n",
    "#     \"2D Histogram of Semantic Distances: Preferred vs Non-Preferred (Log Scale)\"\n",
    "# )\n",
    "\n",
    "# cbar1 = plt.colorbar(h[3], ax=ax1)\n",
    "# cbar1.set_label(\"Number of Request IDs (Log Scale)\")\n",
    "\n",
    "# # Scatter plot\n",
    "# ax2.scatter(x_data, y_data, alpha=0.1, s=1)\n",
    "# ax2.set_xlabel(\"Semantic Distance (Preferred)\")\n",
    "# ax2.set_ylabel(\"Semantic Distance (Non-Preferred)\")\n",
    "# ax2.set_title(\"Scatter Plot of Semantic Distances: Preferred vs Non-Preferred\")\n",
    "# ax2.set_xlim(0, 1)\n",
    "# ax2.set_ylim(0, 1)\n",
    "\n",
    "# plt.tight_layout()\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.659461Z",
     "iopub.status.busy": "2025-11-20T22:02:13.659096Z",
     "iopub.status.idle": "2025-11-20T22:02:13.674790Z",
     "shell.execute_reply": "2025-11-20T22:02:13.674262Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.659432Z"
    }
   },
   "outputs": [],
   "source": [
    "# train_metas = read_jsonl(os.path.join(OUT_DATA_DIR, f\"meta_tr.jsonl\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.675532Z",
     "iopub.status.busy": "2025-11-20T22:02:13.675381Z",
     "iopub.status.idle": "2025-11-20T22:02:13.690525Z",
     "shell.execute_reply": "2025-11-20T22:02:13.690008Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.675519Z"
    }
   },
   "outputs": [],
   "source": [
    "# train_info.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.691212Z",
     "iopub.status.busy": "2025-11-20T22:02:13.691073Z",
     "iopub.status.idle": "2025-11-20T22:02:13.706293Z",
     "shell.execute_reply": "2025-11-20T22:02:13.705774Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.691199Z"
    }
   },
   "outputs": [],
   "source": [
    "# import torch\n",
    "\n",
    "# a = torch.tensor([6.2500e-04, 3.9062e-05, 2.3462e-03])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.706961Z",
     "iopub.status.busy": "2025-11-20T22:02:13.706822Z",
     "iopub.status.idle": "2025-11-20T22:02:13.721924Z",
     "shell.execute_reply": "2025-11-20T22:02:13.721401Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.706948Z"
    }
   },
   "outputs": [],
   "source": [
    "# a.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.722553Z",
     "iopub.status.busy": "2025-11-20T22:02:13.722419Z",
     "iopub.status.idle": "2025-11-20T22:02:13.737677Z",
     "shell.execute_reply": "2025-11-20T22:02:13.737240Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.722539Z"
    }
   },
   "outputs": [],
   "source": [
    "# import time\n",
    "# time.sleep(3600 * 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.738391Z",
     "iopub.status.busy": "2025-11-20T22:02:13.738256Z",
     "iopub.status.idle": "2025-11-20T22:02:13.752979Z",
     "shell.execute_reply": "2025-11-20T22:02:13.752536Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.738378Z"
    }
   },
   "outputs": [],
   "source": [
    "# !cd /home/tony/Work/tony/slurm/diffusion && sbatch run_diffusion_infill.sh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:02:13.753633Z",
     "iopub.status.busy": "2025-11-20T22:02:13.753488Z",
     "iopub.status.idle": "2025-11-20T22:04:58.217668Z",
     "shell.execute_reply": "2025-11-20T22:04:58.217017Z",
     "shell.execute_reply.started": "2025-11-20T22:02:13.753620Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "check subset shape (7312962, 206) (593344, 206)\n",
      "user_id\n",
      "9      0.500000\n",
      "30     0.000000\n",
      "411    1.000000\n",
      "591    0.466667\n",
      "717    0.000000\n",
      "Name: preference, dtype: float64\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 600x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def get_control_slider(metadata):\n",
    "    if \"param_experiment\" in metadata:\n",
    "        exp = metadata.get(\"param_experiment\", \"\")\n",
    "        if exp:\n",
    "            if exp == \"mask_control_slider\":\n",
    "                if not metadata.get(\"control_sliders\", None):\n",
    "                    return False\n",
    "                else:\n",
    "                    return True\n",
    "            return None\n",
    "\n",
    "df[\"mask_control\"] = df.apply(\n",
    "    lambda row: get_control_slider(row[\"metadata\"]), axis=1\n",
    ")\n",
    "masked_request_id = df[~df[\"mask_control\"].isna()][\"request_id\"].unique()\n",
    "subset_df = df[df[\"request_id\"].isin(masked_request_id)].copy()\n",
    "print(\"check subset shape\", df.shape, subset_df.shape)\n",
    "# control masked\n",
    "user_pref_pct = (\n",
    "    subset_df[subset_df[\"mask_control\"] == True].groupby(\"user_id\")[\"preference\"]\n",
    "    .apply(lambda x: x.mean())\n",
    ")\n",
    "print(user_pref_pct.head())\n",
    "# Plot a histogram of the user preference percentages\n",
    "plt.figure(figsize=(6, 4))\n",
    "plt.hist(user_pref_pct, bins=np.linspace(0, 1, 100), edgecolor=\"black\")\n",
    "plt.xlabel(\"Preference % for mask_control\")\n",
    "plt.ylabel(\"Number of Users\")\n",
    "plt.title(\"Histogram of User Preference for 'mask_control'\")\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:04:58.218409Z",
     "iopub.status.busy": "2025-11-20T22:04:58.218259Z",
     "iopub.status.idle": "2025-11-20T22:04:59.523207Z",
     "shell.execute_reply": "2025-11-20T22:04:59.522685Z",
     "shell.execute_reply.started": "2025-11-20T22:04:58.218394Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "57589"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "user_counts = subset_df.groupby(\"user_id\")[\"preference\"].count()\n",
    "eligible_users = user_counts[user_counts >= 4].index\n",
    "len(eligible_users)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:04:59.523958Z",
     "iopub.status.busy": "2025-11-20T22:04:59.523798Z",
     "iopub.status.idle": "2025-11-20T22:05:01.656278Z",
     "shell.execute_reply": "2025-11-20T22:05:01.655681Z",
     "shell.execute_reply.started": "2025-11-20T22:04:59.523944Z"
    }
   },
   "outputs": [],
   "source": [
    "# control masked\n",
    "eligible_user_pref_pct = (\n",
    "    subset_df[subset_df[\"user_id\"].isin(eligible_users) & (subset_df[\"mask_control\"] == True)].groupby(\"user_id\")[\"preference\"]\n",
    "    .apply(lambda x: x.mean())\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:01.657066Z",
     "iopub.status.busy": "2025-11-20T22:05:01.656907Z",
     "iopub.status.idle": "2025-11-20T22:05:01.834249Z",
     "shell.execute_reply": "2025-11-20T22:05:01.833729Z",
     "shell.execute_reply.started": "2025-11-20T22:05:01.657051Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 600x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot a histogram of the user preference percentages\n",
    "plt.figure(figsize=(6, 4))\n",
    "plt.hist(eligible_user_pref_pct, bins=np.linspace(0, 1, 20), edgecolor=\"black\")\n",
    "plt.xlabel(\"Preference % for mask_control\")\n",
    "plt.ylabel(\"Number of Users\")\n",
    "plt.title(\"Histogram of User Preference for 'mask_control'\")\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:01.835000Z",
     "iopub.status.busy": "2025-11-20T22:05:01.834841Z",
     "iopub.status.idle": "2025-11-20T22:05:01.859635Z",
     "shell.execute_reply": "2025-11-20T22:05:01.859172Z",
     "shell.execute_reply.started": "2025-11-20T22:05:01.834985Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.25"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eligible_user_pref_pct[172918] # kakermix"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## sliders"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:01.860341Z",
     "iopub.status.busy": "2025-11-20T22:05:01.860193Z",
     "iopub.status.idle": "2025-11-20T22:05:01.883184Z",
     "shell.execute_reply": "2025-11-20T22:05:01.882698Z",
     "shell.execute_reply.started": "2025-11-20T22:05:01.860327Z"
    }
   },
   "outputs": [],
   "source": [
    "from typing import Any\n",
    "import pandas as pd\n",
    "\n",
    "def map_control_sliders_to_df(df: pd.DataFrame) -> pd.DataFrame:\n",
    "    \"\"\"Extracts 'style_weight' and 'weirdness_constraint' from the 'control_sliders' dict in the 'metadata' column\n",
    "    and adds them as new columns to the DataFrame.\n",
    "\n",
    "    Args:\n",
    "        df (pd.DataFrame): DataFrame with a 'metadata' column containing a 'control_sliders' dict.\n",
    "\n",
    "    Returns:\n",
    "        pd.DataFrame: DataFrame with added 'style_weight' and 'weirdness_constraint' columns.\n",
    "\n",
    "    Raises:\n",
    "        KeyError: If 'control_sliders', 'style_weight', or 'weirdness_constraint' are missing in any row.\n",
    "        TypeError: If the extracted values are not floats.\n",
    "\n",
    "    Example:\n",
    "        >>> import pandas as pd\n",
    "        >>> data = [{'metadata': {'control_sliders': {'style_weight': 0.89, 'weirdness_constraint': 0.8}}}]\n",
    "        >>> df = pd.DataFrame(data)\n",
    "        >>> df = map_control_sliders_to_df(df)\n",
    "        >>> df[['style_weight', 'weirdness_constraint']].iloc[0].tolist()\n",
    "        [0.89, 0.8]\n",
    "    \"\"\"\n",
    "    # Vectorized extraction for performance\n",
    "    sliders = df[\"metadata\"].map(lambda m: m.get(\"control_sliders\", {}))\n",
    "    style_weight = sliders.map(lambda s: s.get(\"style_weight\", None))\n",
    "    weirdness_constraint = sliders.map(lambda s: s.get(\"weirdness_constraint\", None))\n",
    "    audio_weight = sliders.map(lambda s: s.get(\"audio_weight\", None))\n",
    "\n",
    "    df[\"style_weight\"] = style_weight\n",
    "    df[\"weirdness_constraint\"] = weirdness_constraint\n",
    "    df[\"audio_weight\"] = audio_weight\n",
    "    return df\n",
    "\n",
    "def print_percentiles(\n",
    "    data: np.ndarray,\n",
    "    percentiles: list[float] = [5, 10, 20, 25, 50, 75, 80, 90, 95]\n",
    ") -> None:\n",
    "    \"\"\"Prints specified percentiles of the data.\n",
    "\n",
    "    Args:\n",
    "        data (np.ndarray): Array of values to compute percentiles for.\n",
    "        percentiles (list[float], optional): List of percentiles to print. Defaults to [5, 10, 20, 25, 50, 75, 80, 90, 95].\n",
    "\n",
    "    Example:\n",
    "        >>> print_percentiles(np.array([1, 2, 3, 4, 5]))\n",
    "    \"\"\"\n",
    "    data = data[~data.isna()]\n",
    "    results = np.percentile(data, percentiles)\n",
    "    print(\"Percentiles:\")\n",
    "    for p, v in zip(percentiles, results):\n",
    "        print(f\"  {p:>3}%: {v:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:01.883859Z",
     "iopub.status.busy": "2025-11-20T22:05:01.883713Z",
     "iopub.status.idle": "2025-11-20T22:05:04.149828Z",
     "shell.execute_reply": "2025-11-20T22:05:04.149319Z",
     "shell.execute_reply.started": "2025-11-20T22:05:01.883844Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>style_weight</th>\n",
       "      <th>weirdness_constraint</th>\n",
       "      <th>audio_weight</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>213890.000000</td>\n",
       "      <td>202538.000000</td>\n",
       "      <td>132966.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>0.748650</td>\n",
       "      <td>0.409438</td>\n",
       "      <td>0.645010</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>0.227708</td>\n",
       "      <td>0.275673</td>\n",
       "      <td>0.301108</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>0.630000</td>\n",
       "      <td>0.170000</td>\n",
       "      <td>0.410000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>0.795580</td>\n",
       "      <td>0.402682</td>\n",
       "      <td>0.700000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>0.930000</td>\n",
       "      <td>0.660000</td>\n",
       "      <td>0.920000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        style_weight  weirdness_constraint   audio_weight\n",
       "count  213890.000000         202538.000000  132966.000000\n",
       "mean        0.748650              0.409438       0.645010\n",
       "std         0.227708              0.275673       0.301108\n",
       "min         0.000000              0.000000       0.000000\n",
       "25%         0.630000              0.170000       0.410000\n",
       "50%         0.795580              0.402682       0.700000\n",
       "75%         0.930000              0.660000       0.920000\n",
       "max         1.000000              1.000000       1.000000"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_total = map_control_sliders_to_df(df_total)\n",
    "df_total[[\"style_weight\",\"weirdness_constraint\",\"audio_weight\"]].describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:04.150554Z",
     "iopub.status.busy": "2025-11-20T22:05:04.150403Z",
     "iopub.status.idle": "2025-11-20T22:05:04.429200Z",
     "shell.execute_reply": "2025-11-20T22:05:04.428678Z",
     "shell.execute_reply.started": "2025-11-20T22:05:04.150539Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Percentiles:\n",
      "    5%: 0.2900\n",
      "   10%: 0.4503\n",
      "   20%: 0.6000\n",
      "   25%: 0.6300\n",
      "   50%: 0.7956\n",
      "   75%: 0.9300\n",
      "   80%: 1.0000\n",
      "   90%: 1.0000\n",
      "   95%: 1.0000\n"
     ]
    },
    {
     "data": {
      "image/png": "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aaNHHnlEZ86c0RNPPKFGjRoVu//HH3+srKwsjRw5UiEhIXr99df1wAMPaMOGDQoPD9fIkSN1+vRpff311/4GDoDz0FgAwEUaN26s2rVr+z/tLs7XX3+t/Px8/elPfyr2TW39+vV13XXXaf78+erUqVOxk4tTU1M1bdo0jRo1qkx1nTlzRuvWrfNf5nLVVVfpoYce0vLlyzV27Ngyjq5stV3os88+05YtW/TQQw/530SPHj1akydP1pIlS3THHXfo5z//uX//w4cPa926df5t3bp10+DBg7V27dpiJxwXeu+993T48GE999xz/jMEo0aN0pgxY/Tiiy9q2LBhql+/vgYPHqyXXnpJjRo1umTtnTp10jXXXKPly5frb3/7m6699lp17txZffr08TcdktS2bVtdddVV+vjjj3X99deradOm/sduuukmzZgxQ2vWrNGjjz7q375mzRrFxMToxhtvLPH4L7zwgjwejz766CN/s/LrX/9a//3f/62FCxdq1KhRpTaFnTt31hdffOGfS7Fjxw41bdpUDRs2VGJiohYuXOjf99tvv5X005mOYI49d+5cNWrUSH/+859Vq1YtSefP5o0ZM0ZNmjQpsv/Jkyf117/+VXXr1pUktWjRQvfdd582bdqkPn36KDExUVdeeaW+/vrrS2YGoObiUigAKEZMTIyysrJKfLxwcu9nn30mr9dboWNERERo6NChZd7/1ltvDbh2/qabblKDBg305ZdfVuj4ZfXVV1/J5XIVuTzrN7/5jXw+X5HLnHr06BHQaLRt21axsbGlNmqFx2nQoIFuvvlm/7bw8HCNGTNG2dnZ+uabb8pde0hIiN544w099NBDqlOnjj7++GNNnz5dffr00UMPPVSmORa1a9dWv379tHbtWv+lXx6PR+vXr1e/fv0UExNT7Pf5fD799a9/Vd++feXz+ZSRkeH/LykpSefOndPevXtLPfYvfvEL5ebm+vfbsWOHEhMTJZ1vOtLT03X06FFJ5yefN23aVI0aNQrq2KdOndLBgwd16623+psKSbrmmmsCzthcaMCAAf6mQpK6dOkiSZfMHICzcMYCAIqRnZ1d6qVJAwYM0Pvvv68nn3xSc+fOVffu3XXDDTfopptuUmho2T6zadSoUbkmajdv3jzg65CQEDVv3lwnTpwo83NUxIkTJ9SwYcMiE4ILV1O6+PiXX355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ADuisXCQmJgIq0uARcjeTORuLrIHYEc0Fg4SGhpidQmwCNmbidzNRfYA7IjGAgAAAEDQwqwuAAAAACjN8ePHlJGRXuxj9erFqWnTZtVcEYpDY+EgOTn5VpcAi5C9mcjdXGQPkxw/fkw9enZVbk52sY9HRcdo89ff0FzYAI2Fg3g8XqtLgEXI3kzkbi6yh0kyMtKVm5OtETNfUcMWrQMeO/39IS1/cqIyMtJpLGyAxsJBatWKVFZWntVlwAJkbyZyN8uFl4JERUUoN9ftf4xLQWCChi1aq0m7jlaXgVLQWDhICIuEGIvszUTu5uBSEAA1AY0FAAA2x6UgAGoCS5eb/eabbzRhwgQlJSUpPj5eGzZsCHjc5/PppZdeUlJSkjp06KC77rpLR48eDdjnP//5jx555BF17txZXbp00dSpU5WVlRWwz/79+3X77berffv26t27t/70pz8VqWX9+vW66aab1L59ew0aNEhffvllpY8XAIBgFF4KcuF/FzcaAGAVSxuL7OxsxcfH6+mnny728T/96U9655139Mwzz2j58uWKjo7WuHHjlJf30zXFjz76qL777jstXrxYr776qrZv366nnnrK/3hmZqbGjRunK664QitXrtRjjz2mhQsX6r333vPvs2PHDj3yyCO67bbbtHr1avXr10+TJk3SwYMHq27wVSA7233pneBIZG8mcgcA2ImljUXv3r318MMP64YbbijymM/n05IlSzRx4kRdf/31atu2rebMmaPTp0/7z2wcPnxYGzdu1MyZM9WxY0d16dJFTz75pNauXatTp05JktasWaP8/HzNmjVLrVu31sCBAzVmzBgtXrzYf6wlS5aoV69e+u1vf6uWLVvqoYce0lVXXaX//d//rZ4fRCXxen1WlwCLkL2ZyB0AYCe2vfP28ePHlZqaqh49evi31a5dWx07dtTOnTslSTt37lSdOnXUvn17/z49evRQaGiodu/eLUnatWuXunTpooiICP8+SUlJ+v7773XmzBn/Pt27dw84flJSknbt2lVVw6sSsbGRVpcAi5C9mcgdAGAntp28nZqaKkmKi4sL2B4XF6e0tDRJUlpamurVqxfweFhYmOrWrev//rS0NDVt2jRgn/r16/sfq1u3rtLS0vzbijtOedSq9dMf+vx8j/LyChQZGabwcJd/u9tdILfbo+jocLlcP/V2ubkF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dddp2bJlSkxM9G+fM2eOvvnmG73//vsWVgcAAADYW6jVBdjFZZddJpfLpfT0wPkD6enpql+/vkVVAQAAADUDjcX/FxERoauvvlopKSn+bV6vVykpKQFnMAAAAAAUxRyLC9x99916/PHHlZCQoA4dOujtt99WTk6Ohg4danVpAAAAgK3RWFxgwIABysjI0Pz585Wamqp27drp9ddf51IoAAAA4BKYvA0AAAAgaMyxAAAAABA0GgsAAAAAQaOxAAAAABA0GgsAAAAAQaOxqEGWLl2qvn37qn379ho+fLh2795d6v7r16/XTTfdpPbt22vQoEH68ssvq6lSVKby5L58+XLdfvvt6tq1q7p27aq77rrrkq8T2Fd5f+cLrV27VvHx8brvvvuquEJUlfJmf/bsWU2bNk1JSUlKSEhQ//79+X9+DVXe7N966y31799fHTp0UO/evTVr1izl5eVVU7WoDN98840mTJigpKQkxcfHa8OGDZf8nq1bt2rIkCFKSEjQDTfcoJUrV1ZDpZdGY1FDrFu3TsnJyZo0aZJWrVqltm3baty4cUXuFF5ox44deuSRR3Tbbbdp9erV6tevnyZNmqSDBw9Wc+UIRnlz37p1qwYOHKglS5Zo2bJluvzyy/Wb3/xGp06dqubKEazyZl/o+PHj+sMf/qAuXbpUU6WobOXN3u126+6779aJEyf00ksv6ZNPPtGMGTPUqFGjaq4cwSpv9h999JHmzp2r+++/X+vWrdOzzz6rdevWad68edVcOYKRnZ2t+Ph4Pf3002Xa/9ixYxo/fry6deumDz/8UHfeeaeefPJJbdy4sYorLQMfaoTbbrvNN23aNP/XHo/Hl5SU5Fu0aFGx+z/44IO+e++9N2Db8OHDfb///e+rtE5UrvLmfrGCggJfYmKib9WqVVVUIapKRbIvKCjwjRw50rd8+XLf448/7ps4cWJ1lIpKVt7s3333XV+/fv18bre7ukpEFSlv9tOmTfONHTs2YFtycrJv1KhRVVonqk6bNm18n376aan7zJkzxzdw4MCAbQ899JDvN7/5TVWWViacsagB3G639u7dqx49evi3hYaGqkePHtq5c2ex37Nr1y517949YFtSUpJ27dpVlaWiElUk94vl5OSooKBAdevWraoyUQUqmv3LL7+suLg4DR8+vDrKRBWoSPZ/+9vf1KlTJ02fPl09evTQzTffrFdffVUej6e6ykYlqEj2iYmJ2rt3r/9yqWPHjunLL79U7969q6VmWMPO7/G483YN8OOPP8rj8SguLi5ge1xcnI4cOVLs96SlpRW5Y3hcXJzS0tKqrE5UrorkfrHnn39eDRs2DPhDBfurSPbbt2/XBx98oNWrV1dDhagqFcn+2LFj2rJliwYNGqTXXntNP/zwg6ZNm6aCggLdf//91VE2KkFFsh80aJB+/PFH3X777fL5fCooKNCoUaM0YcKE6igZFinuPV79+vWVmZmp3NxcRUVFWVQZcywAx3rttde0bt06LVy4UJGRkVaXgyqUmZmpxx57TDNmzFC9evWsLgfVzOfzKS4uTjNmzFBCQoIGDBigCRMmaNmyZVaXhiq2detWLVq0SE8//bRWrlyphQsX6ssvv9TLL79sdWkwFGcsaoDLLrtMLperyOSt9PT0Ih1rofr16xc5O1Ha/rCfiuRe6I033tBrr72mxYsXq23btlVZJqpAebM/duyYTpw4oYkTJ/q3eb1eSdJVV12lTz75RD//+c+rtmhUior83jdo0EBhYWFyuVz+bf/1X/+l1NRUud1uRUREVGnNqBwVyf6ll17SLbfc4r/8MT4+XtnZ2Xrqqac0ceJEhYby+bETFfceLy0tTbGxsZaerZA4Y1EjRERE6Oqrr1ZKSop/m9frVUpKihITE4v9nk6dOmnLli0B2zZv3qxOnTpVZamoRBXJXZL+9Kc/6Y9//KNef/11tW/fvjpKRSUrb/b/9V//pY8++kirV6/2/9e3b19169ZNq1evVuPGjauzfAShIr/3nTt31g8//OBvJiXp6NGjatCgAU1FDVKR7HNzc4s0D4UNps/nq7piYSk7v8ejsagh7r77bi1fvlyrVq3S4cOH9cwzzygnJ0dDhw6VJD322GOaO3euf/+xY8dq48aNevPNN3X48GEtWLBAe/bs0R133GHVEFAB5c39tdde00svvaRZs2apSZMmSk1NVWpqqrKysqwaAiqoPNlHRkaqTZs2Af/VqVNHtWrVUps2bXhzWcOU9/f+17/+tf7zn//o2Wef1ffff68vvvhCixYt0ujRo60aAiqovNn36dNHf/7zn7V27VodO3ZMX3/9tV566SX16dMn4AwW7C0rK0v79u3Tvn37JJ1fNnzfvn06efKkJGnu3Ll67LHH/PuPGjVKx44d05w5c3T48GEtXbpU69ev11133WVF+QG4FKqGGDBggDIyMjR//nylpqaqXbt2ev311/2nR//9738HfGrRuXNnPf/883rxxRc1b948XXnllXr55ZfVpk0bq4aACihv7suWLVN+fr4mT54c8Dz333+/HnjggWqtHcEpb/ZwjvJmf/nll+uNN95QcnKybrnlFjVq1Ehjx47VPffcY9UQUEHlzX7ixIkKCQnRiy++qFOnTqlevXrq06ePHn74YauGgArYs2ePxo4d6/86OTlZkjRkyBDNnj1bqamp+ve//+1/vFmzZlq0aJGSk5O1ZMkSNW7cWDNnzlSvXr2qvfaLhfg4VwYAAAAgSHzcBQAAACBoNBYAAAAAgkZjAQAAACBoNBYAAAAAgkZjAQAAACBoNBYAAAAAgkZjAQAAACBoNBYAAAAAgkZjAQCoclu3blV8fLzOnj1rdSlFxMfHa8OGDWXe385jAQAr0VgAAPwyMjL09NNP65e//KUSEhLUs2dPjRs3Tt9++61/n/K+Ea8Mhw8fVnx8vHbt2hWwfcSIEWrfvr3y8vL82/Ly8tS+fXu9//77ZXruTZs26brrrqvMcrVgwQINHjy4Up8TAOwuzOoCAAD28cADDyg/P1+zZ89Ws2bNlJ6erpSUFP3nP/+xtK6WLVuqQYMG2rZtmzp16iRJyszM1D//+U/FxcVp165d6tatmyRp586dcrvduvbaa8v03A0aNKiqsgHAKJyxAABIks6ePavt27fr0Ucf1bXXXqsmTZqoQ4cOGj9+vPr16ydJ6tu3ryRp0qRJio+PV9++fXX8+HG1bdtW//jHPwKe76233lKfPn3k9XqLPd727dt1++23q0OHDurdu7dmzpyp7OzsEuvr1q2btm7d6v/622+/1ZVXXqk+ffpo27Zt/u3btm1TkyZN1KxZM0nShg0bNGTIELVv3179+vXTwoULVVBQ4N//4jMwO3bs0ODBg9W+fXsNHTpUGzZsUHx8vPbt2xdQz969ezV06FB17NhRo0aN0pEjRyRJK1eu1MKFC7V//37Fx8crPj5eK1euLPkHDwAOQWMBAJAkxcTEKCYmRhs2bJDb7S52nw8++ECSlJycrE2bNumDDz5Q06ZN1aNHjyJvnleuXKkhQ4YoNLTon5offvhB99xzj2688UatWbNGL7zwgr799lvNmDGjxPq6deumHTt2+JuCrVu36pprrtE111wT0HBs3brVf/Zi+/btevzxxzV27FitW7dO06dP18qVK/Xqq68We4zMzExNnDhRbdq00apVq/Tggw/queeeK3bfF154QVOmTNGKFSvkcrk0depUSdKAAQP0m9/8Rq1bt9amTZu0adMmDRgwoMRxAYBT0FgAACRJYWFhmj17tlavXq0uXbpo1KhRmjdvnvbv3+/fp169epKkOnXqqEGDBv6vb7vtNq1du9bfkOzdu1cHDx7U0KFDiz3WokWLNGjQIN1111268sor1blzZz3xxBNavXp1wHyJC3Xr1k3Z2dn+MyPbtm1T165d1aVLF/39739XXl6ecnNztXv3bn9jsXDhQt17770aMmSImjVrpp49e+rBBx/UsmXLij3GRx99JEmaOXOmWrVqpd69e+u3v/1tsfs+/PDDuuaaa9SqVSvde++92rlzp/Ly8hQVFaWYmBi5XC41aNBADRo0UFRUVKk/ewBwAuZYAAD8+vfvr1/+8pfavn27du3apY0bN+r111/XzJkzS2wSJOn666/X9OnT9emnn2rgwIFatWqVunXrpqZNmxa7//79+3XgwAH/G3lJ8vl88nq9On78uFq2bFnke5o3b67GjRtr27Ztat26tfbt26drrrlGcXFxuuKKK7Rz5075fD653W5/Y7F//37t2LEj4AyFx+NRXl6ecnJyFB0dHXCM77//XvHx8YqMjPRva9++fbFjiI+P9/+7cJ5Genq6rrjiihJ/TgDgZDQWAIAAkZGR6tmzp3r27KlJkybpiSee0IIFC0ptLCIiInTrrbdq5cqVuuGGG/TRRx/piSeeKHH/7OxsjRo1SmPGjCny2OWXX17i9xVe9hQfH6/mzZsrLi5OktS1a1dt3bpVPp9PzZs39z9Hdna2HnjgAd14443FjjMYYWE//QkNCQmRpBLnkwCACWgsAAClatWqVcDk5vDwcHk8niL7DR8+XDfffLPeffddeTyeYt/MF7rqqqv03XffqXnz5uWqpVu3bnr22WfVsmVLXXPNNf7tXbp00fvvvy+fz+c/W1F4nO+//77Mx2nRooXWrFkjt9utiIgISSoyKb0swsPDaTIAGIc5FgAASdKPP/6osWPH6sMPP9T+/ft17NgxrV+/Xq+//rp/VShJatKkiVJSUpSamqozZ874t7ds2VIdO3bU888/r4EDB5Y6r+Cee+7Rzp07NX36dO3bt09Hjx7Vhg0bNH369FJrLJxnsWLFioDG4pprrtHf//73gPkV0vnVqz788EMtXLhQhw4d0uHDh7V27Vq98MILxT7/oEGD5PP59Pvf/16HDx/Wxo0b9eabb0r66axEWTRp0kTHjx/Xvn37lJGRUeJkeABwEhoLAIAkqVatWurYsaPefvtt3XHHHRo0aJBeeuklDR8+XE899ZR/v8cff1ybN2/WL3/5Sw0ZMiTgOW677Tbl5+dr2LBhpR6rbdu2euedd3T06FHdfvvtGjJkiObPn6+GDRuW+n3NmjVTkyZNlJWVpa5du/q3X3HFFWrYsKHy8/MDGo5evXrp1Vdf1aZNm3TbbbdpxIgReuutt9SkSZNinz82NlavvPKK9u3bp8GDB+uFF17QpEmTJMl/BqMs+vfvr169emns2LHq3r27Pv744zJ/LwDUVCE+n89ndREAAGd4+eWX9cknnwRMyq7p1qxZo6lTp2r79u2s7gQApWCOBQAgaFlZWTpx4oSWLl2qhx56yOpygrJ69Wo1bdpUjRo10oEDB/T888/rpptuoqkAgEugsQAABG3GjBn6+OOPdf3111/yMii7S01N1fz585WamqoGDRropptu0sMPP2x1WQBge1wKBQAAACBoTN4GAAAAEDQaCwAAAABBo7EAAAAAEDQaCwAAAABBo7EAAAAAEDQaCwAAAABBo7EAAAAAEDQaCwAAAABBo7EAAAAAELT/B8Kxm+39pVMAAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8, 5))\n",
    "df_total[\"style_weight\"].hist(bins=np.linspace(0, 1, 100), color=\"skyblue\", edgecolor=\"black\")\n",
    "print_percentiles(df_total[\"style_weight\"])\n",
    "plt.title(\"Distribution of Style Weight\")\n",
    "plt.xlabel(\"Style Weight\")\n",
    "plt.ylabel(\"Counts\")\n",
    "plt.grid(True, linestyle=\"--\", alpha=0.6)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:04.429937Z",
     "iopub.status.busy": "2025-11-20T22:05:04.429786Z",
     "iopub.status.idle": "2025-11-20T22:05:04.681717Z",
     "shell.execute_reply": "2025-11-20T22:05:04.681194Z",
     "shell.execute_reply.started": "2025-11-20T22:05:04.429922Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Percentiles:\n",
      "    5%: 0.0000\n",
      "   10%: 0.0000\n",
      "   20%: 0.1000\n",
      "   25%: 0.1700\n",
      "   50%: 0.4027\n",
      "   75%: 0.6600\n",
      "   80%: 0.6990\n",
      "   90%: 0.7600\n",
      "   95%: 0.8000\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAHqCAYAAACZcdjsAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABnpklEQVR4nO3deXxU9b3/8XcyyWQhiEBAFFApSKBlSRBLiUFuccelF5BFEUSpCqi4FhGprCWoSBGhioooFItUFuUWbZWrFiWACpQLRWRRCVAxiyxZJ5mZ3x/8MjJkz0xy5sz39Xw8eDzIOSfnfL7zziTnM2eL8Hq9XgEAAABAACKtLgAAAACA/dFYAAAAAAgYjQUAAACAgNFYAAAAAAgYjQUAAACAgNFYAAAAAAgYjQUAAACAgNFYAAAAAAgYjQUAAACAgNFYAEAQvfDCC0pKSmqQbY0YMUIjRozwfb1lyxYlJSXp/fffb5DtT5w4Uf369WuQbdVVfn6+nnzySV1++eVKSkrSH/7wB0vrOXz4sJKSkrR69eqA1pOUlKQXXnghSFUBQHDQWABAJVavXq2kpCTfv65duyotLU2jR4/W0qVLlZeXF5TtHDt2TC+88IL27NkTlPUFUyjXVhOLFi3SmjVrdOutt+qZZ57Rb37zmwqX69+/v26++eZy0z/44AMlJSXp9ttvLzfv7bffVlJSkj799NOg1w0AdhRldQEAEOrGjx+vNm3aqLS0VNnZ2dq6datmzZql119/XX/605/UqVMn37Jjx47VPffcU6v1//DDD1qwYIFat26tzp071/j7Fi9eXKvt1EVVtc2YMUNer7feawjE5s2b1b17d91///1VLnfppZfq7bff1qlTp9S4cWPf9G3btikqKkr/93//p5KSEkVHR/vNczgcSk5OrnE9rVu31s6dOxUVxZ9fAOGHIxYAUI0rrrhCv/nNbzRo0CDde++9Wrx4sZYsWaKcnByNGzdORUVFvmWjoqIUExNTr/UUFhZKkpxOp5xOZ71uqyrR0dGWbr8mcnJydM4551S73KWXXiqPx6Nt27b5Td+2bZuuu+46FRUVaffu3X7zvvzySyUlJSkhIaHG9URERCgmJkYOh6PK5QoKCmq8TgAIFTQWAFAHvXv31rhx43TkyBG9++67vukVXWPx2Wef6dZbb1XPnj2VkpKia6+9VnPnzpV0+rqIW265RZL0xBNP+E67KjsHf8SIEbrxxhu1a9cuDR8+XN27d/d979nXWJTxeDyaO3euLr/8ciUnJ2vMmDH6z3/+47dMv379NHHixHLfe+Y6q6utomssCgoKNHv2bPXt21ddunTRtddeq8WLF5c7spGUlKTp06frww8/1I033qguXbrohhtu0D//+c+qXnafnJwcTZo0SampqeratatuvvlmrVmzxje/7HqTw4cP6+OPP/bVfvjw4QrXd+mll0qSX2NRXFys3bt365prrlHbtm395uXm5urbb7/1fZ90+rSxJ554Qqmpqb7xvP32237bqegai4kTJyolJUWHDh3S3XffrZSUFD322GOSJJfLpVmzZulXv/qVUlJSNGbMGH3//ffl6i/7ufvuu+80ceJE9ezZU5deeqmeeOIJXyN6pnfeeUcDBw5Ut27d9Mtf/lIPP/xwuZ+Rb7/9Vg888IAuv/xyde3aVVdccYUefvhhnTp1yrdMVT/bAMzDsVgAqKPf/OY3mjt3rj799FMNGTKkwmX27dune++9V0lJSRo/frycTqe+++47305q+/btNX78eM2fP19Dhw717aj26NHDt47jx4/r7rvv1g033KCbb75ZzZs3r7KuF198UREREbr77ruVk5OjN954Q6NGjdI777yj2NjYGo+vJrWdyev1auzYsb6GpHPnztq4caOeeeYZHTt2TJMmTfJb/ssvv9Q//vEP3XbbbWrUqJGWLVum8ePH66OPPlLTpk0rrauoqEgjRozQoUOHNHz4cLVp00bvv/++Jk6cqJMnT+qOO+5Q+/bt9cwzzyg9PV2tWrXSnXfeKUlq1qxZhets27atWrZs6dc8lJ3+lJKSopSUFG3btk133XWXpJ8akLLXIjs7W0OGDFFERISGDx+uZs2a6Z///KeefPJJ5eXladSoUVW+1qWlpRo9erQuvfRSPf74476cnnzySb377ru68cYb1aNHD23evLnKU+0eeughtWnTRo888oj+/e9/669//auaNWum3/3ud75lXnzxRT3//PO6/vrrdcsttyg3N1d//vOfNXz4cK1du1bnnHOOXC6XRo8eLZfLpdtvv12JiYk6duyYPv74Y508eVKNGzeu9mcbgHloLACgjlq1aqXGjRsrMzOz0mU+++wzlZSU6JVXXqlwpzYxMVFXXHGF5s+fr+Tk5AovLs7KytK0adM0bNiwGtV14sQJrV+/3neKzs9//nM99NBDWrlypUaOHFnD0dWstjNt2LBBmzdv1kMPPaSxY8dKkoYPH67x48dr6dKluv3223XhhRf6lj9w4IDWr1/vm9arVy/95je/0d/+9rcKL5Yu89Zbb+nAgQN69tlnfRdcDxs2TCNGjNC8efM0aNAgJSYm6je/+Y2ef/55nXfeedXWLp1uEj7++GPftRTbtm1TmzZt1LJlS6WkpGjBggW+Zb/88ktJPx3p+OMf/yi3261169b5mqJbb71VjzzyiBYsWKBhw4ZV2dS5XC5dd911evTRR33TvvrqK7377ru67bbbNGXKFN/r+eijj2rv3r0Vrqdz586aNWuW7+vjx4/r7bff9jUWR44c0QsvvKCHHnpIY8aM8S13zTXXaMCAAXrzzTc1ZswYHThwQIcPH9bzzz+v6667zrfcmdeqVPezDcA8nAoFAAGIj49Xfn5+pfPLzu/fsGGDPB5PnbbhdDo1cODAGi//3//9337n/V933XVq0aKFPvnkkzptv6b++c9/yuFwlDs966677pLX6y13mlNqaqpfo9GpUyclJCRU2aiVbadFixa68cYbfdOio6M1YsQIFRQU6PPPP69T/ZdeeqnftRTbtm1TSkqKpNNNR05Ojr799ltJ0vbt29WmTRudd9558nq9+sc//qF+/frJ6/UqNzfX9y8tLU2nTp0qd31GRW699Va/r8vyOvv1vOOOOypdx9nNZ8+ePXX8+HHfHcw++OADeTweXX/99X51JiYm6qKLLtKWLVskyffz8+mnn1Z4KpUUnJ9tAOGFIxYAEICCgoIqT03q37+//vrXv2ry5Ml67rnn1Lt3b1199dW67rrrFBlZs892zjvvvFpdJH3RRRf5fR0REaGLLrpIR44cqfE66uLIkSNq2bJluYuZ27dv75t/pvPPP7/cOpo0aaKTJ09Wu52LLrqo3OtXtp2jR4/WunbJ/zqL7t27a/v27XrwwQclSR07dlRCQoK2bdum888/X7t27VL//v0lnb7e4uTJk3rrrbf01ltvVbju3NzcKrcdFRWlVq1a+U07cuSIIiMj/ZovSfrZz35W6XouuOACv6/Ldv5PnDihhIQEffvtt/J6vbrmmmsqrUM6fWrYnXfeqSVLlmjdunXq2bOn+vXrp5tvvtl316xg/GwDCC80FgBQR99//71OnTpVbsfvTLGxsVq+fLm2bNmijz/+WBs3btT69ev11ltv6bXXXqv27kBl62gobre7RjUFQ2XbseoWtp06dVKjRo305Zdfqm/fvjp+/LjvGorIyEh1795dX375pS688EKVlJT4GpGyT+tvvvlmDRgwoMJ1V/fQRKfTGZSd8crWUfaaejweRURE6JVXXqnw9Y+Pj/f9f+LEiRowYIA2bNigzz77TDNnztSiRYu0cuVKtWrVKig/2wDCC40FANTRO++8I0lKS0urcrnIyEj17t1bvXv31hNPPKGXXnpJf/zjH7VlyxalpqYqIiIiqHV99913fl97vV599913fju3lR0ZOHr0qNq2bev7uja1tW7dWhkZGcrLy/M7anHw4EHf/GBo3bq19u7dK4/H47cjXbadsz+1r6myZ1Js27ZNX375pRISEtSxY0ff/JSUFK1fv953RKissWjWrJkaNWokj8ej1NTUug6rnNatW8vj8ejQoUN+RynKxlkXF154obxer9q0aaN27dpVu3zZ3bTGjRunbdu26dZbb9Vf/vIXPfzww5Kq/9kGYBaOVQJAHWRkZOhPf/qT2rRpU+ETm8scP3683LSyB825XC5JUlxcnCRVewpQTa1du9bvqeDvv/++srKydMUVV/imtW3bVv/61798NUjSRx99VO6Wo7Wp7YorrpDb7dby5cv9pr/++uuKiIjw234grrjiCmVlZWn9+vW+aaWlpVq2bJni4+N12WWX1XndPXr0UG5urlavXq3u3bv7NS4pKSn65ptvtGHDBp177rm+U68cDoeuvfZa/f3vf9fXX39dbp3VnQZVmbLXa9myZX7T33jjjTqtTzp9kbbD4dCCBQvKHRnyer368ccfJUl5eXkqLS31m9+xY0dFRkb6fmZq8rMNwCwcsQCAavzzn//UwYMH5Xa7lZ2drS1btuizzz7TBRdcoBdffLHKB+ItXLhQX3zxhfr27avWrVsrJydHb775plq1auX7xPvCCy/UOeecoxUrVqhRo0aKj49Xt27d/I4c1EaTJk102223aeDAgb7bzV500UV+t8QdPHiw/v73v+u3v/2trr/+eh06dEjr1q0rd1pXbWrr16+fevXqpT/+8Y86cuSIkpKS9Nlnn2nDhg264447qjxlrDaGDh2qt956SxMnTtTu3bvVunVr/f3vf9e2bds0adKkWj2w7mxlmWzfvl0PPPCA37zk5GRFRERox44d+vWvf+13NOfRRx/Vli1bNGTIEA0ePFgdOnTQiRMntHv3bmVkZGjr1q21rqVz58668cYb9eabb+rUqVNKSUnR5s2byx2Rqo0LL7xQDz30kJ577jkdOXJEV111lRo1aqTDhw/rww8/1JAhQzR69Ght3rxZ06dP13XXXaeLL75Ybrdb77zzjq+Jkmr2sw3ALDQWAFCN+fPnSzp956Fzzz1XHTt21KRJkzRw4MBqd2L79eunI0eOaNWqVfrxxx/VtGlT/fKXv9QDDzzguwg2Ojpas2fP1ty5czV16lSVlpYqPT29zo3FmDFjtHfvXr388svKz89X7969NWXKFN/RB0nq06ePJk6cqCVLlmjWrFnq0qWLXnrpJT399NN+66pNbZGRkXrxxRc1f/58rV+/XqtXr1br1q01YcIE3/MfgiE2NlbLli3TnDlztGbNGuXl5aldu3ZKT0+v1d2zKpKcnKyoqCiVlpb67ghVJiEhQZdccon27t1bbsc5MTFRf/3rX7Vw4UJ98MEH+stf/qJzzz1XHTp08D3sri5mzZqlpk2bat26ddqwYYN69eqll19+WX379q3zOu+55x5dfPHFev3117Vw4UJJp2+dfPnll/seeJiUlKS0tDR99NFHOnbsmOLi4pSUlKRXXnlFycnJkmr2sw3ALBFeq66SAwAAABA2uMYCAAAAQMBoLAAAAAAEjMYCAAAAQMBoLAAAAAAEjMYCAAAAQMBoLAAAAAAEjMYCAAAAQMBoLAAAAAAEjCdvB1lOzilZ9cjBRo1ilJ9fbM3GYSmyNxO5m4vszUX2ZrIy94gIqXnzxjValsYiyLxeWdZYlG0fZiJ7M5G7ucjeXGRvJjvkzqlQAAAAAAJGYwEAAAAgYBFerx0OrNhHdrZ111gAAAAAwRQRISUm1uwaC45YhJHIyAirS4BFyN5M5G4usjcX2ZvJLrnTWISR+Hin1SXAImRvJnI3F9mbi+zNZJfcaSwAAAAABIzGAgAAAEDAaCzCCBeNm4vszUTu5iJ7c5G9meySO3eFCjLuCgUAAIBwwV2hDOVwEKepyN5M5G4usjcX2ZvJLrnbo0rUSFxctNUlwCJkbyZyNxfZm4vszWSX3GksAAAAAASMxgIAAABAwGgswojHw1XjpiJ7M5G7ucjeXGRvJrvkzl2hgoy7QgEAACBccFcoQ0VFOawuARYhezORu7nI3lxkbya75B5ldQEInqyso8rM/E+56c2aNVebNm0tqAgNJTY2Snl5bqvLQAMjd3ORvbnI3kx2yZ3GIkwcPpypy9MuU2FBQbl5sXHx2vTZ5zQXAAAAqDc0FmEiNzdHhQUFGjLzRbVsd4lv+g/f7NPKyWOVm5tDYwEAAIB6Q2MRZlq2u0StO3e3ugw0MLfbY3UJsAC5m4vszUX2ZrJL7ly8DYSBwsISq0uABcjdXGRvLrI3k11yp7EAwoDTaY+7RSC4yN1cZG8usjeTXXKnsQDCgNPJWY0mIndzkb25yN5MdsmdxgIAAABAwGgsAAAAAASMxgIIAyUlof/QHAQfuZuL7M1F9mayS+40FkAYKC4utboEWIDczUX25iJ7M9kld0sbizfffFM33XSTevTooR49emjo0KH65JNPfPOLi4s1bdo09erVSykpKXrggQeUnZ3tt46jR4/qnnvuUffu3dW7d289/fTTKi31f/G3bNmiAQMGqEuXLrr66qu1evXqcrUsX75c/fr1U9euXTV48GDt3LmzfgYN1IOYGHtc1IXgIndzkb25yN5Mdsnd0saiVatWeuyxx7R69WqtWrVKv/rVr3Tfffdp3759kqRZs2bpo48+0rx587Rs2TL98MMPuv/++33f73a7de+996qkpEQrVqzQ7NmztWbNGs2fP9+3TGZmpu6991716tVL77zzju644w5NnjxZGzdu9C2zfv16paen67777tOaNWvUqVMnjR49Wjk5OQ33YgABiI62x23oEFzkbi6yNxfZm8kuuVvaWPTr1099+/bVxRdfrHbt2unhhx9WfHy8duzYoVOnTmnVqlWaOHGievfurS5dumjWrFnavn27duzYIUn69NNPtX//fj377LPq3Lmz+vbtqwcffFDLly+Xy+WSJK1YsUJt2rTRxIkT1b59e91+++269tpr9frrr/vqWLJkiYYMGaJBgwapQ4cOmjZtmmJjY7Vq1SoLXhUAAADAfkLmGgu3262//e1vKigoUEpKinbt2qWSkhKlpqb6lmnfvr0uuOACX2OxY8cOdezYUYmJib5l0tLSlJeXp/379/uW6d27t9+20tLSfOtwuVzavXu333YiIyOVmpqq7du319NoAQAAgPBi+Qlbe/fu1bBhw1RcXKz4+HgtXLhQHTp00J49exQd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lNUFVCYrK0uS1Lx5c7/pzZs3V3Z2tiQpOztbzZo185sfFRWlJk2a+L4/Oztbbdq08VsmMTHRN69JkybKzs72TatoO7XRqFGM7/8lJW4VF5cqJiZK0dEO33SXq1Qul1txcdF+58wVFZWqtNSt+Hin3xMWCwtL5HZ71KhRjCLOePBiQYFLHo9XCQkxiour+sEpsbGn5zsckX6H0zwerwoKXIqKcig29qcfB7fbo8LCEjmdDjmdP01vyDGdKS+vWJGREX4PiPF6T1/MxJhKFBER4bf+cBhTOOYU7DFFRTmUkBATVmMqw5j8x1Td7/gydhpTmXDKqSHGFBXlkNPpCKsxSeGXU7iOqToh21jYVX5+cblbghUXl6q4uLTcsoWFJRWuo6DAVem6K5KXV6zCwoq/p0xR0en5brdHeXnl11Na6lZenrvcdJfLLZer/PSGGNPZPB5vhdMZk3TqVFGF27TzmMIxJ8bEmKS6jam63/Fl7DSms4VDTmdjTIxJCs6YKlu2IcbkcpXW+MONkD0VqkWLFpKknJwcv+k5OTm+owuJiYnKzc31m19aWqoTJ074vj8xMbHckYeyr89cz9nLnLkdINRFRdX80wSED3IHzMP73kx2yT1kG4s2bdqoRYsWysjI8E3Ly8vTv/71L6WkpEiSUlJSdPLkSe3atcu3zObNm+XxeNStWzdJUnJysr744guVlPzULW7atEnt2rVTkyZNfMts3rzZb/ubNm1ScnJyfQ0PCKozD2vCHOQOmIf3vZnskruljUV+fr727NmjPXv2SDp9wfaePXt09OhRRUREaOTIkXrxxRe1YcMG7d27VxMmTFDLli111VVXSZLat2+vPn366Pe//7127typL7/8UjNmzNANN9yg8847T5J00003KTo6Wk8++aT27dun9evXa+nSpbrzzjt9dYwcOVIbN27Ua6+9pgMHDuiFF17Qrl27dPvttzf8iwIAAADYkKXtz65duzRy5Ejf1+np6ZKkAQMGaPbs2br77rtVWFiop556SidPntSll16qV199VTExP128MmfOHM2YMUN33HGHIiMjdc0112jy5Mm++Y0bN9bixYs1ffp0DRw4UE2bNtW4ceM0dOhQ3zI9evTQnDlzNG/ePM2dO1cXX3yxFi5cqI4dOzbAqwAAAADYn6WNRa9evbR3795K50dEROjBBx/Ugw8+WOky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qUuXLrr22mu1du1av+9PSkrSX//6V913333q3r27rrnmGm3YsME3v6rarrzySknSf//3fyspKUkjRozwe71efPFFpaWl6brrrpMkrV27VgMHDlRKSoouv/xyPfroo8rJyfFt6+xToVavXq2ePXtq48aNuv7665WSkqLRo0frhx9+kHT6lLU1a9Zow4YNSkpKUlJSkt9rDgANIcrqAgAA5fXs2VP5+fn697//ra5du2rr1q1q2rSptm7d6lvm888/1913361Dhw7p7rvv1oMPPqhZs2YpNzdXM2bM0IwZM5Senl7pNhYsWKBHH31UTz75pBwOh9avX68XXnhBTz31lC699FK98847WrZsmdq2bev3fVu2bFGLFi30xhtv6NChQ3r44YfVuXNnDRkyRJI0ffp07d+/X3/84x/VsmVLffDBB/rtb3+rdevW6eKLL9b06dNVUlKiP//5z4qPj9f+/fsVHx8vSXr++ed14MABvfLKK2ratKkOHTqkoqKial+v/Px83X777TrvvPP0pz/9SS1atNDu3bvl8XgkSR988IFmzZqlJ554Qqmpqfr44481adIktWrVSr/61a/8XpPf/e53mjBhgpYtW6bHHntMH330kc4999wqa/vrX/+qwYMH6/XXX1eHDh0UHR3tW2dGRoYSEhK0ZMkS37TS0lI9+OCD+tnPfqacnBzNnj1bEydO1CuvvFLpGIuKivTaa6/pmWeeUWRkpH73u9/p6aef1nPPPae77rpLBw4cUF5eni/zJk2aVPu6AUAw0VgAQAhq3LixOnfurK1bt/oai1GjRmnBggXKz89XXl6evvvuO1122WVatGiRbrrpJo0aNUqSdPHFF+vJJ5/UiBEjNHXqVMXExFS4jRtvvFGDBg3yff3II4/olltu0eDBgyVJDz/8sDIyMsodtWjSpImeeuopORwOtW/fXn379lVGRoaGDBmio0ePavXq1froo4903nnnSZJGjx6tjRs3avXq1XrkkUd09OhRXXvttUpKSpIkv8bl6NGj6ty5s7p27SpJatOmTY1er//5n/9Rbm6u3n77bZ177rmSpIsuusg3f/HixRowYICGDx8uSWrXrp127Nih1157za+xGDBggG688Ubf67Fs2TLt3LlTV1xxRZW1NWvWTJJ07rnnqkWLFn61xcfHa+bMmXI6nb5pt9xyi+//bdu21ZNPPqlbbrlF+fn5atSoUYVjLCkp0bRp03ThhRdKkoYPH64//elPkqRGjRopNjZWLper3PYBoKHQWABAiLrsssu0detW3XXXXfriiy/0yCOP6L333tOXX36pEydOqGXLlrr44ov11Vdfae/evVq3bp3ve71erzwejw4fPqz27dtXuP4uXbr4fX3gwAENGzbMb1pycnK5U2o6dOggh8Ph+7pFixb6+uuvJUlff/213G6375SfMi6Xy7fDP3LkSE2dOlWffvqpUlNTdc0116hTp06SpFtvvVXjx4/Xv//9b11++eW66qqr1KNHj2pfqz179ujnP/+5bxtnO3jwYLmL13v06KGlS5f6TStrdqTTDUFCQoJyc3MDqq1jx45+TYUk7dq1SwsWLNBXX32lEydOyOv1SpL+85//qEOHDhWuJy4uztdUSFLLli39Tp8CAKvRWABAiPrlL3+pVatW6auvvlJ0dLTat2+vX/7yl9q6datOnjypX/7yl5KkgoICDRs2zHde/5nOP//8StdfdvpRbUVF+f/piIiI8O0YFxQUyOFwaNWqVX7Nx5nbGzx4sNLS0vTxxx/rs88+08svv6zHH39cI0aMUN++ffXRRx/pk08+0WeffaZRo0Zp+PDhevzxx6usKTY2tk5jOduZpzCVja3sdKq61nb2RfMFBQUaPXq00tLSNGfOHDVt2lT/+c9/NHr06Covoq/qdQeAUMDF2wAQosqus3j99dd12WWXSZJ69eqlrVu3asuWLb7G4uc//7n279+viy66qNy/sz8pr0r79u39LnaWVO7r6nTu3Flut1u5ubnlajnzFJ3zzz9ft956qxYsWKA777xTK1eu9M1r1qyZBgwYoDlz5mjSpEl66623qt1u2a1ejx8/XuH8n/3sZ9q2bZvftG3btlV6dKAyldVW1pCUXWxflYMHD+r48eN67LHH1LNnT7Vv3z4oRx6io6N9TRAAWIHGAgBCVJMmTZSUlKR169b5moiePXvq3//+t7799ltfs3H33Xdr+/btmj59uvbs2aNvv/1WH374oaZPn16r7Y0cOVKrVq3SqlWr9M0332j+/Pnat29frdbRrl073XTTTZowYYL+8Y9/KDMzUzt37tSiRYv08ccfS5L+8Ic/aOPGjcrMzNTu3bu1ZcsW3+lazz//vD788EN999132rdvnz7++ONKT+U60w033KDExETdd999+vLLL5WZmam///3v2r59uyTpt7/9rdasWaM333xT3377rZYsWaIPPvhAd911V43HVlVtzZs3V2xsrDZu3Kjs7GydOnWq0vVccMEFio6O1rJly5SZmakNGzb4rpUIROvWrbV3714dPHhQubm53EIYQIPjVCgACGGXXXaZ9uzZ42sszj33XN8n3D/72c8kSZ06ddKyZcs0b9483XbbbZJOXxDcv3//Wm2rf//+OnTokJ599lkVFxfr2muv1a233qpPP/20VutJT0/Xiy++qNmzZ+uHH37Queeeq+TkZP3Xf/2XJMnj8Wj69On6/vvvlZCQoD59+uiJJ56QdPpT97lz5+rIkSOKjY3VpZdeqrlz51a7TafTqddee01PP/207rnnHrndbrVv315TpkyRJF111VWaNGmSXnvtNc2aNUutW7fWrFmz1KtXrxqPq6raoqKiNHnyZC1cuFDz589Xz549tWzZsgrX06xZM82ePVtz587VsmXL9Itf/EKPP/64xo4dW+NaKjJkyBBt3bpVgwYNUkFBgZYuXVqr8QFAoCK8nKAJAAAAIECcCgUAAAAgYJwKBQAIeS+99JIWLVpU4bxLL71Ur776agNXBAA4G6dCAQBC3vHjx3XixIkK58XGxvoexgcAsA6NBQAAAICAcY0FAAAAgIDRWAAAAAAIGI0FAAAAgIDRWAAAAAAIGI0FAAAAgIDRWAAAAAAIGI0FAAAAgIDRWAAAAAAI2P8D7tkToUx9tF4AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8, 5))\n",
    "df_total[\"weirdness_constraint\"].hist(bins=np.linspace(0, 1, 100), color=\"skyblue\", edgecolor=\"black\")\n",
    "print_percentiles(df_total[\"weirdness_constraint\"])\n",
    "plt.title(\"Distribution of Weirdness\")\n",
    "plt.xlabel(\"weirdness_constraint\")\n",
    "plt.ylabel(\"Counts\")\n",
    "plt.grid(True, linestyle=\"--\", alpha=0.6)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-11-20T22:05:04.682460Z",
     "iopub.status.busy": "2025-11-20T22:05:04.682306Z",
     "iopub.status.idle": "2025-11-20T22:05:04.918443Z",
     "shell.execute_reply": "2025-11-20T22:05:04.917945Z",
     "shell.execute_reply.started": "2025-11-20T22:05:04.682445Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Percentiles:\n",
      "    5%: 0.1000\n",
      "   10%: 0.2000\n",
      "   20%: 0.3500\n",
      "   25%: 0.4100\n",
      "   50%: 0.7000\n",
      "   75%: 0.9200\n",
      "   80%: 1.0000\n",
      "   90%: 1.0000\n",
      "   95%: 1.0000\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAHqCAYAAACZcdjsAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABfCUlEQVR4nO3deXhU5d3/8U+2yUKQCmEHlbIElCVBlF8gwCNqVVAsuMsiisoioq1PKUUqqwQVEMENEUEUi1gBtaJttVVBAgiCFArIToAWs8iSdZKZ+f3Bw5AheybJOZn7/bouroucOXPO984ngfM9yz1BHo/HIwAAAADwQ7DVBQAAAACo/WgsAAAAAPiNxgIAAACA32gsAAAAAPiNxgIAAACA32gsAAAAAPiNxgIAAACA32gsAAAAAPiNxgIAAACA32gsAKAUCxYsUGxsbI3sa+jQoRo6dKj3602bNik2Nlaff/55jex/woQJ6tu3b43sq7KysrL09NNPq2fPnoqNjdWzzz5rdUlatWqVYmNjdezYMe+yi7OsTfypfejQobr11luruCIAtUWo1QUAQE1ZtWqV/vCHP3i/djgcqlevnmJjY9WnTx8NGjRI0dHRfu/n5MmTWrlypW644QZ16NDB7+1VJTvXVh4LFy7U6tWrNWbMGLVs2VKtW7e2uiRUQm3/OQRQPBoLAMYZN26cWrRooYKCAqWlpWnz5s2aOXOmli5dqldffVXt27f3rjt69Gg9+uijFdr+Tz/9pJdfflnNmzev0EHT4sWLK7SfyiittunTp8vj8VR7Df7YuHGjunTporFjx1pdSqlqIsvqYvXPIYDai8YCgHF69+6tTp06eb8eOXKkkpOTNWrUKI0ZM0Zr165VRESEJCk0NFShodX7T2VOTo4iIyPlcDiqdT9lCQsLs3T/5ZGenq42bdpYXUaZrM7SH7W5dgDW4hkLAJCUkJCgMWPG6Pjx4/r444+9y4t7xuLbb7/Vfffdp27duik+Pl433XST5s6dK+nccxF33nmnJOkPf/iDYmNjFRsbq1WrVkm6cA/6zp07NXjwYHXp0sX73pLubXe73Zo7d6569uypuLg4jRo1Sv/5z3981unbt68mTJhQ5L2Ft1lWbcU9Y5Gdna1Zs2apT58+6tixo2666SYtXry4yJWN2NhYTZs2TV988YVuvfVWdezYUf3799c333xT2rfdKz09XRMnTlSPHj3UqVMnDRgwQKtXr/a+fv55k2PHjumrr77y1l74uYaLffjhhxo2bJgSEhLUsWNH9evXT++9916R9WJjY7VgwYIiy4v7nu7bt0/Dhg1T586d1bt3b7366qtyu91F3ltclmWNsTyWLVumDh066MyZM95lb731lmJjY5WUlORd5nK5FB8frxdeeMG7zO12a+nSperfv786deqkHj166JlnntHp06fLrP348eMaNWqU4uLilJCQoJkzZ2rdunWKjY3Vpk2bitS5f/9+DR06VF26dFGvXr20aNEi72tl/RwCqL24YgEA/+f222/X3LlztX79et19993FrrNv3z6NHDlSsbGxGjdunBwOh44cOaLvv/9ektS6dWuNGzdO8+fP1z333KOrr75aktS1a1fvNk6dOqVHHnlE/fv314ABA9SgQYNS63rttdcUFBSkRx55ROnp6Xr77bc1fPhwffTRR94rK+VRntoK83g8Gj16tPdAsEOHDlq3bp2ef/55nTx5UhMnTvRZf+vWrfrb3/6m+++/X3Xq1NE777yjcePG6Z///KcuvfTSEuvKzc3V0KFDdfToUQ0ePFgtWrTQ559/rgkTJujMmTN64IEH1Lp1az3//PNKSkpSkyZN9OCDD0qS6tevX+J2//SnP6lt27bq27evQkND9c9//lNTp06Vx+PR4MGDy/19Oy81NVXDhg2Ty+XSo48+qsjISK1cuVLh4eFlvrc8YyyPbt26ye12a+vWrbruuuskSVu2bFFwcLC2bNniXe/f//63srOzdc0113iXPfPMM1q9erUGDRqkoUOH6tixY1q+fLn+/e9/609/+lOJV6yys7P1wAMPeMcfExOjv/zlL8U2FJJ0+vRpPfzww7rxxht1yy236K9//atmz56tdu3aqU+fPhX+OQRQe9BYAMD/adKkierWrauUlJQS1/n222+Vn5+vRYsWFXtQGxMTo969e2v+/PmKi4vT7bffXmSd1NRUTZ06Vffee2+56jp9+rTWrl3rfbD8yiuv1JNPPqmVK1dq2LBh5Rxd+Wor7Msvv9TGjRv15JNPavTo0ZKkwYMHa9y4cVq2bJmGDBmiyy67zLv+gQMHtHbtWu+y7t276/bbb9enn36qIUOGlLif999/XwcOHNALL7ygAQMGSJLuvfdeDR06VPPmzdMdd9yhmJgY3X777XrppZfUuHHjMmuXpHfffden8RoyZIhGjBihJUuWVKqxWLRokTIyMvTBBx+oc+fOkqSBAwfqV7/6VZnvLc8YyzNxQPv27RUdHa0tW7bouuuuk8fj0datW/WrX/1Kf//735WVlaU6depo69atCg4O9h6sb9myRR988IFmz56t2267zbu97t276+GHH9bnn3/us/zi2lNSUvTKK6/ohhtu8Nb+61//utj1f/rpJz333HPe1++880717dtXH374ofr06VPhn0MAtQe3QgFAIVFRUcrKyirx9UsuuUTSuYPu4m6BKQ+Hw6FBgwaVe/1f//rXPgedN998sxo2bKivv/66Uvsvr2+++UYhISFFbot56KGH5PF4itzm1KNHD59G4/xBcGmN2vn9NGzY0Gea0rCwMA0dOlTZ2dn67rvvKlV/4abi7NmzysjI0LXXXquUlBSdPXu2wtv7+uuvFRcX520qpHNXTEo6IC+sqsYYHBys+Ph479WJAwcO6NSpU3r00Ufl8Xi0fft2SecaibZt23p/Xj///HPVrVtXPXv2VEZGhvfPVVddpaioqBKvPkjSunXr1LhxY11//fXeZeHh4SVe1YuKivJpFhwOhzp16lTmzwGA2o8rFgBQSHZ2dqm3JvXr108ffPCBJk2apDlz5ighIUE33nijbr75ZgUHl+9cTePGjSv0gOzll1/u83VQUJAuv/xyHT9+vNzbqIzjx4+rUaNGRc6kn5/i9eL9N23atMg26tWr5/M8QEn7ufzyy4t8/87v58SJExWuXTp3a9aCBQu0fft25eTk+Lx29uxZ1a1bt0LbO3HihLp06VJkeatWrcp8b1WOsVu3bnr55ZeVm5urLVu2qGHDhrrqqqvUvn17bdmyRT179tTWrVt1yy23eN9z5MgRnT17VgkJCcVuMz09vdTaL7vsMgUFBfksL9xEFtakSZMi69arV0979+4t7xAB1FI0FgDwf/773//q7NmzJR4wSefOgi9fvlybNm3SV199pXXr1mnt2rV6//339dZbbykkJKTM/VTkuQh/uVyuctVUFUrajxVT2B49elTDhw/XL3/5S02YMEFNmzZVWFiYvv76ay1durRcV5tcLlcNVFpxV199tfLz87Vt2zZt2bJF3bp18y7fsmWLDhw4oIyMDO9y6dyD2w0aNNDs2bOL3WZpz6pUVE39vAGwHxoLAPg/H330kSQpMTGx1PWCg4OVkJCghIQE/eEPf9Drr7+uF198UZs2bVKPHj2KnK3115EjR3y+9ng8OnLkiM9sVSVdGThx4oRatmzp/boitTVv3lzJycnKzMz0uWpx8OBB7+tVoXnz5tq7d6/cbrfPGf3z+2nWrFmFt/mPf/xDTqdTr732ms/7i7vlp7jvndPpVGpqqs+yZs2aFclCkg4dOlRmPVU5xs6dOyssLExbt27V1q1bNWLECEnSNddcow8++EAbN26UJJ/G4rLLLlNycrK6du1a4ca2efPm2r9/vzwej8/Pz9GjRyu0ncKq+ncEgD3wjAUASEpOTtarr76qFi1aeB+uLc6pU6eKLDv/AV9Op1OSFBkZKUll3gJUXmvWrFFmZqb3688//1ypqanq3bu3d1nLli31ww8/eGuQpH/+859FpqWtSG29e/eWy+XS8uXLfZYvXbpUQUFBPvv3R+/evZWamqq1a9d6lxUUFOidd95RVFSUz8xG5XX+rHnhqyVnz57Vhx9+WGTdli1b+syoJEkrV64scsWiT58+2r59u3bs2OFdlpGRoU8++aTMeqpyjOHh4erUqZP+8pe/6MSJE94Golu3bsrNzdWyZct02WWXqVGjRt733HLLLXK5XHr11VeLbK+goKDUn4fExESdPHlSX375pXdZXl6eVq5cWe6aL1bVvyMA7IErFgCM88033+jgwYNyuVxKS0vTpk2b9O2336pZs2Z67bXXSp0+9JVXXtGWLVvUp08fNW/eXOnp6XrvvffUpEkT77SZl112mS655BKtWLFCderUUVRUlDp37uxz5aAi6tWrp/vvv1+DBg3yTjd7+eWX+zw8e9ddd+mvf/2rHn74Yd1yyy06evSoPvnkkyK3dVWktr59+6p79+568cUXdfz4ccXGxurbb7/Vl19+qQceeKDUW8Yq4p577tH777+vCRMmaNeuXWrevLn++te/6vvvv9fEiRPLNVvSxXr27KmwsDCNGjVK9957r7KysvTBBx+oQYMGRa5E3HXXXZo8ebIef/xx9ejRQ3v27NH69euLTJH78MMP66OPPtLDDz+sYcOGeaebbdasWZnPD1T1GLt166Y33nhDdevWVbt27SRJDRo0UKtWrXTo0KEikwNce+21uueee7Rw4ULt3r3b+/05fPiwPv/8cz399NO6+eabS6z93Xff1VNPPaVhw4apYcOG+uSTT7y/J5W5+lDVvyMA7IHGAoBx5s+fL+ncrDy/+MUv1K5dO02cOFGDBg0q8wCvb9++On78uD788EP9/PPPuvTSS3Xttdfq8ccf9z4MHBYWplmzZmnu3LmaMmWKCgoKlJSUVOmDplGjRmnv3r164403lJWVpYSEBE2ePNl71leSevXqpQkTJmjJkiWaOXOmOnbsqNdff13PPfecz7YqUltwcLBee+01zZ8/X2vXrtWqVavUvHlzjR8/Xg899FClxlKciIgIvfPOO5o9e7ZWr16tzMxMtWrVSklJSRWaPauwX/7yl5o/f77mzZun5557TjExMbrvvvtUv379Ip+/cffdd+vYsWP685//rHXr1unqq6/WkiVLNHz4cJ/1GjVqpGXLlmnGjBl644039Itf/EL33nuvGjVqpKeffrpGx3i+sYiPj/e5tapbt246dOiQt8ktbNq0aerYsaNWrFihF198USEhIWrevLkGDBhQ6mdI1KlTR2+//bZmzJihZcuWKSoqSr/+9a8VHx+vxx9/vFyf43Gxqv4dAWAPQR4rnqoDAAC12tKlS5WUlKRvvvlGjRs3trocADbAMxYAAKBUubm5Pl/n5eXp/fff1xVXXEFTAcCLW6EAALCBU6dOKT8/v8TXQ0JCqnRa2IoYO3asmjVrpvbt2yszM1Mff/yxDh48WOL0tQDMxK1QAADYwNChQ7V58+YSX2/evLn+8Y9/1GBFFyxdulR//vOfdfz4cblcLrVp00YPP/yw+vXrZ0k9AOyJxgIAABvYuXNnqdOvhoeHF/tQNgDYBY0FAAAAAL/x8DYAAAAAv9FYAAAAAPAbjQUAAAAAvzHdbBVLTz8rq55aqVMnXFlZedbsHJYiezORu7nI3lxkbyYrcw8Kkho0qFuudWksqpjHI8sai/P7h5nI3kzkbi6yNxfZm6k25M6tUAAAAAD8RmMBAAAAwG98jkUVS0uz7hkLAAAAoCoFBUkxMeV7xoIrFgEkODjI6hJgEbI3E7mbi+zNRfZmqi2501gEkKgoh9UlwCJkbyZyNxfZm4vszVRbcqexAAAAAOA3GgsAAAAAfqOxCCA8NG4usjcTuZuL7M1F9maqLbkzK1QVY1YoAAAABApmhTJUSAhxmorszUTu5iJ7c5G9mWpL7rWjSpRLZGSY1SXAImRvJnI3F9mbi+zNVFtyp7EAAAAA4DcaCwAAAAB+o7EIIG43T42biuzNRO7mIntzkb2ZakvuzApVxZgVCgAAAIGCWaEMFRoaYnUJsAjZm4nczUX25iJ7M9WW3EOtLgBVJyIiVJmZLqvLgAXI3kzkbi6yNxfZB7Zjx1KUkZFeZHnLlk116aWNLaioYmgsAAAAAIsdO5aiHj2vUW5OdpHXIqOi9O3679SiRUsLKis/GgsAAADAYhkZ6crNydbdM15To1Ztvct/OrRPKyeNVkZGOo0Fao7L5ba6BFiE7M1E7uYie3ORfeBr1KqtmnfoYnUZlcLD2wEkJyff6hJgEbI3E7mbi+zNRfawMxqLAOJw1I4ZA1D1yN5M5G4usjcX2cPOaCwCiMPBnW2mInszkbu5yN5cZA87o7EAAAAA4DcaCwAAAAB+o7EIIPn5fGCOqcjeTORuLrI3F9nDzmgsAkheXoHVJcAiZG8mcjcX2ZuL7GFnNBYBJDycB7pMRfZmIndzkb25yB52RmMRQMLCmILOVGRvJnI3F9mbi+xhZzQWAAAAAPxGYwEAAADAbzQWAcTp5IEuU5G9mcjdXGRvLrKHndFYBBCnkynoTEX2ZiJ3c5G9ucgedkZjEUAiI8OsLgEWIXszkbu5yN5cZA87o7EIICEhxGkqsjcTuZuL7M1F9rAzfjoBAAAA+I3GAgAAAIDfaCwCSG4uM0WYiuzNRO7mIntzkT3sjMYigBQUMFOEqcjeTORuLrI3F9nDzmgsAkhUlMPqEmARsjcTuZuL7M1F9rAzGosAEhwcZHUJsAjZm4nczUX25iJ72BmNBQAAAAC/0VgAAAAA8BuNRQDJycm3ugRYhOzNRO7mIntzkT3sjMYigLhcbqtLgEXI3kzkbi6yNxfZw85oLAJInTrhVpcAi5C9mcjdXGRvLrKHndFYBJAgJoowFtmbidzNRfbmInvYGY0FAAAAAL/RWAAAAADwG41FAMnOdlpdAixC9mYid3ORvbnIHnZmaWOxcOFC3XHHHYqPj1dCQoLGjBmjgwcP+qwzdOhQxcbG+vx55plnfNY5ceKEHn30UXXp0kUJCQl67rnnVFBQ4LPOpk2bNHDgQHXs2FE33nijVq1aVaSe5cuXq2/fvurUqZPuuusu7dixo+oHXY3cbo/VJcAiZG8mcjcX2ZuL7GFnljYWmzdv1uDBg7Vy5UotWbJEBQUFGjFihLKzs33Wu/vuu7V+/Xrvn/Hjx3tfc7lcGjlypPLz87VixQrNmjVLq1ev1vz5873rpKSkaOTIkerevbs++ugjPfDAA5o0aZLWrVvnXWft2rVKSkrSY489ptWrV6t9+/YaMWKE0tPTq/8bUUWio5kpwlRkbyZyNxfZm4vsYWeWNhaLFy/WoEGD1LZtW7Vv316zZs3SiRMntGvXLp/1IiIi1LBhQ++f6Oho72vr16/X/v379cILL6hDhw7q06ePnnjiCS1fvlxO57nLhStWrFCLFi00YcIEtW7dWkOGDNFNN92kpUuXerezZMkS3X333brjjjvUpk0bTZ06VREREfrwww9r5HsBAAAA1Ga2esbi7NmzkqR69er5LP/kk0/UvXt33XrrrZozZ45ycnK8r23fvl3t2rVTTEyMd1liYqIyMzO1f/9+7zoJCQk+20xMTNT27dslSU6nU7t27VKPHj28rwcHB6tHjx7atm1blY4RAAAACEShVhdwntvt1syZM9W1a1e1a9fOu/zWW29Vs2bN1KhRI+3du1ezZ8/WoUOH9PLLL0uS0tLSfJoKSd6vU1NTS10nMzNTubm5On36tFwulxo0aOCzToMGDYo88wEAAACgKNs0FlOnTtW+ffv03nvv+Sy/5557vH+PjY1Vw4YNNXz4cB09elSXXXZZTZdZpsKfiJmf71JeXoHCw0MVFhbiXe50FsjpdCkyMkwhIRcuGuXmFqigwKWoKIeCgy98Ak5OTr5cLrfq1An3+WCc7Gyn3G6Pz/2W0dHhyszMU3BwkKKiHN7lHo+UlZWnkJBgRUaGeZe73R5lZzsVGhqiiIgLPw4ul1s5OflyOELkcFxYbsWYJDGmMsbkdBb4bD8QxhSIOVXHmKKjwwNuTFLg5VTVY8rJyfdZPxDGFIg5VdeYHI6QgBtTIOZU0TEFB5d+I1FkpMNnXFaMqSy2aCymTZumr776Su+++66aNGlS6rpdunSRJB05ckSXXXaZYmJiiszelJaWJklq2LChpHNXJ84vK7xOdHS0IiIiFBwcrJCQkCIPaqenpxe50lGWrKw8eS6asCEvr0B5eQVF1s3JyS92GyVNJZeVlVfs8szMc8uDg4O8s0W43R7v8sJcLnexywsKXMrMdBVZ7nS65HQWXV5TYyqMMZU8poICt5zOouvX5jEFYk5VPabCv/NSYIzpYoyp+DF5PMUvr81jCsScqmNMhX/vA2VMhZk8JrfbXex6F7bjLFJnTYzJ6SxQZKSjyGvFsfQZC4/Ho2nTpunvf/+73n77bbVs2bLM9+zevVvShaYhLi5OP/74o09TsGHDBkVHR6tNmzbedTZu3OiznQ0bNiguLk6S5HA4dNVVVyk5Odn7utvtVnJysuLj4/0aY00q3LHCLGRvJnI3F9mbi+xhZ5Y2FlOnTtXHH3+sOXPmqE6dOkpNTVVqaqpyc3MlSUePHtUrr7yinTt36tixY/ryyy/1+9//Xtdcc43at28v6dxD2G3atNH48eO1Z88erVu3TvPmzdPgwYPlcJz75bv33nuVkpKi559/XgcOHNDy5cv12Wefafjw4d5aHnzwQa1cuVKrV6/WgQMHNGXKFOXk5GjQoEE1/n0BAAAAahtLb4X605/+JOnch+AVlpSUpEGDBiksLEzJyclatmyZsrOz1bRpU/3qV7/SmDFjvOuGhITo9ddf15QpU3TPPfcoMjJSAwcO1Lhx47zrtGzZUgsXLlRSUpKWLVumJk2aaMaMGerVq5d3nX79+ikjI0Pz589XamqqOnTooDfffLPCt0IBAAAAJrK0sdi7d2+przdt2lTvvvtumdtp3ry5Fi1aVOo63bt315o1a0pdZ8iQIRoyZEiZ+7Ori5/tgDnI3kzkbi6yNxfZw85s9TkW8E9JDzAh8JG9mcjdXGRvLrKHndFYBJDCU5nBLGRvJnI3F9mbi+xhZ/x0BpDC8xXDLGRvJnI3F9mbi+xhZzQWAAAAAPxGYwEAAADAbzQWAaTwJ/DCLGRvJnI3F9mbi+xhZzQWAaSkj7tH4CN7M5G7ucjeXGQPO6OxCCChoSFWlwCLkL2ZyN1cZG8usoed0VgEkIgISz/vEBYiezORu7nI3lxkDzujsQAAAADgNxoLAAAAAH6jsQggLpfb6hJgEbI3E7mbi+zNRfawMxqLAJKTk291CbAI2ZuJ3M1F9uYie9gZjUUAcTiYKcJUZG8mcjcX2ZuL7GFnNBYBxOFgpghTkb2ZyN1cZG8usoed0VgAAAAA8BuNBQAAAAC/0VgEkPx8l9UlwCJkbyZyNxfZm4vsYWc0FgEkL6/A6hJgEbI3E7mbi+zNRfawMxqLABIezgNdpiJ7M5G7ucjeXGQPO6OxCCBhYUxBZyqyNxO5m4vszUX2sDMaCwAAAAB+o7EAAAAA4DcaiwDidPJAl6nI3kzkbi6yNxfZw85oLAKI08kUdKYiezORu7nI3lxkDzujsQggkZFhVpcAi5C9mcjdXGRvLrKHndFYBJCQEOI0FdmbidzNRfbmInvYGT+dAAAAAPxGYwEAAADAbzQWASQ3l5kiTEX2ZiJ3c5G9ucgedkZjEUAKCpgpwlRkbyZyNxfZm4vsYWc0FgEkKsphdQmwCNmbidzNRfbmInvYGY1FAAkODrK6BFiE7M1E7uYie3ORPeyMxgIAAACA32gsAAAAAPiNxiKA5OTkW10CLEL2ZiJ3c5G9ucgedkZjEUBcLrfVJcAiZG8mcjcX2ZuL7GFnNBYBpE6dcKtLgEXI3kzkbi6yNxfZw85oLAJIEBNFGIvszUTu5iJ7c5E97IzGAgAAAIDfaCwAAAAA+I3GIoBkZzutLgEWIXszkbu5yN5cZA87o7EIIG63x+oSYBGyNxO5m4vszUX2sDMaiwASHc1MEaYiezORu7nI3lxkDzujsQAAAADgNxoLAAAAAH6jsQAAAADgNxqLAJKZmWd1CbAI2ZuJ3M1F9uYie9gZjUUACQ7m4zhNRfZmIndzkb25yB52RmMRQKKiHFaXAIuQvZnI3Vxkby6yh53RWAAAAADwG40FAAAAAL/RWAQQDx/GaSyyNxO5m4vszUX2sDMaiwCSlcVMEaYiezORu7nI3lxkDzujsQggISHEaSqyNxO5m4vszUX2sDN+OgNIZGSY1SXAImRvJnI3F9mbi+xhZzQWAAAAAPxGYwEAAADAbzQWAcTtZqoIU5G9mcjdXGRvLrKHnVnaWCxcuFB33HGH4uPjlZCQoDFjxujgwYM+6+Tl5Wnq1Knq3r274uPj9fjjjystLc1nnRMnTujRRx9Vly5dlJCQoOeee04FBQU+62zatEkDBw5Ux44ddeONN2rVqlVF6lm+fLn69u2rTp066a677tKOHTuqftDVKDvbaXUJsAjZm4nczUX25iJ72JmljcXmzZs1ePBgrVy5UkuWLFFBQYFGjBih7Oxs7zozZ87UP//5T82bN0/vvPOOfvrpJ40dO9b7usvl0siRI5Wfn68VK1Zo1qxZWr16tebPn+9dJyUlRSNHjlT37t310Ucf6YEHHtCkSZO0bt067zpr165VUlKSHnvsMa1evVrt27fXiBEjlJ6eXjPfjCoQGhpidQmwCNmbidzNRfbmInvYmaWNxeLFizVo0CC1bdtW7du316xZs3TixAnt2rVLknT27Fl9+OGHmjBhghISEtSxY0fNnDlT27Zt0/bt2yVJ69ev1/79+/XCCy+oQ4cO6tOnj5544gktX75cTue5rn7FihVq0aKFJkyYoNatW2vIkCG66aabtHTpUm8tS5Ys0d1336077rhDbdq00dSpUxUREaEPP/ywpr8tlRYREWp1CbAI2ZuJ3M1F9uYie9iZrZ6xOHv2rCSpXr16kqSdO3cqPz9fPXr08K7TunVrNWvWzNtYbN++Xe3atVNMTIx3ncTERGVmZmr//v3edRISEnz2lZiY6N2G0+nUrl27fPYTHBysHj16aNu2bVU+TgAAACDQ2Kbtdbvdmjlzprp27ap27dpJktLS0hQWFqZLLrnEZ90GDRooNTXVu07hpkKS9+uy1snMzFRubq5Onz4tl8ulBg0aFNnPxc98lKVOnXDv3/PzXcrLK1B4eKjCwi5cunQ6C+R0uhQZGebzQTe5uQUqKHApKsqh4OAg7/KcnHy5XG7VqROuoAuLlZ3tlNvtUXT0uX2GhYUoOjpcmZl5Cg4OUlSUw7uux3Pu0zpDQoJ95sB2uz3KznYqNDTE5yyIy+VWTk6+HI4QORwXltf0mM5jTKWPKTg4yGf7gTCmQMypqsd0/nc+kMZ0HmMqfUxBQb6/84EwpkDMqTrGFBYWIocjJKDGJAVeTpUZU3Bw6ef7IyMdPuOyYkxlsU1jMXXqVO3bt0/vvfee1aX4JSsrT56LJmzIyytQXl5BkXVzcvKL3UZJD2ZlZeUVuzwz89zyyMgw7zbdbo93eWEul7vY5QUFLmVmuoosdzpdcjqLLq+pMRXGmEoeU36+q9g6a/OYAjGnqh5T4d95KTDGdDHGVPyYCgqK/52vzWMKxJyqY0yRkWHedQJlTIWZPCa3213sehe24yxSZ02MyeksUGSko8hrxbHFrVDTpk3TV199pbfffltNmjTxLo+JiVF+fr7OnDnjs356eroaNmzoXefiWaLOf13WOtHR0YqIiNCll16qkJCQIg9qp6enF7nSYWcl/eAi8JG9mcjdXGRvLrKHnVnaWHg8Hk2bNk1///vf9fbbb6tly5Y+r3fs2FFhYWFKTk72Ljt48KBOnDihuLg4SVJcXJx+/PFHn6Zgw4YNio6OVps2bbzrbNy40WfbGzZs8G7D4XDoqquu8tmP2+1WcnKy4uPjq3LI1crhYKYIU5G9mcjdXGRvLrKHnVnaWEydOlUff/yx5syZozp16ig1NVWpqanKzc2VJNWtW1d33HGHZs2apY0bN2rnzp2aOHGi4uPjvU1BYmKi2rRpo/Hjx2vPnj1at26d5s2bp8GDB8vhOHfZ5t5771VKSoqef/55HThwQMuXL9dnn32m4cOHe2t58MEHtXLlSq1evVoHDhzQlClTlJOTo0GDBtX0t6XSCt8bB7OQvZnI3Vxkby6yh51Z+tP5pz/9SZI0dOhQn+VJSUneA/qJEycqODhY48aNk9PpVGJioiZPnuxdNyQkRK+//rqmTJmie+65R5GRkRo4cKDGjRvnXadly5ZauHChkpKStGzZMjVp0kQzZsxQr169vOv069dPGRkZmj9/vlJTU9WhQwe9+eabtepWKAAAAMAqQR7PxY8awx9paWeLPLxdU87PCAXzkL2ZyN1cZG8usg9cO3Zs1w039NbY5V+oeYcu3uXHd/+glwffoC+++EadO8fVeF1BQVJMTN1yrWuLh7dRNfLziz7NDzOQvZnI3Vxkby6yh53RWASQ4qY4gxnI3kzkbi6yNxfZw85oLAJIeDgPdJmK7M1E7uYie3ORPeyMxiKAVOSTERFYyN5M5G4usjcX2cPOaCwAAAAA+I3GAgAAAIDfaCwCiNPJA12mInszkbu5yN5cZA87o7EIIE4nU9CZiuzNRO7mIntzkT3sjMYigERGhlldAixC9mYid3ORvbnIHnZGYxFAQkKI01RkbyZyNxfZm4vsYWf8dAIAAADwG40FAAAAAL/RWASQ3FxmijAV2ZuJ3M1F9uYie9gZjUUAKShgpghTkb2ZyN1cZG8usoed0VgEkKgoh9UlwCJkbyZyNxfZm4vsYWc0FgEkODjI6hJgEbI3E7mbi+zNRfawMxoLAAAAAH6jsQAAAADgNxqLAJKTk291CbAI2ZuJ3M1F9uYie9gZjUUAcbncVpcAi5C9mcjdXGRvLrKHndFYBJA6dcKtLgEWIXszkbu5yN5cZA87o7EIIEFMFGEssjcTuZuL7M1F9rAzGgsAAAAAfqOxAAAAAOA3GosAkp3ttLoEWITszUTu5iJ7c5E97IzGIoC43R6rS4BFyN5M5G4usjcX2cPOaCwCSHQ0M0WYiuzNRO7mIntzkT3sjMYCAAAAgN9oLAAAAAD4jcYCAAAAgN9oLAJIZmae1SXAImRvJnI3F9mbi+xhZzQWASQ4mI/jNBXZm4nczUX25iJ72BmNRQCJinJYXQIsQvZmIndzkb25yB52RmMBAAAAwG80FgAAAAD8RmMRQDx8GKexyN5M5G4usjcX2cPOaCwCSFYWM0WYiuzNRO7mIntzkT3sjMYigISEEKepyN5M5G4usjcX2cPO+OkMIJGRYVaXAIuQvZnI3Vxkby6yh53RWAAAAADwG40FAAAAAL/RWAQQt5upIkxF9mYid3ORvbnIHnZGYxFAsrOdVpcAi5C9mcjdXGRvLrKHndFYBJDQ0BCrS4BFyN5M5G4usjcX2cPOaCwCSEREqNUlwCJkbyZyNxfZm4vsYWc0FgAAAAD8RmMBAAAAwG+Vaix27dqlvXv3er/+4osvNGbMGM2dO1dOJw8VWcXlcltdAixC9mYid3ORvbnIHnZWqcbimWee0eHDhyVJKSkp+u1vf6vIyEh9/vnneuGFF6qyPlRATk6+1SXAImRvJnI3F9mbi+xhZ5VqLA4fPqwOHTpIkj777DNdc801mjNnjpKSkvS3v/2tSgtE+TkczBRhKrI3E7mbi+zNRfaws0o1Fh6PR273uUtxycnJ6t27tySpadOm+vnnn6uuOlSIw8FMEaYiezORu7nI3lxkDzurVGPRsWNHvfbaa1qzZo2+++47/c///I8k6dixY4qJianK+gAAAADUApVqLCZOnKh///vfmj59ukaNGqXLL79ckvTXv/5V8fHxVVogAAAAAPur1PW09u3b65NPPimyfPz48QoJ4d4/q+Tnu6wuARYhezORu7nI3lxkDzur1BWL66+/vthnKfLy8nTTTTf5XRQqJy+vwOoSYBGyNxO5m4vszUX2sLNKNRbHjx/3PrxdmNPp1MmTJ/0uCpUTHs4DXaYiezORu7nI3lxkDzur0E/nl19+6f37unXrVLduXe/XbrdbycnJat68edVVhwoJCwvhTIahyN5M5G4usjcX2cPOKtRYPPbYY5KkoKAgTZgwwXdDoaFq3rx5keUAAAAAAl+FboXas2eP9uzZo6ZNm2rDhg3er/fs2aOdO3fqr3/9q6677rpyb++7777TqFGjlJiYqNjYWH3xxRc+r0+YMEGxsbE+f0aMGOGzzqlTp/TUU0+pa9eu6tatmyZOnKisrKwidd9///3q1KmT+vTpo0WLFhWp5bPPPtPNN9+sTp066bbbbtPXX39dge8MAAAAYLZKPWPxj3/8Q/Xr1/d759nZ2YqNjdXkyZNLXKdXr15av36998/cuXN9Xv/f//1f7d+/X0uWLNHrr7+uLVu26JlnnvG+npmZqREjRqhZs2ZatWqVxo8fr5dfflnvv/++d53vv/9eTz31lO68806tWbNG119/vR577DH9+OOPfo+xJjmdXBo1FdmbidzNRfbmInvYWaWfAEpOTlZycrLS09OLPMidlJRUrm306dNHffr0KXUdh8Ohhg0bFvvagQMHtG7dOv35z39Wp06dJEmTJk3So48+qvHjx6tx48b6+OOPlZ+fr5kzZ8rhcKht27bavXu3lixZonvuuUeStGzZMvXq1UsPP/ywJOnJJ5/Uhg0b9O6772ratGnlGosdOJ1MQWcqsjcTuZuL7M1F9rCzSl2xePnll/XQQw8pOTlZP//8s86cOePzpypt3rxZCQkJuummmzR58mSfaW63bdumSy65xNtUSFKPHj0UHBysHTt2SJK2b9+ubt26yeFweNdJTEzUoUOHdPr0ae86CQkJPvtNTEzU9u3bq3Qs1S0yMszqEmARsjcTuZuL7M1F9rCzSl2xWLFihZKSkvTrX/+6isvx1atXL914441q0aKFUlJSNHfuXD3yyCN6//33FRISorS0tCK3ZIWGhqpevXpKTU2VJKWlpalFixY+68TExHhfq1evntLS0rzLzmvQoIHS0tIqXHOdOuHev+fnu5SXV6Dw8FCFhV344ECns0BOp0uRkWEKCbnQ2+XmFqigwKWoKIeCg4O8y3Ny8uVyuVWnTriCLixWdrZTbrdH0dHn9hkWFqKQkGBlZuYpODhIUVEXmimPR8rKylNISLDPP0put0fZ2U6FhoYoIuLCj4PL5VZOTr4cjhA5HBeW1/SYzmNMpY/pfPaBNKZAzKmqx3Q+90Aa03mMqfQxhYaGKDr6wj4DYUyBmFN1jCksLEQulzugxiQFXk6VGVNwcOnn+yMjHT7jsmJMZalUY5Gfn6+uXbtW5q0V0r9/f+/fzz+8fcMNN3ivYthRVlaePB7fZXl5BcVODZeTk1/sNrKznSVuuziZmeeWR0eHe//udnu8fy/M5XIXu7ygwKXMzKKXV51OV7GXXWtqTIUxppLHVNJ2avOYAjGnqh5T4d95KTDGdDHGVPyYPJ7il9fmMQViTtUxpujocO86gTKmwkweU3GfEee7HWeROmtiTE5ngSIjHUVeK06lboW688479cknn1TmrX5p2bKlLr30Uh05ckTSuSsPGRkZPusUFBTo9OnT3ucyYmJiilx5OP/1+asUxa2Tnp5e5CoGAAAAgOJV6opFXl6eVq5cqeTkZMXGxio01Hczf/jDH6qkuIv997//1alTp7xNQ3x8vM6cOaOdO3eqY8eOkqSNGzfK7Xarc+fOkqS4uDjNmzdP+fn5Cgs7d0low4YNatWqlerVq+ddZ+PGjRo+fLh3Xxs2bFBcXFy1jKO65OYyU4SpyN5M5G4usjcX2cPOKnXFYu/evWrfvr2CgoL0448/6t///rf3z+7du8u9naysLO3evdv7nmPHjmn37t06ceKEsrKy9Nxzz2n79u06duyYkpOTNWbMGF1++eXq1auXJKl169bq1auX/vjHP2rHjh3aunWrpk+frv79+6tx48aSpNtuu01hYWF6+umntW/fPq1du1bLli3Tgw8+6K1j2LBhWrdund566y0dOHBACxYs0M6dOzVkyJDKfHssU1DATBGmInszkbu5yN5cZA87C/J4Ln4ioOZs2rRJw4YNK7J84MCBmjJlih577DH9+9//1tmzZ9WoUSP17NlTTzzxhM8tSqdOndL06dP1j3/8Q8HBwfrVr36lSZMmqU6dOt519uzZo2nTpulf//qXLr30Ug0ZMkSPPvqozz4/++wzzZs3T8ePH9cVV1yh3/3ud2VOhVuctLSzRZ6xqClRUY4S70FEYCN7M5G7ucjeXGQfuHbs2K4bbuitscu/UPMOXbzLj+/+QS8PvkFffPGNOneOq/G6goKkmJi65Vq30p9jURW6d++uvXv3lvj64sWLy9zGL37xC82ZM6fUddq3b6/33nuv1HVuueUW3XLLLWXuz84KzywAs5C9mcjdXGRvLrKHnVWqsRg6dKiCgkr+wV62bFmlCwIAAABQ+1SqsejQoYPP1wUFBdq9e7f27dtX7Z9tAQAAAMB+KtVYTJw4sdjlCxYsUHZ2tl8FofJKmicZgY/szUTu5iJ7c5E97KxSs0KVZMCAAfrwww+rcpOoAJer9A9WQeAiezORu7nI3lxkDzur0sZi27ZtcjjK98l8qHp16oSXvRICEtmbidzNRfbmInvYWaVuhRo7dqzP1x6PR6mpqdq5c6fGjBlTJYWh4kp5nh4BjuzNRO7mIntzkT3srFKNRd26vnPZBgUFqVWrVho3bpwSExOrpDAAAAAAtUelGoukpKSqrgMAAABALebXB+Tt3LlTBw4ckCS1bdtWV155ZZUUhcrhkzjNRfZmIndzkb25yB52VqnGIj09Xb/5zW+0efNmXXLJJZKkM2fOqHv37nrxxRdVv379Ki0S5eN2e6wuARYhezORu7nI3lxkDzur1KxQ06dPV1ZWlj799FNt3rxZmzdv1l/+8hdlZmZqxowZVV0jyik6mpkiTEX2ZiJ3c5G9ucgedlapxmLdunWaPHmyWrdu7V3Wpk0bTZ48Wd98802VFQcAAACgdqhUY+F2uxUWFlZkeWhoqNxuPrgFAAAAME2lGov/9//+n5599lmdPHnSu+zkyZNKSkpSQkJClRUHAAAAoHao1MPbzzzzjEaPHq3rr79eTZo0kST997//Vdu2bfXCCy9UaYEov8zMPKtLgEXI3kzkbi6yNxfZw84q1Vg0bdpUq1ev1oYNG3Tw4EFJUuvWrdWjR48qLQ4VExwcxGwRhiJ7M5G7ucjeXGQPO6vQrVDJycnq16+fMjMzFRQUpJ49e2ro0KEaOnSoOnXqpP79+2vLli3VVSvKEBXlsLoEWITszUTu5iJ7c5E97KxCjcXbb7+tu+++W9HR0UVeq1u3ru655x4tWbKkyooDAAAAUDtUqLHYu3evevXqVeLrPXv21K5du/wuCgAAAEDtUqHGIi0tTaGhJT+WERoaqoyMDL+LQuV4uOXSWGRvJnI3F9mbi+xhZxVqLBo3bqx9+/aV+PrevXvVsGFDv4tC5WRlMVOEqcjeTORuLrI3F9nDzirUWPTp00cvvfSS8vKK/lDn5uZqwYIFuu6666qsOFRMSEilPpYEAYDszUTu5iJ7c5E97KxC082OHj1af/vb33TTTTdp8ODBatWqlSTp4MGDeu+99+RyuTRq1KhqKRRli4wMY35rQ5G9mcjdXGRvLrKHnVWosYiJidGKFSs0ZcoUzZ07V57/u9EvKChIiYmJeuaZZxQTE1MthQIAAACwrwp/QF7z5s21aNEinT59WkeOHJEkXX755apXr16VFwcAAACgdqjUJ29LUr169dS5c+eqrAV+4pM4zUX2ZiJ3c5G9ucgedsYTQAEkO9tpdQmwCNmbidzNRfbmInvYGY1FAAkNDbG6BFiE7M1E7uYie3ORPeyMxiKARERU+s421HJkbyZyNxfZm4vsYWc0FgAAAAD8RmMBAAAAwG80FgHE5XJbXQIsQvZmIndzkb25yB52RmMRQHJy8q0uARYhezORu7nI3lxkDzujsQggDgczRZiK7M1E7uYie3ORPeyMxiKAOBzMFGEqsjcTuZuL7M1F9rAzGgsAAAAAfqOxAAAAAOA3GosAkp/vsroEWITszUTu5iJ7c5E97IzGIoDk5RVYXQIsQvZmIndzkb25yB52RmMRQMLDeaDLVGRvJnI3F9mbi+xhZzQWASQsjCnoTEX2ZiJ3c5G9ucgedkZjAQAAAMBvNBYAAAAA/EZjEUCcTh7oMhXZm4nczUX25iJ72BmNRQBxOpmCzlRkbyZyNxfZm4vsYWc0FgEkMjLM6hJgEbI3E7mbi+zNRfawMxqLABISQpymInszkbu5yN5cZA8746cTAAAAgN9oLAAAAAD4jcYigOTmMlOEqcjeTORuLrI3F9nDzmgsAkhBATNFmIrszUTu5iJ7c5E97IzGIoBERTmsLgEWIXszkbu5yN5cZA87o7EIIMHBQVaXAIuQvZnI3Vxkby6yh52FWl0AAADlcexYijIy0ot9rX79BmrRomUNVwQAKIzGAgBge8eOpahHz2uUm5Nd7OsRkVHa8O13NBcAYCEaiwCSk5NvdQmwCNmbyaTcMzLSlZuTrbtnvKZGrdr6vPbToX1aOWm0MjLSjWksTMoevsgedkZjEUBcLrfVJcAiZG8mE3Nv1KqtmnfoYnUZljMxe5xD9rAzHt4OIHXqhFtdAixC9mYid3ORvbnIHnZmaWPx3XffadSoUUpMTFRsbKy++OILn9c9Ho9eeuklJSYmqnPnzho+fLgOHz7ss86pU6f01FNPqWvXrurWrZsmTpyorKwsn3X27Nmj+++/X506dVKfPn20aNGiIrV89tlnuvnmm9WpUyfddttt+vrrr6t8vNUtiIkijEX2ZiJ3c5G9ucgedmZpY5Gdna3Y2FhNnjy52NcXLVqkd955R1OmTNHKlSsVGRmpESNGKC8vz7vO//7v/2r//v1asmSJXn/9dW3ZskXPPPOM9/XMzEyNGDFCzZo106pVqzR+/Hi9/PLLev/9973rfP/993rqqad05513as2aNbr++uv12GOP6ccff6y+wQMAAAABxNLGok+fPvrNb36jG2+8schrHo9Hy5Yt0+jRo3XDDTeoffv2ev755/XTTz95r2wcOHBA69at04wZM9SlSxd169ZNkyZN0qeffqqTJ09Kkj7++GPl5+dr5syZatu2rfr376+hQ4dqyZIl3n0tW7ZMvXr10sMPP6zWrVvrySef1JVXXql33323Zr4RAAAAQC1n22csjh07ptTUVPXo0cO7rG7duurSpYu2bdsmSdq2bZsuueQSderUybtOjx49FBwcrB07dkiStm/frm7dusnhuPBJlYmJiTp06JBOnz7tXSchIcFn/4mJidq+fXt1Da9aZGc7rS4BFiF7M5G7ucjeXGQPO7NtY5GamipJatCggc/yBg0aKC0tTZKUlpam+vXr+7weGhqqevXqed+flpammJgYn3XOf114OxevU3g/tYXb7bG6BFiE7M1E7uYie3ORPeyM6WarWOHZGvLzXcrLK1B4eKjCwkK8y53OAjmdLkVGhikk5EJvl5tboIICl6KiHAoOvvB0Vk5Ovlwut+rUCfd5aCs72ym326Po6HP7DAsLUX6+S5mZeQoODlJU1IWrNB6PlJWVp5CQYEVGhnmXu90eZWc7FRoaooiICz8OLpdbOTn5cjhC5HBcWF7TYzqPMZU+pksuifD5zyYQxhSIOVX1mM7/zgfSmM67eEyRkRdqLUlQUJDPWO0+pvMqk1PduhHyeC78zgfCmAIxp+oYU1hYiLKy8gJqTFLg5VSZMQUHl36+PzLS4TMuK8ZUFts2Fg0bNpQkpaenq1GjRt7l6enpat++vaRzVx4yMjJ83ldQUKDTp0973x8TE1PkysP5r89fpShunfT09CJXMcojKytPnotOJuTlFSgvr6DIuiV9yE1JlzmzsvKKXZ6ZeW55dHS49+9ut8f798JcLnexywsKXMrMdBVZ7nS65HQWXV5TYyqMMZU8ppK2U5vHFIg5VfWYCv/OS4ExpoudH1NOTtm3f3g8tWtMF6tITiWNtTaPKRBzqo4xRUeHe9cJlDEVZvKY3O7SP6MkJ8dZpM6aGJPTWVCukzuSjW+FatGihRo2bKjk5GTvsszMTP3www+Kj4+XJMXHx+vMmTPauXOnd52NGzfK7Xarc+fOkqS4uDht2bJF+fkXQt2wYYNatWqlevXqedfZuHGjz/43bNiguLi46hoeAAAAEFAsbSyysrK0e/du7d69W9K5B7Z3796tEydOKCgoSMOGDdNrr72mL7/8Unv37tX48ePVqFEj3XDDDZKk1q1bq1evXvrjH/+oHTt2aOvWrZo+fbr69++vxo0bS5Juu+02hYWF6emnn9a+ffu0du1aLVu2TA8++KC3jmHDhmndunV66623dODAAS1YsEA7d+7UkCFDav6bAgAAANRClt4KtXPnTg0bNsz7dVJSkiRp4MCBmjVrlh555BHl5OTomWee0ZkzZ3T11VfrzTffVHj4hfvLZs+erenTp+uBBx5QcHCwfvWrX2nSpEne1+vWravFixdr2rRpGjRokC699FKNGTNG99xzj3edrl27avbs2Zo3b57mzp2rK664Qq+88oratWtXA9+FqlPcJS+YgezNRO7mIntzkT3szNLGonv37tq7d2+JrwcFBemJJ57QE088UeI6v/jFLzRnzpxS99O+fXu99957pa5zyy236JZbbim9YJsLDg5itghDkb2ZyN1cZG8usoed2fYZC1Rc4VkBYBayNxO5m4vszUX2sDMaCwAAAAB+o7EAAAAA4DcaiwBy8ednwBxkbyZyNxfZm4vsYWc0FgGkpA+JQeAjezORu7nI3lxkDzujsQgghT8uHmYhezORu7nI3lxkDzvjpzOAREaGWV0CLEL2ZiJ3c5G9ucgedkZjAQAAAMBvNBYAAAAA/EZjEUD4JE5zkb2ZyN1cZG8usoed0VgEkOxsp9UlwCJkbyZyNxfZm4vsYWc0FgEkNDTE6hJgEbI3E7mbi+zNRfawMxqLABIREWp1CbAI2ZuJ3M1F9uYie9gZjQUAAAAAv9FYAAAAAPAbjUUAcbncVpcAi5C9mcjdXGRvLrKHndFYBJCcnHyrS4BFyN5M5G4usjcX2cPOaCwCiMPBTBGmInszkbu5yN5cZA87o7EIIA4HM0WYiuzNRO7mIntzkT3sjMYCAAAAgN9oLAAAAAD4jcYigOTnu6wuARYhezORu7nI3lxkDzujsQggeXkFVpcAi5C9mcjdXGRvLrKHndFYBJDwcB7oMhXZm4nczUX25iJ72BmNRQAJC2MKOlORvZnI3Vxkby6yh53RWAAAAADwG40FAAAAAL/RWAQQp5MHukxF9mYid3ORvbnIHnZGYxFAnE6moDMV2ZuJ3M1F9uYie9gZjUUAiYwMs7oEWITszUTu5iJ7c5E97IzGIoCEhBCnqcjeTORuLrI3F9nDzvjpBAAAAOA3GgsAAAAAfqOxCCC5ucwUYSqyNxO5m4vszUX2sDMaiwBSUMBMEaYiezORu7nI3lxkDzujsQggUVEOq0uARcjeTORuLrI3F9nDzmgsAkhwcJDVJcAiZG8mcjcX2ZuL7GFnNBYAAAAA/EZjAQAAAMBvNBYBJCcn3+oSYBGyNxO5m4vszUX2sDMaiwDicrmtLgEWIXszkbu5yN5cZA87o7EIIHXqhFtdAixC9mYid3ORvbnIHnZGYxFAgpgowlhkbyZyNxfZm4vsYWc0FgAAAAD8RmMBAAAAwG80FgEkO9tpdQmwCNmbidzNRfbmInvYGY1FAHG7PVaXAIuQvZnI3Vxkby6yh53RWASQ6GhmijAV2ZuJ3M1F9uYie9gZjQUAAAAAv9FYAAAAAPBbqNUFAAAAoHTHjqUoIyNdkZEO5eT4PsBdv34DtWjR0qLKgAtoLAJIZmae1SXAImRvJnI3F9mb5dixFPXoeY1yc7KLfT0iMkobvv2O5gKWo7EIIMHBQcwWYSiyNxO5m4vszZKRka7cnGzdPeM1NWrV1ue1nw7t08pJo5WRkU5jAcvRWASQqCgHZ7EMRfZmIndzkb2ZGrVqq+YdulhdBlAiHt4GAAAA4DcaCwAAAAB+o7EIIB5utzUW2ZuJ3M1F9gDsiMYigGRlcb+tqcjeTORuLrIHYEc0FgEkJIQ4TUX2ZiJ3c5E9ADuy9b9MCxYsUGxsrM+fm2++2ft6Xl6epk6dqu7duys+Pl6PP/640tLSfLZx4sQJPfroo+rSpYsSEhL03HPPqaCgwGedTZs2aeDAgerYsaNuvPFGrVq1qkbGV9UiI8OsLgEWIXszkbu5yB6AHdl+utm2bdtqyZIl3q9DQkK8f585c6a+/vprzZs3T3Xr1tX06dM1duxYrVixQpLkcrk0cuRIxcTEaMWKFfrpp5/0+9//XmFhYfrtb38rSUpJSdHIkSN17733avbs2UpOTtakSZPUsGFD9erVq2YHCwAAANRStm8sQkJC1LBhwyLLz549qw8//FCzZ89WQkKCpHONRr9+/bR9+3bFxcVp/fr12r9/v5YsWaKYmBh16NBBTzzxhGbPnq2xY8fK4XBoxYoVatGihSZMmCBJat26tbZu3aqlS5fSWAAAAADlZPvG4siRI0pMTFR4eLji4uL01FNPqVmzZtq5c6fy8/PVo0cP77qtW7dWs2bNvI3F9u3b1a5dO8XExHjXSUxM1JQpU7R//35deeWV2r59u7cxKbzOzJkza2yMVYVPYTUX2ZuJ3M1F9jXv2LEUZWSkF/ta/foN+NTrasb3v3awdWPRuXNnJSUlqVWrVkpNTdUrr7yiwYMH65NPPlFaWprCwsJ0ySWX+LynQYMGSk1NlSSlpaX5NBWSvF+XtU5mZqZyc3MVERFRoZrr1An3/j0/36W8vAKFh4cqLOzCLVxOZ4GcTpciI8N8HsDLzS1QQYFLUVEOBQcHeZfn5OTL5XKrTp1wBV1YrOxsp9xuj6KjL+wzOjpcmZl5Cg4OUlSUw7vc4zk3i0hISLDPvblut0fZ2U6FhoYoIuLCj4PL5VZOTr4cjhA5HBeWWzEmSYypjDEVFLh8th8IYwrEnKpjTNHR4QE3JqloTpGRF2otSVBQkM9Y7T6m8yqTU15egc/6gTAmO+eUknJUPXpeo9ycbBUnIjJKP2z/QS1bXlYtYyo8npJERjoUGhoSkDkdPnxYPROvUU528d//yKgobd927vtfW8ZUXE7BwaU/+hwZ6fAZlxVjKoutG4s+ffp4/96+fXt16dJF1113nT777LMKH/DXlKysvCLzi+flFSgvr6DIujk5+cVuIzvbWeK2i5OZeW75+X9QpHM/QOeXF+ZyuYtdXlDgUmamq8hyp9Mlp7Po8poaU2GMqeQxud3Fb782jykQc6rqMRX+nZcCY0wXOz+mnJziXy/M46ldY7pYRXIKCgoKuDHZOaeUlP8oNydbd894TY1atfVZ76dD+7Ry0milpPxHl17auFrGlJ9fdNnFcnKc3n8PAi2njIx05WRX7Ptv9zFJRXNyu93FrndhO84iddbEmJzOgnKd3JFs3lhc7JJLLtEVV1yho0ePqkePHsrPz9eZM2d8rlqkp6d7n8mIiYnRjh07fLZxftaowutcPJNUWlqaoqOjbdu8lCQiIrTYHxYEPrI3E7mbi+yt0ahVWzXv0MXqMozF99/+bD3d7MWysrKUkpKihg0bqmPHjgoLC1NycrL39YMHD+rEiROKi4uTJMXFxenHH39UevqFe/I2bNig6OhotWnTxrvOxo0bffazYcMG7zYAAAAAlM3WjcVzzz2nzZs369ixY/r+++81duxYBQcH69Zbb1XdunV1xx13aNasWdq4caN27typiRMnKj4+3tsUJCYmqk2bNho/frz27NmjdevWad68eRo8eLAcjnOXdO69916lpKTo+eef14EDB7R8+XJ99tlnGj58uHUDBwAAAGoZW98K9d///le//e1vderUKdWvX19XX321Vq5cqfr160uSJk6cqODgYI0bN05Op1OJiYmaPHmy9/0hISF6/fXXNWXKFN1zzz2KjIzUwIEDNW7cOO86LVu21MKFC5WUlKRly5apSZMmmjFjRq2catblKv3ePAQusjcTuZuL7AHYka0bixdffLHU18PDwzV58mSfZuJizZs316JFi0rdTvfu3bVmzZrKlGgrJT0chMBH9mYid3ORPQA7svWtUKgYh6P804EhsJC9mcjdXGQPwI5oLAJI4fmHYRayNxO5m4vsAdgRjQUAAAAAv3HKAwAA2N6xYynKyEgv9rX69RuoRYuWNVwRgIvRWASQ8nwyJwIT2ZuJ3M1lWvbHjqWoR89rlJuTXezrEZFR2vDtdzQXgMVoLALIgQOHij2bw5mcwJeXV2B1CbAAuZvLtOwzMtKVm5Otu2e8pkat2vq89tOhfVo5abQyMtL5vw6wGI1FgDh2LEU9e16jnGLO5nAmJ/CFh4cad6ABcjeZqdk3atVWzTt0sboMACWgsQgQGRnpyinmbA5ncswQFhZi5EGG6cjdXGQPwI5oLAIMZ3MAAABgBaabBQAAAOA3GgsgADid3BJhInI3F9kDsCMaCyAAOJ1mTT2Jc8jdXGQPwI54xgIIAJGRYcrJybe6DFSziz8grPDMQEwrbRZ+5wHYEY0FEABCQsy4+GjyJ+/yAWEozJTfeQC1C40FgFrB9ANrPiAMAGB3NBYAagUOrM9hSmkAgF3RWAABIDfXnBliOLAGzPqdB1B70FgAAaCggBligEBn8jNGAGoHGgsgAERFOZSd7bS6DADVxPRnjADUDjQWQAAIDg6yugQA1YhnjADUBjQWQC1S0q0QkZEORUbW5aACCHA8YwTAzmgsgFqCWyEAAICd0VgAtQS3QgAAADujsQBqGW6FAAAAdhRsdQEAAAAAaj8aCwAAAAB+o7EAAAAA4DcaCwAAAAB+o7EAAAAA4DcaCwAAAAB+o7EAAAAA4DcaCwAAAAB+o7EAAAAA4DcaCwAAAAB+C7W6AKAijh1LUUZGerGv1a/fQC1atKzhigAAACDRWKAWOXYsRT16XqPcnOxiX4+IjNKGb7+juQAAALAAjQVqjYyMdOXmZOvuGa+pUau2Pq/9dGifVk4arYyMdBoLAAAAC9BYoNZp1KqtmnfoYnUZAADAENyKXT40FgAAACiVyQfW3IpdfjQWAAAAKJHpB9bcil1+NBYAAAAoEQfW53ArdtloLACgnEy+FQAAOLBGWWgsAKAcTL8VAACAstBYAEA5cCuA/e3bt7fIMq4k1T7FXRksLlsA9kNjAQAVwK0A9nM27aSCgoM1evQjRV7jSlLtUtaVQQD2RmMBVAD32APVr6JnrHPOnpHH7S5yNYkrSbVPSVcG9377pf7+apKFldUcrtigNqOxAMqJe+yB6ufPGWuuJlWvmjyxcnGWPx3aV2XbtjM7XLGxurGxev/wD40FUE7cYw9UP85Y2xMnVmqG1T//Vjc2Vu8f/qOxACqIs6JA9TP1jLVdcWKlZlXm578qJi+wurGxev/wH40FgIDBrEBA9eLEiv1Ux+QFVjf2VjVW8B+NBYBaj1mBagaTF8DOTD2wrK2TF1TVsxT8+28vNBYAar3a+h9rSSr7H251Hlhxjz2NlV1xYHlORa8mWfmQdFU+S1Fb//0P1IfUaSwABIyq+I9VsvYgsTL/4dbEgZXp99jTWJXNqisGZR1Ybtq0QRkZseWurSoP+EprRvPy8hQeHl4l+ylNcds8efKkRowYptzcnCrfX3lUx7MUJf37X9L3tKrzL26d4jKWrP/+VycaC1QIZ+zszdRbASqjtANFKw8SK/Mfbk2esavKe+xr6oxdRQ8silOTjZUdr1iVxi5XDC7+2SytrpJqq8oz6WVtKyg4WB632+/9lKSs8Uuy/CHp6nyWo6zxh4dH6K233lHjxo29yypzwF/afsrK2Orvf3WgsUC5ccaubKb/x15VqvqAs7j37tu3t9gDxZLOclbHgV1p46zMf7i16cHamphWsjIHlmWp7u+xXa9YlaayjW11N5Yl1VVabVV5Jr20ZvT89qrzwLK08Z/fT1Ue2FfkjH1N3PJT2vgPbduktXP/qMGD7yr2vVVxYqekjAu/ZvVD8tWBxgLlZvqtEKWp6v/Yq/qThyt6K0BlVNVtRVV5wFmeM3YVPctZ0f0Ud1ZMqtlL4TV1K0BxSvq5KKmxq6kDq9J+N2rqKl9J3+eqvmJV0u9/SQd9lR1/RW5Fqcmf/9KawYtr86exL++2Cm+vJg4sS9t/VfDnjH1NKGn8pTUDVXFip6SMy7u92orGAhVm57Oidr3HtyJn7Pz5D7cqbgWojMreVlRVB1YlKc8Zu/K+pzIHdmWdFZOq91J4Td0KcN7Fv3/l2ZZVB1YVbQar+opVWQ10VRzYlJV/SQd9lR3/xex8K05lTiDUxLZqI3/O2FstEK8YWI3GAgGhMmeMpZLP2FX2obqqPGNX3QfWpZ3NrOiZzJKuZpW2j7LGX5X/4FfmjFFVnbGqyVsRLlZTtwKUdWBlxwMLf5rBi1Xm3x+rr9iUdNBXmfH7s3+rDuwqcwKhJrZVm3HGHhKNRRHLly/X4sWLlZqaqvbt2+uPf/yjOnfubHVZxqmqW4HK+k+ypDN2VXX51p8zdtV9YF2Zy9elHSQVtx87n7GsSVb/x1rdtwKUdWBl9fhLU95msLquWFl9K0xVjN+f/VutOv+dtcsYgZpEY1HI2rVrlZSUpKlTp6pLly56++23NWLECH3++edq0KCB1eVVi5Luf67sGfuKPLxV0mtVeStQec4Yl/fybXXdimPXM3ZVcSbTzuPHORxYFa+mrljZVSBlCaDm0FgUsmTJEt1999264447JElTp07VV199pQ8//FCPPvqoxdX5p6K34lT0jH1lH94q7bWaOmNW3su3NX0rTk2pyPgre5Bk5/ED1Y2ffwCmoLH4P06nU7t27dLIkSO9y4KDg9WjRw9t27bNwsr848+tKDU13VpN3AqEqsNBEgAAKA6Nxf/5+eef5XK5itzy1KBBAx08eLDc2wkKqurKyickJER169bV2eOHlR4a4l1+6sg+Rdepo94PjNUvmjT3ec+xXdv1/V/eV6QjTBGF3hMVEa66deuWuPzifUhSXsbJUt9z8fLK7Of8Pkrbf3W+h/2zf/bP/tk/+2f/7L+m93/2+GHVrVtXISEhlhxnVmSfQR6Px1N9pdQeJ0+eVO/evbVixQrFx8d7lz///PP67rvv9MEHH1hYHQAAAGBvwVYXYBeXXnqpQkJClJ7u+yBzenq6YmJiLKoKAAAAqB1oLP6Pw+HQVVddpeTkZO8yt9ut5ORknysYAAAAAIriGYtCHnzwQf3+979Xx44d1blzZ7399tvKycnRoEGDrC4NAAAAsDUai0L69eunjIwMzZ8/X6mpqerQoYPefPNNboUCAAAAysDD2wAAAAD8xjMWAAAAAPxGYwEAAADAbzQWAAAAAPxGYwEAAADAbzQWtcjy5cvVt29fderUSXfddZd27NhR6vqfffaZbr75ZnXq1Em33Xabvv766xqqFFWpIrmvXLlS999/v6655hpdc801Gj58eJk/J7Cviv7On/fpp58qNjZWY8aMqeYKUV0qmv2ZM2c0depUJSYmqmPHjrrpppv4N7+Wqmj2S5cu1U033aTOnTurT58+mjlzpvLy8mqoWlSF7777TqNGjVJiYqJiY2P1xRdflPmeTZs2aeDAgerYsaNuvPFGrVq1qgYqLRuNRS2xdu1aJSUl6bHHHtPq1avVvn17jRgxosgnhZ/3/fff66mnntKdd96pNWvW6Prrr9djjz2mH3/8sYYrhz8qmvumTZvUv39/LVu2TCtWrFDTpk310EMP6eTJkzVcOfxV0ezPO3bsmJ577jl169athipFVato9k6nUw8++KCOHz+ul156SZ9//rmmT5+uxo0b13Dl8FdFs//kk080Z84cjR07VmvXrtWzzz6rtWvXau7cuTVcOfyRnZ2t2NhYTZ48uVzrp6SkaOTIkerevbs++ugjPfDAA5o0aZLWrVtXzZWWgwe1wp133umZOnWq92uXy+VJTEz0LFy4sNj1n3jiCc+jjz7qs+yuu+7y/PGPf6zWOlG1Kpr7xQoKCjzx8fGe1atXV1OFqC6Vyb6goMBzzz33eFauXOn5/e9/7xk9enRNlIoqVtHs33vvPc/111/vcTqdNVUiqklFs586dapn2LBhPsuSkpI89957b7XWierTrl07z9///vdS13n++ec9/fv391n25JNPeh566KHqLK1cuGJRCzidTu3atUs9evTwLgsODlaPHj20bdu2Yt+zfft2JSQk+CxLTEzU9u3bq7NUVKHK5H6xnJwcFRQUqF69etVVJqpBZbN/5ZVX1KBBA9111101USaqQWWy/8c//qG4uDhNmzZNPXr00K233qrXX39dLperpspGFahM9vHx8dq1a5f3dqmUlBR9/fXX6tOnT43UDGvY+RiPT96uBX7++We5XC41aNDAZ3mDBg108ODBYt+TlpZW5BPDGzRooLS0tGqrE1WrMrlfbPbs2WrUqJHPf1Swv8pkv2XLFv35z3/WmjVraqBCVJfKZJ+SkqKNGzfqtttu0xtvvKGjR49q6tSpKigo0NixY2uibFSBymR/22236eeff9b9998vj8ejgoIC3XvvvRo1alRNlAyLFHeMFxMTo8zMTOXm5ioiIsKiynjGAghYb7zxhtauXauXX35Z4eHhVpeDapSZmanx48dr+vTpql+/vtXloIZ5PB41aNBA06dPV8eOHdWvXz+NGjVKK1assLo0VLNNmzZp4cKFmjx5slatWqWXX35ZX3/9tV555RWrS4OhuGJRC1x66aUKCQkp8vBWenp6kY71vJiYmCJXJ0pbH/ZTmdzPW7x4sd544w0tWbJE7du3r84yUQ0qmn1KSoqOHz+u0aNHe5e53W5J0pVXXqnPP/9cl112WfUWjSpRmd/7hg0bKjQ0VCEhId5lv/zlL5Wamiqn0ymHw1GtNaNqVCb7l156SQMGDPDe/hgbG6vs7Gw988wzGj16tIKDOX8ciIo7xktLS1N0dLSlVyskrljUCg6HQ1dddZWSk5O9y9xut5KTkxUfH1/se+Li4rRx40afZRs2bFBcXFx1looqVJncJWnRokV69dVX9eabb6pTp041USqqWEWz/+Uvf6lPPvlEa9as8f7p27evunfvrjVr1qhJkyY1WT78UJnf+65du+ro0aPeZlKSDh8+rIYNG9JU1CKVyT43N7dI83C+wfR4PNVXLCxl52M8Gota4sEHH9TKlSu1evVqHThwQFOmTFFOTo4GDRokSRo/frzmzJnjXX/YsGFat26d3nrrLR04cEALFizQzp07NWTIEKuGgEqoaO5vvPGGXnrpJc2cOVPNmzdXamqqUlNTlZWVZdUQUEkVyT48PFzt2rXz+XPJJZeoTp06ateuHQeXtUxFf+/vu+8+nTp1Ss8++6wOHTqkr776SgsXLtTgwYOtGgIqqaLZX3fddfrTn/6kTz/9VCkpKfr222/10ksv6brrrvO5ggV7y8rK0u7du7V7925J56YN3717t06cOCFJmjNnjsaPH+9d/95771VKSoqef/55HThwQMuXL9dnn32m4cOHW1G+D26FqiX69eunjIwMzZ8/X6mpqerQoYPefPNN7+XR//znPz5nLbp27arZs2dr3rx5mjt3rq644gq98sorateunVVDQCVUNPcVK1YoPz9f48aN89nO2LFj9fjjj9do7fBPRbNH4Kho9k2bNtXixYuVlJSkAQMGqHHjxho2bJgeeeQRq4aASqpo9qNHj1ZQUJDmzZunkydPqn79+rruuuv0m9/8xqohoBJ27typYcOGeb9OSkqSJA0cOFCzZs1Samqq/vOf/3hfb9mypRYuXKikpCQtW7ZMTZo00YwZM9SrV68ar/1iQR6ulQEAAADwE6e7AAAAAPiNxgIAAACA32gsAAAAAPiNxgIAAACA32gsAAAAAPiNxgIAAACA32gsAAAAAPiNxgIAAACA32gsAADVYtWqVerWrZv36wULFuj222+3sKKSbdq0SbGxsTpz5ky532Pn8QCAFWgsAAA14qGHHtLSpUutLqNY8fHxWr9+verWrVul2x06dKieffbZKt0mANhVqNUFAADMUKdOHdWpU8fqMorlcDjUsGFDq8sAgFqNKxYAAH3zzTe677771K1bN3Xv3l0jR47U0aNHJRV/m9Du3bsVGxurY8eOeZetWrVK//M//6MuXbroscce06lTp3z2cfGtQ263Wy+//LJ69+6tjh076vbbb9c333xTrnrHjRunadOmeb9+9tlnFRsbqwMHDkiSnE6n4uLitGHDBu++Fi5cqL59+6pz584aMGCAPv/8c+/7ixvjypUr1adPH+94lixZ4nNr13lr1qxR3759dfXVV+s3v/mNMjMzJUkTJkzQ5s2btWzZMsXGxhb5fgFAoKGxAAAoJydHDz74oD788EMtXbpUQUFBeuyxx+R2u8v1/h9++EFPP/20Bg8erDVr1qh79+567bXXSn3PsmXLtGTJEv3+97/Xxx9/rMTERI0ZM0aHDx8uc3/XXHONNm/e7P36u+++06WXXupd9q9//UsFBQWKj4+XJC1cuFBr1qzR1KlT9emnn2r48OH63e9+57ONwrZu3arJkydr2LBhWrNmjXr06KHXX3+9yHpHjx7Vl19+qddff10LFy7Ud999p0WLFkmSnn76acXHx+vuu+/W+vXrtX79ejVt2rTMsQFAbcWtUAAA3XTTTT5fz5w5UwkJCdq/f3+53r9s2TL16tVLjzzyiCSpVatW2rZtm9atW1fiexYvXqxHHnlE/fv3lyT97ne/06ZNm/T2229r8uTJpe7v2muv1bPPPquMjAyFhIRo//79GjNmjDZv3qz77rtPmzdvVseOHRUZGSmn06mFCxdqyZIl3kajZcuW2rp1q95//31de+21Rbb/7rvvqnfv3hoxYoTPeL766iuf9Twej5KSkhQdHS1JGjBggJKTk/Wb3/xGdevWVVhYmCIiIrjNCoARaCwAADp8+LDmz5+vH374QT///LM8Ho8k6T//+Y8iIiLKfP+BAwd0ww03+CyLi4srsbHIzMzUTz/9pK5du/os79q1q/bs2VPm/tq1a6d69epp8+bNCgsL05VXXqnrrrtO7733nqRzVzC6d+8uSTpy5IhycnL00EMP+WwjPz9fHTp0KHb7hw4dKjKezp07F2ksmjdv7m0qJKlRo0ZKT08vs34ACEQ0FgAAjRo1Ss2bN9eMGTPUqFEjud1u3XrrrcrPz1dUVJQkeZsN6dxBuZWCgoK8t0M5HA5de+21io2NldPp1I8//qht27Z5G4ns7GxJ526Haty4sc92HA6HX3WEhhb9b7Tw9wkATMIzFgBguJ9//lmHDh3S6NGjlZCQoNatW+v06dPe1+vXry9JSk1N9S67+KpC69attWPHDp9lP/zwQ4n7jI6OVqNGjfT999/7LP/+++/Vpk2bctV9vrHYvHmzrr32WgUHB6tbt25avHixnE6n92pI69at5XA4dOLECV1++eU+f0p65qFVq1bauXOnz7J//etf5aqrsLCwsHI/pwIAtR2NBQAYrl69evrFL36h999/X0eOHFFycrJmzZrlff2yyy5T06ZNtWDBAh0+fFhfffWV3nrrLZ9tDB06VOvWrdPixYt1+PBhvfvuu6U+XyFJI0aM0KJFi7R27VodPHhQs2fP1p49ezRs2LBy1d29e3ft379f+/bt09VXXy3p3LMXn3zyiTp27Oi90hIdHa2HHnpISUlJWr16tY4ePapdu3bpnXfe0erVq4vd9pAhQ/T1119ryZIlOnz4sFasWKFvvvlGQUFB5artvObNm+uHH37QsWPHlJGRQZMBIKDRWACA4YKDg/Xiiy9q165duvXWW5WUlKTx48d7Xw8LC9OcOXN08OBBDRgwQIsWLdKTTz7ps424uDhNnz5dy5Yt0+23367169dr9OjRpe532LBhevDBBzVr1iwNGDBA69at06uvvqorrriiXHW3a9dOl1xyiTp06OD9fIzu3bvL5XIVeSD7ySef1JgxY7Rw4UL169dPDz/8sL766iu1aNGi2G1fffXVmjp1qpYsWaLbb79d69at0/DhwxUeHl6u2s576KGHFBISov79+yshIUEnTpyo0PsBoDYJ8nAzKAAAZZo0aZIOHjzofUAcAOCLKxYAABRj8eLF2rNnj44cOaJ33nlHa9as0cCBA60uCwBsiysWAADbOf+Bc8W5+uqr9eabb1Z7DU888YQ2b96srKwstWzZUkOGDNF9991X7fsFgNqKxgIAYDunTp3ymZmqsIiIiCLTxgIArEdjAQAAAMBvPGMBAAAAwG80FgAAAAD8RmMBAAAAwG80FgAAAAD8RmMBAAAAwG80FgAAAAD8RmMBAAAAwG80FgAAAAD89v8BO7010sFdD/4AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8, 5))\n",
    "df_total[\"audio_weight\"].hist(bins=np.linspace(0, 1, 100), color=\"skyblue\", edgecolor=\"black\")\n",
    "print_percentiles(df_total[\"audio_weight\"])\n",
    "plt.title(\"Distribution of audio_weight\")\n",
    "plt.xlabel(\"audio_weight\")\n",
    "plt.ylabel(\"Counts\")\n",
    "plt.grid(True, linestyle=\"--\", alpha=0.6)\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fetch other parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.15"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
