Spaces:
Sleeping
Sleeping
| import pyvista as pv | |
| import numpy as np | |
| from scipy.spatial.distance import jensenshannon | |
| import os | |
| dataset = "plane_transonic" | |
| train_folder = f'/raid/ansysai/pkakka/6-Transformers/comparePhysicsLM/Data/{dataset}/' | |
| train_save_dir = train_folder + f"../../metrics/{dataset}/" | |
| test_dir = train_save_dir + f"Transformer_baseline_ep1000/best_case/vtk_files/" | |
| # Function to extract pressure values from VTP file | |
| # For training data: uses 'pressure' field | |
| # For test data: can extract both 'gt_pressure' and 'pred_pressure' | |
| def get_pressures(vtp_file, pressure_field='pressure'): | |
| mesh = pv.read(vtp_file) | |
| if pressure_field not in mesh.point_data: | |
| raise ValueError(f"No '{pressure_field}' data in {vtp_file}") | |
| return mesh.point_data[pressure_field] | |
| # Function to get both GT and predicted pressures from test VTK file | |
| def get_both_pressures(vtk_file): | |
| mesh = pv.read(vtk_file) | |
| gt_pressure = None | |
| pred_pressure = None | |
| if 'gt_pressure' in mesh.point_data: | |
| gt_pressure = mesh.point_data['gt_pressure'] | |
| elif 'pressure' in mesh.point_data: | |
| gt_pressure = mesh.point_data['pressure'] | |
| if 'pred_pressure' in mesh.point_data: | |
| pred_pressure = mesh.point_data['pred_pressure'] | |
| return gt_pressure, pred_pressure | |
| # Part 1: Compute and store training PDF (histogram) | |
| def compute_training_pdf(train_folder, output_file='train_dist.npz', num_bins=50): | |
| # List all VTP files in training folder | |
| train_files = [os.path.join(train_folder, f) for f in os.listdir(train_folder) if f.endswith('.vtp')] | |
| if not train_files: | |
| raise ValueError("No VTP files found in training folder") | |
| # Collect all training pressures | |
| # Read train.txt to get list of training VTP files | |
| train_txt_path = os.path.join(train_folder, '1_VTK_surface/train.txt') | |
| with open(train_txt_path, 'r') as f: | |
| folder_names = [line.strip() for line in f if line.strip()] | |
| # Construct full paths to VTP files | |
| train_files = [] | |
| for folder_name in folder_names: | |
| vtp_file = os.path.join(train_folder, '1_VTK_surface', folder_name, f'{folder_name}.vtp') | |
| if os.path.exists(vtp_file): | |
| train_files.append(vtp_file) | |
| else: | |
| print(f"Warning: VTP file not found: {vtp_file}") | |
| if not train_files: | |
| raise ValueError("No VTP files found from train.txt list") | |
| train_pressures = np.concatenate([get_pressures(f) for f in train_files]) | |
| # Compute bin edges and normalized histogram (PDF) | |
| bin_edges = np.histogram_bin_edges(train_pressures, bins=num_bins) | |
| train_hist, _ = np.histogram(train_pressures, bins=bin_edges, density=True) | |
| # Save histogram and bin edges | |
| np.savez(train_save_dir + output_file, hist=train_hist, edges=bin_edges) | |
| print(f"Training PDF saved to {train_save_dir + output_file}") | |
| # Part 2: Compute JS divergence confidence score for a test VTP file | |
| def compute_js_score(test_file, train_dist_file='train_dist.npz', pressure_field='pressure'): | |
| # Load training distribution | |
| data = np.load(train_save_dir+train_dist_file) | |
| train_hist = data['hist'] | |
| bin_edges = data['edges'] | |
| # Get test pressures | |
| test_pressures = get_pressures(test_file, pressure_field) | |
| # Compute test histogram with same bins | |
| test_hist, _ = np.histogram(test_pressures, bins=bin_edges, density=True) | |
| # Add small epsilon for smoothing to avoid log(0) | |
| epsilon = 1e-10 | |
| train_hist = train_hist + epsilon | |
| test_hist = test_hist + epsilon | |
| train_hist /= train_hist.sum() | |
| test_hist /= test_hist.sum() | |
| # Compute JS divergence | |
| div = jensenshannon(train_hist, test_hist) | |
| # Confidence score (higher = better alignment, e.g., 1 - div) | |
| score = 1 - div | |
| return score | |
| # Part 2b: Compute JS scores for both GT and predicted pressures | |
| def compute_js_score_both(test_pressures, train_dist_file='train_dist.npz'): | |
| # Load training distribution | |
| data = np.load(train_save_dir+train_dist_file) | |
| train_hist = data['hist'] | |
| bin_edges = data['edges'] | |
| # Compute test histogram with same bins | |
| test_hist, _ = np.histogram(test_pressures, bins=bin_edges, density=True) | |
| # Add small epsilon for smoothing to avoid log(0) | |
| epsilon = 1e-10 | |
| train_hist = train_hist + epsilon | |
| test_hist = test_hist + epsilon | |
| train_hist /= train_hist.sum() | |
| test_hist /= test_hist.sum() | |
| # Compute JS divergence | |
| div = jensenshannon(train_hist, test_hist) | |
| # Confidence score (higher = better alignment, e.g., 1 - div) | |
| score = 1 - div | |
| return score | |
| # Part 3: Compute JS scores for test cases from test.txt, using VTK files in test directory | |
| # Computes scores for both GT and predicted pressure | |
| def compute_test_scores_from_vtk(vtk_test_dir, train_dist_file='train_dist.npz', output_file='test_js_scores.txt'): | |
| # Read test.txt to get list of test case names | |
| test_txt_path = os.path.join(train_folder, '1_VTK_surface/test.txt') | |
| with open(test_txt_path, 'r') as f: | |
| test_case_names = [line.strip() for line in f if line.strip()] | |
| if not test_case_names: | |
| raise ValueError("No test cases found in test.txt") | |
| # Save output file one directory behind the test directory | |
| output_path = os.path.join(os.path.dirname(test_dir+"/../"), output_file) | |
| # Compute scores for each test case | |
| gt_scores = [] | |
| pred_scores = [] | |
| with open(output_path, 'w') as f: | |
| f.write("Test_File\tGT_JS_Score\tPred_JS_Score\n") | |
| for test_case in test_case_names: | |
| # Look for corresponding VTK file in the test directory | |
| vtk_file = f"{test_case}.vtk" | |
| vtk_path = os.path.join(vtk_test_dir, vtk_file) | |
| if os.path.exists(vtk_path): | |
| try: | |
| # Get both GT and predicted pressures | |
| gt_pressure, pred_pressure = get_both_pressures(vtk_path) | |
| gt_score = None | |
| pred_score = None | |
| # Compute GT score if available | |
| if gt_pressure is not None: | |
| gt_score = compute_js_score_both(gt_pressure, train_dist_file) | |
| gt_scores.append(gt_score) | |
| print(f"GT Score for {test_case}: {gt_score:.6f}") | |
| # Compute Pred score if available | |
| if pred_pressure is not None: | |
| pred_score = compute_js_score_both(pred_pressure, train_dist_file) | |
| pred_scores.append(pred_score) | |
| print(f"Pred Score for {test_case}: {pred_score:.6f}") | |
| # Write to file | |
| gt_str = f"{gt_score:.6f}" if gt_score is not None else "N/A" | |
| pred_str = f"{pred_score:.6f}" if pred_score is not None else "N/A" | |
| f.write(f"{test_case}\t{gt_str}\t{pred_str}\n") | |
| except Exception as e: | |
| print(f"Error computing score for {test_case}: {e}") | |
| f.write(f"{test_case}\tERROR: {e}\tERROR: {e}\n") | |
| else: | |
| print(f"Warning: VTK file not found for test case {test_case}: {vtk_path}") | |
| f.write(f"{test_case}\tERROR: VTK file not found\tERROR: VTK file not found\n") | |
| print(f"\nTest scores saved to {output_path}") | |
| # Print statistics for GT scores | |
| if gt_scores: | |
| print(f"\nGT Pressure Statistics:") | |
| print(f"Average GT JS Score: {np.mean(gt_scores):.6f}") | |
| print(f"Std GT JS Score: {np.std(gt_scores):.6f}") | |
| print(f"Min GT JS Score: {np.min(gt_scores):.6f}") | |
| print(f"Max GT JS Score: {np.max(gt_scores):.6f}") | |
| # Print statistics for Pred scores | |
| if pred_scores: | |
| print(f"\nPredicted Pressure Statistics:") | |
| print(f"Average Pred JS Score: {np.mean(pred_scores):.6f}") | |
| print(f"Std Pred JS Score: {np.std(pred_scores):.6f}") | |
| print(f"Min Pred JS Score: {np.min(pred_scores):.6f}") | |
| print(f"Max Pred JS Score: {np.max(pred_scores):.6f}") | |
| return gt_scores, pred_scores | |
| # Part 4: Original function for VTP files from test.txt (kept for compatibility) | |
| def compute_test_scores(test_folder, train_dist_file='train_dist.npz', output_file='test_js_scores.txt'): | |
| # Read test.txt to get list of test VTP files | |
| test_txt_path = os.path.join(test_folder, '1_VTK_surface/test.txt') | |
| with open(test_txt_path, 'r') as f: | |
| folder_names = [line.strip() for line in f if line.strip()] | |
| # Construct full paths to VTP files | |
| test_files = [] | |
| for folder_name in folder_names: | |
| vtp_file = os.path.join(test_folder, '1_VTK_surface', folder_name, f'{folder_name}.vtp') | |
| if os.path.exists(vtp_file): | |
| test_files.append((folder_name, vtp_file)) | |
| else: | |
| print(f"Warning: VTP file not found: {vtp_file}") | |
| if not test_files: | |
| raise ValueError("No VTP files found from test.txt list") | |
| # Compute scores for each test file | |
| scores = [] | |
| with open(test_dir+"/../test_js_scores.txt", 'w') as f: | |
| f.write("Test_File\tJS_Score\n") | |
| for folder_name, vtp_file in test_files: | |
| try: | |
| score = compute_js_score(vtp_file, train_dist_file) | |
| scores.append(score) | |
| f.write(f"{folder_name}\t{score:.6f}\n") | |
| print(f"Score for {folder_name}: {score:.6f}") | |
| except Exception as e: | |
| print(f"Error computing score for {folder_name}: {e}") | |
| f.write(f"{folder_name}\tERROR: {e}\n") | |
| print(f"\nTest scores saved to {test_dir}/../test_js_scores.txt") | |
| print(f"Average JS Score: {np.mean(scores):.6f}") | |
| print(f"Std JS Score: {np.std(scores):.6f}") | |
| print(f"Min JS Score: {np.min(scores):.6f}") | |
| print(f"Max JS Score: {np.max(scores):.6f}") | |
| return scores | |
| # Example Usage: | |
| # Step 1: Compute training PDF | |
| #compute_training_pdf(train_folder) | |
| # Step 2: Compute scores for VTK files in test directory | |
| test_scores = compute_test_scores_from_vtk(test_dir) |