未分類

import sys
import numpy as np
import os
from PyQt6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QPushButton, 
                             QFileDialog, QLabel, QTableWidget, QTableWidgetItem, QHeaderView)
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QColor, QFont

class NpzInspectorTable(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("NPZ データ点検ツール (表形式一括確認)")
        self.resize(850, 600)
        self.setAcceptDrops(True) # ドラッグ&ドロップを有効化
        
        self.setStyleSheet("""
            QWidget { background-color: #1E1E1E; color: #D4D4D4; font-size: 10pt; font-family: 'Meiryo', 'MS Gothic', sans-serif; }
            QLabel { color: #569CD6; font-weight: bold; margin: 5px; }
            QPushButton { background-color: #0E639C; color: white; padding: 8px; border-radius: 4px; font-weight: bold; }
            QPushButton:hover { background-color: #1177BB; }
            QTableWidget { background-color: #2D2D2D; color: #FFFFFF; gridline-color: #444444; border: 1px solid #3C3C3C; }
            QHeaderView::section { background-color: #333333; color: #569CD6; padding: 5px; border: 1px solid #444444; font-weight: bold; }
        """)
        
        layout = QVBoxLayout(self)
        
        self.info_label = QLabel("🔽 ここに .npz ファイルをドラッグ&ドロップしてください 🔽")
        self.info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(self.info_label)
        
        self.file_label = QLabel("選択ファイル: なし (要素数: 0)")
        layout.addWidget(self.file_label)
        
        self.btn = QPushButton("フォルダからファイルを選択")
        self.btn.clicked.connect(self.select_file)
        layout.addWidget(self.btn)
        
        # テーブルの設定
        self.table = QTableWidget()
        self.table.setColumnCount(7)
        self.table.setHorizontalHeaderLabels(["気象要素名", "データ形状", "最小値", "最大値", "欠損(NaN)数", "状態判定", "備考"])
        
        # 列の幅を調整
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents) # 要素名
        header.setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents) # 形状
        header.setSectionResizeMode(2, QHeaderView.ResizeMode.Stretch)          # 最小
        header.setSectionResizeMode(3, QHeaderView.ResizeMode.Stretch)          # 最大
        header.setSectionResizeMode(4, QHeaderView.ResizeMode.ResizeToContents) # NaN
        header.setSectionResizeMode(5, QHeaderView.ResizeMode.ResizeToContents) # 状態
        header.setSectionResizeMode(6, QHeaderView.ResizeMode.Stretch)          # 備考
        
        layout.addWidget(self.table)
        
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
            
    def dropEvent(self, event):
        urls = event.mimeData().urls()
        if urls:
            file_path = urls[0].toLocalFile()
            if file_path.lower().endswith('.npz'):
                self.inspect_npz(file_path)
            else:
                self.file_label.setText("⚠️ エラー: .npzファイルではありません。")
                
    def select_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "NPZファイルを選択", "", "Numpy Zip (*.npz)")
        if file_path:
            self.inspect_npz(file_path)
            
    def inspect_npz(self, file_path):
        self.table.setRowCount(0) # テーブルをリセット
        
        try:
            with np.load(file_path) as data:
                keys = data.files
                self.file_label.setText(f"📁 選択ファイル: {os.path.basename(file_path)}  (収録要素数: {len(keys)} 個)")
                self.table.setRowCount(len(keys))
                
                for row, key in enumerate(keys):
                    arr = data[key]
                    
                    shape_str = str(arr.shape)
                    min_str = "-"
                    max_str = "-"
                    nan_str = "-"
                    status_str = "不明"
                    memo_str = "座標データ等" if key in ['lon', 'lat', 'lon_surf', 'lat_surf', 'lon_pall', 'lat_pall'] else ""
                    
                    # 背景色のデフォルト
                    bg_color = QColor(45, 45, 45) # 通常のグレー
                    text_color = QColor(255, 255, 255)
                    
                    if np.issubdtype(arr.dtype, np.number):
                        nan_count = np.isnan(arr).sum()
                        total_count = arr.size
                        nan_str = str(nan_count)
                        
                        if nan_count == total_count:
                            status_str = "全欠損"
                            memo_str = "wgrib2抽出失敗の可能性大"
                            bg_color = QColor(139, 0, 0) # 暗い赤(エラー)
                        else:
                            min_str = f"{np.nanmin(arr):.3f}"
                            max_str = f"{np.nanmax(arr):.3f}"
                            
                            if nan_count > 0:
                                status_str = "一部欠損"
                                memo_str = "日本域外のマスク等の可能性"
                                bg_color = QColor(139, 128, 0) # 暗い黄色(警告)
                            else:
                                status_str = "正常"
                                bg_color = QColor(0, 100, 0) if memo_str == "" else QColor(45, 45, 45) # 緑(正常データ)
                    else:
                        status_str = "数値以外"

                    # テーブルにセット
                    items = [
                        QTableWidgetItem(key), QTableWidgetItem(shape_str), 
                        QTableWidgetItem(min_str), QTableWidgetItem(max_str), 
                        QTableWidgetItem(nan_str), QTableWidgetItem(status_str),
                        QTableWidgetItem(memo_str)
                    ]
                    
                    for col, item in enumerate(items):
                        item.setBackground(bg_color)
                        item.setForeground(text_color)
                        item.setTextAlignment(Qt.AlignmentFlag.AlignCenter if col != 6 else Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
                        self.table.setItem(row, col, item)

        except Exception as e:
            self.file_label.setText(f"❌ 読み込みエラー: ファイルが壊れているか、アクセスできません。({e})")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = NpzInspectorTable()
    window.show()
    sys.exit(app.exec())

コメント