first commit
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
/build
|
/build
|
||||||
/dist
|
/dist
|
||||||
.GCRAS_logo_rus_curves.ico
|
GCRAS_logo_rus_curves.ico
|
||||||
|
/data
|
||||||
|
/.idea
|
||||||
|
/.git
|
||||||
|
|||||||
8
about.md
Normal file
8
about.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# GSM-19 (.g file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| | time | lon | lat | magnetic field | gradient |
|
||||||
|
|:--------------:|:---------:|:-----------------------------------------------------------:|:-----------------------------------------------------------:|:--------------:|:--------:|
|
||||||
|
| <b>units</b> | HHMMSS.ss | DDMMmmmmm | DDMMmmmmm | nT | nT / m |
|
||||||
|
| <b>comment</b> | | D - degrees, <br/> M - minutes, <br/> m - decimal minutes | D - degrees, <br/> M - minutes, <br/> m - decimal minutes | | |
|
||||||
48
functions.py
Normal file
48
functions.py
Normal file
@@ -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
|
||||||
166
main.py
Normal file
166
main.py
Normal file
@@ -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()
|
||||||
39
main.spec
Normal file
39
main.spec
Normal file
@@ -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,
|
||||||
|
)
|
||||||
42
prog.py
Normal file
42
prog.py
Normal file
@@ -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
|
||||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pandas==1.3.5
|
||||||
|
pyinstaller==6.20
|
||||||
Reference in New Issue
Block a user