{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":39763,"databundleVersionId":11756775,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport matplotlib.animation as animation\nfrom pathlib import Path","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:48:44.166553Z","iopub.execute_input":"2025-05-21T07:48:44.166835Z","iopub.status.idle":"2025-05-21T07:48:44.514508Z","shell.execute_reply.started":"2025-05-21T07:48:44.166814Z","shell.execute_reply":"2025-05-21T07:48:44.513815Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fpath = Path(\"/kaggle/input/waveform-inversion\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:48:44.515948Z","iopub.execute_input":"2025-05-21T07:48:44.516407Z","iopub.status.idle":"2025-05-21T07:48:44.520626Z","shell.execute_reply.started":"2025-05-21T07:48:44.516376Z","shell.execute_reply":"2025-05-21T07:48:44.519905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dir = fpath/'test'\ntrain_dir = fpath/'train_samples'\nsamp_sub = pd.read_csv(fpath/'sample_submission.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:48:44.521403Z","iopub.execute_input":"2025-05-21T07:48:44.521716Z","iopub.status.idle":"2025-05-21T07:49:14.528227Z","shell.execute_reply.started":"2025-05-21T07:48:44.521689Z","shell.execute_reply":"2025-05-21T07:49:14.527529Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\nSample submission head:\")\nprint(samp_sub.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:50:18.020306Z","iopub.execute_input":"2025-05-21T07:50:18.021529Z","iopub.status.idle":"2025-05-21T07:50:18.040972Z","shell.execute_reply.started":"2025-05-21T07:50:18.021457Z","shell.execute_reply":"2025-05-21T07:50:18.039805Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_test = np.load(test_dir/os.listdir(test_dir)[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:49:14.575408Z","iopub.execute_input":"2025-05-21T07:49:14.575680Z","iopub.status.idle":"2025-05-21T07:49:15.115001Z","shell.execute_reply.started":"2025-05-21T07:49:14.575659Z","shell.execute_reply":"2025-05-21T07:49:15.114043Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Plot all 5 slices as subplots in a single figure:\nplt.clf() # Clear previous figure settings if any for this new subplot example\nfig, axes = plt.subplots(nrows=1, ncols=data_test.shape[0], figsize=(20, 5))\nif data_test.shape[0] == 1: axes = [axes]\nelse: axes = axes.flatten()\n\nfor i in range(data_test.shape[0]):\n    ax = axes[i]\n    im = ax.imshow(data_test[i, :, :], aspect='auto', cmap='viridis')\n    ax.set_title(f'Slice {i}')\n    ax.set_xlabel('Dim 70')\n    if i == 0: ax.set_ylabel('Dim 1000')\n    else: ax.set_yticks([])\n    fig.colorbar(im, ax=ax, orientation='vertical', fraction=0.046, pad=0.04)\n\n\nplt.suptitle('Visualization of 5 Slices (each 1000x70)', fontsize=16)\nplt.tight_layout(rect=[0, 0, 1, 0.96]) # Adjust layout to make space for suptitle\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:49:15.115809Z","iopub.execute_input":"2025-05-21T07:49:15.116097Z","iopub.status.idle":"2025-05-21T07:49:16.603140Z","shell.execute_reply.started":"2025-05-21T07:49:15.116076Z","shell.execute_reply":"2025-05-21T07:49:16.601948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# List available training family folders\nif train_dir.exists():\n    family_folders = sorted([d.name for d in train_dir.iterdir() if d.is_dir()])\n    print(f\"Available training families: {family_folders}\")\nelse:\n    print(f\"ERROR: Training directory not found at {train_dir}\")\n    family_folders = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:49:16.620918Z","iopub.execute_input":"2025-05-21T07:49:16.621294Z","iopub.status.idle":"2025-05-21T07:49:16.638939Z","shell.execute_reply.started":"2025-05-21T07:49:16.621274Z","shell.execute_reply":"2025-05-21T07:49:16.637990Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define get_sample_pair_paths Function\ndef get_sample_pair_paths(family_path: Path):\n    \"\"\"\n    Finds a pair of (seismic_data_file, velocity_model_file) paths from a given family folder.\n    Handles two structures:\n    1. Vel/Style families: data/*.npy in 'data/' subdir, model/*.npy in 'model/' subdir.\n    2. Fault families: seis_*.npy and vel_*.npy directly in family_path.\n    \"\"\"\n    data_subdir = family_path / 'data'\n    model_subdir = family_path / 'model'\n\n    seismic_file_path = None\n    model_file_path = None\n\n    if data_subdir.exists() and model_subdir.exists():\n        # Vel or Style family structure\n        print(f\"Found 'data' and 'model' subdirectories in {family_path.name}. (Vel/Style family)\")\n        try:\n            # Get the first .npy file from data subdir\n            data_files = sorted([f for f in data_subdir.iterdir() if f.suffix == '.npy'])\n            if not data_files:\n                print(f\"No .npy files found in {data_subdir}\")\n                return None, None\n            seismic_file_path = data_files[0]\n\n            # Try to find corresponding model file\n            # e.g., data1.npy -> model1.npy\n            model_file_name = seismic_file_path.name.replace('data', 'model', 1)\n            potential_model_path = model_subdir / model_file_name\n            \n            if potential_model_path.exists():\n                model_file_path = potential_model_path\n            else:\n                # Fallback: take the first model file if direct match fails\n                print(f\"Warning: Could not find direct match {model_file_name}, trying first model file.\")\n                model_files = sorted([f for f in model_subdir.iterdir() if f.suffix == '.npy'])\n                if model_files:\n                    model_file_path = model_files[0]\n                else:\n                    print(f\"No .npy files found in {model_subdir}\")\n                    return None, None\n            \n        except IndexError:\n            print(f\"Error accessing files in {data_subdir} or {model_subdir}\")\n            return None, None\n    else:\n        # Fault family structure (files directly in family_path)\n        print(f\"No 'data'/'model' subdirs in {family_path.name}. Assuming Fault family structure.\")\n        all_npy_files_in_family = sorted([f for f in family_path.iterdir() if f.suffix == '.npy'])\n        \n        seis_files = [f for f in all_npy_files_in_family if f.name.startswith('seis_')]\n        vel_files = [f for f in all_npy_files_in_family if f.name.startswith('vel_')]\n\n        if seis_files and vel_files:\n            # Try to find a matching pair\n            for s_file in seis_files:\n                expected_v_file_name = s_file.name.replace('seis_', 'vel_')\n                # Check if the corresponding vel file exists by constructing its full path\n                potential_v_file_path = family_path / expected_v_file_name\n                if potential_v_file_path in vel_files: # Check if Path object is in list of Path objects\n                    seismic_file_path = s_file\n                    model_file_path = potential_v_file_path\n                    break # Found a pair\n            if not seismic_file_path:\n                # Fallback: if no direct match, take the first of each\n                print(\"Warning: Could not find a directly name-matched seis/vel pair. Using first found files.\")\n                seismic_file_path = seis_files[0]\n                model_file_path = vel_files[0]\n        else:\n            print(f\"No 'seis_'/'vel_' .npy file pairs found directly in {family_path.name}\")\n            return None, None\n            \n    return seismic_file_path, model_file_path","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:51:20.700171Z","iopub.execute_input":"2025-05-21T07:51:20.700520Z","iopub.status.idle":"2025-05-21T07:51:20.713019Z","shell.execute_reply.started":"2025-05-21T07:51:20.700482Z","shell.execute_reply":"2025-05-21T07:51:20.711958Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Choose a Family and Get Specific File Paths\n\n# --- You can change this to any family name from 'family_folders' ---\n# Example for a Fault family:\n# chosen_family_name = 'CurveFault_A'\n# Example for a Vel family:\nchosen_family_name = 'CurveVel_A'\n# Example for a Style family:\n# chosen_family_name = 'Style_A'\n\n# Fallback if chosen_family_name isn't available\nif not family_folders:\n    print(\"Error: family_folders list is empty. Cannot proceed.\")\n    # Handle error appropriately, perhaps skip subsequent snippets\n    seismic_data_filepath = None\n    velocity_model_filepath = None\nelif chosen_family_name not in family_folders:\n    print(f\"Warning: Chosen family '{chosen_family_name}' not found. Defaulting to first available: {family_folders[0]}\")\n    chosen_family_name = family_folders[0]\n# --------------------------------------------------------------------\n\nif family_folders: # Proceed only if family_folders is not empty\n    chosen_family_path = train_dir / chosen_family_name\n    print(f\"\\nExploring family: {chosen_family_name} (Path: {chosen_family_path})\")\n\n    seismic_data_filepath, velocity_model_filepath = get_sample_pair_paths(chosen_family_path)\n\n    if seismic_data_filepath and velocity_model_filepath:\n        print(f\"  Seismic data file: {seismic_data_filepath}\")\n        print(f\"  Velocity model file: {velocity_model_filepath}\")\n    else:\n        print(f\"Could not retrieve a valid file pair for {chosen_family_name}.\")\nelse:\n    # This else corresponds to the \"if not family_folders:\" check earlier\n    print(\"Skipping file path retrieval as no family folders were found.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:51:38.747293Z","iopub.execute_input":"2025-05-21T07:51:38.747614Z","iopub.status.idle":"2025-05-21T07:51:38.763377Z","shell.execute_reply.started":"2025-05-21T07:51:38.747590Z","shell.execute_reply":"2025-05-21T07:51:38.762280Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load Data and Select a Sample\n\n# Initialize variables to avoid NameError if previous snippet failed\nseismic_data_batch = None\nvelocity_model_batch = None\nsample_seismic_data = None\nsample_velocity_model = None\n\nif seismic_data_filepath and velocity_model_filepath:\n    try:\n        seismic_data_batch = np.load(seismic_data_filepath)\n        velocity_model_batch = np.load(velocity_model_filepath)\n\n        print(f\"\\nShape of loaded seismic data batch: {seismic_data_batch.shape}\")\n        print(f\"Shape of loaded velocity model batch: {velocity_model_batch.shape}\")\n\n        # Pick the first sample from the batch for visualization\n        # (batch_size is typically the first dimension)\n        if seismic_data_batch.shape[0] > 0:\n            sample_seismic_data = seismic_data_batch[0]\n            print(f\"Shape of one seismic data sample: {sample_seismic_data.shape}\")\n            # Expected: (num_sources, time_steps, num_receivers)\n        else:\n            print(\"Seismic data batch is empty.\")\n\n        if velocity_model_batch.shape[0] > 0:\n            sample_velocity_model = velocity_model_batch[0]\n            print(f\"Shape of one velocity model sample: {sample_velocity_model.shape}\")\n            # Expected: (height, width)\n        else:\n            print(\"Velocity model batch is empty.\")\n\n    except Exception as e:\n        print(f\"Error loading .npy files: {e}\")\nelse:\n    print(\"\\nSkipping data loading as file paths were not resolved.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T07:52:06.329601Z","iopub.execute_input":"2025-05-21T07:52:06.329967Z","iopub.status.idle":"2025-05-21T07:52:10.722841Z","shell.execute_reply.started":"2025-05-21T07:52:06.329941Z","shell.execute_reply":"2025-05-21T07:52:10.722003Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize Velocity Model\n\nif sample_velocity_model is not None:\n    plt.figure(figsize=(8, 6))\n    plt.imshow(sample_velocity_model.squeeze(), cmap='viridis', aspect='auto')\n    plt.colorbar(label='Velocity (e.g., m/s)')\n    plt.title(f'Velocity Model (Sample 0 from {chosen_family_name})')\n    plt.xlabel('Width Index')\n    plt.ylabel('Height (Depth) Index')\n    plt.tight_layout()\n    plt.show()\nelse:\n    print(\"\\nSkipping velocity model visualization as data is not loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T08:00:54.760485Z","iopub.execute_input":"2025-05-21T08:00:54.760789Z","iopub.status.idle":"2025-05-21T08:00:55.073674Z","shell.execute_reply.started":"2025-05-21T08:00:54.760768Z","shell.execute_reply":"2025-05-21T08:00:55.072743Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize a Single Seismogram\n\nif sample_seismic_data is not None:\n    try:\n        num_sources, time_steps, num_receivers = sample_seismic_data.shape\n        \n        # Define which source and receiver to plot\n        source_idx_to_plot = 0 \n        receiver_idx_to_plot = 0\n\n        if num_sources > source_idx_to_plot and num_receivers > receiver_idx_to_plot:\n            single_seismogram = sample_seismic_data[source_idx_to_plot, :, receiver_idx_to_plot]\n            \n            plt.figure(figsize=(12, 4))\n            plt.plot(single_seismogram)\n            plt.title(f'Seismogram: Source {source_idx_to_plot}, Receiver {receiver_idx_to_plot}\\n(Sample 0 from {chosen_family_name})')\n            plt.xlabel('Time Step Index')\n            plt.ylabel('Amplitude')\n            plt.grid(True)\n            plt.tight_layout()\n            plt.show()\n        else:\n            print(f\"Cannot plot seismogram: Source index {source_idx_to_plot} or Receiver index {receiver_idx_to_plot} out of bounds.\")\n            print(f\"(Available: {num_sources} sources, {num_receivers} receivers)\")\n            \n    except ValueError: # If sample_seismic_data doesn't have 3 dimensions\n        print(f\"Error: sample_seismic_data does not have the expected 3 dimensions. Shape is {sample_seismic_data.shape}\")\nelse:\n    print(\"\\nSkipping seismogram visualization as data is not loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T08:01:48.519635Z","iopub.execute_input":"2025-05-21T08:01:48.520451Z","iopub.status.idle":"2025-05-21T08:01:48.739832Z","shell.execute_reply.started":"2025-05-21T08:01:48.520426Z","shell.execute_reply":"2025-05-21T08:01:48.738953Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize a Shot Record\n\nif sample_seismic_data is not None:\n    try:\n        num_sources, time_steps, num_receivers = sample_seismic_data.shape\n        source_idx_to_view = 0 # View data from the first source\n\n        if num_sources > source_idx_to_view:\n            shot_record = sample_seismic_data[source_idx_to_view, :, :] # Shape: (time_steps, num_receivers)\n\n            plt.figure(figsize=(10, 7))\n            # Plot with time on y-axis, receivers on x-axis (a common convention)\n            # Transpose shot_record to have time_steps as columns for imshow if receivers are the primary \"image width\"\n            # Or plot directly if time_steps are the \"image width\"\n            # Let's plot time_steps along x-axis, receivers along y-axis for consistency with previous imshow.\n            # extent=[x_min, x_max, y_min, y_max]\n            plt.imshow(shot_record.T, aspect='auto', cmap='seismic', extent=[0, time_steps, num_receivers, 0])\n            plt.colorbar(label='Amplitude')\n            plt.title(f'Shot Record for Source {source_idx_to_view}\\n(Sample 0 from {chosen_family_name})')\n            plt.xlabel('Time Step Index')\n            plt.ylabel('Receiver Index')\n            plt.tight_layout()\n            plt.show()\n        else:\n            print(f\"Cannot plot shot record: Source index {source_idx_to_view} out of bounds (Num sources: {num_sources}).\")\n    except ValueError:\n         print(f\"Error: sample_seismic_data does not have the expected 3 dimensions. Shape is {sample_seismic_data.shape}\")\nelse:\n    print(\"\\nSkipping shot record visualization as data is not loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T08:02:02.825669Z","iopub.execute_input":"2025-05-21T08:02:02.826086Z","iopub.status.idle":"2025-05-21T08:02:03.296691Z","shell.execute_reply.started":"2025-05-21T08:02:02.826053Z","shell.execute_reply":"2025-05-21T08:02:03.295692Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Visualize Multiple Shot Records\n\nif sample_seismic_data is not None:\n    try:\n        num_sources, time_steps, num_receivers = sample_seismic_data.shape\n        \n        # Safety check: plot up to 'max_sources_to_plot' or all if fewer\n        max_sources_to_plot = min(num_sources, 5) \n        \n        if max_sources_to_plot > 0:\n            fig, axes = plt.subplots(nrows=1, ncols=max_sources_to_plot, figsize=(4 * max_sources_to_plot, 7), squeeze=False)\n            # squeeze=False ensures axes is always 2D, even if nrows or ncols is 1. Access with axes[0, i]\n            \n            for i in range(max_sources_to_plot):\n                ax = axes[0, i] # Access subplot from the 2D array\n                current_shot_record = sample_seismic_data[i, :, :] # Data for i-th source\n                \n                im = ax.imshow(current_shot_record.T, aspect='auto', cmap='seismic', extent=[0, time_steps, num_receivers, 0])\n                ax.set_title(f'Source {i}')\n                ax.set_xlabel('Time Steps')\n                if i == 0:\n                    ax.set_ylabel('Receivers')\n                else:\n                    ax.set_yticks([]) # Hide y-ticks for subsequent subplots for clarity\n            \n            # Add a single colorbar for the entire figure\n            # Adjust 'right' to make space for colorbar, 'wspace' for space between subplots\n            fig.subplots_adjust(right=0.90, wspace=0.3) \n            cbar_ax = fig.add_axes([0.92, 0.15, 0.02, 0.7]) # [left, bottom, width, height]\n            fig.colorbar(im, cax=cbar_ax, label='Amplitude')\n\n            plt.suptitle(f'Shot Records (First {max_sources_to_plot} Sources)\\n(Sample 0 from {chosen_family_name})', fontsize=16)\n            # Adjust layout to make space for suptitle. rect=[left, bottom, right, top]\n            # This might need fine-tuning after seeing the plot with the colorbar.\n            # plt.tight_layout(rect=[0, 0, 0.9, 0.95]) # tight_layout might conflict with add_axes, adjust manually or remove\n            plt.show()\n        else:\n            print(\"No sources found in the sample seismic data to plot multiple shot records.\")\n    except ValueError:\n        print(f\"Error: sample_seismic_data does not have the expected 3 dimensions. Shape is {sample_seismic_data.shape}\")\n\nelse:\n    print(\"\\nSkipping multiple shot records visualization as data is not loaded.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T08:02:19.484600Z","iopub.execute_input":"2025-05-21T08:02:19.484947Z","iopub.status.idle":"2025-05-21T08:02:20.311437Z","shell.execute_reply.started":"2025-05-21T08:02:19.484920Z","shell.execute_reply":"2025-05-21T08:02:20.310344Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}