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