{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":39763,"databundleVersionId":11756775,"sourceType":"competition"},{"sourceId":11372645,"sourceType":"datasetVersion","datasetId":7112154},{"sourceId":233221031,"sourceType":"kernelVersion"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"raw","source":"I just tried to infer by InversionNet and the pre-trained model.","metadata":{}},{"cell_type":"code","source":"import os\nimport sys\nimport json\nimport glob\n\nimport torch\nimport numpy as np\nimport pandas as pd\nfrom torchvision.transforms import Compose\n\nsys.path.append('/kaggle/input/openfwi-pretrainedmodel/OpenFWI')\n\nimport network\nimport transforms as T\nfrom dataset import FWIDataset","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:10.062140Z","iopub.execute_input":"2025-04-15T07:11:10.062421Z","iopub.status.idle":"2025-04-15T07:11:10.908698Z","shell.execute_reply.started":"2025-04-15T07:11:10.062401Z","shell.execute_reply":"2025-04-15T07:11:10.907914Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DEBUG = False # Set to False to process all files","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:10.909821Z","iopub.execute_input":"2025-04-15T07:11:10.910256Z","iopub.status.idle":"2025-04-15T07:11:10.913818Z","shell.execute_reply.started":"2025-04-15T07:11:10.910206Z","shell.execute_reply":"2025-04-15T07:11:10.912958Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#! wget --no-check-certificate 'https://zenodo.org/record/7293942/files/cva_l1.pth'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:10.915623Z","iopub.execute_input":"2025-04-15T07:11:10.915890Z","iopub.status.idle":"2025-04-15T07:11:10.944338Z","shell.execute_reply.started":"2025-04-15T07:11:10.915869Z","shell.execute_reply":"2025-04-15T07:11:10.943527Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"WEIGHTS_PATH = '/kaggle/input/gwi-pretrainedmodel/PretrainedModel/ffb_l2.pth'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:10.945633Z","iopub.execute_input":"2025-04-15T07:11:10.945901Z","iopub.status.idle":"2025-04-15T07:11:10.959304Z","shell.execute_reply.started":"2025-04-15T07:11:10.945873Z","shell.execute_reply":"2025-04-15T07:11:10.958519Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"MODEL_NAME = 'InversionNet' \n\nTEST_DATA_DIR = '/kaggle/input/waveform-inversion/test' \nOUTPUT_CSV = 'submission.csv'\n\nDATASET_CONFIG = '/kaggle/input/openfwi-pretrainedmodel/OpenFWI/dataset_config.json'\nDATASET_NAME = 'flatfault-b' # Adjust based on the dataset used for training the weights, needed for normalization params\n\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\nK_TRANSFORM = 1 # k value for LogTransform, adjust if needed (from test.py --k)\nBATCH_SIZE = 16 # Process one file (oid) at a time\n\n# Sample spatial/temporal might be needed depending on the model architecture used for fva_l1.pth\nSAMPLE_SPATIAL = 1.0 # Adjust if needed (from test.py --sample-spatial)\nSAMPLE_TEMPORAL = 1  # Adjust if needed (from test.py --sample-temporal)\nNORM_LAYER = 'bn' # Adjust if needed (from test.py --norm)\nUP_MODE = None # Adjust if needed (from test.py --up-mode)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:59.167948Z","iopub.execute_input":"2025-04-15T07:11:59.168281Z","iopub.status.idle":"2025-04-15T07:11:59.172638Z","shell.execute_reply.started":"2025-04-15T07:11:59.168252Z","shell.execute_reply":"2025-04-15T07:11:59.171749Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_dataset_config(config_path, dataset_name):\n    \"\"\"Loads normalization parameters from dataset_config.json.\"\"\"\n    try:\n        with open(config_path) as f:\n            ctx = json.load(f)[dataset_name]\n        print(f\"Loaded config for dataset: {dataset_name}\")\n        return ctx\n    except FileNotFoundError:\n        print(f\"Error: {config_path} not found.\")\n        sys.exit(1)\n    except KeyError:\n        print(f\"Error: Dataset '{dataset_name}' not found in {config_path}.\")\n        sys.exit(1)\n\ndef get_transforms(ctx, k):\n    \"\"\"Gets the transformations for data and label based on test.py.\"\"\"\n    log_data_min = T.log_transform(ctx['data_min'], k=k)\n    log_data_max = T.log_transform(ctx['data_max'], k=k)\n    transform_data = Compose([\n        T.LogTransform(k=k),\n        T.MinMaxNormalize(log_data_min, log_data_max),\n    ])\n\n    return transform_data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:59.173768Z","iopub.execute_input":"2025-04-15T07:11:59.174027Z","iopub.status.idle":"2025-04-15T07:11:59.196319Z","shell.execute_reply.started":"2025-04-15T07:11:59.174007Z","shell.execute_reply":"2025-04-15T07:11:59.195514Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def main():\n    print(f\"Using device: {DEVICE}\")\n    print(f\"Loading model: {MODEL_NAME}\")\n    print(f\"Loading weights from: {WEIGHTS_PATH}\")\n    print(f\"Test data directory: {TEST_DATA_DIR}\")\n    print(f\"Output CSV: {OUTPUT_CSV}\")\n\n    # Load dataset configuration for normalization parameters\n    ctx = load_dataset_config(DATASET_CONFIG, DATASET_NAME)\n\n    # Initialize Model\n    if MODEL_NAME not in network.model_dict:\n        print(f\"Error: Unsupported model '{MODEL_NAME}'. Check network.py.\")\n        sys.exit(1)\n\n    model = network.model_dict[MODEL_NAME](\n        upsample_mode=UP_MODE,\n        sample_spatial=SAMPLE_SPATIAL,\n        sample_temporal=SAMPLE_TEMPORAL,\n        norm=NORM_LAYER\n    ).to(DEVICE)\n\n    # Load Weights\n    try:\n        checkpoint = torch.load(WEIGHTS_PATH, map_location='cpu')\n        # Handle potential legacy keys or different saving structures\n        if 'model' in checkpoint:\n            state_dict = checkpoint['model']\n        elif 'state_dict' in checkpoint:\n            state_dict = checkpoint['state_dict']\n        else:\n            state_dict = checkpoint\n        # Apply legacy replacement if needed (adapt from test.py if necessary)\n        # state_dict = network.replace_legacy(state_dict) # Uncomment/adapt if needed\n        model.load_state_dict(state_dict)\n        print(\"Model weights loaded successfully.\")\n        if 'epoch' in checkpoint and 'step' in checkpoint:\n             print(f\"Weights from Epoch {checkpoint['epoch']} / Step {checkpoint['step']}.\")\n\n    except FileNotFoundError:\n        print(f\"Error: Weights file not found at {WEIGHTS_PATH}\")\n        sys.exit(1)\n    except Exception as e:\n        print(f\"Error loading weights: {e}\")\n        sys.exit(1)\n\n    model.eval()\n\n    # Get data transform\n    transform_data = get_transforms(ctx, K_TRANSFORM)\n\n    # Find test files\n    test_files = glob.glob(os.path.join(TEST_DATA_DIR, '*.npy'))\n    if not test_files:\n        print(f\"Error: No .npy files found in {TEST_DATA_DIR}\")\n        sys.exit(1)\n\n    # --- Debugging: Process only the first file if DEBUG is True ---\n    if DEBUG:\n        print(\"*** DEBUG MODE: Processing only the first file ***\")\n        test_files = test_files[:1]\n    # --- End Debugging ---\n\n    print(f\"Found {len(test_files)} test file(s) to process.\")\n\n    results = []\n    with torch.no_grad():\n        for i, file_path in enumerate(test_files):\n            oid = os.path.splitext(os.path.basename(file_path))[0]\n            print(f\"Processing ({i+1}/{len(test_files)}): {oid}\")\n\n            try:\n                # Load seismic data\n                seismic_data = np.load(file_path)\n\n                if seismic_data.ndim == 3:\n                     # Add batch dimension\n                    seismic_data = seismic_data[np.newaxis, :, :, :]\n                    # If model expects single channel, select one source, e.g., seismic_data = seismic_data[:, 0:1, :, :]\n                elif seismic_data.ndim != 4:\n                     print(f\"Warning: Unexpected data dimension {seismic_data.ndim} for {oid}. Skipping.\")\n                     continue\n\n                # Convert to tensor and move to device\n                data_tensor = torch.from_numpy(seismic_data).type(torch.FloatTensor)\n\n                # Manual Transformation (Example - adapt based on actual T implementations)\n                data_tensor = T.log_transform(data_tensor, k=K_TRANSFORM)\n                log_data_min = T.log_transform(ctx['data_min'], k=K_TRANSFORM)\n                log_data_max = T.log_transform(ctx['data_max'], k=K_TRANSFORM)\n                data_tensor = T.minmax_normalize(data_tensor, log_data_min, log_data_max)\n\n\n                data_tensor = data_tensor.to(DEVICE)\n\n\n                # Perform inference\n                pred_tensor = model(data_tensor)\n\n                # Denormalize prediction\n                # pred_tensor shape is likely (batch, 1, height, width)\n                pred_np = T.tonumpy_denormalize(pred_tensor, ctx['label_min'], ctx['label_max'], exp=False)\n\n                # pred_np shape should now be (batch, 1, height, width) as numpy array\n                velocity_map = pred_np[0, 0] # Get the (height, width) map\n\n                # Format for submission\n                height, width = velocity_map.shape\n                # Ensure width allows for indexing up to x_69 (i.e., width >= 70)\n                if width < 70:\n                    print(f\"Warning: Predicted width {width} for {oid} is less than 70. Padding or check model output.\")\n\n\n                for y_pos in range(height):\n                    row_data = {'oid_ypos': f\"{oid}_y_{y_pos}\"}\n                    odd_indices = range(1, min(width, 70), 2) # Generate indices 1, 3, ..., 69 (or less if width is smaller)\n                    for x_idx in odd_indices:\n                        col_name = f\"x_{x_idx}\"\n                        row_data[col_name] = velocity_map[y_pos, x_idx]\n\n                    # Handle missing columns if width < 70 by filling with a default (e.g., last valid value or 0)\n                    last_valid_x = odd_indices[-1] if odd_indices else -1 # Find the last index added\n                    for x_idx_req in range(1, 70, 2): # Required indices 1, 3, ..., 69\n                         col_name_req = f\"x_{x_idx_req}\"\n                         if x_idx_req > last_valid_x:\n                             # Fill missing required columns, e.g., with the value of the last valid odd column\n                             fill_value = velocity_map[y_pos, last_valid_x] if last_valid_x >= 0 else 3000.0 # Or use a constant like 3000\n                             row_data[col_name_req] = fill_value\n\n\n                    results.append(row_data)\n\n            except Exception as e:\n                print(f\"Error processing file {file_path}: {e}\")\n                continue # Skip to next file\n\n    # Create DataFrame and save to CSV\n    if not results:\n        print(\"No results generated. Exiting.\")\n        sys.exit(1)\n\n    submission_df = pd.DataFrame(results)\n\n    # Ensure correct column order\n    cols = ['oid_ypos'] + [f'x_{i}' for i in range(1, 70, 2)]\n    submission_df = submission_df[cols]\n\n    submission_df.to_csv(OUTPUT_CSV, index=False, float_format='%.4f') # Format float precision if needed\n    print(f\"Submission file saved to {OUTPUT_CSV}\")\n\n    # --- Debugging: Print head of submission if DEBUG is True ---\n    if DEBUG:\n        print(\"\\n--- Submission DataFrame Head (DEBUG) ---\")\n        print(submission_df.head(5))\n        print(\"-----------------------------------------\")\n    # --- End Debugging ---\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:59.197522Z","iopub.execute_input":"2025-04-15T07:11:59.197741Z","iopub.status.idle":"2025-04-15T07:11:59.217186Z","shell.execute_reply.started":"2025-04-15T07:11:59.197724Z","shell.execute_reply":"2025-04-15T07:11:59.216415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if __name__ == '__main__':\n    main()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T07:11:59.218121Z","iopub.execute_input":"2025-04-15T07:11:59.218367Z","iopub.status.idle":"2025-04-15T07:12:04.033531Z","shell.execute_reply.started":"2025-04-15T07:11:59.218348Z","shell.execute_reply":"2025-04-15T07:12:04.032651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}