通过配置文件监控目录,当出现csv时做以下操作:
1、转辐亮度; 2、调用丰算法计算sif,输出成csv; 3、将2中的csv上传到ftp服务器;
This commit is contained in:
244
.gitignore
vendored
Normal file
244
.gitignore
vendored
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
# tc
|
||||||
|
/.idea
|
||||||
|
test_data
|
||||||
|
tmp
|
||||||
|
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
9
config.ini
Normal file
9
config.ini
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[FTP]
|
||||||
|
host = 172.16.0.73
|
||||||
|
port = 22
|
||||||
|
user = ftpuser
|
||||||
|
password = 123
|
||||||
|
target_dir = /home/ftpuser/
|
||||||
|
[monitor]
|
||||||
|
WATCH_DIR = D:\PycharmProjects\sif_data_parse\test_data
|
||||||
|
cal_dir = D:\PycharmProjects\sif_data_parse\test_data\cal
|
362
main.py
Normal file
362
main.py
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
import csv, tempfile, os, re
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
import numpy as np
|
||||||
|
import argparse
|
||||||
|
import paramiko
|
||||||
|
import shutil
|
||||||
|
import configparser
|
||||||
|
from ftplib import FTP
|
||||||
|
from pathlib import Path
|
||||||
|
from watchdog.observers import Observer
|
||||||
|
from watchdog.events import FileSystemEventHandler
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def parse_sif_csv(_file_path):
|
||||||
|
_metadata = {}
|
||||||
|
_wavelengths = []
|
||||||
|
_spectra_data = []
|
||||||
|
|
||||||
|
with open(_file_path, encoding='utf-8') as f:
|
||||||
|
reader = csv.reader(f)
|
||||||
|
rows = list(reader)
|
||||||
|
|
||||||
|
# 第1行:除了第一列,后续是变量名和值交替出现
|
||||||
|
row1 = rows[0][1:]
|
||||||
|
for i in range(0, len(row1), 2):
|
||||||
|
if i + 1 < len(row1):
|
||||||
|
_metadata[row1[i]] = row1[i + 1]
|
||||||
|
|
||||||
|
# 第2行:前一个是变量名,后一个是变量值
|
||||||
|
if len(rows) > 1 and len(rows[1]) >= 2:
|
||||||
|
_metadata[rows[1][0]] = rows[1][1]
|
||||||
|
|
||||||
|
# 第3行:除了第一列,后续是变量名和值交替出现
|
||||||
|
row3 = rows[2][1:]
|
||||||
|
for i in range(0, len(row3), 2):
|
||||||
|
if i + 1 < len(row3):
|
||||||
|
_metadata[row3[i]] = row3[i + 1]
|
||||||
|
|
||||||
|
# 第4行是波长
|
||||||
|
_wavelengths = np.array([float(w) for w in rows[3][1:]])
|
||||||
|
|
||||||
|
# 第5行忽略
|
||||||
|
|
||||||
|
# 从第6行开始是光谱数据
|
||||||
|
for row in rows[5:]:
|
||||||
|
if len(row) < 4 or row[1].lower() != "valid":
|
||||||
|
continue # 跳过表头或无效行
|
||||||
|
try:
|
||||||
|
entry = {
|
||||||
|
"Location": row[0],
|
||||||
|
"Valid": row[1],
|
||||||
|
"Integration": int(row[2]),
|
||||||
|
"DN": np.array([float(val) for val in row[3:]])
|
||||||
|
}
|
||||||
|
_spectra_data.append(entry)
|
||||||
|
except ValueError:
|
||||||
|
continue # 跳过不能解析的行
|
||||||
|
|
||||||
|
return _metadata, _wavelengths, _spectra_data
|
||||||
|
|
||||||
|
def read_cal(_file_path):
|
||||||
|
# 定义结构体格式
|
||||||
|
# unsigned int (4) + float (4) + int (4) + 4096 floats (4 each) + 4096 doubles (8 each) + 4096 doubles (8 each)
|
||||||
|
fmt = '<I f i ' + '4096f' + '4096d' + '4096d' # 小端
|
||||||
|
|
||||||
|
# 计算总字节大小
|
||||||
|
struct_size = struct.calcsize(fmt)
|
||||||
|
|
||||||
|
with open(_file_path, 'rb') as f:
|
||||||
|
data = f.read(struct_size)
|
||||||
|
unpacked = struct.unpack(fmt, data)
|
||||||
|
|
||||||
|
# 拆分数据
|
||||||
|
_uiExposureTimeInMS = unpacked[0]
|
||||||
|
_fTemperature = unpacked[1]
|
||||||
|
_iPixels = unpacked[2]
|
||||||
|
_fWaveLength = np.array(unpacked[3:3+4096])[0:_iPixels]
|
||||||
|
_dCal_Gain = np.array(unpacked[3+4096 : 3+4096+4096])[0:_iPixels]
|
||||||
|
_dCal_Offset = np.array(unpacked[3+4096+4096:])[0:_iPixels]
|
||||||
|
|
||||||
|
return _uiExposureTimeInMS,_fTemperature,_iPixels,_fWaveLength,_dCal_Gain,_dCal_Offset
|
||||||
|
|
||||||
|
def write_file(_in_path, _out_path, _spectra_data):
|
||||||
|
with open(_in_path, encoding='utf-8') as f:
|
||||||
|
reader = csv.reader(f)
|
||||||
|
rows = list(reader)
|
||||||
|
|
||||||
|
with open(_out_path, 'w', newline='', encoding='utf-8') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
|
||||||
|
# 写入前4行原样(元数据和波长信息)
|
||||||
|
writer.writerow(rows[0])
|
||||||
|
writer.writerow(rows[1])
|
||||||
|
writer.writerow(rows[2])
|
||||||
|
writer.writerow(rows[3])
|
||||||
|
writer.writerow(rows[4]) # 第5行照抄
|
||||||
|
|
||||||
|
# 写入处理后的光谱数据
|
||||||
|
for entry in _spectra_data:
|
||||||
|
row = [entry["Location"], entry["Valid"], entry["Integration"]] + list(entry["RAD"])
|
||||||
|
writer.writerow(row)
|
||||||
|
|
||||||
|
def get_sorted_files_by_number(folder_path):
|
||||||
|
# 获取文件夹下所有文件和子文件夹
|
||||||
|
all_items = os.listdir(folder_path)
|
||||||
|
|
||||||
|
# 过滤出文件(排除文件夹),并转换为绝对路径
|
||||||
|
files = [
|
||||||
|
os.path.abspath(os.path.join(folder_path, item))
|
||||||
|
for item in all_items
|
||||||
|
if os.path.isfile(os.path.join(folder_path, item))
|
||||||
|
]
|
||||||
|
|
||||||
|
# 定义一个函数来提取文件名中的数字(仅文件名部分)
|
||||||
|
def extract_numbers(filepath):
|
||||||
|
filename = os.path.basename(filepath) # 获取文件名(不含路径)
|
||||||
|
numbers = re.findall(r'\d+', filename) # 提取数字
|
||||||
|
return [int(num) for num in numbers] # 转为整数
|
||||||
|
|
||||||
|
# 按文件名中的数字排序文件
|
||||||
|
sorted_files = sorted(files, key=lambda x: extract_numbers(x))
|
||||||
|
|
||||||
|
return sorted_files
|
||||||
|
|
||||||
|
# 配置读取函数
|
||||||
|
def load_config(config_path='config.ini'):
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(config_path)
|
||||||
|
return config
|
||||||
|
|
||||||
|
class CSVFileHandler(FileSystemEventHandler):
|
||||||
|
def __init__(self, ftp_config):
|
||||||
|
super().__init__()
|
||||||
|
self.ftp_config = ftp_config
|
||||||
|
|
||||||
|
def on_created(self, event):
|
||||||
|
if event.is_directory:
|
||||||
|
return
|
||||||
|
if event.src_path.lower().endswith('.csv'):
|
||||||
|
file_path = os.path.abspath(event.src_path)
|
||||||
|
print(f"发现CSV文件: {file_path}")
|
||||||
|
|
||||||
|
# 选择定标文件夹
|
||||||
|
cal_dir = self.ftp_config['monitor']['cal_dir']
|
||||||
|
a=1
|
||||||
|
if "towersif20" in file_path:
|
||||||
|
cal_dir = os.path.join(cal_dir,"20")
|
||||||
|
elif "towersif21" in file_path:
|
||||||
|
cal_dir = os.path.join(cal_dir,"21")
|
||||||
|
|
||||||
|
time.sleep(0.1) # 文件一出现就处理文件,偶发permission deny,所以等待100ms
|
||||||
|
_ = self.process_csv(file_path, cal_dir)
|
||||||
|
|
||||||
|
# 为csv添加有效性字段
|
||||||
|
for i in _:
|
||||||
|
self.add_validity_column_to_file(i)
|
||||||
|
|
||||||
|
self.send_via_sftp(_)
|
||||||
|
|
||||||
|
def send_via_sftp(self, file_paths, max_retries=3, retry_delay=5):
|
||||||
|
retries = 0
|
||||||
|
ssh = None
|
||||||
|
sftp = None
|
||||||
|
|
||||||
|
while retries < max_retries:
|
||||||
|
try:
|
||||||
|
print("正在尝试连接 SFTP 服务器...")
|
||||||
|
|
||||||
|
# 创建 SSH 客户端
|
||||||
|
ssh = paramiko.SSHClient()
|
||||||
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 生产环境建议更安全的方式
|
||||||
|
|
||||||
|
# 连接参数(参考 FileZilla 的设置)
|
||||||
|
ssh.connect(
|
||||||
|
hostname=self.ftp_config['FTP']['host'],
|
||||||
|
port=int(self.ftp_config['FTP'].get('port', 22)),
|
||||||
|
username=self.ftp_config['FTP']['user'],
|
||||||
|
password=self.ftp_config['FTP']['password'],
|
||||||
|
timeout=30,
|
||||||
|
allow_agent=False, # 禁用 ssh-agent(避免 'lost ssh-agent' 错误)
|
||||||
|
look_for_keys=False, # 不自动查找密钥(强制使用密码认证)
|
||||||
|
)
|
||||||
|
|
||||||
|
print("SFTP 连接成功,准备上传文件...")
|
||||||
|
sftp = ssh.open_sftp()
|
||||||
|
|
||||||
|
# 检查并切换到目标目录
|
||||||
|
remote_dir = self.ftp_config['FTP'].get('target_dir', '.')
|
||||||
|
try:
|
||||||
|
sftp.chdir(remote_dir) # 尝试进入目录
|
||||||
|
except IOError:
|
||||||
|
print(f"远程目录不存在,尝试创建: {remote_dir}")
|
||||||
|
sftp.mkdir(remote_dir) # 尝试创建目录
|
||||||
|
sftp.chdir(remote_dir)
|
||||||
|
|
||||||
|
# 上传多个文件
|
||||||
|
success_count = 0
|
||||||
|
for file_path in file_paths:
|
||||||
|
try:
|
||||||
|
filename = os.path.basename(file_path)
|
||||||
|
sftp.put(file_path, filename)
|
||||||
|
print(f"✅ 文件上传成功: {filename}")
|
||||||
|
success_count += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 文件上传失败 {file_path}: {e}")
|
||||||
|
|
||||||
|
return success_count == len(file_paths) # 全部成功返回True,否则False
|
||||||
|
|
||||||
|
except paramiko.AuthenticationException as e:
|
||||||
|
print(f"❌ 认证失败: {e}")
|
||||||
|
return False
|
||||||
|
except paramiko.SSHException as e:
|
||||||
|
retries += 1
|
||||||
|
print(f"❌ SFTP 连接失败(尝试 {retries}/{max_retries}): {e}")
|
||||||
|
if retries < max_retries:
|
||||||
|
time.sleep(retry_delay)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 未知错误: {e}")
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if sftp:
|
||||||
|
sftp.close()
|
||||||
|
if ssh:
|
||||||
|
ssh.close()
|
||||||
|
|
||||||
|
print(f"❌ 上传失败(已达最大重试次数 {max_retries})")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def process_csv(self, input_csv, input_cal):
|
||||||
|
# 提取文件夹路径
|
||||||
|
folder_path = os.path.dirname(input_csv)
|
||||||
|
base_name = os.path.basename(input_csv) # 获取文件名(含扩展名)
|
||||||
|
name_part, ext = os.path.splitext(base_name) # 拆分文件名和扩展名
|
||||||
|
parts = name_part.split('_', 1) # 在第一个 _ 处分割
|
||||||
|
today = datetime.now()
|
||||||
|
formatted_date = today.strftime("%Y_%m_%d")
|
||||||
|
new_name = f"{formatted_date}_{parts[1]}{ext}" # 组合新文件名
|
||||||
|
|
||||||
|
# tmp_folder = os.path.join(os.path.dirname(ftp_config['monitor']['WATCH_DIR']), "tmp")
|
||||||
|
tmp_folder = os.path.join(Path(ftp_config['monitor']['WATCH_DIR']).parent, "tmp")
|
||||||
|
if not os.path.exists(tmp_folder):
|
||||||
|
os.makedirs(tmp_folder)
|
||||||
|
print(f"文件夹已创建: {tmp_folder}")
|
||||||
|
else:
|
||||||
|
print(f"文件夹已存在: {tmp_folder}")
|
||||||
|
|
||||||
|
rad_folder = os.path.join(tmp_folder, "rad")
|
||||||
|
if os.path.exists(rad_folder):
|
||||||
|
shutil.rmtree(rad_folder)
|
||||||
|
os.makedirs(rad_folder)
|
||||||
|
|
||||||
|
sif_folder = os.path.join(tmp_folder, "sif")
|
||||||
|
if not os.path.exists(sif_folder):
|
||||||
|
os.makedirs(sif_folder)
|
||||||
|
print(f"文件夹已创建: {sif_folder}")
|
||||||
|
else:
|
||||||
|
print(f"文件夹已存在: {sif_folder}")
|
||||||
|
|
||||||
|
rad_path = os.path.join(rad_folder, new_name)
|
||||||
|
|
||||||
|
metadata, wavelengths, spectra_data = parse_sif_csv(input_csv)
|
||||||
|
|
||||||
|
sorted_cal_files_path = get_sorted_files_by_number(input_cal)
|
||||||
|
for i in range(len(spectra_data)):
|
||||||
|
uiExposureTimeInMS, fTemperature, iPixels, fWaveLength, dCal_Gain, dCal_Offset = read_cal(
|
||||||
|
sorted_cal_files_path[i])
|
||||||
|
|
||||||
|
gain_scale = uiExposureTimeInMS / spectra_data[i]['Integration']
|
||||||
|
data_gain_adjust = dCal_Gain * gain_scale
|
||||||
|
spectra_data[i]['RAD'] = spectra_data[i]['DN'] * data_gain_adjust
|
||||||
|
|
||||||
|
write_file(input_csv, rad_path, spectra_data)
|
||||||
|
|
||||||
|
# 调用丰算法
|
||||||
|
if os.name == "nt": # Windows
|
||||||
|
program_path = r"python D:\PycharmProjects\sif\sif_retrieval.py"
|
||||||
|
standard_sif_path = r"C:\EasySIF\standard_sif.csv"
|
||||||
|
elif os.name == "posix": # Linux/macOS/Unix-like
|
||||||
|
program_path = r"python3 /root/sif/feng/sif_retrieval.py"
|
||||||
|
standard_sif_path = r"/root/sif/feng/standard_sif.csv"
|
||||||
|
|
||||||
|
input_path = rad_folder
|
||||||
|
|
||||||
|
file_name_tmp = parts[0] + "_" + new_name.split('.')[0]
|
||||||
|
|
||||||
|
output_path_3fld = os.path.join(sif_folder, file_name_tmp + "_3fld.csv")
|
||||||
|
param_3fld = r"[740,780],[756,759],[761,762] P1 3fld"
|
||||||
|
|
||||||
|
output_path_sfld = os.path.join(sif_folder, file_name_tmp + "_sfld.csv")
|
||||||
|
param_sfld = r"[740,780],[756,759] P1 sfld"
|
||||||
|
|
||||||
|
output_path_sfm = os.path.join(sif_folder, file_name_tmp + "_sfm.csv")
|
||||||
|
param_sfm = r" [759,770],760 P1 sfm"
|
||||||
|
|
||||||
|
command_str_3fld = program_path + " " + standard_sif_path + " " + input_path + " " + output_path_3fld + " " + param_3fld
|
||||||
|
command_str_sfld = program_path + " " + standard_sif_path + " " + input_path + " " + output_path_sfld + " " + param_sfld
|
||||||
|
command_str_sfm = program_path + " " + standard_sif_path + " " + input_path + " " + output_path_sfm + " " + param_sfm
|
||||||
|
|
||||||
|
return_code = os.system(command_str_3fld)
|
||||||
|
return_code = os.system(command_str_sfld)
|
||||||
|
return_code = os.system(command_str_sfm)
|
||||||
|
print(f"命令返回状态码: {return_code}")
|
||||||
|
|
||||||
|
return output_path_3fld, output_path_sfld, output_path_sfm
|
||||||
|
|
||||||
|
def add_validity_column_to_file(self, file_path):
|
||||||
|
# 创建临时文件
|
||||||
|
temp_file = tempfile.NamedTemporaryFile(mode='w', delete=False, newline='')
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', newline='') as csvfile, temp_file:
|
||||||
|
reader = csv.reader(csvfile)
|
||||||
|
writer = csv.writer(temp_file)
|
||||||
|
|
||||||
|
# 读取所有行
|
||||||
|
rows = list(reader)
|
||||||
|
|
||||||
|
if len(rows) < 2:
|
||||||
|
return # 如果行数不足,直接返回
|
||||||
|
|
||||||
|
# 添加validity列
|
||||||
|
rows[0].append('validity')
|
||||||
|
rows[1].append('1')
|
||||||
|
|
||||||
|
# 写入临时文件
|
||||||
|
writer.writerows(rows)
|
||||||
|
|
||||||
|
# 用临时文件替换原始文件
|
||||||
|
shutil.move(temp_file.name, file_path)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 如果出错,删除临时文件
|
||||||
|
os.unlink(temp_file.name)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
# Press the green button in the gutter to run the script.
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser(description="监控文件夹的状态,当出现新的csv时,提取sif,并通过ftp发送。", prog='sif.')
|
||||||
|
|
||||||
|
parser.add_argument('-i', '--input_ini', required=True, type=str, help='输入ini配置文件路径。')
|
||||||
|
|
||||||
|
parser.add_argument("-v", "--version", action='version', version='%(prog)s 1.0')
|
||||||
|
# parser.add_argument('-v', '--verbose', action='store_true', help='启用详细模式')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
ftp_config = load_config(args.input_ini)
|
||||||
|
event_handler = CSVFileHandler(ftp_config)
|
||||||
|
observer = Observer()
|
||||||
|
observer.schedule(event_handler, ftp_config['monitor']['WATCH_DIR'], recursive=True)
|
||||||
|
observer.start()
|
||||||
|
print(f"正在监控目录:{ftp_config['monitor']['WATCH_DIR']}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
time.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
observer.stop()
|
||||||
|
observer.join()
|
Reference in New Issue
Block a user