diff --git a/.gitignore b/.gitignore index c7decf8..fad94d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ /build /dist -.GCRAS_logo_rus_curves.ico +GCRAS_logo_rus_curves.ico +/data +/.idea +/.git diff --git a/about.md b/about.md new file mode 100644 index 0000000..dd9874c --- /dev/null +++ b/about.md @@ -0,0 +1,8 @@ +# GSM-19 (.g file) + + + +| | time | lon | lat | magnetic field | gradient | +|:--------------:|:---------:|:-----------------------------------------------------------:|:-----------------------------------------------------------:|:--------------:|:--------:| +| units | HHMMSS.ss | DDMMmmmmm | DDMMmmmmm | nT | nT / m | +| comment | | D - degrees,
M - minutes,
m - decimal minutes | D - degrees,
M - minutes,
m - decimal minutes | | | \ No newline at end of file diff --git a/functions.py b/functions.py new file mode 100644 index 0000000..be0acd6 --- /dev/null +++ b/functions.py @@ -0,0 +1,48 @@ +def convert_deg(x): + x = str(x) + if x != "0": + return int(x[0:2]) + ( int( x[2:4] ) + int( x[4:] ) / 100000) / 60 + + return x + + +def time_to_seconds(time): + # Разделяем на целую и дробную часть + time_str = str(time) + if '.' in time_str: + main, frac = time_str.split('.') + frac_seconds = float(f'0.{frac}') + else: + main = time_str + frac_seconds = 0.0 + + # Дополняем до 6 цифр (добавляем ведущий ноль если нужно) + main = main.zfill(6) + + hours = int(main[0:2]) + minutes = int(main[2:4]) + seconds = int(main[4:6]) + + return hours * 3600 + minutes * 60 + seconds + frac_seconds + + +def datetime_to_seconds(time_str): + """ + Преобразует время в формате HH:MM:SS.sss в секунды от полуночи + Пример: '14:40:00.000' -> 52800.0 + """ + # Разделяем на основное время и миллисекунды + if '.' in time_str: + hms, ms = time_str.split('.') + milliseconds = int(ms) + else: + hms = time_str + milliseconds = 0 + + # Парсим часы, минуты, секунды + parts = hms.split(':') + hours = int(parts[0]) + minutes = int(parts[1]) + seconds = int(parts[2]) if len(parts) > 2 else 0 + + return hours * 3600 + minutes * 60 + seconds + milliseconds / 1000 \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..a928c4b --- /dev/null +++ b/main.py @@ -0,0 +1,166 @@ +import tkinter as tk +from tkinter import filedialog, messagebox +import os +from prog import calculate_anomaly + + +# Меню выбора файла GSM-19, устанавливает пусть к файлу в окошко +def select_gsm_file(entry_var): + filetypes = ( + ("Файлы GSM-19", "*.g"), + ("Все файлы", "*.*") + ) + filename = filedialog.askopenfilename( + title="Выберите файл градиентометра", + filetypes=filetypes + ) + if filename: + entry_var.set(filename) + status_label.config(text=f"Выбран файл: {os.path.basename(filename)}", fg="blue") + + +# Меню выбора файла базовой станции, устанавливает пусть к файлу в окошко +def select_base_file(entry_var): + filetypes = ( + ("Текстовые файлы", "*.txt"), + ("Все файлы", "*.*") + ) + filename = filedialog.askopenfilename( + title="Выберите файл базовой станции", + filetypes=filetypes + ) + if filename: + entry_var.set(filename) + status_label.config(text=f"Выбран файл: {os.path.basename(filename)}", fg="blue") + + +# Обработка введенных файлов +def process_files(): + """Основная функция обработки файлов""" + # Получаем пути к файлам + gsm_file = file1_path.get() + base_file = file2_path.get() + + # Проверяем, что оба файла выбраны + if not gsm_file or not base_file: + messagebox.showwarning("Внимание", "Пожалуйста, выберите оба файла!") + return + + # Проверяем, что файлы существуют + if not os.path.exists(gsm_file): + messagebox.showerror("Ошибка", f"Файл не найден:\n{gsm_file}") + return + if not os.path.exists(base_file): + messagebox.showerror("Ошибка", f"Файл не найден:\n{base_file}") + return + + # + try: + + # Вызываем логику обработки + result = calculate_anomaly(gsm_file, base_file) + result.to_csv("result.csv", index=False) + + # Показываем результат + messagebox.showinfo("Успех", f"Обработка завершена!") + status_label.config(text="Обработка завершена успешно", fg="green") + + except Exception as e: + messagebox.showerror("Ошибка", f"Произошла ошибка при обработке:\n{str(e)}") + status_label.config(text="Ошибка при обработке", fg="red") + + finally: + # Возвращаем интерфейс в исходное состояние + process_btn.config(state="normal", text="Обработать") + + +# Создаём главное окно +root = tk.Tk() +root.title("Обработчик файлов") +root.geometry("550x210") +root.resizable(False, False) + +# Переменные для хранения путей к файлам +file1_path = tk.StringVar() +file2_path = tk.StringVar() + +# === Рамка для первого файла === +frame1 = tk.Frame(root) +frame1.pack(pady=20, padx=20, fill="x") + +# Надпись "Файл градиентометра" +tk.Label( + frame1, # В каком окне + text="Файл градиентометра:", # Текст надписи + width=20, # Ширина + anchor="w" # Выравнивание надписи слева по центру +) \ + .pack(side="left") # Прижим к левому краю + +# Окошко ввода для градиентометра +entry1 = tk.Entry( + frame1, # В каком окне + textvariable=file1_path, # Надпись внутри окошка + width=50 # Ширина окошка +) +entry1.pack( + side="left", # Выравнивание слева + padx=5 # Отступ по горизонтали +) + +# Кнопка для выбора файла для окошка +tk.Button( + frame1, # В каком окне + text="Обзор", # Текст кнопки + command=lambda: select_gsm_file( # Команда по нажатию + file1_path + ) +) \ + .pack(side="left") # Выравнивание по левому краю + +# === Рамка для второго файла === +frame2 = tk.Frame(root) +frame2.pack(pady=10, padx=20, fill="x") + +tk.Label( + frame2, + text="Файл базовой станции:", + width=20, + anchor="w" +) \ + .pack(side="left") + +entry2 = tk.Entry( + frame2, + textvariable=file2_path, + width=50 +) +entry2.pack( + side="left", + padx=5 +) +tk.Button( + frame2, + text="Обзор", + command=lambda: select_base_file( + file2_path + ) +) \ + .pack(side="left") + +# === Кнопка обработки === +process_btn = tk.Button( + root, + text="Обработать", + command=process_files, + padx=20, + pady=5 +) +process_btn.pack(pady=20) + +# === Статусная строка === +status_label = tk.Label(root, text="Готов к работе", fg="gray") +status_label.pack(pady=5) + +# Запускаем приложение +root.mainloop() diff --git a/main.spec b/main.spec new file mode 100644 index 0000000..dbae667 --- /dev/null +++ b/main.spec @@ -0,0 +1,39 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=['functions.py', 'prog.py'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='gradientometr', + icon='GCRAS_logo_rus_curves.ico', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/prog.py b/prog.py new file mode 100644 index 0000000..15e4f26 --- /dev/null +++ b/prog.py @@ -0,0 +1,42 @@ +import pandas as pd +from functions import * + + +def calculate_anomaly(gsm_file, base_file): + + df_gsm = pd.read_csv( + gsm_file, + delimiter=" ", + skiprows=1, + names=["time", "lon", "lat", "f", "grad", "_", "quality"] + ) + + df_gsm["lon"] = df_gsm["lon"].apply(convert_deg) + df_gsm["lat"] = df_gsm["lat"].apply(convert_deg) + df_gsm["time"] = df_gsm["time"].apply(time_to_seconds) + df_gsm = df_gsm[["time", "lon", "lat", "f", "grad", "quality"]] + df_gsm["time"] = df_gsm["time"].apply(round).astype(float) + + df_base = pd.read_csv( + base_file, + sep=r"\s+", + skiprows=22, + names=["date", "time", "doy", "x", "y", "z", "f"] + ) + + df_base = df_base[df_base["f"] < 88000] + df_base["time"] = df_base["time"].apply(datetime_to_seconds) + result_df = pd.merge_asof( + df_gsm, + df_base[['time', 'f']], # берем только нужные колонки + left_on='time', + right_on='time', + direction='nearest', + suffixes=('_grad', '_base') + ) + + result_df["delta_f"] = result_df["f_grad"] - result_df["f_base"] + result_df = result_df[["lon", "lat", "time", "f_grad", "delta_f", "grad"]] + result_df = result_df.rename(columns={"f_grad": "f", "grad": "grad_f"}) + + return result_df diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ab0cbb2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pandas==1.3.5 +pyinstaller==6.20 \ No newline at end of file