Initial commit: GasFlux project with core processing pipelines

This commit is contained in:
2026-01-05 09:33:27 +08:00
commit f085d7c5fe
50 changed files with 10634 additions and 0 deletions

140
.gitignore vendored Normal file
View File

@ -0,0 +1,140 @@
# repo stuff
survey
# 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/
pip-wheel-metadata/
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/
# 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
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.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
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__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/
# VSCode
.vscode/
# Node modules for this repo
package.json
package-lock.json
node_modules/

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

23
.idea/gasflux-develop.iml generated Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="gasflux2" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/src/gasflux/templates" />
</list>
</option>
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="py.test" />
</component>
</module>

View File

@ -0,0 +1,35 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="22">
<item index="0" class="java.lang.String" itemvalue="catboost" />
<item index="1" class="java.lang.String" itemvalue="opencv-python" />
<item index="2" class="java.lang.String" itemvalue="xgboost" />
<item index="3" class="java.lang.String" itemvalue="opencv-python-headless" />
<item index="4" class="java.lang.String" itemvalue="zstandard" />
<item index="5" class="java.lang.String" itemvalue="scikit-image" />
<item index="6" class="java.lang.String" itemvalue="scipy" />
<item index="7" class="java.lang.String" itemvalue="tensorflow_gpu" />
<item index="8" class="java.lang.String" itemvalue="h5py" />
<item index="9" class="java.lang.String" itemvalue="matplotlib" />
<item index="10" class="java.lang.String" itemvalue="numpy" />
<item index="11" class="java.lang.String" itemvalue="opencv_python" />
<item index="12" class="java.lang.String" itemvalue="Pillow" />
<item index="13" class="java.lang.String" itemvalue="tensorflow" />
<item index="14" class="java.lang.String" itemvalue="jupyter" />
<item index="15" class="java.lang.String" itemvalue="ipykernel" />
<item index="16" class="java.lang.String" itemvalue="pandas" />
<item index="17" class="java.lang.String" itemvalue="Werkzeug" />
<item index="18" class="java.lang.String" itemvalue="cellpose" />
<item index="19" class="java.lang.String" itemvalue="torchvision" />
<item index="20" class="java.lang.String" itemvalue="Flask" />
<item index="21" class="java.lang.String" itemvalue="fiona" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="gasflux_env" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="gasflux2" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/gasflux-develop.iml" filepath="$PROJECT_DIR$/.idea/gasflux-develop.iml" />
</modules>
</component>
</project>

72
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,72 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-added-large-files # prevents giant files from being committed
args: ["--maxkb=1024"]
- id: check-ast # simply checks whether the files parse as valid python
- id: check-builtin-literals # requires literal syntax when initializing empty or zero python builtin types
- id: check-case-conflict # checks for files that would conflict in case-insensitive filesystems
- id: check-docstring-first # checks a common error of defining a docstring after code
- id: check-executables-have-shebangs # ensures that (non-binary) executables have a shebang
- id: pretty-format-json # pretty formats json files
- id: check-json # checks json files for syntax errors
- id: check-merge-conflict # prevents git merge conflicts from being committed (finds conflict markers)
- id: check-shebang-scripts-are-executable # ensures that (non-binary) files with a shebang are executable
- id: check-toml # checks toml files for syntax errors
- id: check-vcs-permalinks # ensures that links to vcs websites are permalinks
- id: check-yaml # checks yaml files for parseable syntax
- id: debug-statements # checks for debugger imports and py37+ `breakpoint()` calls in python source
# - id: detect-aws-credentials # detects *your* aws credentials from the aws cli credentials file
- id: detect-private-key # detects the presence of private keys
- id: end-of-file-fixer # ensures that a file is either empty, or ends with one newline
files: ^.*py$
- id: mixed-line-ending # replaces or checks mixed line ending
files: ^.*py$
- id: no-commit-to-branch
args: ["--branch", "main", "--branch", "develop"]
- id: requirements-txt-fixer # sorts entries in requirements.txt
- id: trailing-whitespace # trims trailing whitespace
files: ^.*py$
- repo: local
hooks:
- id: nbdev
name: nbdev clean
entry: nbdev_clean --clear_all
pass_filenames: false
language: python
files: .ipynb
- id: mypy
name: mypy
entry: mypy
language: python
files: ^.*py$
- id: vulture
name: vulture
entry: vulture
args: ["--min-confidence", "61"]
language: python
files: ^.*py$
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.5
hooks:
- id: ruff
types_or: [python, pyi, jupyter]
args: [--fix]
- id: ruff-format
types_or: [python, pyi, jupyter]
# ci:
# autofix_commit_msg: |
# [pre-commit.ci] auto fixes from pre-commit.com hooks
# for more information, see https://pre-commit.ci
# autofix_prs: true
# autoupdate_branch: ""
# autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate"
# autoupdate_schedule: monthly
# skip: []
# submodules: false

253
3DVIEW_README.md Normal file
View File

@ -0,0 +1,253 @@
# 3D轨迹可视化工具
一个用于将GPS轨迹数据转换为可交互3D可视化的Python工具。
## 功能特性
- 🎯 **多格式支持**: 支持CSV和Excel文件 (.csv, .xlsx, .xls)
- 📊 **3D交互式图表**: 基于Plotly的完全可交互3D可视化
- 🎨 **智能着色**: 按高程自动着色,颜色映射到海拔高度
- 🔧 **灵活配置**: 可自定义列索引、工作表等参数
- 📱 **响应式设计**: 生成的HTML可在任何现代浏览器中查看
## 数据格式要求
### 文件格式
- **CSV文件**: 逗号分隔值文件
- **Excel文件**: .xlsx 或 .xls 格式
### 数据列要求
文件至少需要包含4列数据按以下顺序排列
| 列索引 | 列名 | 数据类型 | 说明 |
|--------|------|----------|------|
| 0 | 经度 | 数值 | GPS经度坐标原始格式 |
| 1 | 纬度 | 数值 | GPS纬度坐标原始格式 |
| 2 | 高程 | 数值 | 飞行器高程(可选) |
| 3 | 融合高程 | 数值 | 融合后的高程数据 |
### 数据示例
**CSV格式**:
```csv
1157855289,403491370,500110,435.789
1157855290,403491371,500111,436.123
1157855291,403491372,500112,437.456
```
**Excel格式**:
- 第一行(如果有标题)将被忽略
- 数据从第二行开始读取
### 坐标转换
- 经纬度数据会自动除以 10^7 进行单位转换
- 这是因为原始GPS数据通常以放大整数形式存储
## 安装依赖
```bash
pip install pandas plotly openpyxl
```
## 使用方法
### 1. 命令行使用
#### 基本用法
```bash
# 处理CSV文件
python 3Dview.py data.csv
# 处理Excel文件
python 3Dview.py trajectory.xlsx
# 指定输出文件
python 3Dview.py data.csv -o my_visualization.html
```
#### 高级参数
```bash
# 自定义列索引
python 3Dview.py data.xlsx --lon-col 1 --lat-col 2 --alt-col 4
# 指定Excel工作表
python 3Dview.py data.xlsx --sheet-name "Flight_Data"
# 自定义标题
python 3Dview.py data.csv --title "无人机飞行轨迹"
# 组合使用
python 3Dview.py trajectory.xlsx \
--lon-col 0 \
--lat-col 1 \
--alt-col 3 \
--sheet-name 0 \
--output flight_path.html \
--title "2024年飞行数据"
```
### 2. Python代码调用
#### 基本调用
```python
from 3Dview import main
# 处理CSV文件
success = main('trajectory.csv')
# 处理Excel文件
success = main('flight_data.xlsx', sheet_name='Sheet1')
```
#### 完整参数调用
```python
from 3Dview import main
success = main(
input_file='drone_trajectory.xlsx',
output_file='visualization.html',
lon_col=0, # 经度列索引
lat_col=1, # 纬度列索引
alt_col=3, # 融合高程列索引
sheet_name=0, # Excel工作表索引
title='无人机轨迹3D可视化'
)
if success:
print("可视化生成成功!")
```
## 输出结果
### HTML文件内容
- **3D散点图**: 每个数据点在三维空间中的位置
- **颜色编码**: 点的颜色根据高程自动映射
- **交互功能**: 支持旋转、缩放、平移等操作
### 控制说明
- **鼠标左键拖拽**: 旋转视角
- **鼠标滚轮**: 缩放视图
- **鼠标右键拖拽**: 平移视图
- **双击**: 重置到初始视角
- **悬停**: 显示数据点的详细信息
## 参数说明
### 命令行参数
| 参数 | 简称 | 默认值 | 说明 |
|------|------|--------|------|
| `input_file` | - | 必需 | 输入文件路径 |
| `--output` | `-o` | `3d_view.html` | 输出HTML文件路径 |
| `--lon-col` | - | `0` | 经度列索引 |
| `--lat-col` | - | `1` | 纬度列索引 |
| `--alt-col` | - | `3` | 融合高程列索引 |
| `--sheet-name` | - | `0` | Excel工作表名称或索引 |
| `--delimiter` | - | `None` | CSV分隔符自动检测 |
| `--title` | - | `3D轨迹可视化` | 图表标题 |
### 函数参数
```python
def main(
input_file, # 输入文件路径
output_file='3d_view.html', # 输出文件路径
lon_col=0, # 经度列索引
lat_col=1, # 纬度列索引
alt_col=3, # 高程列索引
delimiter=None, # CSV分隔符
title='3D轨迹可视化', # 图表标题
sheet_name=0 # Excel工作表
):
```
## 故障排除
### 常见问题
#### 1. 文件读取错误
```
错误:输入文件不存在: xxx
```
**解决**: 检查文件路径是否正确,文件是否存在
#### 2. 列数不足
```
数据文件至少需要4列经度、纬度、高程、融合高程。当前只有X列。
```
**解决**: 检查数据文件格式,确保包含所需列
#### 3. Excel工作表不存在
```
Worksheet 'Sheet1' not found
```
**解决**: 检查Excel文件中的工作表名称或使用索引如0
#### 4. 坐标转换问题
如果坐标显示不正确,检查:
- 经纬度数据格式是否正确
- 单位转换是否合适除以10^7
### 数据验证
运行脚本时会显示以下统计信息:
```
成功加载数据XXX 个数据点
经度范围: XXX.XXXXXX - XXX.XXXXXX
纬度范围: XXX.XXXXXX - XXX.XXXXXX
高程范围: XXX.XX - XXX.XX 米
```
## 示例应用
### 无人机飞行轨迹
```python
from 3Dview import main
# 可视化无人机飞行路径
main(
input_file='drone_flight.xlsx',
output_file='drone_path_3d.html',
title='无人机飞行轨迹3D可视化',
sheet_name='GPS_Data'
)
```
### 地面车辆轨迹
```python
from 3Dview import main
# 可视化车辆行驶轨迹
main(
input_file='vehicle_gps.csv',
output_file='vehicle_path.html',
title='车辆轨迹可视化',
alt_col=2 # 如果没有高程数据,使用其他列
)
```
## 技术细节
### 依赖库
- **pandas**: 数据处理
- **plotly**: 3D可视化
- **openpyxl**: Excel文件读取
### 坐标系统
- 输入: 原始GPS坐标通常为度×10^-7
- 处理: 转换为标准经纬度坐标
- 显示: WGS84地理坐标系
### 性能考虑
- 大文件处理: 建议分批处理超大数据集
- 内存使用: 每个数据点占用约50-100字节内存
- 渲染性能: 浏览器对大量数据点的渲染有限制
## 许可证
本工具遵循与主项目相同的许可证。
---
**版本**: 1.0.0
**最后更新**: 2024年12月

370
3Dview.py Normal file
View File

@ -0,0 +1,370 @@
#!/usr/bin/env python3
"""
3D可视化脚本 - 显示经纬度高程数据
读取CSV文件中的经度、纬度、融合高程数据
生成可交互的三维点图输出为HTML格式。
数据格式要求:
经度 纬度 高程 融合高程
经纬度坐标需要除以10^-7进行单位转换。
"""
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio
import argparse
import sys
import numpy as np
from pathlib import Path
def load_and_process_data(file_path, lon_col=0, lat_col=1, alt_col=3, delimiter=None, sheet_name=0):
"""
加载并处理CSV或Excel数据
Args:
file_path: 文件路径 (支持.csv, .xlsx, .xls)
lon_col: 经度列索引 (默认0)
lat_col: 纬度列索引 (默认1)
alt_col: 高程列索引 (默认3为融合高程)
delimiter: CSV分隔符None表示自动检测
sheet_name: Excel工作表名称或索引 (默认0)
Returns:
pandas.DataFrame: 处理后的数据
"""
try:
file_path_obj = Path(file_path)
# 根据文件扩展名选择读取方式
if file_path_obj.suffix.lower() in ['.xlsx', '.xls']:
# 读取Excel文件
print(f"检测到Excel文件: {file_path}")
df = pd.read_excel(file_path, sheet_name=sheet_name, header=None)
else:
# 读取CSV文件
print(f"检测到CSV文件: {file_path}")
df = pd.read_csv(file_path, delimiter=delimiter, header=None)
# 验证数据列数
if df.shape[1] < 4:
raise ValueError(f"数据文件至少需要4列经度、纬度、高程、融合高程。当前只有{df.shape[1]}列。")
# 显示前几行数据以便调试
print(f"数据预览 (前3行):")
print(df.head(3))
print()
# 提取所需列
lon_raw = df.iloc[:, lon_col] # 经度(原始格式)
lat_raw = df.iloc[:, lat_col] # 纬度(原始格式)
altitude = df.iloc[:, alt_col] # 融合高程
# 数据类型转换和清理
try:
lon_raw = pd.to_numeric(lon_raw, errors='coerce')
lat_raw = pd.to_numeric(lat_raw, errors='coerce')
altitude = pd.to_numeric(altitude, errors='coerce')
except Exception as e:
print(f"数据类型转换失败: {e}")
print("尝试手动转换...")
# 手动转换函数
def safe_convert(value):
try:
return float(value)
except (ValueError, TypeError):
return np.nan
lon_raw = lon_raw.apply(safe_convert)
lat_raw = lat_raw.apply(safe_convert)
altitude = altitude.apply(safe_convert)
# 检查转换结果
nan_count_lon = lon_raw.isna().sum()
nan_count_lat = lat_raw.isna().sum()
nan_count_alt = altitude.isna().sum()
if nan_count_lon > 0 or nan_count_lat > 0 or nan_count_alt > 0:
print(f"警告:发现无效数据点 - 经度: {nan_count_lon}, 纬度: {nan_count_lat}, 高程: {nan_count_alt}")
print("无效数据点将被移除")
# 移除NaN值
valid_mask = ~(lon_raw.isna() | lat_raw.isna() | altitude.isna())
lon_raw = lon_raw[valid_mask]
lat_raw = lat_raw[valid_mask]
altitude = altitude[valid_mask]
if len(lon_raw) == 0:
raise ValueError("没有有效的坐标数据")
# 经纬度单位转换 (除以10^7)
longitude = lon_raw / 1e7
latitude = lat_raw / 1e7
# 创建处理后的DataFrame
processed_df = pd.DataFrame({
'longitude': longitude,
'latitude': latitude,
'altitude': altitude
})
print(f"成功加载数据:{len(processed_df)} 个数据点")
print(f"经度范围: {longitude.min():.6f} - {longitude.max():.6f}")
print(f"纬度范围: {latitude.min():.6f} - {latitude.max():.6f}")
print(f"高程范围: {altitude.min():.2f} - {altitude.max():.2f}")
return processed_df
except Exception as e:
print(f"数据加载失败: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
def create_3d_plot(df, title="3D轨迹可视化", output_file="3d_view.html"):
"""
创建三维散点图
Args:
df: 包含longitude, latitude, altitude列的DataFrame
title: 图表标题
output_file: 输出HTML文件路径
"""
# 创建3D散点图
fig = go.Figure(data=[go.Scatter3d(
x=df['longitude'],
y=df['latitude'],
z=df['altitude'],
mode='markers',
marker=dict(
size=3,
color=df['altitude'], # 颜色映射到高程
colorscale='Viridis', # 颜色方案
colorbar=dict(title="高程 (m)"),
opacity=0.8
),
hovertemplate=(
'经度: %{x:.6f}<br>' +
'纬度: %{y:.6f}<br>' +
'高程: %{z:.2f} m<br>' +
'<extra></extra>'
)
)])
# 设置布局
fig.update_layout(
title=title,
scene=dict(
xaxis_title='经度',
yaxis_title='纬度',
zaxis_title='高程 (m)',
xaxis=dict(showgrid=True, gridcolor='lightgray'),
yaxis=dict(showgrid=True, gridcolor='lightgray'),
zaxis=dict(showgrid=True, gridcolor='lightgray'),
# 设置视角
camera=dict(
eye=dict(x=1.5, y=1.5, z=1.5) # 初始视角位置
)
),
margin=dict(l=0, r=0, b=0, t=40),
paper_bgcolor='white',
plot_bgcolor='white'
)
# 添加交互说明
fig.add_annotation(
text="鼠标拖拽旋转视角,滚轮缩放,双击重置",
xref="paper", yref="paper",
x=0.02, y=0.98,
showarrow=False,
bgcolor="rgba(255,255,255,0.8)",
bordercolor="black",
borderwidth=1
)
# 保存为HTML文件
try:
pio.write_html(fig, file=output_file, auto_open=False)
print(f"3D可视化已保存到: {output_file}")
print("在浏览器中打开该文件即可查看可交互的3D图表")
except Exception as e:
print(f"保存HTML文件失败: {e}")
sys.exit(1)
return fig
def main(input_file, output_file='3d_view.html', lon_col=2, lat_col=3, alt_col=5,
delimiter=None, title='3D轨迹可视化', sheet_name=0):
"""
直接调用函数生成3D可视化
Args:
input_file: 输入文件路径 (支持.csv, .xlsx, .xls)
output_file: 输出HTML文件路径
lon_col: 经度列索引 (默认: 0)
lat_col: 纬度列索引 (默认: 1)
alt_col: 融合高程列索引 (默认: 3)
delimiter: CSV分隔符 (默认: 自动检测)
title: 图表标题 (默认: '3D轨迹可视化')
sheet_name: Excel工作表名称或索引 (默认: 0)
"""
# 检查输入文件
input_path = Path(input_file)
if not input_path.exists():
print(f"错误:输入文件不存在: {input_path}")
return False
print(f"正在处理文件: {input_path}")
print(f"输出文件: {output_file}")
print("-" * 50)
try:
# 加载和处理数据
df = load_and_process_data(
file_path=input_path,
lon_col=lon_col,
lat_col=lat_col,
alt_col=alt_col,
delimiter=delimiter,
sheet_name=sheet_name
)
# 创建3D图表
fig = create_3d_plot(
df=df,
title=title,
output_file=output_file
)
print("-" * 50)
print("处理完成!")
print(f"\n✅ 3D可视化已保存到: {output_file}")
print("\n使用说明:")
print("- 在浏览器中打开生成的HTML文件")
print("- 鼠标左键拖拽:旋转视角")
print("- 鼠标滚轮:缩放视图")
print("- 双击:重置到初始视角")
print("- 右键拖拽:平移视图")
return True
except Exception as e:
print(f"❌ 处理失败: {e}")
import traceback
traceback.print_exc()
return False
# 命令行接口(保持兼容性)
def cli_main():
"""命令行接口"""
parser = argparse.ArgumentParser(
description="3D轨迹可视化工具 - 将CSV数据转换为可交互的3D点图",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用示例:
# CSV文件
python 3Dview.py data.csv
python 3Dview.py data.csv -o custom_output.html
python 3Dview.py data.csv --lon-col 1 --lat-col 2 --alt-col 4
# Excel文件
python 3Dview.py trajectory.xlsx
python 3Dview.py data.xlsx --sheet-name "Sheet1"
数据格式:
文件应包含至少4列经度 纬度 高程 融合高程
支持格式: CSV (.csv), Excel (.xlsx, .xls)
经纬度将自动除以10^7进行单位转换
直接调用示例:
from 3Dview import main
main('data.xlsx', sheet_name='Sheet1') # Excel文件
main('data.csv', lon_col=0, lat_col=1, alt_col=3) # CSV文件
"""
)
parser.add_argument('input_file', help='输入CSV文件路径')
parser.add_argument('-o', '--output', default='3d_view.html',
help='输出HTML文件路径 (默认: 3d_view.html)')
parser.add_argument('--lon-col', type=int, default=0,
help='经度列索引 (默认: 0)')
parser.add_argument('--lat-col', type=int, default=1,
help='纬度列索引 (默认: 1)')
parser.add_argument('--alt-col', type=int, default=3,
help='融合高程列索引 (默认: 3)')
parser.add_argument('--delimiter', default=None,
help='CSV分隔符 (默认: 自动检测)')
parser.add_argument('--title', default='3D轨迹可视化',
help='图表标题 (默认: 3D轨迹可视化)')
parser.add_argument('--sheet-name', default=0,
help='Excel工作表名称或索引 (默认: 0)')
args = parser.parse_args()
success = main(
input_file=args.input_file,
output_file=args.output,
lon_col=args.lon_col,
lat_col=args.lat_col,
alt_col=args.alt_col,
delimiter=args.delimiter,
title=args.title,
sheet_name=args.sheet_name
)
if not success:
sys.exit(1)
# 示例用法
if __name__ == "__main__":
# 检查是否有命令行参数
if len(sys.argv) > 1:
# 使用命令行接口
cli_main()
else:
# 直接调用示例
print("3D可视化工具使用示例")
print("=" * 50)
# 示例1: 处理Excel文件
print("\n示例1: 处理Excel数据文件")
excel_file = r"C:\Users\HL\Documents\xwechat_files\wxid_rdrswaol1qsr21_737e\msg\file\2025-12\08_51_15_间隔高度10m.xlsx"
if Path(excel_file).exists():
success = main(
input_file=excel_file,
output_file='./10m_3d_view.html',
title='无人机轨迹3D可视化示例'
)
else:
print(f"示例文件不存在: {excel_file}")
print("请提供正确的Excel文件路径")
success = False
if success:
print("\n示例代码:")
print("""
# 直接调用示例
from 3Dview import main
# 处理Excel文件
main('data.xlsx', sheet_name=0) # 指定工作表
# 处理CSV文件
main('data.csv')
# 自定义参数
main(
input_file='trajectory.xlsx',
output_file='flight_path.html',
lon_col=0, # 经度列索引
lat_col=1, # 纬度列索引
alt_col=3, # 融合高程列索引
sheet_name=0, # Excel工作表
title='飞行轨迹可视化'
)
""")

295
DATA_PROCESSOR_README.md Normal file
View File

@ -0,0 +1,295 @@
# 无人机数据处理工具
将Excel格式的无人机测量数据转换为GasFlux标准输入格式的完整解决方案。
## 📋 处理流程
### 输入数据格式
Excel文件必须包含以下列顺序可以不同
| 列名 | 数据类型 | 说明 |
|------|----------|------|
| `日期` | 字符串 | 日期 (YYYY-MM-DD 或 YYYY/MM/DD) |
| `时间` | 字符串 | 时间 (HH:MM:SS 或 H:MM:SS) |
| `经度` | 数值 | GPS经度坐标 (原始大数值) |
| `纬度` | 数值 | GPS纬度坐标 (原始大数值) |
| `高程` | 数值 | 飞行器高程 |
| `融合高程` | 数值 | 融合后的海拔高度 |
| `速度x` | 数值 | 东向速度分量 |
| `速度y` | 数值 | 北向速度分量 |
| `速度z` | 数值 | 垂直速度分量 |
| `四元数_q0-q3` | 数值 | 姿态四元数 |
| `pitch` | 数值 | 俯仰角 |
| `roll` | 数值 | 横滚角 |
| `yaw` | 数值 | 偏航角 |
| `CH4` | 数值 | 甲烷浓度 |
| `H2O` | 数值 | 水蒸气浓度 |
| `修正风向` | 数值 | 修正后的风向 |
| `修正风速` | 数值 | 修正后的风速 |
| `原始风向` | 数值 | 原始风向 |
| `原始风速` | 数值 | 原始风速 |
| `风温` | 数值 | 风温 (温度) |
## 🔄 处理步骤详解
### 1. 列删除
自动删除以下不需要的列:
- `高程`, `速度x`, `速度y`, `速度z`
- `四元数_q0`, `四元数_q1`, `四元数_q2`, `四元数_q3`
- `pitch`, `roll`, `yaw`
- `H2O`, `原始风向`, `原始风速`
### 2. 时间修正
根据文件名提取小时信息并修正时间列:
**文件名示例**: `08_34_01_间隔高度5m.xlsx`
- 提取: `08` (小时)
- 时间转换: `0:34:01``08:34:01`
### 3. 坐标转换
经纬度坐标除以 `10^7` 进行单位转换:
```
原始经度: 1157855289 → 转换后: 115.7855289
原始纬度: 403491370 → 转换后: 40.3491370
```
### 4. 气压计算(智能优化)
使用 `qiya.py` 模块智能计算地面气压,支持两种计算模式:
#### 🎯 三级智能计算策略
- **高度变化小**默认容差≤10米只计算一次平均气压应用到所有行
- **中等变化**:使用高度分档策略,每个档位计算一次气压
- **高度变化大**:逐行计算气压,支持进度条显示
#### 📏 高度分档优化
- **分档间隔**默认2米一个档位可自定义
- **档位计算**:每个档位使用中间高度和平均位置计算一次气压
- **减少API调用**:大幅降低重复计算,提高效率
#### 📊 计算参数
- **日期格式**: 转换为 `YYYY-MM-DD`(自动提取日期部分)
- **时间格式**: 提取小时部分 `HH`
- **海拔高度**: 使用 `融合高程` 列或档位中心高度
- **API调用**: Open-Meteo 历史天气数据
- **进度条**: 自动显示计算进度需要安装tqdm
#### ⚙️ 自定义参数
```python
# 自定义参数
df = calculate_pressure(
df,
max_samples=None,
height_tolerance=10.0, # 高度变化容差
height_bin_size=2.0 # 高度分档间隔
)
```
### 5. 高度调整
`融合高程` 进行基准调整:
```
调整后高度 = 原始高度 - 最小高度
```
### 6. 时间戳融合
`日期``时间` 列合并:
```
输入: 日期="2024-01-15", 时间="08:34:01"
输出: timestamp="2024-01-15 08:34:01"
```
### 7. 字段重命名
转换为GasFlux标准字段名
| 原始字段 | GasFlux字段 | 数据类型 |
|----------|-------------|----------|
| `日期+时间` | `timestamp` | datetime |
| `经度` | `latitude` | float |
| `纬度` | `longitude` | float |
| `融合高程` | `height_ato` | float |
| `修正风向` | `windir` | float |
| `修正风速` | `windspeed` | float |
| `风温` | `temperature` | float |
| `气压计算结果` | `pressure` | float |
| `CH4` | `ch4` | float |
## 🚀 使用方法
### 1. 交互式输入模式(推荐新用户)
```bash
# 直接运行脚本,会自动进入交互式模式
python data_processor.py
# 或者明确指定交互式模式
python data_processor.py --interactive
```
在交互式模式下,程序会提示您:
- 输入Excel文件路径
- 指定输出CSV文件路径可选
- 确认处理参数
### 2. 命令行参数模式
```bash
# 基本用法
python data_processor.py your_data.xlsx
# 指定输出路径
python data_processor.py input.xlsx -o output.csv
# 查看帮助
python data_processor.py --help
```
### 3. Python脚本直接调用推荐
```python
# 最简单的方式
from src.gasflux.data_processor import process_file
# 处理文件并返回DataFrame
df = process_file('your_data.xlsx')
# 或者指定输出文件名
df = process_file('input.xlsx', 'output.csv')
# 使用返回的DataFrame进行进一步分析
print(df.head())
print(df['ch4'].describe())
```
### 4. 完整使用脚本
复制以下代码到新文件(如 `process_my_data.py`
```python
from src.gasflux.data_processor import process_file
# 修改这里的输入文件名
input_file = "08_34_01_间隔高度5m.xlsx" # 您的Excel文件名
output_file = "processed_data.csv" # 输出文件名(可选)
try:
df = process_file(input_file, output_file)
print("✅ 处理成功!")
print(f"数据形状: {df.shape}")
print(f"列名: {list(df.columns)}")
print(df.head())
except Exception as e:
print(f"❌ 处理失败: {e}")
```
### Python代码调用
```python
from src.gasflux.data_processor import process_excel_file
# 处理单个文件
df = process_excel_file('path/to/data.xlsx')
# 查看结果
print(df.head())
print(df.columns)
```
## 📊 输出格式
处理后的数据完全符合GasFlux输入要求
```csv
timestamp,latitude,longitude,height_ato,windspeed,windir,temperature,pressure,ch4
2024-01-15 08:34:01,115.785529,40.349137,10.5,3.2,180.5,22.3,1013.25,2.15
2024-01-15 08:34:02,115.785530,40.349138,10.8,3.1,181.2,22.4,1013.26,2.18
...
```
## ⚙️ 配置选项
### 文件名格式
脚本根据文件名自动提取时间信息:
- 格式: `{HH}_{MM}_{SS}_{其他信息}.xlsx`
- 示例: `08_34_01_间隔高度5m.xlsx` → 小时=08
### 气压计算
- 默认只计算前20行数据避免过多API调用
- 可以修改 `max_samples` 参数调整计算数量
## 🔧 依赖要求
```bash
pip install pandas openpyxl requests
```
确保GasFlux的`qiya.py`模块可用。
## ⚠️ 注意事项
### 数据质量
- 确保Excel文件格式正确
- 检查日期时间格式
- 验证经纬度坐标范围
### API限制
- Open-Meteo有每日请求限制
- 批量处理时注意请求频率
- 网络连接稳定很重要
### 内存使用
- 大文件处理时注意内存占用
- 可以分批处理超大数据集
## 🎯 应用场景
### 无人机通量测量
1. **数据采集**: 无人机飞行收集原始数据
2. **数据处理**: 使用本脚本转换为标准格式
3. **通量计算**: 输入GasFlux进行气体通量分析
### 数据预处理工作流
```
原始Excel → 数据处理脚本 → GasFlux格式 → 通量计算 → 结果分析
```
## 📈 处理结果验证
处理完成后检查:
- ✅ 时间戳格式正确 (YYYY-MM-DD HH:MM:SS)
- ✅ 经纬度坐标合理范围
- ✅ 高度值从0开始 (已减去最小值)
- ✅ 气压值在合理范围 (900-1100 hPa)
- ✅ 所有必需字段都存在
## 🛠️ 故障排除
### 常见问题
#### 1. 文件读取错误
```
确保Excel文件未损坏列名与预期一致
```
#### 2. 时间格式错误
```
检查文件名格式,确包含小时信息 (HH_MM_SS...)
```
#### 3. 气压计算失败
```
检查网络连接,确认日期格式正确
```
#### 4. 坐标转换异常
```
验证经纬度数据是数值类型,不是字符串
```
## 📞 支持
如遇问题,请检查:
1. 输入数据格式是否正确
2. 网络连接是否正常
3. GasFlux依赖是否完整安装
4. Python版本兼容性
---
**版本**: 1.0.0
**最后更新**: 2024年12月

661
LICENSE Normal file
View File

@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

75
README.md Normal file
View File

@ -0,0 +1,75 @@
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
[![Tests](https://github.com/gasflux/gasflux/workflows/CI/badge.svg)](https://github.com/gasflux/gasflux/actions?query=workflow%3A%22CI%22)
[![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v0.json)](https://github.com/charliermarsh/ruff)
[![format - Black](https://img.shields.io/badge/format-black-000000.svg)](https://github.com/psf/black)
[![types - mypy](https://img.shields.io/badge/types-mypy-blue.svg)](https://github.com/python/mypy)
# GasFlux
`pip install gasflux` \
`gasflux --help`
📖 **[详细用户指南](USER_GUIDE.md)** - 完整的功能说明和使用教程
GasFlux is a tool for processing atmospheric gas concentration data and windspeeds into mass emissions fluxes, with principle applications to greenhouse gas measurement and vulcanology. Currently it works with in situ ("sniffing") data from UAVs and other aircraft, using mass balance as a paradigm and kriging as an interpolation strategy, but the intention is to expand this to other kinds of sampling and processing strategies, such as open-path and tracer methods.
It is released under the AGPLv3 license as a free and open-source project - comments, pull requests, issues and co-development are warmly welcomed. Currently development is co-ordinated by Jamie McQuilkin ([@pipari](https://github.com/pipari)) at the UAV Greenhouse Gas group at the University of Manchester.
## User Installation
The package is available on PyPi and can be installed using `pip install gasflux`.
## Usage
The package interface is in active development. Currently it ingests a data csv file (or folder containing only data csv files) and a config file that dictates the parameters of the analysis.
This is done through the syntax `gasflux process <input_file> --config <config_file>`.
### The config file
The default gasflux_config.yaml is located in the package source. It can be generated in a supplied directory using `gasflux generate-config <path>`. If a directory is supplied to `gasflux process` and a config is not also explicitly supplied, the package will look for one config file in that directory or its subdirectories and attempt to process all csv files in that directory and subdirectories. If multiple or no config is found, it will raise an error. If supplying a single csv file for processing (rather than a directory), only the parent directory will be searched for config files (not its subdirectories).
Through it, variables can be passed to the [scikit-gstat](https://scikit-gstat.readthedocs.io/en/latest/) package used for kriging and the [pybaselines](https://pybaselines.readthedocs.io/en/latest/) package used for background correction.
### The data file
Input data files must be csv-type (i.e. readable by `pandas`) and have the following columns (all lower case):
- `timestamp` (datetime)
- `latitude` (float)
- `longitude` (float)
- `height_ato` (float) - height above takeoff
- `windspeed` (float) - in m/s, as measured or inferred at each measurement point
- `winddir` (float) - in standard 0-360 degree format, relative to the earth
- `temperature` (float) in degrees celsius
- `pressure` (float) - in hPa/mBar
At least one gas concentration in ppm is also required. The column name should be the gas name, e.g. `co2`, `ch4`, `n2o`, etc.
The gas should be entered in the gasflux_config.yaml file along with a range of concentrations in ppmv, e.g.:
```
gases:
ch4: [1.5, 500]
co2: [300, 5000]
c2h6: [-0.5, 10]
```
Ensuring input data are sufficient and correctly formatted is non-trivial and important, but is left to the user. Data sources vary enormously so it is difficult to generalise this part of the analysis - in many cases these will be a mix of flight logs, GPS, one or more anemometers, one or more gas sensors, a thermometer, hygrometer, barometer.
Synchronisation and fusion of these data sources is important and should be given great attention - there are several ways to do this, including GPS logging on each sensor, recording everything on a single device, or NTP server synchronisation. Care should also be taken to avoid loss of data through resampling or interpolation.
One way to convert encoded DJI logs is to use `djiparsetext`, a C++ library available on github [here](https://github.com/uav4geo/djiparsetxt) and documented [here](http://djilogs.live555.com/).
## Development
### Installation
To install, clone the repository using e.g. `git clone` and use `pip install -e .` to install it as an editable python package.
It's highly recommended to use a virtual environment to manage dependencies. If you're not currently using one, [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/install.html) is a good option.
Then run `pip install -r requirements.txt` and `pip install -r dev-requirements.txt` to install the required dependencies.
User requirements.txt is generated using `pigar generate` rather than `pip freeze`.

48
build_gasflux_exe.bat Normal file
View File

@ -0,0 +1,48 @@
@echo off
echo ========================================
echo GasFlux RunExample EXE打包工具 (Windows)
echo ========================================
echo.
cd /d "%~dp0"
echo [1/4] 检查Python环境...
python --version
if errorlevel 1 (
echo 错误未找到Python
pause
exit /b 1
)
echo [2/4] 升级pip...
python -m pip install --upgrade pip
echo [3/4] 安装PyInstaller...
python -m pip install pyinstaller
if errorlevel 1 (
echo 错误PyInstaller安装失败
pause
exit /b 1
)
echo [4/4] 开始打包...
python -m PyInstaller --clean gasflux_run_example.spec
if errorlevel 1 (
echo 错误:打包失败
pause
exit /b 1
)
echo.
echo ========================================
echo 打包完成!
echo ========================================
echo.
echo 可执行文件位置dist\GasFlux_RunExample.exe
echo.
echo 使用方法:
echo GasFlux_RunExample.exe input.xlsx
echo GasFlux_RunExample.exe input.xlsx --output result.csv
echo GasFlux_RunExample.exe input.xlsx --no-gasflux
echo.
pause

48
build_gasflux_exe.sh Normal file
View File

@ -0,0 +1,48 @@
#!/bin/bash
echo "========================================"
echo "GasFlux RunExample EXE打包工具 (Linux/Mac)"
echo "========================================"
echo
cd "$(dirname "$0")"
echo "[1/4] 检查Python环境..."
if ! command -v python3 &> /dev/null; then
echo "错误未找到Python3"
exit 1
fi
python3 --version
echo "[2/4] 升级pip..."
python3 -m pip install --upgrade pip
echo "[3/4] 安装PyInstaller..."
python3 -m pip install pyinstaller
if [ $? -ne 0 ]; then
echo "错误PyInstaller安装失败"
exit 1
fi
echo "[4/4] 开始打包..."
python3 -m PyInstaller --clean gasflux_run_example.spec
if [ $? -ne 0 ]; then
echo "错误:打包失败"
exit 1
fi
echo
echo "========================================"
echo "打包完成!"
echo "========================================"
echo
echo "可执行文件位置dist/GasFlux_RunExample"
echo
echo "使用方法:"
echo " ./GasFlux_RunExample input.xlsx"
echo " ./GasFlux_RunExample input.xlsx --output result.csv"
echo " ./GasFlux_RunExample input.xlsx --no-gasflux"
echo

View File

@ -0,0 +1,52 @@
output_dir: ./advanced_output
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [-100, 500]
windspeed: [1, 15]
winddir: [0, 360]
temperature: [0, 30]
pressure: [980, 1030]
gases:
ch4: [1.8, 5.0]
co2: [400, 500]
strategies:
background: "algorithm"
sensor: "insitu"
spatial: "curtain"
interpolation: "kriging"
algorithmic_baseline_settings:
algorithm: dietrich
dietrich:
poly_order: 4
smooth_half_window: 4
semivariogram_settings:
model: gaussian
estimator: cressie
n_lags: 15
bin_func: even
fit_method: lm
maxlag: 80
tolerance: 15
azimuth: 0
bandwidth: 25
ordinary_kriging_settings:
min_points: 5
max_points: 80
grid_resolution: 200
min_nodes: 10
y_min: 20
cut_ground: True
filters:
course_filter:
azimuth_filter: 15
azimuth_window: 8
elevation_filter: 8

Binary file not shown.

View File

@ -0,0 +1,69 @@
# GasFlux configuration file for basic usage example
output_dir: ./10m
# Required columns and their maximum valid ranges
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [0, 50] # meters above takeoff
windspeed: [0, 50] # m/s
winddir: [0, 360] # degrees
temperature: [-50, 60] # degrees Celsius
pressure: [900, 1100] # hPa/mb
# Optional gas columns and their maximum ppm concentration ranges.
# Relative concentrations are used, so absolute offset can be incorrect as long as gain and linearity are correct.
gases:
ch4: [2, 2.5]
strategies:
background: "algorithm" # Currently only algorithmic baseline correction (via pybaselines) is supported
sensor: "insitu" # Currently only in-situ sensor data is supported
spatial: "spiral" # Spatial processing mode: "curtain" and "spiral" are supported
interpolation: "kriging" # Currently only kriging interpolation is supported
# Baseline correction algorithm settings
algorithmic_baseline_settings:
algorithm: fastchrom
fastchrom: {
"half_window": 6,
"threshold": "custom", #
"min_fwhm": ~,
"interp_half_window": 3,
"smooth_half_window": 3,
"weights": ~,
"max_iter": 100,
"min_length": 2}
fabc : {
"lam": 10000, # The smoothing parameter. Larger values will create smoother baselines. Default is 1e6.
"scale": 10, # The scale at which to calculate the continuous wavelet transform. Should be approximately equal to the index-based full-width-at-half-maximum of the peaks or features in the data. Default is None, which will use half of the value from optimize_window(), which is not always a good value, but at least scales with the number of data points and gives a starting point for tuning the parameter.
"diff_order": 2} # The order of the differential matrix. Must be greater than 0. Default is 2 (second order differential matrix). Typical values are 2 or 1.
dietrich : {
"poly_order": 5,
"smooth_half_window": 5,}
golotvin : {
"half_window": 2,
"sections": 10}
# Kriging settings - aggressively optimized for Spiral mode
semivariogram_settings:
model: exponential # Changed to exponential model for better circular data fitting
estimator: cressie # Robust estimator for variogram calculation
n_lags: 50 # Further increased to 50 for better variogram resolution
bin_func: even # Even binning function
fit_method: lm # Least squares fitting method
### Aggressively increased search ranges for circular/spiral data distribution
maxlag: 5000 # Dramatically increased to 5000m for comprehensive coverage
tolerance: 180 # Increased to 180° to allow full circular search
azimuth: 0 # Horizontal direction maintained
bandwidth: 300 # Further increased to 300m for maximum search bandwidth
# fit_sigma: linear # this should allow for a spatial uncertainty but currently producing bugs
ordinary_kriging_settings:
min_points: 1 # Reduced to 1 to allow interpolation even with sparse data
max_points: 20 # Further reduced to 20 to minimize computational load
grid_resolution: 100 # Increased density to 100 for finer interpolation grid
min_nodes: 20 # Increased to 20 to ensure sufficient grid nodes
y_min: ~ # Automatically determine minimum y value
cut_ground: False # Keep ground cutting disabled

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
# GasFlux 基本使用示例配置文件
# 这个配置文件演示了最基本的设置,用于处理简单的气体通量数据
# 输出目录
output_dir: ./output
# 数据验证参数
required_cols:
latitude: [-90, 90] # 纬度范围
longitude: [-180, 180] # 经度范围
height_ato: [0, 200] # 相对起飞高度(米)
windspeed: [0, 20] # 风速m/s
winddir: [0, 360] # 风向(度)
temperature: [-50, 60] # 温度°C
pressure: [900, 1100] # 气压hPa
# 气体配置气体名称和浓度范围ppmv
gases:
ch4: [1.5, 10.0] # 甲烷
co2: [300, 500] # 二氧化碳
# 处理策略
strategies:
background: "algorithm" # 背景校正方法
sensor: "insitu" # 传感器类型
spatial: "curtain" # 空间处理模式
interpolation: "kriging" # 插值方法
# 背景校正算法设置
algorithmic_baseline_settings:
algorithm: fastchrom # 使用FastChrom算法
fastchrom:
half_window: 3 # 半窗口大小
threshold: "custom" # 阈值方法
min_fwhm: ~
interp_half_window: 2
smooth_half_window: 2
weights: ~
max_iter: 50
min_length: 2
# 克里金插值设置
semivariogram_settings:
model: spherical # 半变异函数模型
estimator: cressie # 估计器
n_lags: 10 # 滞后期数
bin_func: even # 分箱函数
fit_method: lm # 拟合方法
maxlag: 50 # 最大滞后距离
tolerance: 10 # 方向容差
azimuth: 0 # 方位角
bandwidth: 15 # 带宽
# 普通克里金设置
ordinary_kriging_settings:
min_points: 3 # 最小邻点数
max_points: 50 # 最大邻点数
grid_resolution: 100 # 网格分辨率
min_nodes: 5 # 最小网格节点数
y_min: ~ # 最小y值
cut_ground: False # 是否切割地面

View File

@ -0,0 +1,820 @@
timestamp,latitude,longitude,height_ato,windspeed,winddir,temperature,pressure,ch4,course_elevation,course_azimuth
2016-02-12 08:34:01,40.349137,115.7855289,11.865000000000009,4.85383,126.121,18.1,957.6,2.28753,8.50882,74.9353
2016-02-12 08:34:02,40.349137,115.7855289,11.865000000000009,3.5045,142.744,18.1,957.6,2.27667,8.50882,74.9353
2016-02-12 08:34:02,40.349137,115.7855296,9.830000000000041,3.30667,145.626,18.1,957.4,2.28621,7.26866,75.2618
2016-02-12 08:34:02,40.3491369,115.7855295,9.830000000000041,3.19669,147.2,18.1,957.4,2.29012,6.6954,75.3488
2016-02-12 08:34:02,40.3491366,115.7855289,9.830000000000041,3.1958,146.33,18.1,957.4,2.28968,5.15029,75.4473
2016-02-12 08:34:02,40.3491365,115.7855279,9.830000000000041,2.24203,142.349,18.1,957.4,2.27675,3.60147,75.8082
2016-02-12 08:34:02,40.3491365,115.7855279,9.830000000000041,2.24203,142.349,18.1,957.4,2.28111,3.60147,75.8082
2016-02-12 08:34:02,40.3491362,115.7855267,9.830000000000041,2.65173,132.045,18.1,957.4,2.27628,2.90435,75.7617
2016-02-12 08:34:03,40.3491359,115.7855254,9.830000000000041,3.12274,124.934,18.1,957.4,2.26905,1.51899,75.2541
2016-02-12 08:34:04,40.3491342,115.7855197,9.482000000000028,3.62267,96.3253,18.1,957.4,2.26865,2.08601,74.3647
2016-02-12 08:34:05,40.3491317,115.7855115,6.3040000000000305,3.48429,103.687,18.1,957.4,2.25985,-1.48779,74.6518
2016-02-12 08:34:06,40.349131,115.7855068,3.1860000000000355,3.08523,110.241,18.1,957.4,2.25816,-5.50997,78.0309
2016-02-12 08:34:07,40.3491309,115.7855052,0.45100000000002183,2.57202,106.603,18.1,957.4,2.26128,-2.11963,61.7648
2016-02-12 08:34:08,40.3491307,115.7855046,0.06300000000004502,1.67764,109.782,18.0,957.4,2.26535,-6.78676,47.9709
2016-02-12 08:34:09,40.3491332,115.7855083,0.0,1.87728,168.504,18.0,957.4,2.26713,-11.0121,47.0035
2016-02-12 08:34:10,40.3491444,115.7855253,0.813000000000045,2.70038,170.113,18.0,957.4,2.27136,-6.98884,46.7738
2016-02-12 08:34:11,40.3491573,115.7855439,1.1070000000000277,4.09542,158.538,17.9,957.4,2.26672,-3.50721,45.9275
2016-02-12 08:34:12,40.3491708,115.7855627,0.8600000000000136,4.92415,152.325,17.9,957.4,2.26796,-3.67191,47.1102
2016-02-12 08:34:13,40.3491838,115.7855814,1.4639999999999986,5.05104,149.272,17.9,957.4,2.26253,-2.6092,47.3419
2016-02-12 08:34:14,40.3491963,115.7855993,1.2660000000000196,4.7566,146.774,17.8,957.4,2.25574,-3.68899,47.5405
2016-02-12 08:34:15,40.3492086,115.7856167,0.9460000000000264,4.4861,146.945,17.8,957.4,2.27209,-4.73718,47.8124
2016-02-12 08:34:16,40.3492212,115.7856339,1.1129999999999995,4.49042,147.234,17.8,957.4,2.2685,-3.71094,47.8571
2016-02-12 08:34:17,40.3492333,115.785651,1.330000000000041,4.67508,147.701,17.8,957.4,2.26577,-4.10178,47.8265
2016-02-12 08:34:18,40.3492453,115.7856683,0.3660000000000423,4.80069,142.768,17.8,957.4,2.26449,-4.00834,51.3819
2016-02-12 08:34:19,40.3492558,115.7856869,0.42900000000003047,4.41849,139.131,17.8,957.4,2.2629,-3.5961,55.2403
2016-02-12 08:34:20,40.3492652,115.7857063,0.5040000000000191,4.17348,135.791,17.8,957.4,2.27134,-3.66223,59.0575
2016-02-12 08:34:21,40.3492739,115.7857263,0.6690000000000396,4.24922,133.776,17.7,957.4,2.26504,-4.04384,62.0997
2016-02-12 08:34:22,40.3492823,115.7857472,0.6270000000000095,4.12397,132.906,17.7,957.4,2.26494,-3.93005,65.1934
2016-02-12 08:34:23,40.3492897,115.7857691,0.38800000000003365,3.87817,129.092,17.7,957.4,2.26202,-3.17112,69.0847
2016-02-12 08:34:24,40.3492958,115.7857913,0.535000000000025,3.56279,124.29,17.7,957.4,2.2705,-2.8296,73.4975
2016-02-12 08:34:25,40.3493007,115.7858139,0.41500000000002046,3.20321,120.437,17.7,957.4,2.26211,-2.58427,74.5562
2016-02-12 08:34:26,40.3493053,115.7858363,0.32600000000002183,2.84368,126.241,17.7,957.4,2.27064,-3.00187,74.5266
2016-02-12 08:34:27,40.3493102,115.7858587,0.39800000000002456,2.66869,123.302,17.6,957.4,2.26641,-2.85474,74.2713
2016-02-12 08:34:28,40.3493153,115.7858814,0.1560000000000059,2.33673,125.416,17.6,957.4,2.2613,-2.58352,74.0617
2016-02-12 08:34:29,40.3493205,115.7859044,0.015000000000043201,2.1419,112.039,17.6,957.4,2.27285,-2.4898,74.4684
2016-02-12 08:34:30,40.349325,115.7859273,0.023000000000024556,2.12291,112.287,17.6,957.4,2.26546,-2.37166,74.68
2016-02-12 08:34:31,40.3493296,115.7859502,0.09500000000002728,2.11867,112.449,17.5,957.4,2.26334,-2.52349,74.727
2016-02-12 08:34:32,40.3493339,115.7859728,0.21500000000003183,2.03503,104.255,17.5,957.4,2.25624,-2.35695,77.5604
2016-02-12 08:34:33,40.3493375,115.7859955,0.06800000000004047,2.08166,105.808,17.5,957.4,2.26756,-2.18838,81.7064
2016-02-12 08:34:34,40.3493398,115.7860185,0.09100000000000819,2.10121,101.349,17.5,957.4,2.27006,-2.16129,86.1149
2016-02-12 08:34:35,40.3493408,115.7860419,0.09800000000001319,2.0652,92.3755,17.5,957.4,2.26534,-1.97706,89.1031
2016-02-12 08:34:36,40.3493407,115.7860652,0.28400000000004866,2.03562,89.3814,17.5,957.4,2.26928,-1.69654,91.8991
2016-02-12 08:34:37,40.3493397,115.7860884,0.16800000000000637,2.01381,86.7262,17.4,957.4,2.26397,-1.49829,95.0727
2016-02-12 08:34:38,40.3493378,115.7861116,0.10599999999999454,1.94986,82.7376,17.4,957.4,2.26526,-1.28459,98.4028
2016-02-12 08:34:39,40.3493345,115.7861345,0.2300000000000182,1.98893,75.9616,17.4,957.4,2.27142,-1.40811,102.871
2016-02-12 08:34:40,40.3493301,115.786157,0.22400000000004638,1.97218,72.7694,17.4,957.4,2.26352,-1.32349,106.444
2016-02-12 08:34:41,40.3493248,115.7861794,0.26300000000003365,1.9978,72.1563,17.4,957.4,2.26984,-1.26987,107.053
2016-02-12 08:34:42,40.3493192,115.7862018,0.15399999999999636,1.99455,72.3657,17.4,957.4,2.27778,-1.2788,106.81
2016-02-12 08:34:43,40.3493138,115.7862243,0.16800000000000637,2.00894,73.2219,17.4,957.4,2.27545,-1.35789,106.736
2016-02-12 08:34:44,40.3493084,115.786247,0.23200000000002774,2.01704,73.3629,17.4,957.4,2.26695,-1.14838,107.083
2016-02-12 08:34:45,40.3493031,115.7862696,0.14400000000000546,1.99527,72.7411,17.4,957.4,2.26658,-0.891773,107.534
2016-02-12 08:34:46,40.3492978,115.7862919,0.14500000000003865,1.9958,72.9977,17.4,957.4,2.26718,-1.23237,107.164
2016-02-12 08:34:47,40.3492925,115.7863145,0.20400000000000773,2.00589,73.2645,17.3,957.4,2.27372,-0.841243,107.309
2016-02-12 08:34:48,40.3492871,115.7863372,0.11000000000001364,2.00215,73.3395,17.3,957.4,2.26653,-0.756934,106.873
2016-02-12 08:34:49,40.3492815,115.7863599,0.16599999999999682,2.00296,69.5246,17.3,957.4,2.27131,-0.454938,110.252
2016-02-12 08:34:50,40.3492749,115.7863818,0.27899999999999636,1.97805,64.6886,17.3,957.4,2.25977,-0.706977,114.756
2016-02-12 08:34:51,40.349267,115.7864029,0.23900000000003274,1.9369,61.1256,17.3,957.4,2.27473,-0.520325,118.334
2016-02-12 08:34:52,40.3492562,115.7864271,0.37700000000000955,1.9232,56.7933,17.3,957.4,2.27288,-0.892102,122.079
2016-02-12 08:34:53,40.3492466,115.7864464,0.3160000000000309,1.9402,53.0758,17.3,957.4,2.26006,-0.668285,125.41
2016-02-12 08:34:54,40.3492383,115.7864611,0.4070000000000391,1.94647,49.7541,17.3,957.4,2.26102,-0.793088,129.068
2016-02-12 08:34:55,40.3492244,115.7864817,0.46200000000004593,1.96366,44.9617,17.3,957.4,2.26623,-0.715602,133.755
2016-02-12 08:34:56,40.3492118,115.7864981,0.43200000000001637,1.96034,44.2948,17.3,957.4,2.26446,-0.690077,134.303
2016-02-12 08:34:57,40.3491991,115.7865145,0.34700000000003683,1.97744,45.1225,17.3,957.4,2.26972,-0.643342,134.308
2016-02-12 08:34:58,40.3491864,115.7865314,0.37700000000000955,1.76954,51.6213,17.3,957.4,2.26913,-0.884507,134.019
2016-02-12 08:34:59,40.3491734,115.7865484,0.3170000000000073,1.64919,64.6824,17.3,957.4,2.26522,-0.561871,134.093
2016-02-12 08:35:00,40.3491603,115.786565,0.38900000000001,1.53019,22.4667,17.3,957.4,2.27348,-0.283173,139.001
2016-02-12 08:35:01,40.3491468,115.7865794,0.3860000000000241,1.66544,16.1733,17.3,957.4,2.25965,-0.622678,146.88
2016-02-12 08:35:02,40.349132,115.7865915,0.49600000000003774,1.90088,25.2598,17.3,957.4,2.27091,-0.675699,152.432
2016-02-12 08:35:03,40.3491161,115.7866014,0.660000000000025,1.92716,21.0727,17.3,957.4,2.27679,-0.638564,157.896
2016-02-12 08:35:04,40.3490997,115.786609,0.6190000000000282,1.94499,15.5196,17.3,957.4,2.2683,-1.18828,163.563
2016-02-12 08:35:05,40.3490826,115.7866145,0.6270000000000095,2.06029,5.61009,17.3,957.4,2.26783,-0.849828,170.567
2016-02-12 08:35:06,40.349065,115.7866175,0.7410000000000423,2.25531,18.8411,17.3,957.4,2.27565,-1.02481,175.647
2016-02-12 08:35:07,40.3490471,115.7866191,0.5990000000000464,2.6897,27.0446,17.3,957.4,2.26251,-0.938632,175.901
2016-02-12 08:35:08,40.3490295,115.7866204,0.8120000000000118,3.5706,22.8119,17.3,957.4,2.26682,-1.4553,175.625
2016-02-12 08:35:09,40.3490118,115.7866221,0.5160000000000196,3.58223,23.2989,17.3,957.4,2.26834,-1.51818,175.649
2016-02-12 08:35:10,40.3489939,115.7866236,0.6400000000000432,3.47975,23.2924,17.3,957.4,2.26655,-1.19849,175.598
2016-02-12 08:35:11,40.3489761,115.7866252,0.5400000000000205,3.19407,20.9252,17.3,957.4,2.26637,-0.986002,176.011
2016-02-12 08:35:12,40.3489581,115.7866269,0.5540000000000305,2.9534,17.5397,17.3,957.4,2.2573,-1.64013,176.158
2016-02-12 08:35:13,40.3489399,115.7866285,0.7060000000000173,3.15458,18.2456,17.3,957.4,2.26939,-0.792553,175.629
2016-02-12 08:35:14,40.3489218,115.7866301,0.6890000000000214,3.20536,19.0764,17.3,957.4,2.2633,-1.16851,175.798
2016-02-12 08:35:15,40.3489038,115.7866319,0.8970000000000482,3.5823,22.3026,17.3,957.4,2.25549,-0.91357,175.775
2016-02-12 08:35:16,40.3488859,115.7866335,0.7669999999999959,3.65156,26.1432,17.3,957.4,2.27439,-1.38495,178.614
2016-02-12 08:35:17,40.3488681,115.7866336,0.7250000000000227,3.69689,28.3517,17.2,957.4,2.2692,-1.36653,-178.318
2016-02-12 08:35:18,40.3488503,115.7866322,0.8000000000000114,3.65114,28.7382,17.2,957.4,2.26636,-1.90382,-175.758
2016-02-12 08:35:19,40.3488325,115.7866297,0.7480000000000473,3.6946,29.076,17.2,957.4,2.27162,-1.64705,-173.079
2016-02-12 08:35:20,40.3488148,115.7866265,0.7590000000000146,3.86282,32.9325,17.2,957.4,2.26822,-1.50341,-170.331
2016-02-12 08:35:21,40.3487974,115.7866223,0.57000000000005,3.78317,34.2873,17.2,957.4,2.259,-1.77715,-168.664
2016-02-12 08:35:22,40.3487801,115.7866172,0.8000000000000114,3.73202,35.6475,17.2,957.4,2.26842,-1.80386,-166.087
2016-02-12 08:35:23,40.348763,115.7866112,0.5540000000000305,3.64181,38.9923,17.2,957.4,2.26291,-1.70703,-162.255
2016-02-12 08:35:24,40.348746,115.7866039,0.7320000000000277,3.81269,41.8128,17.2,957.4,2.26664,-1.71048,-159.878
2016-02-12 08:35:25,40.3487291,115.7865957,0.7630000000000337,3.48729,42.0299,17.2,957.4,2.26374,-1.33685,-159.608
2016-02-12 08:35:26,40.3487121,115.7865872,1.0080000000000382,3.75868,43.3489,17.2,957.4,2.26646,-1.55744,-159.91
2016-02-12 08:35:27,40.3486957,115.7865788,0.7060000000000173,3.79234,42.8656,17.2,957.4,2.26328,-2.0048,-159.441
2016-02-12 08:35:28,40.3486789,115.7865705,0.7350000000000136,4.22793,42.0491,17.2,957.4,2.26176,-1.98951,-159.699
2016-02-12 08:35:29,40.3486623,115.7865625,0.7860000000000014,4.27342,41.0633,17.2,957.4,2.2614,-2.18286,-159.799
2016-02-12 08:35:30,40.3486421,115.7865527,0.5580000000000496,4.18449,42.0908,17.2,957.4,2.2712,-1.9235,-159.6
2016-02-12 08:35:31,40.3486252,115.7865443,0.4430000000000405,4.02941,43.9017,17.2,957.4,2.26236,-1.78458,-159.343
2016-02-12 08:35:32,40.3486085,115.7865356,0.4370000000000118,4.02369,47.8521,17.2,957.4,2.26458,-1.82948,-155.262
2016-02-12 08:35:33,40.3485927,115.7865251,0.6200000000000045,4.1616,52.7125,17.2,957.4,2.26249,-2.21001,-149.328
2016-02-12 08:35:34,40.3485776,115.7865124,0.5920000000000414,4.1949,56.7896,17.2,957.4,2.26734,-1.6575,-143.271
2016-02-12 08:35:35,40.3485635,115.7864976,0.6930000000000405,4.27443,63.2883,17.2,957.4,2.27079,-1.35784,-137.443
2016-02-12 08:35:36,40.3485507,115.7864814,1.0370000000000346,4.18031,70.4075,17.2,957.4,2.27161,-2.25059,-133.151
2016-02-12 08:35:37,40.3485392,115.7864642,1.143000000000029,4.11209,74.1468,17.1,957.4,2.26222,-2.27961,-128.075
2016-02-12 08:35:38,40.3485291,115.7864455,1.0510000000000446,4.69329,81.6319,17.1,957.4,2.26785,-2.59902,-121.299
2016-02-12 08:35:39,40.3485208,115.7864255,1.2220000000000368,5.02418,87.2004,17.1,957.4,2.26188,-3.57525,-114.178
2016-02-12 08:35:40,40.3485143,115.7864042,1.0570000000000164,5.29014,89.51,17.1,957.4,2.25589,-3.38018,-109.557
2016-02-12 08:35:41,40.3485083,115.7863817,1.0950000000000273,5.35193,86.5112,17.1,957.4,2.26569,-3.63266,-110.057
2016-02-12 08:35:42,40.3485019,115.7863589,0.9279999999999973,5.48287,85.2166,17.1,957.4,2.25651,-3.05251,-109.671
2016-02-12 08:35:43,40.3484959,115.7863364,1.3120000000000118,5.33864,85.4933,17.1,957.4,2.2527,-3.46027,-109.986
2016-02-12 08:35:44,40.3484896,115.7863142,0.9790000000000418,5.04344,87.0444,17.1,957.4,2.25495,-2.7903,-109.977
2016-02-12 08:35:45,40.3484838,115.7862919,0.8730000000000473,5.04691,88.3346,17.1,957.4,2.25385,-2.69067,-109.498
2016-02-12 08:35:46,40.3484784,115.7862698,0.7189999999999941,4.85317,86.7704,17.1,957.4,2.25565,-3.02553,-109.5
2016-02-12 08:35:47,40.3484727,115.7862479,0.4759999999999991,4.84407,85.5268,17.1,957.4,2.26485,-2.80897,-109.877
2016-02-12 08:35:48,40.3484667,115.786226,0.7650000000000432,4.92592,82.6714,17.1,957.4,2.26122,-3.19976,-110.092
2016-02-12 08:35:49,40.3484607,115.7862036,0.9590000000000032,4.84169,80.0226,17.1,957.4,2.26519,-3.37566,-109.883
2016-02-12 08:35:50,40.3484548,115.7861811,0.9000000000000341,4.92234,79.5242,17.0,957.4,2.25928,-3.44132,-109.953
2016-02-12 08:35:51,40.3484488,115.7861583,0.7050000000000409,4.87384,79.8274,17.0,957.4,2.26367,-2.44092,-108.984
2016-02-12 08:35:52,40.3484431,115.7861355,1.3520000000000323,4.80479,85.2199,17.0,957.4,2.26016,-2.95146,-104.259
2016-02-12 08:35:53,40.3484387,115.7861128,1.2720000000000482,4.68873,88.9,17.0,957.4,2.26904,-3.00915,-99.8611
2016-02-12 08:35:54,40.3484358,115.7860899,1.1779999999999973,4.69722,95.5627,17.0,957.4,2.26347,-3.11661,-95.6539
2016-02-12 08:35:55,40.3484345,115.7860661,1.05600000000004,4.66468,100.449,17.0,957.4,2.26009,-2.20477,-92.2146
2016-02-12 08:35:56,40.3484343,115.7860428,1.3660000000000423,4.72368,105.041,17.0,957.4,2.25921,-2.67096,-88.8258
2016-02-12 08:35:57,40.3484347,115.7860198,1.8100000000000023,4.68402,107.835,17.0,957.4,2.25358,-3.15406,-84.749
2016-02-12 08:35:58,40.3484367,115.7859975,2.1230000000000473,4.85389,110.385,17.0,957.4,2.26588,-4.38063,-81.1136
2016-02-12 08:35:59,40.3484402,115.7859746,1.6659999999999968,5.12074,113.453,17.0,957.4,2.25073,-3.78266,-75.9072
2016-02-12 08:36:00,40.3484451,115.7859519,1.5710000000000264,5.51489,114.162,16.9,957.4,2.25645,-3.45966,-73.0747
2016-02-12 08:36:01,40.3484506,115.7859298,1.41700000000003,5.60618,114.705,16.9,957.4,2.26324,-3.852,-72.6888
2016-02-12 08:36:02,40.3484562,115.7859079,1.4260000000000446,5.9885,113.608,16.9,957.4,2.25939,-4.08462,-72.4005
2016-02-12 08:36:03,40.3484618,115.7858859,1.2960000000000491,6.06681,114.146,16.9,957.4,2.26444,-4.33265,-72.7478
2016-02-12 08:36:04,40.3484672,115.7858634,1.875,6.16502,113.964,16.9,957.4,2.25122,-4.29353,-72.6671
2016-02-12 08:36:05,40.3484723,115.7858407,1.288000000000011,5.83346,114.53,16.9,957.4,2.25211,-4.46077,-72.5697
2016-02-12 08:36:06,40.3484779,115.785818,1.2210000000000036,5.89907,113.53,16.9,957.4,2.25987,-4.01207,-72.7203
2016-02-12 08:36:07,40.3484833,115.7857951,1.188000000000045,5.87513,112.884,16.9,957.4,2.25998,-3.94424,-72.7445
2016-02-12 08:36:08,40.3484887,115.7857725,1.0230000000000246,5.86465,112.761,16.9,957.4,2.25653,-3.75708,-72.6379
2016-02-12 08:36:09,40.3484941,115.78575,1.3140000000000214,5.86195,113.211,16.9,957.4,2.26881,-3.84116,-72.7711
2016-02-12 08:36:10,40.3484998,115.7857277,1.1030000000000086,5.76417,116.283,16.8,957.4,2.26094,-3.59034,-70.8237
2016-02-12 08:36:11,40.3485062,115.785706,1.30600000000004,5.63247,121.963,16.8,957.4,2.26475,-4.2956,-65.0574
2016-02-12 08:36:12,40.348514,115.7856854,1.295000000000016,5.60765,127.444,16.8,957.4,2.27279,-4.16794,-59.1853
2016-02-12 08:36:13,40.3485233,115.7856661,1.3950000000000387,5.85706,131.455,16.8,957.4,2.24993,-4.41538,-54.0778
2016-02-12 08:36:14,40.3485344,115.7856481,1.2980000000000018,5.88649,137.158,16.8,957.4,2.25646,-4.22068,-48.5817
2016-02-12 08:36:15,40.3485493,115.7856278,1.413000000000011,5.83127,140.639,16.8,957.4,2.263,-3.64977,-43.7228
2016-02-12 08:36:16,40.3485596,115.7856156,1.6090000000000373,5.7416,144.321,16.8,957.4,2.25908,-4.5659,-39.0127
2016-02-12 08:36:17,40.3485769,115.7855999,1.2909999999999968,5.95436,149.405,16.7,957.4,2.25161,-3.4582,-31.6394
2016-02-12 08:36:18,40.3485927,115.7855881,1.032000000000039,5.88089,152.516,16.7,957.4,2.26682,-3.81466,-26.593
2016-02-12 08:36:19,40.3486084,115.7855776,1.410000000000025,5.92927,151.424,16.7,957.4,2.26897,-4.88384,-25.4304
2016-02-12 08:36:20,40.3486242,115.7855675,1.4120000000000346,6.06628,150.826,16.7,957.4,2.25404,-4.74525,-25.5442
2016-02-12 08:36:21,40.3486401,115.7855574,1.1860000000000355,6.09935,150.336,16.7,957.4,2.25539,-4.647,-25.6555
2016-02-12 08:36:22,40.3486565,115.7855475,0.9850000000000136,6.11633,148.496,16.7,957.4,2.26913,-4.63177,-25.7067
2016-02-12 08:36:23,40.3486729,115.7855371,0.7600000000000477,5.92629,148.812,16.6,957.4,2.26475,-4.46693,-26.0157
2016-02-12 08:36:24,40.3486891,115.7855269,0.7820000000000391,6.07324,148.379,16.6,957.4,2.25667,-4.99766,-25.7595
2016-02-12 08:36:25,40.3487052,115.7855169,1.1040000000000418,5.99085,149.5,16.6,957.4,2.25532,-4.78653,-25.4645
2016-02-12 08:36:26,40.3487213,115.7855067,0.8840000000000146,6.04219,151.354,16.6,957.4,2.26913,-4.636,-25.7042
2016-02-12 08:36:27,40.3487372,115.7854966,0.8730000000000473,5.95603,152.786,16.6,957.4,2.26901,-4.5439,-24.9907
2016-02-12 08:36:28,40.348753,115.7854872,0.6620000000000346,6.0444,155.92,16.6,957.4,2.25882,-5.09607,-21.8508
2016-02-12 08:36:29,40.3487698,115.7854789,0.7740000000000009,6.23573,157.69,16.6,957.4,2.27421,-4.48643,-17.9076
2016-02-12 08:36:30,40.3487874,115.7854718,0.9569999999999936,6.31058,159.216,16.5,957.4,2.25334,-4.42131,-14.4395
2016-02-12 08:36:31,40.3488052,115.7854663,0.8700000000000045,6.16818,160.728,16.5,957.4,2.25037,-4.45109,-11.6332
2016-02-12 08:36:32,40.3488228,115.785462,0.5060000000000286,6.10734,161.71,16.5,957.4,2.25493,-4.35846,-8.40024
2016-02-12 08:36:33,40.3488399,115.7854588,0.799000000000035,6.11898,164.494,16.4,957.4,2.24844,-5.41057,-6.17409
2016-02-12 08:36:34,40.3488573,115.7854564,0.742999999999995,6.07141,167.215,16.4,957.4,2.26561,-5.26034,-2.7436
2016-02-12 08:36:35,40.3488754,115.7854551,0.6370000000000005,6.0496,171.946,16.4,957.4,2.25455,-4.44777,1.35836
2016-02-12 08:36:36,40.3488935,115.785456,0.7320000000000277,5.83808,173.643,16.4,957.4,2.26214,-4.58309,4.52072
2016-02-12 08:36:37,40.3489117,115.7854579,0.8480000000000132,5.70385,172.17,16.4,957.4,2.26151,-3.90147,5.07055
2016-02-12 08:36:38,40.3489293,115.78546,0.9800000000000182,5.51454,171.791,16.4,957.4,2.25964,-4.5457,5.24711
2016-02-12 08:36:39,40.348947,115.7854622,1.1539999999999964,5.33505,173.485,16.4,957.4,2.26292,-4.35318,5.33673
2016-02-12 08:36:40,40.3489653,115.7854648,1.0,5.29204,174.852,16.3,957.4,2.25233,-3.87292,4.70492
2016-02-12 08:36:41,40.3489836,115.7854674,1.3559999999999945,5.29741,176.258,16.3,957.4,2.25662,-3.21208,5.21414
2016-02-12 08:36:42,40.3490015,115.7854698,1.3730000000000473,5.14176,174.023,16.3,957.4,2.25812,-3.51608,5.02582
2016-02-12 08:36:43,40.3490189,115.7854713,1.516999999999996,5.12388,174.751,16.2,957.4,2.25788,-4.56814,5.03848
2016-02-12 08:36:44,40.3490365,115.7854732,1.4870000000000232,5.10234,176.725,16.2,957.4,2.26351,-3.96444,5.46284
2016-02-12 08:36:45,40.3490545,115.7854759,1.3980000000000246,5.09201,176.966,16.2,957.4,2.2583,-3.79534,5.24914
2016-02-12 08:36:46,40.3490724,115.7854788,1.6370000000000005,5.11211,176.889,16.2,957.4,2.2544,-3.72235,5.29693
2016-02-12 08:36:47,40.3490906,115.785481,1.1280000000000427,4.8991,175.319,16.2,957.4,2.26159,-3.32421,5.01752
2016-02-12 08:36:48,40.3491085,115.7854831,0.8170000000000073,4.10668,170.376,16.2,957.4,2.25495,10.1467,5.26258
2016-02-12 08:36:49,40.3491158,115.7854839,0.9000000000000341,2.6314,163.343,16.2,957.4,2.26207,0.106344,5.66132
2016-02-12 08:36:50,40.349117,115.785484,0.38100000000002865,1.58396,131.609,16.1,957.4,2.26455,-0.625125,5.82946
2016-02-12 08:36:51,40.3491165,115.7854841,0.313000000000045,0.960517,119.397,16.1,957.4,2.25937,-1.82616,5.43775
2016-02-12 08:36:52,40.3491162,115.7854839,0.5020000000000095,0.136019,56.7013,16.1,957.4,2.26542,-1.73079,5.51902
2016-02-12 08:36:53,40.3491157,115.7854835,0.3410000000000082,0.0603939,21.4057,16.1,957.4,2.25628,-1.86747,5.8482
2016-02-12 08:36:54,40.3491154,115.7854833,0.19600000000002638,0.0369274,47.6323,16.1,957.4,2.25712,-1.53655,6.2355
2016-02-12 08:36:55,40.3491151,115.7854834,0.2470000000000141,0.0871401,79.15,16.1,957.4,2.26202,-1.14965,6.09218
2016-02-12 08:36:56,40.3491149,115.7854834,0.08300000000002683,0.393658,71.1975,16.1,957.4,2.25841,-1.21857,5.48189
2016-02-12 08:36:57,40.3491148,115.7854834,0.32900000000000773,0.586761,66.23,16.1,957.4,2.27044,-1.31146,5.43551
2016-02-12 08:36:58,40.3491145,115.7854834,0.28600000000000136,0.596112,53.5956,16.1,957.4,2.25902,-1.45305,5.54127
2016-02-12 08:36:59,40.3491142,115.7854835,0.21200000000004593,0.25565,52.3429,16.1,957.4,2.25571,-1.29331,5.77698
2016-02-12 08:37:00,40.3491142,115.7854836,0.25200000000000955,0.0781401,60.0922,16.1,957.4,2.26602,-1.42537,5.60733
2016-02-12 08:37:01,40.3491142,115.7854835,0.16100000000000136,0.0230935,155.25,16.1,957.4,2.25023,-1.26584,5.76965
2016-02-12 08:37:02,40.349114,115.7854833,0.10099999999999909,0.0296167,138.082,16.1,957.4,2.26859,-0.900714,6.01267
2016-02-12 08:37:03,40.349114,115.7854834,0.15500000000002956,0.430488,50.8187,16.1,957.4,2.25236,-1.35083,5.15359
2016-02-12 08:37:04,40.3491135,115.7854833,0.48500000000001364,0.980068,84.1409,16.1,957.4,2.26295,-2.14462,6.25571
2016-02-12 08:37:05,40.3491133,115.7854835,0.3830000000000382,1.27921,103.371,16.1,957.4,2.25558,-2.13589,6.19036
2016-02-12 08:37:06,40.3491131,115.7854836,0.4159999999999968,1.00135,137.031,16.1,957.4,2.26097,-2.52534,5.96649
2016-02-12 08:37:07,40.3491134,115.7854836,0.2950000000000159,0.717434,155.678,16.1,957.4,2.26059,-1.63997,5.78432
2016-02-12 08:37:08,40.3491138,115.7854835,0.21200000000004593,0.303557,137.275,16.1,957.4,2.25044,-0.967678,5.61883
2016-02-12 08:37:09,40.3491137,115.7854835,0.21100000000001273,0.285436,130.174,16.1,957.4,2.25547,-0.834362,5.65676
2016-02-12 08:37:10,40.3491134,115.7854835,0.1500000000000341,0.083626,87.1777,16.1,957.4,2.26308,-0.800933,5.2812
2016-02-12 08:37:11,40.3491131,115.7854835,0.16700000000003,0.10367,42.9916,16.1,957.4,2.25831,-1.52589,4.76376
2016-02-12 08:37:12,40.3491127,115.7854833,0.5340000000000487,0.113468,112.581,16.1,957.4,2.26024,-1.83201,5.26747
2016-02-12 08:37:13,40.3491126,115.7854835,0.5110000000000241,0.0976797,81.7381,16.1,957.4,2.2573,-1.50989,5.33285
2016-02-12 08:37:14,40.3491124,115.7854837,0.5590000000000259,1.8663,90.5845,16.1,957.4,2.26294,-1.44776,5.84654
2016-02-12 08:37:15,40.3491125,115.7854838,1.865000000000009,2.56762,89.8643,16.1,957.4,2.26043,-0.567501,6.1396
2016-02-12 08:37:16,40.3491122,115.7854834,4.349000000000046,0.917837,91.5823,16.1,957.6,2.26137,-1.97875,5.82784
2016-02-12 08:37:17,40.3491111,115.7854803,5.638000000000034,0.716475,48.2852,16.1,957.6,2.26394,-2.59172,42.491
2016-02-12 08:37:18,40.349111,115.7854795,5.432000000000016,0.760453,50.6434,16.1,957.6,2.25914,-6.46643,44.7529
2016-02-12 08:37:19,40.3491155,115.785485,5.338999999999999,0.642827,152.992,16.2,957.6,2.25408,-8.15347,44.0491
2016-02-12 08:37:20,40.3491267,115.7854981,5.7379999999999995,1.76091,82.2608,16.2,957.6,2.25425,2.78277,45.1
2016-02-12 08:37:21,40.3491335,115.7855064,5.6650000000000205,0.881555,11.1025,16.2,957.6,2.26243,3.05661,47.7378
2016-02-12 08:37:23,40.3491349,115.7855084,5.471000000000004,0.876476,69.6464,16.2,957.6,2.25292,-11.4077,48.1101
2016-02-12 08:37:23,40.3491427,115.7855204,5.588999999999999,1.84099,115.054,16.2,957.6,2.25092,-3.99469,47.4194
2016-02-12 08:37:25,40.3491553,115.7855389,5.801000000000045,2.39834,107.803,16.2,957.6,2.25989,-2.57408,47.3755
2016-02-12 08:37:26,40.3491683,115.7855575,6.093000000000018,3.37656,124.034,16.2,957.4,2.26015,-2.74762,47.3582
2016-02-12 08:37:27,40.3491811,115.785576,6.409000000000049,3.88895,134.223,16.2,957.4,2.25817,-3.03106,47.53
2016-02-12 08:37:28,40.3491935,115.7855944,6.5540000000000305,3.92564,147.649,16.2,957.4,2.25108,-3.07153,47.3604
2016-02-12 08:37:29,40.3492054,115.7856118,6.573000000000036,4.2193,150.06,16.2,957.4,2.2539,-3.572,47.243
2016-02-12 08:37:30,40.3492176,115.7856288,6.5160000000000196,4.64874,149.884,16.2,957.4,2.24965,-3.67273,47.4047
2016-02-12 08:37:31,40.3492301,115.7856461,6.145000000000039,4.72077,150.734,16.2,957.4,2.2622,-3.50582,47.5138
2016-02-12 08:37:32,40.3492422,115.7856636,6.133000000000038,4.53941,145.099,16.2,957.4,2.25039,-3.6977,50.4106
2016-02-12 08:37:33,40.3492531,115.7856817,6.093999999999994,4.65501,139.49,16.2,957.4,2.25039,-4.10876,54.9473
2016-02-12 08:37:34,40.3492629,115.785701,6.29400000000004,4.75953,137.043,16.2,957.4,2.26519,-3.8511,58.421
2016-02-12 08:37:35,40.349272,115.7857212,6.16700000000003,4.68933,133.723,16.2,957.4,2.25982,-2.84437,61.008
2016-02-12 08:37:36,40.3492803,115.7857422,5.970000000000027,3.71239,129.472,16.2,957.6,2.25764,-2.38204,64.3574
2016-02-12 08:37:37,40.3492877,115.7857639,5.673000000000002,3.24695,125.042,16.2,957.6,2.25472,-2.49819,68.7895
2016-02-12 08:37:38,40.3492935,115.7857858,6.0020000000000095,3.11102,121.256,16.2,957.4,2.26319,-2.82953,72.6732
2016-02-12 08:37:39,40.3492985,115.7858079,5.843000000000018,3.55585,127.703,16.2,957.6,2.26381,-3.01438,73.9861
2016-02-12 08:37:40,40.3493033,115.78583,5.6860000000000355,3.66656,127.519,16.2,957.6,2.26546,-3.47219,74.2353
2016-02-12 08:37:41,40.3493081,115.7858522,5.900000000000034,3.7344,126.386,16.2,957.6,2.26321,-3.65925,74.02
2016-02-12 08:37:42,40.3493131,115.7858748,5.757000000000005,3.59181,124.73,16.2,957.6,2.2622,-3.15687,74.24
2016-02-12 08:37:43,40.3493182,115.7858977,5.725999999999999,3.52774,122.094,16.2,957.6,2.25546,-3.02432,74.6855
2016-02-12 08:37:44,40.349323,115.7859204,5.878000000000043,3.64108,121.595,16.2,957.6,2.25546,-3.44193,74.1486
2016-02-12 08:37:45,40.3493279,115.7859431,5.875,4.10979,123.849,16.2,957.6,2.25546,-3.16246,74.2353
2016-02-12 08:37:46,40.3493334,115.7859706,5.775000000000034,4.2231,121.878,16.2,957.6,2.25546,-2.85934,77.3826
2016-02-12 08:37:47,40.3493371,115.7859941,5.854000000000042,3.38294,116.494,16.2,957.6,2.25546,-1.69435,81.6517
2016-02-12 08:37:48,40.349339,115.7860126,5.703000000000031,3.05009,112.988,16.2,957.6,2.25773,-2.59874,84.8266
2016-02-12 08:37:49,40.3493403,115.7860404,5.862000000000023,2.45333,104.114,16.2,957.6,2.25121,-2.6631,88.8626
2016-02-12 08:37:50,40.3493403,115.7860637,5.515000000000043,2.71353,107.91,16.2,957.6,2.26119,-2.36504,91.8881
2016-02-12 08:37:51,40.3493394,115.7860872,5.501000000000033,2.80362,106.534,16.2,957.6,2.272,-2.08923,94.6365
2016-02-12 08:37:52,40.3493377,115.7861101,5.75,2.76796,106.874,16.2,957.6,2.26665,-1.91928,98.7676
2016-02-12 08:37:53,40.3493346,115.7861332,5.528999999999996,2.30693,90.5027,16.1,957.6,2.27118,-1.50633,102.875
2016-02-12 08:37:54,40.3493303,115.7861556,5.57000000000005,2.15987,80.27,16.1,957.6,2.26014,-2.41663,106.747
2016-02-12 08:37:55,40.3493251,115.7861782,5.718000000000018,1.98563,72.6664,16.1,957.6,2.26723,-2.04302,107.311
2016-02-12 08:37:56,40.3493196,115.7862007,5.552999999999997,2.00151,72.8042,16.1,957.6,2.26513,-2.02087,106.976
2016-02-12 08:37:57,40.3493142,115.7862233,5.675000000000011,2.00659,73.3209,16.1,957.6,2.27117,-2.0311,106.897
2016-02-12 08:37:58,40.349309,115.786246,5.585000000000036,1.99442,73.2617,16.1,957.6,2.26669,-1.85794,107.051
2016-02-12 08:37:59,40.3493037,115.7862686,5.536000000000001,2.00573,73.0795,16.1,957.6,2.26195,-1.67994,106.978
2016-02-12 08:38:00,40.3492984,115.7862912,5.532000000000039,2.00435,72.5278,16.1,957.6,2.26446,-1.44107,107.109
2016-02-12 08:38:01,40.3492929,115.7863138,5.579000000000008,2.01129,72.6281,16.1,957.6,2.26836,-1.59664,107.211
2016-02-12 08:38:02,40.3492874,115.7863364,5.55800000000005,1.98886,72.6863,16.1,957.6,2.2662,-1.67881,106.822
2016-02-12 08:38:03,40.3492821,115.7863585,5.632000000000005,1.97927,70.5809,16.1,957.6,2.26912,-1.75376,109.576
2016-02-12 08:38:04,40.349276,115.7863801,5.837000000000046,1.97986,64.8357,16.1,957.6,2.27006,-1.97127,114.942
2016-02-12 08:38:05,40.3492681,115.7864007,5.823000000000036,1.97842,61.166,16.1,957.6,2.26009,-1.6458,118.698
2016-02-12 08:38:06,40.3492592,115.7864208,5.7900000000000205,1.99769,57.8575,16.1,957.6,2.26133,-1.79207,121.582
2016-02-12 08:38:07,40.3492495,115.7864403,5.853000000000009,2.00282,54.7015,16.1,957.6,2.26969,-1.57073,124.545
2016-02-12 08:38:08,40.349239,115.786459,5.771000000000015,1.9989,50.599,16.1,957.6,2.25815,-1.77694,129.001
2016-02-12 08:38:09,40.3492274,115.7864766,5.78000000000003,1.98813,46.3829,16.1,957.6,2.26562,-1.72888,133.366
2016-02-12 08:38:10,40.349215,115.7864933,5.866000000000042,1.99488,45.6054,16.1,957.6,2.26581,-2.17574,134.303
2016-02-12 08:38:11,40.3492022,115.7865101,5.807000000000016,1.98864,45.893,16.1,957.6,2.2618,-1.81056,134.52
2016-02-12 08:38:12,40.3491897,115.7865271,5.6410000000000196,1.99804,46.0968,16.1,957.6,2.26713,-1.72293,134.343
2016-02-12 08:38:13,40.3491772,115.7865441,5.715000000000032,2.01774,45.7766,16.2,957.6,2.26881,-1.66066,134.316
2016-02-12 08:38:14,40.3491645,115.7865609,5.787000000000035,2.01669,41.1983,16.2,957.6,2.26173,-1.78608,137.866
2016-02-12 08:38:15,40.3491509,115.7865759,5.875,1.98778,34.7049,16.2,957.6,2.25985,-1.48482,144.993
2016-02-12 08:38:16,40.3491362,115.7865886,5.813000000000045,1.97874,28.2621,16.2,957.6,2.26267,-1.65466,150.873
2016-02-12 08:38:17,40.3491205,115.7865992,6.025000000000034,2.26713,25.0355,16.2,957.4,2.2593,-1.70951,156.254
2016-02-12 08:38:18,40.3491039,115.7866075,6.006000000000029,2.47573,18.7115,16.2,957.4,2.2718,-1.63082,161.557
2016-02-12 08:38:19,40.349087,115.7866139,5.956999999999994,2.56727,8.6849,16.2,957.6,2.26504,-1.88711,168.928
2016-02-12 08:38:20,40.3490696,115.7866172,6.229000000000042,2.75719,0.527441,16.2,957.4,2.26636,-1.99268,174.757
2016-02-12 08:38:21,40.3490516,115.7866186,6.1370000000000005,3.24292,2.39415,16.2,957.4,2.26015,-2.09729,175.563
2016-02-12 08:38:22,40.3490337,115.7866199,6.097000000000037,3.42724,3.36974,16.2,957.4,2.26113,-2.11005,175.792
2016-02-12 08:38:23,40.3490159,115.7866215,6.021000000000015,3.56703,2.19504,16.2,957.4,2.26318,-2.58626,176.337
2016-02-12 08:38:24,40.3489978,115.7866231,6.031000000000006,2.98014,0.730891,16.2,957.4,2.2592,-2.18878,176.036
2016-02-12 08:38:25,40.3489799,115.7866245,6.050000000000011,2.8769,1.18416,16.2,957.4,2.25769,-2.45616,175.722
2016-02-12 08:38:26,40.348962,115.7866262,6.004000000000019,2.97136,0.474847,16.2,957.4,2.25814,-2.30747,176.164
2016-02-12 08:38:27,40.348944,115.7866277,6.004000000000019,3.28611,0.877931,16.2,957.4,2.269,-2.20202,176.154
2016-02-12 08:38:28,40.3489259,115.7866295,5.921000000000049,3.28373,1.71368,16.2,957.6,2.26907,-2.02838,175.744
2016-02-12 08:38:29,40.3489042,115.786632,5.921000000000049,3.18593,0.556809,16.2,957.6,2.26987,-1.73959,176.318
2016-02-12 08:38:30,40.3488863,115.7866332,5.9430000000000405,3.17403,2.17954,16.2,957.6,2.26099,-1.88535,178.499
2016-02-12 08:38:31,40.3488686,115.7866333,6.1370000000000005,3.17068,5.38026,16.2,957.4,2.25922,-2.30753,-178.254
2016-02-12 08:38:32,40.3488508,115.786632,6.119000000000028,2.97947,7.49582,16.2,957.4,2.26828,-1.80747,-175.54
2016-02-12 08:38:33,40.348833,115.7866299,6.079000000000008,2.76366,9.47064,16.2,957.4,2.2712,-2.05905,-172.77
2016-02-12 08:38:34,40.3488154,115.7866269,6.048000000000002,2.80114,12.3371,16.2,957.4,2.26121,-2.1765,-171.028
2016-02-12 08:38:35,40.3487978,115.7866228,5.961000000000013,2.38589,13.145,16.2,957.6,2.25807,-1.81427,-168.985
2016-02-12 08:38:36,40.3487802,115.7866181,5.861000000000047,2.69336,16.9089,16.2,957.6,2.26228,-1.41431,-166.704
2016-02-12 08:38:37,40.3487628,115.7866124,6.129000000000019,3.06392,23.064,16.2,957.4,2.26631,-1.84058,-163.542
2016-02-12 08:38:38,40.3487457,115.7866051,6.288000000000011,3.4603,28.1621,16.2,957.4,2.26631,-1.43673,-160.633
2016-02-12 08:38:39,40.3487288,115.7865968,6.198000000000036,3.43651,28.6348,16.2,957.4,2.26631,-1.62867,-159.419
2016-02-12 08:38:40,40.348712,115.7865883,5.991000000000042,2.75678,26.6074,16.2,957.6,2.26457,-0.846973,-159.113
2016-02-12 08:38:41,40.3486952,115.7865797,6.177000000000021,2.54112,26.0398,16.2,957.4,2.26195,-1.4228,-160.025
2016-02-12 08:38:42,40.3486785,115.7865715,6.125,2.77843,30.673,16.2,957.4,2.27229,-1.28339,-158.953
2016-02-12 08:38:43,40.3486617,115.7865631,5.989000000000033,2.89037,31.4589,16.2,957.6,2.26166,-1.72081,-159.983
2016-02-12 08:38:44,40.3486446,115.7865549,6.1059999999999945,3.4807,38.7283,16.2,957.4,2.2613,-0.817808,-159.645
2016-02-12 08:38:45,40.3486278,115.7865468,6.263000000000034,3.21584,39.218,16.2,957.4,2.25894,-1.0708,-159.434
2016-02-12 08:38:46,40.3486114,115.7865384,6.3799999999999955,3.20978,42.7982,16.3,957.4,2.24972,-1.54731,-156.522
2016-02-12 08:38:47,40.3485958,115.7865289,6.196000000000026,3.13252,47.861,16.3,957.4,2.25409,-2.09613,-150.524
2016-02-12 08:38:48,40.3485808,115.7865168,6.437000000000012,3.67395,54.5351,16.3,957.4,2.2518,-2.04851,-144.217
2016-02-12 08:38:49,40.348567,115.7865025,6.314999999999998,3.8837,60.8641,16.3,957.4,2.2588,-2.03042,-138.723
2016-02-12 08:38:50,40.3485541,115.7864867,6.55600000000004,4.24575,66.9797,16.3,957.4,2.25364,-2.63416,-133.698
2016-02-12 08:38:51,40.3485426,115.7864697,6.711000000000013,4.50037,69.3373,16.3,957.4,2.26174,-3.24088,-128.675
2016-02-12 08:38:52,40.3485322,115.7864511,6.847000000000037,4.77316,73.4454,16.3,957.4,2.26407,-3.37251,-123.113
2016-02-12 08:38:53,40.3485233,115.786431,6.723000000000013,5.25047,74.79,16.3,957.4,2.2571,-3.46872,-116.851
2016-02-12 08:38:54,40.3485158,115.7864097,6.77800000000002,5.24579,78.8962,16.3,957.4,2.26562,-2.75706,-110.608
2016-02-12 08:38:55,40.3485097,115.7863879,6.963000000000022,5.36328,78.6499,16.3,957.4,2.263,-3.80411,-109.608
2016-02-12 08:38:56,40.3485038,115.7863656,6.785000000000025,5.18284,77.9227,16.3,957.4,2.24412,-3.57529,-109.918
2016-02-12 08:38:57,40.3484977,115.7863432,6.955000000000041,5.49547,77.0321,16.3,957.4,2.25077,-3.53406,-110.109
2016-02-12 08:38:58,40.3484917,115.7863208,6.76400000000001,5.50554,76.9921,16.3,957.4,2.25282,-3.11968,-109.696
2016-02-12 08:38:59,40.3484855,115.7862986,7.1860000000000355,5.67789,76.452,16.3,957.4,2.25288,-3.84746,-109.962
2016-02-12 08:39:00,40.3484793,115.7862769,7.2760000000000105,5.58245,78.3723,16.3,957.4,2.25248,-4.04632,-109.703
2016-02-12 08:39:01,40.3484733,115.7862548,7.010000000000048,5.50281,81.2427,16.3,957.4,2.25681,-3.7117,-109.605
2016-02-12 08:39:02,40.3484675,115.7862318,6.583000000000027,5.4681,80.5694,16.3,957.4,2.25373,-2.64838,-110.026
2016-02-12 08:39:03,40.3484615,115.7862087,6.435000000000002,5.24186,80.0162,16.3,957.4,2.26402,-2.47181,-110.066
2016-02-12 08:39:04,40.3484553,115.7861861,6.744000000000028,4.78997,78.1177,16.3,957.4,2.25976,-3.00221,-110.003
2016-02-12 08:39:05,40.3484491,115.7861637,6.635000000000048,4.66952,79.3902,16.3,957.4,2.25965,-2.87573,-109.383
2016-02-12 08:39:06,40.3484432,115.7861416,6.846000000000004,4.6271,83.315,16.2,957.4,2.25455,-2.74948,-106.217
2016-02-12 08:39:07,40.3484387,115.7861197,7.13900000000001,4.8648,90.499,16.2,957.4,2.25685,-3.80011,-100.807
2016-02-12 08:39:08,40.348436,115.7860971,7.078000000000031,5.13107,93.7453,16.2,957.4,2.25624,-3.61118,-96.6337
2016-02-12 08:39:09,40.3484346,115.7860739,6.874000000000024,5.30274,96.2317,16.2,957.4,2.25331,-3.42438,-93.2439
2016-02-12 08:39:10,40.3484343,115.7860502,6.77800000000002,5.30424,98.1641,16.2,957.4,2.2591,-3.43879,-89.3696
2016-02-12 08:39:11,40.3484346,115.7860267,6.948000000000036,5.36689,101.168,16.2,957.4,2.26334,-3.13154,-85.9754
2016-02-12 08:39:12,40.3484361,115.7860039,6.992999999999995,5.36225,105.602,16.2,957.4,2.26374,-3.71979,-81.9432
2016-02-12 08:39:13,40.3484392,115.7859812,6.986000000000047,5.58163,111.056,16.2,957.4,2.27043,-3.86594,-76.8084
2016-02-12 08:39:14,40.3484453,115.7859542,7.071000000000026,5.59064,113.182,16.2,957.4,2.26144,-3.68614,-72.9019
2016-02-12 08:39:15,40.3484508,115.7859315,6.8180000000000405,5.49402,114.441,16.2,957.4,2.26241,-3.7118,-72.5991
2016-02-12 08:39:16,40.3484563,115.7859087,6.723000000000013,5.288,114.232,16.2,957.4,2.2694,-3.66929,-72.6022
2016-02-12 08:39:17,40.3484619,115.785886,6.861000000000047,5.0759,114.328,16.2,957.4,2.27796,-3.37821,-72.5735
2016-02-12 08:39:18,40.3484673,115.7858638,6.777000000000044,4.85226,114.202,16.2,957.4,2.2586,-3.65391,-72.617
2016-02-12 08:39:19,40.3484724,115.7858417,6.831000000000017,4.95735,114.591,16.2,957.4,2.26003,-3.9336,-72.5228
2016-02-12 08:39:20,40.3484777,115.7858195,6.79400000000004,5.19502,114.403,16.2,957.4,2.26938,-3.7664,-72.49
2016-02-12 08:39:21,40.348483,115.7857968,6.8910000000000196,5.40131,114.221,16.2,957.4,2.26292,-3.57338,-72.637
2016-02-12 08:39:22,40.3484882,115.785774,6.80800000000005,5.49249,113.991,16.2,957.4,2.25832,-3.62734,-72.9702
2016-02-12 08:39:23,40.3484933,115.7857514,6.855000000000018,5.30347,113.598,16.2,957.4,2.26829,-3.95096,-72.8731
2016-02-12 08:39:24,40.3484986,115.7857289,7.079000000000008,5.39845,115.741,16.2,957.4,2.26638,-3.72339,-70.6984
2016-02-12 08:39:25,40.3485052,115.7857071,6.997000000000014,5.59344,120.748,16.2,957.4,2.25883,-3.71214,-65.1554
2016-02-12 08:39:26,40.3485135,115.7856866,6.882000000000005,5.57928,126.78,16.2,957.4,2.27045,-3.56952,-59.0728
2016-02-12 08:39:27,40.3485232,115.7856676,7.5540000000000305,5.53672,130.762,16.2,957.4,2.26442,-4.75008,-53.7121
2016-02-12 08:39:28,40.3485341,115.7856494,7.011000000000024,5.59819,132.478,16.2,957.4,2.27287,-4.20102,-49.5037
2016-02-12 08:39:29,40.3485461,115.7856316,6.975999999999999,5.6987,136.872,16.1,957.4,2.27001,-3.76073,-44.3638
2016-02-12 08:39:30,40.3485592,115.7856157,6.80600000000004,5.66211,141.975,16.1,957.4,2.25656,-4.27646,-39.2167
2016-02-12 08:39:31,40.3485731,115.7856017,6.959000000000003,5.84401,147.888,16.1,957.4,2.26741,-4.22084,-33.5571
2016-02-12 08:39:32,40.348588,115.7855893,6.881000000000029,5.84942,153.684,16.1,957.4,2.26479,-4.14474,-27.6361
2016-02-12 08:39:33,40.348604,115.7855792,7.069000000000017,5.77161,153.734,16.1,957.4,2.25661,-4.20067,-25.4868
2016-02-12 08:39:34,40.3486205,115.7855695,6.948000000000036,5.68293,151.175,16.1,957.4,2.26653,-4.28749,-25.5627
2016-02-12 08:39:35,40.3486369,115.7855593,6.831999999999994,5.59499,149.507,16.1,957.4,2.26059,-3.60083,-25.7786
2016-02-12 08:39:36,40.3486532,115.785549,6.910000000000025,5.34526,148.245,16.1,957.4,2.25904,-3.79517,-25.4626
2016-02-12 08:39:37,40.3486694,115.7855391,6.90300000000002,5.2722,148.018,16.1,957.4,2.24588,-4.47698,-26.0671
2016-02-12 08:39:38,40.3486856,115.7855286,6.662000000000035,5.58787,149.531,16.1,957.4,2.26247,-3.74773,-25.3043
2016-02-12 08:39:39,40.348702,115.7855183,6.588000000000022,5.58677,149.414,16.1,957.4,2.2546,-3.41345,-25.3933
2016-02-12 08:39:40,40.3487186,115.7855084,6.819000000000017,5.39394,150.467,16.1,957.4,2.26018,-3.45871,-25.8609
2016-02-12 08:39:41,40.3487348,115.785498,6.869000000000028,5.13558,149.501,16.1,957.4,2.25899,-3.54752,-25.3197
2016-02-12 08:39:42,40.3487508,115.7854881,7.076999999999998,5.12994,151.902,16.0,957.4,2.2604,-3.27375,-23.0354
2016-02-12 08:39:43,40.348767,115.7854795,7.107000000000028,5.24712,156.111,16.0,957.4,2.25978,-4.17538,-19.0296
2016-02-12 08:39:44,40.3487838,115.7854726,7.342000000000041,5.14911,158.067,16.0,957.4,2.26895,-3.91688,-14.9458
2016-02-12 08:39:45,40.3488012,115.7854673,7.123000000000047,5.12797,160.258,16.0,957.4,2.25685,-3.97569,-12.4655
2016-02-12 08:39:46,40.3488187,115.7854626,7.0470000000000255,5.25077,161.458,16.0,957.4,2.2575,-3.93482,-9.47375
2016-02-12 08:39:47,40.3488361,115.7854589,6.831000000000017,5.34247,163.638,16.0,957.4,2.2747,-3.97845,-6.77187
2016-02-12 08:39:48,40.3488535,115.7854563,6.91700000000003,5.35046,168.762,16.0,957.4,2.2638,-4.43388,-3.3938
2016-02-12 08:39:49,40.3488712,115.7854556,7.05800000000005,5.36638,172.552,16.0,957.4,2.24989,-4.01909,0.499612
2016-02-12 08:39:50,40.3488894,115.7854567,6.927999999999997,5.18338,176.719,16.0,957.4,2.25543,-2.9186,4.27917
2016-02-12 08:39:51,40.3489075,115.7854591,6.824000000000012,4.74102,174.68,16.0,957.4,2.26294,-3.10757,5.12577
2016-02-12 08:39:52,40.3489253,115.7854614,6.846000000000004,4.61108,173.089,16.0,957.4,2.26023,-3.50273,5.24859
2016-02-12 08:39:53,40.3489432,115.7854633,6.754000000000019,4.60728,171.857,16.0,957.4,2.24849,-3.4541,5.02424
2016-02-12 08:39:54,40.348961,115.7854649,6.802000000000021,4.80725,173.53,16.0,957.4,2.24994,-3.31187,5.23906
2016-02-12 08:39:55,40.3489786,115.7854669,6.7690000000000055,4.84929,175.141,16.0,957.4,2.26774,-3.80584,4.93247
2016-02-12 08:39:56,40.3489961,115.7854684,6.984000000000037,4.82154,177.285,16.0,957.4,2.25052,-4.3044,6.02525
2016-02-12 08:39:57,40.3490136,115.7854712,7.0750000000000455,4.97235,176.681,16.0,957.4,2.26103,-4.44092,4.73105
2016-02-12 08:39:58,40.3490352,115.7854737,7.221000000000004,5.17525,176.871,16.0,957.4,2.24897,-4.50248,5.03347
2016-02-12 08:39:59,40.3490496,115.7854757,7.2830000000000155,5.31328,175.68,15.9,957.4,2.2604,-4.74577,5.08683
2016-02-12 08:40:00,40.3490715,115.7854787,6.9150000000000205,5.36721,173.39,15.9,957.4,2.25116,-3.63533,5.45957
2016-02-12 08:40:01,40.3490892,115.7854806,7.02800000000002,5.49745,171.838,15.9,957.4,2.24886,-5.20438,5.31366
2016-02-12 08:40:02,40.3491065,115.7854825,7.034000000000049,4.96294,169.028,15.9,957.4,2.25694,8.55605,4.86752
2016-02-12 08:40:03,40.3491136,115.7854833,7.170000000000016,3.77454,166.109,15.9,957.4,2.2609,-2.98443,5.3243
2016-02-12 08:40:04,40.349114,115.7854833,6.729000000000042,2.51774,161.1,15.9,957.4,2.25686,-2.8505,5.30476
2016-02-12 08:40:05,40.3491134,115.7854828,6.692000000000007,2.18392,157.804,15.9,957.4,2.255,-3.45238,5.31065
2016-02-12 08:40:06,40.3491132,115.7854827,6.604000000000042,1.60109,157.059,15.9,957.4,2.25357,-2.80026,5.5161
2016-02-12 08:40:07,40.3491134,115.7854827,6.537000000000035,2.12836,156.218,15.9,957.4,2.25833,-2.45733,5.39147
2016-02-12 08:40:08,40.3491137,115.7854829,6.403999999999996,2.12331,158.872,15.9,957.4,2.25188,-2.14385,5.2223
2016-02-12 08:40:09,40.3491142,115.7854831,6.421000000000049,1.8301,160.043,15.9,957.4,2.25406,-2.07424,4.97781
2016-02-12 08:40:10,40.3491147,115.785483,6.369000000000028,1.81565,164.795,15.9,957.4,2.25066,-2.04528,5.5712
2016-02-12 08:40:11,40.349115,115.785483,6.395000000000039,1.20916,168.073,15.9,957.4,2.25142,-2.12568,5.6004
2016-02-12 08:40:12,40.3491152,115.785483,6.479000000000042,0.923121,169.145,15.9,957.4,2.25772,-2.39996,5.49499
2016-02-12 08:40:13,40.3491156,115.7854834,6.295000000000016,0.112622,176.925,15.9,957.4,2.2419,-0.992479,5.52595
2016-02-12 08:40:14,40.3491156,115.7854835,5.983000000000004,0.104385,137.479,15.9,957.6,2.24902,-2.09931,4.83266
2016-02-12 08:40:15,40.3491156,115.7854831,6.322000000000003,0.0972996,135.981,15.9,957.4,2.25507,-2.44217,5.66033
2016-02-12 08:40:16,40.3491157,115.785483,6.293000000000006,0.399473,144.672,15.9,957.4,2.24642,-1.95636,5.97701
2016-02-12 08:40:17,40.3491159,115.7854832,6.54200000000003,0.419162,134.864,15.9,957.4,2.25464,-2.12978,4.8956
2016-02-12 08:40:18,40.3491159,115.7854832,6.412000000000035,0.0974758,162.941,15.9,957.4,2.25094,-2.48262,5.51442
2016-02-12 08:40:19,40.349116,115.7854833,6.161000000000001,0.109608,160.361,15.9,957.4,2.25091,-1.41836,5.54454
2016-02-12 08:40:20,40.3491161,115.7854831,6.199000000000012,0.0171219,103.985,15.9,957.4,2.24909,-1.11168,5.4494
2016-02-12 08:40:21,40.349116,115.7854829,6.218000000000018,0.0288269,128.137,15.9,957.4,2.25383,-1.09086,5.29294
2016-02-12 08:40:22,40.349116,115.7854829,6.281000000000006,0.0365605,136.308,15.9,957.4,2.25341,-1.30006,5.35584
2016-02-12 08:40:23,40.349116,115.7854829,6.138000000000034,0.300536,142.642,15.9,957.4,2.24777,-1.31523,5.10688
2016-02-12 08:40:24,40.3491159,115.7854831,6.272000000000048,0.362359,104.119,15.9,957.4,2.2515,-1.26287,5.34579
2016-02-12 08:40:25,40.3491158,115.7854836,6.330000000000041,0.57932,67.1366,15.9,957.4,2.25599,-1.2537,5.10477
2016-02-12 08:40:26,40.349116,115.7854837,6.2590000000000146,0.293271,61.2633,15.9,957.4,2.25032,-1.35474,4.62019
2016-02-12 08:40:27,40.3491159,115.7854839,6.537000000000035,1.43408,87.8411,15.9,957.4,2.24641,-1.43189,4.81176
2016-02-12 08:40:28,40.3491158,115.7854845,7.9360000000000355,2.6621,90.2237,15.9,957.4,2.25034,-1.61754,4.72443
2016-02-12 08:40:29,40.349116,115.7854846,10.175000000000011,1.31573,89.1393,16.0,957.6,2.24564,-1.20717,4.9345
2016-02-12 08:40:30,40.3491154,115.7854833,11.519000000000005,0.487783,84.9451,16.0,957.6,2.23793,1.226,32.3446
2016-02-12 08:40:31,40.3491146,115.7854801,11.199000000000012,0.888404,113.077,16.0,957.6,2.24013,-0.910583,49.0509
2016-02-12 08:40:32,40.3491176,115.7854848,11.338000000000022,1.21106,161.686,16.0,957.6,2.24855,-8.71139,49.124
2016-02-12 08:40:33,40.349127,115.7854984,11.410000000000025,1.15788,160.732,16.0,957.6,2.24702,2.53409,49.1037
2016-02-12 08:40:34,40.3491327,115.785507,11.30600000000004,1.57306,101.28,16.0,957.6,2.23904,3.0513,47.7375
2016-02-12 08:40:35,40.3491341,115.7855092,11.441000000000031,1.65924,120.583,16.0,957.6,2.23278,-11.256,47.7951
2016-02-12 08:40:36,40.3491421,115.7855205,11.745000000000005,2.09369,165.994,16.0,957.6,2.25014,-5.38932,47.3602
2016-02-12 08:40:37,40.3491545,115.7855384,11.939999999999998,2.19563,170.682,16.0,957.6,2.25111,-3.70094,47.3836
2016-02-12 08:40:38,40.3491676,115.7855572,12.343999999999994,2.72588,175.629,16.0,957.4,2.24778,-3.39111,47.5684
2016-02-12 08:40:39,40.3491805,115.7855757,12.349000000000046,3.77058,170.431,16.0,957.4,2.23919,-2.92421,47.3679
2016-02-12 08:40:40,40.3491932,115.7855932,12.30400000000003,4.32723,164.713,16.0,957.4,2.24849,-3.69776,47.2196
2016-02-12 08:40:41,40.3492058,115.7856107,12.257000000000005,4.97482,149.719,16.0,957.4,2.23899,-4.2628,46.9518
2016-02-12 08:40:42,40.3492184,115.7856285,12.064999999999998,5.01454,148.244,16.0,957.4,2.24654,-3.29362,47.9102
2016-02-12 08:40:43,40.3492309,115.7856463,11.847000000000037,4.75528,148.534,16.0,957.6,2.2461,-2.87623,47.2497
2016-02-12 08:40:44,40.3492429,115.7856634,11.926000000000045,4.45324,145.688,16.0,957.6,2.24807,-3.24547,50.6289
2016-02-12 08:40:45,40.3492538,115.7856819,11.890000000000043,4.37085,139.85,16.0,957.6,2.24435,-2.29374,55.1856
2016-02-12 08:40:46,40.3492636,115.7857015,11.858000000000004,4.45991,136.808,16.0,957.6,2.23915,-2.55544,58.6457
2016-02-12 08:40:47,40.3492726,115.7857216,11.834000000000003,4.44533,135.258,16.0,957.6,2.25354,-2.42264,61.5678
2016-02-12 08:40:48,40.3492809,115.7857425,11.573000000000036,4.17545,135.351,16.0,957.6,2.2454,-2.13607,64.4989
2016-02-12 08:40:49,40.3492883,115.7857639,11.456000000000017,3.50478,129.539,16.0,957.6,2.23091,-1.86106,68.0806
2016-02-12 08:40:50,40.3492945,115.7857856,11.674000000000035,3.04936,123.522,16.0,957.6,2.24878,-2.12556,72.5683
2016-02-12 08:40:51,40.3492995,115.7858078,11.607000000000028,2.59356,118.042,16.0,957.6,2.24837,-2.43165,74.4098
2016-02-12 08:40:52,40.349304,115.7858305,11.578000000000031,2.53347,125.879,16.0,957.6,2.24868,-2.31417,74.0187
2016-02-12 08:40:54,40.3493085,115.7858534,11.64100000000002,2.66835,133.005,16.0,957.6,2.25345,-2.44876,73.9301
2016-02-12 08:40:55,40.3493133,115.7858761,11.571000000000026,2.67835,132.957,16.0,957.6,2.24898,-2.21838,74.0699
2016-02-12 08:40:56,40.3493182,115.7858987,11.422000000000025,2.77779,137.606,16.0,957.6,2.24687,-2.05583,74.0956
2016-02-12 08:40:57,40.3493232,115.7859214,11.383000000000038,2.65526,125.47,16.0,957.6,2.25382,-2.1098,73.9022
2016-02-12 08:40:58,40.3493284,115.7859437,11.393000000000029,2.57385,121.79,16.0,957.6,2.25263,-2.48862,74.428
2016-02-12 08:40:59,40.3493328,115.7859659,11.778999999999996,2.60091,118.797,16.0,957.6,2.24775,-2.6614,76.9316
2016-02-12 08:41:00,40.3493363,115.7859886,11.846000000000004,2.80531,113.214,16.0,957.6,2.25006,-2.35789,81.2004
2016-02-12 08:41:01,40.3493386,115.7860116,11.75200000000001,3.46673,114.085,16.0,957.6,2.2521,-2.83111,84.5953
2016-02-12 08:41:02,40.3493399,115.7860352,11.573000000000036,3.45173,111.082,16.0,957.6,2.24462,-2.19087,88.0719
2016-02-12 08:41:03,40.3493402,115.7860585,11.668000000000006,3.17838,106.4,16.0,957.6,2.23597,-2.32365,91.6851
2016-02-12 08:41:04,40.3493394,115.7860821,11.456999999999994,2.92245,104.091,16.0,957.6,2.25143,-1.39402,94.5082
2016-02-12 08:41:05,40.3493376,115.7861056,11.509000000000015,2.69757,107.508,16.0,957.6,2.24626,-1.14534,97.7257
2016-02-12 08:41:06,40.349335,115.786129,11.551000000000045,2.14221,105.163,16.0,957.6,2.24878,-1.12488,101.724
2016-02-12 08:41:07,40.3493308,115.7861515,11.583000000000027,1.70315,97.0246,16.0,957.6,2.24965,-1.2808,105.324
2016-02-12 08:41:08,40.3493256,115.7861737,11.629999999999995,1.73263,82.1027,16.0,957.6,2.24099,-1.10128,106.318
2016-02-12 08:41:09,40.3493203,115.786196,11.79000000000002,1.88123,77.929,16.0,957.6,2.25065,-0.890223,106.882
2016-02-12 08:41:10,40.3493151,115.7862185,11.629999999999995,2.02174,72.4556,16.0,957.6,2.24402,-1.06764,106.757
2016-02-12 08:41:11,40.3493095,115.7862408,11.56800000000004,1.92404,75.0366,16.0,957.6,2.25262,-1.81658,106.7
2016-02-12 08:41:12,40.3493042,115.7862632,11.723000000000013,1.96386,76.6269,16.1,957.6,2.24628,-2.08718,106.681
2016-02-12 08:41:13,40.3492993,115.7862859,11.694000000000017,1.97875,76.6054,16.1,957.6,2.24301,-1.62918,106.355
2016-02-12 08:41:14,40.3492944,115.7863083,11.80800000000005,2.00308,72.8553,16.1,957.6,2.24278,-1.89877,107.29
2016-02-12 08:41:15,40.3492889,115.7863306,11.740000000000009,2.16399,82.2897,16.1,957.6,2.24469,-1.95941,107.744
2016-02-12 08:41:16,40.349282,115.7863579,11.583000000000027,2.06573,79.7034,16.1,957.6,2.24813,-1.54695,110.369
2016-02-12 08:41:17,40.3492752,115.7863801,11.729000000000042,1.96264,82.2375,16.1,957.6,2.24149,-1.13449,115.571
2016-02-12 08:41:18,40.349269,115.7863971,11.831999999999994,1.75547,77.7442,16.1,957.6,2.2488,-0.483331,119.086
2016-02-12 08:41:19,40.3492581,115.7864217,11.521000000000015,1.54649,80.1118,16.1,957.6,2.24992,-0.430019,121.889
2016-02-12 08:41:20,40.3492484,115.7864414,11.724000000000046,1.33618,90.5358,16.1,957.6,2.24614,-0.160765,124.514
2016-02-12 08:41:21,40.3492379,115.7864599,11.656000000000006,1.45789,75.7241,16.1,957.6,2.24723,-0.584383,129.253
2016-02-12 08:41:22,40.3492265,115.7864776,11.586000000000013,1.52183,64.4082,16.1,957.6,2.2461,-0.1055,133.895
2016-02-12 08:41:23,40.3492142,115.7864946,11.551000000000045,1.41725,53.5575,16.1,957.6,2.24917,-0.06657,133.811
2016-02-12 08:41:24,40.3492018,115.786511,11.67900000000003,1.96325,45.1024,16.1,957.6,2.24306,-0.546846,133.629
2016-02-12 08:41:25,40.3491892,115.7865273,11.583000000000027,1.89267,44.8856,16.1,957.6,2.25231,-0.522077,133.854
2016-02-12 08:41:26,40.3491766,115.786544,11.583000000000027,1.88507,45.3735,16.1,957.6,2.25312,-0.6115120000000001,134.018
2016-02-12 08:41:27,40.349164,115.7865603,11.56800000000004,1.90691,44.2069,16.1,957.6,2.24901,-0.704764,137.995
2016-02-12 08:41:28,40.3491509,115.7865759,11.733000000000004,1.89895,34.7881,16.1,957.6,2.2386,0.216962,144.763
2016-02-12 08:41:29,40.3491363,115.7865883,12.136000000000024,1.57389,21.6126,16.1,957.4,2.25495,-0.546539,150.518
2016-02-12 08:41:30,40.3491207,115.7865983,12.105999999999995,1.35377,6.14142,16.1,957.4,2.25067,-0.483964,155.45
2016-02-12 08:41:31,40.3491041,115.7866067,11.953000000000031,1.48538,7.6301,16.1,957.6,2.25743,0.186806,161.625
2016-02-12 08:41:32,40.349087,115.7866129,12.30800000000005,1.43146,25.3402,16.1,957.4,2.25932,-1.17416,169.539
2016-02-12 08:41:33,40.3490693,115.7866169,12.262,1.67297,11.2128,16.1,957.4,2.24673,-0.856737,175.334
2016-02-12 08:41:34,40.3490516,115.7866188,12.27600000000001,1.88287,5.05985,16.1,957.4,2.23945,-1.40952,175.648
2016-02-12 08:41:35,40.349034,115.7866202,12.26600000000002,2.07013,7.49265,16.2,957.4,2.25005,-1.36203,175.821
2016-02-12 08:41:36,40.3490162,115.7866215,12.102000000000032,2.16284,5.99243,16.2,957.4,2.24761,-1.28881,175.884
2016-02-12 08:41:37,40.3489984,115.786623,12.342000000000041,2.62051,11.9578,16.2,957.4,2.2545,-1.72705,176.135
2016-02-12 08:41:38,40.3489803,115.7866248,12.266999999999996,2.80948,9.05194,16.2,957.4,2.24654,-1.73863,175.918
2016-02-12 08:41:39,40.3489624,115.7866263,12.15500000000003,2.79103,5.93186,16.2,957.4,2.24162,-1.93178,175.373
2016-02-12 08:41:40,40.3489442,115.7866283,12.194000000000017,2.98124,7.96713,16.2,957.4,2.23972,-1.38345,175.634
2016-02-12 08:41:41,40.3489261,115.7866302,12.290999999999997,2.76977,6.80938,16.2,957.4,2.23927,-1.48399,175.852
2016-02-12 08:41:42,40.348908,115.7866319,12.145000000000039,2.88923,11.1758,16.2,957.4,2.24577,-1.11357,175.647
2016-02-12 08:41:43,40.34889,115.7866334,12.115000000000009,2.73138,15.2008,16.2,957.4,2.2535,-1.25101,178.042
2016-02-12 08:41:44,40.3488722,115.7866338,12.066000000000031,2.96751,22.2279,16.2,957.4,2.24615,-1.35349,-178.621
2016-02-12 08:41:45,40.3488544,115.7866327,12.17100000000005,3.10965,27.6051,16.2,957.4,2.25523,-1.46058,-175.496
2016-02-12 08:41:46,40.3488367,115.7866304,12.064000000000021,2.92633,28.5539,16.2,957.4,2.24891,-1.73632,-173.742
2016-02-12 08:41:47,40.3488192,115.7866273,12.215000000000032,2.91376,27.4537,16.2,957.4,2.25825,-2.3877,-171.862
2016-02-12 08:41:48,40.3488017,115.7866234,12.088999999999999,3.08075,27.0256,16.2,957.4,2.24402,-1.70543,-170.067
2016-02-12 08:41:49,40.3487842,115.7866186,12.199000000000012,3.22416,29.298,16.3,957.4,2.26024,-1.40647,-166.772
2016-02-12 08:41:50,40.3487669,115.7866126,12.105999999999995,3.04744,30.399,16.3,957.4,2.26284,-1.90689,-163.401
2016-02-12 08:41:51,40.34875,115.7866053,12.230999999999995,3.03816,32.1537,16.3,957.4,2.25274,-2.12911,-160.487
2016-02-12 08:41:52,40.3487332,115.7865977,12.277000000000044,3.16828,36.9141,16.3,957.4,2.24902,-2.42806,-158.691
2016-02-12 08:41:53,40.3487164,115.7865891,12.119000000000028,3.51183,36.1496,16.3,957.4,2.25103,-2.7569,-159.977
2016-02-12 08:41:54,40.3486995,115.7865807,12.200000000000045,3.67923,34.0202,16.3,957.4,2.25266,-2.03718,-159.794
2016-02-12 08:41:55,40.3486826,115.7865724,12.234000000000037,3.99466,32.2461,16.3,957.4,2.25307,-2.50656,-159.647
2016-02-12 08:41:56,40.3486656,115.7865644,12.124000000000024,3.87245,32.552,16.3,957.4,2.25371,-2.16503,-159.25
2016-02-12 08:41:57,40.3486488,115.7865561,12.090000000000032,4.08144,33.5234,16.3,957.4,2.24347,-2.05622,-159.351
2016-02-12 08:41:58,40.3486319,115.7865478,12.209000000000003,3.86491,36.1923,16.3,957.4,2.24522,-1.63832,-159.568
2016-02-12 08:41:59,40.348615,115.7865392,12.052000000000021,3.72907,37.497,16.3,957.4,2.24749,-1.51081,-158.014
2016-02-12 08:42:00,40.3485989,115.7865303,12.175000000000011,3.44141,42.7996,16.3,957.4,2.24907,-1.9916,-152.302
2016-02-12 08:42:01,40.3485838,115.7865188,12.503000000000043,3.81648,51.5505,16.3,957.4,2.24449,-2.30392,-145.352
2016-02-12 08:42:02,40.3485697,115.7865051,12.378000000000043,4.09751,56.1889,16.3,957.4,2.24475,-3.35498,-140.287
2016-02-12 08:42:03,40.348554,115.7864864,12.354000000000042,4.45431,63.4819,16.3,957.4,2.25055,-2.78677,-133.264
2016-02-12 08:42:04,40.3485421,115.7864686,12.239000000000033,4.57333,67.1847,16.3,957.4,2.25146,-2.48321,-128.375
2016-02-12 08:42:05,40.3485336,115.7864536,12.379999999999995,4.48019,71.2003,16.3,957.4,2.24778,-2.34836,-123.58
2016-02-12 08:42:06,40.348523,115.7864295,12.398000000000025,4.48081,77.9232,16.3,957.4,2.24845,-2.83183,-116.547
2016-02-12 08:42:07,40.3485159,115.7864082,12.41500000000002,4.49352,80.9574,16.3,957.4,2.25643,-2.8192,-110.823
2016-02-12 08:42:08,40.3485099,115.7863862,12.507000000000005,4.71163,79.3181,16.3,957.4,2.25778,-3.08629,-109.918
2016-02-12 08:42:09,40.348504,115.7863639,12.674000000000035,4.83949,77.9107,16.3,957.4,2.24253,-2.90956,-109.746
2016-02-12 08:42:10,40.348498,115.7863416,12.966000000000008,5.05952,75.906,16.3,957.4,2.24613,-2.97764,-110.009
2016-02-12 08:42:11,40.3484919,115.7863189,12.289000000000044,4.99548,74.3886,16.3,957.4,2.24257,-2.69509,-109.879
2016-02-12 08:42:12,40.3484856,115.7862963,12.305000000000007,4.86027,75.585,16.3,957.4,2.24794,-2.39785,-109.656
2016-02-12 08:42:13,40.3484795,115.786274,12.30600000000004,4.63504,75.6022,16.3,957.4,2.25423,-2.3631,-109.497
2016-02-12 08:42:14,40.3484733,115.7862519,12.319000000000017,4.62832,77.8567,16.3,957.4,2.24955,-2.26553,-109.463
2016-02-12 08:42:15,40.3484674,115.7862297,12.467000000000041,4.51333,78.3431,16.3,957.4,2.24946,-2.37776,-110.25
2016-02-12 08:42:16,40.3484612,115.7862076,12.367000000000019,4.41789,79.0752,16.3,957.4,2.25625,-2.54596,-110.091
2016-02-12 08:42:17,40.3484548,115.7861855,12.536000000000001,4.47514,81.1023,16.3,957.4,2.24774,-2.51819,-109.937
2016-02-12 08:42:18,40.3484486,115.7861638,12.861000000000047,4.55631,82.4619,16.3,957.4,2.24383,-2.94212,-109.487
2016-02-12 08:42:19,40.3484429,115.7861421,12.637,4.85356,87.9828,16.3,957.4,2.25176,-3.28014,-106.279
2016-02-12 08:42:20,40.3484385,115.78612,12.87700000000001,5.05794,92.5173,16.3,957.4,2.25419,-3.86801,-101.332
2016-02-12 08:42:21,40.3484355,115.7860973,12.540999999999997,5.22229,96.0485,16.3,957.4,2.26133,-3.48247,-96.9957
2016-02-12 08:42:22,40.3484339,115.786074,12.859000000000037,5.29359,99.1907,16.3,957.4,2.25554,-3.74325,-93.293
2016-02-12 08:42:23,40.3484335,115.7860508,12.79400000000004,5.51611,102.248,16.3,957.4,2.25186,-3.60425,-89.6605
2016-02-12 08:42:24,40.3484341,115.7860275,12.837000000000046,5.91545,104.712,16.3,957.4,2.26173,-4.32424,-86.4569
2016-02-12 08:42:25,40.3484362,115.7860043,12.738,5.97849,108.205,16.3,957.4,2.25334,-4.14827,-81.8178
2016-02-12 08:42:26,40.3484397,115.7859813,12.995000000000005,5.95724,109.774,16.3,957.4,2.26212,-3.98325,-77.084
2016-02-12 08:42:27,40.3484442,115.7859587,13.02600000000001,5.88203,112.074,16.3,957.4,2.26216,-3.93422,-73.0804
2016-02-12 08:42:28,40.3484496,115.7859361,12.66700000000003,5.89762,112.488,16.3,957.4,2.25082,-3.98341,-72.3455
2016-02-12 08:42:29,40.3484555,115.7859136,13.284000000000049,5.88128,111.104,16.3,957.4,2.25202,-4.08997,-73.1645
2016-02-12 08:42:30,40.3484603,115.7858911,13.001000000000033,5.88179,112.502,16.3,957.4,2.25494,-4.32926,-72.1189
2016-02-12 08:42:31,40.3484659,115.785869,12.974000000000046,5.89474,113.961,16.3,957.4,2.2582,-4.21522,-72.1881
2016-02-12 08:42:32,40.3484716,115.7858467,13.950000000000045,5.89713,112.242,16.3,957.4,2.25086,-4.48302,-72.4782
2016-02-12 08:42:33,40.348477,115.785824,12.950000000000045,5.83897,111.227,16.3,957.4,2.25219,-3.79417,-72.9491
2016-02-12 08:42:34,40.3484819,115.7858011,13.550000000000011,5.70104,110.514,16.3,957.4,2.25342,-4.27485,-72.8564
2016-02-12 08:42:35,40.3484869,115.7857784,13.302999999999997,5.65056,112.288,16.2,957.4,2.25351,-4.61801,-72.341
2016-02-12 08:42:36,40.3484922,115.7857551,12.936000000000035,5.64385,114.009,16.2,957.4,2.25632,-3.38854,-72.9091
2016-02-12 08:42:37,40.348498,115.7857323,12.79000000000002,5.63199,115.023,16.2,957.4,2.25322,-3.08252,-71.8235
2016-02-12 08:42:38,40.3485042,115.7857104,12.858000000000004,5.36999,121.775,16.2,957.4,2.25358,-3.24984,-65.9687
2016-02-12 08:42:39,40.3485119,115.78569,12.900000000000034,5.15898,126.711,16.2,957.4,2.26002,-3.20228,-60.2979
2016-02-12 08:42:40,40.348521,115.7856707,13.067000000000007,5.14989,132.227,16.2,957.4,2.25982,-3.62738,-54.9838
2016-02-12 08:42:41,40.3485316,115.7856526,13.647000000000048,5.22281,136.78,16.2,957.4,2.26323,-4.14084,-49.9837
2016-02-12 08:42:42,40.3485433,115.7856361,13.871000000000038,5.67075,139.828,16.2,957.4,2.25176,-4.97773,-45.5356
2016-02-12 08:42:43,40.3485561,115.7856201,12.992000000000019,5.82711,142.777,16.2,957.4,2.26061,-4.46511,-40.6979
2016-02-12 08:42:44,40.3485702,115.7856055,12.66700000000003,5.82758,147.255,16.2,957.4,2.26035,-3.8026,-34.6946
2016-02-12 08:42:45,40.3485853,115.785593,12.718999999999994,5.62707,149.964,16.2,957.4,2.24634,-4.16698,-28.7379
2016-02-12 08:42:46,40.3486012,115.7855819,12.712000000000046,5.40462,152.98,16.2,957.4,2.25537,-3.65881,-25.8209
2016-02-12 08:42:47,40.3486175,115.7855715,12.614000000000033,5.40776,154.124,16.2,957.4,2.24852,-3.58218,-25.511
2016-02-12 08:42:48,40.348634,115.7855611,12.459000000000003,5.20386,155.024,16.2,957.4,2.25714,-3.00576,-25.8377
2016-02-12 08:42:49,40.3486501,115.7855508,12.467000000000041,5.17858,156.915,16.2,957.4,2.26037,-3.62848,-25.7774
2016-02-12 08:42:50,40.3486696,115.7855384,12.532000000000039,5.27778,157.696,16.2,957.4,2.25554,-3.50805,-25.7918
2016-02-12 08:42:51,40.3486825,115.7855303,12.616000000000042,5.37135,158.794,16.2,957.4,2.25686,-3.56731,-25.5099
2016-02-12 08:42:52,40.3487016,115.7855185,12.533000000000015,5.46752,156.941,16.2,957.4,2.25935,-3.98915,-25.6481
2016-02-12 08:42:53,40.3487176,115.7855085,12.420000000000016,5.58741,155.836,16.2,957.4,2.26681,-4.31272,-25.4288
2016-02-12 08:42:54,40.3487336,115.7854986,12.732000000000028,5.78335,155.823,16.2,957.4,2.25226,-4.67656,-25.4368
2016-02-12 08:42:55,40.3487496,115.785489,12.701999999999998,5.92013,158.796,16.1,957.4,2.25212,-4.80537,-23.1046
2016-02-12 08:42:56,40.348766,115.78548,12.518000000000029,5.9415,162.588,16.1,957.4,2.24934,-4.43397,-19.1058
2016-02-12 08:42:57,40.348783,115.7854727,12.524000000000001,5.72876,166.81,16.1,957.4,2.25649,-4.15858,-15.3635
2016-02-12 08:42:58,40.3488007,115.7854667,12.446000000000026,5.43129,168.769,16.1,957.4,2.25655,-3.56822,-12.2917
2016-02-12 08:42:59,40.3488186,115.7854623,12.591000000000008,5.38271,169.969,16.1,957.4,2.25312,-3.63613,-9.66924
2016-02-12 08:43:00,40.3488359,115.7854588,12.819000000000017,5.39655,172.218,16.1,957.4,2.25178,-4.54191,-6.79331
2016-02-12 08:43:01,40.3488535,115.7854562,12.608000000000004,5.58193,174.925,16.1,957.4,2.25727,-4.15431,-3.67836
2016-02-12 08:43:02,40.3488709,115.7854557,12.687000000000012,5.78932,176.998,16.1,957.4,2.24647,-4.26279,0.864772
2016-02-12 08:43:03,40.3488887,115.7854572,12.700000000000045,5.80957,176.641,16.1,957.4,2.24594,-4.19075,4.37661
2016-02-12 08:43:04,40.3489065,115.7854597,12.713999999999999,5.79471,176.923,16.1,957.4,2.25494,-4.33135,5.51263
2016-02-12 08:43:05,40.3489243,115.7854622,12.805000000000007,5.76599,174.367,16.1,957.4,2.25948,-4.54469,5.39902
2016-02-12 08:43:06,40.3489424,115.7854643,12.515000000000043,5.66438,170.978,16.1,957.4,2.24338,-3.95422,5.18129
2016-02-12 08:43:07,40.3489605,115.7854662,12.734000000000037,5.51594,168.338,16.1,957.4,2.25627,-3.94131,5.09212
2016-02-12 08:43:08,40.3489785,115.7854682,12.634000000000015,5.26331,167.49,16.0,957.4,2.25091,-3.82072,5.21668
2016-02-12 08:43:09,40.3489964,115.7854699,11.968000000000018,5.3484,169.105,16.0,957.6,2.253,-3.64647,5.05816
2016-02-12 08:43:10,40.3490145,115.7854713,12.449000000000012,5.24774,170.138,16.0,957.4,2.25451,-3.90744,4.97669
2016-02-12 08:43:11,40.3490323,115.7854731,12.962000000000046,5.00866,172.165,16.0,957.4,2.25349,-4.42495,5.03938
2016-02-12 08:43:12,40.3490499,115.7854749,12.913000000000011,5.17607,173.761,16.0,957.4,2.25456,-3.96802,4.88758
2016-02-12 08:43:13,40.3490678,115.7854774,12.772000000000048,5.17531,173.632,16.0,957.4,2.24864,-4.1331,5.31392
2016-02-12 08:43:14,40.3490859,115.7854799,12.660000000000025,5.33766,172.301,16.0,957.4,2.24415,-3.63245,5.13994
2016-02-12 08:43:15,40.3491037,115.7854819,12.688000000000045,5.06418,172.85,16.0,957.4,2.25334,3.77341,5.43588
2016-02-12 08:43:16,40.3491139,115.7854834,12.534000000000049,3.21808,163.848,16.0,957.4,2.25053,-3.0238,4.27478
2016-02-12 08:43:17,40.3491151,115.7854831,12.472000000000037,2.30783,161.518,16.0,957.4,2.25659,-2.5161,4.4831
2016-02-12 08:43:18,40.3491145,115.7854826,12.115000000000009,1.10665,156.651,16.0,957.4,2.25019,-3.33712,3.89
2016-02-12 08:43:19,40.3491143,115.7854821,12.076000000000022,0.729867,160.824,16.0,957.4,2.25651,-2.90574,4.24684
2016-02-12 08:43:20,40.3491143,115.785482,12.163000000000011,0.916749,168.514,16.0,957.4,2.24599,-2.40328,5.06117
2016-02-12 08:43:21,40.3491144,115.7854825,12.129999999999995,0.736194,174.551,16.0,957.4,2.24683,-2.259,4.69336
2016-02-12 08:43:22,40.3491147,115.7854827,12.256000000000029,0.721629,173.06,16.0,957.4,2.24472,-2.30074,3.95699
2016-02-12 08:43:23,40.3491147,115.7854826,12.312000000000012,1.02892,170.476,16.0,957.4,2.25346,-2.14544,4.63103
2016-02-12 08:43:24,40.3491148,115.7854826,12.391999999999996,1.71353,162.162,16.0,957.4,2.24199,-2.70262,4.38941
2016-02-12 08:43:25,40.349115,115.7854826,12.213999999999999,1.90056,157.922,15.9,957.4,2.25142,-2.56983,4.16209
2016-02-12 08:43:26,40.3491151,115.785483,12.249000000000024,1.89172,162.111,15.9,957.4,2.24987,-2.37081,4.33851
2016-02-12 08:43:27,40.3491153,115.7854835,12.331000000000017,2.02974,161.345,15.9,957.4,2.25097,-2.36842,4.13939
2016-02-12 08:43:28,40.3491156,115.7854835,12.210000000000036,2.11439,163.381,15.9,957.4,2.24901,-2.72557,4.44417
2016-02-12 08:43:29,40.3491158,115.7854836,12.192000000000007,1.61638,157.271,15.9,957.4,2.2473,-2.35678,4.22427
2016-02-12 08:43:30,40.3491159,115.7854837,12.297000000000025,1.69106,156.577,15.9,957.4,2.24907,-2.72985,4.52237
2016-02-12 08:43:31,40.3491159,115.785484,12.105999999999995,1.27958,154.251,16.0,957.4,2.24912,-2.4493,4.27238
2016-02-12 08:43:32,40.3491158,115.7854842,12.254000000000019,1.37727,157.977,16.0,957.4,2.25123,-3.27265,4.57478
2016-02-12 08:43:33,40.3491159,115.7854845,12.354000000000042,1.21603,157.19,16.0,957.4,2.25817,-3.16157,4.23416
2016-02-12 08:43:34,40.3491161,115.7854845,12.486000000000047,1.52134,161.142,16.0,957.4,2.24876,-2.97854,4.09014
2016-02-12 08:43:35,40.3491163,115.7854843,12.413000000000011,1.62379,159.631,16.0,957.4,2.24613,-2.711,4.14956
2016-02-12 08:43:36,40.3491166,115.7854841,12.363,1.91354,161.307,16.0,957.4,2.24829,-2.66831,4.3683
2016-02-12 08:43:37,40.3491167,115.7854843,12.518000000000029,2.54485,128.325,16.0,957.4,2.24011,-2.99271,4.54588
2016-02-12 08:43:38,40.3491171,115.7854846,13.846000000000004,3.16679,122.058,16.0,957.4,2.24456,-2.10601,4.30452
2016-02-12 08:43:39,40.3491173,115.7854846,16.337000000000046,1.4036,139.974,16.0,957.4,2.25051,-2.11919,4.49659
2016-02-12 08:43:40,40.3491161,115.7854819,17.247000000000014,0.665258,149.372,16.0,957.4,2.25517,-2.29389,44.7974
2016-02-12 08:43:41,40.3491153,115.7854797,17.309000000000026,0.15585,172.788,16.0,957.4,2.25108,-6.16028,50.6785
2016-02-12 08:43:42,40.3491182,115.7854836,17.16300000000001,1.79734,144.454,16.0,957.4,2.24024,-9.94753,51.2855
2016-02-12 08:43:43,40.3491268,115.7854975,17.49200000000002,2.21825,152.062,16.0,957.4,2.26809,1.95625,50.9678
2016-02-12 08:43:44,40.3491325,115.7855068,17.25600000000003,2.33955,175.315,16.0,957.4,2.26068,1.88367,47.4681
2016-02-12 08:43:45,40.3491338,115.7855087,17.298000000000002,2.15619,172.161,16.0,957.4,2.23978,-10.4233,47.4627
2016-02-12 08:43:46,40.3491408,115.7855185,17.400000000000034,3.19316,157.115,16.0,957.4,2.24856,-5.19856,47.9142
2016-02-12 08:43:47,40.349153,115.7855364,18.277000000000044,3.51508,159.235,16.0,957.4,2.25081,-4.18958,47.1094
2016-02-12 08:43:48,40.349166,115.7855553,18.075000000000045,4.85972,155.95,16.0,957.4,2.2575,-3.81284,46.5688
2016-02-12 08:43:49,40.349179,115.7855737,18.112000000000023,5.30648,153.064,16.0,957.4,2.25406,-4.46158,47.5726
2016-02-12 08:43:50,40.3491919,115.7855918,18.206000000000017,5.51106,149.706,16.0,957.4,2.25075,-3.58214,47.8376
2016-02-12 08:43:51,40.3492042,115.7856099,18.246000000000038,5.69668,149.791,16.0,957.4,2.25386,-4.1528,47.7509
2016-02-12 08:43:52,40.3492167,115.7856276,17.972000000000037,5.65832,151.933,16.0,957.4,2.25417,-3.96174,47.7473
2016-02-12 08:43:53,40.349229,115.7856451,17.373000000000047,5.52845,152.475,16.0,957.4,2.25498,-3.35287,47.6634
2016-02-12 08:43:54,40.3492411,115.7856621,17.248000000000047,5.19567,150.868,16.0,957.4,2.25428,-3.57325,50.2049
2016-02-12 08:43:55,40.3492522,115.7856796,17.732000000000028,4.85903,145.241,16.0,957.4,2.25249,-4.60038,54.3005
2016-02-12 08:43:56,40.3492618,115.7856982,17.80200000000002,4.89722,141.182,16.0,957.4,2.25698,-4.268,57.7334
2016-02-12 08:43:57,40.3492709,115.7857178,17.648000000000025,5.00458,138.678,16.0,957.4,2.25503,-4.03971,60.8126
2016-02-12 08:43:58,40.3492792,115.7857383,17.670000000000016,5.06119,134.395,16.0,957.4,2.25882,-4.43467,64.1499
2016-02-12 08:43:59,40.3492867,115.7857602,17.617999999999995,4.97336,132.843,16.0,957.4,2.25522,-3.4857,67.6561
2016-02-12 08:44:00,40.3492929,115.7857822,17.749000000000024,4.76678,129.392,16.0,957.4,2.25682,-3.13844,72.5023
2016-02-12 08:44:01,40.3492981,115.7858047,17.458000000000027,4.70141,129.949,16.0,957.4,2.25787,-3.00207,73.9701
2016-02-12 08:44:02,40.3493031,115.7858268,17.75600000000003,4.64818,127.629,16.0,957.4,2.25249,-4.01299,74.3217
2016-02-12 08:44:03,40.3493081,115.7858497,17.591000000000008,4.78015,127.062,16.0,957.4,2.26045,-3.45797,73.9458
2016-02-12 08:44:04,40.349313,115.7858725,17.576000000000022,4.80095,126.743,16.0,957.4,2.25445,-3.48772,74.0784
2016-02-12 08:44:05,40.3493179,115.7858957,17.460000000000036,4.46846,127.093,16.0,957.4,2.25907,-2.84138,74.6726
2016-02-12 08:44:06,40.3493226,115.7859187,17.524,4.40493,128.632,16.0,957.4,2.2653,-2.7391,74.8234
2016-02-12 08:44:07,40.3493273,115.7859409,17.883000000000038,4.20996,130.254,16.0,957.4,2.25721,-3.75628,74.3471
2016-02-12 08:44:08,40.3493319,115.7859629,18.008000000000038,4.54446,126.276,16.0,957.4,2.24421,-4.13393,75.9746
2016-02-12 08:44:09,40.349336,115.7859856,17.601,4.60809,119.994,16.0,957.4,2.25283,-3.65654,80.2085
2016-02-12 08:44:10,40.3493389,115.7860089,17.54600000000005,4.59821,116.256,16.0,957.4,2.25826,-3.52848,84.5632
2016-02-12 08:44:11,40.3493404,115.7860326,17.343999999999994,4.60662,111.882,16.0,957.4,2.26272,-2.83632,87.8923
2016-02-12 08:44:12,40.3493407,115.786056,17.586000000000013,4.26527,108.906,16.0,957.4,2.26141,-2.64772,91.0007
2016-02-12 08:44:13,40.34934,115.7860794,17.64300000000003,4.15369,106.719,16.0,957.4,2.25931,-2.97149,93.9182
2016-02-12 08:44:14,40.3493383,115.7861028,17.40500000000003,4.06511,102.898,15.9,957.4,2.25609,-2.43398,97.4505
2016-02-12 08:44:15,40.3493351,115.7861305,17.194000000000017,4.10584,100.818,15.9,957.4,2.25337,-2.45874,102.19
2016-02-12 08:44:16,40.3493312,115.7861533,17.29600000000005,3.5283,94.6166,15.9,957.4,2.25653,-2.18443,106.176
2016-02-12 08:44:17,40.349326,115.7861758,17.158000000000015,3.14686,91.3884,15.9,957.4,2.26545,-1.54058,107.424
2016-02-12 08:44:18,40.3493205,115.7861983,17.150000000000034,2.79263,94.4733,15.9,957.4,2.25802,-2.1108,106.841
2016-02-12 08:44:19,40.349315,115.7862206,17.38900000000001,2.88462,94.7514,15.9,957.4,2.25069,-2.22205,107.513
2016-02-12 08:44:20,40.3493094,115.7862432,17.067000000000007,2.76044,95.8841,15.9,957.4,2.2528,-1.19721,107.134
2016-02-12 08:44:21,40.3493041,115.7862659,17.110000000000014,2.41459,96.6922,15.9,957.4,2.26201,-1.52747,106.883
2016-02-12 08:44:22,40.3492987,115.7862882,17.20500000000004,2.22398,91.4351,15.9,957.4,2.25557,-2.13694,106.758
2016-02-12 08:44:23,40.3492936,115.7863106,17.402000000000044,2.22706,93.5224,15.9,957.4,2.25374,-2.07331,107.193
2016-02-12 08:44:24,40.3492882,115.786333,17.234000000000037,2.23447,93.8195,16.0,957.4,2.25663,-1.73543,107.136
2016-02-12 08:44:25,40.3492828,115.7863553,17.341000000000008,2.369,89.0479,16.0,957.4,2.25711,-2.02998,109.231
2016-02-12 08:44:26,40.3492764,115.786377,17.462000000000046,2.58026,83.2347,16.0,957.4,2.26416,-1.803,114.054
2016-02-12 08:44:27,40.3492688,115.7863981,17.28200000000004,2.71047,83.2986,16.0,957.4,2.25945,-2.07605,117.681
2016-02-12 08:44:28,40.3492603,115.7864185,17.536,2.62323,77.0265,16.0,957.4,2.25908,-1.97262,120.92
2016-02-12 08:44:29,40.3492507,115.786438,17.591000000000008,2.65832,73.4184,16.0,957.4,2.25308,-1.5131,124.759
2016-02-12 08:44:30,40.3492401,115.7864565,17.560000000000002,2.7659,69.8955,16.0,957.4,2.26277,-2.36132,129.088
2016-02-12 08:44:31,40.3492287,115.7864741,17.32800000000003,2.67548,62.8153,16.0,957.4,2.25068,-2.22984,133.597
2016-02-12 08:44:32,40.3492162,115.7864915,17.398000000000025,2.61916,62.5652,16.0,957.4,2.2546,-1.56645,134.004
2016-02-12 08:44:33,40.3492038,115.7865082,17.36500000000001,2.38325,63.9515,16.0,957.4,2.25572,-2.22344,134.419
2016-02-12 08:44:34,40.3491913,115.7865247,17.396000000000015,2.4148,60.3102,16.0,957.4,2.26123,-1.89722,134.63
2016-02-12 08:44:35,40.3491787,115.7865415,17.450000000000045,2.71965,65.9189,16.0,957.4,2.24881,-1.83215,134.581
2016-02-12 08:44:36,40.3491659,115.7865581,17.43300000000005,2.8837,66.0174,16.0,957.4,2.26288,-1.92149,136.984
2016-02-12 08:44:37,40.3491527,115.7865736,17.39300000000003,2.99332,47.2055,16.0,957.4,2.25737,-1.88269,144.475
2016-02-12 08:44:39,40.3491381,115.7865865,17.437000000000012,2.60973,38.2454,16.0,957.4,2.26084,-1.88556,150.27
2016-02-12 08:44:39,40.3491223,115.7865974,17.41500000000002,2.0888,24.9333,16.0,957.4,2.26337,-1.17669,155.997
2016-02-12 08:44:40,40.3491058,115.7866061,17.382000000000005,2.04768,20.821,16.0,957.4,2.26543,-0.978078,161.237
2016-02-12 08:44:42,40.3490888,115.7866126,17.50400000000002,2.02731,13.2953,16.0,957.4,2.25556,-1.22699,167.844
2016-02-12 08:44:43,40.3490714,115.7866164,17.65500000000003,1.96942,5.29049,16.0,957.4,2.25431,-0.927087,174.693
2016-02-12 08:44:44,40.3490538,115.7866182,17.715000000000032,1.96387,3.9822,16.0,957.4,2.25309,-1.37721,176.111
2016-02-12 08:44:45,40.349036,115.7866197,17.62900000000002,1.97297,4.3481,16.0,957.4,2.26046,-1.17786,176.094
2016-02-12 08:44:46,40.3490182,115.7866212,17.64500000000004,1.97891,4.29482,16.0,957.4,2.25826,-1.22428,175.974
2016-02-12 08:44:47,40.3490003,115.7866228,17.56400000000002,1.92987,5.27529,16.0,957.4,2.25967,-1.38526,175.432
2016-02-12 08:44:48,40.3489822,115.7866244,17.507000000000005,2.11482,2.04059,16.1,957.4,2.25986,-1.25446,175.941
2016-02-12 08:44:49,40.348964,115.786626,17.494000000000028,2.2084,4.66539,16.1,957.4,2.25505,-1.25606,175.786
2016-02-12 08:44:50,40.3489461,115.7866279,17.533000000000015,1.98396,12.7157,16.1,957.4,2.25133,-1.10287,176.088
2016-02-12 08:44:51,40.3489282,115.7866296,17.510000000000048,2.00829,16.0908,16.1,957.4,2.26272,-1.05535,176.051
2016-02-12 08:44:52,40.3489102,115.7866312,17.38900000000001,2.00029,6.62347,16.1,957.4,2.26306,-1.15381,175.658
2016-02-12 08:44:53,40.3488923,115.7866329,17.53200000000004,2.00055,5.94855,16.1,957.4,2.26199,-1.15091,177.283
2016-02-12 08:44:54,40.3488743,115.7866336,17.375,1.84412,12.2126,16.1,957.4,2.25823,-0.905536,-179.37
2016-02-12 08:44:55,40.3488565,115.7866328,17.537000000000035,1.81085,14.9492,16.1,957.4,2.25636,-0.861661,-176.408
2016-02-12 08:44:56,40.3488387,115.7866309,17.624000000000024,1.84405,14.0908,16.1,957.4,2.25948,-1.10296,-174.525
2016-02-12 08:44:57,40.348821,115.7866281,17.559000000000026,1.93804,11.6952,16.1,957.4,2.26045,-0.947733,-172.353
2016-02-12 08:44:58,40.3488035,115.7866242,17.694000000000017,2.00184,14.1004,16.1,957.4,2.25602,-1.26374,-169.775
2016-02-12 08:44:59,40.348786,115.7866195,17.708000000000027,2.03629,21.9379,16.1,957.4,2.2498,-1.05616,-166.958
2016-02-12 08:45:00,40.3487688,115.7866138,17.646000000000015,2.05078,24.9459,16.1,957.4,2.25291,-1.05454,-163.484
2016-02-12 08:45:01,40.3487517,115.7866069,17.65900000000005,1.95402,30.7938,16.2,957.4,2.26536,-0.651226,-160.678
2016-02-12 08:45:02,40.3487347,115.786599,17.588000000000022,1.7691,34.7243,16.2,957.4,2.24918,-0.857132,-159.513
2016-02-12 08:45:03,40.348718,115.7865908,17.598000000000013,1.67192,47.1372,16.2,957.4,2.26345,-1.21446,-159.669
2016-02-12 08:45:04,40.3487011,115.7865824,17.69500000000005,1.68668,54.3084,16.2,957.4,2.25893,-0.823606,-159.862
2016-02-12 08:45:05,40.3486843,115.7865742,17.79200000000003,1.74508,47.7868,16.2,957.4,2.25838,-0.884091,-159.588
2016-02-12 08:45:06,40.3486642,115.7865643,17.739000000000033,1.86477,34.9555,16.2,957.4,2.25685,-1.2888,-159.629
2016-02-12 08:45:07,40.3486473,115.7865559,17.80200000000002,1.9374,38.5253,16.2,957.4,2.26043,-0.978609,-159.995
2016-02-12 08:45:08,40.3486305,115.7865474,17.758000000000038,1.92136,38.8821,16.2,957.4,2.26082,-0.655105,-160.113
2016-02-12 08:45:09,40.3486139,115.7865389,17.77000000000004,1.86096,61.4759,16.2,957.4,2.26501,-0.96432,-157.731
2016-02-12 08:45:10,40.3485975,115.7865297,17.74000000000001,1.84646,65.4398,16.2,957.4,2.26133,-0.770468,-151.285
2016-02-12 08:45:11,40.3485824,115.7865178,17.840000000000032,1.77807,66.8571,16.3,957.4,2.25876,-0.859863,-144.656
2016-02-12 08:45:12,40.3485682,115.7865036,17.966000000000008,1.88744,61.4756,16.3,957.4,2.26721,-0.782214,-139.476
2016-02-12 08:45:13,40.3485553,115.7864884,17.864000000000033,2.1576,77.0466,16.3,957.4,2.26486,-1.47746,-133.976
2016-02-12 08:45:14,40.3485435,115.7864713,18.11700000000002,2.70015,81.7995,16.3,957.4,2.26416,-1.10274,-128.533
2016-02-12 08:45:15,40.3485332,115.786453,18.287000000000035,2.69214,88.1674,16.3,957.4,2.26025,-1.94088,-122.849
2016-02-12 08:45:16,40.3485245,115.7864337,18.45500000000004,3.78728,89.9081,16.3,957.4,2.25168,-3.04325,-117.301
2016-02-12 08:45:17,40.3485173,115.7864131,18.396000000000015,4.16305,89.0334,16.3,957.4,2.25147,-3.31608,-111.595
2016-02-12 08:45:18,40.3485111,115.786391,18.156000000000006,4.32816,88.5418,16.4,957.4,2.25652,-3.47936,-110.1
2016-02-12 08:45:19,40.3485051,115.7863681,18.30000000000001,4.57069,83.1046,16.4,957.4,2.24823,-2.257,-110.004
2016-02-12 08:45:20,40.348499,115.7863454,18.563000000000045,4.63882,82.4551,16.4,957.4,2.25442,-2.3749,-109.707
2016-02-12 08:45:21,40.3484927,115.786323,18.28800000000001,4.55507,82.4027,16.4,957.4,2.26189,-2.34621,-109.863
2016-02-12 08:45:22,40.3484865,115.7863004,18.225000000000023,4.52532,83.4422,16.4,957.4,2.26022,-2.46761,-109.93
2016-02-12 08:45:23,40.3484803,115.7862778,18.161,4.26556,86.1035,16.4,957.4,2.25502,-2.08226,-109.794
2016-02-12 08:45:24,40.3484741,115.7862556,18.208000000000027,4.23751,87.8882,16.4,957.4,2.25048,-2.05877,-109.916
2016-02-12 08:45:25,40.348468,115.7862333,18.089,4.12006,88.2306,16.4,957.4,2.24768,-2.21128,-109.852
2016-02-12 08:45:26,40.3484618,115.7862112,18.319000000000017,3.95742,89.733,16.4,957.4,2.25324,-1.93889,-109.628
2016-02-12 08:45:27,40.3484557,115.7861892,18.310000000000002,3.98109,89.0515,16.4,957.4,2.25249,-2.38076,-109.893
2016-02-12 08:45:28,40.3484497,115.7861672,18.201999999999998,3.97322,90.7361,16.4,957.4,2.25567,-2.45486,-109.649
2016-02-12 08:45:29,40.3484439,115.7861451,18.471000000000004,3.97965,94.0065,16.4,957.4,2.26075,-2.21297,-106.317
2016-02-12 08:45:30,40.3484394,115.7861226,18.227000000000032,3.89264,97.9598,16.4,957.4,2.25305,-2.42729,-101.534
2016-02-12 08:45:31,40.3484363,115.7860996,18.062000000000012,3.88647,103.014,16.4,957.4,2.26572,-2.24522,-97.1811
2016-02-12 08:45:32,40.3484347,115.7860764,18.20500000000004,3.96167,107.487,16.4,957.4,2.25969,-2.48252,-93.2813
2016-02-12 08:45:33,40.3484342,115.7860533,18.545000000000016,4.19445,109.054,16.4,957.4,2.26069,-2.93529,-89.8609
2016-02-12 08:45:34,40.3484348,115.7860307,18.602000000000032,4.59572,106.289,16.4,957.4,2.25846,-3.74323,-87.0064
2016-02-12 08:45:35,40.3484361,115.7860075,18.62700000000001,4.55856,108.097,16.5,957.4,2.25328,-3.77968,-82.5635
2016-02-12 08:45:36,40.3484388,115.7859842,18.871000000000038,4.94187,112.091,16.5,957.4,2.25766,-3.47161,-77.7257
2016-02-12 08:45:37,40.3484431,115.7859614,18.620000000000005,4.99916,114.421,16.5,957.4,2.24696,-4.25361,-73.8859
2016-02-12 08:45:38,40.3484484,115.7859379,18.662000000000035,5.041,118.194,16.5,957.4,2.24988,-2.40826,-72.456
2016-02-12 08:45:39,40.3484539,115.7859151,18.590000000000032,4.86597,121.342,16.5,957.4,2.23913,-2.65323,-72.0437
2016-02-12 08:45:40,40.3484598,115.7858929,18.458000000000027,4.57349,122.896,16.5,957.4,2.24802,-2.92134,-72.8244
2016-02-12 08:45:41,40.3484654,115.7858701,18.50400000000002,4.62556,125.251,16.5,957.4,2.25008,-2.46242,-72.5329
2016-02-12 08:45:42,40.3484709,115.7858478,18.313000000000045,4.34028,123.989,16.5,957.4,2.2451,-3.08264,-72.7796
2016-02-12 08:45:43,40.3484763,115.7858252,17.950000000000045,4.58716,121.914,16.5,957.4,2.24825,-2.61072,-72.9401
2016-02-12 08:45:44,40.3484817,115.7858026,17.908000000000015,4.45187,123.576,16.5,957.4,2.2571,-2.53661,-72.1734
2016-02-12 08:45:45,40.3484873,115.7857801,18.42700000000002,4.56513,122.201,16.5,957.4,2.24877,-2.19526,-72.9211
2016-02-12 08:45:46,40.3484926,115.7857577,18.236000000000047,4.27496,122.441,16.5,957.4,2.25316,-2.56898,-72.6472
2016-02-12 08:45:47,40.3484981,115.7857353,18.04000000000002,4.05575,123.342,16.5,957.4,2.24489,-2.28949,-71.977
2016-02-12 08:45:48,40.3485039,115.7857134,18.49200000000002,4.03684,127.936,16.5,957.4,2.25751,-2.46188,-67.2151
2016-02-12 08:45:49,40.348511,115.785693,18.735000000000014,4.11837,133.691,16.5,957.4,2.25974,-3.48746,-61.2099
2016-02-12 08:45:50,40.3485197,115.7856737,18.715000000000032,4.69469,136.928,16.5,957.4,2.24865,-3.85436,-55.4787
2016-02-12 08:45:51,40.3485302,115.785655,18.584000000000003,4.95181,138.959,16.5,957.4,2.25789,-3.25282,-50.9018
2016-02-12 08:45:52,40.3485445,115.7856342,19.019000000000005,5.16532,142.967,16.5,957.4,2.25162,-3.51994,-44.9958
2016-02-12 08:45:53,40.3485551,115.7856217,18.930000000000007,5.17427,145.326,16.5,957.4,2.25415,-3.20807,-40.945
2016-02-12 08:45:54,40.3485718,115.7856049,19.383000000000038,5.22752,149.735,16.5,957.4,2.23934,-4.49393,-34.1759
2016-02-12 08:45:55,40.3485865,115.7855928,19.444000000000017,5.46417,153.647,16.5,957.4,2.24285,-3.81437,-28.297
2016-02-12 08:45:56,40.3486022,115.7855819,19.15900000000005,5.61763,151.635,16.5,957.4,2.24025,-3.88984,-25.5592
2016-02-12 08:45:57,40.3486185,115.7855714,19.13100000000003,5.22492,151.447,16.5,957.4,2.24517,-4.60596,-25.7129
2016-02-12 08:45:58,40.348635,115.7855608,18.66500000000002,5.22477,152.331,16.5,957.4,2.25713,-3.54813,-26.0158
2016-02-12 08:45:59,40.3486512,115.78555,18.549000000000035,5.00249,156.044,16.5,957.4,2.2507,-3.84303,-26.0043
2016-02-12 08:46:00,40.3486673,115.7855394,18.598000000000013,4.90608,159.322,16.5,957.4,2.24678,-3.58029,-25.9375
2016-02-12 08:46:01,40.3486837,115.7855294,18.55400000000003,4.89749,161.021,16.5,957.4,2.24366,-3.33764,-25.6277
2016-02-12 08:46:02,40.3486999,115.7855194,18.826999999999998,4.74312,160.992,16.5,957.4,2.24832,-3.63823,-25.437
2016-02-12 08:46:03,40.3487159,115.7855095,18.734000000000037,5.08126,160.834,16.5,957.4,2.24889,-3.83332,-25.7044
2016-02-12 08:46:04,40.348732,115.7854993,18.697000000000003,5.29667,161.546,16.5,957.4,2.24539,-3.81592,-25.3915
2016-02-12 08:46:05,40.3487486,115.7854894,18.629999999999995,5.33145,161.929,16.5,957.4,2.24517,-3.09275,-23.3054
2016-02-12 08:46:06,40.3487655,115.7854806,18.716000000000008,4.78943,163.905,16.5,957.4,2.25106,-2.56043,-19.1261
2016-02-12 08:46:07,40.348782,115.7854734,18.864000000000033,4.65857,165.761,16.5,957.4,2.24854,-3.60127,-15.6055
2016-02-12 08:46:08,40.3487988,115.7854675,19.091000000000008,4.77459,166.962,16.5,957.4,2.24936,-4.10476,-12.4039
2016-02-12 08:46:09,40.3488161,115.785463,19.161,5.17038,169.08,16.5,957.4,2.26161,-3.88614,-10.0499
2016-02-12 08:46:10,40.3488335,115.7854591,19.347000000000037,5.30009,171.894,16.5,957.4,2.25124,-4.02029,-7.24302
2016-02-12 08:46:11,40.3488513,115.7854566,19.013000000000034,5.39223,174.83,16.5,957.4,2.24748,-4.18501,-4.02827
2016-02-12 08:46:12,40.3488692,115.7854554,18.531000000000006,5.22289,177.792,16.5,957.4,2.24002,-3.68792,-0.138169
2016-02-12 08:46:13,40.348887,115.7854559,18.712000000000046,5.29908,176.119,16.5,957.4,2.24991,-4.16261,3.40361
2016-02-12 08:46:14,40.3489049,115.7854579,18.876000000000033,5.18513,175.604,16.5,957.4,2.25581,-3.8008,4.82798
2016-02-12 08:46:15,40.3489226,115.7854601,18.70300000000003,5.28377,174.7,16.5,957.4,2.25573,-4.42704,5.10422
2016-02-12 08:46:16,40.3489402,115.7854625,18.723000000000013,5.07867,173.898,16.5,957.4,2.25527,-4.51496,5.49623
2016-02-12 08:46:17,40.3489577,115.7854654,19.19500000000005,5.09618,175.518,16.5,957.4,2.25583,-4.36611,5.46923
2016-02-12 08:46:18,40.3489756,115.7854678,18.958000000000027,5.11867,176.609,16.4,957.4,2.25081,-4.54822,5.33563
2016-02-12 08:46:19,40.3489936,115.7854701,18.870000000000005,5.4073,176.796,16.4,957.4,2.25643,-4.75882,5.40797
2016-02-12 08:46:20,40.3490114,115.7854722,18.610000000000014,5.58391,175.575,16.4,957.4,2.24946,-5.50701,5.03366
2016-02-12 08:46:21,40.3490293,115.7854738,18.632000000000005,5.9049,176.505,16.4,957.4,2.25577,-4.83407,5.36974
2016-02-12 08:46:22,40.3490473,115.7854761,18.746000000000038,5.91032,176.712,16.4,957.4,2.26172,-4.47638,5.38053
2016-02-12 08:46:23,40.3490654,115.7854787,18.749000000000024,5.8128,175.791,16.4,957.4,2.24897,-4.6601,5.14888
2016-02-12 08:46:24,40.3490833,115.7854808,18.635000000000048,5.96479,174.72,16.4,957.4,2.26363,-5.30749,5.15921
2016-02-12 08:46:25,40.3491012,115.7854828,18.662000000000035,5.69564,172.094,16.4,957.4,2.2571,-0.473702,4.87027
2016-02-12 08:46:26,40.3491131,115.7854838,18.741000000000042,3.78275,164.729,16.4,957.4,2.25241,-0.887125,4.75248
2016-02-12 08:46:27,40.3491144,115.7854838,18.359000000000037,3.20324,161.213,16.4,957.4,2.25493,-3.26957,5.54402
2016-02-12 08:46:28,40.3491142,115.7854837,18.223000000000013,2.40983,155.756,16.3,957.4,2.25721,-3.09028,5.36807
2016-02-12 08:46:29,40.3491141,115.7854836,18.116000000000042,2.11352,157.024,16.3,957.4,2.25414,-2.34086,5.54559
2016-02-12 08:46:30,40.349114,115.7854839,18.098000000000013,1.80536,155.986,16.3,957.4,2.24952,-2.62845,5.28901
2016-02-12 08:46:31,40.3491139,115.7854841,18.104000000000042,1.53764,153.71,16.3,957.4,2.25496,-2.72331,4.91931
2016-02-12 08:46:32,40.3491141,115.785484,18.013000000000034,1.25194,135.14,16.3,957.4,2.25252,-2.51398,5.07391
2016-02-12 08:46:33,40.3491145,115.7854839,18.096000000000004,0.909581,119.528,16.3,957.4,2.26502,-2.23522,4.9321
2016-02-12 08:46:34,40.3491148,115.7854839,18.11500000000001,1.00363,116.368,16.3,957.4,2.25633,-1.86102,4.94461
2016-02-12 08:46:35,40.3491147,115.7854839,18.156000000000006,1.29567,116.279,16.3,957.4,2.24816,-3.27238,4.93432
2016-02-12 08:46:36,40.3491148,115.7854839,18.29200000000003,1.80343,117.547,16.3,957.4,2.25323,-3.03301,5.0516
2016-02-12 08:46:37,40.3491153,115.7854844,18.262,2.20721,129.988,16.3,957.4,2.23802,-2.33693,-3.56446
2016-02-12 08:46:38,40.349117,115.7854858,18.539000000000044,2.41458,130.441,16.3,957.4,2.25003,-3.03663,-32.2437
2016-02-12 08:46:39,40.3491192,115.7854854,18.525000000000034,2.51248,120.631,16.3,957.4,2.2485,-2.14594,-62.1644
2016-02-12 08:46:40,40.3491202,115.7854843,18.311000000000035,2.39774,119.713,16.3,957.4,2.26122,-1.66167,-82.6586
2016-02-12 08:46:41,40.3491201,115.7854826,18.40100000000001,2.6669,112.549,16.3,957.4,2.24148,-9.69869,-94.4252
2016-02-12 08:46:42,40.349119,115.785474,18.451999999999998,3.58092,114.107,16.3,957.4,2.24515,-8.18198,-94.3401
2016-02-12 08:46:43,40.3491177,115.7854533,18.446000000000026,4.36065,111.498,16.3,957.4,2.24984,-6.39408,-94.1511
2016-02-12 08:46:44,40.3491158,115.7854241,18.548000000000002,4.83268,107.56,16.2,957.4,2.25608,-5.52217,-93.985
2016-02-12 08:46:45,40.3491136,115.7853904,18.562000000000012,5.63733,104.996,16.2,957.4,2.25285,-3.73582,-93.9406
2016-02-12 08:46:46,40.3491117,115.7853556,18.718000000000018,5.98308,99.2656,16.2,957.4,2.25147,-1.55215,-94.2177
2016-02-12 08:46:47,40.3491101,115.7853231,18.66900000000004,5.99918,99.0378,16.2,957.4,2.25063,-1.4597,-93.9427
2016-02-12 08:46:48,40.3491088,115.7852936,18.864000000000033,5.58521,98.8318,16.2,957.4,2.25688,-1.74784,-94.2138
2016-02-12 08:46:49,40.3491076,115.7852665,18.647000000000048,5.06914,102.902,16.2,957.4,2.25241,-1.92998,-93.8656
2016-02-12 08:46:50,40.3491069,115.7852413,18.53800000000001,4.57836,107.973,16.2,957.4,2.25181,-1.92374,-92.0432
2016-02-12 08:46:51,40.3491072,115.785218,18.536,4.43143,115.332,16.2,957.4,2.25353,-2.10617,-85.8288
2016-02-12 08:46:52,40.3491093,115.7851963,18.79000000000002,4.43013,123.816,16.2,957.4,2.25323,-2.65061,-78.6565
2016-02-12 08:46:53,40.3491127,115.7851749,18.78800000000001,4.58193,121.516,16.2,957.4,2.24977,-2.85184,-78.4132
2016-02-12 08:46:54,40.3491161,115.7851532,18.649,4.63984,120.281,16.2,957.4,2.2551,-3.52654,-78.4899
2016-02-12 08:46:55,40.3491197,115.7851304,18.391999999999996,4.82902,119.083,16.2,957.4,2.25016,-3.82069,-78.4761
2016-02-12 08:46:56,40.3491238,115.7851057,18.468999999999994,4.82599,118.463,16.2,957.4,2.25212,-4.37022,-78.4759
2016-02-12 08:46:57,40.3491283,115.7850782,18.476,5.24285,115.506,16.2,957.4,2.2514,-5.29125,-78.4982
2016-02-12 08:46:58,40.3491332,115.7850471,18.605999999999995,5.63871,114.027,16.2,957.4,2.25888,-4.89839,-78.6514
2016-02-12 08:46:59,40.3491386,115.7850129,18.64300000000003,6.21575,110.912,16.2,957.4,2.23991,-4.85329,-78.5702
2016-02-12 08:47:00,40.3491446,115.7849764,18.474000000000046,6.52411,109.303,16.2,957.4,2.25149,-4.43201,-78.5637
2016-02-12 08:47:01,40.349151,115.784938,18.80800000000005,6.77679,107.561,16.2,957.4,2.24558,-4.74183,-78.8267
2016-02-12 08:47:02,40.3491576,115.7848981,18.956999999999994,7.09753,106.696,16.2,957.4,2.25637,-4.52781,-78.8386
2016-02-12 08:47:03,40.3491644,115.7848569,18.587000000000046,7.33927,106.749,16.2,957.4,2.26023,-4.96421,-78.5891
2016-02-12 08:47:04,40.3491715,115.784814,18.772000000000048,7.50092,106.624,16.2,957.4,2.25672,-5.29089,-78.658
2016-02-12 08:47:05,40.3491788,115.7847687,18.714,7.58947,106.181,16.2,957.4,2.24472,-4.61858,-78.6736
2016-02-12 08:47:06,40.3491862,115.7847216,18.861000000000047,7.58499,106.907,16.2,957.4,2.26091,-2.96341,-78.4489
2016-02-12 08:47:07,40.3491932,115.7846768,19.076000000000022,7.63955,107.249,16.1,957.4,2.24757,-2.96918,-78.5038
2016-02-12 08:47:08,40.3492001,115.7846343,18.950000000000045,7.56674,107.19,16.1,957.4,2.25598,-1.65859,-78.5213
2016-02-12 08:47:09,40.3492063,115.7845963,18.875,6.51291,106.081,16.1,957.4,2.25284,0.87737,-78.6438
2016-02-12 08:47:10,40.3492115,115.7845658,18.902000000000044,5.94177,109.224,16.1,957.4,2.25329,-0.890602,-75.947
2016-02-12 08:47:11,40.3492163,115.7845434,18.91700000000003,3.39562,124.224,16.1,957.4,2.25078,5.36068,-61.0265
2016-02-12 08:47:12,40.3492168,115.7845391,18.373000000000047,2.35105,144.149,16.1,957.4,2.25335,0.560695,-45.7276
2016-02-12 08:47:13,40.3492155,115.784539,18.483000000000004,0.893619,174.724,16.1,957.4,2.25703,-1.3111,-23.1751
2016-02-12 08:47:14,40.3492136,115.7845378,18.56800000000004,0.103818,119.339,16.1,957.4,2.25902,-1.38589,10.1569
2016-02-12 08:47:15,40.3492129,115.7845354,18.382000000000005,0.0326814,130.99,16.1,957.4,2.25777,-1.22882,35.8235
2016-02-12 08:47:16,40.3492121,115.7845341,18.218999999999994,0.387784,31.1506,16.1,957.4,2.25355,-1.60541,40.0295
2016-02-12 08:47:17,40.3492103,115.7845329,18.116000000000042,0.509455,87.3243,16.1,957.4,2.23954,-2.1407,39.683
2016-02-12 08:47:18,40.3492105,115.7845333,17.775000000000034,0.381268,100.864,16.1,957.4,2.25254,-1.36341,39.8437
2016-02-12 08:47:19,40.3492113,115.7845336,17.50200000000001,0.370224,45.6902,16.1,957.4,2.25597,-1.52545,39.8108
2016-02-12 08:47:20,40.3492121,115.7845342,17.311000000000035,0.349136,85.5964,16.1,957.4,2.24971,-0.617308,39.8674
2016-02-12 08:47:21,40.349212,115.7845348,16.980000000000018,0.418138,75.5565,16.1,957.4,2.25604,-1.80859,39.3206
2016-02-12 08:47:22,40.3492118,115.7845347,16.562000000000012,0.729231,92.0266,16.1,957.4,2.24718,-1.91448,39.8363
2016-02-12 08:47:23,40.3492116,115.784534,16.108000000000004,0.752719,77.3196,16.1,957.4,2.2566,-2.7967,40.4346
2016-02-12 08:47:24,40.3492117,115.7845338,15.56800000000004,0.876472,112.876,16.2,957.6,2.24441,-2.74975,40.4632
2016-02-12 08:47:25,40.3492114,115.7845344,14.550000000000011,0.910692,111.859,16.2,957.6,2.24345,-3.14775,40.1516
2016-02-12 08:47:26,40.3492114,115.7845344,13.948000000000036,1.52511,98.9897,16.2,957.4,2.25048,-2.48058,39.9685
2016-02-12 08:47:27,40.3492112,115.7845344,13.17100000000005,1.46838,143.535,16.2,957.4,2.25029,1.99029,39.8544
2016-02-12 08:47:28,40.3492081,115.7845311,12.235000000000014,1.59666,132.338,16.2,957.4,2.24882,0.489737,39.9297
2016-02-12 08:47:29,40.3492023,115.7845249,11.288000000000011,2.02849,101.22,16.2,957.6,2.24682,0.807989,40.035
2016-02-12 08:47:30,40.3491942,115.7845164,10.459000000000003,2.41615,81.7842,16.2,957.6,2.24377,-1.64567,39.8959
2016-02-12 08:47:31,40.3491866,115.7845083,9.474000000000046,2.36492,77.0593,16.2,957.4,2.25103,-9.16326,40.0477
2016-02-12 08:47:32,40.3491841,115.7845057,8.593000000000018,2.04153,85.8787,16.2,957.4,2.25579,-3.23226,40.0162
2016-02-12 08:47:33,40.3491831,115.7845048,7.691000000000031,2.01561,84.4265,16.2,957.4,2.24309,2.06283,40.2772
2016-02-12 08:47:34,40.3491783,115.7844987,6.6720000000000255,2.23031,79.3183,16.2,957.4,2.24866,3.54644,46.1237
2016-02-12 08:47:35,40.3491704,115.7844869,5.802000000000021,2.77827,78.7524,16.2,957.6,2.24481,0.782934,49.3694
2016-02-12 08:47:36,40.3491614,115.7844734,5.021000000000015,2.6489,80.7009,16.2,957.6,2.24837,-3.47997,49.2569
1 timestamp latitude longitude height_ato windspeed winddir temperature pressure ch4 course_elevation course_azimuth
2 2016-02-12 08:34:01 40.349137 115.7855289 11.865000000000009 4.85383 126.121 18.1 957.6 2.28753 8.50882 74.9353
3 2016-02-12 08:34:02 40.349137 115.7855289 11.865000000000009 3.5045 142.744 18.1 957.6 2.27667 8.50882 74.9353
4 2016-02-12 08:34:02 40.349137 115.7855296 9.830000000000041 3.30667 145.626 18.1 957.4 2.28621 7.26866 75.2618
5 2016-02-12 08:34:02 40.3491369 115.7855295 9.830000000000041 3.19669 147.2 18.1 957.4 2.29012 6.6954 75.3488
6 2016-02-12 08:34:02 40.3491366 115.7855289 9.830000000000041 3.1958 146.33 18.1 957.4 2.28968 5.15029 75.4473
7 2016-02-12 08:34:02 40.3491365 115.7855279 9.830000000000041 2.24203 142.349 18.1 957.4 2.27675 3.60147 75.8082
8 2016-02-12 08:34:02 40.3491365 115.7855279 9.830000000000041 2.24203 142.349 18.1 957.4 2.28111 3.60147 75.8082
9 2016-02-12 08:34:02 40.3491362 115.7855267 9.830000000000041 2.65173 132.045 18.1 957.4 2.27628 2.90435 75.7617
10 2016-02-12 08:34:03 40.3491359 115.7855254 9.830000000000041 3.12274 124.934 18.1 957.4 2.26905 1.51899 75.2541
11 2016-02-12 08:34:04 40.3491342 115.7855197 9.482000000000028 3.62267 96.3253 18.1 957.4 2.26865 2.08601 74.3647
12 2016-02-12 08:34:05 40.3491317 115.7855115 6.3040000000000305 3.48429 103.687 18.1 957.4 2.25985 -1.48779 74.6518
13 2016-02-12 08:34:06 40.349131 115.7855068 3.1860000000000355 3.08523 110.241 18.1 957.4 2.25816 -5.50997 78.0309
14 2016-02-12 08:34:07 40.3491309 115.7855052 0.45100000000002183 2.57202 106.603 18.1 957.4 2.26128 -2.11963 61.7648
15 2016-02-12 08:34:08 40.3491307 115.7855046 0.06300000000004502 1.67764 109.782 18.0 957.4 2.26535 -6.78676 47.9709
16 2016-02-12 08:34:09 40.3491332 115.7855083 0.0 1.87728 168.504 18.0 957.4 2.26713 -11.0121 47.0035
17 2016-02-12 08:34:10 40.3491444 115.7855253 0.813000000000045 2.70038 170.113 18.0 957.4 2.27136 -6.98884 46.7738
18 2016-02-12 08:34:11 40.3491573 115.7855439 1.1070000000000277 4.09542 158.538 17.9 957.4 2.26672 -3.50721 45.9275
19 2016-02-12 08:34:12 40.3491708 115.7855627 0.8600000000000136 4.92415 152.325 17.9 957.4 2.26796 -3.67191 47.1102
20 2016-02-12 08:34:13 40.3491838 115.7855814 1.4639999999999986 5.05104 149.272 17.9 957.4 2.26253 -2.6092 47.3419
21 2016-02-12 08:34:14 40.3491963 115.7855993 1.2660000000000196 4.7566 146.774 17.8 957.4 2.25574 -3.68899 47.5405
22 2016-02-12 08:34:15 40.3492086 115.7856167 0.9460000000000264 4.4861 146.945 17.8 957.4 2.27209 -4.73718 47.8124
23 2016-02-12 08:34:16 40.3492212 115.7856339 1.1129999999999995 4.49042 147.234 17.8 957.4 2.2685 -3.71094 47.8571
24 2016-02-12 08:34:17 40.3492333 115.785651 1.330000000000041 4.67508 147.701 17.8 957.4 2.26577 -4.10178 47.8265
25 2016-02-12 08:34:18 40.3492453 115.7856683 0.3660000000000423 4.80069 142.768 17.8 957.4 2.26449 -4.00834 51.3819
26 2016-02-12 08:34:19 40.3492558 115.7856869 0.42900000000003047 4.41849 139.131 17.8 957.4 2.2629 -3.5961 55.2403
27 2016-02-12 08:34:20 40.3492652 115.7857063 0.5040000000000191 4.17348 135.791 17.8 957.4 2.27134 -3.66223 59.0575
28 2016-02-12 08:34:21 40.3492739 115.7857263 0.6690000000000396 4.24922 133.776 17.7 957.4 2.26504 -4.04384 62.0997
29 2016-02-12 08:34:22 40.3492823 115.7857472 0.6270000000000095 4.12397 132.906 17.7 957.4 2.26494 -3.93005 65.1934
30 2016-02-12 08:34:23 40.3492897 115.7857691 0.38800000000003365 3.87817 129.092 17.7 957.4 2.26202 -3.17112 69.0847
31 2016-02-12 08:34:24 40.3492958 115.7857913 0.535000000000025 3.56279 124.29 17.7 957.4 2.2705 -2.8296 73.4975
32 2016-02-12 08:34:25 40.3493007 115.7858139 0.41500000000002046 3.20321 120.437 17.7 957.4 2.26211 -2.58427 74.5562
33 2016-02-12 08:34:26 40.3493053 115.7858363 0.32600000000002183 2.84368 126.241 17.7 957.4 2.27064 -3.00187 74.5266
34 2016-02-12 08:34:27 40.3493102 115.7858587 0.39800000000002456 2.66869 123.302 17.6 957.4 2.26641 -2.85474 74.2713
35 2016-02-12 08:34:28 40.3493153 115.7858814 0.1560000000000059 2.33673 125.416 17.6 957.4 2.2613 -2.58352 74.0617
36 2016-02-12 08:34:29 40.3493205 115.7859044 0.015000000000043201 2.1419 112.039 17.6 957.4 2.27285 -2.4898 74.4684
37 2016-02-12 08:34:30 40.349325 115.7859273 0.023000000000024556 2.12291 112.287 17.6 957.4 2.26546 -2.37166 74.68
38 2016-02-12 08:34:31 40.3493296 115.7859502 0.09500000000002728 2.11867 112.449 17.5 957.4 2.26334 -2.52349 74.727
39 2016-02-12 08:34:32 40.3493339 115.7859728 0.21500000000003183 2.03503 104.255 17.5 957.4 2.25624 -2.35695 77.5604
40 2016-02-12 08:34:33 40.3493375 115.7859955 0.06800000000004047 2.08166 105.808 17.5 957.4 2.26756 -2.18838 81.7064
41 2016-02-12 08:34:34 40.3493398 115.7860185 0.09100000000000819 2.10121 101.349 17.5 957.4 2.27006 -2.16129 86.1149
42 2016-02-12 08:34:35 40.3493408 115.7860419 0.09800000000001319 2.0652 92.3755 17.5 957.4 2.26534 -1.97706 89.1031
43 2016-02-12 08:34:36 40.3493407 115.7860652 0.28400000000004866 2.03562 89.3814 17.5 957.4 2.26928 -1.69654 91.8991
44 2016-02-12 08:34:37 40.3493397 115.7860884 0.16800000000000637 2.01381 86.7262 17.4 957.4 2.26397 -1.49829 95.0727
45 2016-02-12 08:34:38 40.3493378 115.7861116 0.10599999999999454 1.94986 82.7376 17.4 957.4 2.26526 -1.28459 98.4028
46 2016-02-12 08:34:39 40.3493345 115.7861345 0.2300000000000182 1.98893 75.9616 17.4 957.4 2.27142 -1.40811 102.871
47 2016-02-12 08:34:40 40.3493301 115.786157 0.22400000000004638 1.97218 72.7694 17.4 957.4 2.26352 -1.32349 106.444
48 2016-02-12 08:34:41 40.3493248 115.7861794 0.26300000000003365 1.9978 72.1563 17.4 957.4 2.26984 -1.26987 107.053
49 2016-02-12 08:34:42 40.3493192 115.7862018 0.15399999999999636 1.99455 72.3657 17.4 957.4 2.27778 -1.2788 106.81
50 2016-02-12 08:34:43 40.3493138 115.7862243 0.16800000000000637 2.00894 73.2219 17.4 957.4 2.27545 -1.35789 106.736
51 2016-02-12 08:34:44 40.3493084 115.786247 0.23200000000002774 2.01704 73.3629 17.4 957.4 2.26695 -1.14838 107.083
52 2016-02-12 08:34:45 40.3493031 115.7862696 0.14400000000000546 1.99527 72.7411 17.4 957.4 2.26658 -0.891773 107.534
53 2016-02-12 08:34:46 40.3492978 115.7862919 0.14500000000003865 1.9958 72.9977 17.4 957.4 2.26718 -1.23237 107.164
54 2016-02-12 08:34:47 40.3492925 115.7863145 0.20400000000000773 2.00589 73.2645 17.3 957.4 2.27372 -0.841243 107.309
55 2016-02-12 08:34:48 40.3492871 115.7863372 0.11000000000001364 2.00215 73.3395 17.3 957.4 2.26653 -0.756934 106.873
56 2016-02-12 08:34:49 40.3492815 115.7863599 0.16599999999999682 2.00296 69.5246 17.3 957.4 2.27131 -0.454938 110.252
57 2016-02-12 08:34:50 40.3492749 115.7863818 0.27899999999999636 1.97805 64.6886 17.3 957.4 2.25977 -0.706977 114.756
58 2016-02-12 08:34:51 40.349267 115.7864029 0.23900000000003274 1.9369 61.1256 17.3 957.4 2.27473 -0.520325 118.334
59 2016-02-12 08:34:52 40.3492562 115.7864271 0.37700000000000955 1.9232 56.7933 17.3 957.4 2.27288 -0.892102 122.079
60 2016-02-12 08:34:53 40.3492466 115.7864464 0.3160000000000309 1.9402 53.0758 17.3 957.4 2.26006 -0.668285 125.41
61 2016-02-12 08:34:54 40.3492383 115.7864611 0.4070000000000391 1.94647 49.7541 17.3 957.4 2.26102 -0.793088 129.068
62 2016-02-12 08:34:55 40.3492244 115.7864817 0.46200000000004593 1.96366 44.9617 17.3 957.4 2.26623 -0.715602 133.755
63 2016-02-12 08:34:56 40.3492118 115.7864981 0.43200000000001637 1.96034 44.2948 17.3 957.4 2.26446 -0.690077 134.303
64 2016-02-12 08:34:57 40.3491991 115.7865145 0.34700000000003683 1.97744 45.1225 17.3 957.4 2.26972 -0.643342 134.308
65 2016-02-12 08:34:58 40.3491864 115.7865314 0.37700000000000955 1.76954 51.6213 17.3 957.4 2.26913 -0.884507 134.019
66 2016-02-12 08:34:59 40.3491734 115.7865484 0.3170000000000073 1.64919 64.6824 17.3 957.4 2.26522 -0.561871 134.093
67 2016-02-12 08:35:00 40.3491603 115.786565 0.38900000000001 1.53019 22.4667 17.3 957.4 2.27348 -0.283173 139.001
68 2016-02-12 08:35:01 40.3491468 115.7865794 0.3860000000000241 1.66544 16.1733 17.3 957.4 2.25965 -0.622678 146.88
69 2016-02-12 08:35:02 40.349132 115.7865915 0.49600000000003774 1.90088 25.2598 17.3 957.4 2.27091 -0.675699 152.432
70 2016-02-12 08:35:03 40.3491161 115.7866014 0.660000000000025 1.92716 21.0727 17.3 957.4 2.27679 -0.638564 157.896
71 2016-02-12 08:35:04 40.3490997 115.786609 0.6190000000000282 1.94499 15.5196 17.3 957.4 2.2683 -1.18828 163.563
72 2016-02-12 08:35:05 40.3490826 115.7866145 0.6270000000000095 2.06029 5.61009 17.3 957.4 2.26783 -0.849828 170.567
73 2016-02-12 08:35:06 40.349065 115.7866175 0.7410000000000423 2.25531 18.8411 17.3 957.4 2.27565 -1.02481 175.647
74 2016-02-12 08:35:07 40.3490471 115.7866191 0.5990000000000464 2.6897 27.0446 17.3 957.4 2.26251 -0.938632 175.901
75 2016-02-12 08:35:08 40.3490295 115.7866204 0.8120000000000118 3.5706 22.8119 17.3 957.4 2.26682 -1.4553 175.625
76 2016-02-12 08:35:09 40.3490118 115.7866221 0.5160000000000196 3.58223 23.2989 17.3 957.4 2.26834 -1.51818 175.649
77 2016-02-12 08:35:10 40.3489939 115.7866236 0.6400000000000432 3.47975 23.2924 17.3 957.4 2.26655 -1.19849 175.598
78 2016-02-12 08:35:11 40.3489761 115.7866252 0.5400000000000205 3.19407 20.9252 17.3 957.4 2.26637 -0.986002 176.011
79 2016-02-12 08:35:12 40.3489581 115.7866269 0.5540000000000305 2.9534 17.5397 17.3 957.4 2.2573 -1.64013 176.158
80 2016-02-12 08:35:13 40.3489399 115.7866285 0.7060000000000173 3.15458 18.2456 17.3 957.4 2.26939 -0.792553 175.629
81 2016-02-12 08:35:14 40.3489218 115.7866301 0.6890000000000214 3.20536 19.0764 17.3 957.4 2.2633 -1.16851 175.798
82 2016-02-12 08:35:15 40.3489038 115.7866319 0.8970000000000482 3.5823 22.3026 17.3 957.4 2.25549 -0.91357 175.775
83 2016-02-12 08:35:16 40.3488859 115.7866335 0.7669999999999959 3.65156 26.1432 17.3 957.4 2.27439 -1.38495 178.614
84 2016-02-12 08:35:17 40.3488681 115.7866336 0.7250000000000227 3.69689 28.3517 17.2 957.4 2.2692 -1.36653 -178.318
85 2016-02-12 08:35:18 40.3488503 115.7866322 0.8000000000000114 3.65114 28.7382 17.2 957.4 2.26636 -1.90382 -175.758
86 2016-02-12 08:35:19 40.3488325 115.7866297 0.7480000000000473 3.6946 29.076 17.2 957.4 2.27162 -1.64705 -173.079
87 2016-02-12 08:35:20 40.3488148 115.7866265 0.7590000000000146 3.86282 32.9325 17.2 957.4 2.26822 -1.50341 -170.331
88 2016-02-12 08:35:21 40.3487974 115.7866223 0.57000000000005 3.78317 34.2873 17.2 957.4 2.259 -1.77715 -168.664
89 2016-02-12 08:35:22 40.3487801 115.7866172 0.8000000000000114 3.73202 35.6475 17.2 957.4 2.26842 -1.80386 -166.087
90 2016-02-12 08:35:23 40.348763 115.7866112 0.5540000000000305 3.64181 38.9923 17.2 957.4 2.26291 -1.70703 -162.255
91 2016-02-12 08:35:24 40.348746 115.7866039 0.7320000000000277 3.81269 41.8128 17.2 957.4 2.26664 -1.71048 -159.878
92 2016-02-12 08:35:25 40.3487291 115.7865957 0.7630000000000337 3.48729 42.0299 17.2 957.4 2.26374 -1.33685 -159.608
93 2016-02-12 08:35:26 40.3487121 115.7865872 1.0080000000000382 3.75868 43.3489 17.2 957.4 2.26646 -1.55744 -159.91
94 2016-02-12 08:35:27 40.3486957 115.7865788 0.7060000000000173 3.79234 42.8656 17.2 957.4 2.26328 -2.0048 -159.441
95 2016-02-12 08:35:28 40.3486789 115.7865705 0.7350000000000136 4.22793 42.0491 17.2 957.4 2.26176 -1.98951 -159.699
96 2016-02-12 08:35:29 40.3486623 115.7865625 0.7860000000000014 4.27342 41.0633 17.2 957.4 2.2614 -2.18286 -159.799
97 2016-02-12 08:35:30 40.3486421 115.7865527 0.5580000000000496 4.18449 42.0908 17.2 957.4 2.2712 -1.9235 -159.6
98 2016-02-12 08:35:31 40.3486252 115.7865443 0.4430000000000405 4.02941 43.9017 17.2 957.4 2.26236 -1.78458 -159.343
99 2016-02-12 08:35:32 40.3486085 115.7865356 0.4370000000000118 4.02369 47.8521 17.2 957.4 2.26458 -1.82948 -155.262
100 2016-02-12 08:35:33 40.3485927 115.7865251 0.6200000000000045 4.1616 52.7125 17.2 957.4 2.26249 -2.21001 -149.328
101 2016-02-12 08:35:34 40.3485776 115.7865124 0.5920000000000414 4.1949 56.7896 17.2 957.4 2.26734 -1.6575 -143.271
102 2016-02-12 08:35:35 40.3485635 115.7864976 0.6930000000000405 4.27443 63.2883 17.2 957.4 2.27079 -1.35784 -137.443
103 2016-02-12 08:35:36 40.3485507 115.7864814 1.0370000000000346 4.18031 70.4075 17.2 957.4 2.27161 -2.25059 -133.151
104 2016-02-12 08:35:37 40.3485392 115.7864642 1.143000000000029 4.11209 74.1468 17.1 957.4 2.26222 -2.27961 -128.075
105 2016-02-12 08:35:38 40.3485291 115.7864455 1.0510000000000446 4.69329 81.6319 17.1 957.4 2.26785 -2.59902 -121.299
106 2016-02-12 08:35:39 40.3485208 115.7864255 1.2220000000000368 5.02418 87.2004 17.1 957.4 2.26188 -3.57525 -114.178
107 2016-02-12 08:35:40 40.3485143 115.7864042 1.0570000000000164 5.29014 89.51 17.1 957.4 2.25589 -3.38018 -109.557
108 2016-02-12 08:35:41 40.3485083 115.7863817 1.0950000000000273 5.35193 86.5112 17.1 957.4 2.26569 -3.63266 -110.057
109 2016-02-12 08:35:42 40.3485019 115.7863589 0.9279999999999973 5.48287 85.2166 17.1 957.4 2.25651 -3.05251 -109.671
110 2016-02-12 08:35:43 40.3484959 115.7863364 1.3120000000000118 5.33864 85.4933 17.1 957.4 2.2527 -3.46027 -109.986
111 2016-02-12 08:35:44 40.3484896 115.7863142 0.9790000000000418 5.04344 87.0444 17.1 957.4 2.25495 -2.7903 -109.977
112 2016-02-12 08:35:45 40.3484838 115.7862919 0.8730000000000473 5.04691 88.3346 17.1 957.4 2.25385 -2.69067 -109.498
113 2016-02-12 08:35:46 40.3484784 115.7862698 0.7189999999999941 4.85317 86.7704 17.1 957.4 2.25565 -3.02553 -109.5
114 2016-02-12 08:35:47 40.3484727 115.7862479 0.4759999999999991 4.84407 85.5268 17.1 957.4 2.26485 -2.80897 -109.877
115 2016-02-12 08:35:48 40.3484667 115.786226 0.7650000000000432 4.92592 82.6714 17.1 957.4 2.26122 -3.19976 -110.092
116 2016-02-12 08:35:49 40.3484607 115.7862036 0.9590000000000032 4.84169 80.0226 17.1 957.4 2.26519 -3.37566 -109.883
117 2016-02-12 08:35:50 40.3484548 115.7861811 0.9000000000000341 4.92234 79.5242 17.0 957.4 2.25928 -3.44132 -109.953
118 2016-02-12 08:35:51 40.3484488 115.7861583 0.7050000000000409 4.87384 79.8274 17.0 957.4 2.26367 -2.44092 -108.984
119 2016-02-12 08:35:52 40.3484431 115.7861355 1.3520000000000323 4.80479 85.2199 17.0 957.4 2.26016 -2.95146 -104.259
120 2016-02-12 08:35:53 40.3484387 115.7861128 1.2720000000000482 4.68873 88.9 17.0 957.4 2.26904 -3.00915 -99.8611
121 2016-02-12 08:35:54 40.3484358 115.7860899 1.1779999999999973 4.69722 95.5627 17.0 957.4 2.26347 -3.11661 -95.6539
122 2016-02-12 08:35:55 40.3484345 115.7860661 1.05600000000004 4.66468 100.449 17.0 957.4 2.26009 -2.20477 -92.2146
123 2016-02-12 08:35:56 40.3484343 115.7860428 1.3660000000000423 4.72368 105.041 17.0 957.4 2.25921 -2.67096 -88.8258
124 2016-02-12 08:35:57 40.3484347 115.7860198 1.8100000000000023 4.68402 107.835 17.0 957.4 2.25358 -3.15406 -84.749
125 2016-02-12 08:35:58 40.3484367 115.7859975 2.1230000000000473 4.85389 110.385 17.0 957.4 2.26588 -4.38063 -81.1136
126 2016-02-12 08:35:59 40.3484402 115.7859746 1.6659999999999968 5.12074 113.453 17.0 957.4 2.25073 -3.78266 -75.9072
127 2016-02-12 08:36:00 40.3484451 115.7859519 1.5710000000000264 5.51489 114.162 16.9 957.4 2.25645 -3.45966 -73.0747
128 2016-02-12 08:36:01 40.3484506 115.7859298 1.41700000000003 5.60618 114.705 16.9 957.4 2.26324 -3.852 -72.6888
129 2016-02-12 08:36:02 40.3484562 115.7859079 1.4260000000000446 5.9885 113.608 16.9 957.4 2.25939 -4.08462 -72.4005
130 2016-02-12 08:36:03 40.3484618 115.7858859 1.2960000000000491 6.06681 114.146 16.9 957.4 2.26444 -4.33265 -72.7478
131 2016-02-12 08:36:04 40.3484672 115.7858634 1.875 6.16502 113.964 16.9 957.4 2.25122 -4.29353 -72.6671
132 2016-02-12 08:36:05 40.3484723 115.7858407 1.288000000000011 5.83346 114.53 16.9 957.4 2.25211 -4.46077 -72.5697
133 2016-02-12 08:36:06 40.3484779 115.785818 1.2210000000000036 5.89907 113.53 16.9 957.4 2.25987 -4.01207 -72.7203
134 2016-02-12 08:36:07 40.3484833 115.7857951 1.188000000000045 5.87513 112.884 16.9 957.4 2.25998 -3.94424 -72.7445
135 2016-02-12 08:36:08 40.3484887 115.7857725 1.0230000000000246 5.86465 112.761 16.9 957.4 2.25653 -3.75708 -72.6379
136 2016-02-12 08:36:09 40.3484941 115.78575 1.3140000000000214 5.86195 113.211 16.9 957.4 2.26881 -3.84116 -72.7711
137 2016-02-12 08:36:10 40.3484998 115.7857277 1.1030000000000086 5.76417 116.283 16.8 957.4 2.26094 -3.59034 -70.8237
138 2016-02-12 08:36:11 40.3485062 115.785706 1.30600000000004 5.63247 121.963 16.8 957.4 2.26475 -4.2956 -65.0574
139 2016-02-12 08:36:12 40.348514 115.7856854 1.295000000000016 5.60765 127.444 16.8 957.4 2.27279 -4.16794 -59.1853
140 2016-02-12 08:36:13 40.3485233 115.7856661 1.3950000000000387 5.85706 131.455 16.8 957.4 2.24993 -4.41538 -54.0778
141 2016-02-12 08:36:14 40.3485344 115.7856481 1.2980000000000018 5.88649 137.158 16.8 957.4 2.25646 -4.22068 -48.5817
142 2016-02-12 08:36:15 40.3485493 115.7856278 1.413000000000011 5.83127 140.639 16.8 957.4 2.263 -3.64977 -43.7228
143 2016-02-12 08:36:16 40.3485596 115.7856156 1.6090000000000373 5.7416 144.321 16.8 957.4 2.25908 -4.5659 -39.0127
144 2016-02-12 08:36:17 40.3485769 115.7855999 1.2909999999999968 5.95436 149.405 16.7 957.4 2.25161 -3.4582 -31.6394
145 2016-02-12 08:36:18 40.3485927 115.7855881 1.032000000000039 5.88089 152.516 16.7 957.4 2.26682 -3.81466 -26.593
146 2016-02-12 08:36:19 40.3486084 115.7855776 1.410000000000025 5.92927 151.424 16.7 957.4 2.26897 -4.88384 -25.4304
147 2016-02-12 08:36:20 40.3486242 115.7855675 1.4120000000000346 6.06628 150.826 16.7 957.4 2.25404 -4.74525 -25.5442
148 2016-02-12 08:36:21 40.3486401 115.7855574 1.1860000000000355 6.09935 150.336 16.7 957.4 2.25539 -4.647 -25.6555
149 2016-02-12 08:36:22 40.3486565 115.7855475 0.9850000000000136 6.11633 148.496 16.7 957.4 2.26913 -4.63177 -25.7067
150 2016-02-12 08:36:23 40.3486729 115.7855371 0.7600000000000477 5.92629 148.812 16.6 957.4 2.26475 -4.46693 -26.0157
151 2016-02-12 08:36:24 40.3486891 115.7855269 0.7820000000000391 6.07324 148.379 16.6 957.4 2.25667 -4.99766 -25.7595
152 2016-02-12 08:36:25 40.3487052 115.7855169 1.1040000000000418 5.99085 149.5 16.6 957.4 2.25532 -4.78653 -25.4645
153 2016-02-12 08:36:26 40.3487213 115.7855067 0.8840000000000146 6.04219 151.354 16.6 957.4 2.26913 -4.636 -25.7042
154 2016-02-12 08:36:27 40.3487372 115.7854966 0.8730000000000473 5.95603 152.786 16.6 957.4 2.26901 -4.5439 -24.9907
155 2016-02-12 08:36:28 40.348753 115.7854872 0.6620000000000346 6.0444 155.92 16.6 957.4 2.25882 -5.09607 -21.8508
156 2016-02-12 08:36:29 40.3487698 115.7854789 0.7740000000000009 6.23573 157.69 16.6 957.4 2.27421 -4.48643 -17.9076
157 2016-02-12 08:36:30 40.3487874 115.7854718 0.9569999999999936 6.31058 159.216 16.5 957.4 2.25334 -4.42131 -14.4395
158 2016-02-12 08:36:31 40.3488052 115.7854663 0.8700000000000045 6.16818 160.728 16.5 957.4 2.25037 -4.45109 -11.6332
159 2016-02-12 08:36:32 40.3488228 115.785462 0.5060000000000286 6.10734 161.71 16.5 957.4 2.25493 -4.35846 -8.40024
160 2016-02-12 08:36:33 40.3488399 115.7854588 0.799000000000035 6.11898 164.494 16.4 957.4 2.24844 -5.41057 -6.17409
161 2016-02-12 08:36:34 40.3488573 115.7854564 0.742999999999995 6.07141 167.215 16.4 957.4 2.26561 -5.26034 -2.7436
162 2016-02-12 08:36:35 40.3488754 115.7854551 0.6370000000000005 6.0496 171.946 16.4 957.4 2.25455 -4.44777 1.35836
163 2016-02-12 08:36:36 40.3488935 115.785456 0.7320000000000277 5.83808 173.643 16.4 957.4 2.26214 -4.58309 4.52072
164 2016-02-12 08:36:37 40.3489117 115.7854579 0.8480000000000132 5.70385 172.17 16.4 957.4 2.26151 -3.90147 5.07055
165 2016-02-12 08:36:38 40.3489293 115.78546 0.9800000000000182 5.51454 171.791 16.4 957.4 2.25964 -4.5457 5.24711
166 2016-02-12 08:36:39 40.348947 115.7854622 1.1539999999999964 5.33505 173.485 16.4 957.4 2.26292 -4.35318 5.33673
167 2016-02-12 08:36:40 40.3489653 115.7854648 1.0 5.29204 174.852 16.3 957.4 2.25233 -3.87292 4.70492
168 2016-02-12 08:36:41 40.3489836 115.7854674 1.3559999999999945 5.29741 176.258 16.3 957.4 2.25662 -3.21208 5.21414
169 2016-02-12 08:36:42 40.3490015 115.7854698 1.3730000000000473 5.14176 174.023 16.3 957.4 2.25812 -3.51608 5.02582
170 2016-02-12 08:36:43 40.3490189 115.7854713 1.516999999999996 5.12388 174.751 16.2 957.4 2.25788 -4.56814 5.03848
171 2016-02-12 08:36:44 40.3490365 115.7854732 1.4870000000000232 5.10234 176.725 16.2 957.4 2.26351 -3.96444 5.46284
172 2016-02-12 08:36:45 40.3490545 115.7854759 1.3980000000000246 5.09201 176.966 16.2 957.4 2.2583 -3.79534 5.24914
173 2016-02-12 08:36:46 40.3490724 115.7854788 1.6370000000000005 5.11211 176.889 16.2 957.4 2.2544 -3.72235 5.29693
174 2016-02-12 08:36:47 40.3490906 115.785481 1.1280000000000427 4.8991 175.319 16.2 957.4 2.26159 -3.32421 5.01752
175 2016-02-12 08:36:48 40.3491085 115.7854831 0.8170000000000073 4.10668 170.376 16.2 957.4 2.25495 10.1467 5.26258
176 2016-02-12 08:36:49 40.3491158 115.7854839 0.9000000000000341 2.6314 163.343 16.2 957.4 2.26207 0.106344 5.66132
177 2016-02-12 08:36:50 40.349117 115.785484 0.38100000000002865 1.58396 131.609 16.1 957.4 2.26455 -0.625125 5.82946
178 2016-02-12 08:36:51 40.3491165 115.7854841 0.313000000000045 0.960517 119.397 16.1 957.4 2.25937 -1.82616 5.43775
179 2016-02-12 08:36:52 40.3491162 115.7854839 0.5020000000000095 0.136019 56.7013 16.1 957.4 2.26542 -1.73079 5.51902
180 2016-02-12 08:36:53 40.3491157 115.7854835 0.3410000000000082 0.0603939 21.4057 16.1 957.4 2.25628 -1.86747 5.8482
181 2016-02-12 08:36:54 40.3491154 115.7854833 0.19600000000002638 0.0369274 47.6323 16.1 957.4 2.25712 -1.53655 6.2355
182 2016-02-12 08:36:55 40.3491151 115.7854834 0.2470000000000141 0.0871401 79.15 16.1 957.4 2.26202 -1.14965 6.09218
183 2016-02-12 08:36:56 40.3491149 115.7854834 0.08300000000002683 0.393658 71.1975 16.1 957.4 2.25841 -1.21857 5.48189
184 2016-02-12 08:36:57 40.3491148 115.7854834 0.32900000000000773 0.586761 66.23 16.1 957.4 2.27044 -1.31146 5.43551
185 2016-02-12 08:36:58 40.3491145 115.7854834 0.28600000000000136 0.596112 53.5956 16.1 957.4 2.25902 -1.45305 5.54127
186 2016-02-12 08:36:59 40.3491142 115.7854835 0.21200000000004593 0.25565 52.3429 16.1 957.4 2.25571 -1.29331 5.77698
187 2016-02-12 08:37:00 40.3491142 115.7854836 0.25200000000000955 0.0781401 60.0922 16.1 957.4 2.26602 -1.42537 5.60733
188 2016-02-12 08:37:01 40.3491142 115.7854835 0.16100000000000136 0.0230935 155.25 16.1 957.4 2.25023 -1.26584 5.76965
189 2016-02-12 08:37:02 40.349114 115.7854833 0.10099999999999909 0.0296167 138.082 16.1 957.4 2.26859 -0.900714 6.01267
190 2016-02-12 08:37:03 40.349114 115.7854834 0.15500000000002956 0.430488 50.8187 16.1 957.4 2.25236 -1.35083 5.15359
191 2016-02-12 08:37:04 40.3491135 115.7854833 0.48500000000001364 0.980068 84.1409 16.1 957.4 2.26295 -2.14462 6.25571
192 2016-02-12 08:37:05 40.3491133 115.7854835 0.3830000000000382 1.27921 103.371 16.1 957.4 2.25558 -2.13589 6.19036
193 2016-02-12 08:37:06 40.3491131 115.7854836 0.4159999999999968 1.00135 137.031 16.1 957.4 2.26097 -2.52534 5.96649
194 2016-02-12 08:37:07 40.3491134 115.7854836 0.2950000000000159 0.717434 155.678 16.1 957.4 2.26059 -1.63997 5.78432
195 2016-02-12 08:37:08 40.3491138 115.7854835 0.21200000000004593 0.303557 137.275 16.1 957.4 2.25044 -0.967678 5.61883
196 2016-02-12 08:37:09 40.3491137 115.7854835 0.21100000000001273 0.285436 130.174 16.1 957.4 2.25547 -0.834362 5.65676
197 2016-02-12 08:37:10 40.3491134 115.7854835 0.1500000000000341 0.083626 87.1777 16.1 957.4 2.26308 -0.800933 5.2812
198 2016-02-12 08:37:11 40.3491131 115.7854835 0.16700000000003 0.10367 42.9916 16.1 957.4 2.25831 -1.52589 4.76376
199 2016-02-12 08:37:12 40.3491127 115.7854833 0.5340000000000487 0.113468 112.581 16.1 957.4 2.26024 -1.83201 5.26747
200 2016-02-12 08:37:13 40.3491126 115.7854835 0.5110000000000241 0.0976797 81.7381 16.1 957.4 2.2573 -1.50989 5.33285
201 2016-02-12 08:37:14 40.3491124 115.7854837 0.5590000000000259 1.8663 90.5845 16.1 957.4 2.26294 -1.44776 5.84654
202 2016-02-12 08:37:15 40.3491125 115.7854838 1.865000000000009 2.56762 89.8643 16.1 957.4 2.26043 -0.567501 6.1396
203 2016-02-12 08:37:16 40.3491122 115.7854834 4.349000000000046 0.917837 91.5823 16.1 957.6 2.26137 -1.97875 5.82784
204 2016-02-12 08:37:17 40.3491111 115.7854803 5.638000000000034 0.716475 48.2852 16.1 957.6 2.26394 -2.59172 42.491
205 2016-02-12 08:37:18 40.349111 115.7854795 5.432000000000016 0.760453 50.6434 16.1 957.6 2.25914 -6.46643 44.7529
206 2016-02-12 08:37:19 40.3491155 115.785485 5.338999999999999 0.642827 152.992 16.2 957.6 2.25408 -8.15347 44.0491
207 2016-02-12 08:37:20 40.3491267 115.7854981 5.7379999999999995 1.76091 82.2608 16.2 957.6 2.25425 2.78277 45.1
208 2016-02-12 08:37:21 40.3491335 115.7855064 5.6650000000000205 0.881555 11.1025 16.2 957.6 2.26243 3.05661 47.7378
209 2016-02-12 08:37:23 40.3491349 115.7855084 5.471000000000004 0.876476 69.6464 16.2 957.6 2.25292 -11.4077 48.1101
210 2016-02-12 08:37:23 40.3491427 115.7855204 5.588999999999999 1.84099 115.054 16.2 957.6 2.25092 -3.99469 47.4194
211 2016-02-12 08:37:25 40.3491553 115.7855389 5.801000000000045 2.39834 107.803 16.2 957.6 2.25989 -2.57408 47.3755
212 2016-02-12 08:37:26 40.3491683 115.7855575 6.093000000000018 3.37656 124.034 16.2 957.4 2.26015 -2.74762 47.3582
213 2016-02-12 08:37:27 40.3491811 115.785576 6.409000000000049 3.88895 134.223 16.2 957.4 2.25817 -3.03106 47.53
214 2016-02-12 08:37:28 40.3491935 115.7855944 6.5540000000000305 3.92564 147.649 16.2 957.4 2.25108 -3.07153 47.3604
215 2016-02-12 08:37:29 40.3492054 115.7856118 6.573000000000036 4.2193 150.06 16.2 957.4 2.2539 -3.572 47.243
216 2016-02-12 08:37:30 40.3492176 115.7856288 6.5160000000000196 4.64874 149.884 16.2 957.4 2.24965 -3.67273 47.4047
217 2016-02-12 08:37:31 40.3492301 115.7856461 6.145000000000039 4.72077 150.734 16.2 957.4 2.2622 -3.50582 47.5138
218 2016-02-12 08:37:32 40.3492422 115.7856636 6.133000000000038 4.53941 145.099 16.2 957.4 2.25039 -3.6977 50.4106
219 2016-02-12 08:37:33 40.3492531 115.7856817 6.093999999999994 4.65501 139.49 16.2 957.4 2.25039 -4.10876 54.9473
220 2016-02-12 08:37:34 40.3492629 115.785701 6.29400000000004 4.75953 137.043 16.2 957.4 2.26519 -3.8511 58.421
221 2016-02-12 08:37:35 40.349272 115.7857212 6.16700000000003 4.68933 133.723 16.2 957.4 2.25982 -2.84437 61.008
222 2016-02-12 08:37:36 40.3492803 115.7857422 5.970000000000027 3.71239 129.472 16.2 957.6 2.25764 -2.38204 64.3574
223 2016-02-12 08:37:37 40.3492877 115.7857639 5.673000000000002 3.24695 125.042 16.2 957.6 2.25472 -2.49819 68.7895
224 2016-02-12 08:37:38 40.3492935 115.7857858 6.0020000000000095 3.11102 121.256 16.2 957.4 2.26319 -2.82953 72.6732
225 2016-02-12 08:37:39 40.3492985 115.7858079 5.843000000000018 3.55585 127.703 16.2 957.6 2.26381 -3.01438 73.9861
226 2016-02-12 08:37:40 40.3493033 115.78583 5.6860000000000355 3.66656 127.519 16.2 957.6 2.26546 -3.47219 74.2353
227 2016-02-12 08:37:41 40.3493081 115.7858522 5.900000000000034 3.7344 126.386 16.2 957.6 2.26321 -3.65925 74.02
228 2016-02-12 08:37:42 40.3493131 115.7858748 5.757000000000005 3.59181 124.73 16.2 957.6 2.2622 -3.15687 74.24
229 2016-02-12 08:37:43 40.3493182 115.7858977 5.725999999999999 3.52774 122.094 16.2 957.6 2.25546 -3.02432 74.6855
230 2016-02-12 08:37:44 40.349323 115.7859204 5.878000000000043 3.64108 121.595 16.2 957.6 2.25546 -3.44193 74.1486
231 2016-02-12 08:37:45 40.3493279 115.7859431 5.875 4.10979 123.849 16.2 957.6 2.25546 -3.16246 74.2353
232 2016-02-12 08:37:46 40.3493334 115.7859706 5.775000000000034 4.2231 121.878 16.2 957.6 2.25546 -2.85934 77.3826
233 2016-02-12 08:37:47 40.3493371 115.7859941 5.854000000000042 3.38294 116.494 16.2 957.6 2.25546 -1.69435 81.6517
234 2016-02-12 08:37:48 40.349339 115.7860126 5.703000000000031 3.05009 112.988 16.2 957.6 2.25773 -2.59874 84.8266
235 2016-02-12 08:37:49 40.3493403 115.7860404 5.862000000000023 2.45333 104.114 16.2 957.6 2.25121 -2.6631 88.8626
236 2016-02-12 08:37:50 40.3493403 115.7860637 5.515000000000043 2.71353 107.91 16.2 957.6 2.26119 -2.36504 91.8881
237 2016-02-12 08:37:51 40.3493394 115.7860872 5.501000000000033 2.80362 106.534 16.2 957.6 2.272 -2.08923 94.6365
238 2016-02-12 08:37:52 40.3493377 115.7861101 5.75 2.76796 106.874 16.2 957.6 2.26665 -1.91928 98.7676
239 2016-02-12 08:37:53 40.3493346 115.7861332 5.528999999999996 2.30693 90.5027 16.1 957.6 2.27118 -1.50633 102.875
240 2016-02-12 08:37:54 40.3493303 115.7861556 5.57000000000005 2.15987 80.27 16.1 957.6 2.26014 -2.41663 106.747
241 2016-02-12 08:37:55 40.3493251 115.7861782 5.718000000000018 1.98563 72.6664 16.1 957.6 2.26723 -2.04302 107.311
242 2016-02-12 08:37:56 40.3493196 115.7862007 5.552999999999997 2.00151 72.8042 16.1 957.6 2.26513 -2.02087 106.976
243 2016-02-12 08:37:57 40.3493142 115.7862233 5.675000000000011 2.00659 73.3209 16.1 957.6 2.27117 -2.0311 106.897
244 2016-02-12 08:37:58 40.349309 115.786246 5.585000000000036 1.99442 73.2617 16.1 957.6 2.26669 -1.85794 107.051
245 2016-02-12 08:37:59 40.3493037 115.7862686 5.536000000000001 2.00573 73.0795 16.1 957.6 2.26195 -1.67994 106.978
246 2016-02-12 08:38:00 40.3492984 115.7862912 5.532000000000039 2.00435 72.5278 16.1 957.6 2.26446 -1.44107 107.109
247 2016-02-12 08:38:01 40.3492929 115.7863138 5.579000000000008 2.01129 72.6281 16.1 957.6 2.26836 -1.59664 107.211
248 2016-02-12 08:38:02 40.3492874 115.7863364 5.55800000000005 1.98886 72.6863 16.1 957.6 2.2662 -1.67881 106.822
249 2016-02-12 08:38:03 40.3492821 115.7863585 5.632000000000005 1.97927 70.5809 16.1 957.6 2.26912 -1.75376 109.576
250 2016-02-12 08:38:04 40.349276 115.7863801 5.837000000000046 1.97986 64.8357 16.1 957.6 2.27006 -1.97127 114.942
251 2016-02-12 08:38:05 40.3492681 115.7864007 5.823000000000036 1.97842 61.166 16.1 957.6 2.26009 -1.6458 118.698
252 2016-02-12 08:38:06 40.3492592 115.7864208 5.7900000000000205 1.99769 57.8575 16.1 957.6 2.26133 -1.79207 121.582
253 2016-02-12 08:38:07 40.3492495 115.7864403 5.853000000000009 2.00282 54.7015 16.1 957.6 2.26969 -1.57073 124.545
254 2016-02-12 08:38:08 40.349239 115.786459 5.771000000000015 1.9989 50.599 16.1 957.6 2.25815 -1.77694 129.001
255 2016-02-12 08:38:09 40.3492274 115.7864766 5.78000000000003 1.98813 46.3829 16.1 957.6 2.26562 -1.72888 133.366
256 2016-02-12 08:38:10 40.349215 115.7864933 5.866000000000042 1.99488 45.6054 16.1 957.6 2.26581 -2.17574 134.303
257 2016-02-12 08:38:11 40.3492022 115.7865101 5.807000000000016 1.98864 45.893 16.1 957.6 2.2618 -1.81056 134.52
258 2016-02-12 08:38:12 40.3491897 115.7865271 5.6410000000000196 1.99804 46.0968 16.1 957.6 2.26713 -1.72293 134.343
259 2016-02-12 08:38:13 40.3491772 115.7865441 5.715000000000032 2.01774 45.7766 16.2 957.6 2.26881 -1.66066 134.316
260 2016-02-12 08:38:14 40.3491645 115.7865609 5.787000000000035 2.01669 41.1983 16.2 957.6 2.26173 -1.78608 137.866
261 2016-02-12 08:38:15 40.3491509 115.7865759 5.875 1.98778 34.7049 16.2 957.6 2.25985 -1.48482 144.993
262 2016-02-12 08:38:16 40.3491362 115.7865886 5.813000000000045 1.97874 28.2621 16.2 957.6 2.26267 -1.65466 150.873
263 2016-02-12 08:38:17 40.3491205 115.7865992 6.025000000000034 2.26713 25.0355 16.2 957.4 2.2593 -1.70951 156.254
264 2016-02-12 08:38:18 40.3491039 115.7866075 6.006000000000029 2.47573 18.7115 16.2 957.4 2.2718 -1.63082 161.557
265 2016-02-12 08:38:19 40.349087 115.7866139 5.956999999999994 2.56727 8.6849 16.2 957.6 2.26504 -1.88711 168.928
266 2016-02-12 08:38:20 40.3490696 115.7866172 6.229000000000042 2.75719 0.527441 16.2 957.4 2.26636 -1.99268 174.757
267 2016-02-12 08:38:21 40.3490516 115.7866186 6.1370000000000005 3.24292 2.39415 16.2 957.4 2.26015 -2.09729 175.563
268 2016-02-12 08:38:22 40.3490337 115.7866199 6.097000000000037 3.42724 3.36974 16.2 957.4 2.26113 -2.11005 175.792
269 2016-02-12 08:38:23 40.3490159 115.7866215 6.021000000000015 3.56703 2.19504 16.2 957.4 2.26318 -2.58626 176.337
270 2016-02-12 08:38:24 40.3489978 115.7866231 6.031000000000006 2.98014 0.730891 16.2 957.4 2.2592 -2.18878 176.036
271 2016-02-12 08:38:25 40.3489799 115.7866245 6.050000000000011 2.8769 1.18416 16.2 957.4 2.25769 -2.45616 175.722
272 2016-02-12 08:38:26 40.348962 115.7866262 6.004000000000019 2.97136 0.474847 16.2 957.4 2.25814 -2.30747 176.164
273 2016-02-12 08:38:27 40.348944 115.7866277 6.004000000000019 3.28611 0.877931 16.2 957.4 2.269 -2.20202 176.154
274 2016-02-12 08:38:28 40.3489259 115.7866295 5.921000000000049 3.28373 1.71368 16.2 957.6 2.26907 -2.02838 175.744
275 2016-02-12 08:38:29 40.3489042 115.786632 5.921000000000049 3.18593 0.556809 16.2 957.6 2.26987 -1.73959 176.318
276 2016-02-12 08:38:30 40.3488863 115.7866332 5.9430000000000405 3.17403 2.17954 16.2 957.6 2.26099 -1.88535 178.499
277 2016-02-12 08:38:31 40.3488686 115.7866333 6.1370000000000005 3.17068 5.38026 16.2 957.4 2.25922 -2.30753 -178.254
278 2016-02-12 08:38:32 40.3488508 115.786632 6.119000000000028 2.97947 7.49582 16.2 957.4 2.26828 -1.80747 -175.54
279 2016-02-12 08:38:33 40.348833 115.7866299 6.079000000000008 2.76366 9.47064 16.2 957.4 2.2712 -2.05905 -172.77
280 2016-02-12 08:38:34 40.3488154 115.7866269 6.048000000000002 2.80114 12.3371 16.2 957.4 2.26121 -2.1765 -171.028
281 2016-02-12 08:38:35 40.3487978 115.7866228 5.961000000000013 2.38589 13.145 16.2 957.6 2.25807 -1.81427 -168.985
282 2016-02-12 08:38:36 40.3487802 115.7866181 5.861000000000047 2.69336 16.9089 16.2 957.6 2.26228 -1.41431 -166.704
283 2016-02-12 08:38:37 40.3487628 115.7866124 6.129000000000019 3.06392 23.064 16.2 957.4 2.26631 -1.84058 -163.542
284 2016-02-12 08:38:38 40.3487457 115.7866051 6.288000000000011 3.4603 28.1621 16.2 957.4 2.26631 -1.43673 -160.633
285 2016-02-12 08:38:39 40.3487288 115.7865968 6.198000000000036 3.43651 28.6348 16.2 957.4 2.26631 -1.62867 -159.419
286 2016-02-12 08:38:40 40.348712 115.7865883 5.991000000000042 2.75678 26.6074 16.2 957.6 2.26457 -0.846973 -159.113
287 2016-02-12 08:38:41 40.3486952 115.7865797 6.177000000000021 2.54112 26.0398 16.2 957.4 2.26195 -1.4228 -160.025
288 2016-02-12 08:38:42 40.3486785 115.7865715 6.125 2.77843 30.673 16.2 957.4 2.27229 -1.28339 -158.953
289 2016-02-12 08:38:43 40.3486617 115.7865631 5.989000000000033 2.89037 31.4589 16.2 957.6 2.26166 -1.72081 -159.983
290 2016-02-12 08:38:44 40.3486446 115.7865549 6.1059999999999945 3.4807 38.7283 16.2 957.4 2.2613 -0.817808 -159.645
291 2016-02-12 08:38:45 40.3486278 115.7865468 6.263000000000034 3.21584 39.218 16.2 957.4 2.25894 -1.0708 -159.434
292 2016-02-12 08:38:46 40.3486114 115.7865384 6.3799999999999955 3.20978 42.7982 16.3 957.4 2.24972 -1.54731 -156.522
293 2016-02-12 08:38:47 40.3485958 115.7865289 6.196000000000026 3.13252 47.861 16.3 957.4 2.25409 -2.09613 -150.524
294 2016-02-12 08:38:48 40.3485808 115.7865168 6.437000000000012 3.67395 54.5351 16.3 957.4 2.2518 -2.04851 -144.217
295 2016-02-12 08:38:49 40.348567 115.7865025 6.314999999999998 3.8837 60.8641 16.3 957.4 2.2588 -2.03042 -138.723
296 2016-02-12 08:38:50 40.3485541 115.7864867 6.55600000000004 4.24575 66.9797 16.3 957.4 2.25364 -2.63416 -133.698
297 2016-02-12 08:38:51 40.3485426 115.7864697 6.711000000000013 4.50037 69.3373 16.3 957.4 2.26174 -3.24088 -128.675
298 2016-02-12 08:38:52 40.3485322 115.7864511 6.847000000000037 4.77316 73.4454 16.3 957.4 2.26407 -3.37251 -123.113
299 2016-02-12 08:38:53 40.3485233 115.786431 6.723000000000013 5.25047 74.79 16.3 957.4 2.2571 -3.46872 -116.851
300 2016-02-12 08:38:54 40.3485158 115.7864097 6.77800000000002 5.24579 78.8962 16.3 957.4 2.26562 -2.75706 -110.608
301 2016-02-12 08:38:55 40.3485097 115.7863879 6.963000000000022 5.36328 78.6499 16.3 957.4 2.263 -3.80411 -109.608
302 2016-02-12 08:38:56 40.3485038 115.7863656 6.785000000000025 5.18284 77.9227 16.3 957.4 2.24412 -3.57529 -109.918
303 2016-02-12 08:38:57 40.3484977 115.7863432 6.955000000000041 5.49547 77.0321 16.3 957.4 2.25077 -3.53406 -110.109
304 2016-02-12 08:38:58 40.3484917 115.7863208 6.76400000000001 5.50554 76.9921 16.3 957.4 2.25282 -3.11968 -109.696
305 2016-02-12 08:38:59 40.3484855 115.7862986 7.1860000000000355 5.67789 76.452 16.3 957.4 2.25288 -3.84746 -109.962
306 2016-02-12 08:39:00 40.3484793 115.7862769 7.2760000000000105 5.58245 78.3723 16.3 957.4 2.25248 -4.04632 -109.703
307 2016-02-12 08:39:01 40.3484733 115.7862548 7.010000000000048 5.50281 81.2427 16.3 957.4 2.25681 -3.7117 -109.605
308 2016-02-12 08:39:02 40.3484675 115.7862318 6.583000000000027 5.4681 80.5694 16.3 957.4 2.25373 -2.64838 -110.026
309 2016-02-12 08:39:03 40.3484615 115.7862087 6.435000000000002 5.24186 80.0162 16.3 957.4 2.26402 -2.47181 -110.066
310 2016-02-12 08:39:04 40.3484553 115.7861861 6.744000000000028 4.78997 78.1177 16.3 957.4 2.25976 -3.00221 -110.003
311 2016-02-12 08:39:05 40.3484491 115.7861637 6.635000000000048 4.66952 79.3902 16.3 957.4 2.25965 -2.87573 -109.383
312 2016-02-12 08:39:06 40.3484432 115.7861416 6.846000000000004 4.6271 83.315 16.2 957.4 2.25455 -2.74948 -106.217
313 2016-02-12 08:39:07 40.3484387 115.7861197 7.13900000000001 4.8648 90.499 16.2 957.4 2.25685 -3.80011 -100.807
314 2016-02-12 08:39:08 40.348436 115.7860971 7.078000000000031 5.13107 93.7453 16.2 957.4 2.25624 -3.61118 -96.6337
315 2016-02-12 08:39:09 40.3484346 115.7860739 6.874000000000024 5.30274 96.2317 16.2 957.4 2.25331 -3.42438 -93.2439
316 2016-02-12 08:39:10 40.3484343 115.7860502 6.77800000000002 5.30424 98.1641 16.2 957.4 2.2591 -3.43879 -89.3696
317 2016-02-12 08:39:11 40.3484346 115.7860267 6.948000000000036 5.36689 101.168 16.2 957.4 2.26334 -3.13154 -85.9754
318 2016-02-12 08:39:12 40.3484361 115.7860039 6.992999999999995 5.36225 105.602 16.2 957.4 2.26374 -3.71979 -81.9432
319 2016-02-12 08:39:13 40.3484392 115.7859812 6.986000000000047 5.58163 111.056 16.2 957.4 2.27043 -3.86594 -76.8084
320 2016-02-12 08:39:14 40.3484453 115.7859542 7.071000000000026 5.59064 113.182 16.2 957.4 2.26144 -3.68614 -72.9019
321 2016-02-12 08:39:15 40.3484508 115.7859315 6.8180000000000405 5.49402 114.441 16.2 957.4 2.26241 -3.7118 -72.5991
322 2016-02-12 08:39:16 40.3484563 115.7859087 6.723000000000013 5.288 114.232 16.2 957.4 2.2694 -3.66929 -72.6022
323 2016-02-12 08:39:17 40.3484619 115.785886 6.861000000000047 5.0759 114.328 16.2 957.4 2.27796 -3.37821 -72.5735
324 2016-02-12 08:39:18 40.3484673 115.7858638 6.777000000000044 4.85226 114.202 16.2 957.4 2.2586 -3.65391 -72.617
325 2016-02-12 08:39:19 40.3484724 115.7858417 6.831000000000017 4.95735 114.591 16.2 957.4 2.26003 -3.9336 -72.5228
326 2016-02-12 08:39:20 40.3484777 115.7858195 6.79400000000004 5.19502 114.403 16.2 957.4 2.26938 -3.7664 -72.49
327 2016-02-12 08:39:21 40.348483 115.7857968 6.8910000000000196 5.40131 114.221 16.2 957.4 2.26292 -3.57338 -72.637
328 2016-02-12 08:39:22 40.3484882 115.785774 6.80800000000005 5.49249 113.991 16.2 957.4 2.25832 -3.62734 -72.9702
329 2016-02-12 08:39:23 40.3484933 115.7857514 6.855000000000018 5.30347 113.598 16.2 957.4 2.26829 -3.95096 -72.8731
330 2016-02-12 08:39:24 40.3484986 115.7857289 7.079000000000008 5.39845 115.741 16.2 957.4 2.26638 -3.72339 -70.6984
331 2016-02-12 08:39:25 40.3485052 115.7857071 6.997000000000014 5.59344 120.748 16.2 957.4 2.25883 -3.71214 -65.1554
332 2016-02-12 08:39:26 40.3485135 115.7856866 6.882000000000005 5.57928 126.78 16.2 957.4 2.27045 -3.56952 -59.0728
333 2016-02-12 08:39:27 40.3485232 115.7856676 7.5540000000000305 5.53672 130.762 16.2 957.4 2.26442 -4.75008 -53.7121
334 2016-02-12 08:39:28 40.3485341 115.7856494 7.011000000000024 5.59819 132.478 16.2 957.4 2.27287 -4.20102 -49.5037
335 2016-02-12 08:39:29 40.3485461 115.7856316 6.975999999999999 5.6987 136.872 16.1 957.4 2.27001 -3.76073 -44.3638
336 2016-02-12 08:39:30 40.3485592 115.7856157 6.80600000000004 5.66211 141.975 16.1 957.4 2.25656 -4.27646 -39.2167
337 2016-02-12 08:39:31 40.3485731 115.7856017 6.959000000000003 5.84401 147.888 16.1 957.4 2.26741 -4.22084 -33.5571
338 2016-02-12 08:39:32 40.348588 115.7855893 6.881000000000029 5.84942 153.684 16.1 957.4 2.26479 -4.14474 -27.6361
339 2016-02-12 08:39:33 40.348604 115.7855792 7.069000000000017 5.77161 153.734 16.1 957.4 2.25661 -4.20067 -25.4868
340 2016-02-12 08:39:34 40.3486205 115.7855695 6.948000000000036 5.68293 151.175 16.1 957.4 2.26653 -4.28749 -25.5627
341 2016-02-12 08:39:35 40.3486369 115.7855593 6.831999999999994 5.59499 149.507 16.1 957.4 2.26059 -3.60083 -25.7786
342 2016-02-12 08:39:36 40.3486532 115.785549 6.910000000000025 5.34526 148.245 16.1 957.4 2.25904 -3.79517 -25.4626
343 2016-02-12 08:39:37 40.3486694 115.7855391 6.90300000000002 5.2722 148.018 16.1 957.4 2.24588 -4.47698 -26.0671
344 2016-02-12 08:39:38 40.3486856 115.7855286 6.662000000000035 5.58787 149.531 16.1 957.4 2.26247 -3.74773 -25.3043
345 2016-02-12 08:39:39 40.348702 115.7855183 6.588000000000022 5.58677 149.414 16.1 957.4 2.2546 -3.41345 -25.3933
346 2016-02-12 08:39:40 40.3487186 115.7855084 6.819000000000017 5.39394 150.467 16.1 957.4 2.26018 -3.45871 -25.8609
347 2016-02-12 08:39:41 40.3487348 115.785498 6.869000000000028 5.13558 149.501 16.1 957.4 2.25899 -3.54752 -25.3197
348 2016-02-12 08:39:42 40.3487508 115.7854881 7.076999999999998 5.12994 151.902 16.0 957.4 2.2604 -3.27375 -23.0354
349 2016-02-12 08:39:43 40.348767 115.7854795 7.107000000000028 5.24712 156.111 16.0 957.4 2.25978 -4.17538 -19.0296
350 2016-02-12 08:39:44 40.3487838 115.7854726 7.342000000000041 5.14911 158.067 16.0 957.4 2.26895 -3.91688 -14.9458
351 2016-02-12 08:39:45 40.3488012 115.7854673 7.123000000000047 5.12797 160.258 16.0 957.4 2.25685 -3.97569 -12.4655
352 2016-02-12 08:39:46 40.3488187 115.7854626 7.0470000000000255 5.25077 161.458 16.0 957.4 2.2575 -3.93482 -9.47375
353 2016-02-12 08:39:47 40.3488361 115.7854589 6.831000000000017 5.34247 163.638 16.0 957.4 2.2747 -3.97845 -6.77187
354 2016-02-12 08:39:48 40.3488535 115.7854563 6.91700000000003 5.35046 168.762 16.0 957.4 2.2638 -4.43388 -3.3938
355 2016-02-12 08:39:49 40.3488712 115.7854556 7.05800000000005 5.36638 172.552 16.0 957.4 2.24989 -4.01909 0.499612
356 2016-02-12 08:39:50 40.3488894 115.7854567 6.927999999999997 5.18338 176.719 16.0 957.4 2.25543 -2.9186 4.27917
357 2016-02-12 08:39:51 40.3489075 115.7854591 6.824000000000012 4.74102 174.68 16.0 957.4 2.26294 -3.10757 5.12577
358 2016-02-12 08:39:52 40.3489253 115.7854614 6.846000000000004 4.61108 173.089 16.0 957.4 2.26023 -3.50273 5.24859
359 2016-02-12 08:39:53 40.3489432 115.7854633 6.754000000000019 4.60728 171.857 16.0 957.4 2.24849 -3.4541 5.02424
360 2016-02-12 08:39:54 40.348961 115.7854649 6.802000000000021 4.80725 173.53 16.0 957.4 2.24994 -3.31187 5.23906
361 2016-02-12 08:39:55 40.3489786 115.7854669 6.7690000000000055 4.84929 175.141 16.0 957.4 2.26774 -3.80584 4.93247
362 2016-02-12 08:39:56 40.3489961 115.7854684 6.984000000000037 4.82154 177.285 16.0 957.4 2.25052 -4.3044 6.02525
363 2016-02-12 08:39:57 40.3490136 115.7854712 7.0750000000000455 4.97235 176.681 16.0 957.4 2.26103 -4.44092 4.73105
364 2016-02-12 08:39:58 40.3490352 115.7854737 7.221000000000004 5.17525 176.871 16.0 957.4 2.24897 -4.50248 5.03347
365 2016-02-12 08:39:59 40.3490496 115.7854757 7.2830000000000155 5.31328 175.68 15.9 957.4 2.2604 -4.74577 5.08683
366 2016-02-12 08:40:00 40.3490715 115.7854787 6.9150000000000205 5.36721 173.39 15.9 957.4 2.25116 -3.63533 5.45957
367 2016-02-12 08:40:01 40.3490892 115.7854806 7.02800000000002 5.49745 171.838 15.9 957.4 2.24886 -5.20438 5.31366
368 2016-02-12 08:40:02 40.3491065 115.7854825 7.034000000000049 4.96294 169.028 15.9 957.4 2.25694 8.55605 4.86752
369 2016-02-12 08:40:03 40.3491136 115.7854833 7.170000000000016 3.77454 166.109 15.9 957.4 2.2609 -2.98443 5.3243
370 2016-02-12 08:40:04 40.349114 115.7854833 6.729000000000042 2.51774 161.1 15.9 957.4 2.25686 -2.8505 5.30476
371 2016-02-12 08:40:05 40.3491134 115.7854828 6.692000000000007 2.18392 157.804 15.9 957.4 2.255 -3.45238 5.31065
372 2016-02-12 08:40:06 40.3491132 115.7854827 6.604000000000042 1.60109 157.059 15.9 957.4 2.25357 -2.80026 5.5161
373 2016-02-12 08:40:07 40.3491134 115.7854827 6.537000000000035 2.12836 156.218 15.9 957.4 2.25833 -2.45733 5.39147
374 2016-02-12 08:40:08 40.3491137 115.7854829 6.403999999999996 2.12331 158.872 15.9 957.4 2.25188 -2.14385 5.2223
375 2016-02-12 08:40:09 40.3491142 115.7854831 6.421000000000049 1.8301 160.043 15.9 957.4 2.25406 -2.07424 4.97781
376 2016-02-12 08:40:10 40.3491147 115.785483 6.369000000000028 1.81565 164.795 15.9 957.4 2.25066 -2.04528 5.5712
377 2016-02-12 08:40:11 40.349115 115.785483 6.395000000000039 1.20916 168.073 15.9 957.4 2.25142 -2.12568 5.6004
378 2016-02-12 08:40:12 40.3491152 115.785483 6.479000000000042 0.923121 169.145 15.9 957.4 2.25772 -2.39996 5.49499
379 2016-02-12 08:40:13 40.3491156 115.7854834 6.295000000000016 0.112622 176.925 15.9 957.4 2.2419 -0.992479 5.52595
380 2016-02-12 08:40:14 40.3491156 115.7854835 5.983000000000004 0.104385 137.479 15.9 957.6 2.24902 -2.09931 4.83266
381 2016-02-12 08:40:15 40.3491156 115.7854831 6.322000000000003 0.0972996 135.981 15.9 957.4 2.25507 -2.44217 5.66033
382 2016-02-12 08:40:16 40.3491157 115.785483 6.293000000000006 0.399473 144.672 15.9 957.4 2.24642 -1.95636 5.97701
383 2016-02-12 08:40:17 40.3491159 115.7854832 6.54200000000003 0.419162 134.864 15.9 957.4 2.25464 -2.12978 4.8956
384 2016-02-12 08:40:18 40.3491159 115.7854832 6.412000000000035 0.0974758 162.941 15.9 957.4 2.25094 -2.48262 5.51442
385 2016-02-12 08:40:19 40.349116 115.7854833 6.161000000000001 0.109608 160.361 15.9 957.4 2.25091 -1.41836 5.54454
386 2016-02-12 08:40:20 40.3491161 115.7854831 6.199000000000012 0.0171219 103.985 15.9 957.4 2.24909 -1.11168 5.4494
387 2016-02-12 08:40:21 40.349116 115.7854829 6.218000000000018 0.0288269 128.137 15.9 957.4 2.25383 -1.09086 5.29294
388 2016-02-12 08:40:22 40.349116 115.7854829 6.281000000000006 0.0365605 136.308 15.9 957.4 2.25341 -1.30006 5.35584
389 2016-02-12 08:40:23 40.349116 115.7854829 6.138000000000034 0.300536 142.642 15.9 957.4 2.24777 -1.31523 5.10688
390 2016-02-12 08:40:24 40.3491159 115.7854831 6.272000000000048 0.362359 104.119 15.9 957.4 2.2515 -1.26287 5.34579
391 2016-02-12 08:40:25 40.3491158 115.7854836 6.330000000000041 0.57932 67.1366 15.9 957.4 2.25599 -1.2537 5.10477
392 2016-02-12 08:40:26 40.349116 115.7854837 6.2590000000000146 0.293271 61.2633 15.9 957.4 2.25032 -1.35474 4.62019
393 2016-02-12 08:40:27 40.3491159 115.7854839 6.537000000000035 1.43408 87.8411 15.9 957.4 2.24641 -1.43189 4.81176
394 2016-02-12 08:40:28 40.3491158 115.7854845 7.9360000000000355 2.6621 90.2237 15.9 957.4 2.25034 -1.61754 4.72443
395 2016-02-12 08:40:29 40.349116 115.7854846 10.175000000000011 1.31573 89.1393 16.0 957.6 2.24564 -1.20717 4.9345
396 2016-02-12 08:40:30 40.3491154 115.7854833 11.519000000000005 0.487783 84.9451 16.0 957.6 2.23793 1.226 32.3446
397 2016-02-12 08:40:31 40.3491146 115.7854801 11.199000000000012 0.888404 113.077 16.0 957.6 2.24013 -0.910583 49.0509
398 2016-02-12 08:40:32 40.3491176 115.7854848 11.338000000000022 1.21106 161.686 16.0 957.6 2.24855 -8.71139 49.124
399 2016-02-12 08:40:33 40.349127 115.7854984 11.410000000000025 1.15788 160.732 16.0 957.6 2.24702 2.53409 49.1037
400 2016-02-12 08:40:34 40.3491327 115.785507 11.30600000000004 1.57306 101.28 16.0 957.6 2.23904 3.0513 47.7375
401 2016-02-12 08:40:35 40.3491341 115.7855092 11.441000000000031 1.65924 120.583 16.0 957.6 2.23278 -11.256 47.7951
402 2016-02-12 08:40:36 40.3491421 115.7855205 11.745000000000005 2.09369 165.994 16.0 957.6 2.25014 -5.38932 47.3602
403 2016-02-12 08:40:37 40.3491545 115.7855384 11.939999999999998 2.19563 170.682 16.0 957.6 2.25111 -3.70094 47.3836
404 2016-02-12 08:40:38 40.3491676 115.7855572 12.343999999999994 2.72588 175.629 16.0 957.4 2.24778 -3.39111 47.5684
405 2016-02-12 08:40:39 40.3491805 115.7855757 12.349000000000046 3.77058 170.431 16.0 957.4 2.23919 -2.92421 47.3679
406 2016-02-12 08:40:40 40.3491932 115.7855932 12.30400000000003 4.32723 164.713 16.0 957.4 2.24849 -3.69776 47.2196
407 2016-02-12 08:40:41 40.3492058 115.7856107 12.257000000000005 4.97482 149.719 16.0 957.4 2.23899 -4.2628 46.9518
408 2016-02-12 08:40:42 40.3492184 115.7856285 12.064999999999998 5.01454 148.244 16.0 957.4 2.24654 -3.29362 47.9102
409 2016-02-12 08:40:43 40.3492309 115.7856463 11.847000000000037 4.75528 148.534 16.0 957.6 2.2461 -2.87623 47.2497
410 2016-02-12 08:40:44 40.3492429 115.7856634 11.926000000000045 4.45324 145.688 16.0 957.6 2.24807 -3.24547 50.6289
411 2016-02-12 08:40:45 40.3492538 115.7856819 11.890000000000043 4.37085 139.85 16.0 957.6 2.24435 -2.29374 55.1856
412 2016-02-12 08:40:46 40.3492636 115.7857015 11.858000000000004 4.45991 136.808 16.0 957.6 2.23915 -2.55544 58.6457
413 2016-02-12 08:40:47 40.3492726 115.7857216 11.834000000000003 4.44533 135.258 16.0 957.6 2.25354 -2.42264 61.5678
414 2016-02-12 08:40:48 40.3492809 115.7857425 11.573000000000036 4.17545 135.351 16.0 957.6 2.2454 -2.13607 64.4989
415 2016-02-12 08:40:49 40.3492883 115.7857639 11.456000000000017 3.50478 129.539 16.0 957.6 2.23091 -1.86106 68.0806
416 2016-02-12 08:40:50 40.3492945 115.7857856 11.674000000000035 3.04936 123.522 16.0 957.6 2.24878 -2.12556 72.5683
417 2016-02-12 08:40:51 40.3492995 115.7858078 11.607000000000028 2.59356 118.042 16.0 957.6 2.24837 -2.43165 74.4098
418 2016-02-12 08:40:52 40.349304 115.7858305 11.578000000000031 2.53347 125.879 16.0 957.6 2.24868 -2.31417 74.0187
419 2016-02-12 08:40:54 40.3493085 115.7858534 11.64100000000002 2.66835 133.005 16.0 957.6 2.25345 -2.44876 73.9301
420 2016-02-12 08:40:55 40.3493133 115.7858761 11.571000000000026 2.67835 132.957 16.0 957.6 2.24898 -2.21838 74.0699
421 2016-02-12 08:40:56 40.3493182 115.7858987 11.422000000000025 2.77779 137.606 16.0 957.6 2.24687 -2.05583 74.0956
422 2016-02-12 08:40:57 40.3493232 115.7859214 11.383000000000038 2.65526 125.47 16.0 957.6 2.25382 -2.1098 73.9022
423 2016-02-12 08:40:58 40.3493284 115.7859437 11.393000000000029 2.57385 121.79 16.0 957.6 2.25263 -2.48862 74.428
424 2016-02-12 08:40:59 40.3493328 115.7859659 11.778999999999996 2.60091 118.797 16.0 957.6 2.24775 -2.6614 76.9316
425 2016-02-12 08:41:00 40.3493363 115.7859886 11.846000000000004 2.80531 113.214 16.0 957.6 2.25006 -2.35789 81.2004
426 2016-02-12 08:41:01 40.3493386 115.7860116 11.75200000000001 3.46673 114.085 16.0 957.6 2.2521 -2.83111 84.5953
427 2016-02-12 08:41:02 40.3493399 115.7860352 11.573000000000036 3.45173 111.082 16.0 957.6 2.24462 -2.19087 88.0719
428 2016-02-12 08:41:03 40.3493402 115.7860585 11.668000000000006 3.17838 106.4 16.0 957.6 2.23597 -2.32365 91.6851
429 2016-02-12 08:41:04 40.3493394 115.7860821 11.456999999999994 2.92245 104.091 16.0 957.6 2.25143 -1.39402 94.5082
430 2016-02-12 08:41:05 40.3493376 115.7861056 11.509000000000015 2.69757 107.508 16.0 957.6 2.24626 -1.14534 97.7257
431 2016-02-12 08:41:06 40.349335 115.786129 11.551000000000045 2.14221 105.163 16.0 957.6 2.24878 -1.12488 101.724
432 2016-02-12 08:41:07 40.3493308 115.7861515 11.583000000000027 1.70315 97.0246 16.0 957.6 2.24965 -1.2808 105.324
433 2016-02-12 08:41:08 40.3493256 115.7861737 11.629999999999995 1.73263 82.1027 16.0 957.6 2.24099 -1.10128 106.318
434 2016-02-12 08:41:09 40.3493203 115.786196 11.79000000000002 1.88123 77.929 16.0 957.6 2.25065 -0.890223 106.882
435 2016-02-12 08:41:10 40.3493151 115.7862185 11.629999999999995 2.02174 72.4556 16.0 957.6 2.24402 -1.06764 106.757
436 2016-02-12 08:41:11 40.3493095 115.7862408 11.56800000000004 1.92404 75.0366 16.0 957.6 2.25262 -1.81658 106.7
437 2016-02-12 08:41:12 40.3493042 115.7862632 11.723000000000013 1.96386 76.6269 16.1 957.6 2.24628 -2.08718 106.681
438 2016-02-12 08:41:13 40.3492993 115.7862859 11.694000000000017 1.97875 76.6054 16.1 957.6 2.24301 -1.62918 106.355
439 2016-02-12 08:41:14 40.3492944 115.7863083 11.80800000000005 2.00308 72.8553 16.1 957.6 2.24278 -1.89877 107.29
440 2016-02-12 08:41:15 40.3492889 115.7863306 11.740000000000009 2.16399 82.2897 16.1 957.6 2.24469 -1.95941 107.744
441 2016-02-12 08:41:16 40.349282 115.7863579 11.583000000000027 2.06573 79.7034 16.1 957.6 2.24813 -1.54695 110.369
442 2016-02-12 08:41:17 40.3492752 115.7863801 11.729000000000042 1.96264 82.2375 16.1 957.6 2.24149 -1.13449 115.571
443 2016-02-12 08:41:18 40.349269 115.7863971 11.831999999999994 1.75547 77.7442 16.1 957.6 2.2488 -0.483331 119.086
444 2016-02-12 08:41:19 40.3492581 115.7864217 11.521000000000015 1.54649 80.1118 16.1 957.6 2.24992 -0.430019 121.889
445 2016-02-12 08:41:20 40.3492484 115.7864414 11.724000000000046 1.33618 90.5358 16.1 957.6 2.24614 -0.160765 124.514
446 2016-02-12 08:41:21 40.3492379 115.7864599 11.656000000000006 1.45789 75.7241 16.1 957.6 2.24723 -0.584383 129.253
447 2016-02-12 08:41:22 40.3492265 115.7864776 11.586000000000013 1.52183 64.4082 16.1 957.6 2.2461 -0.1055 133.895
448 2016-02-12 08:41:23 40.3492142 115.7864946 11.551000000000045 1.41725 53.5575 16.1 957.6 2.24917 -0.06657 133.811
449 2016-02-12 08:41:24 40.3492018 115.786511 11.67900000000003 1.96325 45.1024 16.1 957.6 2.24306 -0.546846 133.629
450 2016-02-12 08:41:25 40.3491892 115.7865273 11.583000000000027 1.89267 44.8856 16.1 957.6 2.25231 -0.522077 133.854
451 2016-02-12 08:41:26 40.3491766 115.786544 11.583000000000027 1.88507 45.3735 16.1 957.6 2.25312 -0.6115120000000001 134.018
452 2016-02-12 08:41:27 40.349164 115.7865603 11.56800000000004 1.90691 44.2069 16.1 957.6 2.24901 -0.704764 137.995
453 2016-02-12 08:41:28 40.3491509 115.7865759 11.733000000000004 1.89895 34.7881 16.1 957.6 2.2386 0.216962 144.763
454 2016-02-12 08:41:29 40.3491363 115.7865883 12.136000000000024 1.57389 21.6126 16.1 957.4 2.25495 -0.546539 150.518
455 2016-02-12 08:41:30 40.3491207 115.7865983 12.105999999999995 1.35377 6.14142 16.1 957.4 2.25067 -0.483964 155.45
456 2016-02-12 08:41:31 40.3491041 115.7866067 11.953000000000031 1.48538 7.6301 16.1 957.6 2.25743 0.186806 161.625
457 2016-02-12 08:41:32 40.349087 115.7866129 12.30800000000005 1.43146 25.3402 16.1 957.4 2.25932 -1.17416 169.539
458 2016-02-12 08:41:33 40.3490693 115.7866169 12.262 1.67297 11.2128 16.1 957.4 2.24673 -0.856737 175.334
459 2016-02-12 08:41:34 40.3490516 115.7866188 12.27600000000001 1.88287 5.05985 16.1 957.4 2.23945 -1.40952 175.648
460 2016-02-12 08:41:35 40.349034 115.7866202 12.26600000000002 2.07013 7.49265 16.2 957.4 2.25005 -1.36203 175.821
461 2016-02-12 08:41:36 40.3490162 115.7866215 12.102000000000032 2.16284 5.99243 16.2 957.4 2.24761 -1.28881 175.884
462 2016-02-12 08:41:37 40.3489984 115.786623 12.342000000000041 2.62051 11.9578 16.2 957.4 2.2545 -1.72705 176.135
463 2016-02-12 08:41:38 40.3489803 115.7866248 12.266999999999996 2.80948 9.05194 16.2 957.4 2.24654 -1.73863 175.918
464 2016-02-12 08:41:39 40.3489624 115.7866263 12.15500000000003 2.79103 5.93186 16.2 957.4 2.24162 -1.93178 175.373
465 2016-02-12 08:41:40 40.3489442 115.7866283 12.194000000000017 2.98124 7.96713 16.2 957.4 2.23972 -1.38345 175.634
466 2016-02-12 08:41:41 40.3489261 115.7866302 12.290999999999997 2.76977 6.80938 16.2 957.4 2.23927 -1.48399 175.852
467 2016-02-12 08:41:42 40.348908 115.7866319 12.145000000000039 2.88923 11.1758 16.2 957.4 2.24577 -1.11357 175.647
468 2016-02-12 08:41:43 40.34889 115.7866334 12.115000000000009 2.73138 15.2008 16.2 957.4 2.2535 -1.25101 178.042
469 2016-02-12 08:41:44 40.3488722 115.7866338 12.066000000000031 2.96751 22.2279 16.2 957.4 2.24615 -1.35349 -178.621
470 2016-02-12 08:41:45 40.3488544 115.7866327 12.17100000000005 3.10965 27.6051 16.2 957.4 2.25523 -1.46058 -175.496
471 2016-02-12 08:41:46 40.3488367 115.7866304 12.064000000000021 2.92633 28.5539 16.2 957.4 2.24891 -1.73632 -173.742
472 2016-02-12 08:41:47 40.3488192 115.7866273 12.215000000000032 2.91376 27.4537 16.2 957.4 2.25825 -2.3877 -171.862
473 2016-02-12 08:41:48 40.3488017 115.7866234 12.088999999999999 3.08075 27.0256 16.2 957.4 2.24402 -1.70543 -170.067
474 2016-02-12 08:41:49 40.3487842 115.7866186 12.199000000000012 3.22416 29.298 16.3 957.4 2.26024 -1.40647 -166.772
475 2016-02-12 08:41:50 40.3487669 115.7866126 12.105999999999995 3.04744 30.399 16.3 957.4 2.26284 -1.90689 -163.401
476 2016-02-12 08:41:51 40.34875 115.7866053 12.230999999999995 3.03816 32.1537 16.3 957.4 2.25274 -2.12911 -160.487
477 2016-02-12 08:41:52 40.3487332 115.7865977 12.277000000000044 3.16828 36.9141 16.3 957.4 2.24902 -2.42806 -158.691
478 2016-02-12 08:41:53 40.3487164 115.7865891 12.119000000000028 3.51183 36.1496 16.3 957.4 2.25103 -2.7569 -159.977
479 2016-02-12 08:41:54 40.3486995 115.7865807 12.200000000000045 3.67923 34.0202 16.3 957.4 2.25266 -2.03718 -159.794
480 2016-02-12 08:41:55 40.3486826 115.7865724 12.234000000000037 3.99466 32.2461 16.3 957.4 2.25307 -2.50656 -159.647
481 2016-02-12 08:41:56 40.3486656 115.7865644 12.124000000000024 3.87245 32.552 16.3 957.4 2.25371 -2.16503 -159.25
482 2016-02-12 08:41:57 40.3486488 115.7865561 12.090000000000032 4.08144 33.5234 16.3 957.4 2.24347 -2.05622 -159.351
483 2016-02-12 08:41:58 40.3486319 115.7865478 12.209000000000003 3.86491 36.1923 16.3 957.4 2.24522 -1.63832 -159.568
484 2016-02-12 08:41:59 40.348615 115.7865392 12.052000000000021 3.72907 37.497 16.3 957.4 2.24749 -1.51081 -158.014
485 2016-02-12 08:42:00 40.3485989 115.7865303 12.175000000000011 3.44141 42.7996 16.3 957.4 2.24907 -1.9916 -152.302
486 2016-02-12 08:42:01 40.3485838 115.7865188 12.503000000000043 3.81648 51.5505 16.3 957.4 2.24449 -2.30392 -145.352
487 2016-02-12 08:42:02 40.3485697 115.7865051 12.378000000000043 4.09751 56.1889 16.3 957.4 2.24475 -3.35498 -140.287
488 2016-02-12 08:42:03 40.348554 115.7864864 12.354000000000042 4.45431 63.4819 16.3 957.4 2.25055 -2.78677 -133.264
489 2016-02-12 08:42:04 40.3485421 115.7864686 12.239000000000033 4.57333 67.1847 16.3 957.4 2.25146 -2.48321 -128.375
490 2016-02-12 08:42:05 40.3485336 115.7864536 12.379999999999995 4.48019 71.2003 16.3 957.4 2.24778 -2.34836 -123.58
491 2016-02-12 08:42:06 40.348523 115.7864295 12.398000000000025 4.48081 77.9232 16.3 957.4 2.24845 -2.83183 -116.547
492 2016-02-12 08:42:07 40.3485159 115.7864082 12.41500000000002 4.49352 80.9574 16.3 957.4 2.25643 -2.8192 -110.823
493 2016-02-12 08:42:08 40.3485099 115.7863862 12.507000000000005 4.71163 79.3181 16.3 957.4 2.25778 -3.08629 -109.918
494 2016-02-12 08:42:09 40.348504 115.7863639 12.674000000000035 4.83949 77.9107 16.3 957.4 2.24253 -2.90956 -109.746
495 2016-02-12 08:42:10 40.348498 115.7863416 12.966000000000008 5.05952 75.906 16.3 957.4 2.24613 -2.97764 -110.009
496 2016-02-12 08:42:11 40.3484919 115.7863189 12.289000000000044 4.99548 74.3886 16.3 957.4 2.24257 -2.69509 -109.879
497 2016-02-12 08:42:12 40.3484856 115.7862963 12.305000000000007 4.86027 75.585 16.3 957.4 2.24794 -2.39785 -109.656
498 2016-02-12 08:42:13 40.3484795 115.786274 12.30600000000004 4.63504 75.6022 16.3 957.4 2.25423 -2.3631 -109.497
499 2016-02-12 08:42:14 40.3484733 115.7862519 12.319000000000017 4.62832 77.8567 16.3 957.4 2.24955 -2.26553 -109.463
500 2016-02-12 08:42:15 40.3484674 115.7862297 12.467000000000041 4.51333 78.3431 16.3 957.4 2.24946 -2.37776 -110.25
501 2016-02-12 08:42:16 40.3484612 115.7862076 12.367000000000019 4.41789 79.0752 16.3 957.4 2.25625 -2.54596 -110.091
502 2016-02-12 08:42:17 40.3484548 115.7861855 12.536000000000001 4.47514 81.1023 16.3 957.4 2.24774 -2.51819 -109.937
503 2016-02-12 08:42:18 40.3484486 115.7861638 12.861000000000047 4.55631 82.4619 16.3 957.4 2.24383 -2.94212 -109.487
504 2016-02-12 08:42:19 40.3484429 115.7861421 12.637 4.85356 87.9828 16.3 957.4 2.25176 -3.28014 -106.279
505 2016-02-12 08:42:20 40.3484385 115.78612 12.87700000000001 5.05794 92.5173 16.3 957.4 2.25419 -3.86801 -101.332
506 2016-02-12 08:42:21 40.3484355 115.7860973 12.540999999999997 5.22229 96.0485 16.3 957.4 2.26133 -3.48247 -96.9957
507 2016-02-12 08:42:22 40.3484339 115.786074 12.859000000000037 5.29359 99.1907 16.3 957.4 2.25554 -3.74325 -93.293
508 2016-02-12 08:42:23 40.3484335 115.7860508 12.79400000000004 5.51611 102.248 16.3 957.4 2.25186 -3.60425 -89.6605
509 2016-02-12 08:42:24 40.3484341 115.7860275 12.837000000000046 5.91545 104.712 16.3 957.4 2.26173 -4.32424 -86.4569
510 2016-02-12 08:42:25 40.3484362 115.7860043 12.738 5.97849 108.205 16.3 957.4 2.25334 -4.14827 -81.8178
511 2016-02-12 08:42:26 40.3484397 115.7859813 12.995000000000005 5.95724 109.774 16.3 957.4 2.26212 -3.98325 -77.084
512 2016-02-12 08:42:27 40.3484442 115.7859587 13.02600000000001 5.88203 112.074 16.3 957.4 2.26216 -3.93422 -73.0804
513 2016-02-12 08:42:28 40.3484496 115.7859361 12.66700000000003 5.89762 112.488 16.3 957.4 2.25082 -3.98341 -72.3455
514 2016-02-12 08:42:29 40.3484555 115.7859136 13.284000000000049 5.88128 111.104 16.3 957.4 2.25202 -4.08997 -73.1645
515 2016-02-12 08:42:30 40.3484603 115.7858911 13.001000000000033 5.88179 112.502 16.3 957.4 2.25494 -4.32926 -72.1189
516 2016-02-12 08:42:31 40.3484659 115.785869 12.974000000000046 5.89474 113.961 16.3 957.4 2.2582 -4.21522 -72.1881
517 2016-02-12 08:42:32 40.3484716 115.7858467 13.950000000000045 5.89713 112.242 16.3 957.4 2.25086 -4.48302 -72.4782
518 2016-02-12 08:42:33 40.348477 115.785824 12.950000000000045 5.83897 111.227 16.3 957.4 2.25219 -3.79417 -72.9491
519 2016-02-12 08:42:34 40.3484819 115.7858011 13.550000000000011 5.70104 110.514 16.3 957.4 2.25342 -4.27485 -72.8564
520 2016-02-12 08:42:35 40.3484869 115.7857784 13.302999999999997 5.65056 112.288 16.2 957.4 2.25351 -4.61801 -72.341
521 2016-02-12 08:42:36 40.3484922 115.7857551 12.936000000000035 5.64385 114.009 16.2 957.4 2.25632 -3.38854 -72.9091
522 2016-02-12 08:42:37 40.348498 115.7857323 12.79000000000002 5.63199 115.023 16.2 957.4 2.25322 -3.08252 -71.8235
523 2016-02-12 08:42:38 40.3485042 115.7857104 12.858000000000004 5.36999 121.775 16.2 957.4 2.25358 -3.24984 -65.9687
524 2016-02-12 08:42:39 40.3485119 115.78569 12.900000000000034 5.15898 126.711 16.2 957.4 2.26002 -3.20228 -60.2979
525 2016-02-12 08:42:40 40.348521 115.7856707 13.067000000000007 5.14989 132.227 16.2 957.4 2.25982 -3.62738 -54.9838
526 2016-02-12 08:42:41 40.3485316 115.7856526 13.647000000000048 5.22281 136.78 16.2 957.4 2.26323 -4.14084 -49.9837
527 2016-02-12 08:42:42 40.3485433 115.7856361 13.871000000000038 5.67075 139.828 16.2 957.4 2.25176 -4.97773 -45.5356
528 2016-02-12 08:42:43 40.3485561 115.7856201 12.992000000000019 5.82711 142.777 16.2 957.4 2.26061 -4.46511 -40.6979
529 2016-02-12 08:42:44 40.3485702 115.7856055 12.66700000000003 5.82758 147.255 16.2 957.4 2.26035 -3.8026 -34.6946
530 2016-02-12 08:42:45 40.3485853 115.785593 12.718999999999994 5.62707 149.964 16.2 957.4 2.24634 -4.16698 -28.7379
531 2016-02-12 08:42:46 40.3486012 115.7855819 12.712000000000046 5.40462 152.98 16.2 957.4 2.25537 -3.65881 -25.8209
532 2016-02-12 08:42:47 40.3486175 115.7855715 12.614000000000033 5.40776 154.124 16.2 957.4 2.24852 -3.58218 -25.511
533 2016-02-12 08:42:48 40.348634 115.7855611 12.459000000000003 5.20386 155.024 16.2 957.4 2.25714 -3.00576 -25.8377
534 2016-02-12 08:42:49 40.3486501 115.7855508 12.467000000000041 5.17858 156.915 16.2 957.4 2.26037 -3.62848 -25.7774
535 2016-02-12 08:42:50 40.3486696 115.7855384 12.532000000000039 5.27778 157.696 16.2 957.4 2.25554 -3.50805 -25.7918
536 2016-02-12 08:42:51 40.3486825 115.7855303 12.616000000000042 5.37135 158.794 16.2 957.4 2.25686 -3.56731 -25.5099
537 2016-02-12 08:42:52 40.3487016 115.7855185 12.533000000000015 5.46752 156.941 16.2 957.4 2.25935 -3.98915 -25.6481
538 2016-02-12 08:42:53 40.3487176 115.7855085 12.420000000000016 5.58741 155.836 16.2 957.4 2.26681 -4.31272 -25.4288
539 2016-02-12 08:42:54 40.3487336 115.7854986 12.732000000000028 5.78335 155.823 16.2 957.4 2.25226 -4.67656 -25.4368
540 2016-02-12 08:42:55 40.3487496 115.785489 12.701999999999998 5.92013 158.796 16.1 957.4 2.25212 -4.80537 -23.1046
541 2016-02-12 08:42:56 40.348766 115.78548 12.518000000000029 5.9415 162.588 16.1 957.4 2.24934 -4.43397 -19.1058
542 2016-02-12 08:42:57 40.348783 115.7854727 12.524000000000001 5.72876 166.81 16.1 957.4 2.25649 -4.15858 -15.3635
543 2016-02-12 08:42:58 40.3488007 115.7854667 12.446000000000026 5.43129 168.769 16.1 957.4 2.25655 -3.56822 -12.2917
544 2016-02-12 08:42:59 40.3488186 115.7854623 12.591000000000008 5.38271 169.969 16.1 957.4 2.25312 -3.63613 -9.66924
545 2016-02-12 08:43:00 40.3488359 115.7854588 12.819000000000017 5.39655 172.218 16.1 957.4 2.25178 -4.54191 -6.79331
546 2016-02-12 08:43:01 40.3488535 115.7854562 12.608000000000004 5.58193 174.925 16.1 957.4 2.25727 -4.15431 -3.67836
547 2016-02-12 08:43:02 40.3488709 115.7854557 12.687000000000012 5.78932 176.998 16.1 957.4 2.24647 -4.26279 0.864772
548 2016-02-12 08:43:03 40.3488887 115.7854572 12.700000000000045 5.80957 176.641 16.1 957.4 2.24594 -4.19075 4.37661
549 2016-02-12 08:43:04 40.3489065 115.7854597 12.713999999999999 5.79471 176.923 16.1 957.4 2.25494 -4.33135 5.51263
550 2016-02-12 08:43:05 40.3489243 115.7854622 12.805000000000007 5.76599 174.367 16.1 957.4 2.25948 -4.54469 5.39902
551 2016-02-12 08:43:06 40.3489424 115.7854643 12.515000000000043 5.66438 170.978 16.1 957.4 2.24338 -3.95422 5.18129
552 2016-02-12 08:43:07 40.3489605 115.7854662 12.734000000000037 5.51594 168.338 16.1 957.4 2.25627 -3.94131 5.09212
553 2016-02-12 08:43:08 40.3489785 115.7854682 12.634000000000015 5.26331 167.49 16.0 957.4 2.25091 -3.82072 5.21668
554 2016-02-12 08:43:09 40.3489964 115.7854699 11.968000000000018 5.3484 169.105 16.0 957.6 2.253 -3.64647 5.05816
555 2016-02-12 08:43:10 40.3490145 115.7854713 12.449000000000012 5.24774 170.138 16.0 957.4 2.25451 -3.90744 4.97669
556 2016-02-12 08:43:11 40.3490323 115.7854731 12.962000000000046 5.00866 172.165 16.0 957.4 2.25349 -4.42495 5.03938
557 2016-02-12 08:43:12 40.3490499 115.7854749 12.913000000000011 5.17607 173.761 16.0 957.4 2.25456 -3.96802 4.88758
558 2016-02-12 08:43:13 40.3490678 115.7854774 12.772000000000048 5.17531 173.632 16.0 957.4 2.24864 -4.1331 5.31392
559 2016-02-12 08:43:14 40.3490859 115.7854799 12.660000000000025 5.33766 172.301 16.0 957.4 2.24415 -3.63245 5.13994
560 2016-02-12 08:43:15 40.3491037 115.7854819 12.688000000000045 5.06418 172.85 16.0 957.4 2.25334 3.77341 5.43588
561 2016-02-12 08:43:16 40.3491139 115.7854834 12.534000000000049 3.21808 163.848 16.0 957.4 2.25053 -3.0238 4.27478
562 2016-02-12 08:43:17 40.3491151 115.7854831 12.472000000000037 2.30783 161.518 16.0 957.4 2.25659 -2.5161 4.4831
563 2016-02-12 08:43:18 40.3491145 115.7854826 12.115000000000009 1.10665 156.651 16.0 957.4 2.25019 -3.33712 3.89
564 2016-02-12 08:43:19 40.3491143 115.7854821 12.076000000000022 0.729867 160.824 16.0 957.4 2.25651 -2.90574 4.24684
565 2016-02-12 08:43:20 40.3491143 115.785482 12.163000000000011 0.916749 168.514 16.0 957.4 2.24599 -2.40328 5.06117
566 2016-02-12 08:43:21 40.3491144 115.7854825 12.129999999999995 0.736194 174.551 16.0 957.4 2.24683 -2.259 4.69336
567 2016-02-12 08:43:22 40.3491147 115.7854827 12.256000000000029 0.721629 173.06 16.0 957.4 2.24472 -2.30074 3.95699
568 2016-02-12 08:43:23 40.3491147 115.7854826 12.312000000000012 1.02892 170.476 16.0 957.4 2.25346 -2.14544 4.63103
569 2016-02-12 08:43:24 40.3491148 115.7854826 12.391999999999996 1.71353 162.162 16.0 957.4 2.24199 -2.70262 4.38941
570 2016-02-12 08:43:25 40.349115 115.7854826 12.213999999999999 1.90056 157.922 15.9 957.4 2.25142 -2.56983 4.16209
571 2016-02-12 08:43:26 40.3491151 115.785483 12.249000000000024 1.89172 162.111 15.9 957.4 2.24987 -2.37081 4.33851
572 2016-02-12 08:43:27 40.3491153 115.7854835 12.331000000000017 2.02974 161.345 15.9 957.4 2.25097 -2.36842 4.13939
573 2016-02-12 08:43:28 40.3491156 115.7854835 12.210000000000036 2.11439 163.381 15.9 957.4 2.24901 -2.72557 4.44417
574 2016-02-12 08:43:29 40.3491158 115.7854836 12.192000000000007 1.61638 157.271 15.9 957.4 2.2473 -2.35678 4.22427
575 2016-02-12 08:43:30 40.3491159 115.7854837 12.297000000000025 1.69106 156.577 15.9 957.4 2.24907 -2.72985 4.52237
576 2016-02-12 08:43:31 40.3491159 115.785484 12.105999999999995 1.27958 154.251 16.0 957.4 2.24912 -2.4493 4.27238
577 2016-02-12 08:43:32 40.3491158 115.7854842 12.254000000000019 1.37727 157.977 16.0 957.4 2.25123 -3.27265 4.57478
578 2016-02-12 08:43:33 40.3491159 115.7854845 12.354000000000042 1.21603 157.19 16.0 957.4 2.25817 -3.16157 4.23416
579 2016-02-12 08:43:34 40.3491161 115.7854845 12.486000000000047 1.52134 161.142 16.0 957.4 2.24876 -2.97854 4.09014
580 2016-02-12 08:43:35 40.3491163 115.7854843 12.413000000000011 1.62379 159.631 16.0 957.4 2.24613 -2.711 4.14956
581 2016-02-12 08:43:36 40.3491166 115.7854841 12.363 1.91354 161.307 16.0 957.4 2.24829 -2.66831 4.3683
582 2016-02-12 08:43:37 40.3491167 115.7854843 12.518000000000029 2.54485 128.325 16.0 957.4 2.24011 -2.99271 4.54588
583 2016-02-12 08:43:38 40.3491171 115.7854846 13.846000000000004 3.16679 122.058 16.0 957.4 2.24456 -2.10601 4.30452
584 2016-02-12 08:43:39 40.3491173 115.7854846 16.337000000000046 1.4036 139.974 16.0 957.4 2.25051 -2.11919 4.49659
585 2016-02-12 08:43:40 40.3491161 115.7854819 17.247000000000014 0.665258 149.372 16.0 957.4 2.25517 -2.29389 44.7974
586 2016-02-12 08:43:41 40.3491153 115.7854797 17.309000000000026 0.15585 172.788 16.0 957.4 2.25108 -6.16028 50.6785
587 2016-02-12 08:43:42 40.3491182 115.7854836 17.16300000000001 1.79734 144.454 16.0 957.4 2.24024 -9.94753 51.2855
588 2016-02-12 08:43:43 40.3491268 115.7854975 17.49200000000002 2.21825 152.062 16.0 957.4 2.26809 1.95625 50.9678
589 2016-02-12 08:43:44 40.3491325 115.7855068 17.25600000000003 2.33955 175.315 16.0 957.4 2.26068 1.88367 47.4681
590 2016-02-12 08:43:45 40.3491338 115.7855087 17.298000000000002 2.15619 172.161 16.0 957.4 2.23978 -10.4233 47.4627
591 2016-02-12 08:43:46 40.3491408 115.7855185 17.400000000000034 3.19316 157.115 16.0 957.4 2.24856 -5.19856 47.9142
592 2016-02-12 08:43:47 40.349153 115.7855364 18.277000000000044 3.51508 159.235 16.0 957.4 2.25081 -4.18958 47.1094
593 2016-02-12 08:43:48 40.349166 115.7855553 18.075000000000045 4.85972 155.95 16.0 957.4 2.2575 -3.81284 46.5688
594 2016-02-12 08:43:49 40.349179 115.7855737 18.112000000000023 5.30648 153.064 16.0 957.4 2.25406 -4.46158 47.5726
595 2016-02-12 08:43:50 40.3491919 115.7855918 18.206000000000017 5.51106 149.706 16.0 957.4 2.25075 -3.58214 47.8376
596 2016-02-12 08:43:51 40.3492042 115.7856099 18.246000000000038 5.69668 149.791 16.0 957.4 2.25386 -4.1528 47.7509
597 2016-02-12 08:43:52 40.3492167 115.7856276 17.972000000000037 5.65832 151.933 16.0 957.4 2.25417 -3.96174 47.7473
598 2016-02-12 08:43:53 40.349229 115.7856451 17.373000000000047 5.52845 152.475 16.0 957.4 2.25498 -3.35287 47.6634
599 2016-02-12 08:43:54 40.3492411 115.7856621 17.248000000000047 5.19567 150.868 16.0 957.4 2.25428 -3.57325 50.2049
600 2016-02-12 08:43:55 40.3492522 115.7856796 17.732000000000028 4.85903 145.241 16.0 957.4 2.25249 -4.60038 54.3005
601 2016-02-12 08:43:56 40.3492618 115.7856982 17.80200000000002 4.89722 141.182 16.0 957.4 2.25698 -4.268 57.7334
602 2016-02-12 08:43:57 40.3492709 115.7857178 17.648000000000025 5.00458 138.678 16.0 957.4 2.25503 -4.03971 60.8126
603 2016-02-12 08:43:58 40.3492792 115.7857383 17.670000000000016 5.06119 134.395 16.0 957.4 2.25882 -4.43467 64.1499
604 2016-02-12 08:43:59 40.3492867 115.7857602 17.617999999999995 4.97336 132.843 16.0 957.4 2.25522 -3.4857 67.6561
605 2016-02-12 08:44:00 40.3492929 115.7857822 17.749000000000024 4.76678 129.392 16.0 957.4 2.25682 -3.13844 72.5023
606 2016-02-12 08:44:01 40.3492981 115.7858047 17.458000000000027 4.70141 129.949 16.0 957.4 2.25787 -3.00207 73.9701
607 2016-02-12 08:44:02 40.3493031 115.7858268 17.75600000000003 4.64818 127.629 16.0 957.4 2.25249 -4.01299 74.3217
608 2016-02-12 08:44:03 40.3493081 115.7858497 17.591000000000008 4.78015 127.062 16.0 957.4 2.26045 -3.45797 73.9458
609 2016-02-12 08:44:04 40.349313 115.7858725 17.576000000000022 4.80095 126.743 16.0 957.4 2.25445 -3.48772 74.0784
610 2016-02-12 08:44:05 40.3493179 115.7858957 17.460000000000036 4.46846 127.093 16.0 957.4 2.25907 -2.84138 74.6726
611 2016-02-12 08:44:06 40.3493226 115.7859187 17.524 4.40493 128.632 16.0 957.4 2.2653 -2.7391 74.8234
612 2016-02-12 08:44:07 40.3493273 115.7859409 17.883000000000038 4.20996 130.254 16.0 957.4 2.25721 -3.75628 74.3471
613 2016-02-12 08:44:08 40.3493319 115.7859629 18.008000000000038 4.54446 126.276 16.0 957.4 2.24421 -4.13393 75.9746
614 2016-02-12 08:44:09 40.349336 115.7859856 17.601 4.60809 119.994 16.0 957.4 2.25283 -3.65654 80.2085
615 2016-02-12 08:44:10 40.3493389 115.7860089 17.54600000000005 4.59821 116.256 16.0 957.4 2.25826 -3.52848 84.5632
616 2016-02-12 08:44:11 40.3493404 115.7860326 17.343999999999994 4.60662 111.882 16.0 957.4 2.26272 -2.83632 87.8923
617 2016-02-12 08:44:12 40.3493407 115.786056 17.586000000000013 4.26527 108.906 16.0 957.4 2.26141 -2.64772 91.0007
618 2016-02-12 08:44:13 40.34934 115.7860794 17.64300000000003 4.15369 106.719 16.0 957.4 2.25931 -2.97149 93.9182
619 2016-02-12 08:44:14 40.3493383 115.7861028 17.40500000000003 4.06511 102.898 15.9 957.4 2.25609 -2.43398 97.4505
620 2016-02-12 08:44:15 40.3493351 115.7861305 17.194000000000017 4.10584 100.818 15.9 957.4 2.25337 -2.45874 102.19
621 2016-02-12 08:44:16 40.3493312 115.7861533 17.29600000000005 3.5283 94.6166 15.9 957.4 2.25653 -2.18443 106.176
622 2016-02-12 08:44:17 40.349326 115.7861758 17.158000000000015 3.14686 91.3884 15.9 957.4 2.26545 -1.54058 107.424
623 2016-02-12 08:44:18 40.3493205 115.7861983 17.150000000000034 2.79263 94.4733 15.9 957.4 2.25802 -2.1108 106.841
624 2016-02-12 08:44:19 40.349315 115.7862206 17.38900000000001 2.88462 94.7514 15.9 957.4 2.25069 -2.22205 107.513
625 2016-02-12 08:44:20 40.3493094 115.7862432 17.067000000000007 2.76044 95.8841 15.9 957.4 2.2528 -1.19721 107.134
626 2016-02-12 08:44:21 40.3493041 115.7862659 17.110000000000014 2.41459 96.6922 15.9 957.4 2.26201 -1.52747 106.883
627 2016-02-12 08:44:22 40.3492987 115.7862882 17.20500000000004 2.22398 91.4351 15.9 957.4 2.25557 -2.13694 106.758
628 2016-02-12 08:44:23 40.3492936 115.7863106 17.402000000000044 2.22706 93.5224 15.9 957.4 2.25374 -2.07331 107.193
629 2016-02-12 08:44:24 40.3492882 115.786333 17.234000000000037 2.23447 93.8195 16.0 957.4 2.25663 -1.73543 107.136
630 2016-02-12 08:44:25 40.3492828 115.7863553 17.341000000000008 2.369 89.0479 16.0 957.4 2.25711 -2.02998 109.231
631 2016-02-12 08:44:26 40.3492764 115.786377 17.462000000000046 2.58026 83.2347 16.0 957.4 2.26416 -1.803 114.054
632 2016-02-12 08:44:27 40.3492688 115.7863981 17.28200000000004 2.71047 83.2986 16.0 957.4 2.25945 -2.07605 117.681
633 2016-02-12 08:44:28 40.3492603 115.7864185 17.536 2.62323 77.0265 16.0 957.4 2.25908 -1.97262 120.92
634 2016-02-12 08:44:29 40.3492507 115.786438 17.591000000000008 2.65832 73.4184 16.0 957.4 2.25308 -1.5131 124.759
635 2016-02-12 08:44:30 40.3492401 115.7864565 17.560000000000002 2.7659 69.8955 16.0 957.4 2.26277 -2.36132 129.088
636 2016-02-12 08:44:31 40.3492287 115.7864741 17.32800000000003 2.67548 62.8153 16.0 957.4 2.25068 -2.22984 133.597
637 2016-02-12 08:44:32 40.3492162 115.7864915 17.398000000000025 2.61916 62.5652 16.0 957.4 2.2546 -1.56645 134.004
638 2016-02-12 08:44:33 40.3492038 115.7865082 17.36500000000001 2.38325 63.9515 16.0 957.4 2.25572 -2.22344 134.419
639 2016-02-12 08:44:34 40.3491913 115.7865247 17.396000000000015 2.4148 60.3102 16.0 957.4 2.26123 -1.89722 134.63
640 2016-02-12 08:44:35 40.3491787 115.7865415 17.450000000000045 2.71965 65.9189 16.0 957.4 2.24881 -1.83215 134.581
641 2016-02-12 08:44:36 40.3491659 115.7865581 17.43300000000005 2.8837 66.0174 16.0 957.4 2.26288 -1.92149 136.984
642 2016-02-12 08:44:37 40.3491527 115.7865736 17.39300000000003 2.99332 47.2055 16.0 957.4 2.25737 -1.88269 144.475
643 2016-02-12 08:44:39 40.3491381 115.7865865 17.437000000000012 2.60973 38.2454 16.0 957.4 2.26084 -1.88556 150.27
644 2016-02-12 08:44:39 40.3491223 115.7865974 17.41500000000002 2.0888 24.9333 16.0 957.4 2.26337 -1.17669 155.997
645 2016-02-12 08:44:40 40.3491058 115.7866061 17.382000000000005 2.04768 20.821 16.0 957.4 2.26543 -0.978078 161.237
646 2016-02-12 08:44:42 40.3490888 115.7866126 17.50400000000002 2.02731 13.2953 16.0 957.4 2.25556 -1.22699 167.844
647 2016-02-12 08:44:43 40.3490714 115.7866164 17.65500000000003 1.96942 5.29049 16.0 957.4 2.25431 -0.927087 174.693
648 2016-02-12 08:44:44 40.3490538 115.7866182 17.715000000000032 1.96387 3.9822 16.0 957.4 2.25309 -1.37721 176.111
649 2016-02-12 08:44:45 40.349036 115.7866197 17.62900000000002 1.97297 4.3481 16.0 957.4 2.26046 -1.17786 176.094
650 2016-02-12 08:44:46 40.3490182 115.7866212 17.64500000000004 1.97891 4.29482 16.0 957.4 2.25826 -1.22428 175.974
651 2016-02-12 08:44:47 40.3490003 115.7866228 17.56400000000002 1.92987 5.27529 16.0 957.4 2.25967 -1.38526 175.432
652 2016-02-12 08:44:48 40.3489822 115.7866244 17.507000000000005 2.11482 2.04059 16.1 957.4 2.25986 -1.25446 175.941
653 2016-02-12 08:44:49 40.348964 115.786626 17.494000000000028 2.2084 4.66539 16.1 957.4 2.25505 -1.25606 175.786
654 2016-02-12 08:44:50 40.3489461 115.7866279 17.533000000000015 1.98396 12.7157 16.1 957.4 2.25133 -1.10287 176.088
655 2016-02-12 08:44:51 40.3489282 115.7866296 17.510000000000048 2.00829 16.0908 16.1 957.4 2.26272 -1.05535 176.051
656 2016-02-12 08:44:52 40.3489102 115.7866312 17.38900000000001 2.00029 6.62347 16.1 957.4 2.26306 -1.15381 175.658
657 2016-02-12 08:44:53 40.3488923 115.7866329 17.53200000000004 2.00055 5.94855 16.1 957.4 2.26199 -1.15091 177.283
658 2016-02-12 08:44:54 40.3488743 115.7866336 17.375 1.84412 12.2126 16.1 957.4 2.25823 -0.905536 -179.37
659 2016-02-12 08:44:55 40.3488565 115.7866328 17.537000000000035 1.81085 14.9492 16.1 957.4 2.25636 -0.861661 -176.408
660 2016-02-12 08:44:56 40.3488387 115.7866309 17.624000000000024 1.84405 14.0908 16.1 957.4 2.25948 -1.10296 -174.525
661 2016-02-12 08:44:57 40.348821 115.7866281 17.559000000000026 1.93804 11.6952 16.1 957.4 2.26045 -0.947733 -172.353
662 2016-02-12 08:44:58 40.3488035 115.7866242 17.694000000000017 2.00184 14.1004 16.1 957.4 2.25602 -1.26374 -169.775
663 2016-02-12 08:44:59 40.348786 115.7866195 17.708000000000027 2.03629 21.9379 16.1 957.4 2.2498 -1.05616 -166.958
664 2016-02-12 08:45:00 40.3487688 115.7866138 17.646000000000015 2.05078 24.9459 16.1 957.4 2.25291 -1.05454 -163.484
665 2016-02-12 08:45:01 40.3487517 115.7866069 17.65900000000005 1.95402 30.7938 16.2 957.4 2.26536 -0.651226 -160.678
666 2016-02-12 08:45:02 40.3487347 115.786599 17.588000000000022 1.7691 34.7243 16.2 957.4 2.24918 -0.857132 -159.513
667 2016-02-12 08:45:03 40.348718 115.7865908 17.598000000000013 1.67192 47.1372 16.2 957.4 2.26345 -1.21446 -159.669
668 2016-02-12 08:45:04 40.3487011 115.7865824 17.69500000000005 1.68668 54.3084 16.2 957.4 2.25893 -0.823606 -159.862
669 2016-02-12 08:45:05 40.3486843 115.7865742 17.79200000000003 1.74508 47.7868 16.2 957.4 2.25838 -0.884091 -159.588
670 2016-02-12 08:45:06 40.3486642 115.7865643 17.739000000000033 1.86477 34.9555 16.2 957.4 2.25685 -1.2888 -159.629
671 2016-02-12 08:45:07 40.3486473 115.7865559 17.80200000000002 1.9374 38.5253 16.2 957.4 2.26043 -0.978609 -159.995
672 2016-02-12 08:45:08 40.3486305 115.7865474 17.758000000000038 1.92136 38.8821 16.2 957.4 2.26082 -0.655105 -160.113
673 2016-02-12 08:45:09 40.3486139 115.7865389 17.77000000000004 1.86096 61.4759 16.2 957.4 2.26501 -0.96432 -157.731
674 2016-02-12 08:45:10 40.3485975 115.7865297 17.74000000000001 1.84646 65.4398 16.2 957.4 2.26133 -0.770468 -151.285
675 2016-02-12 08:45:11 40.3485824 115.7865178 17.840000000000032 1.77807 66.8571 16.3 957.4 2.25876 -0.859863 -144.656
676 2016-02-12 08:45:12 40.3485682 115.7865036 17.966000000000008 1.88744 61.4756 16.3 957.4 2.26721 -0.782214 -139.476
677 2016-02-12 08:45:13 40.3485553 115.7864884 17.864000000000033 2.1576 77.0466 16.3 957.4 2.26486 -1.47746 -133.976
678 2016-02-12 08:45:14 40.3485435 115.7864713 18.11700000000002 2.70015 81.7995 16.3 957.4 2.26416 -1.10274 -128.533
679 2016-02-12 08:45:15 40.3485332 115.786453 18.287000000000035 2.69214 88.1674 16.3 957.4 2.26025 -1.94088 -122.849
680 2016-02-12 08:45:16 40.3485245 115.7864337 18.45500000000004 3.78728 89.9081 16.3 957.4 2.25168 -3.04325 -117.301
681 2016-02-12 08:45:17 40.3485173 115.7864131 18.396000000000015 4.16305 89.0334 16.3 957.4 2.25147 -3.31608 -111.595
682 2016-02-12 08:45:18 40.3485111 115.786391 18.156000000000006 4.32816 88.5418 16.4 957.4 2.25652 -3.47936 -110.1
683 2016-02-12 08:45:19 40.3485051 115.7863681 18.30000000000001 4.57069 83.1046 16.4 957.4 2.24823 -2.257 -110.004
684 2016-02-12 08:45:20 40.348499 115.7863454 18.563000000000045 4.63882 82.4551 16.4 957.4 2.25442 -2.3749 -109.707
685 2016-02-12 08:45:21 40.3484927 115.786323 18.28800000000001 4.55507 82.4027 16.4 957.4 2.26189 -2.34621 -109.863
686 2016-02-12 08:45:22 40.3484865 115.7863004 18.225000000000023 4.52532 83.4422 16.4 957.4 2.26022 -2.46761 -109.93
687 2016-02-12 08:45:23 40.3484803 115.7862778 18.161 4.26556 86.1035 16.4 957.4 2.25502 -2.08226 -109.794
688 2016-02-12 08:45:24 40.3484741 115.7862556 18.208000000000027 4.23751 87.8882 16.4 957.4 2.25048 -2.05877 -109.916
689 2016-02-12 08:45:25 40.348468 115.7862333 18.089 4.12006 88.2306 16.4 957.4 2.24768 -2.21128 -109.852
690 2016-02-12 08:45:26 40.3484618 115.7862112 18.319000000000017 3.95742 89.733 16.4 957.4 2.25324 -1.93889 -109.628
691 2016-02-12 08:45:27 40.3484557 115.7861892 18.310000000000002 3.98109 89.0515 16.4 957.4 2.25249 -2.38076 -109.893
692 2016-02-12 08:45:28 40.3484497 115.7861672 18.201999999999998 3.97322 90.7361 16.4 957.4 2.25567 -2.45486 -109.649
693 2016-02-12 08:45:29 40.3484439 115.7861451 18.471000000000004 3.97965 94.0065 16.4 957.4 2.26075 -2.21297 -106.317
694 2016-02-12 08:45:30 40.3484394 115.7861226 18.227000000000032 3.89264 97.9598 16.4 957.4 2.25305 -2.42729 -101.534
695 2016-02-12 08:45:31 40.3484363 115.7860996 18.062000000000012 3.88647 103.014 16.4 957.4 2.26572 -2.24522 -97.1811
696 2016-02-12 08:45:32 40.3484347 115.7860764 18.20500000000004 3.96167 107.487 16.4 957.4 2.25969 -2.48252 -93.2813
697 2016-02-12 08:45:33 40.3484342 115.7860533 18.545000000000016 4.19445 109.054 16.4 957.4 2.26069 -2.93529 -89.8609
698 2016-02-12 08:45:34 40.3484348 115.7860307 18.602000000000032 4.59572 106.289 16.4 957.4 2.25846 -3.74323 -87.0064
699 2016-02-12 08:45:35 40.3484361 115.7860075 18.62700000000001 4.55856 108.097 16.5 957.4 2.25328 -3.77968 -82.5635
700 2016-02-12 08:45:36 40.3484388 115.7859842 18.871000000000038 4.94187 112.091 16.5 957.4 2.25766 -3.47161 -77.7257
701 2016-02-12 08:45:37 40.3484431 115.7859614 18.620000000000005 4.99916 114.421 16.5 957.4 2.24696 -4.25361 -73.8859
702 2016-02-12 08:45:38 40.3484484 115.7859379 18.662000000000035 5.041 118.194 16.5 957.4 2.24988 -2.40826 -72.456
703 2016-02-12 08:45:39 40.3484539 115.7859151 18.590000000000032 4.86597 121.342 16.5 957.4 2.23913 -2.65323 -72.0437
704 2016-02-12 08:45:40 40.3484598 115.7858929 18.458000000000027 4.57349 122.896 16.5 957.4 2.24802 -2.92134 -72.8244
705 2016-02-12 08:45:41 40.3484654 115.7858701 18.50400000000002 4.62556 125.251 16.5 957.4 2.25008 -2.46242 -72.5329
706 2016-02-12 08:45:42 40.3484709 115.7858478 18.313000000000045 4.34028 123.989 16.5 957.4 2.2451 -3.08264 -72.7796
707 2016-02-12 08:45:43 40.3484763 115.7858252 17.950000000000045 4.58716 121.914 16.5 957.4 2.24825 -2.61072 -72.9401
708 2016-02-12 08:45:44 40.3484817 115.7858026 17.908000000000015 4.45187 123.576 16.5 957.4 2.2571 -2.53661 -72.1734
709 2016-02-12 08:45:45 40.3484873 115.7857801 18.42700000000002 4.56513 122.201 16.5 957.4 2.24877 -2.19526 -72.9211
710 2016-02-12 08:45:46 40.3484926 115.7857577 18.236000000000047 4.27496 122.441 16.5 957.4 2.25316 -2.56898 -72.6472
711 2016-02-12 08:45:47 40.3484981 115.7857353 18.04000000000002 4.05575 123.342 16.5 957.4 2.24489 -2.28949 -71.977
712 2016-02-12 08:45:48 40.3485039 115.7857134 18.49200000000002 4.03684 127.936 16.5 957.4 2.25751 -2.46188 -67.2151
713 2016-02-12 08:45:49 40.348511 115.785693 18.735000000000014 4.11837 133.691 16.5 957.4 2.25974 -3.48746 -61.2099
714 2016-02-12 08:45:50 40.3485197 115.7856737 18.715000000000032 4.69469 136.928 16.5 957.4 2.24865 -3.85436 -55.4787
715 2016-02-12 08:45:51 40.3485302 115.785655 18.584000000000003 4.95181 138.959 16.5 957.4 2.25789 -3.25282 -50.9018
716 2016-02-12 08:45:52 40.3485445 115.7856342 19.019000000000005 5.16532 142.967 16.5 957.4 2.25162 -3.51994 -44.9958
717 2016-02-12 08:45:53 40.3485551 115.7856217 18.930000000000007 5.17427 145.326 16.5 957.4 2.25415 -3.20807 -40.945
718 2016-02-12 08:45:54 40.3485718 115.7856049 19.383000000000038 5.22752 149.735 16.5 957.4 2.23934 -4.49393 -34.1759
719 2016-02-12 08:45:55 40.3485865 115.7855928 19.444000000000017 5.46417 153.647 16.5 957.4 2.24285 -3.81437 -28.297
720 2016-02-12 08:45:56 40.3486022 115.7855819 19.15900000000005 5.61763 151.635 16.5 957.4 2.24025 -3.88984 -25.5592
721 2016-02-12 08:45:57 40.3486185 115.7855714 19.13100000000003 5.22492 151.447 16.5 957.4 2.24517 -4.60596 -25.7129
722 2016-02-12 08:45:58 40.348635 115.7855608 18.66500000000002 5.22477 152.331 16.5 957.4 2.25713 -3.54813 -26.0158
723 2016-02-12 08:45:59 40.3486512 115.78555 18.549000000000035 5.00249 156.044 16.5 957.4 2.2507 -3.84303 -26.0043
724 2016-02-12 08:46:00 40.3486673 115.7855394 18.598000000000013 4.90608 159.322 16.5 957.4 2.24678 -3.58029 -25.9375
725 2016-02-12 08:46:01 40.3486837 115.7855294 18.55400000000003 4.89749 161.021 16.5 957.4 2.24366 -3.33764 -25.6277
726 2016-02-12 08:46:02 40.3486999 115.7855194 18.826999999999998 4.74312 160.992 16.5 957.4 2.24832 -3.63823 -25.437
727 2016-02-12 08:46:03 40.3487159 115.7855095 18.734000000000037 5.08126 160.834 16.5 957.4 2.24889 -3.83332 -25.7044
728 2016-02-12 08:46:04 40.348732 115.7854993 18.697000000000003 5.29667 161.546 16.5 957.4 2.24539 -3.81592 -25.3915
729 2016-02-12 08:46:05 40.3487486 115.7854894 18.629999999999995 5.33145 161.929 16.5 957.4 2.24517 -3.09275 -23.3054
730 2016-02-12 08:46:06 40.3487655 115.7854806 18.716000000000008 4.78943 163.905 16.5 957.4 2.25106 -2.56043 -19.1261
731 2016-02-12 08:46:07 40.348782 115.7854734 18.864000000000033 4.65857 165.761 16.5 957.4 2.24854 -3.60127 -15.6055
732 2016-02-12 08:46:08 40.3487988 115.7854675 19.091000000000008 4.77459 166.962 16.5 957.4 2.24936 -4.10476 -12.4039
733 2016-02-12 08:46:09 40.3488161 115.785463 19.161 5.17038 169.08 16.5 957.4 2.26161 -3.88614 -10.0499
734 2016-02-12 08:46:10 40.3488335 115.7854591 19.347000000000037 5.30009 171.894 16.5 957.4 2.25124 -4.02029 -7.24302
735 2016-02-12 08:46:11 40.3488513 115.7854566 19.013000000000034 5.39223 174.83 16.5 957.4 2.24748 -4.18501 -4.02827
736 2016-02-12 08:46:12 40.3488692 115.7854554 18.531000000000006 5.22289 177.792 16.5 957.4 2.24002 -3.68792 -0.138169
737 2016-02-12 08:46:13 40.348887 115.7854559 18.712000000000046 5.29908 176.119 16.5 957.4 2.24991 -4.16261 3.40361
738 2016-02-12 08:46:14 40.3489049 115.7854579 18.876000000000033 5.18513 175.604 16.5 957.4 2.25581 -3.8008 4.82798
739 2016-02-12 08:46:15 40.3489226 115.7854601 18.70300000000003 5.28377 174.7 16.5 957.4 2.25573 -4.42704 5.10422
740 2016-02-12 08:46:16 40.3489402 115.7854625 18.723000000000013 5.07867 173.898 16.5 957.4 2.25527 -4.51496 5.49623
741 2016-02-12 08:46:17 40.3489577 115.7854654 19.19500000000005 5.09618 175.518 16.5 957.4 2.25583 -4.36611 5.46923
742 2016-02-12 08:46:18 40.3489756 115.7854678 18.958000000000027 5.11867 176.609 16.4 957.4 2.25081 -4.54822 5.33563
743 2016-02-12 08:46:19 40.3489936 115.7854701 18.870000000000005 5.4073 176.796 16.4 957.4 2.25643 -4.75882 5.40797
744 2016-02-12 08:46:20 40.3490114 115.7854722 18.610000000000014 5.58391 175.575 16.4 957.4 2.24946 -5.50701 5.03366
745 2016-02-12 08:46:21 40.3490293 115.7854738 18.632000000000005 5.9049 176.505 16.4 957.4 2.25577 -4.83407 5.36974
746 2016-02-12 08:46:22 40.3490473 115.7854761 18.746000000000038 5.91032 176.712 16.4 957.4 2.26172 -4.47638 5.38053
747 2016-02-12 08:46:23 40.3490654 115.7854787 18.749000000000024 5.8128 175.791 16.4 957.4 2.24897 -4.6601 5.14888
748 2016-02-12 08:46:24 40.3490833 115.7854808 18.635000000000048 5.96479 174.72 16.4 957.4 2.26363 -5.30749 5.15921
749 2016-02-12 08:46:25 40.3491012 115.7854828 18.662000000000035 5.69564 172.094 16.4 957.4 2.2571 -0.473702 4.87027
750 2016-02-12 08:46:26 40.3491131 115.7854838 18.741000000000042 3.78275 164.729 16.4 957.4 2.25241 -0.887125 4.75248
751 2016-02-12 08:46:27 40.3491144 115.7854838 18.359000000000037 3.20324 161.213 16.4 957.4 2.25493 -3.26957 5.54402
752 2016-02-12 08:46:28 40.3491142 115.7854837 18.223000000000013 2.40983 155.756 16.3 957.4 2.25721 -3.09028 5.36807
753 2016-02-12 08:46:29 40.3491141 115.7854836 18.116000000000042 2.11352 157.024 16.3 957.4 2.25414 -2.34086 5.54559
754 2016-02-12 08:46:30 40.349114 115.7854839 18.098000000000013 1.80536 155.986 16.3 957.4 2.24952 -2.62845 5.28901
755 2016-02-12 08:46:31 40.3491139 115.7854841 18.104000000000042 1.53764 153.71 16.3 957.4 2.25496 -2.72331 4.91931
756 2016-02-12 08:46:32 40.3491141 115.785484 18.013000000000034 1.25194 135.14 16.3 957.4 2.25252 -2.51398 5.07391
757 2016-02-12 08:46:33 40.3491145 115.7854839 18.096000000000004 0.909581 119.528 16.3 957.4 2.26502 -2.23522 4.9321
758 2016-02-12 08:46:34 40.3491148 115.7854839 18.11500000000001 1.00363 116.368 16.3 957.4 2.25633 -1.86102 4.94461
759 2016-02-12 08:46:35 40.3491147 115.7854839 18.156000000000006 1.29567 116.279 16.3 957.4 2.24816 -3.27238 4.93432
760 2016-02-12 08:46:36 40.3491148 115.7854839 18.29200000000003 1.80343 117.547 16.3 957.4 2.25323 -3.03301 5.0516
761 2016-02-12 08:46:37 40.3491153 115.7854844 18.262 2.20721 129.988 16.3 957.4 2.23802 -2.33693 -3.56446
762 2016-02-12 08:46:38 40.349117 115.7854858 18.539000000000044 2.41458 130.441 16.3 957.4 2.25003 -3.03663 -32.2437
763 2016-02-12 08:46:39 40.3491192 115.7854854 18.525000000000034 2.51248 120.631 16.3 957.4 2.2485 -2.14594 -62.1644
764 2016-02-12 08:46:40 40.3491202 115.7854843 18.311000000000035 2.39774 119.713 16.3 957.4 2.26122 -1.66167 -82.6586
765 2016-02-12 08:46:41 40.3491201 115.7854826 18.40100000000001 2.6669 112.549 16.3 957.4 2.24148 -9.69869 -94.4252
766 2016-02-12 08:46:42 40.349119 115.785474 18.451999999999998 3.58092 114.107 16.3 957.4 2.24515 -8.18198 -94.3401
767 2016-02-12 08:46:43 40.3491177 115.7854533 18.446000000000026 4.36065 111.498 16.3 957.4 2.24984 -6.39408 -94.1511
768 2016-02-12 08:46:44 40.3491158 115.7854241 18.548000000000002 4.83268 107.56 16.2 957.4 2.25608 -5.52217 -93.985
769 2016-02-12 08:46:45 40.3491136 115.7853904 18.562000000000012 5.63733 104.996 16.2 957.4 2.25285 -3.73582 -93.9406
770 2016-02-12 08:46:46 40.3491117 115.7853556 18.718000000000018 5.98308 99.2656 16.2 957.4 2.25147 -1.55215 -94.2177
771 2016-02-12 08:46:47 40.3491101 115.7853231 18.66900000000004 5.99918 99.0378 16.2 957.4 2.25063 -1.4597 -93.9427
772 2016-02-12 08:46:48 40.3491088 115.7852936 18.864000000000033 5.58521 98.8318 16.2 957.4 2.25688 -1.74784 -94.2138
773 2016-02-12 08:46:49 40.3491076 115.7852665 18.647000000000048 5.06914 102.902 16.2 957.4 2.25241 -1.92998 -93.8656
774 2016-02-12 08:46:50 40.3491069 115.7852413 18.53800000000001 4.57836 107.973 16.2 957.4 2.25181 -1.92374 -92.0432
775 2016-02-12 08:46:51 40.3491072 115.785218 18.536 4.43143 115.332 16.2 957.4 2.25353 -2.10617 -85.8288
776 2016-02-12 08:46:52 40.3491093 115.7851963 18.79000000000002 4.43013 123.816 16.2 957.4 2.25323 -2.65061 -78.6565
777 2016-02-12 08:46:53 40.3491127 115.7851749 18.78800000000001 4.58193 121.516 16.2 957.4 2.24977 -2.85184 -78.4132
778 2016-02-12 08:46:54 40.3491161 115.7851532 18.649 4.63984 120.281 16.2 957.4 2.2551 -3.52654 -78.4899
779 2016-02-12 08:46:55 40.3491197 115.7851304 18.391999999999996 4.82902 119.083 16.2 957.4 2.25016 -3.82069 -78.4761
780 2016-02-12 08:46:56 40.3491238 115.7851057 18.468999999999994 4.82599 118.463 16.2 957.4 2.25212 -4.37022 -78.4759
781 2016-02-12 08:46:57 40.3491283 115.7850782 18.476 5.24285 115.506 16.2 957.4 2.2514 -5.29125 -78.4982
782 2016-02-12 08:46:58 40.3491332 115.7850471 18.605999999999995 5.63871 114.027 16.2 957.4 2.25888 -4.89839 -78.6514
783 2016-02-12 08:46:59 40.3491386 115.7850129 18.64300000000003 6.21575 110.912 16.2 957.4 2.23991 -4.85329 -78.5702
784 2016-02-12 08:47:00 40.3491446 115.7849764 18.474000000000046 6.52411 109.303 16.2 957.4 2.25149 -4.43201 -78.5637
785 2016-02-12 08:47:01 40.349151 115.784938 18.80800000000005 6.77679 107.561 16.2 957.4 2.24558 -4.74183 -78.8267
786 2016-02-12 08:47:02 40.3491576 115.7848981 18.956999999999994 7.09753 106.696 16.2 957.4 2.25637 -4.52781 -78.8386
787 2016-02-12 08:47:03 40.3491644 115.7848569 18.587000000000046 7.33927 106.749 16.2 957.4 2.26023 -4.96421 -78.5891
788 2016-02-12 08:47:04 40.3491715 115.784814 18.772000000000048 7.50092 106.624 16.2 957.4 2.25672 -5.29089 -78.658
789 2016-02-12 08:47:05 40.3491788 115.7847687 18.714 7.58947 106.181 16.2 957.4 2.24472 -4.61858 -78.6736
790 2016-02-12 08:47:06 40.3491862 115.7847216 18.861000000000047 7.58499 106.907 16.2 957.4 2.26091 -2.96341 -78.4489
791 2016-02-12 08:47:07 40.3491932 115.7846768 19.076000000000022 7.63955 107.249 16.1 957.4 2.24757 -2.96918 -78.5038
792 2016-02-12 08:47:08 40.3492001 115.7846343 18.950000000000045 7.56674 107.19 16.1 957.4 2.25598 -1.65859 -78.5213
793 2016-02-12 08:47:09 40.3492063 115.7845963 18.875 6.51291 106.081 16.1 957.4 2.25284 0.87737 -78.6438
794 2016-02-12 08:47:10 40.3492115 115.7845658 18.902000000000044 5.94177 109.224 16.1 957.4 2.25329 -0.890602 -75.947
795 2016-02-12 08:47:11 40.3492163 115.7845434 18.91700000000003 3.39562 124.224 16.1 957.4 2.25078 5.36068 -61.0265
796 2016-02-12 08:47:12 40.3492168 115.7845391 18.373000000000047 2.35105 144.149 16.1 957.4 2.25335 0.560695 -45.7276
797 2016-02-12 08:47:13 40.3492155 115.784539 18.483000000000004 0.893619 174.724 16.1 957.4 2.25703 -1.3111 -23.1751
798 2016-02-12 08:47:14 40.3492136 115.7845378 18.56800000000004 0.103818 119.339 16.1 957.4 2.25902 -1.38589 10.1569
799 2016-02-12 08:47:15 40.3492129 115.7845354 18.382000000000005 0.0326814 130.99 16.1 957.4 2.25777 -1.22882 35.8235
800 2016-02-12 08:47:16 40.3492121 115.7845341 18.218999999999994 0.387784 31.1506 16.1 957.4 2.25355 -1.60541 40.0295
801 2016-02-12 08:47:17 40.3492103 115.7845329 18.116000000000042 0.509455 87.3243 16.1 957.4 2.23954 -2.1407 39.683
802 2016-02-12 08:47:18 40.3492105 115.7845333 17.775000000000034 0.381268 100.864 16.1 957.4 2.25254 -1.36341 39.8437
803 2016-02-12 08:47:19 40.3492113 115.7845336 17.50200000000001 0.370224 45.6902 16.1 957.4 2.25597 -1.52545 39.8108
804 2016-02-12 08:47:20 40.3492121 115.7845342 17.311000000000035 0.349136 85.5964 16.1 957.4 2.24971 -0.617308 39.8674
805 2016-02-12 08:47:21 40.349212 115.7845348 16.980000000000018 0.418138 75.5565 16.1 957.4 2.25604 -1.80859 39.3206
806 2016-02-12 08:47:22 40.3492118 115.7845347 16.562000000000012 0.729231 92.0266 16.1 957.4 2.24718 -1.91448 39.8363
807 2016-02-12 08:47:23 40.3492116 115.784534 16.108000000000004 0.752719 77.3196 16.1 957.4 2.2566 -2.7967 40.4346
808 2016-02-12 08:47:24 40.3492117 115.7845338 15.56800000000004 0.876472 112.876 16.2 957.6 2.24441 -2.74975 40.4632
809 2016-02-12 08:47:25 40.3492114 115.7845344 14.550000000000011 0.910692 111.859 16.2 957.6 2.24345 -3.14775 40.1516
810 2016-02-12 08:47:26 40.3492114 115.7845344 13.948000000000036 1.52511 98.9897 16.2 957.4 2.25048 -2.48058 39.9685
811 2016-02-12 08:47:27 40.3492112 115.7845344 13.17100000000005 1.46838 143.535 16.2 957.4 2.25029 1.99029 39.8544
812 2016-02-12 08:47:28 40.3492081 115.7845311 12.235000000000014 1.59666 132.338 16.2 957.4 2.24882 0.489737 39.9297
813 2016-02-12 08:47:29 40.3492023 115.7845249 11.288000000000011 2.02849 101.22 16.2 957.6 2.24682 0.807989 40.035
814 2016-02-12 08:47:30 40.3491942 115.7845164 10.459000000000003 2.41615 81.7842 16.2 957.6 2.24377 -1.64567 39.8959
815 2016-02-12 08:47:31 40.3491866 115.7845083 9.474000000000046 2.36492 77.0593 16.2 957.4 2.25103 -9.16326 40.0477
816 2016-02-12 08:47:32 40.3491841 115.7845057 8.593000000000018 2.04153 85.8787 16.2 957.4 2.25579 -3.23226 40.0162
817 2016-02-12 08:47:33 40.3491831 115.7845048 7.691000000000031 2.01561 84.4265 16.2 957.4 2.24309 2.06283 40.2772
818 2016-02-12 08:47:34 40.3491783 115.7844987 6.6720000000000255 2.23031 79.3183 16.2 957.4 2.24866 3.54644 46.1237
819 2016-02-12 08:47:35 40.3491704 115.7844869 5.802000000000021 2.77827 78.7524 16.2 957.6 2.24481 0.782934 49.3694
820 2016-02-12 08:47:36 40.3491614 115.7844734 5.021000000000015 2.6489 80.7009 16.2 957.6 2.24837 -3.47997 49.2569

View File

@ -0,0 +1,95 @@
# testconfig.yaml
horizontal_pixels: 500 # Width of the concentration map in pixels
vertical_pixels: 100 # Height of the concentration map in pixels
num_plumes: 10 # Number of Gaussian plumes
groupiness: 0.5 # Groupiness of the plumes (0.0 to 1.0)
spread: 0.1 # Spread of the plumes (0.0 to 1.0)
wind_reference_height: 10 # Reference height for wind speed calculation (m)
windspeed_avg: 5 # Average wind speed at 10m height (m/s)
windspeed_rel_std: 0.2 # Relative standard deviation of wind speed (0.0 to inf), recommend 0.2-0.4
surface_roughness: 0.1 # Surface roughness length (m)
seed: 42 # Random seed for reproducibility
simplex_octaves: 4 # Number of octaves for simplex noise (1 to inf, def 1)
simplex_persistence: 0.7 # Persistence of simplex noise (0.0 to 1.0, def 0.5) - specifies the amplitude of each octave relative to the one below it
simplex_lacunarity: 2.0 # Lacunarity of simplex noise (1.0 to inf, def 2.0) - specifies the frequency of each octave relative to the one below it
winddir_avg: 0.0 # Average wind direction in degrees rel to plane (0 is CW)
winddir_std: 10 # Standard deviation of wind direction in degrees
timestamp: "2022-09-26 02:03:00"
flight_time_seconds: 1000
sample_frequency: 1
start_coords:
- 54.87667
- 15.41
transect_azimuth: 260 # the wind will start off 90 degrees CW to this azimuth, and is modified relative to that by the winddir_avg. 260 is a good value to test N problems
sampling_altitude_ato_range:
- -10 # negative values should be fine
- 100
sampling_horizontal_range:
- 50
- 950
scene_altitude_range:
- -20
- 120
scene_horizontal_range:
- 0
- 1000
number_of_transects: 10
gases:
ch4:
- 1.95
- 10.0
co2:
- 380.0
- 500.0
c2h6:
- 0.0
- 1.0
temperature: 10.0
pressure: 1000.0
output_dir: ./gasflux_reports
algorithmic_baseline_settings:
algorithm: fastchrom
semivariogram_settings:
model: spherical
estimator: cressie
n_lags: 20
bin_func: even
fit_method: lm
maxlag: 100
#fit_sigma: linear
tolerance: 10
azimuth: 0
bandwidth: 20
ordinary_kriging_settings:
min_points: 3
max_points: 100
grid_resolution: 500
min_nodes: 10
cut_ground: False
y_min: ~
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [-100, 500]
windspeed: [0, 30]
winddir: [0, 360]
temperature: [-50, 60]
pressure: [900, 1100]
filters:
course_filter:
azimuth_filter: 10
azimuth_window: 5
elevation_filter: 5
strategies:
background: "algorithm"
sensor: "insitu"
spatial: "curtain"
interpolation: "kriging"

120
pyproject.toml Normal file
View File

@ -0,0 +1,120 @@
[project]
name = "gasflux"
dynamic = ["version", "dependencies", "optional-dependencies"]
description = "A package to calculate gas emissions fluxes from natural and anthropogenic sources"
authors = [{ name = "Jamie McQuilkin", email = "jamie.mcquilkin@gmail.com" }]
license = { text = "AGPL-3.0" }
readme = "README.md"
requires-python = ">=3.10"
[project.scripts]
gasflux = "gasflux.cli:main_cli"
[project.urls]
"Homepage" = "https://gasflux.github.io"
"Bug Tracker" = "https://github.com/gasflux/gasflux/issues"
[build-system]
requires = ["setuptools>=69.0", "wheel", "setuptools-scm>=8.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools.dynamic]
version = {attr = "gasflux.__version__"}
dependencies = { file = ["requirements.txt"] }
optional-dependencies = { dev = { file = ["dev-requirements.txt"] } }
[tool.mypy]
ignore_missing_imports = true
check_untyped_defs = true
[tool.ruff]
line-length = 120
target-version = "py311"
[tool.ruff.lint]
ignore = [
"G004", # G004: Logging statement uses f-string
"PD901", # PD901: Using "df" as a variable name is not recommended
"ISC001", # ISC001: Use of implicit string concatenation
]
select = [
"A", # prevent using keywords that clobber python builtins
"B", # bugbear: security warnings
"E", # pycodestyle
"F", # pyflakes
"ISC", # implicit string concatenation
"UP", # alert you when better syntax is available in your python version
"RUF", # the ruff developer's own rules
]
[tool.ruff.lint.pydocstyle]
convention = "google"
[tool.semantic_release]
assets = []
commit_message = "{version}\n\nAutomatically generated by python-semantic-release"
commit_parser = "angular"
logging_use_named_masks = false
major_on_zero = true
allow_zero_version = true
tag_format = "v{version}"
version_variables = ["src/gasflux/__init__.py:__version__"]
[tool.semantic_release.branches.main]
match = "(main|master)"
prerelease_token = "rc"
prerelease = false
[tool.semantic_release.changelog]
# template_dir = "templates"
changelog_file = "CHANGELOG.md"
exclude_commit_patterns = ["ci", "test", "chore", "docs", "style", "refactor"]
[tool.semantic_release.changelog.environment]
block_start_string = "{%"
block_end_string = "%}"
variable_start_string = "{{"
variable_end_string = "}}"
comment_start_string = "{#"
comment_end_string = "#}"
trim_blocks = false
lstrip_blocks = false
newline_sequence = "\n"
keep_trailing_newline = false
extensions = []
autoescape = true
[tool.semantic_release.commit_author]
env = "GIT_COMMIT_AUTHOR"
default = "semantic-release <semantic-release>"
[tool.semantic_release.commit_parser_options]
allowed_tags = [
"build",
"chore",
"ci",
"docs",
"feat",
"fix",
"perf",
"style",
"refactor",
"test",
]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]
default_bump_level = 0
[tool.semantic_release.remote]
name = "origin"
type = "github"
ignore_token_for_push = false
[tool.semantic_release.remote.token]
env = "GH_TOKEN"
[tool.semantic_release.publish]
dist_glob_patterns = ["dist/*"]
upload_to_vcs_release = true

20
requirements.txt Normal file
View File

@ -0,0 +1,20 @@
# Automatically generated by https://github.com/damnever/pigar.
colorama==0.4.6
geopandas==0.14.3
geopy==2.4.1
Jinja2==3.1.6
joblib==1.3.2
matplotlib==3.10.0
molmass==2023.8.30
noise==1.2.2
numpy==2.1.3
pandas==2.2.3
plotly==5.20.0
pybaselines==1.1.0
pytest==8.1.1
PyYAML==6.0.1
scikit-gstat==1.0.19
scikit-image==0.24.0
scipy==1.15.1
simplekml==1.3.6

0
src/__init__.py Normal file
View File

29
src/gasflux/__init__.py Normal file
View File

@ -0,0 +1,29 @@
"""Init file for gasflux package."""
__version__ = "0.2.1" # managed by semantic versioning
from . import (
background,
cli,
gas,
interpolation,
ml,
plotting,
pre_processing,
processing,
processing_pipelines,
reporting,
)
__all__ = [
"background",
"cli",
"gas",
"interpolation",
"ml",
"plotting",
"pre_processing",
"processing",
"processing_pipelines",
"reporting",
]

64
src/gasflux/background.py Normal file
View File

@ -0,0 +1,64 @@
"""Baselining functions."""
import numpy as np
import pandas as pd
import pybaselines as pybs
from . import plotting
# 自定义阈值函数避免依赖scikit-image
def custom_threshold(data):
"""
简单的三角阈值算法实现避免依赖scikit-image
使用直方图的三角法来确定阈值
"""
if len(data) == 0:
return 0
# 计算直方图
hist, bin_edges = np.histogram(data, bins=256)
bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
# 找到最大峰值
max_idx = np.argmax(hist)
# 如果最大峰在边缘,使用中位数作为阈值
if max_idx == 0 or max_idx == len(hist) - 1:
return np.median(data)
# 使用简单的阈值策略:最大峰右侧的第一个局部最小值
# 这里简化为使用均值作为阈值
return np.mean(data)
def algorithmic_baseline(
df: pd.DataFrame,
gas: str,
algorithmic_baseline_settings: dict,
):
df = df.copy()
algorithm = algorithmic_baseline_settings["algorithm"]
settings = algorithmic_baseline_settings.get(algorithm, {}).copy()
if settings.get("threshold") == "custom":
settings["threshold"] = custom_threshold
if len(df) < 20:
raise ValueError("Dataframe must contain at least 20 rows for background correction.")
index = np.arange(len(df))
baseline_fitter = pybs.Baseline(index, check_finite=False)
fit = getattr(baseline_fitter, algorithm)
bkg, params = fit(df[gas], **settings)
bkg_points = params["mask"]
df[f"{gas}_normalised"] = df[gas] - bkg
df[f"{gas}_fit"] = bkg
background = (df[gas] - bkg)[bkg_points]
signal = (df[gas] - bkg)[~bkg_points]
df[f"{gas}_signal"] = np.invert(bkg_points)
fig = plotting.background_plotting(df, gas)
output_text = (
f"Baseline algorithm: {algorithm}\n"
f"Positive and negative 95% percentile of baseline: {np.percentile(background, 2.5):.2f} ppm, \
{np.percentile(background, 97.5):.2f} ppm\n"
f"Mean of baseline: {np.mean(background):.2f} ppm\n"
f"Minimum and maximum of baseline: {np.min(background):.2f} ppm, {np.max(background):.2f} ppm\n"
f"Signal points: {len(signal)}; background points: {len(background)}\n"
)
return df, fig, output_text

279
src/gasflux/cli.py Normal file
View File

@ -0,0 +1,279 @@
import argparse
from pathlib import Path
import shutil
from colorama import init, Fore, Style
from src.gasflux.processing_pipelines import process_main
init()
def find_config_file(path: Path, recursive: bool = True):
if recursive:
config_files = [file for file in path.rglob("*.yaml") if "gasflux_config" in file.read_text()]
else:
config_files = [file for file in path.glob("*.yaml") if "gasflux_config" in file.read_text()]
if len(config_files) == 1:
return config_files[0]
elif len(config_files) > 1:
raise ValueError(
"Multiple candidate config files found: {}".format(", ".join(str(file) for file in config_files))
)
else:
raise FileNotFoundError("No config file found in the supplied path or its child folders")
def process_command(data_path: str, config_path: str, test: bool):
if test:
data_file = Path(__file__).parent / "testdata" / "testdata.csv"
config_file = Path(__file__).parent / "testdata" / "testconfig.yaml"
process_main(data_file, config_file)
return
dpath_obj = Path(data_path)
if dpath_obj.is_dir():
data_files = list(dpath_obj.rglob("*.csv"))
if not data_files:
raise FileNotFoundError(f"No CSV files found in directory: {data_path}")
elif dpath_obj.is_file():
data_files = [dpath_obj]
else:
raise FileNotFoundError(f"Invalid data path: {data_path}")
if config_path is None:
try:
config_file = find_config_file(dpath_obj if dpath_obj.is_dir() else dpath_obj.parent)
except FileNotFoundError:
response = (
input(
"No configuration file found. Generate config file? \n"
"You may have to modify it before processing. [y/n]: "
)
.strip()
.lower()
)
if response == "y":
config_file = (dpath_obj if dpath_obj.is_dir() else dpath_obj.parent) / "gasflux_config.yaml"
shutil.copy(Path(__file__).parent / "gasflux_config.yaml", config_file)
print(f"Config file copied to: {config_file}")
else:
print("No config file generated. Exiting.")
return
else:
config_file = Path(config_path)
for data_file in data_files:
process_main(data_file, config_file)
def generate_config_command(config_destination: str, recursive: bool = False, template_path: str | None = None):
if template_path:
template = Path(template_path)
print(f"Using custom template: {template}")
else:
template = Path(__file__).parent / "gasflux_config.yaml"
if not template.exists():
raise FileNotFoundError(f"Template file not found: {template}")
destination_path = Path(config_destination)
if not destination_path.is_dir():
raise NotADirectoryError(f"Destination path is not a directory: {config_destination}")
overwrite_all = False # Flag to determine if we should overwrite all files without prompting
if recursive:
for subdir in destination_path.rglob("*"):
if subdir.is_dir():
config_file = subdir / "gasflux_config.yaml"
if config_file.exists() and not overwrite_all:
response = (
input(f"Config file already exists at {config_file}. Overwrite? [y/n/a/c]: ").strip().lower()
)
if response == "a":
overwrite_all = True
elif response == "c":
print("Operation canceled.")
return
elif response == "n":
print(f"Skipping {config_file}")
continue
shutil.copy(template, config_file)
print(f"Config file copied to: {config_file}")
else:
config_file = destination_path / "gasflux_config.yaml"
if config_file.exists() and not overwrite_all:
response = input(f"Config file already exists at {config_file}. Overwrite? [y/n/a/c]: ").strip().lower()
if response == "a":
overwrite_all = True
elif response == "c":
print("Operation canceled.")
return
elif response == "n":
print(f"Skipping {config_file}")
return
shutil.copy(template, config_file)
print(f"Config file copied to: {config_file}")
def main_cli():
parser = argparse.ArgumentParser(
description="GasFlux Processing Pipeline",
formatter_class=argparse.RawTextHelpFormatter,
add_help=False, # Disable the default help to use the custom help screen
)
subparsers = parser.add_subparsers(dest="command")
process_parser = subparsers.add_parser(
"process",
help="Process CSV data files",
description=(
"Process CSV data files located in a specified directory or a single file.\n"
"The program will search for a configuration file (gasflux_config.yaml) in the same directory as the data file(s).\n" # noqa
),
formatter_class=argparse.RawTextHelpFormatter,
)
process_parser.add_argument(
"data_path",
nargs="?",
default=None,
help=(
"Path to the data file or directory containing CSV files.\n"
"If a directory is provided, all CSV files within the directory will be processed."
),
)
process_parser.add_argument(
"--config-path",
"-c",
default=None,
help=(
"Path to the configuration file (gasflux_config.yaml).\n"
"If not specified, the program will search for the configuration file in the same directory as the data file(s).\n" # noqa
"If no configuration file is found, the default configuration will be used."
),
)
process_parser.add_argument(
"--test",
action="store_true",
help="Use test data instead of the specified data file(s).",
)
config_parser = subparsers.add_parser(
"generate-config",
help="Generate a configuration file",
description=(
"Generate a configuration file (gasflux_config.yaml) in the specified directory.\n"
"If no directory is specified, the configuration file will be generated in the current directory."
"Use flag --recursive to generate config files in all subdirectories recursively. YOu might want to"
"do this if you want to have a separate config for each data file"
),
formatter_class=argparse.RawTextHelpFormatter,
)
config_parser.add_argument(
"--recursive",
action="store_true",
help="Generate config files in all subdirectories recursively.",
)
config_parser.add_argument(
"--template",
default=None,
help="Path to a custom template configuration file.",
)
config_parser.add_argument(
"config_destination",
nargs="?",
default=None,
help="Destination directory for the generated configuration file.",
)
# Custom help option
parser.add_argument(
"-h",
"--help",
action="store_true",
help="Show this help message and exit",
)
args = parser.parse_args()
if args.command == "process":
process_command(args.data_path, args.config_path, args.test)
elif args.command == "generate-config":
generate_config_command(args.config_destination, args.recursive, args.template)
elif args.help:
display_help()
else:
display_help()
def display_help():
help_text = f"""
{Fore.CYAN}GasFlux Processing Pipeline{Style.RESET_ALL}
{Fore.CYAN}==========================={Style.RESET_ALL}
{Fore.YELLOW}Description:{Style.RESET_ALL}
The GasFlux Processing Pipeline is a command-line tool for processing CSV data files and generating configuration files.
{Fore.YELLOW}Usage:{Style.RESET_ALL}
gasflux [OPTIONS] COMMAND [ARGS]...
{Fore.YELLOW}Commands:{Style.RESET_ALL}
{Fore.GREEN}process{Style.RESET_ALL} Process CSV data files
{Fore.GREEN}generate-config{Style.RESET_ALL} Generate a default configuration file
{Fore.YELLOW}Options:{Style.RESET_ALL}
{Fore.BLUE}-h, --help{Style.RESET_ALL} Show this help message and exit
{Fore.BLUE}-v, --version{Style.RESET_ALL} Show the version and exit
{Fore.YELLOW}Commands Help:{Style.RESET_ALL}
{Fore.GREEN}process{Style.RESET_ALL} Process CSV data files located in a specified directory or a single file.
The program will search for a singular configuration file (gasflux_config.yaml) in the same directory
- if a directory is supplied to [DATA_PATH] then child directories are searched too.
{Fore.YELLOW}Usage:{Style.RESET_ALL} gasflux process [OPTIONS] [DATA_PATH]
{Fore.YELLOW}Options:{Style.RESET_ALL}
{Fore.BLUE}-c, --config-path PATH{Style.RESET_ALL} Path to the configuration file (gasflux_config.yaml).
If not specified, the program will search for the configuration file
in the same directory as the data file(s).
If no configuration file is found, the default configuration will be used.
{Fore.BLUE}--test{Style.RESET_ALL} Use test data instead of the specified data file(s).
{Fore.BLUE}-h, --help{Style.RESET_ALL} Show this help message and exit
{Fore.GREEN}generate-config{Style.RESET_ALL} Generate a default configuration file (gasflux_config.yaml) in the specified directory.
If no directory is specified, the configuration file will be generated in the current directory.
{Fore.YELLOW}Usage:{Style.RESET_ALL} gasflux generate-config [OPTIONS] [CONFIG_DESTINATION]
{Fore.YELLOW}Options:{Style.RESET_ALL}
{Fore.BLUE}-h, --help{Style.RESET_ALL} Show this help message and exit
{Fore.YELLOW}Examples:{Style.RESET_ALL}
Process a single CSV file:
$ gasflux process {Fore.MAGENTA}"/path/to/data.csv"{Style.RESET_ALL}
Process all CSV files in a directory:
$ gasflux process {Fore.MAGENTA}"/path/to/data/directory"{Style.RESET_ALL}
Process a single CSV file with a specific configuration file:
$ gasflux process {Fore.MAGENTA}"/path/to/data.csv"{Style.RESET_ALL} --config-path {Fore.MAGENTA}/path/to/config.yaml{Style.RESET_ALL}
Process test data:
$ gasflux process {Fore.BLUE}--test{Style.RESET_ALL}
Generate a default configuration file in the current directory:
$ gasflux generate-config {Fore.MAGENTA}.{Style.RESET_ALL}
Generate a default configuration file in a specific directory recursively using a custom template:
$ gasflux generate-config {Fore.MAGENTA}"/path/to/directory"{Style.RESET_ALL} {Fore.BLUE}--recursive{Style.RESET_ALL} {Fore.BLUE}--template{Style.RESET_ALL} {Fore.MAGENTA}"/path/to/template.yaml"{Style.RESET_ALL}
""" # noqa
print(help_text)
if __name__ == "__main__":
main_cli()

View File

@ -0,0 +1,934 @@
#!/usr/bin/env python3
"""
无人机数据处理脚本
处理Excel格式的无人机测量数据转换为GasFlux标准输入格式。
支持两种使用方式:
1. 命令行调用python data_processor.py input.xlsx
2. 直接调用from data_processor import process_file; df = process_file('input.xlsx')
处理步骤:
1. 读取Excel文件
2. 删除不需要的列
3. 根据文件名修正时间格式
4. 坐标转换经纬度除以10^7
5. 计算气压使用qiya.py
6. 高度调整(减去最小高度)
7. 时间戳融合
8. 字段重命名
作者GasFlux开发团队
"""
import pandas as pd
import numpy as np
from pathlib import Path
import re
from datetime import datetime
import sys
import os
from collections import Counter
try:
from tqdm import tqdm
HAS_TQDM = True
except ImportError:
HAS_TQDM = False
print("⚠️ 未安装tqdm库将不显示进度条。如需进度条请运行: pip install tqdm")
def create_height_bins(heights, bin_size=2.0):
"""
将高度数据按指定间隔分档
Args:
heights: 高度数据Series
bin_size: 每个档位的间隔(米)
Returns:
list: [(bin_min, bin_max, bin_center, count), ...] 每个档位的信息
"""
if len(heights) == 0:
return []
height_min = heights.min()
height_max = heights.max()
# 计算需要的档位数量
range_size = height_max - height_min
if range_size == 0:
# 所有高度相同
return [(height_min, height_max, height_min, len(heights))]
num_bins = max(1, int(np.ceil(range_size / bin_size)))
bins = []
for i in range(num_bins):
bin_min = height_min + i * bin_size
bin_max = min(height_min + (i + 1) * bin_size, height_max)
bin_center = (bin_min + bin_max) / 2
# 统计这个档位有多少数据点
count = ((heights >= bin_min) & (heights < bin_max)).sum()
if i == num_bins - 1: # 最后一个档位包含上限
count = ((heights >= bin_min) & (heights <= bin_max)).sum()
if count > 0: # 只保留有数据的档位
bins.append((bin_min, bin_max, bin_center, count))
return bins
# 导入qiya模块
try:
from .qiya import get_pressure_at_location
print("✅ 成功导入qiya模块")
except ImportError as e:
print(f"❌ 导入qiya模块失败: {e}")
print("请确保GasFlux包结构完整")
sys.exit(1)
def load_excel_data(file_path):
"""
读取Excel文件并进行初步处理
Args:
file_path: Excel文件路径
Returns:
pd.DataFrame: 读取的数据
"""
try:
print(f"正在读取文件: {file_path}")
# 读取Excel文件
df = pd.read_excel(file_path)
print(f"✅ 成功读取数据:{len(df)} 行,{len(df.columns)}")
print(f"列名:{list(df.columns)}")
return df
except Exception as e:
print(f"❌ 读取文件失败: {e}")
sys.exit(1)
def remove_columns(df, columns_to_remove):
"""
删除指定的列
Args:
df: 输入DataFrame
columns_to_remove: 要删除的列名列表
Returns:
pd.DataFrame: 删除列后的DataFrame
"""
print(f"\n删除列: {columns_to_remove}")
# 检查要删除的列是否存在
existing_columns = [col for col in columns_to_remove if col in df.columns]
missing_columns = [col for col in columns_to_remove if col not in df.columns]
if missing_columns:
print(f"⚠️ 以下列不存在(跳过): {missing_columns}")
if existing_columns:
df = df.drop(columns=existing_columns)
print(f"✅ 已删除 {len(existing_columns)}")
return df
def extract_hour_from_filename(filename):
"""
从文件名中提取小时信息
例如: "08_34_01_间隔高度5m.xlsx" -> "08"
Args:
filename: 文件名
Returns:
str: 小时字符串(两位数)
"""
# 使用正则表达式匹配小时部分
match = re.match(r'(\d{2})_', filename)
if match:
return match.group(1)
else:
print(f"⚠️ 无法从文件名 '{filename}' 中提取小时信息,使用默认值 '00'")
return "00"
def fix_time_column(df, filename):
"""
根据文件名修正时间列
Args:
df: 输入DataFrame
filename: 文件名
Returns:
pd.DataFrame: 修正后的DataFrame
"""
print("修正时间格式...")
# 提取小时信息
hour_prefix = extract_hour_from_filename(filename)
print(f"从文件名提取的小时: {hour_prefix}")
# 检查时间列是否存在
if '时间' not in df.columns:
print("❌ 未找到 '时间'")
return df
# 修正时间格式
def fix_single_time(time_str):
if pd.isna(time_str):
return time_str
time_str = str(time_str).strip()
# 如果时间格式类似 "0:34:01" 或 "00:34:01"
if re.match(r'^\d{1,2}:\d{2}:\d{2}$', time_str):
parts = time_str.split(':')
original_hour = int(parts[0])
filename_hour = int(hour_prefix)
# 小时相加
new_hour = (filename_hour + original_hour) % 24 # 防止超过24小时
# 保持分钟和秒不变
new_time = f"{new_hour:02d}:{parts[1]}:{parts[2]}"
return new_time
else:
# 其他格式,使用默认时间
return f"{hour_prefix}:00:00"
# 应用时间修正
original_times = df['时间'].head(3).tolist()
df['时间'] = df['时间'].apply(fix_single_time)
corrected_times = df['时间'].head(3).tolist()
print(f"时间修正示例:")
for orig, corr in zip(original_times, corrected_times):
print(f" {orig}{corr}")
return df
def convert_coordinates(df):
"""
转换经纬度坐标除以10^7
Args:
df: 输入DataFrame
Returns:
pd.DataFrame: 转换后的DataFrame
"""
print("转换经纬度坐标...")
if '经度' in df.columns:
original_lon = df['经度'].head(3).tolist()
df['经度'] = df['经度'] / 1e7
converted_lon = df['经度'].head(3).tolist()
print("经度转换示例:")
for orig, conv in zip(original_lon, converted_lon):
print(".6f")
if '纬度' in df.columns:
original_lat = df['纬度'].head(3).tolist()
df['纬度'] = df['纬度'] / 1e7
converted_lat = df['纬度'].head(3).tolist()
print("纬度转换示例:")
for orig, conv in zip(original_lat, converted_lat):
print(".6f")
return df
def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_size=2.0):
"""
计算气压数据(高度分档优化版)
Args:
df: 输入DataFrame
max_samples: 最大采样数量None表示计算所有行
height_tolerance: 高度变化容差(米),如果所有高度都在此范围内,只计算一次
height_bin_size: 高度分档间隔(米),每个档位使用中间高度计算气压
Returns:
pd.DataFrame: 添加气压列的DataFrame
"""
print("计算气压数据...")
# 检查必要列是否存在
required_cols = ['日期', '时间', '经度', '纬度', '融合高程']
missing_cols = [col for col in required_cols if col not in df.columns]
if missing_cols:
print(f"❌ 缺少必要列: {missing_cols}")
return df
# 检查高度变化范围
height_min = df['融合高程'].min()
height_max = df['融合高程'].max()
height_range = height_max - height_min
print(f"🏔️ 高度范围: {height_min:.1f} - {height_max:.1f} 米 (变化: {height_range:.1f} 米)")
# 创建高度分档
height_bins = create_height_bins(df['融合高程'], height_bin_size)
print(f"📏 高度分档: {len(height_bins)} 个档位 (间隔: {height_bin_size:.1f} 米)")
for i, (bin_min, bin_max, bin_center, count) in enumerate(height_bins):
print(f" 档位{i+1}: {bin_min:.1f}-{bin_max:.1f}m (中心: {bin_center:.1f}m, 数据: {count}行)")
# 决定计算策略
if height_range <= height_tolerance:
# 高度变化小,只计算一次气压
print("🎯 高度变化小,将使用平均高度计算一次气压")
use_single_calculation = True
mean_height = df['融合高程'].mean()
print(f"📍 使用平均高度: {mean_height:.1f}")
elif len(height_bins) == 1:
# 只有一个高度档位,使用档位中心高度
print("📦 只有一个高度档位,使用档位中心高度")
use_single_calculation = True
mean_height = height_bins[0][2] # bin_center
print(f"📍 使用档位中心高度: {mean_height:.1f}")
else:
# 高度变化大,使用分档计算
print("🏗️ 使用高度分档策略减少API调用")
use_single_calculation = False
# 确定要处理的行数
if max_samples is None or max_samples >= len(df):
# 计算所有行
sample_df = df.copy()
actual_samples = len(df)
if not use_single_calculation:
print(f"📊 将计算所有 {len(df)} 行的气压数据")
else:
# 限制采样数量
print(f"⚠️ 数据量较大 ({len(df)} 行),只对前 {max_samples} 行计算气压")
sample_df = df.head(max_samples).copy()
actual_samples = max_samples
pressures = []
if use_single_calculation:
# 只计算一次气压
try:
# 使用第一行的日期和时间作为代表
first_row = sample_df.iloc[0]
# 转换日期格式 - 只提取日期部分,移除任何时间信息
date_str = str(first_row['日期'])
if ' ' in date_str:
date_str = date_str.split(' ')[0]
elif 'T' in date_str:
date_str = date_str.split('T')[0]
if '/' in date_str:
date_str = date_str.replace('/', '-')
date_parts = date_str.split('-')
if len(date_parts) == 3 and len(date_parts[0]) == 4:
year, month, day = date_parts
formatted_date = f"{year}-{month.zfill(2)}-{day.zfill(2)}"
else:
raise ValueError(f"日期格式异常: {date_str}")
# 使用数据的代表性时间(整点小时,众数)
time_strings = []
for time_val in sample_df['时间']:
time_str = str(time_val).strip()
if ':' in time_str:
# 确保是有效的 HH:MM 格式,然后取整点小时
parts = time_str.split(':')
if len(parts) >= 2:
try:
hour = int(parts[0])
# 确保小时在有效范围内 (0-23)
if 0 <= hour <= 23:
time_strings.append(f"{hour:02d}:00")
except ValueError:
continue
if time_strings:
time_counts = Counter(time_strings)
formatted_time = time_counts.most_common(1)[0][0]
occurrence_count = time_counts.most_common(1)[0][1]
print(f"数据时间选择: {formatted_time} ({occurrence_count}/{len(time_strings)} 次,{occurrence_count/len(time_strings)*100:.1f}%)")
else:
formatted_time = "12:00"
print("无有效时间数据使用默认中午12:00")
print("正在计算平均气压...")
pressure = get_pressure_at_location(
lat=sample_df['纬度'].mean(),
lon=sample_df['经度'].mean(),
altitude=mean_height,
date=formatted_date,
time=formatted_time
)
if pressure is not None:
pressures = [pressure] * len(sample_df)
print("✅ 平均气压计算成功,将应用到所有行")
else:
print("❌ 平均气压计算失败")
pressures = [None] * len(sample_df)
except Exception as e:
print(f"❌ 平均气压计算失败: {e}")
pressures = [None] * len(sample_df)
else:
# 使用高度分档策略
print("🏗️ 开始分档计算气压...")
# 为每个高度档位计算气压
bin_pressures = {} # bin_center -> pressure
# 设置进度条
iterator = height_bins
if HAS_TQDM:
iterator = tqdm(iterator, total=len(height_bins), desc="计算气压档位", unit="")
for bin_min, bin_max, bin_center, count in iterator:
try:
# 使用第一行数据作为代表来获取日期和时间
# 找到这个档位中的一行数据
bin_rows = sample_df[(sample_df['融合高程'] >= bin_min) &
(sample_df['融合高程'] <= bin_max)]
if len(bin_rows) == 0:
continue
first_row = bin_rows.iloc[0]
# 转换日期格式 - 只提取日期部分,移除任何时间信息
date_str = str(first_row['日期'])
if ' ' in date_str:
date_str = date_str.split(' ')[0]
elif 'T' in date_str:
date_str = date_str.split('T')[0]
if '/' in date_str:
date_str = date_str.replace('/', '-')
date_parts = date_str.split('-')
if len(date_parts) == 3 and len(date_parts[0]) == 4:
year, month, day = date_parts
formatted_date = f"{year}-{month.zfill(2)}-{day.zfill(2)}"
else:
print(f"⚠️ 档位高度 {bin_center:.1f}m 日期格式异常: {date_str}")
bin_pressures[bin_center] = None
continue
# 使用该档位数据的代表性时间(整点小时)
time_strings = []
for time_val in bin_rows['时间']:
time_str = str(time_val).strip()
if ':' in time_str:
# 确保是有效的 HH:MM 格式,然后取整点小时
parts = time_str.split(':')
if len(parts) >= 2:
try:
hour = int(parts[0])
# 确保小时在有效范围内 (0-23)
if 0 <= hour <= 23:
time_strings.append(f"{hour:02d}:00")
except ValueError:
continue
if time_strings:
# 使用最常见的时间(众数)
time_counts = Counter(time_strings)
formatted_time = time_counts.most_common(1)[0][0]
occurrence_count = time_counts.most_common(1)[0][1]
print(f" 档位时间选择: {formatted_time} ({occurrence_count}/{len(time_strings)} 次,{occurrence_count/len(time_strings)*100:.1f}%)")
else:
# 如果没有有效时间使用中午12点
formatted_time = "12:00"
print(" 无有效时间数据使用默认中午12:00")
# 计算这个档位的气压(使用平均位置和档位中心高度)
avg_lat = bin_rows['纬度'].mean()
avg_lon = bin_rows['经度'].mean()
pressure = get_pressure_at_location(
lat=avg_lat,
lon=avg_lon,
altitude=bin_center,
date=formatted_date,
time=formatted_time
)
bin_pressures[bin_center] = pressure
# 更新进度条
if HAS_TQDM:
success_count = sum(1 for p in bin_pressures.values() if p is not None)
iterator.set_description(f"计算档位 (成功: {success_count}/{len(bin_pressures)})")
except Exception as e:
print(f"❌ 计算高度档位 {bin_center:.1f}m 气压失败: {e}")
bin_pressures[bin_center] = None
# 为每一行分配对应档位的气压
pressures = []
for idx, row in sample_df.iterrows():
# 找到这个高度对应的档位
height = row['融合高程']
assigned_pressure = None
for bin_min, bin_max, bin_center, count in height_bins:
if bin_min <= height <= bin_max:
assigned_pressure = bin_pressures.get(bin_center)
break
pressures.append(assigned_pressure)
print(f"✅ 完成分档气压计算,共 {len(bin_pressures)} 个档位,{len([p for p in bin_pressures.values() if p is not None])} 个成功")
# 添加气压列
df['pressure'] = None # 初始化
df.loc[sample_df.index, 'pressure'] = pressures
# 对于未计算的行,使用插值或平均值填充
if max_samples is not None and len(df) > max_samples:
# 只计算了部分行,用平均值填充其余行
valid_pressures_for_mean = [p for p in pressures if p is not None]
if valid_pressures_for_mean:
mean_pressure = sum(valid_pressures_for_mean) / len(valid_pressures_for_mean)
df['pressure'] = df['pressure'].fillna(mean_pressure)
print(f"使用平均气压填充其余 {len(df) - max_samples} 行: {mean_pressure:.1f} hPa")
# 统计信息
valid_pressures = [p for p in pressures if p is not None]
if valid_pressures:
avg_pressure = sum(valid_pressures) / len(valid_pressures)
print(f"成功计算 {len(valid_pressures)}/{actual_samples} 个气压值,平均值: {avg_pressure:.1f} hPa")
else:
print("⚠️ 未能计算出任何气压值")
return df
def adjust_altitude(df):
"""
调整融合高程(减去最小值)
Args:
df: 输入DataFrame
Returns:
pd.DataFrame: 调整后的DataFrame
"""
print("调整融合高程...")
if '融合高程' in df.columns:
min_altitude = df['融合高程'].min()
print(".2f")
original_alt = df['融合高程'].head(3).tolist()
df['融合高程'] = df['融合高程'] - min_altitude
adjusted_alt = df['融合高程'].head(3).tolist()
print("高度调整示例:")
for orig, adj in zip(original_alt, adjusted_alt):
print(".2f")
return df
def merge_timestamp(df):
"""
融合日期和时间列为时间戳
Args:
df: 输入DataFrame
Returns:
pd.DataFrame: 融合后的DataFrame
"""
print("融合日期和时间...")
if '日期' in df.columns and '时间' in df.columns:
timestamps = []
for idx, row in df.iterrows():
try:
date_str = str(row['日期'])
time_str = str(row['时间'])
# 清理日期字符串 - 移除任何时间部分
date_str = date_str.strip()
if ' ' in date_str:
date_str = date_str.split(' ')[0] # 只取日期部分
if 'T' in date_str:
date_str = date_str.split('T')[0] # 处理ISO格式
# 标准化日期格式
if '/' in date_str:
date_str = date_str.replace('/', '-')
# 确保日期格式正确
date_parts = date_str.split('-')
if len(date_parts) == 3:
year, month, day = date_parts
date_formatted = f"{year.zfill(4)}-{month.zfill(2)}-{day.zfill(2)}"
else:
print(f"⚠️ 日期格式异常: '{date_str}',使用当前日期")
date_formatted = datetime.now().strftime("%Y-%m-%d")
# 时间字符串已经是修正后的格式(如 "08:34:01"),直接使用
time_str = time_str.strip()
if ':' in time_str and len(time_str.split(':')) >= 2:
time_formatted = time_str
else:
print(f"⚠️ 时间格式异常: '{time_str}',使用默认时间")
time_formatted = "12:00:00"
# 组合时间戳 - 直接连接日期和时间
timestamp = f"{date_formatted} {time_formatted}"
timestamps.append(timestamp)
except Exception as e:
print(f"❌ 处理第 {idx+1} 行时间戳失败: {e}")
timestamps.append(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
df['timestamp'] = timestamps
print("时间戳融合示例:")
for i in range(min(3, len(timestamps))):
print(f" {df.loc[i, '日期']} + {df.loc[i, '时间']}{timestamps[i]}")
return df
def rename_columns(df):
"""
重命名字段为GasFlux标准格式
Args:
df: 输入DataFrame
Returns:
pd.DataFrame: 重命名后的DataFrame
"""
print("重命名字段...")
# 定义字段映射
column_mapping = {
'timestamp': 'timestamp', # 时间戳(已创建)
'经度': 'longitude', # 经度 → latitude
'纬度': 'latitude', # 纬度 → longitude
'融合高程': 'height_ato', # 融合高程 → height_ato
'修正风向': 'winddir', # 修正风向 → winddir
'修正风速': 'windspeed', # 修正风速 → windspeed
'风温': 'temperature', # 风温 → temperature
'pressure': 'pressure', # 气压(已计算)
'CH4': 'ch4', # CH4保持不变
'pitch': 'course_elevation', # pitch → course_elevation
'yaw': 'course_azimuth' # yaw → course_azimuth
}
# 重命名存在的列
columns_to_rename = {}
for old_name, new_name in column_mapping.items():
if old_name in df.columns:
columns_to_rename[old_name] = new_name
if columns_to_rename:
df = df.rename(columns=columns_to_rename)
print("字段重命名:")
for old, new in columns_to_rename.items():
print(f" {old}{new}")
# 只保留GasFlux需要的列
required_columns = ['timestamp', 'latitude', 'longitude', 'height_ato', 'windspeed', 'winddir', 'temperature', 'pressure', 'ch4', 'course_elevation', 'course_azimuth']
existing_required_columns = [col for col in required_columns if col in df.columns]
if len(existing_required_columns) != len(required_columns):
missing = [col for col in required_columns if col not in df.columns]
print(f"⚠️ 缺少必需列: {missing}")
# 移除不需要的列,只保留必需的列
df = df[existing_required_columns]
print(f"最终保留列: {existing_required_columns}")
return df
def process_excel_file(file_path):
"""
处理单个Excel文件的主函数
Args:
file_path: Excel文件路径
"""
print(f"=== 开始处理文件: {file_path} ===\n")
# 获取文件名(用于时间修正)
filename = Path(file_path).name
# 1. 读取数据
df = load_excel_data(file_path)
# 2. 删除不需要的列
columns_to_remove = [
'高程', '速度x', '速度y', '速度z',
'四元数_q0', '四元数_q1', '四元数_q2', '四元数_q3',
'roll', 'H2O', # 保留pitch和yaw将重命名为course_elevation和course_azimuth
'原始风向', '原始风速'
]
df = remove_columns(df, columns_to_remove)
# 3. 修正时间格式
df = fix_time_column(df, filename)
# 4. 坐标转换
df = convert_coordinates(df)
# 5. 计算气压
df = calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_size=2.0) # 计算所有行高度容差10米分档2米
# 6. 高度调整
df = adjust_altitude(df)
# 7. 时间戳融合
df = merge_timestamp(df)
# 调试:检查当前列
print(f"时间戳融合后列名: {list(df.columns)}")
if 'timestamp' in df.columns:
print(f"timestamp列示例: {df['timestamp'].head(3).tolist()}")
# 8. 字段重命名
df = rename_columns(df)
# 保存处理结果
output_path = Path(file_path).with_suffix('.processed.csv')
df.to_csv(output_path, index=False)
print(f"\n✅ 处理完成!")
print(f"📁 输出文件: {output_path}")
print(f"📊 最终数据形状: {df.shape[0]}× {df.shape[1]}")
print(f"📋 最终列名: {list(df.columns)}")
return df
def process_file(input_file, output_file=None):
"""
直接处理Excel文件的函数不使用命令行参数
Args:
input_file: 输入Excel文件路径字符串或Path对象
output_file: 输出CSV文件路径可选字符串或Path对象
Returns:
pd.DataFrame: 处理后的DataFrame
"""
# 转换为Path对象
input_path = Path(input_file)
# 检查输入文件
if not input_path.exists():
raise FileNotFoundError(f"输入文件不存在: {input_path}")
if input_path.suffix.lower() not in ['.xlsx', '.xls']:
raise ValueError(f"输入文件必须是Excel格式 (.xlsx 或 .xls),当前文件: {input_path}")
# 处理文件
df = process_excel_file(str(input_path))
# 如果指定了输出路径,额外保存一份
if output_file:
output_path = Path(output_file)
df.to_csv(output_path, index=False)
print(f"📁 额外保存到: {output_path}")
return df
def interactive_input():
"""
交互式输入模式 - 手动输入参数
Returns:
tuple: (input_file, output_file) 文件路径元组
"""
print("=== 手动输入模式 ===")
print("请按照提示输入参数...\n")
# 输入文件路径
while True:
input_file = input("请输入Excel文件路径 (例如: data.xlsx): ").strip()
if not input_file:
print("❌ 文件路径不能为空,请重新输入")
continue
input_path = Path(input_file)
if not input_path.exists():
print(f"❌ 文件不存在: {input_path}")
print("提示: 请确保文件路径正确,或者将文件放在当前目录下")
continue
if input_path.suffix.lower() not in ['.xlsx', '.xls']:
print(f"❌ 文件格式错误: {input_path.suffix}")
print("只支持 .xlsx 和 .xls 格式的Excel文件")
continue
break
# 输出文件路径(可选)
output_file = input("请输入输出CSV文件路径 (可选,直接回车使用默认): ").strip()
if not output_file:
output_file = None
print("使用默认输出文件名")
print(f"\n✅ 输入确认:")
print(f" 输入文件: {input_file}")
print(f" 输出文件: {output_file or '自动生成'}")
confirm = input("\n确认开始处理? (y/N): ").strip().lower()
if confirm not in ['y', 'yes', '', '确认']:
print("❌ 用户取消操作")
return None, None
return input_file, output_file
def main(input_file=None, output_file=None, interactive=False):
"""
主函数 - 支持多种输入方式
Args:
input_file: 输入文件路径(直接调用时使用)
output_file: 输出文件路径(直接调用时使用)
interactive: 是否启用交互式输入模式
"""
# 如果启用交互式输入
if interactive:
input_file, output_file = interactive_input()
if input_file is None:
return None
# 如果提供了直接参数,使用直接参数
if input_file is not None:
try:
return process_file(input_file, output_file)
except Exception as e:
print(f"❌ 处理失败: {e}")
raise
# 否则使用命令行参数
import argparse
parser = argparse.ArgumentParser(
description="无人机数据处理工具 - 将Excel数据转换为GasFlux格式",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用方式:
1. 命令行模式:
python data_processor.py data.xlsx
python data_processor.py data.xlsx -o output.csv
2. 交互式模式:
python data_processor.py --interactive
3. 直接调用:
from data_processor import process_file
df = process_file('data.xlsx', 'output.csv')
4. Python脚本调用:
from data_processor import main
df = main(input_file='data.xlsx', output_file='output.csv')
处理步骤:
1. 读取Excel文件
2. 删除不需要的列
3. 根据文件名修正时间格式
4. 经纬度坐标转换 (除以10^7)
5. 计算气压数据
6. 高度调整 (减去最小值)
7. 时间戳融合
8. 字段重命名为GasFlux格式
"""
)
parser.add_argument('input_file', nargs='?', help='输入的Excel文件路径')
parser.add_argument('-o', '--output', help='输出CSV文件路径可选默认自动生成')
parser.add_argument('-i', '--interactive', action='store_true', help='启用交互式输入模式')
args = parser.parse_args()
# 如果启用交互式模式
if args.interactive:
input_file, output_file = interactive_input()
if input_file is None:
return None
else:
input_file = args.input_file
output_file = args.output
# 如果没有提供输入文件,显示帮助和使用示例
if not input_file:
parser.print_help()
print("\n" + "="*60)
print("📖 使用示例:")
print("="*60)
print("1. 命令行模式:")
print(" python data_processor.py your_file.xlsx")
print(" python data_processor.py data.xlsx -o output.csv")
print("")
print("2. Python脚本中直接调用:")
print(" from data_processor import process_file")
print(" df = process_file('input.xlsx')")
print(" df = process_file('input.xlsx', 'output.csv')")
print("")
print("3. 交互式模式:")
print(" python data_processor.py --interactive")
print("="*60)
return None
# 检查输入文件
input_path = Path(input_file)
if not input_path.exists():
print(f"❌ 错误:输入文件不存在: {input_path}")
sys.exit(1)
if input_path.suffix.lower() not in ['.xlsx', '.xls']:
print(f"❌ 错误输入文件必须是Excel格式 (.xlsx 或 .xls)")
sys.exit(1)
# 处理文件
try:
df = process_excel_file(str(input_path))
# 如果指定了输出路径,额外保存一份
if output_file:
output_path = Path(output_file)
df.to_csv(output_path, index=False)
print(f"📁 额外保存到: {output_path}")
return df
except KeyboardInterrupt:
print("\n⚠️ 用户中断处理")
sys.exit(1)
except Exception as e:
print(f"\n❌ 处理失败: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
# 当直接运行脚本时,使用命令行参数模式
main()

58
src/gasflux/gas.py Normal file
View File

@ -0,0 +1,58 @@
"""functions related to gas transformations and calculations, e.g. density, point flux etc."""
import molmass
import pandas as pd
gas_variables = {
"standard_pressure": 1013.25, # hPa/mbar
"standard_temperature": 273.15, # degrees K
"standard_molar_volume": 0.022413969545014, # m3⋅mol-1
}
def mass(formula: str) -> float:
"""Return the molar mass of a gas in g/mol."""
return molmass.Formula(formula.upper()).mass # only accepts capital letters
def gas_density(local_pressure: float, local_temperature_celsius: float, gas: str) -> float: # millibars and celsius
"""
Calculate the density of a gas in kg/m3 based on local pressure and temperature.
Parameters:
- local_pressure: The local pressure in hPa/mbar.
- local_temperature: The local temperature in degrees Celsius.
- gas: The chemical formula of the gas.
Returns:
- The density of the gas in kg/m3.
Assumes ideal gas behavior.
"""
local_temperature_kelvin = local_temperature_celsius + gas_variables["standard_temperature"]
local_volume = (
gas_variables["standard_molar_volume"]
* (gas_variables["standard_pressure"] / local_pressure)
* ((local_temperature_kelvin + gas_variables["standard_temperature"]) / gas_variables["standard_temperature"])
) # m3⋅mol-1
return mass(gas) / 1000 / local_volume
def gas_flux_column(df: pd.DataFrame, gas: str, wind: str = "windspeed") -> pd.DataFrame:
"""
Add columns to the DataFrame for the gas density, mass, and flux.
Parameters:
- df: The DataFrame.
- gas: The chemical formula of the gas.
- wind: The column name for the wind speed (NB - must be perpendicular to the plane)
Returns:
- The DataFrame with the added columns.
"""
average_temp = df["temperature"].mean() # celsius
average_pressure = df["pressure"].mean() # hPa
gd = gas_density(local_pressure=average_pressure, local_temperature_celsius=average_temp, gas=gas) # kg/m3
df[f"{gas}_kg_m3"] = gd * (df[f"{gas}_normalised"] * 1e-6) # kg/m3
df[f"{gas}_kg_h_m2"] = df[f"{gas}_kg_m3"] * df[wind] * 60 * 60 # kg/h/m2
return df

View File

@ -0,0 +1,69 @@
# gasflux_config.yaml
output_dir: ~/gasflux_reports
# required columns and maximum ranges
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [-200, 500] # meters above takeoff
windspeed: [0, 50] # m/s
winddir: [0, 360] # degrees
temperature: [-50, 60] # degrees Celsius
pressure: [900, 1100] # hPa/mb
# optional gas columns and maximum ppm ranges. Relative concentrations are used so offset can be wrong as long as gain and linearity are correct.
gases:
ch4: [1.5, 500]
co2: [300, 5000]
c2h6: [-0.5, 10]
strategies:
background: "algorithm" # currently only algorithm (via pybaselines) is supported
sensor: "insitu" # currently only insitu is supported
spatial: "curtain" # currently "curtain" and "spiral" are supported
interpolation: "kriging" # currently only kriging is supported
# baseline settings.
algorithmic_baseline_settings:
algorithm: fastchrom
fastchrom: {
"half_window": 6,
"threshold": "custom", #
"min_fwhm": ~,
"interp_half_window": 3,
"smooth_half_window": 3,
"weights": ~,
"max_iter": 100,
"min_length": 2}
fabc : {
"lam": 10000, # The smoothing parameter. Larger values will create smoother baselines. Default is 1e6.
"scale": 10, # The scale at which to calculate the continuous wavelet transform. Should be approximately equal to the index-based full-width-at-half-maximum of the peaks or features in the data. Default is None, which will use half of the value from optimize_window(), which is not always a good value, but at least scales with the number of data points and gives a starting point for tuning the parameter.
"diff_order": 2} # The order of the differential matrix. Must be greater than 0. Default is 2 (second order differential matrix). Typical values are 2 or 1.
dietrich : {
"poly_order": 5,
"smooth_half_window": 5,}
golotvin : {
"half_window": 2,
"sections": 10}
# kriging settings
semivariogram_settings:
model: spherical
estimator: cressie
n_lags: 20
bin_func: even
fit_method: lm
### Size of the search window; if the algorithm complains about not having enough neighbours, consider increasing these
maxlag: 100 # in meters.
tolerance: 10 # in degrees
azimuth: 0 # in degrees (0 is right/horizontal)
bandwidth: 20 # in meters
# fit_sigma: linear # this should allow for a spatial uncertainty but currently producing bugs
ordinary_kriging_settings:
min_points: 3
max_points: 100
grid_resolution: 500
min_nodes: 10
y_min: ~ # manual override for the minimum y value. Leave blank or ~ to use ymin.
cut_ground: True # cuts everything below the ground level in the krig (need height_agl to work at the moment)

View File

@ -0,0 +1,171 @@
"""Functions related to kriging and other kinds of interpolation"""
import numpy as np
import pandas as pd
import skgstat as skg
from scipy import integrate
from . import plotting
def simpsonintegrate(array: np.ndarray, x_cell_size: float, y_cell_size: float) -> float:
"""Function to obtain the volume of the krig in kgh⁻¹, i.e. the cut-fill volume
(negative volumes from background noise are subtracted)."""
grid = np.nan_to_num(array.copy(), copy=False, nan=0)
vol_rows = integrate.simpson(np.transpose(grid)) # this integrates along each row of the grid
vol_grid = integrate.simpson(vol_rows) # this integrates the rows together
return vol_grid * x_cell_size * y_cell_size # type: ignore
def directional_gas_semivariogram(
df: pd.DataFrame, x: str, z: str, gas: str, semivariogram_filter: float | None = None, **semivariogram_settings
):
"""Function to calculate the directional semivariogram - typically horizontally - of a gas in a dataframe."""
if semivariogram_filter:
df = df[df[gas] > semivariogram_filter]
v = skg.DirectionalVariogram(
df[[x, z]].to_numpy(),
df[gas].to_numpy(),
**semivariogram_settings,
)
return v
def ordinary_kriging(
df: pd.DataFrame,
x: str,
y: str,
gas: str,
ordinary_kriging_settings: dict,
semivariogram_filter: float | None = None,
**semivariogram_settings,
):
"""Function to calculate the ordinary kriging of a gas in a dataframe, after calculating a semivariogram."""
gasflux = f"{gas}_kg_h_m2"
skg.plotting.backend("plotly") # type: ignore
cut_ground = ordinary_kriging_settings["cut_ground"]
semivariogram = directional_gas_semivariogram(df, x, y, gasflux, semivariogram_filter, **semivariogram_settings)
ok = skg.OrdinaryKriging(
semivariogram,
coordinates=df[[x, y]].to_numpy(),
values=df[gasflux].to_numpy(),
min_points=ordinary_kriging_settings["min_points"],
max_points=ordinary_kriging_settings["max_points"],
)
x_max = df[x].max()
x_min = df[x].min()
y_max = df[y].max()
y_min = df[y].min() if ordinary_kriging_settings["y_min"] is None else ordinary_kriging_settings["y_min"]
if cut_ground is True:
df["ground_elevation_ato"] = df.loc[:, "height_ato"] - df.loc[:, "height_agl"]
y_min = min(df["ground_elevation_ato"].min(), y_min)
x_range, y_range = x_max - x_min, y_max - y_min
cell_rough_size = np.sqrt((x_range * y_range) / ordinary_kriging_settings["grid_resolution"])
x_nodes, y_nodes = (
max(int(r / cell_rough_size), ordinary_kriging_settings["min_nodes"]) for r in [x_range, y_range]
)
x_cell_size = (x_max - x_min) / x_nodes
y_cell_size = (y_max - y_min) / y_nodes
xx, yy = np.mgrid[
x_min : x_max : x_nodes * 1j,
y_min : y_max : y_nodes * 1j, # type: ignore
] # type: ignore
field = ok.transform(xx.flatten(), yy.flatten()).reshape(xx.shape)
if cut_ground:
field = remove_values_below_ground(df, field, xx, yy)
volume = simpsonintegrate(field, x_cell_size, y_cell_size)
fieldpos = np.copy(field)
fieldpos[fieldpos < 0] = 0
volumepos = simpsonintegrate(fieldpos, x_cell_size, y_cell_size)
fieldneg = np.copy(field)
fieldneg[fieldneg > 0] = 0
volumeneg = simpsonintegrate(fieldneg, x_cell_size, y_cell_size)
error_1s = ok.sigma.reshape(xx.shape)
# np.nan_to_num(error_1s, copy=False, nan=0)
volume_error = simpsonintegrate(error_1s, x_cell_size, y_cell_size)
contour_plot = plotting.contour_krig(df=df, gas=gas, xx=xx, yy=yy, field=field, x=x, y=y, cut_ground=cut_ground)
grid_plot = plotting.heatmap_krig(xx, yy, field)
output_text = (
f"The emissions flux of {gas.upper()} is {volume:.3f}kgh⁻¹; "
f"the cut and fill volumes of the grid are {volumepos:.3f} and {volumeneg:.3f}kgh⁻¹. "
f"The grid itself is {x_nodes}x{y_nodes} nodes, with nodes measuring {x_cell_size:.2f}m x {y_cell_size:.2f}m."
)
krig_variables = {
"gas": gas,
"field": field,
"fieldpos": fieldpos,
"fieldneg": fieldneg,
"xx": xx,
"yy": yy,
"volume": volume,
"volumepos": volumepos,
"volumeneg": volumeneg,
"error field (1 sigma)": error_1s,
"volume_error": volume_error,
}
semivariogram_plot = semivariogram.plot(show=False)
return krig_variables, output_text, contour_plot, grid_plot, semivariogram_plot
def remove_values_below_ground(
df: pd.DataFrame, field: np.ndarray, xx: np.ndarray, yy: np.ndarray, x: str = "x", alt: str = "height_ato"
) -> np.ndarray:
"""
Adjust field values based on elevation data, setting values below ground to NaN.
"""
max_x = df[x].max()
max_y = df[alt].max()
x_right = np.empty_like(xx)
x_right[:-1, :] = xx[1:, :]
x_right[-1, :] = max_x
x_points = (xx + x_right) / 2
y_top = np.empty_like(yy)
y_top[:, :-1] = yy[:, 1:]
y_top[:, -1] = max_y
y_points = (yy + y_top) / 2
x_points_flat = x_points.ravel()
y_points_flat = y_points.ravel()
ground_levels = compute_relative_ground_levels(df, x_points_flat)
below_ground = y_points_flat < ground_levels
field_flat = field.ravel()
field_flat[below_ground] = np.nan
return field_flat.reshape(field.shape)
def compute_relative_ground_levels(
df: pd.DataFrame, x_points: np.ndarray, y1: str = "height_agl", y2: str = "height_ato"
) -> np.ndarray:
"""
Calculate ground levels at given x coordinates, considering elevation above ground and takeoff altitude. A
sort of janky averaged DEM, basically. Will accept either ground elevation and altitude, or height above ground
level and height above takeoff as inputs for y1 and y2.
"""
df_clean = df.dropna(subset=[y1, y2])
df_sorted = df_clean.sort_values(by="x").drop_duplicates(subset="x")
y1_at_x = np.interp(x_points, df_sorted["x"], df_sorted[y1])
y2_at_x = np.interp(x_points, df_sorted["x"], df_sorted[y2])
return y2_at_x - y1_at_x
# def additive_row_integration(df: pd.DataFrame, rowlabel: str = "slice"):
# """2D integration of a dataframe along the x-axis, with the altitude as the y-axis."""
# integrals = {}
# for i in range(df[rowlabel].max() + 1):
# df_slice = df[df[rowlabel] == i]
# df_slice = df_slice.sort_values(by="x")
# line_integral = integrate.simpson(y=df_slice["ch4_kg_h_m2"], x=df_slice["x"])
# area_integral = line_integral * (df_slice["altitude"].max() - df_slice["altitude"].min())
# integrals[i] = area_integral
# return integrals

61
src/gasflux/ml.py Normal file
View File

@ -0,0 +1,61 @@
"""Experimental module for machine learning flight filtering"""
import os
import joblib
import pandas as pd
from . import plotting
import plotly.graph_objects as go
model = None # Lazy loading: Load the model only if it hasn't been loaded yet
def load_model():
"""Load the model from the model file path. If the model has already been loaded, return it."""
global model
if model is None:
default_model_path = os.path.join(os.path.dirname(__file__), "resources/model.pkl")
model_file_path = os.getenv("GASFLUX_MODEL_PATH", default_model_path)
try:
model = joblib.load(model_file_path)
except FileNotFoundError as e:
raise FileNotFoundError(f"Model file not found at {model_file_path}. Please check the file path.") from e
except Exception as e:
raise Exception("An error occurred while loading the model.") from e
return model
def make_prediction(
df: pd.DataFrame,
course_elevation="course_elevation",
height_ato="height_ato",
horiz_spd="horiz_spd",
z_spd="z_spd",
) -> tuple[pd.DataFrame, go.Figure]:
"""Make predictions based on the input DataFrame and add them to the DataFrame.
:param df: DataFrame containing the required features
:param course_azimuth: Name of the column containing the course azimuth
:param course_elevation: Name of the column containing the course elevation
:param height_ato: Name of the column containing the height above take-off
:param idx: Name of the column containing the index
return: Tuple of the DataFrame with the predictions and a Plotly 3D scatter plot of the predictions
"""
model = load_model()
# Ensure the DataFrame contains all the required features
required_features = [course_elevation, height_ato, horiz_spd, z_spd]
if not all(feature in df.columns for feature in required_features):
missing_features = [feature for feature in required_features if feature not in df.columns]
raise ValueError(f"DataFrame is missing (or mislabelled) the following required features: {missing_features}")
# make idx col if not present
if "idx" not in df.columns:
df["idx"] = df.index
cols_for_model = ["course_elevation", "height_ato", "idx", "horiz_spd", "z_spd"]
predictions = model.predict(df[cols_for_model])
df["predictions"] = predictions
fig = plotting.scatter_3d(df)
return df, fig

609
src/gasflux/plotting.py Normal file
View File

@ -0,0 +1,609 @@
"""Various plotting functions mainly based around plotly."""
import matplotlib.colors as mcolors
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
import simplekml
from plotly.subplots import make_subplots
from . import processing
pio.templates["default"] = go.layout.Template(
layout=go.Layout(
margin=go.layout.Margin(l=0, r=0, b=0, t=0, pad=0),
),
)
pio.templates.default = "simple_white+default"
styling = {
"colorscale": "geyser",
}
def blank_figure():
fig = go.Figure()
return fig
def scatter_3d(
df: pd.DataFrame,
color: str = "",
colorbar_title: str = "",
timestamp: str = "timestamp",
x: str = "utm_easting",
y: str = "utm_northing",
z: str = "height_ato",
courses: bool = False,
):
fig = px.scatter_3d(df, x=x, y=y, z=z)
if color:
custom_data = [df[timestamp]]
if courses:
custom_data.extend([df["course_elevation"], df["course_azimuth"]])
custom_data = np.stack(custom_data, axis=-1)
hover_template = [
f"{x}: %{{x:.2f}}",
f"{y}: %{{y:.2f}}",
f"{z}: %{{z:.2f}}",
f"{color}: %{{marker.color:.2f}}",
f"{timestamp}: %{{customdata[0]|%Y-%m-%d %H:%M:%S}}",
"Index: %{pointNumber}",
]
if courses:
hover_template.extend(
[
"Course Elevation: %{customdata[1]:.2f}",
"Course Azimuth: %{customdata[2]:.2f}",
]
)
hover_template_str = "<br>".join(hover_template)
fig.update_traces(
marker=dict(
color=df[color],
size=4,
opacity=0.5,
colorscale=styling["colorscale"],
colorbar=dict(title=colorbar_title),
),
customdata=custom_data,
hovertemplate=hover_template_str,
)
return fig
def scatter_2d(
df: pd.DataFrame,
x: str,
color: str,
y: str = "height_ato",
**kwargs,
):
fig = px.scatter(
df,
x=x,
y=y,
color=color,
color_continuous_scale=styling["colorscale"],
opacity=0.8,
**kwargs,
)
fig.update_traces(
customdata=df.index,
hovertemplate="<br>".join(
[
"x: %{x:.2f}",
"height_ato: %{y:.2f}",
f"{color}: %{{marker.color:.2f}}",
"Time: %{customdata}",
],
),
)
return fig
def time_series(
df: pd.DataFrame,
ys: str | list[str],
x: str = "timestamp",
color: str | None = None,
split=None,
y_mins: float | list[float | int] | None = None,
rolling_average: bool = True,
scatter: bool = True,
rolling_window: int = 5,
y_titles: str | list[str] | None = None,
legend: bool = True,
) -> go.Figure:
colors = px.colors.qualitative.Plotly
if isinstance(ys, str):
ys = [ys]
if y_titles is None:
y_titles = ys
single_title = False
elif isinstance(y_titles, str):
y_titles = [y_titles]
single_title = True
elif isinstance(y_titles, list):
if len(y_titles) != len(ys):
raise ValueError("Length of y_titles must be equal to length of ys")
single_title = False
else:
raise ValueError("Invalid y_titles value")
if isinstance(y_mins, (float | int)):
y_mins = [y_mins]
if isinstance(y_mins, list):
if len(y_mins) != len(ys):
raise ValueError("Length of y_mins must be equal to length of ys")
fig = go.Figure()
axis_space = 0.05
domain_start = axis_space * (len(ys)) if len(ys) > 1 else 0
fig.update_layout(
xaxis=dict(
domain=[domain_start, 1],
),
)
for i, y in enumerate(ys):
yaxis_name = f"yaxis{i+1}"
yaxis_ref = f"y{i+1}"
trace_color = "black" if single_title and i == 0 else colors[i % len(colors)]
marker_i = dict(size=8, opacity=0.3 if rolling_average else 0.5, color=trace_color)
if color is not None:
marker_i["color"] = df[color] # type: ignore
marker_i["colorscale"] = styling["colorscale"]
hover_template = f"{x}: %{{x}}<br>{y}: %{{y:.2f}}<br>"
if color:
hover_template += f"{color}: %{{marker.color:.2f}}<br>"
if scatter:
fig.add_trace(
go.Scatter(
x=df[x],
y=df[y],
name=y,
mode="markers",
marker=marker_i,
yaxis=yaxis_ref,
hovertemplate=hover_template,
showlegend=legend,
)
)
if rolling_average:
df[f"rolling_avg_{i}"] = df[y].rolling(window=rolling_window, min_periods=1).mean()
fig.add_trace(
go.Scatter(
x=df[x],
y=df[f"rolling_avg_{i}"],
name=f"{y} {rolling_window}-point avg",
mode="lines",
line=dict(color=trace_color, width=2),
yaxis=yaxis_ref,
showlegend=legend,
)
)
y_data = df[y]
y_min_var = y_data.min()
y_max_var = y_data.max()
y_range = y_max_var - y_min_var or y_max_var * 0.05
y_axis_min = y_mins[i] if y_mins is not None and y_mins[i] is not None else y_min_var - y_range * 0.05
y_axis_max = y_max_var + y_range * 0.05
if single_title and i == 0:
axis_title = dict(text=y_titles[0], font=dict(color="black"))
elif not single_title:
axis_title = dict(text=y_titles[i], font=dict(color=trace_color))
else:
axis_title = None
axis_config = dict(
title=axis_title,
tickfont=dict(color=trace_color),
range=[y_axis_min, y_axis_max],
side="left",
position=axis_space * i if i > 0 else None,
anchor="free" if i > 0 else None,
overlaying="y" if i > 0 else None,
showgrid=(i == 0),
)
fig.layout[yaxis_name] = axis_config
if split is not None:
fig.add_shape(
type="line",
xref="x",
yref="paper",
x0=split,
y0=0,
x1=split,
y1=1,
line=dict(color="red", width=2),
)
return fig
def background_plotting(df: pd.DataFrame, gas: str):
fig = make_subplots(specs=[[{"secondary_y": True}]])
ymin = df[gas].min()
ymax = df[gas].max()
ylim = [ymin * 0.95, ymax * 1.05]
y2min = df[f"{gas}_normalised"].min()
y2lim = (y2min, y2min + (ylim[1] - ylim[0]))
fig.update_yaxes(range=ylim, secondary_y=False, title_text=f"Sensor {gas} (ppm)")
fig.update_yaxes(range=y2lim, secondary_y=True, title_text=f"Normalised {gas} (ppm)")
fig.add_scatter(x=df["timestamp"], y=df[gas], opacity=0.3, name="Raw Data")
fig.add_scatter(
x=df["timestamp"], y=df[f"{gas}_fit"], mode="lines", name="Fitted Background", line=dict(dash="dash")
)
fig.add_scatter(
x=df["timestamp"], y=df[f"{gas}_normalised"], yaxis="y2", name="Normalised Data", mode="lines", opacity=0.5
)
fig.add_scatter(
x=df["timestamp"],
y=np.where(df[f"{gas}_signal"], df[f"{gas}_normalised"], np.nan),
yaxis="y2",
name="Classed as signal",
mode="lines",
opacity=0.5,
# color
# mode="markers",
# marker=dict(size=3),
)
return fig
def windrose_process(df: pd.DataFrame):
beaufort = {
"0": [0, 1],
"1": [1, 2],
"2": [2, 4],
"3": [4, 6],
"4": [6, 9],
"5": [9, 11],
"6": [11, 14],
"7": [14, 17],
"8": [17, 21],
"9": [21, 25],
"10": [25, 29],
"11": [29, 33],
"12": [33, 200],
}
beaufort_ms = {
"0": "0-1",
"1": "1-2",
"2": "2-4",
"3": "4-6",
"4": "6-9",
"5": "9-11",
"6": "11-14",
"7": "14-17",
"8": "17-21",
"9": "21-25",
"10": "25-29",
"11": "29-33",
"12": "33+",
}
cardinals = {
"N1": [0, 11.25],
"NNE": [11.25, 33.75],
"NE": [33.75, 56.25],
"ENE": [56.25, 78.75],
"E": [78.75, 101.25],
"ESE": [101.25, 123.75],
"SE": [123.75, 146.25],
"SSE": [146.25, 168.75],
"S": [168.75, 191.25],
"SSW": [191.25, 213.75],
"SW": [213.75, 236.25],
"WSW": [236.25, 258.75],
"W": [258.75, 281.25],
"WNW": [281.25, 303.75],
"NW": [303.75, 326.25],
"NNW": [326.25, 348.75],
"N2": [348.75, 360],
}
df["wind_direction_bin"] = pd.cut(
df["winddir"],
bins=[lower for lower, upper in cardinals.values()] + [list(cardinals.values())[-1][1]],
labels=[key for key in cardinals],
right=False,
)
df["wind_direction_bin"] = (
df["wind_direction_bin"].map(lambda x: "N" if x in ["N1", "N2"] else x).astype("category")
)
df["beaufort"] = pd.cut(
df["windspeed"],
bins=[lower for lower, upper in beaufort.values()] + [list(beaufort.values())[-1][1]],
labels=[key for key in beaufort],
right=False,
)
df["beaufort_ms"] = df["beaufort"].map(beaufort_ms)
df_windrose = df.groupby(["wind_direction_bin", "beaufort"], observed=False).size().reset_index(name="count") # type: ignore
df_windrose["frequency"] = df_windrose["count"] / df_windrose["count"].sum() * 100
df_windrose["wind_direction_bin_degs"] = df_windrose["wind_direction_bin"].cat.rename_categories(
{
"N": 0,
"NNE": 22.5,
"NE": 45,
"ENE": 67.5,
"E": 90,
"ESE": 112.5,
"SE": 135,
"SSE": 157.5,
"S": 180,
"SSW": 202.5,
"SW": 225,
"WSW": 247.5,
"W": 270,
"WNW": 292.5,
"NW": 315,
"NNW": 337.5,
},
)
df_windrose["beaufort"] = df_windrose["beaufort"].astype(int)
return df_windrose
def windrose_graph(df, plot_transect=False, theta1=None, theta2=None):
n_colors = 13
colors = px.colors.sample_colorscale("turbo", [n / (n_colors - 1) for n in range(n_colors)])
fig = px.bar_polar(
df,
r="frequency",
theta="wind_direction_bin_degs",
color="beaufort",
labels={
"frequency": "Frequency (%)",
"wind_direction_bin": "Direction",
"beaufort": "Beaufort Scale",
},
color_discrete_map=colors,
)
fig.update_layout(polar=dict(radialaxis={"visible": False, "showticklabels": False}))
fig.update_layout(
polar=dict(
angularaxis={
"showgrid": False,
},
),
)
fig.update_layout(polar_bargap=0)
if plot_transect:
max_freq = df.groupby("wind_direction_bin", observed=False)["frequency"].sum().max()
fig.add_trace(
go.Scatterpolar(
r=[max_freq, max_freq],
theta=[theta1, theta2],
mode="lines",
line=dict(color="black", width=2, dash="dash"),
showlegend=False,
),
)
return fig
def windrose(df: pd.DataFrame, plot_transect=False):
df_windrose = windrose_process(df)
if plot_transect:
theta1, theta2 = processing.bimodal_azimuth(df)
fig = windrose_graph(df_windrose, plot_transect=plot_transect, theta1=theta1, theta2=theta2)
else:
fig = windrose_graph(df_windrose, plot_transect=plot_transect)
return fig
def outliers(original_data: pd.Series, fence_high: float, fence_low: float):
outliers = np.array(original_data > fence_high) | (original_data < fence_low)
fig = make_subplots(rows=1, cols=2, shared_yaxes=True)
fig.add_trace(px.strip(original_data, color=outliers).data[0], row=1, col=1)
if sum(outliers) > 0:
fig.add_trace(px.strip(original_data, color=outliers).data[1], row=1, col=1)
fig.add_shape(
go.layout.Shape(
type="line",
x0=-0.5,
y0=fence_high,
x1=0.5,
y1=fence_high,
line=dict(color="red", width=2),
),
row=1,
col=1,
)
fig.add_shape(
go.layout.Shape(
type="line",
x0=-0.5,
y0=fence_low,
x1=0.5,
y1=fence_low,
line=dict(color="red", width=2),
),
row=1,
col=1,
)
fig.update_traces(offsetgroup=0)
fig.add_trace(px.scatter(original_data, color=outliers).data[0], row=1, col=2)
if sum(outliers) > 0:
fig.add_trace(px.scatter(original_data, color=outliers).data[1], row=1, col=2)
fig.update_layout(showlegend=False, yaxis_title="Windspeed (ms⁻¹)")
return fig
def contour_krig(
df: pd.DataFrame,
gas: str,
# array of float 64
xx: np.ndarray,
yy: np.ndarray,
field: np.ndarray,
cut_ground: bool = False,
x: str = "x",
y: str = "height_ato",
) -> go.Figure:
if np.isnan(field).all():
return blank_figure()
fig = go.Figure()
fig.add_trace(
go.Scatter(
x=df[x],
y=df[y],
mode="markers",
marker={
"color": df[f"{gas}_normalised"],
"colorscale": styling["colorscale"],
"showscale": True,
"colorbar": {
"title": f"{gas} (ppm)",
},
},
showlegend=False,
)
)
fig.add_trace(
go.Contour(
z=field.T,
x=xx[:, 0],
y=yy[0, :],
contours={
"start": field.min(),
"end": field.max(),
"size": (field[~np.isnan(field)].max() - field[~np.isnan(field)].min()) / 21,
},
colorscale=styling["colorscale"],
opacity=0.5,
showlegend=False,
showscale=False,
)
)
fig.update_xaxes(
showline=True,
linewidth=1,
linecolor="black",
title_text="horizontal distance on projected flux plane (m)",
range=[np.min(xx), np.max(xx)],
ticks="outside",
tickwidth=1,
tickcolor="black",
ticklen=5,
nticks=20,
)
fig.update_yaxes(
showline=True,
linewidth=1,
linecolor="black",
title_text="height above takeoff (m)",
range=[np.min(yy), np.max(yy)],
ticks="outside",
tickwidth=1,
tickcolor="black",
ticklen=5,
nticks=10,
)
if cut_ground:
resolution = 200 # how many points to interpolate over
df["ground_elevation_ato"] = df.loc[:, "height_ato"] - df.loc[:, "height_agl"]
df_sorted = df.dropna(subset=[x, "ground_elevation_ato"]).sort_values(x)
x_min, x_max = df_sorted[x].min(), df_sorted[x].max()
x_interp = np.linspace(x_min, x_max, resolution)
ground_ato_interp = np.interp(x_interp, df_sorted[x], df_sorted["ground_elevation_ato"])
fig.add_trace(
go.Scatter(
x=x_interp,
y=ground_ato_interp,
mode="lines",
line=dict(color="black", width=2, dash="dash"),
name="Interpolated Ground Level",
)
)
fig.layout.coloraxis.colorbar.title = "Emissions flux (kg⋅m⁻²⋅h⁻¹)"
return fig
def heatmap_krig(xx: np.ndarray, yy: np.ndarray, field: np.ndarray):
fig = px.imshow(field.T, x=xx[:, 0], y=yy[0, :], color_continuous_scale=styling["colorscale"], origin="lower")
fig.layout.coloraxis.colorbar.title = "Emissions flux (kg⋅m⁻²⋅h⁻¹)"
fig.update_xaxes(
showline=True,
linewidth=1,
linecolor="black",
title_text="horizontal distance on cylindrical projected flux plane (m)",
range=[xx.min(), xx.max()],
ticks="outside",
tickwidth=1,
tickcolor="black",
ticklen=5,
nticks=20,
)
fig.update_yaxes(
showline=True,
linewidth=1,
linecolor="black",
title_text="height above ground level (m)",
range=[yy.min(), yy.max()],
ticks="outside",
tickwidth=1,
tickcolor="black",
ticklen=5,
nticks=10,
)
fig.update_layout(coloraxis_colorbar=dict(len=0.25))
return fig
def create_kml_file(data: pd.DataFrame, output_file: str, column: str, altitudemode: str):
kml = simplekml.Kml()
min_value = data[column].min()
max_value = data[column].max()
custom_colors = [
"#008080",
"#70a494",
"#b4c8a8",
"#f6edbd",
"#edbb8a",
"#de8a5a",
"#ca562c",
] # based on plotly geyser
cmap = mcolors.LinearSegmentedColormap.from_list("custom_cmap", custom_colors)
for _index, row in data.iterrows():
col_normalized = (row[column] - min) / (max_value - min_value)
color = mcolors.rgb2hex(cmap(col_normalized))
pnt = kml.newpoint(coords=[(row["longitude"], row["latitude"], row["height_ato"])], altitudemode=altitudemode)
pnt.iconstyle.icon.href = "http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png"
pnt.iconstyle.color = simplekml.Color.rgb(int(color[1:3], 16), int(color[3:5], 16), int(color[5:], 16))
pnt.iconstyle.scale = 0.6
pnt.description = f"Concentration: {row[column]} ppm"
kml.save(output_file)

View File

@ -0,0 +1,109 @@
"""Functions that organise the data into standard columns in pandas dataframes. Conversion functions (e.g. WGS84 to UTM)
are here but transformations take place in processing.py"""
import geopandas as gpd
import numpy as np
import pandas as pd
from . import plotting
from .processing import circ_median
def data_tests(df: pd.DataFrame):
assert df["ch4"].min() > 1.6, "ch4 values are too low"
assert df.index.is_monotonic_increasing, "data is not sorted by time"
assert df.index.is_unique, "data has duplicate timestamps"
assert df["ch4"].isna().sum() == 0, "ch4 has missing values"
assert df["windspeed"].min() >= 0, "windspeed values are negative"
assert df["windspeed"].max() < 20, "windspeed values are too high"
if df["windspeed"].max() > 15:
print("Warning: windspeed is greater than 15 m/s, perhaps due to errors in the data.")
# make timestamp column from UTCs, Month, Day, Year
def timestamp_from_four_columns(df):
df["Year"] = df["Year"] + 2000
df["time"] = pd.to_datetime(df["UTCs"], unit="s")
df["date"] = pd.to_datetime(df[["Year", "Month", "Day"]])
df["timestamp"] = pd.to_datetime(df["date"].dt.date.astype(str) + " " + df["time"].dt.time.astype(str))
df.index = df["timestamp"]
df.drop(
["Year", "Month", "Day", "time", "date", "timestamp", "UTCs"],
axis=1,
inplace=True,
)
return df
# add UTM from latitudes and longitudes
def add_utm(df: pd.DataFrame) -> pd.DataFrame:
gdf = gpd.GeoDataFrame( # type: ignore
df,
geometry=gpd.points_from_xy(df["longitude"], df["latitude"], crs="EPSG:4326"),
)
utm = gdf.estimate_utm_crs()
gdf = gdf.to_crs(utm)
if not isinstance(gdf, gpd.GeoDataFrame):
raise TypeError("Failed to reproject to a GeoDataFrame")
gdf["utm_easting"] = gdf.geometry.x
gdf["utm_northing"] = gdf.geometry.y
output_df = pd.DataFrame(gdf.drop(columns="geometry"))
return output_df
# add columns for drone course azimuth and elevation
def add_course(df, rolling_window=1):
df["hor_distance"] = np.sqrt((df["utm_northing"].diff()) ** 2 + (df["utm_easting"].diff()) ** 2)
df["vert_distance"] = df["height_ato"].diff()
df["vert_distance"] = pd.to_numeric(df["vert_distance"], errors="coerce")
df["hor_distance"] = pd.to_numeric(df["hor_distance"], errors="coerce")
df["course_azimuth"] = (
(np.degrees(np.arctan2(df["utm_easting"].diff(), df["utm_northing"].diff())) % 360)
.rolling(rolling_window)
.apply(lambda x: circ_median(x), raw=True)
)
df["course_elevation"] = (
np.degrees(np.arctan2(df["vert_distance"], df["hor_distance"]))
.rolling(rolling_window)
.apply(lambda x: circ_median(x), raw=True)
)
return df
def manual_filtering(dict_dfs: dict, split_times: dict, mask_spans: dict) -> dict:
filtered_dfs = {}
for name, df in dict_dfs.items():
if name in mask_spans:
for i in range(len(mask_spans[name])):
df = df.drop(
df.between_time(mask_spans[name][i].split(" - ")[0], mask_spans[name][i].split(" - ")[1]).index,
).copy()
filtered_dfs[name] = df.copy()
if name in split_times:
split_times[name].append("23:59:59")
split_times[name].insert(0, "00:00:00")
for i in range(len(split_times[name]) - 1):
df2 = df.between_time(split_times[name][i], split_times[name][i + 1]).copy()
filtered_dfs[name + "_" + str(i)] = df2.copy()
elif name not in split_times:
filtered_dfs[name] = df.copy()
return filtered_dfs
def remove_outliers(df: pd.DataFrame, column: str, name: str):
q1 = df[column].quantile(0.25)
q3 = df[column].quantile(0.75)
iqr = q3 - q1
fence_low = q1 - 3 * iqr
fence_high = q3 + 3 * iqr
fig = plotting.outliers(df[column], fence_high, fence_low)
outliers = df.loc[(df[column] < fence_low) | (df[column] > fence_high)]
if len(outliers) > 0:
print(f"{len(outliers)} outliers removed from {name} {column} data")
# nan for outliers, not row removal
df.loc[(df[column] < fence_low) | (df[column] > fence_high), column] = float("nan")
elif len(outliers) == 0:
print(f"No outliers found in {name} {column} data")
return df, fig

650
src/gasflux/processing.py Normal file
View File

@ -0,0 +1,650 @@
"""Processing function, usually implying some kind of filtering or data transformation."""
from matplotlib.figure import Figure
from itertools import groupby
from typing import Any
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import odr
from scipy.optimize import least_squares
from scipy.signal import find_peaks
from scipy.stats import circmean
import warnings
import logging
def circ_median(x: np.ndarray | pd.Series) -> float:
"""
Finds the largest "empty" arc in the circle, splits it there and returns the median of the straight line.
Probably there are more elegant ways... see https://github.com/scipy/scipy/issues/6644
Parameters:
x (np.ndarray | pd.Series): The input array of angles.
Returns:
float: The circular median of the input angles.
"""
angles = sorted(x)
n = len(angles)
if n == 1:
return angles[0]
gaps = [(angles[(i + 1) % n] - angles[i]) % 360 for i in range(n)]
largest_gap_index = gaps.index(max(gaps))
rearranged_angles = angles[largest_gap_index + 1 :] + angles[: largest_gap_index + 1]
if n % 2 == 1:
return rearranged_angles[n // 2]
else:
return (rearranged_angles[n // 2 - 1] + rearranged_angles[n // 2]) % 360 / 2
def min_angular_displacement(x: float | np.ndarray, y: float | np.ndarray) -> float | np.ndarray:
"""
Calculates the minimum circular difference between two angles (in 360 degree space)
"""
return np.minimum(np.abs(x - y) % 360, (360 - np.abs(x - y)) % 360)
def wind_offset_correction(df: pd.DataFrame, plane_angle: float) -> pd.DataFrame:
"""
Corrects wind direction data for a given plane angle, assuming the plane is the primary orientation of the dataset.
This is useful for aligning wind data with the plane's orientation, facilitating analysis of wind effects.
Parameters:
df (pd.DataFrame): The input dataframe containing wind direction data.
wind_dir_col (str): Column name for wind direction data.
plane_angle (float): Angle of the plane in degrees.
Returns:
pd.DataFrame: The modified dataframe with corrected wind direction data.
"""
df = df.copy()
df["winddir_rel"] = df.apply(lambda row: abs(90 - min_angular_displacement(row["winddir"], plane_angle)), axis=1) # type: ignore
df["windspeed_measured"] = df["windspeed"]
df["windspeed"] = df["windspeed"] * np.cos(np.radians(df["winddir_rel"]))
return df
def bimodal_azimuth(
df: pd.DataFrame, course_col: str = "course_azimuth", min_height: int = 5, min_diff: int = 160
) -> tuple[float, float]:
"""
Identifies the two most frequent course azimuths in the dataset, ensuring they are sufficiently
distinct. Filters data by height and removes NaNs before analysis.
Parameters:
df (pd.DataFrame): The input dataframe.
course_col (str): Column name for course azimuth data. Default is "course_azimuth".
min_altitude (int): Minimum height (_ato typically) for data to be included. Default is 5.
min_diff (int): Minimum difference between the two modes. Default is 160.
Returns:
tuple: Two modes of the course azimuth.
"""
df = df[df["height_ato"] >= min_height]
data = df[course_col].dropna().to_numpy()
hist, edges = np.histogram(data, bins=50)
edgedist = edges[1] - edges[0]
bin_centers = edges[:-1] + edgedist / 2
max_freq_idx = np.argsort(hist)[-2:] # top 2 frequencies
mode1, mode2 = bin_centers[max_freq_idx]
while min_angular_displacement(mode1, mode2) < min_diff:
if hist[max_freq_idx[0]] < hist[max_freq_idx[1]]:
hist[max_freq_idx[0]] = 0
max_freq_idx = np.argsort(hist)[-2:]
else:
hist[max_freq_idx[1]] = 0
max_freq_idx = np.argsort(hist)[-2:]
mode1, mode2 = bin_centers[max_freq_idx]
if min_angular_displacement(mode1, mode2) < 160:
warnings.warn(
f"Two modes are close together - this probably should never happen: {mode1:.2f} and {mode2:.2f}",
UserWarning,
stacklevel=2,
)
return (mode1, mode2)
# this returns modes of slope from -90 to 90 degrees.
def bimodal_elevation(
df: pd.DataFrame, course_col: str = "course_elevation", min_height: float = 5, max_slope: float = 70
) -> tuple[float, float]:
"""
Identifies the most frequent course elevation in the dataset, adjusted for vertical movements.
Filters data by height and removes NaNs before analysis.
Parameters:
df (pd.DataFrame): The input dataframe.
course_col (str): Column name for course elevation data. Default is "course_elevation".
min_height (int): Minimum height for data to be included. Default is 5.
max_slope (int): Maximum slope to consider, avoTupleiding vertical movements. Default is 70.
Returns:
tuple: Mode of course elevation and its negative, representing possible ascent/descent angles.
"""
df = df[df["height_ato"] >= df["height_ato"].min() + min_height]
data = df[course_col].to_numpy()
data = np.abs(data[~np.isnan(data)])
# to get around the edge case where vertical movements are modal
data = data[data < max_slope]
hist, edges = np.histogram(data, bins=50)
max_freq_idx = np.argsort(hist)[::-1][:2]
mode = edges[max_freq_idx][0]
return (mode, -mode)
def height_transect_splitter(df: pd.DataFrame, height_col: str = "height_ato") -> tuple[pd.DataFrame, Figure]:
"""
Splits the dataset into height-based transects and plots histogram peaks to identify prominent
height ranges. Only works if the flights are flat.
Parameters:
df (pd.DataFrame): The input dataframe containing height data.
Returns:
tuple: Modified dataframe with transect labels and a figure showing the histogram with peaks.
"""
df = df.copy()
heights = df[height_col].to_numpy()
counts, bin_edges = np.histogram(heights, bins=40)
bin_width = bin_edges[1] - bin_edges[0]
bin_edges = np.append(heights.min() - bin_width, bin_edges) # avoid literal edge effects
bin_edges = np.append(bin_edges, heights.max() + bin_width)
counts = np.append(0, counts)
counts = np.append(counts, 0)
bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
peaks, properties = find_peaks(counts)
transect_edges = (bin_centers[peaks][:-1] + bin_centers[peaks][1:]) / 2
transect_edges = np.append(heights.min(), transect_edges)
transect_edges = np.append(transect_edges, heights.max())
fig, ax = plt.subplots()
ax.stairs(edges=bin_edges, values=counts, fill=True)
ax.plot(bin_centers[peaks], counts[peaks], "x", color="red")
ax.vlines(transect_edges, ymin=0, ymax=max(counts), color="red")
df["transect_num"] = pd.cut(df[height_col], bins=list(transect_edges), labels=False, include_lowest=True) # type: ignore
return df, fig
def add_transect_azimuth_switches(df: pd.DataFrame, threshold=150, shift=3) -> pd.DataFrame:
"""
Identifies transects based on significant changes in course azimuth, incrementing a transect
counter to distinguish different flight paths. This is a really crude function and should probably
be only used with data that's already been filtered in some way.
Parameters:
df (pd.DataFrame): The input dataframe with course azimuths.
Returns:
pd.DataFrame: The modified dataframe with a new 'transect' column indicating transect IDs.
"""
df = df.copy()
df["transect_num"] = 0
df["prev_course_azimuth"] = df["course_azimuth"].shift(shift) # this gives better behaviour for very neat transects
df["deg_displace"] = df.apply(
lambda row: min_angular_displacement(row["course_azimuth"], row["prev_course_azimuth"]) # type: ignore
if not pd.isnull(row["prev_course_azimuth"])
else np.nan,
axis=1,
)
df.loc[df["deg_displace"] > threshold, "transect_num"] = 1
# remove ones that are next to each other
for i in range(1, len(df)):
if (df.loc[i, "transect_num"] == 1 and df.loc[i - 1, "transect_num"] == 1) or (
df.loc[i, "transect_num"] == 1 and df.loc[i - 2, "transect_num"] == 1
):
df.loc[i, "transect_num"] = 0
df["transect_num"] = df["transect_num"].shift(-shift) # recorrect for shift
df["transect_num"] = df["transect_num"].cumsum() + 1 # 1 indexed
df["transect_num"] = df["transect_num"].ffill()
df = df.drop(columns=["prev_course_azimuth", "deg_displace"])
return df
def course_filter(
df: pd.DataFrame, azimuth_filter: float, azimuth_window: int, elevation_filter: float
) -> tuple[pd.DataFrame, pd.DataFrame]:
"""
Filters data based on specified course azimuth and elevation, aiming to isolate transects that
align with main flight directions. First elevation is filtered to remove significant climbs or descents
(beware terrain-following flights). Bimodal course azimuths are calculated and used to filter the
data based on the main flight directions, with a rolling median applied (the window) to smooth the data.
Parameters:
df (pd.DataFrame): The input dataframe.
azimuth_filter (float): The tolerance for deviation from the main course azimuths.
azimuth_window (int): The window size for rolling median calculation of course azimuths.
elevation_filter (float): The tolerance for deviation from horizontal flight.
Returns:
tuple: The filtered dataframe and the original unfiltered dataframe for comparison.
"""
df_filtered = df.copy()
df_filtered = df_filtered[abs(df["course_elevation"]) < elevation_filter]
azi1, azi2 = bimodal_azimuth(df_filtered)
logging.info(f"Drone appears to be flying mainly on the courses {azi1:.2f} degrees and {azi2:.2f} degrees")
df_filtered["rolling_course_azimuth"] = (
df_filtered["course_azimuth"].rolling(azimuth_window, center=True).apply(lambda x: circ_median(x), raw=True)
)
df_filtered = df_filtered[
(df_filtered["rolling_course_azimuth"] < azi1 + azimuth_filter)
& (df_filtered["rolling_course_azimuth"] > azi1 - azimuth_filter)
| (df_filtered["rolling_course_azimuth"] < azi2 + azimuth_filter)
& (df_filtered["rolling_course_azimuth"] > azi2 - azimuth_filter)
]
return df_filtered, df
def mCount_max(data_dict: dict[int, float]) -> tuple[int, int]:
"""
Finds the start and end of the longest monotonic sequence in a dictionary of floats, typically used
to identify a series of continuous altitude measurements. The first and last are retained.
Parameters:
data_dict (Dict[int, float]): Dictionary with sequential numeric keys and numeric values representing measures
such as altitude.
Returns:
tuple: Start and end indices of the longest monotonic sequence in the dictionary.
"""
if len(data_dict) < 2:
raise ValueError("Dictionary must contain at least two values")
if list(data_dict.keys()) != list(range(1, len(data_dict) + 1)):
raise ValueError("Keys must be sequential integers starting from 1")
poscount = 0
negcount = 0
max_pos_count = 0
max_pos_transect = 0
max_neg_count = 0
max_neg_transect = 0
pos_start = 0
neg_start = 0
for i in range(2, len(data_dict) + 1):
if data_dict[i] >= data_dict[i - 1]:
poscount += 1
negcount = 0
elif data_dict[i] < data_dict[i - 1]:
negcount += 1
poscount = 0
if max_pos_count < poscount:
max_pos_count = poscount
max_pos_transect = i
pos_start = i - poscount
elif max_neg_count < negcount:
max_neg_count = negcount
max_neg_transect = i
neg_start = i - negcount
if max_pos_count > 0 or max_neg_count > 0:
if max_pos_count >= max_neg_count:
return pos_start, max_pos_transect
else:
return neg_start, max_neg_transect
else:
return 0, 0
def largest_monotonic_transect_series(
df: pd.DataFrame, transect_col: str = "transect_num", alt_col: str = "height_ato"
) -> tuple[pd.DataFrame, int, int]:
"""
Filters the input dataframe to include only the largest continuous series of transects based on
monotonic altitude changes.
Parameters:
df (pd.DataFrame): The input dataframe with transect and altitude information.
transect_col (str): Column name for transect numbers. Default is "transect_num".
alt_col (str): Column name for altitude data. Default is "height_ato".
Returns:
tuple: The filtered dataframe, start transect, and end transect of the largest monotonic series.
"""
df = add_transect_azimuth_switches(df) # course switches
alt_dict = dict(df.groupby(transect_col)[alt_col].mean())
starttransect, endtransect = mCount_max(alt_dict) # type: ignore
# filter to the biggest monotonic series of values
df = df[(df[transect_col] >= starttransect) & (df[transect_col] <= endtransect)]
logging.info(
f"Parsed a flight of {len(np.unique(df[transect_col]))} transects from {alt_dict[starttransect]:.0f}m"
f" to {alt_dict[endtransect]:.0f}m between {df['timestamp'].iloc[0]} and {df['timestamp'].iloc[-1]}",
)
return df, starttransect, endtransect
def monotonic_transect_groups(
df: pd.DataFrame, transect_col: str = "transect_num", alt_col: str = "height_ato"
) -> tuple[pd.DataFrame, dict[int, str]]:
"""
Groups transects into a dict of monotonic transect sequences based on altitude, facilitating analysis of continuous
flight patterns. Current behaviour is to reuse end transects of previous sequences as the start of the next.
Parameters:
df (pd.DataFrame): The input dataframe with transect and altitude information.
transect_col (str): Column name for transect numbers. Default is "transect_num".
alt_col (str): Column name for altitude data. Default is "height_ato".
Returns:
tuple: The dataframe with a new 'group' column indicating the monotonic group ID, and a
dictionary mapping transects to group IDs.
"""
df = add_transect_azimuth_switches(df)
alt_dict = dict(df.groupby(transect_col)[alt_col].mean())
group_dict = {}
previous_altitude = None
current_group = 1
previous_trend = None
first_transect_in_series = True
for transect, altitude in alt_dict.items():
if previous_altitude is None:
group_dict[transect] = f"Group_{current_group}"
else:
if altitude == previous_altitude:
raise ValueError("Error: altitude is the same as the previous transect")
elif altitude > previous_altitude:
current_trend = "ascending"
else:
current_trend = "descending"
if current_trend != previous_trend and previous_trend is not None and not first_transect_in_series:
current_group += 1 # Increment group counter
first_transect_in_series = True
if current_trend == previous_trend or previous_trend is None:
# handles edge case where someone flies up, flies down one transect and then up again (yes really)
first_transect_in_series = False
group_dict[transect] = f"Group_{current_group}"
previous_trend = current_trend
previous_altitude = altitude
df["group"] = df["transect_num"].map(group_dict)
return df, group_dict
def remove_non_transects(
df: pd.DataFrame,
chain_length: int = 70,
azimuth_tolerance: int = 10,
elevation_tolerance: int = 40,
smoothing_window: int = 5,
) -> tuple[pd.DataFrame, pd.DataFrame]:
"""
Filters the dataframe to remove segments not matching the criteria for being considered as transects,
based on course azimuth and elevation and segment length.
Parameters:
df (pd.DataFrame): The input dataframe.
chain_length (int): Minimum number of consecutive points to be considered a transect. Default is 70.
azimuth_tolerance (int): Tolerance for deviation from modal course azimuths. Default is 10.
elevation_tolerance (int): Tolerance for deviation from modal course elevation. Default is 40.
smoothing_window (int): Window size for rolling median smoothing of courses. Default is 5. Rolling median
avoids single point errors.
Returns:
tuple: Dataframes of removed segments and retained segments that fit transect criteria.
"""
def get_true_runs(mask):
enumerated_mask = list(enumerate(mask)) # add index numbers to mask
# group consecutive true/false values
groups = groupby(enumerated_mask, key=lambda x: x[1])
# retain groups of True values
true_runs = [list(group) for key, group in groups if key]
return true_runs
def split_runs_on_azimuth_inversion(df, runs, azimuth_inversion_threshold=120):
split_runs = []
for run in runs:
last_azimuth = df.iloc[run[0][0]]["smoothed_course_azimuth"]
current_run = [run[0]]
for point in run[1:]:
current_azimuth = df.iloc[point[0]]["smoothed_course_azimuth"]
if min_angular_displacement(current_azimuth, last_azimuth) > azimuth_inversion_threshold:
split_runs.append(current_run)
current_run = [point]
else:
current_run.append(point)
last_azimuth = current_azimuth
split_runs.append(current_run)
return split_runs
# Create new columns for filtering reasons, initialized with False
df_removed = df.copy()
df_removed["filtered_by_azimuth"] = False
df_removed["filtered_by_elevation"] = False
df_removed["filtered_by_chain"] = False
# Apply azimuth filter
modal_course_azimuths = bimodal_azimuth(df, course_col="course_azimuth")
modal_elevation_azimuths = bimodal_elevation(df, course_col="course_elevation")
# Apply rolling median to course azimuth and elevation and store them in new columns
df_removed["smoothed_course_azimuth"] = (
df_removed["course_azimuth"]
.rolling(smoothing_window, center=True)
.apply(lambda x: circmean(x, 360, 0), raw=True)
.fillna(df_removed["course_azimuth"], inplace=False)
)
df_removed["smoothed_course_elevation"] = (
df_removed["course_elevation"]
.rolling(smoothing_window, center=True)
.apply(lambda x: circmean(x, 360, 0), raw=True)
.fillna(df_removed["course_elevation"], inplace=False)
)
azimuth_mask = df_removed["smoothed_course_azimuth"].apply(
lambda x: any([min_angular_displacement(x, mode) <= azimuth_tolerance for mode in modal_course_azimuths])
)
df_removed.loc[~azimuth_mask, "filtered_by_azimuth"] = True
# Apply elevation filter
elevation_mask = df_removed["smoothed_course_elevation"].apply(
lambda x: any([min_angular_displacement(x, mode) <= elevation_tolerance for mode in modal_elevation_azimuths])
)
df_removed.loc[~elevation_mask, "filtered_by_elevation"] = True
# Combined mask for azimuth and elevation
mask = azimuth_mask & elevation_mask
true_runs = get_true_runs(mask)
split_runs = split_runs_on_azimuth_inversion(df_removed, true_runs)
chain_mask = [len(run) >= chain_length for run in split_runs]
chain_filtered_runs = [run for run, filter_by_chain in zip(split_runs, chain_mask, strict=False) if filter_by_chain]
chain_filtered_indices = [point[0] for run in chain_filtered_runs for point in run]
df_removed.loc[df_removed.index.difference(chain_filtered_indices), "filtered_by_chain"] = True
filtered_segments = [df_removed.iloc[run[0][0] : run[-1][0] + 1] for run in chain_filtered_runs]
df_retained = pd.concat(filtered_segments)
df_removed = df_removed[~df_removed.index.isin(df_retained.index)]
return df_removed, df_retained
def flatten_linear_plane(
df: pd.DataFrame, alt_col: str = "height_ato", distance_filter: float = 10000
) -> tuple[pd.DataFrame, float]:
"""
Transforms a 3D dataset into a linear plane, focusing on the largest contiguous dataset aligned with
the plane's primary orientation. The new x coordinate is the distance along the plane, y is the distance
perpendicular to the plane (useful only for deviation), and z is the altitude.
Parameters:
df (pd.DataFrame): Input dataframe with "utm_easting", "utm_northing", and "height_ato" columns.
alt_col (str): Column name for altitude data. Default is "height_ato".
distance_filter (float): Threshold for filtering points based on their distance from the regression line.
Returns:
tuple: Modified dataframe with new 'x', 'y', and 'z' columns representing transformed coordinates,
and one of the plane's angles of rotation (from N, 0-360) in degrees.
"""
def orthogonal_distance_regression(df: pd.DataFrame) -> tuple[pd.DataFrame, np.ndarray[Any, Any]]:
"""
Perform orthogonal distance regression on the given DataFrame.
Parameters:
df (pd.DataFrame): DataFrame containing "utm_easting" and "utm_northing" columns.
Returns:
tuple[pd.DataFrame, np.ndarra[Any,Any]]]: Updated DataFrame with "distance_from_fit" column
and the fitted parameters (slope, intercept).
"""
def linear_reg_equation(B, x):
return B[0] * x + B[1] # y = mx + c
required_columns = ["utm_easting", "utm_northing"]
if not all(col in df.columns for col in required_columns):
raise ValueError(f"DataFrame must contain columns: {required_columns}")
model = odr.Model(linear_reg_equation)
data = odr.Data(df["utm_easting"], df["utm_northing"])
INITIAL_BETA = [1, 0] # Initial guess of slope=1, intercept=0
odr_instance = odr.ODR(data, model, beta0=INITIAL_BETA)
fit = odr_instance.run()
if fit.stopreason[0] == "Iteration limit reached":
raise RuntimeError("ODR fitting failed to converge")
slope, intercept = fit.beta
df = df.assign(
distance_from_fit=abs((slope * df["utm_easting"] - df["utm_northing"] + intercept) / np.sqrt(slope**2 + 1))
)
return df, fit.beta
df, coefs2D = orthogonal_distance_regression(df)
df = df.loc[df["distance_from_fit"] < distance_filter, :]
df, coefs2D = orthogonal_distance_regression(df) # this is intentionally done twice
df = df.loc[df["distance_from_fit"] < distance_filter, :]
rotation = np.arctan(coefs2D[0])
df.loc[:, "x"] = (df["utm_easting"] - df["utm_easting"].min()) * np.cos(-rotation) - (
df["utm_northing"] - df["utm_northing"].min()
) * np.sin(-rotation)
df.loc[:, "y"] = (df["utm_easting"] - df["utm_easting"].min()) * np.sin(-rotation) + (
df["utm_northing"] - df["utm_northing"].min()
) * np.cos(-rotation)
df.loc[:, "z"] = df[alt_col]
plane_angle = (np.pi / 2) - np.arctan(coefs2D[0])
plane_angle = np.degrees(plane_angle)
return df, plane_angle
## Functions for circular/spiral flights ##
def circle_deviation(df: pd.DataFrame, x_col: str, y_col: str) -> tuple[pd.DataFrame, float, float, float]:
"""
Calculates the deviation of points from a fitted circle and their azimuth angles.
Parameters:
df (pd.DataFrame): The input dataframe containing the data.
x (str): Column name for the x-coordinate.
y (str): Column name for the y-coordinate.
Returns:
Tuple[pd.Dataframe, float, float, float]: A tuple containing the modified dataframe with azimuth angles
and deviations,the radius of the fitted circle, and the coordinates of the circle's center.
"""
df = df.copy()
required_columns = [x_col, y_col]
if not all(col in df.columns for col in required_columns):
raise ValueError(f"DataFrame must contain columns: {required_columns}")
x = df[x_col]
y = df[y_col]
def midhalf(x): # select middle half of data to avoid edge effects
return x.iloc[int(len(x) * 1 / 4) : int(len(x) * 3 / 4)]
x_filter, y_filter = midhalf(x), midhalf(y)
def func(params):
xc, yc, r = params
return np.sqrt((x - xc) ** 2 + (y - yc) ** 2) - r
x_m = np.mean(np.array(x_filter)) # initial guess for parameters
y_m = np.mean(np.array(y_filter))
r_m = np.mean(np.sqrt((np.array(x_filter) - x_m) ** 2 + (np.array(y_filter) - y_m) ** 2))
params0 = np.array([x_m, y_m, r_m])
result = least_squares(func, params0)
xc, yc, r = result.x
deviation = np.sqrt((x - xc) ** 2 + (y - yc) ** 2) - r
# output azimuth in radians with 0 at north and increasing clockwise thanks to modulos
azimuth = np.degrees(np.arctan2(x - xc, y - yc) % (2 * np.pi))
df["circ_azimuth"] = azimuth
df["circ_deviation"] = deviation
return df, r, xc, yc
def recentre_azimuth(df: pd.DataFrame, r: float, x: str = "circ_azimuth", y: str = "ch4_normalised") -> pd.DataFrame:
"""
Recentres the azimuth angles based on the angle of maximum value and computes the distance along the
circumference of the circle.
Parameters:
df (pd.DataFrame): The input dataframe.
r (float): The radius of the circle.
x (str): Column name for azimuth angles. Default is 'circ_azimuth'.
y (str): Column name for the values used to find the maximum. Default is 'ch4_normalised'.
Returns:
pd.DataFrame: The modified dataframe with centered azimuth angles and distances along the circumference.
"""
df = df.copy()
def azimuth_of_max(df: pd.DataFrame, x: str = "circ_azimuth", y: str = "ch4_normalised") -> float:
return df.loc[df[y].idxmax()][x] # type: ignore
centre_azimuth = azimuth_of_max(df, x, y)
df["centred_azimuth"] = df[x] - centre_azimuth
df.loc[df["centred_azimuth"] > 180, "centred_azimuth"] -= 360
df.loc[df["centred_azimuth"] < -180, "centred_azimuth"] += 360
df["circumference_distance"] = r * np.radians(df["centred_azimuth"])
df["circumference_distance"] = df["circumference_distance"] - df["circumference_distance"].min()
return df
def drone_anemo_to_point_wind(
df: pd.DataFrame, yaw_col: str, anemo_u_col: str, anemo_v_col: str, easting_col: str, northing_col: str
) -> pd.DataFrame:
"""
Convert anemometer wind data from drone's coordinate system to Earth's coordinate system
and calculate true wind speed and direction.
Parameters:
df (pd.DataFrame): Input DataFrame containing drone yaw, anemometer data, and drone speed.
yaw_col (str): Column name for drone's yaw (in degrees, range [-180, 180]).
anemo_u_col (str): Column name for anemometer U (wind speed in drone's X direction, from port to starboard).
anemo_v_col (str): Column name for anemometer V (wind speed in drone's Y direction, from aft to nose).
easting_col (str): Column name for drone's speed from west to east
northing_col (str): Column name for drone's speed from south to north
Returns:
pd.DataFrame: DataFrame with calculated true wind speed ("windspeed") and true wind direction ("winddir").
"""
yaw_rad = np.deg2rad(df[yaw_col] % 360)
rotated_U = df[anemo_u_col] * np.cos(yaw_rad) + df[anemo_v_col] * np.sin(yaw_rad)
rotated_V = -df[anemo_u_col] * np.sin(yaw_rad) + df[anemo_v_col] * np.cos(yaw_rad)
true_U = -rotated_U - df[easting_col]
true_V = -rotated_V - df[northing_col]
df["windspeed"] = np.sqrt(true_U**2 + true_V**2)
df["winddir"] = np.degrees(np.arctan2(true_U, true_V)) % 360
return df

View File

@ -0,0 +1,317 @@
import logging
from datetime import datetime
from pathlib import Path
from scipy import stats
import pandas as pd
import plotly.graph_objects as go
import yaml
from src.gasflux import background,plotting,processing,reporting,interpolation,pre_processing,gas
from abc import ABC, abstractmethod
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def read_csv(file_path: Path) -> pd.DataFrame:
"""Read a CSV file and return a DataFrame."""
try:
return pd.read_csv(file_path)
except FileNotFoundError:
logger.exception(f"File not found: {file_path}")
raise
def load_config(config_path: Path) -> dict:
"""Load a YAML config file and return a dictionary."""
try:
with open(config_path) as file:
return yaml.safe_load(file)
except FileNotFoundError:
logger.exception(f"Config file not found: {config_path}")
raise
except yaml.YAMLError as e:
logger.exception(f"Error parsing YAML config: {e}")
raise
class DataValidator: # TODO(me): decide whether to move this to preprocessing
"""Validate the data before processing."""
def __init__(self, df: pd.DataFrame, config: dict) -> None:
"""Initialise the validator with the DataFrame and config."""
self.df = df
self.required_cols = config["required_cols"].copy()
self.required_cols.update(config["gases"])
def validate(self) -> None:
"""Validate the data."""
self._check_is_df()
self._check_cols()
self._check_dtypes()
self._check_ranges()
logger.info("Data validation passed")
def _check_is_df(self) -> None:
"""Check that the input is a DataFrame."""
if not isinstance(self.df, pd.DataFrame):
logging.error("Input data is not a DataFrame.")
raise ValueError("Input data is not a DataFrame.")
def _check_cols(self) -> None:
"""Check that the required columns are present."""
missing_cols = set(self.required_cols) - set(self.df.columns)
if missing_cols:
logging.error(f"Missing or mislabelled columns: {missing_cols}")
raise ValueError(f"Missing or mislabelled columns: {missing_cols}")
def _check_dtypes(self) -> None:
"""Check that the required columns are of the correct type and do not contain NaN values."""
for col in self.required_cols:
if col in self.df:
if self.df[col].isna().any():
logging.error(f"Column '{col}' contains NaN values.")
raise ValueError(f"Column '{col}' contains NaN values.")
if self.df[col].dtype != "float64":
logging.error(f"Column '{col}' is not of type 'float64'.")
raise ValueError(f"Column '{col}' is not of type 'float64'.")
def _check_ranges(self) -> None:
"""Check that the required columns are within the specified ranges."""
for col, (min_val, max_val) in self.required_cols.items():
if col in self.df.columns and not self.df[col].between(min_val, max_val, inclusive="both").all():
logging.error(f"Column '{col}' contains values out of range: {min_val} to {max_val}.")
raise ValueError(f"Column '{col}' contains values out of range: {min_val} to {max_val}.")
class BackgroundStrategy(ABC):
def __init__(self, data_processor):
self.data_processor = data_processor
@abstractmethod
def process(self):
pass
class AlgorithmicBaselineStrategy(BackgroundStrategy):
def process(self):
logger.info("Applying algorithmic background correction")
for gas in self.data_processor.gases:
(
self.data_processor.df,
self.data_processor.figs["background"][gas],
self.data_processor.text[f"background_{gas}"],
) = background.algorithmic_baseline(
df=self.data_processor.df,
gas=gas,
algorithmic_baseline_settings=self.data_processor.config["algorithmic_baseline_settings"],
)
self.data_processor.df_std = self.data_processor.df.copy()
class SensorStrategy(ABC):
def __init__(self, data_processor):
self.data_processor = data_processor
@abstractmethod
def process(self):
pass
class InSituSensorStrategy(SensorStrategy):
def process(self):
logger.info("Processing in-situ (point) data")
for gas in self.data_processor.gases:
self.data_processor.figs["scatter_3d"][gas] = plotting.scatter_3d(
df=self.data_processor.df, color=gas, colorbar_title=f"{gas.upper()} flux (kg/m²/h)"
)
if SpatialProcessingStrategy == CurtainSpatialProcessingStrategy:
self.data_processor.figs["windrose"] = plotting.windrose(self.data_processor.df, plot_transect=True)
else:
self.data_processor.figs["windrose"] = plotting.windrose(self.data_processor.df)
self.data_processor.figs["wind_timeseries"] = plotting.time_series(
self.data_processor.df, ys=["windspeed", "winddir"]
)
class SpatialProcessingStrategy(ABC):
def __init__(self, data_processor):
self.data_processor = data_processor
@abstractmethod
def process(self):
pass
class CurtainSpatialProcessingStrategy(SpatialProcessingStrategy):
def process(self):
logger.info("Applying curtain spatial processing")
self.data_processor.dfs["original"] = self.data_processor.df.copy()
self.data_processor.df, self.data_processor.start_transect, self.data_processor.end_transect = (
processing.largest_monotonic_transect_series(self.data_processor.df)
)
self.data_processor.dfs["removed"] = self.data_processor.dfs["original"].loc[
self.data_processor.dfs["original"].index.difference(self.data_processor.df.index)
]
self.data_processor.df, self.data_processor.plane_angle = processing.flatten_linear_plane(
self.data_processor.df
)
self.data_processor.df = processing.wind_offset_correction(
self.data_processor.df, self.data_processor.plane_angle
)
for gas_name in self.data_processor.gases:
#计算通量
self.data_processor.df = gas.gas_flux_column(self.data_processor.df, gas_name)
self.data_processor.figs["scatter_3d"][gas_name].add_trace(
go.Scatter3d(
x=self.data_processor.dfs["removed"]["utm_easting"],
y=self.data_processor.dfs["removed"]["utm_northing"],
z=self.data_processor.dfs["removed"]["height_ato"],
mode="markers",
marker={"size": 2, "color": "black", "symbol": "circle", "opacity": 0.5},
)
)
class SpiralSpatialProcessingStrategy(SpatialProcessingStrategy):
def process(self):
logger.info("Applying spiral spatial processing")
self.data_processor.dfs["original"] = self.data_processor.df.copy()
# self.data_processor.df, self.data_processor.start_transect, self.data_processor.end_transect = (
# gasflux.processing.largest_monotonic_transect_series(self.data_processor.df)
# no wind offset correction - assume wind is perpendicular to the spiral
self.data_processor.dfs["removed"] = self.data_processor.dfs["original"].loc[
self.data_processor.dfs["original"].index.difference(self.data_processor.df.index)
]
(
self.data_processor.df,
self.data_processor.circle_radius,
self.data_processor.circle_center_x,
self.data_processor.circle_center_y,
) = processing.circle_deviation(self.data_processor.df, x_col="utm_easting", y_col="utm_northing")
self.data_processor.df = processing.recentre_azimuth(
self.data_processor.df, r=self.data_processor.circle_radius
)
self.data_processor.df["x"] = self.data_processor.df["circumference_distance"]
for gas_name in self.data_processor.gases:
self.data_processor.df = gas.gas_flux_column(self.data_processor.df, gas_name)
self.data_processor.figs["scatter_3d"][gas_name].add_trace(
go.Scatter3d(
x=self.data_processor.dfs["removed"]["utm_easting"],
y=self.data_processor.dfs["removed"]["utm_northing"],
z=self.data_processor.dfs["removed"]["height_ato"],
mode="markers",
marker={"size": 2, "color": "black", "symbol": "circle", "opacity": 0.5},
)
)
class InterpolationStrategy(ABC):
def __init__(self, data_processor):
self.data_processor = data_processor
@abstractmethod
def process(self):
pass
class KrigingInterpolationStrategy(InterpolationStrategy):
def process(self):
logger.info("Applying kriging interpolation")
for gas in self.data_processor.gases:
(
self.data_processor.output_vars["krig_parameters"][gas],
self.data_processor.text[f"krig_output_{gas}"],
self.data_processor.figs["contour"][gas],
self.data_processor.figs["krig_grid"][gas],
self.data_processor.figs["semivariogram"][gas],
) = interpolation.ordinary_kriging(
df=self.data_processor.df,
x="x",
y="height_ato",
gas=gas,
ordinary_kriging_settings=self.data_processor.config["ordinary_kriging_settings"],
**self.data_processor.config["semivariogram_settings"],
)
logger.info(f"Kriged {gas}")
class DataProcessor:
def __init__(self, config: dict, df: pd.DataFrame):
self.config: dict = config
self.df: pd.DataFrame = df
self.gases: list[str] = list(config["gases"].keys())
self.processing_time = datetime.now()
self.figs: dict = {
"scatter_3d": {},
"windrose": None,
"wind_timeseries": None,
"background": {},
"contour": {},
"krig_grid": {},
"semivariogram": {},
}
self.text: dict = {}
self.output_vars: dict = {"krig_parameters": {}, "std": {}}
self.dfs: dict = {}
self.reports: dict = {}
def strategy_selection(self):
self.background_strategy: BackgroundStrategy
if self.config["strategies"]["background"] == "algorithm":
self.background_strategy = AlgorithmicBaselineStrategy(self)
self.sensor_strategy: SensorStrategy
if self.config["strategies"]["sensor"] == "insitu":
self.sensor_strategy = InSituSensorStrategy(self)
self.spatial_processing_strategy: SpatialProcessingStrategy
if self.config["strategies"]["spatial"] == "curtain":
self.spatial_processing_strategy = CurtainSpatialProcessingStrategy(self)
if self.config["strategies"]["spatial"] == "spiral":
self.spatial_processing_strategy = SpiralSpatialProcessingStrategy(self)
self.interpolation_strategy: InterpolationStrategy
if self.config["strategies"]["interpolation"] == "kriging":
self.interpolation_strategy = KrigingInterpolationStrategy(self)
def process(self):
self.df = pre_processing.add_utm(self.df)
self.df = pre_processing.add_course(self.df)
DataValidator(self.df, self.config).validate()
self.background_strategy.process()
self.sensor_strategy.process()
self.spatial_processing_strategy.process()
self.interpolation_strategy.process()
# Reporting
for gas in self.gases:
self.reports[gas] = reporting.mass_balance_report(
krig_params=self.output_vars["krig_parameters"][gas],
wind_fig=self.figs["wind_timeseries"],
background_fig=self.figs["background"][gas],
threed_fig=self.figs["scatter_3d"][gas],
krig_fig=self.figs["contour"][gas],
windrose_fig=self.figs["windrose"],
)
# Collecting descriptive variables
self.output_vars["std"]["windspeed"] = self.df["windspeed"].std()
self.output_vars["std"]["windddir"] = stats.circstd(self.df["winddir"], high=360)
for gas in self.gases:
self.output_vars["std"][f"{gas}_background"] = self.df.loc[
~self.df[f"{gas}_signal"], f"{gas}_normalised"
].std()
def process_main(data_file: Path, config_file: Path) -> None:
"""Main function to run the pipeline."""
config = load_config(config_file)
name = data_file.stem
df = read_csv(data_file)
processor = DataProcessor(config, df)
processor.strategy_selection()
processor.process()
reporting.generate_reports(name, processor, config)
logger.info("Processing complete")

190
src/gasflux/qiya.py Normal file
View File

@ -0,0 +1,190 @@
import requests
import time
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def get_pressure_at_location(lat, lon, altitude, date, time, max_retries=3, timeout=30):
"""
获取指定位置、时间、高度的气压
Args:
lat: 纬度
lon: 经度
altitude: 海拔高度 (米)
date: 日期 (格式: YYYY-MM-DD 或 YYYY/MM/DD)
time: 时间 (格式: HH:MM 或 HH:MM:SS)
max_retries: 最大重试次数
timeout: 请求超时时间(秒)
Returns:
float: 气压值 (hPa),获取失败返回 None
"""
# 标准化日期格式为 YYYY-MM-DD
def normalize_date(d):
"""将各种日期格式标准化为 YYYY-MM-DD"""
if not d:
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d")
# 处理斜杠分隔符
if "/" in d:
d = d.replace("/", "-")
parts = d.split("-")
if len(parts) == 3:
year = parts[0]
month = parts[1].zfill(2) # 确保月份是两位数
day = parts[2].zfill(2) # 确保日期是两位数
return f"{year}-{month}-{day}"
else:
# 如果格式不正确,返回今天的日期
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d")
date = normalize_date(date)
# 标准化时间格式为 HH:MM
def normalize_time(t):
"""将各种时间格式标准化为 HH:MM"""
if not t or ":" not in t:
return "12:00" # 默认中午12点
parts = t.split(":")
if len(parts) >= 2:
hour = parts[0].zfill(2) # 确保小时是两位数
minute = parts[1].zfill(2) # 确保分钟是两位数
return f"{hour}:{minute}"
elif len(parts) == 1:
hour = parts[0].zfill(2)
return f"{hour}:00"
else:
return "12:00"
time = normalize_time(time)
url = "https://archive-api.open-meteo.com/v1/archive"
params = {
"latitude": lat,
"longitude": lon,
"start_date": date, # 格式: YYYY-MM-DD
"end_date": date,
"hourly": ["pressure_msl", "surface_pressure"],
"timezone": "auto"
}
# 创建带有重试机制的会话
session = requests.Session()
retry_strategy = Retry(
total=max_retries,
status_forcelist=[429, 500, 502, 503, 504],
backoff_factor=1
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
try:
print(f"正在获取位置 ({lat:.6f}, {lon:.6f}) 在 {date} {time} 的气压数据...")
response = session.get(url, params=params, timeout=timeout)
# 检查响应状态
response.raise_for_status()
data = response.json()
# 检查API错误
if "error" in data:
print(f"API错误: {data['error']}")
return None
# 解析气压数据
if data and "hourly" in data:
times = data["hourly"]["time"]
pressures = data["hourly"]["surface_pressure"] # 地表气压
if not times or not pressures:
print("未找到气压数据")
return None
# 根据时间找到对应气压
target_time = f"{date}T{time}"
if target_time in times:
idx = times.index(target_time)
pressure = pressures[idx]
print(f"成功获取气压: {pressure} hPa")
return pressure
else:
print(f"在数据中未找到时间: {target_time}")
print(f"可用时间范围: {times[0]}{times[-1]}")
return None
else:
print("API响应中没有hourly数据")
return None
except requests.exceptions.ConnectionError as e:
print(f"网络连接错误: {e}")
print("请检查网络连接或稍后重试")
return None
except requests.exceptions.Timeout as e:
print(f"请求超时: {e}")
print(f"已重试 {max_retries} 次,请检查网络连接")
return None
except requests.exceptions.HTTPError as e:
print(f"HTTP错误: {e}")
return None
except ValueError as e:
print(f"数据解析错误: {e}")
return None
except Exception as e:
print(f"未知错误: {e}")
return None
finally:
session.close()
def batch_get_pressure(data_list):
"""
批量获取多个位置的气压数据
Args:
data_list: 包含 (lat, lon, altitude, date, time) 元组的列表
Returns:
list: 气压值列表
"""
results = []
for i, (lat, lon, alt, date, time) in enumerate(data_list):
print(f"\n处理第 {i+1} 个位置...")
pressure = get_pressure_at_location(lat, lon, alt, date, time)
results.append(pressure)
if pressure is not None:
print(f"位置 {i+1}: {pressure} hPa")
else:
print(f"位置 {i+1}: 获取失败")
# 添加短暂延迟,避免请求过于频繁
if i < len(data_list) - 1:
time.sleep(0.5)
return results
# 使用示例
if __name__ == "__main__":
print("=== 气压数据获取工具 ===\n")
# 单个位置示例
print("1. 单个位置查询:")
pressure = get_pressure_at_location(
lat=40.3491370, # 纽约纬度
lon=115.7855289, # 纽约经度 (西经)
altitude=435.789, # 海拔10米
date="2016-02-12",
time="08:00" # HH:MM格式
)
if pressure is not None:
print(f"纽约当前气压: {pressure} hPa")
else:
print("获取纽约气压数据失败")

130
src/gasflux/reporting.py Normal file
View File

@ -0,0 +1,130 @@
"""This module provides functions for generating mass balance reports."""
from pathlib import Path
import plotly.graph_objects as go
from jinja2 import Template
from plotly.io import to_html
from datetime import datetime
import yaml
import logging
from . import plotting
import json
import numpy as np
logger = logging.getLogger(__name__)
def mass_balance_report(
krig_params: dict,
wind_fig: go.Figure,
background_fig: go.Figure,
threed_fig: go.Figure,
krig_fig: go.Figure,
windrose_fig: go.Figure,
) -> str:
"""Generate a mass balance report."""
template_path = Path(__file__).parent / "templates" / "mass_balance_template.html"
# Convert the figures to HTML
plot_htmls = {}
for name, fig in zip(
["3D", "krig", "windrose", "wind", "background"],
[threed_fig, krig_fig, windrose_fig, wind_fig, background_fig],
strict=False,
):
if fig:
plot_htmls[name] = to_html(fig, full_html=False)
else:
plot_htmls[name] = plotting.blank_figure()
summary_data = {
"Estimated flux": f"{krig_params.get('volume', 0):.3f} kgh⁻¹",
}
with Path.open(template_path) as f:
template_content = f.read()
template = Template(template_content)
return template.render(
title="Mass Balance Report",
summary_data=summary_data,
threeD=plot_htmls["3D"],
krig=plot_htmls["krig"],
windrose=plot_htmls["windrose"],
wind=plot_htmls["wind"],
background=plot_htmls["background"],
)
def generate_reports(name: str, processor, config: dict):
"""
Generates reports, configuration files, and processed output variables for gasflux processing runs.
Parameters:
name (str): The name identifier for the current processing run.
processor (object): The processing object containing report data and output variables.
config (dict): Configuration dictionary used for processing.
"""
output_dir = Path(config["output_dir"]).expanduser()
processing_time = datetime.now()
output_path = output_dir / name / processing_time.strftime("%Y-%m-%d_%H-%M-%S-%f_processing_run")
output_path.mkdir(parents=True, exist_ok=True)
# Save reports
for gas, report in processor.reports.items():
report_path = output_path / f"{name}_{gas}_report.html"
with open(report_path, "w", encoding="utf-8") as file:
file.write(report)
# Save config
header = f"# Gasflux output config for file {name} from processing run at {processing_time}\n"
config_path = output_path / f"{name}_config.yaml"
with open(config_path, "w") as file:
file.write(header)
yaml.safe_dump(config, file)
# Save DataFrame to CSV
if hasattr(processor, 'df') and processor.df is not None:
csv_path = output_path / f"{name}_data.csv"
processor.df.to_csv(csv_path, index=False)
logger.info(f"DataFrame saved to {csv_path}")
# Save output variables
output_vars = processor.output_vars
# output_vars = delete_large_arrays(output_vars, threshold_size=50)
header = (
f"# Gasflux output variables for file {name} from processing run at {processing_time}\n"
)
filename = output_path / f"{name}_output_vars.json"
with open(filename, "w") as file:
file.write(header)
json.dump(
output_vars, file, default=lambda item: item.tolist() if isinstance(item, np.ndarray) else item, indent=4
)
logger.info(f"Processing run saved to {output_path}")
def delete_large_arrays(output_vars: dict, threshold_size: int) -> dict:
"""
Iterate through the output_vars dictionary and replace large numpy arrays
with their metadata (e.g., shape and data type).
Parameters:
output_vars (dict): The dictionary containing output data including potential numpy arrays.
threshold_size (int): The number of elements above which an array is considered large.
"""
del_keys = []
for key, value in output_vars.items():
if isinstance(value, dict):
output_vars[key] = delete_large_arrays(value, threshold_size) # recursive
elif isinstance(value, np.ndarray):
if value.size > threshold_size:
del_keys.append(key)
for key in del_keys:
del output_vars[key]
return output_vars

Binary file not shown.

142
src/gasflux/run_example.py Normal file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env python3
"""
GasFlux 完整处理示例脚本
这个脚本演示了完整的GasFlux处理流程
1. 使用data_processor.py处理原始Excel数据
2. GasFlux数据验证和处理
- 背景校正
- 空间处理
- 克里金插值
- 生成报告
运行方法:
python run_example.py input.xlsx
python run_example.py input.xlsx --output processed_data.csv
"""
import sys
import argparse
from pathlib import Path
# 导入同一包内的模块
# 优先尝试相对导入(当作为包的一部分运行时)
# 如果失败,则尝试绝对导入(当直接运行脚本时)
try:
# 尝试相对导入
from .processing_pipelines import process_main
from .data_processor import process_file
print("✅ 成功导入GasFlux模块相对导入")
except ImportError:
try:
# 相对导入失败,尝试绝对导入
from src.gasflux.processing_pipelines import process_main
from src.gasflux.data_processor import process_file
print("✅ 成功导入GasFlux模块绝对导入")
except ImportError as e:
print(f"❌ 导入GasFlux模块失败: {e}")
print("请确保GasFlux包结构完整或从项目根目录运行")
sys.exit(1)
def main():
"""主函数运行完整的数据处理和GasFlux分析流程"""
parser = argparse.ArgumentParser(
description="GasFlux完整处理流程Excel数据预处理 + 通量分析",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用示例:
python run_example.py data.xlsx # 基本使用
python run_example.py data.xlsx --output result.csv # 指定输出文件名
python run_example.py data.xlsx --no-gasflux # 仅预处理,不进行通量分析
处理步骤:
1. 使用data_processor.py处理Excel文件
2. 对处理后的数据进行GasFlux通量分析
"""
)
parser.add_argument('input_file', help='输入的Excel文件路径 (.xlsx 或 .xls)')
parser.add_argument('-o', '--output', help='预处理后的CSV输出文件名可选')
parser.add_argument('--no-gasflux', action='store_true',
help='仅执行数据预处理跳过GasFlux通量分析')
parser.add_argument('-c', '--config', help='GasFlux配置文件路径可选默认使用内置配置')
args = parser.parse_args()
print("=== GasFlux 完整处理流程 ===\n")
# 检查输入文件
input_path = Path(args.input_file)
if not input_path.exists():
print(f"❌ 错误:输入文件不存在: {input_path}")
return
if input_path.suffix.lower() not in ['.xlsx', '.xls']:
print(f"❌ 错误输入文件必须是Excel格式: {input_path}")
return
# 确定输出文件名
if args.output:
processed_csv = Path(args.output)
else:
processed_csv = input_path.with_suffix('.processed.csv')
# 确定配置文件
if args.config:
config_file = Path(args.config)
else:
config_file = Path(__file__).parent / "data" / "gasflux_config.yaml"
print(f"输入Excel文件: {input_path}")
print(f"预处理输出CSV: {processed_csv}")
if not args.no_gasflux:
print(f"GasFlux配置文件: {config_file}")
print()
try:
# 第一步:数据预处理
print("🔄 第一步:数据预处理...")
processed_df = process_file(str(input_path), str(processed_csv))
print(f"✅ 数据预处理完成,输出文件: {processed_csv}")
print()
# 如果不需要进行GasFlux分析直接返回
if args.no_gasflux:
print("⏭️ 跳过GasFlux通量分析")
return
# 第二步GasFlux通量分析
print("🔄 第二步GasFlux通量分析...")
# 检查配置文件
if not config_file.exists():
print(f"❌ 错误GasFlux配置文件不存在: {config_file}")
return
print(f"使用数据文件: {processed_csv}")
print(f"使用配置文件: {config_file}")
print()
# 运行GasFlux处理流程
process_main(processed_csv, config_file)
print("\n✅ GasFlux通量分析完成")
# 显示输出信息
output_dir = Path("../../examples/basic_usage/5m") / processed_csv.stem / "processing_run"
if output_dir.exists():
print(f"\n📁 GasFlux输出目录: {output_dir}")
print("📊 生成的文件:")
for file in output_dir.rglob("*"):
if file.is_file():
print(f" - {file.name}")
except Exception as e:
print(f"\n❌ 处理失败: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<style>
.grid-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
height: 800px;
}
.grid-item.double {
grid-column: span 2;
}
.grid-item {
width: 100%;
min-width: 300px;
}
.grid-item .plot-container {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<h1>{{title}}</h1>
<table>
<tbody>
{% for key, value in summary_data.items() %}
<tr>
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="grid-container">
<div class="grid-item">
<div class="plot-container">
{{ threeD|safe }}
</div>
</div>
<div class="grid-item double">
<div class="plot-container">
{{ krig|safe }}
</div>
</div>
<div class="grid-item">
<div class="plot-container">
{{ windrose|safe }}
</div>
</div>
<div class="grid-item double">
<div class="plot-container">
{{ wind|safe }}
</div>
</div>
<div class="grid-item double">
<div class="plot-container">
{{ background|safe }}
</div>
</div>
</div>
</body>
</html>

1001
src/gasflux/testdata/exampledata.csv vendored Normal file

File diff suppressed because it is too large Load Diff

95
src/gasflux/testdata/testconfig.yaml vendored Normal file
View File

@ -0,0 +1,95 @@
# testconfig.yaml
horizontal_pixels: 500 # Width of the concentration map in pixels
vertical_pixels: 100 # Height of the concentration map in pixels
num_plumes: 10 # Number of Gaussian plumes
groupiness: 0.5 # Groupiness of the plumes (0.0 to 1.0)
spread: 0.1 # Spread of the plumes (0.0 to 1.0)
wind_reference_height: 10 # Reference height for wind speed calculation (m)
windspeed_avg: 5 # Average wind speed at 10m height (m/s)
windspeed_rel_std: 0.2 # Relative standard deviation of wind speed (0.0 to inf), recommend 0.2-0.4
surface_roughness: 0.1 # Surface roughness length (m)
seed: 42 # Random seed for reproducibility
simplex_octaves: 4 # Number of octaves for simplex noise (1 to inf, def 1)
simplex_persistence: 0.7 # Persistence of simplex noise (0.0 to 1.0, def 0.5) - specifies the amplitude of each octave relative to the one below it
simplex_lacunarity: 2.0 # Lacunarity of simplex noise (1.0 to inf, def 2.0) - specifies the frequency of each octave relative to the one below it
winddir_avg: 0.0 # Average wind direction in degrees rel to plane (0 is CW)
winddir_std: 10 # Standard deviation of wind direction in degrees
timestamp: "2022-09-26 02:03:00"
flight_time_seconds: 1000
sample_frequency: 1
start_coords:
- 54.87667
- 15.41
transect_azimuth: 260 # the wind will start off 90 degrees CW to this azimuth, and is modified relative to that by the winddir_avg. 260 is a good value to test N problems
sampling_altitude_ato_range:
- -10 # negative values should be fine
- 100
sampling_horizontal_range:
- 50
- 950
scene_altitude_range:
- -20
- 120
scene_horizontal_range:
- 0
- 1000
number_of_transects: 10
gases:
ch4:
- 1.95
- 10.0
co2:
- 380.0
- 500.0
c2h6:
- 0.0
- 1.0
temperature: 10.0
pressure: 1000.0
output_dir: ~/gasflux_reports
algorithmic_baseline_settings:
algorithm: fastchrom
semivariogram_settings:
model: spherical
estimator: cressie
n_lags: 20
bin_func: even
fit_method: lm
maxlag: 100
#fit_sigma: linear
tolerance: 10
azimuth: 0
bandwidth: 20
ordinary_kriging_settings:
min_points: 3
max_points: 100
grid_resolution: 500
min_nodes: 10
cut_ground: False
y_min: ~
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [-100, 500]
windspeed: [0, 30]
winddir: [0, 360]
temperature: [-50, 60]
pressure: [900, 1100]
filters:
course_filter:
azimuth_filter: 10
azimuth_window: 5
elevation_filter: 5
strategies:
background: "algorithm"
sensor: "insitu"
spatial: "curtain"
interpolation: "kriging"

1001
src/gasflux/testdata/testdata.csv vendored Normal file

File diff suppressed because it is too large Load Diff

0
tests/__init__.py Normal file
View File

205
tests/test_processing.py Normal file
View File

@ -0,0 +1,205 @@
import pandas as pd
from src.gasflux import processing
import yaml
from pathlib import Path
import numpy as np
from src.gasflux.processing import min_angular_displacement
import pytest
testdf = pd.read_csv(Path(__file__).parents[1] / "src" / "gasflux" / "testdata" / "testdata.csv")
testconfig = yaml.safe_load(open(Path(__file__).parents[1] / "src" / "gasflux" / "testdata" / "testconfig.yaml"))
def load_cols(cols):
return testdf[cols]
def test_min_angular_diff_def():
def test_min_angular_displacement():
assert min_angular_displacement(10, 350) == 20
assert min_angular_displacement(0, 180) == 180
x = np.array([10, 0])
y = np.array([350, 180])
expected = np.array([20, 180])
result = min_angular_displacement(x, y)
assert np.all(result == expected), "Vectorized function failed"
def test_circ_median():
x = np.array([0, 1, 2, 359, 4, 3])
median = processing.circ_median(x)
assert median == 1.5, "Circular median not calculated correctly"
@pytest.mark.parametrize(
"plane_angle,expected_winddir_rel,expected_windspeed_normal",
[
(
90,
[0, 90, 0, 90, 0],
[5, 0, 5, 0, 5],
),
(
30,
[60, 30, 60, 30, 60],
np.array([1 / 2, np.sqrt(3) / 2, 1 / 2, np.sqrt(3) / 2, 1 / 2]) * 5,
),
(
60,
[30, 60, 30, 60, 30],
np.array([np.sqrt(3) / 2, 1 / 2, np.sqrt(3) / 2, 1 / 2, np.sqrt(3) / 2]) * 5,
),
],
)
def test_wind_offset_correction_parametrized(plane_angle, expected_winddir_rel, expected_windspeed_normal):
data = {"winddir": [0, 90, 180, 270, 360], "windspeed": [5, 5, 5, 5, 5]}
df = pd.DataFrame(data)
corrected_df = processing.wind_offset_correction(df, plane_angle)
assert "winddir_rel" in corrected_df.columns, f"Relative wind direction column not added for angle {plane_angle}"
assert "windspeed" in corrected_df.columns, f"Normalised wind speed column not added for angle {plane_angle}"
assert np.allclose(corrected_df["winddir_rel"], expected_winddir_rel, rtol=1e-5, atol=1e-10), (
f"Relative wind directions not calculated correctly for angle {plane_angle}"
)
assert np.allclose(corrected_df["windspeed"], expected_windspeed_normal, rtol=1e-5, atol=1e-10), (
f"Normalised wind speeds not calculated correctly for angle {plane_angle}"
)
def test_bimodal_azimuth():
input_mode = testconfig["transect_azimuth"]
input_reciprocal_mode = (input_mode + 180) % 360
df = load_cols(["course_azimuth", "height_ato"])
mode1, mode2 = processing.bimodal_azimuth(df)
assert (
min_angular_displacement(mode1, input_mode) < 3 or min_angular_displacement(mode1, input_reciprocal_mode) < 3
), "Mode1 does not match expected azimuth or its reciprocal within 3 degrees"
if min_angular_displacement(mode1, input_mode) < 3:
assert min_angular_displacement(mode2, input_reciprocal_mode) < 3, (
"Mode2 does not match expected reciprocal azimuth within 3 degrees"
)
else:
assert min_angular_displacement(mode2, input_mode) < 3, "Mode2 does not match expected azimuth within 3 degrees"
def test_bimodal_elevation():
df = load_cols(["course_elevation", "height_ato"])
input_mode = 0
input_reciprocal_mode = 0 - input_mode
mode1, mode2 = processing.bimodal_elevation(df)
assert (
min_angular_displacement(mode1, input_mode) < 3 or min_angular_displacement(mode1, input_reciprocal_mode) < 3
), "Mode1 does not match expected elevation or its reciprocal within 3 degrees"
if min_angular_displacement(mode1, input_mode) < 3:
assert min_angular_displacement(mode2, input_reciprocal_mode) < 3, (
"Mode2 does not match expected reciprocal elevation within 3 degrees"
)
else:
assert min_angular_displacement(mode2, input_mode) < 3, (
"Mode2 does not match expected elevation within 3 degrees"
)
def test_height_transect_splitter():
df = load_cols(["height_ato"])
df, fig = processing.height_transect_splitter(df)
assert "transect_num" in df.columns, "Transect number column not added to dataframe"
assert df["transect_num"].nunique() == testconfig["number_of_transects"], (
"Dataframe was not split into the right number of transects"
)
def test_add_transect_azimuth_switches():
df = load_cols(["course_azimuth"])
df = processing.add_transect_azimuth_switches(df)
assert df["transect_num"].nunique() == testconfig["number_of_transects"], (
"Transect azimuth switches not added to dataframe"
)
def test_course_filter():
df = load_cols(["course_azimuth", "course_elevation", "height_ato"])
azimuth_filter = testconfig["filters"]["course_filter"]["azimuth_filter"]
azimuth_window = testconfig["filters"]["course_filter"]["azimuth_window"]
elevation_filter = testconfig["filters"]["course_filter"]["elevation_filter"]
df_filtered, df_unfiltered = processing.course_filter(
df, azimuth_filter=azimuth_filter, azimuth_window=azimuth_window, elevation_filter=elevation_filter
)
input_mode = testconfig["transect_azimuth"]
input_reciprocal_mode = (input_mode + 180) % 360
# assert that the filtered dataframe contains the expected azimuth or its reciprocal within the window
df_filtered["near_mode1"] = df_filtered["rolling_course_azimuth"].apply(
lambda x: min_angular_displacement(x, input_mode) < azimuth_window
)
df_filtered["near_mode2"] = df_filtered["rolling_course_azimuth"].apply(
lambda x: min_angular_displacement(x, input_reciprocal_mode) < azimuth_window
)
assert df_filtered["near_mode1"].any() or df_filtered["near_mode2"].any(), (
"Filtered dataframe does not contain expected azimuth or its reciprocal within the window"
)
def test_mCount_max():
data_dict = {1: -5.4, 2: 0.6, 3: 5.6, 4: 3.2, 5: 10.4, 6: 18.4, 7: 20.8, 8: 19.4}
start, end = processing.mCount_max(data_dict)
assert start == 4, "Start index of max count not calculated correctly"
assert end == 7, "End index of max count not calculated correctly"
def test_largest_monotonic_transect_series():
df = load_cols(
["timestamp", "height_ato", "course_azimuth", "longitude", "latitude", "utm_easting", "utm_northing"]
)
df, starttransect, endtransect = processing.largest_monotonic_transect_series(df)
starttransect = 1
endtransect = testconfig["number_of_transects"]
assert starttransect == starttransect, "Start index of largest monotonic transect not calculated correctly"
assert endtransect == endtransect, "End index of largest monotonic transect not calculated correctly"
def test_remove_non_transects():
df = load_cols(
["height_ato", "course_azimuth", "course_elevation", "longitude", "latitude", "utm_easting", "utm_northing"]
)
retained_df, removed_df = processing.remove_non_transects(df)
assert retained_df is not None, "Retained dataframe is None"
assert removed_df is not None, "Removed dataframe is None"
def test_flatten_linear_plane():
df = load_cols(["height_ato", "utm_easting", "utm_northing"])
df, plane_angle = processing.flatten_linear_plane(df)
input_plane_angle = testconfig["transect_azimuth"]
reciprocal_plane_angle = (input_plane_angle + 180) % 360
assert (
min_angular_displacement(plane_angle, input_plane_angle) < 3
or min_angular_displacement(plane_angle, reciprocal_plane_angle) < 3
), "Plane angle not calculated correctly"
def test_drone_anemo_to_point_wind():
data = {
"yaw": [0, 90, 0, -90, 180],
"anemo_u": [0, 0, 10, 10, 10],
"anemo_v": [0, 0, 0, 0, 0],
"easting": [0, 10, 0, 10, 0],
"northing": [0, 0, 0, 0, 10],
}
df_test = pd.DataFrame(data)
yaw_col = "yaw"
anemo_u_col = "anemo_u"
anemo_v_col = "anemo_v"
easting_col = "easting"
northing_col = "northing"
result_df = processing.drone_anemo_to_point_wind(
df_test, yaw_col, anemo_u_col, anemo_v_col, easting_col, northing_col
)
expected_windspeed = np.array([0, 10, 10, np.sqrt(200), np.sqrt(200)])
expected_winddir = np.array(
[180, 270, 270, 225, 135]
) # 180 not zero because of the way IEEE 754 handles floating point numbers
windspeed_diff = np.abs(result_df["windspeed"].values - expected_windspeed)
winddir_diff = processing.min_angular_displacement(result_df["winddir"].to_numpy(), expected_winddir)
assert np.all(windspeed_diff < 1e-10), "Wind speed not calculated correctly"
assert np.all(np.array(winddir_diff) < 3), "Wind direction not calculated correctly"

View File

@ -0,0 +1,58 @@
from src.gasflux import processing_pipelines
import yaml
from pathlib import Path
import pytest
@pytest.fixture
def setup_test_environment(tmp_path):
"""Prepare actual test data and configuration with a modified output directory."""
df_path = Path(__file__).parents[1] / "src" / "gasflux" / "testdata" / "testdata.csv"
config_path = Path(__file__).parents[1] / "src" / "gasflux" / "testdata" / "testconfig.yaml"
with open(config_path) as f:
config = yaml.safe_load(f)
config["output_dir"] = str(tmp_path)
temp_config_path = tmp_path / "temp_testconfig.yaml"
with open(temp_config_path, "w") as f:
yaml.safe_dump(config, f)
return df_path, temp_config_path
def test_process_main_config_output(setup_test_environment):
df_path, temp_config_path = setup_test_environment
processing_pipelines.process_main(df_path, temp_config_path)
with open(temp_config_path) as f:
temp_config = yaml.safe_load(f)
output_dir = Path(temp_config["output_dir"]) / df_path.stem
assert output_dir.exists(), "Output directory does not exist."
processing_run_dirs = [d for d in output_dir.iterdir() if d.is_dir()]
assert len(processing_run_dirs) > 0, "No processing run directory found."
processing_run_dir = processing_run_dirs[0]
with open(temp_config_path) as f:
original_config = yaml.safe_load(f)
for gas in original_config.get("gases", []):
report_path = processing_run_dir / f"{df_path.stem}_{gas}_report.html"
assert report_path.exists(), f"Report for {gas} does not exist."
config_dump_path = processing_run_dir / f"{df_path.stem}_config.yaml"
assert config_dump_path.exists(), "Config dump file does not exist."
def load_and_redump(yaml_file):
with open(yaml_file) as file:
data = yaml.safe_load(file)
redumped_data = yaml.dump(data, sort_keys=True, default_flow_style=False)
return redumped_data
assert load_and_redump(temp_config_path) == load_and_redump(
config_dump_path
), "The dumped config does not match the input config."
def test_process_main_deterministic_output(setup_test_environment):
df_path, temp_config_path = setup_test_environment
processing_pipelines.process_main(df_path, temp_config_path)

View File

@ -0,0 +1,108 @@
"""a script to split a folder of flights into multiple flights based on the monotonic changes in altitude.
Takes a csv file as an input and will split it out into several csvs.
Needs course azimuths to work properly.
"""
import argparse
from pathlib import Path
import colorama
import numpy as np
import pandas as pd
from src.gasflux import processing
colorama.init()
def main(target_dir, search_string, filter_mask, output_dir=None):
df_list = {}
for file_path in Path(target_dir).rglob(search_string):
df = pd.read_csv(file_path)
df_list[file_path] = df
for file_path, df in df_list.items():
print(colorama.Fore.WHITE + "----------------------------------------")
if filter_mask in df.columns: # check for boolean mask columns
df = df[~df[filter_mask]].reset_index(drop=True)
df, groupdict = processing.monotonic_transect_groups(df)
last_transect = None
last_group_trend = None
for group in df["group"].unique():
# leaving this out for now as the group folder is a good identifier
# if len(df['group'].unique()) == 1:
# print(colorama.Fore.RED + f'Skipping{file_path.name} - only one group')
# continue
group_df = df[df["group"] == group]
avg_altitudes = group_df.groupby("transect_num")["height_ato"].mean().values
avg_change = (
sum([avg_altitudes[i + 1] - avg_altitudes[i] for i in range(len(avg_altitudes) - 1)])
/ len(avg_altitudes)
if len(avg_altitudes) > 1
else 0
)
# what's the trend
current_group_trend = "ascending" if avg_change > 0 else "descending"
# add last transect from previous group if there's a change in trend
if last_group_trend and last_group_trend != current_group_trend and last_transect is not None:
group_df = pd.concat([last_transect, group_df])
avg_altitudes = group_df.groupby("transect_num")["height_ato"].mean().values
avg_altitudes = np.array(avg_altitudes)
# check if the group is monotonic
is_monotonic = np.all(np.diff(avg_altitudes) > 0) or np.all(np.diff(avg_altitudes) < 0)
if not is_monotonic: # exception
print(f"group {group} is not monotonic - check the code!")
formatted_avg_altitudes = ", ".join([f"{alt:.1f}" for alt in avg_altitudes])
# do it where transect is the maximum transect number
last_transect = group_df[group_df["transect_num"] == group_df["transect_num"].max()].copy()
last_transect.loc[:, "transect_num"] = 0
last_group_trend = current_group_trend
unique_transects = len(group_df["transect_num"].unique())
if unique_transects < 3:
print(
colorama.Fore.RED + f"Not saving {group} from {file_path} - too few transects"
f"({unique_transects} transects at {formatted_avg_altitudes}m)"
)
else:
file_path = Path(file_path)
if output_dir:
output_path = Path(
Path(output_dir)
/ f"{file_path.parents[1].name}"
/ f"{file_path.parent.name}_{group}"
/ f"{file_path.stem}_{group}.csv"
)
else:
# assuming in date and time folder
output_path = Path(
file_path.parent.parent.parent # time -> date -> analysis
/ "splits"
/ file_path.parent.parent.name # date
/ f"{file_path.parent.name}_{group}" # time + group
/ f"{file_path.stem}_{group}.csv"
)
output_path.parent.mkdir(parents=True, exist_ok=True)
group_df.to_csv(output_path, index=False)
print(
colorama.Fore.GREEN
+ f'wrote {unique_transects} monotonic transects at {formatted_avg_altitudes}m to \n'
f'{"/".join(output_path.parts[-5:])}'
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--target-dir", help="the directory to search for csvs", default="survey")
parser.add_argument("--search-string", help="the string to search for in the directory", default="*filtered.csv")
parser.add_argument(
"--filter-mask", help="name of a column with a boolean filter; TRUE means discard", default="filtered"
)
parser.add_argument("--output-dir", help="the metadirectory to save the date/time/csvs to", required=False)
args = parser.parse_args()
main(
args.target_dir,
args.search_string,
args.filter_mask,
args.output_dir,
)