{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport math\nimport time\nimport librosa\nimport pandas as pd\nimport numpy as np\nfrom tqdm.notebook import tqdm\n\nimport torch\nimport matplotlib.pyplot as plt\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Config:\n \n    DEBUG_MODE = False\n    \n    OUTPUT_DIR = '/kaggle/working/'\n    DATA_ROOT = '/kaggle/input/birdclef-2025'\n    FS = 32000\n    \n    N_FFT = 2048 \n    HOP_LENGTH = 512\n    N_CHROMA = 12 \n    \n    FMIN = 50 \n    BINS_PER_OCTAVE = 36 \n    \n    TARGET_DURATION = 5.0\n    TARGET_SHAPE = (256, 256)  \n    \n    N_MAX = 50 if DEBUG_MODE else None  ","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"config = Config()\nprint(f\"Debug mode: {'ON' if config.DEBUG_MODE else 'OFF'}\")\nprint(f\"Max samples to process: {config.N_MAX if config.N_MAX is not None else 'ALL'}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Loading taxonomy data...\")\ntaxonomy_df = pd.read_csv(f'{config.DATA_ROOT}/taxonomy.csv')\nspecies_class_map = dict(zip(taxonomy_df['primary_label'], taxonomy_df['class_name']))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Loading training metadata...\")\ntrain_df = pd.read_csv(f'{config.DATA_ROOT}/train.csv')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_list = sorted(train_df['primary_label'].unique())\nlabel_id_list = list(range(len(label_list)))\nlabel2id = dict(zip(label_list, label_id_list))\nid2label = dict(zip(label_id_list, label_list))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f'Found {len(label_list)} unique species')\nworking_df = train_df[['primary_label', 'rating', 'filename']].copy()\nworking_df['target'] = working_df.primary_label.map(label2id)\nworking_df['filepath'] = config.DATA_ROOT + '/train_audio/' + working_df.filename\nworking_df['samplename'] = working_df.filename.map(lambda x: x.split('/')[0] + '-' + x.split('/')[-1].split('.')[0])\nworking_df['class'] = working_df.primary_label.map(lambda x: species_class_map.get(x, 'Unknown'))\ntotal_samples = min(len(working_df), config.N_MAX or len(working_df))\nprint(f'Total samples to process: {total_samples} out of {len(working_df)} available')\nprint(f'Samples by class:')\nprint(working_df['class'].value_counts())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def audio2chromagram(audio_data):\n    if np.isnan(audio_data).any():\n        mean_signal = np.nanmean(audio_data)\n        audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n\n    # Generate constant-Q chromagram\n    chromagram = librosa.feature.chroma_cqt(\n        y=audio_data,\n        sr=config.FS,\n        hop_length=config.HOP_LENGTH,\n        fmin=config.FMIN,\n        n_chroma=config.N_CHROMA,\n        bins_per_octave=config.BINS_PER_OCTAVE\n    )\n    \n    eps = 1e-6\n    chroma_log = np.log(chromagram + eps)\n    chroma_norm = (chroma_log - chroma_log.min()) / (chroma_log.max() - chroma_log.min() + eps)\n    \n    return chroma_norm","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Starting audio processing for chromagrams...\")\nprint(f\"{'DEBUG MODE - Processing only 50 samples' if config.DEBUG_MODE else 'FULL MODE - Processing all samples'}\")\nstart_time = time.time()\n\nall_bird_data = {}\nerrors = []\n\nfor i, row in tqdm(working_df.iterrows(), total=total_samples):\n    if config.N_MAX is not None and i >= config.N_MAX:\n        break\n    \n    try:\n        audio_data, _ = librosa.load(row.filepath, sr=config.FS)\n\n        target_samples = int(config.TARGET_DURATION * config.FS)\n\n        if len(audio_data) < target_samples:\n            n_copy = math.ceil(target_samples / len(audio_data))\n            if n_copy > 1:\n                audio_data = np.concatenate([audio_data] * n_copy)\n\n        start_idx = max(0, int(len(audio_data) / 2 - target_samples / 2))\n        end_idx = min(len(audio_data), start_idx + target_samples)\n        center_audio = audio_data[start_idx:end_idx]\n\n        if len(center_audio) < target_samples:\n            center_audio = np.pad(center_audio, \n                                 (0, target_samples - len(center_audio)), \n                                 mode='constant')\n\n        chromagram = audio2chromagram(center_audio)\n\n        if chromagram.shape != config.TARGET_SHAPE:\n            chromagram = cv2.resize(chromagram, config.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n\n        all_bird_data[row.samplename] = chromagram.astype(np.float32)\n        \n    except Exception as e:\n        print(f\"Error processing {row.filepath}: {e}\")\n        errors.append((row.filepath, str(e)))\n\nend_time = time.time()\nprint(f\"Processing completed in {end_time - start_time:.2f} seconds\")\nprint(f\"Successfully processed {len(all_bird_data)} files out of {total_samples} total\")\nprint(f\"Failed to process {len(errors)} files\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"samples = []\ndisplayed_classes = set()\n\nmax_samples = min(4, len(all_bird_data))\n\nfor i, row in working_df.iterrows():\n    if i >= (config.N_MAX or len(working_df)):\n        break\n        \n    if row['samplename'] in all_bird_data:\n        if config.DEBUG_MODE:\n            if row['class'] not in displayed_classes:\n                samples.append((row['samplename'], row['class'], row['primary_label']))\n                displayed_classes.add(row['class'])\n        else:\n            if row['class'] not in displayed_classes:\n                samples.append((row['samplename'], row['class'], row['primary_label']))\n                displayed_classes.add(row['class'])\n        \n        if len(samples) >= max_samples:  \n            break\n\nif samples:\n    plt.figure(figsize=(16, 12))\n    \n    for i, (samplename, class_name, species) in enumerate(samples):\n        plt.subplot(2, 2, i+1)\n        plt.imshow(all_bird_data[samplename], aspect='auto', origin='lower', cmap='viridis')\n        plt.title(f\"{class_name}: {species}\")\n        plt.ylabel('Pitch Class')\n        plt.xlabel('Time')\n        plt.colorbar(label='Energy')\n    \n    plt.tight_layout()\n    debug_note = \"debug_\" if config.DEBUG_MODE else \"\"\n    plt.savefig(f'{debug_note}chromagram_examples.png')\n    plt.show()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def save_chromagram_data(output_dir):\n    if not os.path.exists(output_dir):\n        os.makedirs(output_dir)\n        \n    np_save_path = os.path.join(output_dir, 'chromagram_data.npz')\n    print(f\"Saving chromagram data to {np_save_path}\")\n    np.savez_compressed(np_save_path, **all_bird_data)\n    \n    data_list = []\n    for samplename, _ in all_bird_data.items():\n        row = working_df[working_df['samplename'] == samplename].iloc[0]\n        data_list.append({\n            'samplename': samplename,\n            'primary_label': row['primary_label'],\n            'class': row['class'],\n            'target': row['target']\n        })\n    \n    data_df = pd.DataFrame(data_list)\n    \n    csv_path = os.path.join(output_dir, 'chromagram_metadata.csv')\n    data_df.to_csv(csv_path, index=False)\n    print(f\"Saved metadata to {csv_path}\")\n    \n    return np_save_path, csv_path","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_chromagram_data(np_path):\n    data = np.load(np_path, allow_pickle=True)\n    return {k: data[k] for k in data.files}","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"save_path, meta_path = save_chromagram_data(config.OUTPUT_DIR)\nprint(f\"Saved chromagram data to {save_path}\")\nprint(f\"Saved metadata to {meta_path}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def prepare_data_for_modeling():\n    print(\"Example: Preparing chromagram data for model training\")\n    \n    X = np.array([all_bird_data[name] for name in all_bird_data.keys()])\n    samplenames = list(all_bird_data.keys())\n    labels = [working_df[working_df['samplename'] == name].iloc[0]['target'] for name in samplenames]\n    y = np.array(labels)\n    \n    print(f\"Input shape: {X.shape}, Target shape: {y.shape}\")\n    print(f\"Number of classes: {len(np.unique(y))}\")\n    \n    return X, y, samplenames","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X, y, samplenames = prepare_data_for_modeling()\n\nchroma_shapes = [all_bird_data[name].shape for name in all_bird_data.keys()]\nunique_shapes = set(chroma_shapes)\nprint(f\"Unique chromagram shapes: {unique_shapes}\")\n\nchroma_min = min([np.min(all_bird_data[name]) for name in all_bird_data.keys()])\nchroma_max = max([np.max(all_bird_data[name]) for name in all_bird_data.keys()])\nprint(f\"Value range: [{chroma_min:.4f}, {chroma_max:.4f}]\")\n\nprint(\"Notebook completed!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}