增加web_api

This commit is contained in:
2026-02-05 15:13:54 +08:00
parent 443ec09c5c
commit d5edbc0723
43 changed files with 7036 additions and 2640 deletions

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

1734
API_DOCUMENTATION.md Normal file

File diff suppressed because it is too large Load Diff

782
API_ENDPOINTS.md Normal file
View File

@ -0,0 +1,782 @@
# GasFlux Web API 端点参考
## 概述
GasFlux Web API 是一个基于 Flask 的 RESTful API用于上传数据文件、执行气体通量分析处理并下载处理结果。
**基础信息:**
- **基础 URL**: `http://localhost:5000`
- **认证**: 无需认证
- **数据格式**: JSON
- **文件大小限制**: 100MB
- **支持的文件类型**: `.xlsx`, `.xls`, `.yaml`, `.yml`
---
## 🔍 监控和健康检查
### 1. 获取健康状态
**端点**: `GET /health`
**描述**: 获取 API 的健康状态、系统信息和性能指标。
**响应示例** (200):
```json
{
"code": 200,
"message": "健康检查完成",
"data": {
"status": "healthy",
"version": "1.0.0",
"timestamp": 1705257600.123,
"uptime": "2h 30m 15s",
"storage": {
"uploads_writable": true,
"outputs_writable": true
},
"tasks": {
"active_count": 2,
"total_tracked": 15,
"total_processed": 13,
"success_rate_percent": 92.31
},
"performance": {
"requests_per_second": 0.08,
"avg_response_time_ms": 234.56,
"error_rate_percent": 1.5
}
}
}
```
**响应示例** (503):
```json
{
"code": 503,
"message": "服务不可用",
"data": {
"status": "degraded",
"version": "1.0.0",
"timestamp": 1705257600.123,
"uptime": "1h 30m 45s",
"storage": {
"uploads_writable": true,
"outputs_writable": true
},
"tasks": {
"active_count": 0,
"total_tracked": 5,
"total_processed": 3,
"success_rate_percent": 60.0
},
"performance": {
"requests_per_second": 0.12,
"avg_response_time_ms": 145.67,
"error_rate_percent": 50.0
},
"issues": [
"错误率过高 (50.0%)",
"活跃任务数量过多 (25)"
]
}
}
```
**状态码**:
- `200`: API 健康
- `503`: API 不健康
---
### 2. 获取系统统计信息
**端点**: `GET /stats`
**描述**: 获取详细的 API 统计信息、性能指标和系统监控数据。
**响应示例** (200):
```json
{
"code": 200,
"message": "统计信息获取成功",
"data": {
"summary": {
"uptime_seconds": 3600.5,
"uptime_formatted": "1h 0m 0s",
"requests_total": 150,
"requests_per_second": 0.04,
"error_rate_percent": 2.0,
"active_tasks": 1
},
"requests": {
"by_method": {
"GET": 120,
"POST": 30
},
"by_status": {
"200": 145,
"400": 3,
"500": 2
},
"top_endpoints": {
"/task/abc123": 45,
"/health": 30,
"/": 25
}
},
"tasks": {
"total_created": 25,
"total_completed": 20,
"total_failed": 2,
"success_rate_percent": 90.91,
"by_status": {
"pending": 1,
"processing": 1,
"completed": 20,
"failed": 2
}
},
"performance": {
"avg_response_time_ms": 245.67,
"max_response_time_ms": 1250.34,
"min_response_time_ms": 12.45
},
"system": {
"memory_usage_percent": 45.2,
"memory_used_gb": 7.3,
"memory_total_gb": 16.0,
"disk_usage_percent": 23.1,
"disk_used_gb": 46.8,
"disk_total_gb": 203.2
},
"recent_tasks": [
{
"task_id": "abc123-def456",
"status": "completed",
"age_seconds": 45.2,
"message": "处理完成成功"
}
]
}
}
```
**状态码**:
- `200`: 成功
---
### 3. 重置统计信息
**端点**: `POST /stats/reset`
**描述**: 重置所有 API 统计数据(管理员功能)。
**响应示例** (200):
```json
{
"code": 200,
"message": "统计信息重置成功",
"data": {
"timestamp": 1705257600.123
}
}
```
**状态码**:
- `200`: 成功
---
### 4. 获取配置信息
**端点**: `GET /config`
**描述**: 获取当前应用配置信息和支持的环境变量。
**响应示例** (200):
```json
{
"code": 200,
"message": "配置信息获取成功",
"data": {
"configuration": {
"host": "0.0.0.0",
"port": 5000,
"debug": false,
"base_dir": "/app",
"upload_folder": "/app/web_api_data/uploads",
"output_folder": "/app/web_api_data/outputs",
"max_content_length": 104857600,
"log_level": "INFO",
"log_file": "logs/gasflux_api.log",
"cors_origins": ["*"],
"task_cleanup_interval": 3600,
"max_task_age": 86400,
"threads": 8,
"connection_limit": 100,
"channel_timeout": 300
},
"environment_variables": {
"supported": [
"GASFLUX_HOST", "GASFLUX_PORT", "GASFLUX_DEBUG",
"GASFLUX_UPLOAD_FOLDER", "GASFLUX_OUTPUT_FOLDER",
"GASFLUX_MAX_CONTENT_LENGTH", "GASFLUX_LOG_LEVEL",
"GASFLUX_LOG_FILE", "GASFLUX_CORS_ORIGINS",
"GASFLUX_TASK_CLEANUP_INTERVAL", "GASFLUX_MAX_TASK_AGE",
"GASFLUX_THREADS", "GASFLUX_CONNECTION_LIMIT",
"GASFLUX_CHANNEL_TIMEOUT"
],
"current_values": {
"GASFLUX_HOST": "0.0.0.0",
"GASFLUX_PORT": "5000",
"GASFLUX_DEBUG": "false"
}
}
}
}
```
**状态码**:
- `200`: 成功
---
## 📤 文件上传和管理
### 5. 文件上传和处理
**端点**: `POST /upload`
**描述**: 上传数据文件并启动异步处理任务。
**请求参数** (multipart/form-data):
- `file` (必需): 数据文件 (.xlsx 或 .xls 格式)
- `config` (可选): 配置文件 (.yaml 或 .yml 格式)
**响应示例** (202):
```json
{
"code": 202,
"message": "任务已接受并加入处理队列",
"data": {
"status": "accepted",
"job_id": "abc123-def456-ghi789",
"task_status_url": "/task/abc123-def456-ghi789"
}
}
```
**错误响应示例** (400):
```json
{
"code": 400,
"message": "无效的数据文件类型。只允许 .xlsx 和 .xls 格式。",
"data": {}
}
```
**错误响应示例** (413):
```json
{
"code": 413,
"message": "文件过大。最大尺寸为 100MB。",
"data": {}
}
```
**状态码**:
- `202`: 任务已接受
- `400`: 请求参数错误
- `413`: 文件过大
---
## 📊 任务管理和监控
### 6. 分页查询任务列表
**端点**: `GET /tasks`
**描述**: 分页查询所有任务,支持按状态过滤、排序和分页。返回体为前端友好的瘦身结构:仅包含任务状态信息;当任务已完成时会包含 `downloads` 直达下载链接。
**查询参数**:
- `page` (可选): 页码 (默认: 1)
- `page_size` (可选): 每页任务数量 (默认: 20, 最大: 100)
- `sort_by` (可选): 排序字段 ('created_at', 'updated_at', 'status') (默认: 'updated_at')
- `sort_order` (可选): 排序顺序 ('asc', 'desc') (默认: 'desc')
- `status` (可选): 按任务状态过滤,支持多个状态用逗号分隔
**响应示例** (200):
```json
{
"code": 200,
"message": "任务列表查询成功",
"data": {
"tasks": [
{
"task_id": "abc123-def456-ghi789",
"status": "completed",
"message": "Processing completed successfully",
"updated_at": 1705257700.456,
"downloads": {
"data_xlsx": "/download/abc123-def456-ghi789/08_34_01_5m.processed_data.xlsx",
"report_ch4": "/download/abc123-def456-ghi789/08_34_01_5m.processed_ch4_report.html",
"report_co2": "/download/abc123-def456-ghi789/08_34_01_5m.processed_co2_report.html",
"config": "/download/abc123-def456-ghi789/08_34_01_5m.processed_config.yaml",
"metadata": "/download/abc123-def456-ghi789/08_34_01_5m.processed_output_vars.json"
}
},
{
"task_id": "xyz789-abc123-def456",
"status": "processing",
"message": "正在进行数据分析...",
"updated_at": 1705257650.321
}
],
"total": 25,
"page": 1,
"page_size": 20,
"total_pages": 2,
"has_next": true,
"has_prev": false
}
}
```
**状态码**:
- `200`: 成功
- `400`: 参数无效
---
### 7. 获取任务池统计信息
**端点**: `GET /tasks/stats`
**描述**: 获取任务池的统计信息,包括各状态任务数量、活跃任务数等。
**响应示例** (200):
```json
{
"code": 200,
"message": "任务池统计信息查询成功",
"data": {
"total_tasks": 25,
"status_counts": {
"pending": 3,
"processing": 2,
"completed": 18,
"failed": 2
},
"active_tasks": 2,
"queued_tasks": 3,
"completed_tasks": 18,
"failed_tasks": 2
}
}
```
**状态码**:
- `200`: 成功
---
### 8. 获取活跃任务列表
**端点**: `GET /tasks/active`
**描述**: 获取当前正在处理的任务列表(瘦身结构)。当列表中包含已完成任务时会附带 `downloads` 直达下载链接。
**响应示例** (200):
```json
{
"code": 200,
"message": "活跃任务查询成功",
"data": {
"active_tasks": [
{
"task_id": "abc123-def456-ghi789",
"status": "processing",
"message": "正在生成报告...",
"updated_at": 1705257650.321
},
{
"task_id": "completed-task-123",
"status": "completed",
"message": "Processing completed successfully",
"updated_at": 1705257550.456,
"downloads": {
"data_xlsx": "/download/completed-task-123/processed_data.xlsx",
"report_html": "/download/completed-task-123/data_report.html"
}
}
],
"count": 2
}
}
```
**状态码**:
- `200`: 成功
---
### 9. 获取队列任务列表
**端点**: `GET /tasks/queue`
**描述**: 获取等待处理的任务队列(瘦身结构)。当列表中包含已完成任务时会附带 `downloads` 直达下载链接。
**响应示例** (200):
```json
{
"code": 200,
"message": "队列任务查询成功",
"data": {
"queued_tasks": [
{
"task_id": "xyz789-abc123-def456",
"status": "pending",
"message": "等待处理",
"updated_at": 1705257400.123
},
{
"task_id": "completed-queued-task",
"status": "completed",
"message": "Processing completed successfully",
"updated_at": 1705257450.321,
"downloads": {
"data_xlsx": "/download/completed-queued-task/processed_data.xlsx",
"report_html": "/download/completed-queued-task/analysis_report.html"
}
}
],
"count": 2,
"queue_position_info": "任务按创建时间排序,较早的任务优先处理"
}
}
```
**状态码**:
- `200`: 成功
---
### 10. 查询任务状态
**端点**: `GET /task/{task_id}`
**描述**: 查询异步处理任务的当前状态和进度信息。
**路径参数**:
- `task_id`: 任务 ID (UUID 格式)
**响应示例** - 处理中 (200):
```json
{
"code": 200,
"message": "任务查询成功",
"data": {
"task_id": "abc123-def456-ghi789",
"status": "processing",
"message": "GasFlux 分析完成,正在生成报告...",
"updated_at": 1705257600.123
}
}
```
**响应示例** - 处理完成 (200):
```json
{
"code": 200,
"message": "任务查询成功",
"data": {
"task_id": "abc123-def456-ghi789",
"status": "completed",
"message": "处理完成成功",
"updated_at": 1705257600.123,
"results": [
{
"name": "08_34_01_5m.processed_ch4_report.html",
"rel_path": "abc123-def456-ghi789/08_34_01_5m.processed_ch4_report.html",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed_ch4_report.html",
"size": 245760,
"type": "report"
},
{
"name": "08_34_01_5m.processed_data.xlsx",
"rel_path": "abc123-def456-ghi789/08_34_01_5m.processed_data.xlsx",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed_data.xlsx",
"size": 153600,
"type": "data"
},
{
"name": "08_34_01_5m.processed_config.yaml",
"rel_path": "abc123-def456-ghi789/08_34_01_5m.processed_config.yaml",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed_config.yaml",
"size": 2048,
"type": "config"
},
{
"name": "08_34_01_5m.processed_output_vars.json",
"rel_path": "abc123-def456-ghi789/08_34_01_5m.processed_output_vars.json",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed_output_vars.json",
"size": 4096,
"type": "metadata"
}
],
"downloads": {
"data_xlsx": "/download/abc123-def456-ghi789/08_34_01_5m.processed_data.xlsx",
"report_ch4": "/download/abc123-def456-ghi789/08_34_01_5m.processed_ch4_report.html",
"report_co2": "/download/abc123-def456-ghi789/08_34_01_5m.processed_co2_report.html",
"config": "/download/abc123-def456-ghi789/08_34_01_5m.processed_config.yaml",
"metadata": "/download/abc123-def456-ghi789/08_34_01_5m.processed_output_vars.json"
}
}
}
```
**响应示例** - 任务不存在 (404):
```json
{
"code": 404,
"message": "任务未找到",
"data": {}
}
```
**状态码**:
- `200`: 成功
- `404`: 任务不存在
---
### 11. 更新任务状态
**端点**: `PUT /task/{task_id}`
**描述**: 更新任务的状态、信息或优先级。
**路径参数**:
- `task_id`: 任务 ID (UUID 格式)
**请求参数** (JSON):
- `status` (可选): 新的任务状态
- `message` (可选): 状态消息或错误描述
- `priority` (可选): 任务优先级 (normal/high/low)
**响应示例** (200):
```json
{
"code": 200,
"message": "任务更新成功",
"data": {
"task_id": "abc123-def456-ghi789",
"status": "updated",
"task_info": {
"status": "completed",
"message": "手动标记为完成",
"updated_at": 1705257600.123,
"priority": "normal"
}
}
}
```
**错误响应示例** (404):
```json
{
"code": 404,
"message": "任务未找到",
"data": {}
}
```
**错误响应示例** (400):
```json
{
"code": 400,
"message": "无效状态。必须是以下之一: pending, processing, completed, failed",
"data": {}
}
```
**状态码**:
- `200`: 成功
- `400`: 无效请求
- `404`: 任务不存在
---
### 12. 删除任务
**端点**: `DELETE /task/{task_id}`
**描述**: 删除任务及其所有相关的文件和数据。
**路径参数**:
- `task_id`: 任务 ID (UUID 格式)
**响应示例** (200):
```json
{
"code": 200,
"message": "任务及相关文件删除成功",
"data": {
"task_id": "abc123-def456-ghi789",
"status": "deleted",
"details": {
"folders_deleted": 1,
"total_size_deleted": 307200,
"task_status": "completed"
}
}
}
```
**错误响应示例** (404):
```json
{
"code": 404,
"message": "任务未找到",
"data": {}
}
```
**错误响应示例** (409):
```json
{
"code": 409,
"message": "无法删除当前正在处理或等待处理的任务",
"data": {
"task_status": "processing"
}
}
```
**状态码**:
- `200`: 成功
- `404`: 任务不存在
- `409`: 任务正在处理
---
## 📋 报告管理和查询
### 13. 分页查询已生成报告
**端点**: `GET /reports`
**描述**: 分页查询所有已生成的处理报告,支持排序和过滤。
**查询参数**:
- `page` (可选): 页码 (默认: 1)
- `per_page` (可选): 每页报告数量 (默认: 20, 最大: 100)
- `sort_by` (可选): 排序字段 (默认: created_at)
- `sort_order` (可选): 排序顺序 (默认: desc)
- `status` (可选): 按任务状态过滤
**响应示例** (200):
```json
{
"code": 200,
"message": "报告列表获取成功",
"data": {
"reports": [
{
"task_id": "abc123-def456-ghi789",
"report_name": "08_34_01_5m",
"status": "completed",
"created_at": 1705257600.123,
"file_count": 4,
"total_size": 307200,
"processing_time_seconds": 125.67,
"main_report": {
"name": "08_34_01_5m.processed_ch4_report.html",
"size": 245760,
"type": "report",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed/2026-01-14_10-33-29-961698_processing_run/08_34_01_5m.processed_ch4_report.html"
},
"all_files": [
{
"name": "08_34_01_5m.processed_ch4_report.html",
"size": 245760,
"type": "report",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed/2026-01-14_10-33-29-961698_processing_run/08_34_01_5m.processed_ch4_report.html"
},
{
"name": "08_34_01_5m.processed_data.csv",
"size": 153600,
"type": "data",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed/2026-01-14_10-33-29-961698_processing_run/08_34_01_5m.processed_data.csv"
},
{
"name": "08_34_01_5m.processed_config.yaml",
"size": 2048,
"type": "config",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed/2026-01-14_10-33-29-961698_processing_run/08_34_01_5m.processed_config.yaml"
},
{
"name": "08_34_01_5m.processed_output_vars.json",
"size": 4096,
"type": "metadata",
"download_url": "/download/abc123-def456-ghi789/08_34_01_5m.processed/2026-01-14_10-33-29-961698_processing_run/08_34_01_5m.processed_output_vars.json"
}
],
"run_directory": "abc123-def456-ghi789/08_34_01_5m.processed/2026-01-14_10-33-29-961698_processing_run"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total_reports": 45,
"total_pages": 3,
"has_next": true,
"has_prev": false
},
"filters": {
"sort_by": "created_at",
"sort_order": "desc",
"status": null
}
}
}
```
**错误响应示例** (400):
```json
{
"code": 400,
"message": "Invalid parameter: per_page must be between 1 and 100",
"data": {}
}
```
**状态码**:
- `200`: 成功
- `400`: 参数无效
---
## 📁 文件下载
### 14. 下载处理结果
**端点**: `GET /download/{filename}`
**描述**: 下载处理后的结果文件,支持传入完整文件路径。
**路径参数**:
- `filename`: 文件的完整路径或相对路径 (包含任务ID)
**状态码**:
- `200`: 成功下载文件
- `403`: 访问被拒绝
- `404`: 文件不存在
- `400`: 路径不是文件
---
## 🌐 Web 界面
### 15. Web 管理界面
**端点**: `GET /`
**描述**: 访问用户友好的 Web 界面,支持文件上传、任务监控和结果下载。
**状态码**:
- `200`: 成功
---
*最后更新: 2026年1月29日*
*GasFlux Web API 版本: 1.0.0*

255
ENVIRONMENT_VARIABLES.md Normal file
View File

@ -0,0 +1,255 @@
# GasFlux Web API - 环境变量配置指南
本文档介绍如何使用环境变量来配置 GasFlux Web API 的行为。
## 概述
GasFlux 支持通过环境变量进行灵活配置,无需修改代码即可适应不同的部署环境和需求。
## 环境变量列表
### 服务器配置
| 变量名 | 默认值 | 描述 |
|--------|--------|------|
| `GASFLUX_HOST` | `0.0.0.0` | 服务器监听主机地址 |
| `GASFLUX_PORT` | `5000` | 服务器监听端口 |
| `GASFLUX_DEBUG` | `false` | 是否启用调试模式 (true/false) |
### 目录配置
| 变量名 | 默认值 | 描述 |
|--------|--------|------|
| `GASFLUX_UPLOAD_FOLDER` | `web_api_data/uploads` | 上传文件存储目录 |
| `GASFLUX_OUTPUT_FOLDER` | `web_api_data/outputs` | 处理结果输出目录 |
### 文件和性能配置
| 变量名 | 默认值 | 描述 |
|--------|--------|------|
| `GASFLUX_MAX_CONTENT_LENGTH` | `104857600` (100MB) | 最大上传文件大小(字节) |
| `GASFLUX_THREADS` | `8` | Waitress 服务器线程数 |
| `GASFLUX_CONNECTION_LIMIT` | `100` | 最大并发连接数 |
| `GASFLUX_CHANNEL_TIMEOUT` | `300` | 连接超时时间(秒) |
### 日志配置
| 变量名 | 默认值 | 描述 |
|--------|--------|------|
| `GASFLUX_LOG_LEVEL` | `INFO` | 日志级别 (DEBUG/INFO/WARNING/ERROR/CRITICAL) |
| `GASFLUX_LOG_FILE` | `logs/gasflux_api.log` | 日志文件路径 |
### 安全和跨域配置
| 变量名 | 默认值 | 描述 |
|--------|--------|------|
| `GASFLUX_CORS_ORIGINS` | `*` | 允许的 CORS 源,用逗号分隔 |
### 任务管理配置
| 变量名 | 默认值 | 描述 |
|--------|--------|------|
| `GASFLUX_TASK_CLEANUP_INTERVAL` | `3600` | 任务清理检查间隔(秒) |
| `GASFLUX_MAX_TASK_AGE` | `86400` | 任务最大保留时间24小时 |
## 配置示例
### 开发环境
```bash
# 开发环境配置
export GASFLUX_HOST=127.0.0.1
export GASFLUX_PORT=5000
export GASFLUX_DEBUG=true
export GASFLUX_LOG_LEVEL=DEBUG
```
### 生产环境
```bash
# 生产环境配置
export GASFLUX_HOST=0.0.0.0
export GASFLUX_PORT=80
export GASFLUX_DEBUG=false
export GASFLUX_LOG_LEVEL=INFO
export GASFLUX_THREADS=16
export GASFLUX_CONNECTION_LIMIT=200
export GASFLUX_MAX_CONTENT_LENGTH=524288000 # 500MB
```
### Docker 部署
```bash
# Docker 环境变量
docker run -p 80:5000 \
-e GASFLUX_HOST=0.0.0.0 \
-e GASFLUX_PORT=5000 \
-e GASFLUX_LOG_LEVEL=INFO \
gasflux-api
```
### Windows 服务
创建 `start_gasflux.bat`:
```batch
@echo off
set GASFLUX_HOST=0.0.0.0
set GASFLUX_PORT=80
set GASFLUX_LOG_LEVEL=INFO
set GASFLUX_THREADS=8
GasFluxAPI.exe
```
### Linux systemd
创建 `/etc/systemd/system/gasflux.service`:
```ini
[Unit]
Description=GasFlux Web API
After=network.target
[Service]
Type=simple
User=gasflux
Environment=GASFLUX_HOST=0.0.0.0
Environment=GASFLUX_PORT=80
Environment=GASFLUX_LOG_LEVEL=INFO
Environment=GASFLUX_THREADS=8
ExecStart=/path/to/GasFluxAPI
Restart=always
[Install]
WantedBy=multi-user.target
```
## 运行时配置检查
启动应用后,可以通过以下方式检查当前配置:
### API 端点
```bash
curl http://localhost:5000/config
```
### 启动日志
应用启动时会输出当前配置信息:
```
Configuration: {
'host': '0.0.0.0',
'port': 5000,
'debug': False,
...
}
```
## 最佳实践
### 安全考虑
1. **生产环境**
- 设置 `GASFLUX_DEBUG=false`
- 配置适当的 `GASFLUX_CORS_ORIGINS`
- 使用防火墙限制访问
2. **文件权限**
- 确保上传和输出目录有适当的权限
- 定期清理旧文件
### 性能调优
1. **线程数**:根据 CPU 核心数设置 `GASFLUX_THREADS`
2. **连接限制**:根据服务器容量设置 `GASFLUX_CONNECTION_LIMIT`
3. **文件大小**:根据实际需求调整 `GASFLUX_MAX_CONTENT_LENGTH`
### 日志管理
1. **日志轮转**:定期备份和清理日志文件
2. **日志级别**
- 开发环境:`DEBUG`
- 生产环境:`INFO``WARNING`
## 故障排除
### 常见问题
1. **端口占用**
```bash
# 检查端口使用
netstat -tulpn | grep :5000
```
2. **权限问题**
```bash
# 确保目录权限正确
chmod -R 755 web_api_data/
```
3. **配置不生效**
- 确保环境变量在应用启动前设置
- 检查变量名拼写是否正确
### 调试配置
启用详细日志查看配置加载:
```bash
export GASFLUX_LOG_LEVEL=DEBUG
# 启动应用
```
## 配置验证脚本
创建一个验证脚本 `check_config.py`
```python
#!/usr/bin/env python3
"""Configuration validation script"""
import os
from pathlib import Path
def check_config():
"""Check current configuration."""
print("GasFlux Configuration Check")
print("=" * 40)
# Server config
print(f"Host: {os.getenv('GASFLUX_HOST', '0.0.0.0')}")
print(f"Port: {os.getenv('GASFLUX_PORT', '5000')}")
print(f"Debug: {os.getenv('GASFLUX_DEBUG', 'false')}")
print(f"Log Level: {os.getenv('GASFLUX_LOG_LEVEL', 'INFO')}")
# Directory config
base_dir = Path.cwd()
upload_dir = base_dir / os.getenv('GASFLUX_UPLOAD_FOLDER', 'web_api_data/uploads')
output_dir = base_dir / os.getenv('GASFLUX_OUTPUT_FOLDER', 'web_api_data/outputs')
print(f"Upload Folder: {upload_dir}")
print(f"Output Folder: {output_dir}")
# Check directories
print("
Directory Status:")
print(f"Upload dir exists: {upload_dir.exists()}")
print(f"Output dir exists: {output_dir.exists()}")
# Performance config
print("
Performance Config:")
print(f"Threads: {os.getenv('GASFLUX_THREADS', '8')}")
print(f"Connection Limit: {os.getenv('GASFLUX_CONNECTION_LIMIT', '100')}")
if __name__ == "__main__":
check_config()
```
运行验证:
```bash
python check_config.py
```

203
EXE_BUILD_README.md Normal file
View File

@ -0,0 +1,203 @@
# GasFlux Web API - Executable Build Guide
This guide explains how to build and deploy the GasFlux Web API as a standalone executable using Waitress WSGI server.
## Prerequisites
Before building the executable, ensure you have all dependencies installed:
```bash
# Install all required packages
pip install -r requirements.txt
# Install build tools
pip install pyinstaller waitress
```
## Building the Executable
### Windows
Run the build script:
```cmd
build_exe.bat
```
Or manually:
```cmd
pyinstaller --onefile ^
--name GasFluxAPI ^
--hidden-import waitress ^
--hidden-import flask ^
--hidden-import werkzeug ^
--hidden-import yaml ^
--hidden-import pandas ^
--hidden-import numpy ^
--hidden-import flask_cors ^
--add-data "src\gasflux\gasflux_config.yaml;src\gasflux" ^
--add-data "API_DOCUMENTATION.md;." ^
--exclude-module matplotlib ^
--exclude-module tkinter ^
server_waitress.py
```
### Linux/macOS
Make the build script executable and run it:
```bash
chmod +x build_exe.sh
./build_exe.sh
```
Or manually:
```bash
pyinstaller --onefile \
--name GasFluxAPI \
--hidden-import waitress \
--hidden-import flask \
--hidden-import werkzeug \
--hidden-import yaml \
--hidden-import pandas \
--hidden-import numpy \
--hidden-import flask_cors \
--add-data "src/gasflux/gasflux_config.yaml:src/gasflux" \
--add-data "API_DOCUMENTATION.md:." \
--exclude-module matplotlib \
--exclude-module tkinter \
server_waitress.py
```
## Running the Executable
After successful build, you'll find `GasFluxAPI.exe` (Windows) or `GasFluxAPI` (Linux/macOS) in the `dist/` directory.
### Basic Usage
```bash
# Windows
GasFluxAPI.exe
# Linux/macOS
./GasFluxAPI
```
The server will start on `http://localhost:5000` by default.
### Command Line Options
Waitress supports various command-line options. You can create a wrapper script to customize:
```bash
# Custom port and host
waitress-serve --listen=0.0.0.0:8080 server_waitress:app
# Production settings
waitress-serve --threads=16 --connection-limit=200 server_waitress:app
```
## Deployment Considerations
### Directory Structure
When deploying the executable, ensure these directories exist and are writable:
```
your-deployment-directory/
├── GasFluxAPI(.exe) # The executable
├── web_api_data/ # Data directory (auto-created)
│ ├── uploads/ # Uploaded files
│ └── outputs/ # Processing results
├── logs/ # Log files (auto-created)
└── gasflux_config.yaml # Configuration (optional)
```
### Firewall Configuration
Make sure the server port (default 5000) is open in your firewall.
### Production Deployment
For production use:
1. **Use a reverse proxy**: Place Nginx or Apache in front of the executable
2. **SSL/TLS**: Configure HTTPS
3. **Process management**: Use systemd, supervisor, or similar
4. **Logging**: Configure log rotation
### Example systemd Service (Linux)
Create `/etc/systemd/system/gasflux-api.service`:
```ini
[Unit]
Description=GasFlux Web API
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/deployment
ExecStart=/path/to/deployment/GasFluxAPI
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
Then:
```bash
sudo systemctl daemon-reload
sudo systemctl enable gasflux-api
sudo systemctl start gasflux-api
```
## Troubleshooting
### Common Issues
1. **"Permission denied"**: Ensure the executable has execute permissions and data directories are writable
2. **"Port already in use"**: Change the port or stop other services using port 5000
3. **"Module not found"**: Some dependencies might be missing. Try:
```bash
pip install --upgrade pyinstaller
pip install -r requirements.txt
```
4. **Large executable size**: The `--exclude-module` options help reduce size, but some scientific packages are large
### Performance Tuning
- **Threads**: Increase `--threads` for more concurrent requests
- **Connection limit**: Adjust `--connection-limit` based on server capacity
- **Memory**: Monitor memory usage, especially with large data processing
### Logs
Logs are written to:
- Console output (when running interactively)
- `logs/gasflux_api.log` file
Check logs for startup errors and runtime issues.
## API Documentation
Once running, access the API documentation at:
- Web interface: `http://your-server:5000`
- API docs: See `API_DOCUMENTATION.md`
- Statistics: `GET /stats` - Real-time API statistics and monitoring
- Health check: `GET /health` - System health with performance metrics
## Security Notes
- Default configuration listens on all interfaces (`0.0.0.0`)
- No authentication is configured by default
- Consider adding authentication and SSL for production use
- Regularly update dependencies for security patches

View File

@ -0,0 +1,422 @@
# GasFlux 配置清单完整说明文档
## 概述
GasFlux 是一个用于处理无人机气体通量数据的完整管道系统。本文档详细说明了所有配置文件参数及其使用方法。
## 配置文件结构
GasFlux 使用 YAML 格式的配置文件,主要包含以下几个部分:
1. **输出设置** (`output_dir`)
2. **必需列定义** (`required_cols`)
3. **气体配置** (`gases`)
4. **处理策略** (`strategies`)
5. **背景校正设置** (`algorithmic_baseline_settings`)
6. **半变异函数设置** (`semivariogram_settings`)
7. **普通克里金设置** (`ordinary_kriging_settings`)
8. **可选过滤器** (`filters`) - 高级配置
## 详细参数说明
### 1. 输出设置
```yaml
output_dir: ./output # 输出目录路径
```
- **类型**: 字符串
- **描述**: 指定处理结果的输出目录
- **默认值**: `./output`
- **注意**: 可以使用相对路径或绝对路径
### 2. 必需列定义
```yaml
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
```
- **格式**: 字典,键为列名,值为 `[最小值, 最大值]` 数组
- **作用**: 数据验证和范围检查
- **注意**:
- 所有值必须是 float64 类型
- 不允许 NaN 值
- 超出范围的值会报错
### 3. 气体配置
```yaml
gases:
co2: [300, 500] # 二氧化碳浓度范围ppm
ch4: [1.5, 10.0] # 甲烷浓度范围ppm
```
- **格式**: 字典,键为气体名称,值为 `[最小值, 最大值]` 数组
- **作用**: 指定要处理的 gases 及其合理浓度范围
- **注意**:
- 气体名称必须与数据中的列名完全匹配
- 范围用于数据验证
### 4. 处理策略
```yaml
strategies:
background: "algorithm" # 背景校正方法
sensor: "insitu" # 传感器类型
spatial: "curtain" # 空间处理模式: "curtain" 或 "spiral"
interpolation: "kriging" # 插值方法
```
- **background**: 目前只支持 `"algorithm"`
- **sensor**: 目前只支持 `"insitu"`
- **spatial**: `"curtain"` (平面模式) 或 `"spiral"` (螺旋模式)
- **interpolation**: 目前只支持 `"kriging"`
## 背景校正算法设置
### 算法总览
```yaml
algorithmic_baseline_settings:
algorithm: fastchrom # 选择使用的算法
# 以下是各算法的具体参数
```
### 支持的算法
#### 1. FastChrom 算法 (推荐用于大多数情况)
```yaml
algorithmic_baseline_settings:
algorithm: fastchrom
fastchrom:
half_window: 6 # 半窗口大小,用于基线拟合
threshold: "custom" # 阈值方法,推荐使用 "custom"
min_fwhm: ~ # 最小峰宽,~ 表示 null
interp_half_window: 3 # 插值半窗口
smooth_half_window: 3 # 平滑半窗口
weights: ~ # 权重,~ 表示 null
max_iter: 100 # 最大迭代次数
min_length: 2 # 最小段长度
```
#### 2. Dietrich 算法
```yaml
algorithmic_baseline_settings:
algorithm: dietrich
dietrich:
poly_order: 5 # 多项式阶数
smooth_half_window: 5 # 平滑半窗口
```
#### 3. FABC (Fully Automatic Baseline Correction) 算法
```yaml
algorithmic_baseline_settings:
algorithm: fabc
fabc:
lam: 10000 # 平滑参数,值越大基线越平滑
scale: 10 # 小波变换尺度
diff_order: 2 # 微分矩阵阶数
```
#### 4. Golotvin 算法
```yaml
algorithmic_baseline_settings:
algorithm: golotvin
golotvin:
half_window: 2 # 半窗口大小
sections: 10 # 分段数量
```
## 克里金插值设置
### 半变异函数设置
```yaml
semivariogram_settings:
model: spherical # 变异函数模型: spherical, gaussian, exponential
estimator: cressie # 估计器: cressie, matheron, dowd
n_lags: 20 # 滞后期数
bin_func: even # 分箱函数: even, uniform
fit_method: lm # 拟合方法: lm, manual
maxlag: 100 # 最大滞后距离(米)
tolerance: 10 # 方向容差(度)
azimuth: 0 # 方位角0为水平向右
bandwidth: 20 # 带宽(米)
```
### 普通克里金设置
```yaml
ordinary_kriging_settings:
min_points: 3 # 最小邻点数
max_points: 100 # 最大邻点数
grid_resolution: 500 # 网格分辨率
min_nodes: 10 # 最小网格节点数
y_min: ~ # 最小y值覆盖手动覆盖~表示使用默认
cut_ground: True # 是否切割地面以下的值
```
## 空间处理模式详解
### 平面模式 (Curtain Mode)
**适用场景**: 直线飞行路径,沿着固定方向的多个平行航线
```yaml
strategies:
spatial: "curtain"
# 推荐的半变异函数设置(平面模式)
semivariogram_settings:
model: spherical
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
```
**特点**:
- 应用风偏移校正
- 沿着最大单调序列提取航线
- 适合规则的栅格飞行模式
### 螺旋模式 (Spiral Mode)
**适用场景**: 螺旋或圆形飞行路径
```yaml
strategies:
spatial: "spiral"
# 推荐的半变异函数设置(螺旋模式)
semivariogram_settings:
model: spherical
estimator: cressie
n_lags: 20
bin_func: even
fit_method: lm
maxlag: 100 # 较大的最大距离适应螺旋半径
tolerance: 30 # 更大的容差适应圆形路径
azimuth: 0 # 径向方向
bandwidth: 20 # 适应螺旋间距
ordinary_kriging_settings:
min_points: 3
max_points: 100
grid_resolution: 500 # 较低的分辨率适应圆形区域
min_nodes: 10
y_min: ~ # 自动确定最小高度
cut_ground: True
```
**特点**:
- 不应用风偏移校正(假设风垂直于螺旋)
- 计算圆偏差和中心
- 重新居中方位角
- 使用周长距离作为x坐标
## 可选过滤器(高级配置)
```yaml
filters:
course_filter:
azimuth_filter: 15 # 方位角过滤容差(度)
azimuth_window: 8 # 滚动中位数窗口大小
elevation_filter: 8 # 海拔过滤容差(度)
```
## 完整配置示例
### 平面模式完整配置
```yaml
output_dir: ./curtain_output
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [0, 200]
windspeed: [0, 20]
winddir: [0, 360]
temperature: [-50, 60]
pressure: [900, 1100]
gases:
co2: [300, 500]
ch4: [1.5, 10.0]
strategies:
background: "algorithm"
sensor: "insitu"
spatial: "curtain"
interpolation: "kriging"
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
semivariogram_settings:
model: spherical
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
```
### 螺旋模式完整配置
```yaml
output_dir: ./spiral_output
required_cols:
latitude: [-90, 90]
longitude: [-180, 180]
height_ato: [0, 200]
windspeed: [0, 20]
winddir: [0, 360]
temperature: [-50, 60]
pressure: [900, 1100]
gases:
co2: [300, 500]
ch4: [1.5, 10.0]
strategies:
background: "algorithm"
sensor: "insitu"
spatial: "spiral"
interpolation: "kriging"
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
semivariogram_settings:
model: spherical
estimator: cressie
n_lags: 20
bin_func: even
fit_method: lm
maxlag: 100
tolerance: 30
azimuth: 0
bandwidth: 20
ordinary_kriging_settings:
min_points: 3
max_points: 100
grid_resolution: 500
min_nodes: 10
y_min: ~
cut_ground: True
```
## 参数调优指南
### 空间模式选择
1. **平面模式 (curtain)**:
- 飞行路径呈直线或平行航线
- 数据点分布在规则的栅格中
- 适合大型区域的系统采样
2. **螺旋模式 (spiral)**:
- 飞行路径呈螺旋或圆形
- 数据点围绕中心点分布
- 适合点源排放的详细采样
### 半变异函数调优
1. **maxlag**: 设置为数据空间范围的 80-100%
2. **tolerance**: 平面模式 10-20°螺旋模式 20-40°
3. **bandwidth**: 根据飞行间距调整,过大会影响精度
4. **n_lags**: 通常 10-25根据数据量调整
### 克里金插值调优
1. **grid_resolution**: 影响输出网格密度
2. **min_points/max_points**: 平衡计算速度和精度
3. **cut_ground**: 根据是否有地面高程数据决定
## 故障排除
### 常见错误
1. **"autodetected range of [nan, nan] is not finite"**
- 检查气体列是否有NaN值
- 确认气体名称与数据列名匹配
2. **"`ydata` must not be empty!"**
- 检查半变异函数参数是否过于严格
- 减少 maxlag 或增加 tolerance
3. **Missing columns**
- 确认数据列名与配置中的 gases 键匹配
- 检查必需列是否存在
### 性能优化
1. **减少计算时间**: 降低 grid_resolution减少 max_points
2. **提高精度**: 增加 n_lags调整半变异函数参数
3. **内存优化**: 适当减少 max_points 和 grid_resolution
## 版本信息
- **GasFlux 版本**: 开发版
- **最后更新**: 2025年2月
- **文档版本**: 1.0
---
*本配置文档基于 GasFlux 系统的实际代码实现编写。如有疑问,请参考源码注释或提交 Issue。*

View File

@ -14,6 +14,7 @@ GasFlux 是一个专门用于处理无人机或飞行器采集的气体浓度数
- **灵活配置**: 基于 YAML 的配置系统,支持自定义参数 - **灵活配置**: 基于 YAML 的配置系统,支持自定义参数
- **可视化输出**: 自动生成数据分析图表和报告 - **可视化输出**: 自动生成数据分析图表和报告
- **命令行工具**: 提供直观的 CLI 接口 - **命令行工具**: 提供直观的 CLI 接口
- **Web API 服务**: 提供完整的 RESTful API支持异步处理、实时监控和详细统计
- **跨平台支持**: 支持 Windows、macOS 和 Linux - **跨平台支持**: 支持 Windows、macOS 和 Linux
## 📋 系统要求 ## 📋 系统要求
@ -77,6 +78,62 @@ gasflux process /path/to/data/directory
python src/gasflux/run_example.py your_data.xlsx python src/gasflux/run_example.py your_data.xlsx
``` ```
## 🌐 Web API 服务
GasFlux 提供完整的 Web API 服务,支持通过 HTTP 接口进行数据处理。详见以下文档:
- [API 文档](API_DOCUMENTATION.md) - 完整的 API 接口说明
- [环境变量配置](ENVIRONMENT_VARIABLES.md) - 环境变量配置指南
- [Waitress 部署](WAITRESS_DEPLOYMENT.md) - 生产环境部署指南
### 启动 Web 服务
```bash
# 启动 API 服务(使用默认配置)
python run_api.py
# 或使用自定义环境变量
export GASFLUX_PORT=8080
export GASFLUX_LOG_LEVEL=DEBUG
python run_api.py
# 服务将在配置的地址和端口启动
# 访问 http://localhost:5000 查看 Web 界面
```
### 环境变量配置
GasFlux 支持通过环境变量进行灵活配置。详见 [ENVIRONMENT_VARIABLES.md](ENVIRONMENT_VARIABLES.md) 获取完整配置指南。
**常用配置示例**
```bash
# 端口配置
export GASFLUX_PORT=8080
# 日志配置
export GASFLUX_LOG_LEVEL=DEBUG
export GASFLUX_LOG_FILE=/var/log/gasflux/api.log
# 性能配置
export GASFLUX_THREADS=16
export GASFLUX_MAX_CONTENT_LENGTH=524288000 # 500MB
# 目录配置
export GASFLUX_UPLOAD_FOLDER=/data/uploads
export GASFLUX_OUTPUT_FOLDER=/data/outputs
```
### API 特性
- **异步处理**: 支持大文件处理,不阻塞客户端
- **实时监控**: 通过任务 ID 实时查询处理状态
- **文件管理**: 自动文件上传、处理和下载
- **健康检查**: 系统状态监控和诊断
- **详细日志**: 完整的请求日志和性能监控
- **统计监控**: 实时 API 统计、性能指标和系统资源监控
- **环境变量配置**: 通过环境变量灵活配置,无需修改代码
## 📖 使用指南 ## 📖 使用指南
### 配置文件 ### 配置文件

271
WAITRESS_DEPLOYMENT.md Normal file
View File

@ -0,0 +1,271 @@
# GasFlux Web API - Waitress WSGI 部署指南
本文档介绍如何使用 Waitress WSGI 服务器打包和部署 GasFlux Web API 为独立可执行文件。
## 概述
Waitress 是一个纯 Python WSGI 服务器,适合生产环境使用。本部署方案将 Flask 应用与 Waitress 打包为单个可执行文件,无需额外安装 Python 环境。
## 文件说明
### 核心文件
- **`server_waitress.py`** - Waitress 服务器入口点
- **`src/gasflux/app.py`** - Flask 应用定义
- **`build_exe.bat`** - Windows 构建脚本
- **`build_exe.sh`** - Linux/macOS 构建脚本
- **`EXE_BUILD_README.md`** - 详细构建和部署指南
### 构建产物
- **`dist/GasFluxAPI.exe`** (Windows) 或 **`dist/GasFluxAPI`** (Linux/macOS) - 独立可执行文件
## 快速开始
### 1. 安装依赖
```bash
pip install -r requirements.txt
pip install pyinstaller waitress
```
### 2. 构建可执行文件
**Windows:**
```cmd
build_exe.bat
```
**Linux/macOS:**
```bash
chmod +x build_exe.sh
./build_exe.sh
```
### 3. 运行服务器
```bash
# Windows
dist\GasFluxAPI.exe
# Linux/macOS
./dist/GasFluxAPI
```
服务器将在 `http://localhost:5000` 启动。
## 服务器配置
### 默认配置
```python
host = '0.0.0.0' # 监听所有接口
port = 5000 # 默认端口
threads = 8 # 工作线程数
connection_limit = 100 # 最大并发连接
timeout = 300 # 请求超时(秒)
```
### 自定义配置
修改 `server_waitress.py` 中的参数:
```python
# 自定义端口
port = 8080
# 增加线程数
threads = 16
# 调整超时时间
timeout = 600 # 10分钟
```
## 部署架构
### 单文件部署
```
部署目录/
├── GasFluxAPI(.exe) # 可执行文件
├── web_api_data/ # 数据目录(自动创建)
│ ├── uploads/ # 上传文件
│ └── outputs/ # 处理结果
├── logs/ # 日志文件(自动创建)
└── gasflux_config.yaml # 配置文件(可选)
```
### 生产部署建议
#### 使用反向代理
```nginx
# nginx 配置示例
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
#### 使用进程管理器
**systemd (Linux):**
```ini
[Unit]
Description=GasFlux Web API
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/path/to/deployment
ExecStart=/path/to/deployment/GasFluxAPI
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
**Windows 服务:**
使用 NSSM (Non-Sucking Service Manager) 将 exe 注册为 Windows 服务。
## 性能优化
### Waitress 参数调优
```python
serve(
app,
host='0.0.0.0',
port=5000,
threads=16, # 根据 CPU 核心数调整
connection_limit=200, # 最大并发连接
timeout=300, # 长请求超时
backlog=2048, # 连接队列长度
recv_bytes=8192, # 接收缓冲区
send_bytes=8192, # 发送缓冲区
)
```
### 监控和日志
- **访问日志**: `logs/gasflux_api.log`
- **控制台输出**: 启动时显示的控制台信息
- **健康检查**: `GET /health` 端点
### 资源使用
- **内存**: 每个工作进程约 50-200MB取决于数据处理量
- **CPU**: 多线程处理,建议 4+ 核心
- **磁盘**: 日志和临时文件存储
## 安全考虑
### 基本安全措施
1. **防火墙配置**: 只开放必要端口
2. **用户权限**: 以非 root 用户运行
3. **文件权限**: 数据目录限制访问权限
### 生产环境建议
1. **HTTPS**: 使用反向代理配置 SSL
2. **认证**: 添加 API 密钥或 JWT 认证
3. **限流**: 实现请求频率限制
4. **监控**: 设置日志监控和告警
## 故障排除
### 常见问题
1. **端口占用**
```bash
# 检查端口使用
netstat -tulpn | grep :5000
# 或 Windows: netstat -ano | findstr :5000
```
2. **权限问题**
```bash
# 确保可执行文件有执行权限
chmod +x GasFluxAPI
# 确保数据目录可写
chmod -R 755 web_api_data/
```
3. **构建失败**
```bash
# 清理旧构建
rm -rf build/ dist/
# 重新安装依赖
pip install --upgrade pyinstaller waitress
```
4. **内存不足**
- 减少线程数
- 增加服务器内存
- 优化数据处理流程
### 调试模式
临时启用详细日志:
```bash
# 修改 server_waitress.py
import logging
logging.basicConfig(level=logging.DEBUG)
```
## 维护和更新
### 更新部署
1. 构建新版本可执行文件
2. 备份数据目录
3. 停止旧服务
4. 替换可执行文件
5. 启动新服务
### 备份策略
- **数据**: `web_api_data/` 目录
- **配置**: `gasflux_config.yaml`
- **日志**: `logs/` 目录
## API 使用
部署完成后API 端点与开发环境相同:
- **健康检查**: `GET /health`
- **文件上传**: `POST /upload`
- **任务状态**: `GET /task/{task_id}`
- **文件下载**: `GET /download/{filename}`
- **Web 界面**: `GET /`
详细 API 文档请参考 `API_DOCUMENTATION.md`。
## 总结
使用 Waitress 打包的方案提供了:
-**零依赖部署**: 单文件可执行
-**生产就绪**: WSGI 服务器,适合高并发
-**跨平台**: 支持 Windows/Linux/macOS
-**易于维护**: 简单的部署和更新流程
-**完整功能**: 保留所有 Flask 应用功能
这种部署方式特别适合:
- Windows 服务器环境
- 简单的生产部署需求
- 需要独立可执行文件的场景

62
build_exe.bat Normal file
View File

@ -0,0 +1,62 @@
@echo off
REM GasFlux Web API - Build executable with PyInstaller
REM This script builds a standalone executable using Waitress WSGI server
echo Building GasFlux Web API executable...
REM Check if PyInstaller is installed
python -c "import PyInstaller" >nul 2>&1
if errorlevel 1 (
echo Error: PyInstaller is not installed. Please run:
echo pip install pyinstaller waitress
pause
exit /b 1
)
REM Check if Waitress is installed
python -c "import waitress" >nul 2>&1
if errorlevel 1 (
echo Error: Waitress is not installed. Please run:
echo pip install waitress
pause
exit /b 1
)
REM Create dist directory if it doesn't exist
if not exist "dist" mkdir dist
echo Creating executable with PyInstaller...
REM Build the executable
pyinstaller --onefile ^
--name GasFluxAPI ^
--hidden-import waitress ^
--hidden-import flask ^
--hidden-import werkzeug ^
--hidden-import yaml ^
--hidden-import pandas ^
--hidden-import numpy ^
--hidden-import flask_cors ^
--hidden-import psutil ^
--add-data "src\gasflux\gasflux_config.yaml;src\gasflux" ^
--add-data "API_DOCUMENTATION.md;." ^
--exclude-module matplotlib ^
--exclude-module tkinter ^
server_waitress.py
if errorlevel 1 (
echo Error: Failed to build executable
pause
exit /b 1
)
echo.
echo Build completed successfully!
echo Executable created: dist\GasFluxAPI.exe
echo.
echo To run the server:
echo GasFluxAPI.exe
echo.
echo The server will start on http://localhost:5000
echo.
pause

55
build_exe.sh Normal file
View File

@ -0,0 +1,55 @@
#!/bin/bash
# GasFlux Web API - Build executable with PyInstaller
# This script builds a standalone executable using Waitress WSGI server
echo "Building GasFlux Web API executable..."
# Check if PyInstaller is installed
if ! python3 -c "import PyInstaller" 2>/dev/null; then
echo "Error: PyInstaller is not installed. Please run:"
echo "pip install pyinstaller waitress"
exit 1
fi
# Check if Waitress is installed
if ! python3 -c "import waitress" 2>/dev/null; then
echo "Error: Waitress is not installed. Please run:"
echo "pip install waitress"
exit 1
fi
# Create dist directory if it doesn't exist
mkdir -p dist
echo "Creating executable with PyInstaller..."
# Build the executable
pyinstaller --onefile \
--name GasFluxAPI \
--hidden-import waitress \
--hidden-import flask \
--hidden-import werkzeug \
--hidden-import yaml \
--hidden-import pandas \
--hidden-import numpy \
--hidden-import flask_cors \
--hidden-import psutil \
--add-data "src/gasflux/gasflux_config.yaml:src/gasflux" \
--add-data "API_DOCUMENTATION.md:." \
--exclude-module matplotlib \
--exclude-module tkinter \
server_waitress.py
if [ $? -ne 0 ]; then
echo "Error: Failed to build executable"
exit 1
fi
echo ""
echo "Build completed successfully!"
echo "Executable created: dist/GasFluxAPI"
echo ""
echo "To run the server:"
echo "./dist/GasFluxAPI"
echo ""
echo "The server will start on http://localhost:5000"

View File

@ -1,48 +0,0 @@
@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

View File

@ -1,48 +0,0 @@
#!/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

30
env.example Normal file
View File

@ -0,0 +1,30 @@
# GasFlux Web API - Environment Variables Example
# Copy this file to your environment and modify as needed
# Server Configuration
GASFLUX_HOST=0.0.0.0
GASFLUX_PORT=5000
GASFLUX_DEBUG=false
# Directory Configuration
GASFLUX_UPLOAD_FOLDER=web_api_data/uploads
GASFLUX_OUTPUT_FOLDER=web_api_data/outputs
# File Size Limits (in bytes)
GASFLUX_MAX_CONTENT_LENGTH=104857600 # 100MB
# Logging Configuration
GASFLUX_LOG_LEVEL=INFO
GASFLUX_LOG_FILE=logs/gasflux_api.log
# CORS Configuration
GASFLUX_CORS_ORIGINS=*
# Task Management
GASFLUX_TASK_CLEANUP_INTERVAL=3600 # 1 hour
GASFLUX_MAX_TASK_AGE=86400 # 24 hours
# Performance Tuning
GASFLUX_THREADS=8
GASFLUX_CONNECTION_LIMIT=100
GASFLUX_CHANNEL_TIMEOUT=300

View File

@ -1,52 +0,0 @@
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

View File

@ -1,69 +0,0 @@
# 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

@ -1,61 +0,0 @@
# 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

@ -1,820 +0,0 @@
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

@ -1,95 +0,0 @@
# 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"

View File

@ -7,7 +7,6 @@ Jinja2==3.1.6
joblib==1.3.2 joblib==1.3.2
matplotlib==3.10.0 matplotlib==3.10.0
molmass==2023.8.30 molmass==2023.8.30
noise==1.2.2
numpy==2.1.3 numpy==2.1.3
pandas==2.2.3 pandas==2.2.3
plotly==5.20.0 plotly==5.20.0
@ -18,3 +17,8 @@ scikit-gstat==1.0.19
scikit-image==0.24.0 scikit-image==0.24.0
scipy==1.15.1 scipy==1.15.1
simplekml==1.3.6 simplekml==1.3.6
flask
werkzeug
flask-cors
waitress
psutil

30
run_api.py Normal file
View File

@ -0,0 +1,30 @@
import os
import sys
from pathlib import Path
# Add the project root and src directory to PYTHONPATH
project_root = Path(__file__).parent.absolute()
src_dir = project_root / "src"
sys.path.append(str(project_root))
sys.path.append(str(src_dir))
# Set environment variables for Flask
os.environ['FLASK_APP'] = 'src/gasflux/app.py'
os.environ['FLASK_ENV'] = 'development'
if __name__ == "__main__":
print("Starting GasFlux Web API...")
# Import and run the app
try:
import gasflux.app as gasflux_app
app = gasflux_app.app
print("GasFlux app imported successfully")
print("Starting Flask development server on http://0.0.0.0:5000")
app.run(host='0.0.0.0', port=5000, debug=True)
except Exception as e:
print(f"Error starting GasFlux app: {e}")
import traceback
traceback.print_exc()
sys.exit(1)

117
server_waitress.py Normal file
View File

@ -0,0 +1,117 @@
#!/usr/bin/env python3
"""
GasFlux Web API Server using Waitress WSGI server.
This is the production server entry point for the GasFlux Web API.
Includes full GasFlux processing capabilities with task pool management.
Features:
- File upload and processing (.xlsx, .xls)
- Asynchronous task processing with background workers
- Task pool management with pagination and filtering
- Real-time task status monitoring
- Report generation and file download
- Health monitoring and statistics
API Endpoints:
- /upload - File upload and processing initiation
- /task/<task_id> - Task status management
- /tasks - Task pool management (NEW)
- /download/<filename> - File download
- /reports - Report listing
- /health - Health monitoring
- /stats - System statistics
- /config - Configuration info
- / - Web interface
Usage:
python server_waitress.py
Or package with PyInstaller:
pyinstaller --onefile --name GasFluxAPI server_waitress.py
"""
import os
import sys
from pathlib import Path
# Add the project root and src directory to PYTHONPATH
project_root = Path(__file__).parent.absolute()
src_dir = project_root / "src"
sys.path.insert(0, str(project_root))
sys.path.insert(0, str(src_dir))
# Set environment variables for production
os.environ['FLASK_APP'] = 'src/gasflux/app.py'
os.environ['FLASK_ENV'] = 'production'
def main():
"""Main entry point for the GasFlux Web API server."""
print("Starting GasFlux Web API with Waitress...")
try:
# Import the Flask app
import gasflux.app as gasflux_app
from src.gasflux.app import Config
app = gasflux_app.app
print("✓ GasFlux app imported successfully")
print("✓ Task pool management enabled")
print("✓ All blueprints loaded: upload, tasks, task_pool, download, reports, health, stats, config, web")
# Import waitress
from waitress import serve
print("✓ Waitress WSGI server imported")
# Server configuration from environment variables
host = Config.HOST
port = Config.PORT
threads = Config.THREADS
connection_limit = Config.CONNECTION_LIMIT
channel_timeout = Config.CHANNEL_TIMEOUT
print(f"Starting Waitress server on {host}:{port}")
print(f"- Threads: {threads}")
print(f"- Connection limit: {connection_limit}")
print(f"- Channel timeout: {channel_timeout}s")
print("Press Ctrl+C to stop the server")
print("=" * 50)
print("Available API endpoints:")
print(" POST /upload - Upload files for processing")
print(" GET /task/<id> - Get task status")
print(" PUT /task/<id> - Update task status")
print(" DEL /task/<id> - Delete task")
print(" GET /tasks - List tasks (paginated)")
print(" GET /tasks/stats - Task pool statistics")
print(" GET /tasks/active - Active tasks")
print(" GET /tasks/queue - Queued tasks")
print(" GET /download/<file> - Download files")
print(" GET /reports - List reports")
print(" GET /health - Health check")
print(" GET /stats - System stats")
print(" GET /config - Configuration")
print(" GET / - Web interface")
print("=" * 50)
print(f"Configuration: {Config.to_dict()}")
# Start the server with valid Waitress parameters
serve(
app,
host=host,
port=port,
threads=threads,
connection_limit=connection_limit,
channel_timeout=channel_timeout,
)
except KeyboardInterrupt:
print("\nServer stopped by user")
except Exception as e:
print(f"✗ Error starting GasFlux app: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()

728
src/gasflux/app.py Normal file
View File

@ -0,0 +1,728 @@
import os
import shutil
import sys
import uuid
import logging
import threading
import time
from functools import wraps
from pathlib import Path
from flask import Flask, request, jsonify, send_file, render_template_string, url_for, g
from flask_cors import CORS
from werkzeug.utils import secure_filename
import yaml
# Shared utilities imported from shared.py
try:
# Try relative import (when run as part of package)
from .shared import task_status, TASK_STATUS_PENDING, TASK_STATUS_PROCESSING, TASK_STATUS_COMPLETED, TASK_STATUS_FAILED
except ImportError:
# Fallback to absolute import (when run directly)
from shared import task_status, TASK_STATUS_PENDING, TASK_STATUS_PROCESSING, TASK_STATUS_COMPLETED, TASK_STATUS_FAILED
# Blueprints will be imported after app initialization to avoid circular imports
# Environment-based configuration management
class Config:
"""Configuration management using environment variables with defaults."""
# Server configuration
HOST = os.getenv('GASFLUX_HOST', '0.0.0.0')
PORT = int(os.getenv('GASFLUX_PORT', '5000'))
DEBUG = os.getenv('GASFLUX_DEBUG', 'false').lower() in ('true', '1', 'yes', 'on')
# Directory configuration
BASE_DIR = None # Will be set dynamically
UPLOAD_FOLDER_NAME = os.getenv('GASFLUX_UPLOAD_FOLDER', 'web_api_data/uploads')
OUTPUT_FOLDER_NAME = os.getenv('GASFLUX_OUTPUT_FOLDER', 'web_api_data/outputs')
# File size limits (in bytes)
MAX_CONTENT_LENGTH = int(os.getenv('GASFLUX_MAX_CONTENT_LENGTH', str(100 * 1024 * 1024))) # 100MB
# Logging configuration
LOG_LEVEL = os.getenv('GASFLUX_LOG_LEVEL', 'INFO').upper()
LOG_FILE = os.getenv('GASFLUX_LOG_FILE', 'logs/gasflux_api.log')
# CORS configuration
CORS_ORIGINS = os.getenv('GASFLUX_CORS_ORIGINS', '*').split(',')
# Task management
TASK_CLEANUP_INTERVAL = int(os.getenv('GASFLUX_TASK_CLEANUP_INTERVAL', '3600')) # 1 hour in seconds
MAX_TASK_AGE = int(os.getenv('GASFLUX_MAX_TASK_AGE', str(24 * 3600))) # 24 hours in seconds
# Performance tuning
THREADS = int(os.getenv('GASFLUX_THREADS', '8')) # Waitress threads
CONNECTION_LIMIT = int(os.getenv('GASFLUX_CONNECTION_LIMIT', '100'))
CHANNEL_TIMEOUT = int(os.getenv('GASFLUX_CHANNEL_TIMEOUT', '300')) # 5 minutes
@classmethod
def init_base_dir(cls):
"""Initialize base directory based on environment."""
try:
if getattr(sys, 'frozen', False):
# Running in PyInstaller bundle
cls.BASE_DIR = Path(sys.executable).parent
else:
# Running in normal Python environment
cls.BASE_DIR = Path(__file__).resolve().parent.parent.parent
except:
# Fallback to current working directory
cls.BASE_DIR = Path.cwd()
# Initialize directories based on config
cls.init_directories()
@classmethod
def init_directories(cls, output_dir=None):
"""Initialize upload and output directories."""
if output_dir:
# Use config-based output directory
output_base = Path(output_dir)
if not output_base.is_absolute():
output_base = cls.BASE_DIR / output_base
else:
# Use default relative paths
output_base = cls.BASE_DIR
# Set upload and output directories relative to output_base
cls.UPLOAD_FOLDER = output_base / "uploads"
cls.OUTPUT_FOLDER = output_base / "outputs"
# Create directories
cls.UPLOAD_FOLDER.mkdir(parents=True, exist_ok=True)
cls.OUTPUT_FOLDER.mkdir(parents=True, exist_ok=True)
logger.info(f"Directories initialized - Upload: {cls.UPLOAD_FOLDER}, Output: {cls.OUTPUT_FOLDER}")
@classmethod
def update_directories_from_config(cls, config_path=None):
"""Update directories based on config file."""
if config_path and Path(config_path).exists():
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
output_dir = config.get('output_dir')
if output_dir:
cls.init_directories(output_dir)
logger.info(f"Directories updated from config: {config_path}")
except Exception as e:
logger.warning(f"Failed to update directories from config {config_path}: {e}")
else:
logger.info("Using default directory configuration")
@classmethod
def get_log_level(cls):
"""Get logging level from string."""
levels = {
'DEBUG': logging.DEBUG,
'INFO': logging.INFO,
'WARNING': logging.WARNING,
'ERROR': logging.ERROR,
'CRITICAL': logging.CRITICAL
}
return levels.get(cls.LOG_LEVEL, logging.INFO)
@classmethod
def to_dict(cls):
"""Return configuration as dictionary for debugging."""
return {
'host': cls.HOST,
'port': cls.PORT,
'debug': cls.DEBUG,
'base_dir': str(cls.BASE_DIR) if cls.BASE_DIR else None,
'upload_folder': str(cls.UPLOAD_FOLDER) if hasattr(cls, 'UPLOAD_FOLDER') else None,
'output_folder': str(cls.OUTPUT_FOLDER) if hasattr(cls, 'OUTPUT_FOLDER') else None,
'max_content_length': cls.MAX_CONTENT_LENGTH,
'log_level': cls.LOG_LEVEL,
'log_file': cls.LOG_FILE,
'cors_origins': cls.CORS_ORIGINS,
'task_cleanup_interval': cls.TASK_CLEANUP_INTERVAL,
'max_task_age': cls.MAX_TASK_AGE,
'threads': cls.THREADS,
'connection_limit': cls.CONNECTION_LIMIT,
'channel_timeout': cls.CHANNEL_TIMEOUT
}
# Initialize logging with environment-based configuration
logging.basicConfig(
level=Config.get_log_level(),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(), # Console output
]
)
logger = logging.getLogger("gasflux_api")
logger.info("Basic logging initialized")
def log_performance(func):
"""Decorator to log function performance."""
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
func_name = func.__name__
logger.debug(f"PERF: Starting {func_name}")
try:
result = func(*args, **kwargs)
duration = time.time() - start_time
logger.info(f"PERF: {func_name} completed in {duration:.3f}s")
return result
except Exception as e:
duration = time.time() - start_time
logger.error(f"PERF: {func_name} failed after {duration:.3f}s - Error: {str(e)}")
raise
return wrapper
# Task status management
# Task status constants and storage moved to shared.py
def update_task_status(task_id, status, message=None, results=None, error=None):
"""Update task status in the global dictionary."""
timestamp = time.time()
old_status = task_status.get(task_id, {}).get("status", "unknown")
task_status[task_id] = {
"status": status,
"message": message,
"results": results,
"error": error,
"updated_at": timestamp
}
# Log detailed status change with context
log_msg = f"Task {task_id} status changed: {old_status} -> {status}"
if message:
log_msg += f" | Message: {message}"
if results:
log_msg += f" | Results count: {len(results) if isinstance(results, list) else 'N/A'}"
if error:
log_msg += f" | Error: {error}"
log_level = logging.ERROR if status == TASK_STATUS_FAILED else logging.INFO
logger.log(log_level, log_msg)
# Update task statistics
stats_collector.record_task_status_change(old_status, status)
# Statistics and Monitoring
class APIStatsCollector:
"""Collect and manage API statistics."""
def __init__(self):
self.start_time = time.time()
self.reset_stats()
def reset_stats(self):
"""Reset all statistics."""
self.stats = {
'requests': {
'total': 0,
'by_method': {},
'by_endpoint': {},
'by_status': {},
'response_times': [],
'errors': 0
},
'tasks': {
'total_created': 0,
'total_completed': 0,
'total_failed': 0,
'by_status': {
'pending': 0,
'processing': 0,
'completed': 0,
'failed': 0
},
'processing_times': []
},
'performance': {
'avg_response_time': 0,
'max_response_time': 0,
'min_response_time': float('inf'),
'uptime_seconds': time.time() - self.start_time
}
}
def record_request(self, method, endpoint, status_code, response_time):
"""Record an API request."""
self.stats['requests']['total'] += 1
# Method stats
if method not in self.stats['requests']['by_method']:
self.stats['requests']['by_method'][method] = 0
self.stats['requests']['by_method'][method] += 1
# Endpoint stats
if endpoint not in self.stats['requests']['by_endpoint']:
self.stats['requests']['by_endpoint'][endpoint] = 0
self.stats['requests']['by_endpoint'][endpoint] += 1
# Status stats
status_category = str(status_code // 100 * 100) # 200, 400, 500, etc.
if status_category not in self.stats['requests']['by_status']:
self.stats['requests']['by_status'][status_category] = 0
self.stats['requests']['by_status'][status_category] += 1
# Response time stats
self.stats['requests']['response_times'].append(response_time)
# Keep only last 1000 response times for memory efficiency
if len(self.stats['requests']['response_times']) > 1000:
self.stats['requests']['response_times'] = self.stats['requests']['response_times'][-1000:]
# Error tracking
if status_code >= 400:
self.stats['requests']['errors'] += 1
# Update performance stats
self._update_performance_stats()
def record_task_status_change(self, old_status, new_status):
"""Record task status changes."""
if old_status == "unknown": # New task
self.stats['tasks']['total_created'] += 1
if new_status == TASK_STATUS_COMPLETED:
self.stats['tasks']['total_completed'] += 1
elif new_status == TASK_STATUS_FAILED:
self.stats['tasks']['total_failed'] += 1
# Update status counts
for status in [old_status, new_status]:
if status in self.stats['tasks']['by_status']:
if status == old_status and old_status != "unknown":
self.stats['tasks']['by_status'][old_status] -= 1
elif status == new_status:
self.stats['tasks']['by_status'][new_status] += 1
def record_task_completion_time(self, completion_time):
"""Record task completion time."""
self.stats['tasks']['processing_times'].append(completion_time)
# Keep only last 100 processing times
if len(self.stats['tasks']['processing_times']) > 100:
self.stats['tasks']['processing_times'] = self.stats['tasks']['processing_times'][-100:]
def _update_performance_stats(self):
"""Update performance statistics."""
response_times = self.stats['requests']['response_times']
if response_times:
self.stats['performance']['avg_response_time'] = sum(response_times) / len(response_times)
self.stats['performance']['max_response_time'] = max(response_times)
self.stats['performance']['min_response_time'] = min(response_times)
self.stats['performance']['uptime_seconds'] = time.time() - self.start_time
def get_summary(self):
"""Get a summary of current statistics."""
current_time = time.time()
uptime = current_time - self.start_time
# Calculate rates
requests_per_second = self.stats['requests']['total'] / max(uptime, 1)
error_rate = (self.stats['requests']['errors'] / max(self.stats['requests']['total'], 1)) * 100
# Task completion rate
total_tasks_processed = self.stats['tasks']['total_completed'] + self.stats['tasks']['total_failed']
task_success_rate = (self.stats['tasks']['total_completed'] / max(total_tasks_processed, 1)) * 100
return {
'summary': {
'uptime_seconds': uptime,
'uptime_formatted': self._format_uptime(uptime),
'requests_total': self.stats['requests']['total'],
'requests_per_second': round(requests_per_second, 2),
'error_rate_percent': round(error_rate, 2),
'active_tasks': len([t for t in task_status.values()
if t.get('status') in [TASK_STATUS_PENDING, TASK_STATUS_PROCESSING]])
},
'requests': {
'by_method': self.stats['requests']['by_method'],
'by_status': self.stats['requests']['by_status'],
'top_endpoints': dict(sorted(self.stats['requests']['by_endpoint'].items(),
key=lambda x: x[1], reverse=True)[:10])
},
'tasks': {
'total_created': self.stats['tasks']['total_created'],
'total_completed': self.stats['tasks']['total_completed'],
'total_failed': self.stats['tasks']['total_failed'],
'success_rate_percent': round(task_success_rate, 2),
'by_status': self.stats['tasks']['by_status']
},
'performance': {
'avg_response_time_ms': round(self.stats['performance']['avg_response_time'] * 1000, 2),
'max_response_time_ms': round(self.stats['performance']['max_response_time'] * 1000, 2),
'min_response_time_ms': round(self.stats['performance']['min_response_time'] * 1000, 2) if self.stats['performance']['min_response_time'] != float('inf') else 0
}
}
def _format_uptime(self, seconds):
"""Format uptime in human readable format."""
days, remainder = divmod(int(seconds), 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
parts = []
if days > 0:
parts.append(f"{days}d")
if hours > 0:
parts.append(f"{hours}h")
if minutes > 0:
parts.append(f"{minutes}m")
parts.append(f"{seconds}s")
return " ".join(parts)
# Global statistics collector
stats_collector = APIStatsCollector()
# get_task_status moved to shared.py
# cleanup_old_tasks moved to shared.py
def process_data_async(task_id, data_path, config_path, job_output_dir):
"""Background task to process data asynchronously."""
logger.info(f"Job {task_id}: Background processing started for task {task_id}")
start_time = time.time()
try:
update_task_status(task_id, TASK_STATUS_PROCESSING, "Starting data processing...")
# 1. Load and override config FIRST
logger.info(f"Job {task_id}: Loading configuration from {config_path}")
config_start = time.time()
try:
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
logger.info(f"Job {task_id}: Configuration loaded successfully with {len(config)} keys")
except Exception as e:
logger.error(f"Job {task_id}: Failed to load config from {config_path}: {str(e)}")
raise
# Update directories based on config output_dir
Config.update_directories_from_config(config_path)
# Sync app.config with updated directories
app.config['UPLOAD_FOLDER'] = Config.UPLOAD_FOLDER
app.config['OUTPUT_FOLDER'] = Config.OUTPUT_FOLDER
# Update task status file path to new output directory
from .shared import set_task_status_file_path, load_task_status_from_file
set_task_status_file_path(Config.OUTPUT_FOLDER / "task_status.json")
# 立即从新路径加载现有状态,避免后续保存清空文件
load_task_status_from_file()
# Update job directories to be under the correct config-based paths
from pathlib import Path
job_upload_dir = Path(Config.UPLOAD_FOLDER) / task_id
job_output_dir = Path(Config.OUTPUT_FOLDER) / task_id
job_upload_dir.mkdir(parents=True, exist_ok=True)
job_output_dir.mkdir(parents=True, exist_ok=True)
# Move uploaded files to the correct config-based directories
try:
import shutil
# Move data file to correct uploads directory
if data_path.parent != job_upload_dir:
new_data_path = job_upload_dir / data_path.name
if data_path != new_data_path:
shutil.move(str(data_path), str(new_data_path))
data_path = new_data_path
logger.info(f"Job {task_id}: Moved data file to {data_path}")
# Move config file to correct uploads directory (if it's a custom config)
if config_path.parent != job_upload_dir and config_path.parent != Config.BASE_DIR:
new_config_path = job_upload_dir / config_path.name
if config_path != new_config_path:
shutil.move(str(config_path), str(new_config_path))
config_path = new_config_path
logger.info(f"Job {task_id}: Moved config file to {config_path}")
except Exception as e:
logger.warning(f"Job {task_id}: Failed to move uploaded files to configured directories: {str(e)}")
logger.debug(f"Job {task_id}: Keeping original output directory: {config.get('output_dir', 'not set')}")
logger.debug(f"Job {task_id}: Updated directories - Upload: {Config.UPLOAD_FOLDER}, Output: {Config.OUTPUT_FOLDER}, Job output: {job_output_dir}")
config_duration = time.time() - config_start
logger.info(f"Job {task_id}: Configuration processing completed in {config_duration:.3f}s")
update_task_status(task_id, TASK_STATUS_PROCESSING, "Configuration loaded, starting preprocessing...")
# 2. Data Preprocessing (files are already in correct directories)
logger.info(f"Job {task_id}: Starting preprocessing phase...")
preprocess_start = time.time()
processed_csv = data_path.parent / f"{data_path.stem}.processed.csv"
logger.debug(f"Job {task_id}: Input file: {data_path}, Output file: {processed_csv}")
process_file(str(data_path), str(processed_csv), str(config_path))
preprocess_duration = time.time() - preprocess_start
logger.info(f"Job {task_id}: Preprocessing completed in {preprocess_duration:.3f}s")
update_task_status(task_id, TASK_STATUS_PROCESSING, "Preprocessing completed, starting GasFlux analysis...")
# Write modified config to a temp file
final_config_path = data_path.parent / "final_config.yaml"
try:
with open(final_config_path, 'w') as f:
yaml.safe_dump(config, f)
logger.info(f"Job {task_id}: Final config written to {final_config_path}")
except Exception as e:
logger.error(f"Job {task_id}: Failed to write final config: {str(e)}")
raise
config_duration = time.time() - config_start
logger.info(f"Job {task_id}: Configuration processing completed in {config_duration:.3f}s")
update_task_status(task_id, TASK_STATUS_PROCESSING, "Configuration loaded, starting GasFlux analysis...")
# 3. GasFlux Processing
logger.info(f"Job {task_id}: Starting GasFlux analysis...")
analysis_start = time.time()
process_main(processed_csv, final_config_path, task_id)
analysis_duration = time.time() - analysis_start
logger.info(f"Job {task_id}: GasFlux analysis completed in {analysis_duration:.3f}s")
update_task_status(task_id, TASK_STATUS_PROCESSING, "GasFlux analysis completed, generating reports...")
# Collect results and generate full URLs
logger.info(f"Job {task_id}: Collecting generated files from {job_output_dir}")
results_start = time.time()
results = []
try:
for f in job_output_dir.rglob("*"):
if f.is_file():
rel_path = f.relative_to(app.config['OUTPUT_FOLDER']).as_posix()
file_size = f.stat().st_size
results.append({
"name": f.name,
"rel_path": rel_path,
"download_url": f"/download/{rel_path}", # Relative URL that client can use
"size": file_size
})
logger.debug(f"Job {task_id}: Found output file: {f.name} ({file_size} bytes)")
results_duration = time.time() - results_start
logger.info(f"Job {task_id}: Results collection completed in {results_duration:.3f}s - {len(results)} files generated")
total_size = sum(r.get('size', 0) for r in results)
logger.info(f"Job {task_id}: Total output size: {total_size} bytes across {len(results)} files")
except Exception as e:
logger.error(f"Job {task_id}: Failed to collect results: {str(e)}")
raise
total_duration = time.time() - start_time
logger.info(f"Job {task_id}: Processing complete. Total duration: {total_duration:.3f}s, {len(results)} files generated.")
# Record task completion time for statistics
stats_collector.record_task_completion_time(total_duration)
update_task_status(task_id, TASK_STATUS_COMPLETED, "Processing completed successfully", results=results)
except Exception as e:
total_duration = time.time() - start_time
logger.error(f"Job {task_id}: Processing failed after {total_duration:.3f}s - Error: {str(e)}", exc_info=True)
# Record failed task processing time for statistics
stats_collector.record_task_completion_time(total_duration)
logger.error(f"Job {task_id}: Failed task details - Data: {data_path}, Config: {config_path}, Output: {job_output_dir}")
# Try to capture any partial results
partial_results = []
try:
for f in job_output_dir.rglob("*"):
if f.is_file():
rel_path = f.relative_to(app.config['OUTPUT_FOLDER']).as_posix()
partial_results.append({
"name": f.name,
"rel_path": rel_path,
"download_url": f"/download/{rel_path}", # Relative URL that client can use
"size": f.stat().st_size,
"note": "partial_result"
})
except Exception as collect_error:
logger.warning(f"Job {task_id}: Failed to collect partial results: {str(collect_error)}")
error_msg = f"Processing failed: {str(e)}"
if partial_results:
error_msg += f" (partial results available: {len(partial_results)} files)"
update_task_status(task_id, TASK_STATUS_FAILED, error=error_msg, results=partial_results if partial_results else None)
# Import GasFlux modules
logger.info("Importing GasFlux modules...")
import_start = time.time()
try:
# Try absolute imports first (more reliable)
from src.gasflux.processing_pipelines import process_main
from src.gasflux.data_processor import process_file
from src.gasflux.reporting import generate_reports
import_duration = time.time() - import_start
logger.info(f"GasFlux modules imported successfully in {import_duration:.3f}s (absolute import)")
except ImportError as e1:
logger.warning(f"Absolute import failed, trying relative import: {e1}")
try:
from .processing_pipelines import process_main
from .data_processor import process_file
from .reporting import generate_reports
import_duration = time.time() - import_start
logger.info(f"GasFlux modules imported successfully in {import_duration:.3f}s (relative import)")
except ImportError as e2:
import_duration = time.time() - import_start
logger.error(f"Failed to import GasFlux modules after {import_duration:.3f}s - Absolute error: {e1}, Relative error: {e2}")
raise ImportError(f"Cannot import GasFlux modules: {e2}")
app = Flask(__name__)
CORS(app) # Initialize CORS
# Enhanced logging configuration after app initialization
try:
log_file_path = Path(Config.LOG_FILE)
log_file_path.parent.mkdir(parents=True, exist_ok=True)
# Create file handler
file_handler = logging.FileHandler(log_file_path, encoding='utf-8')
file_handler.setLevel(Config.get_log_level())
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# Add file handler to logger
logger.addHandler(file_handler)
logger.info(f"File logging initialized. Log file: {log_file_path.absolute()}")
print(f"Log file: {log_file_path.absolute()}") # Also print to console
except Exception as e:
print(f"Warning: Failed to initialize file logging: {e}")
logger.warning(f"Failed to initialize file logging: {e}")
logger.info("Flask application initialized")
# Request logging middleware
@app.before_request
def log_request_info():
"""Log incoming request details."""
g.start_time = time.time()
logger.info(f"REQUEST: {request.method} {request.url} - IP: {request.remote_addr} - User-Agent: {request.headers.get('User-Agent', 'Unknown')}")
@app.after_request
def log_response_info(response):
"""Log response details."""
duration = time.time() - g.start_time
logger.info(f"RESPONSE: {request.method} {request.url} - Status: {response.status_code} - Duration: {duration:.3f}s")
# Record statistics
endpoint = request.url_rule.rule if request.url_rule else request.path
stats_collector.record_request(request.method, endpoint, response.status_code, duration)
return response
# Initialize configuration from environment variables
Config.init_base_dir()
# Apply configuration to app (directories will be created dynamically based on config)
# ALLOWED_DATA_EXTENSIONS and ALLOWED_CONFIG_EXTENSIONS moved to shared.py
app.config['MAX_CONTENT_LENGTH'] = Config.MAX_CONTENT_LENGTH
# Don't set UPLOAD_FOLDER and OUTPUT_FOLDER here - they will be set dynamically per request
# Set defaults to avoid KeyError if any handler reads before config is applied
app.config.setdefault('UPLOAD_FOLDER', None)
app.config.setdefault('OUTPUT_FOLDER', None)
# Log current configuration
logger.info(f"Upload folder: {Config.UPLOAD_FOLDER}")
logger.info(f"Output folder: {Config.OUTPUT_FOLDER}")
logger.info(f"Configuration: {Config.to_dict()}")
# Ensure directories exist at startup
def setup_directories():
logger.info("Initializing application directories...")
start_time = time.time()
try:
# Check if directories already exist
upload_exists = Config.UPLOAD_FOLDER.exists()
output_exists = Config.OUTPUT_FOLDER.exists()
Config.UPLOAD_FOLDER.mkdir(parents=True, exist_ok=True)
Config.OUTPUT_FOLDER.mkdir(parents=True, exist_ok=True)
duration = time.time() - start_time
logger.info(f"Directories initialized in {duration:.3f}s: {Config.UPLOAD_FOLDER} ({'existing' if upload_exists else 'created'}), {Config.OUTPUT_FOLDER} ({'existing' if output_exists else 'created'})")
# Log directory permissions
upload_writable = os.access(Config.UPLOAD_FOLDER, os.W_OK)
output_writable = os.access(Config.OUTPUT_FOLDER, os.W_OK)
logger.info(f"Directory permissions - Upload writable: {upload_writable}, Output writable: {output_writable}")
except Exception as e:
duration = time.time() - start_time
logger.error(f"Failed to create directories after {duration:.3f}s: {e}")
raise
# setup_directories() - commented out to avoid creating directories at startup
# Directories will be created dynamically based on config when processing tasks
# allowed_file moved to shared.py
# Import blueprints after app initialization to avoid circular imports
from .blueprints.health import health_bp
from .blueprints.upload import upload_bp
from .blueprints.tasks import tasks_bp
from .blueprints.task_pool import task_pool_bp
from .blueprints.stats import stats_bp
from .blueprints.config import config_bp
from .blueprints.reports import reports_bp
from .blueprints.download import download_bp
from .blueprints.web import web_bp
# Register blueprints
app.register_blueprint(health_bp)
app.register_blueprint(upload_bp)
app.register_blueprint(tasks_bp)
app.register_blueprint(task_pool_bp)
app.register_blueprint(stats_bp)
app.register_blueprint(config_bp)
app.register_blueprint(reports_bp)
app.register_blueprint(download_bp)
app.register_blueprint(web_bp)
# Load persisted task status after app initialization
try:
from .shared import (
load_task_status_from_file,
save_task_status_to_file,
set_task_status_file_path,
)
# 只有在 OUTPUT_FOLDER 有效时才启用持久化
if hasattr(Config, 'OUTPUT_FOLDER') and Config.OUTPUT_FOLDER:
task_status_path = Config.OUTPUT_FOLDER / "task_status.json"
set_task_status_file_path(task_status_path)
logger.info(f"Task status persistence path set to: {task_status_path}")
with app.app_context():
load_task_status_from_file()
import atexit
def _save_on_exit():
with app.app_context():
save_task_status_to_file()
atexit.register(_save_on_exit)
else:
logger.info("Task status persistence will be configured after config is loaded")
except Exception as e:
print(f"⚠ Failed to setup task persistence: {e}")
# _get_file_type and _format_response moved to shared.py
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)

View File

@ -0,0 +1 @@
# GasFlux API Blueprints

View File

@ -0,0 +1,67 @@
"""
Configuration Blueprint
Provides configuration information and environment variables endpoints.
"""
import os
from flask import Blueprint
from ..app import Config
from ..shared import _format_response, log_performance, logger
# Create blueprint
config_bp = Blueprint('config', __name__, url_prefix='/config')
@config_bp.route('', methods=['GET'])
@log_performance
def get_config():
"""Get current configuration (without sensitive information)."""
logger.debug("Configuration requested")
try:
config_info = Config.to_dict()
# Remove potentially sensitive information
safe_config = config_info.copy()
data = {
"configuration": safe_config,
"environment_variables": {
"supported": [
"GASFLUX_HOST",
"GASFLUX_PORT",
"GASFLUX_DEBUG",
"GASFLUX_UPLOAD_FOLDER",
"GASFLUX_OUTPUT_FOLDER",
"GASFLUX_MAX_CONTENT_LENGTH",
"GASFLUX_LOG_LEVEL",
"GASFLUX_LOG_FILE",
"GASFLUX_CORS_ORIGINS",
"GASFLUX_TASK_CLEANUP_INTERVAL",
"GASFLUX_MAX_TASK_AGE",
"GASFLUX_THREADS",
"GASFLUX_CONNECTION_LIMIT",
"GASFLUX_CHANNEL_TIMEOUT"
],
"current_values": {
key: os.getenv(key, "not set") if key.startswith("GASFLUX_") else "internal"
for key in [
"GASFLUX_HOST", "GASFLUX_PORT", "GASFLUX_DEBUG",
"GASFLUX_UPLOAD_FOLDER", "GASFLUX_OUTPUT_FOLDER",
"GASFLUX_MAX_CONTENT_LENGTH", "GASFLUX_LOG_LEVEL",
"GASFLUX_LOG_FILE", "GASFLUX_CORS_ORIGINS",
"GASFLUX_TASK_CLEANUP_INTERVAL", "GASFLUX_MAX_TASK_AGE",
"GASFLUX_THREADS", "GASFLUX_CONNECTION_LIMIT",
"GASFLUX_CHANNEL_TIMEOUT"
]
}
}
}
return _format_response(200, "配置信息获取成功", data)
except Exception as e:
logger.error(f"Failed to retrieve configuration: {str(e)}", exc_info=True)
return _format_response(500, "获取配置信息失败", {
"error_details": str(e)
})

View File

@ -0,0 +1,68 @@
"""
Download Blueprint
Handles file download endpoints.
"""
from pathlib import Path
from flask import Blueprint, send_file, current_app
from ..shared import _format_response, log_performance, logger
# Create blueprint
download_bp = Blueprint('download', __name__, url_prefix='/download')
@download_bp.route('/<path:filename>')
@log_performance
def download_file(filename):
"""Download a processed file."""
from flask import request
logger.info(f"Download request for file: {filename} from IP {request.remote_addr}")
try:
# 支持两种路径格式:
# 1. 绝对路径(以 / 开头,如 /full/path/to/file
# 2. 相对路径task_id/filename
if filename.startswith('/'):
# 绝对路径 - 直接使用
file_path = Path(filename)
else:
# 相对路径 - 相对于 OUTPUT_FOLDER
output_folder = Path(current_app.config.get('OUTPUT_FOLDER') or '')
if not output_folder:
logger.error("OUTPUT_FOLDER not configured")
return _format_response(500, "服务器配置错误")
# 解析 task_id/filename 格式
parts = filename.split('/', 1)
if len(parts) != 2:
logger.warning(f"Invalid relative path format: {filename}")
return _format_response(400, "无效的文件路径")
task_id, filename_part = parts
file_path = output_folder / task_id / filename_part
# Security check - ensure file is within output folder
file_path = file_path.resolve()
output_folder = Path(current_app.config.get('OUTPUT_FOLDER') or '').resolve()
if output_folder and not str(file_path).startswith(str(output_folder)):
logger.warning(f"Security violation: Attempted to access file outside output folder: {filename}")
return _format_response(403, "访问被拒绝")
if not file_path.exists():
logger.warning(f"File not found: {filename}")
return _format_response(404, "文件未找到")
if not file_path.is_file():
logger.warning(f"Path is not a file: {filename}")
return _format_response(400, "不是文件")
file_size = file_path.stat().st_size
logger.info(f"Serving file: {filename} ({file_size} bytes)")
return send_file(file_path)
except Exception as e:
logger.error(f"Error serving file {filename}: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")

View File

@ -0,0 +1,94 @@
"""
Health Check Blueprint
Provides API health monitoring and system status endpoints.
"""
import os
import time
import logging
from flask import Blueprint, request
from ..app import Config, stats_collector
from ..shared import task_status, TASK_STATUS_PENDING, TASK_STATUS_PROCESSING
from ..shared import _format_response, log_performance, logger
# Create blueprint
health_bp = Blueprint('health', __name__, url_prefix='/health')
@health_bp.route('', methods=['GET'])
@log_performance
def health_check():
"""API Health Check"""
logger.debug("Health check requested")
try:
# Check storage accessibility
uploads_writable = os.access(Config.UPLOAD_FOLDER, os.W_OK)
outputs_writable = os.access(Config.OUTPUT_FOLDER, os.W_OK)
# Check active tasks
active_tasks = len([t for t in task_status.values() if t.get("status") in [TASK_STATUS_PENDING, TASK_STATUS_PROCESSING]])
# Get basic stats for health check
stats_summary = stats_collector.get_summary()
health_data = {
"status": "healthy",
"version": "1.0.0",
"timestamp": time.time(),
"uptime": stats_summary['summary']['uptime_formatted'],
"storage": {
"uploads_writable": uploads_writable,
"outputs_writable": outputs_writable
},
"tasks": {
"active_count": active_tasks,
"total_tracked": len(task_status),
"total_processed": stats_summary['tasks']['total_completed'] + stats_summary['tasks']['total_failed'],
"success_rate_percent": stats_summary['tasks']['success_rate_percent']
},
"performance": {
"requests_per_second": stats_summary['summary']['requests_per_second'],
"avg_response_time_ms": stats_summary['performance']['avg_response_time_ms'],
"error_rate_percent": stats_summary['summary']['error_rate_percent']
}
}
# Determine health status based on metrics
is_healthy = True
issues = []
if not uploads_writable:
issues.append("上传文件夹不可写")
is_healthy = False
if not outputs_writable:
issues.append("输出文件夹不可写")
is_healthy = False
if active_tasks > 20: # High load threshold
issues.append(f"活跃任务数量过多 ({active_tasks})")
if stats_summary['summary']['error_rate_percent'] > 10: # High error rate
issues.append(f"错误率过高 ({stats_summary['summary']['error_rate_percent']:.1f}%)")
is_healthy = False
health_data["status"] = "healthy" if is_healthy else "degraded"
if issues:
health_data["issues"] = issues
# Log warnings for potential issues
for issue in issues:
logger.warning(f"Health check issue: {issue}")
status_level = logging.DEBUG if is_healthy else logging.WARNING
logger.log(status_level, f"Health check: {health_data['status']} (active tasks: {active_tasks})")
status_code = 200 if is_healthy else 503 # 503 Service Unavailable for degraded
return _format_response(status_code, "健康检查完成" if is_healthy else "服务不可用", health_data)
except Exception as e:
logger.error(f"Health check failed: {str(e)}", exc_info=True)
return _format_response(500, "健康检查失败", {
"status": "unhealthy",
"error": str(e),
"timestamp": time.time()
})

View File

@ -0,0 +1,192 @@
"""
Reports Blueprint
Provides report listing and management endpoints.
"""
import time
from pathlib import Path
from flask import Blueprint, request, current_app
from ..shared import _get_file_type, _format_response, log_performance, logger, task_status
from ..app import Config
# Create blueprint
reports_bp = Blueprint('reports', __name__, url_prefix='/reports')
@reports_bp.route('', methods=['GET'])
@log_performance
def list_reports():
"""List all generated reports with pagination and filtering."""
logger.debug("Reports list requested")
try:
# Parse query parameters
try:
page = int(request.args.get('page', 1))
if page < 1:
return _format_response(400, "Invalid parameter: page must be >= 1")
except (ValueError, TypeError):
return _format_response(400, "Invalid parameter: page must be a valid integer")
try:
per_page = int(request.args.get('per_page', 20))
if per_page < 1 or per_page > 100:
return _format_response(400, "Invalid parameter: per_page must be between 1 and 100")
except (ValueError, TypeError):
return _format_response(400, "Invalid parameter: per_page must be a valid integer")
sort_by = request.args.get('sort_by', 'created_at')
sort_order = request.args.get('sort_order', 'desc')
status_filter = request.args.get('status', None) # 'completed', 'failed', or None for all
# Validate sort parameters
valid_sort_fields = ['created_at', 'task_id', 'file_size', 'processing_time']
if sort_by not in valid_sort_fields:
return _format_response(400, f"Invalid parameter: sort_by must be one of {valid_sort_fields}")
if sort_order not in ['asc', 'desc']:
return _format_response(400, "Invalid parameter: sort_order must be 'asc' or 'desc'")
# Validate status filter
valid_statuses = ['completed', 'failed', None]
if status_filter is not None and status_filter not in ['completed', 'failed']:
return _format_response(400, "Invalid parameter: status must be 'completed', 'failed', or not specified")
# 兼容缺省:优先 app.config其次 Config.OUTPUT_FOLDER
output_root = current_app.config.get('OUTPUT_FOLDER') or getattr(Config, 'OUTPUT_FOLDER', None)
if not output_root:
return _format_response(200, "报告列表获取成功", {
'reports': [],
'pagination': {'page': page, 'per_page': per_page, 'total_reports': 0, 'total_pages': 0, 'has_next': False, 'has_prev': False},
'filters': {'sort_by': sort_by, 'sort_order': sort_order, 'status': status_filter}
})
output_folder = Path(output_root)
reports = []
# Scan all task directories
if output_folder.exists():
for task_dir in output_folder.iterdir():
if not task_dir.is_dir():
continue
task_id = task_dir.name
# Get task information from global task_status
task_info = task_status.get(task_id, {})
task_status_value = task_info.get('status')
# Log task status for debugging
logger.debug(f"Task {task_id}: status from memory={task_status_value}, info={task_info}")
# 直接扫描平铺文件
files = [p for p in task_dir.iterdir() if p.is_file()]
if not files:
# 按需应用状态过滤
if status_filter:
continue
reports.append({
'task_id': task_id,
'report_name': "N/A",
'status': 'failed',
'created_at': task_dir.stat().st_mtime,
'file_count': 0,
'total_size': 0,
'processing_time_seconds': None,
'main_report': None,
'all_files': [],
'run_directory': f'{task_id}'
})
continue
# 识别主报告与统计
total_size = sum(f.stat().st_size for f in files)
created_at = max(f.stat().st_mtime for f in files) if files else task_dir.stat().st_mtime
def file_entry(p):
return {
'name': p.name,
'size': p.stat().st_size,
'type': _get_file_type(p.name),
# 使用相对路径下载,清晰且安全
'download_url': f"/download/{task_id}/{p.name}"
}
all_files = [file_entry(f) for f in files]
# 优先 CO2_report其次任意 *_report_*.html
report_html = None
for f in files:
if f.name.endswith('_report_') and f.suffix == '.html':
report_html = file_entry(f)
break
if not report_html:
for f in files:
if f.name.endswith('.html'):
report_html = file_entry(f)
break
# 任务状态:若有报告或关键产物则视为 completed
has_outputs = any(f.name.startswith(('config_', 'output_vars_', 'processed_data_', 'CO2_report_')) for f in files)
task_status_value = 'completed' if has_outputs else 'unknown'
if status_filter and task_status_value != status_filter:
continue
# Create report entry
report_entry = {
'task_id': task_id,
'report_name': task_id,
'status': task_status_value,
'created_at': created_at,
'file_count': len(files),
'total_size': total_size,
'processing_time_seconds': None,
'main_report': report_html,
'all_files': all_files,
'run_directory': f'{task_id}'
}
reports.append(report_entry)
# Sort reports
reverse_order = sort_order == 'desc'
if sort_by == 'created_at':
reports.sort(key=lambda x: x['created_at'], reverse=reverse_order)
elif sort_by == 'task_id':
reports.sort(key=lambda x: x['task_id'], reverse=reverse_order)
elif sort_by == 'file_size':
reports.sort(key=lambda x: x['total_size'], reverse=reverse_order)
elif sort_by == 'processing_time':
reports.sort(key=lambda x: x['processing_time_seconds'] or 0, reverse=reverse_order)
# Paginate results
total_reports = len(reports)
start_idx = (page - 1) * per_page
end_idx = start_idx + per_page
paginated_reports = reports[start_idx:end_idx]
# Calculate pagination metadata
total_pages = (total_reports + per_page - 1) // per_page
response_data = {
'reports': paginated_reports,
'pagination': {
'page': page,
'per_page': per_page,
'total_reports': total_reports,
'total_pages': total_pages,
'has_next': page < total_pages,
'has_prev': page > 1
},
'filters': {
'sort_by': sort_by,
'sort_order': sort_order,
'status': status_filter
}
}
logger.info(f"Returning {len(paginated_reports)} reports (page {page}/{total_pages})")
return _format_response(200, "报告列表获取成功", response_data)
except Exception as e:
logger.error(f"Error listing reports: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")

View File

@ -0,0 +1,93 @@
"""
Statistics Blueprint
Provides API statistics and monitoring endpoints.
"""
import time
from flask import Blueprint, current_app
from ..shared import _format_response, log_performance, logger,stats_collector, task_status
# Create blueprint
stats_bp = Blueprint('stats', __name__, url_prefix='/stats')
@stats_bp.route('', methods=['GET'])
@log_performance
def get_stats():
"""Get detailed API statistics and monitoring data."""
logger.debug("Statistics requested")
try:
# Get detailed statistics
stats_data = stats_collector.get_summary()
# Add current system information
try:
import psutil
memory = psutil.virtual_memory()
disk = psutil.disk_usage(str(current_app.config['OUTPUT_FOLDER']))
stats_data['system'] = {
'memory_usage_percent': memory.percent,
'memory_used_gb': round(memory.used / (1024**3), 2),
'memory_total_gb': round(memory.total / (1024**3), 2),
'disk_usage_percent': disk.percent,
'disk_used_gb': round(disk.used / (1024**3), 2),
'disk_total_gb': round(disk.total / (1024**3), 2)
}
except ImportError:
# psutil not available
stats_data['system'] = {
'note': 'System metrics unavailable - install psutil for detailed monitoring'
}
except Exception as e:
logger.warning(f"Failed to collect system metrics: {e}")
stats_data['system'] = {'error': str(e)}
# Add recent task information
recent_tasks = []
current_time = time.time()
for task_id, task_info in list(task_status.items())[-20:]: # Last 20 tasks
age = current_time - task_info.get('updated_at', 0)
recent_tasks.append({
'task_id': task_id,
'status': task_info.get('status'),
'age_seconds': round(age, 1),
'message': task_info.get('message', '')[:100] # Truncate long messages
})
stats_data['recent_tasks'] = recent_tasks
return _format_response(200, "统计信息获取成功", stats_data)
except Exception as e:
logger.error(f"Failed to retrieve statistics: {str(e)}", exc_info=True)
return _format_response(500, "获取统计信息失败", {
"error_details": str(e)
})
@stats_bp.route('/reset', methods=['POST'])
@log_performance
def reset_stats():
"""Reset API statistics (admin function)."""
logger.warning("Statistics reset requested")
try:
# Reset statistics
stats_collector.reset_stats()
# Log the reset
logger.info("API statistics have been reset")
return _format_response(200, "统计信息重置成功", {
"timestamp": time.time()
})
except Exception as e:
logger.error(f"Failed to reset statistics: {str(e)}", exc_info=True)
return _format_response(500, "重置统计信息失败", {
"error_details": str(e)
})

View File

@ -0,0 +1,228 @@
"""
Task Pool Blueprint
Handles task pool management endpoints: listing tasks with pagination, pool statistics.
"""
from flask import Blueprint, request
from pathlib import Path
from ..shared import (
get_task_list,
get_task_pool_stats,
_format_response,
log_performance,
logger,
task_status,
TASK_STATUS_PENDING,
TASK_STATUS_PROCESSING,
TASK_STATUS_COMPLETED,
TASK_STATUS_FAILED
)
# Create blueprint
task_pool_bp = Blueprint('task_pool', __name__, url_prefix='/tasks')
def _build_simple_downloads_from_results(results: list[dict]) -> dict:
"""
Build direct download shortcuts for common files, based on task results.
This is intentionally minimal and frontend-friendly.
"""
downloads: dict = {}
def set_once(key: str, url: str):
if key not in downloads and url:
downloads[key] = url
for item in results or []:
if not isinstance(item, dict):
continue
rel_path = item.get('rel_path')
if not rel_path:
continue
name_l = (item.get('name') or '').lower()
url = f"/download/{rel_path}"
if name_l.endswith('.xlsx'):
set_once('data_xlsx', url)
elif name_l.endswith('.xls'):
set_once('data_xls', url)
elif name_l.endswith('ch4_report.html'):
set_once('report_ch4', url)
elif name_l.endswith('co2_report.html'):
set_once('report_co2', url)
elif name_l.endswith(('.yaml', '.yml')):
set_once('config', url)
elif name_l.endswith('.json') and 'output_vars' in name_l:
set_once('metadata', url)
elif name_l.endswith('.html'):
# fallback: any html report
set_once('report_html', url)
return downloads
def _lean_task_summary(task_summary: dict) -> dict:
"""Return a minimal task representation for frontend consumption."""
task_id = task_summary.get('task_id')
status = task_summary.get('status')
lean = {
'task_id': task_id,
'status': status,
'message': task_summary.get('message'),
'updated_at': task_summary.get('updated_at'),
}
if status == TASK_STATUS_COMPLETED and task_id:
full_task_info = task_status.get(task_id, {})
results = full_task_info.get('results', []) or []
downloads = _build_simple_downloads_from_results(results)
if downloads:
lean['downloads'] = downloads
return lean
@task_pool_bp.route('', methods=['GET'])
@log_performance
def list_tasks():
"""Get paginated list of tasks with optional filtering."""
logger.debug(f"Task list request from IP {request.remote_addr}")
try:
# Parse query parameters
status_filter = request.args.get('status')
if status_filter:
# Support comma-separated status values
status_filter = status_filter.split(',')
page = int(request.args.get('page', 1))
page_size = int(request.args.get('page_size', 20))
sort_by = request.args.get('sort_by', 'updated_at')
sort_order = request.args.get('sort_order', 'desc')
# Validate parameters
if page < 1:
return _format_response(400, "页码必须大于0")
if page_size < 1 or page_size > 100:
return _format_response(400, "每页数量必须在1-100之间")
valid_sort_fields = ['created_at', 'updated_at', 'status']
if sort_by not in valid_sort_fields:
return _format_response(400, f"排序字段必须是以下之一: {', '.join(valid_sort_fields)}")
if sort_order.lower() not in ['asc', 'desc']:
return _format_response(400, "排序顺序必须是 'asc''desc'")
# Get task list
result = get_task_list(
status_filter=status_filter,
page=page,
page_size=page_size,
sort_by=sort_by,
sort_order=sort_order,
cleanup=False
)
# Slim response: only task status + downloads (completed only)
result['tasks'] = [_lean_task_summary(t) for t in result.get('tasks', [])]
logger.debug(f"Returning {len(result['tasks'])} tasks (page {page} of {result['total_pages']})")
return _format_response(200, "任务列表查询成功", result)
except ValueError as e:
logger.warning(f"Invalid parameter in task list request: {str(e)}")
return _format_response(400, "参数格式错误")
except Exception as e:
logger.error(f"Error listing tasks: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")
@task_pool_bp.route('/stats', methods=['GET'])
@log_performance
def get_pool_stats():
"""Get task pool statistics."""
logger.debug(f"Task pool stats request from IP {request.remote_addr}")
try:
stats = get_task_pool_stats()
logger.debug(f"Pool stats: {stats['total_tasks']} total tasks, "
f"{stats['active_tasks']} active, {stats['queued_tasks']} queued")
return _format_response(200, "任务池统计信息查询成功", stats)
except Exception as e:
logger.error(f"Error getting pool stats: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")
@task_pool_bp.route('/active', methods=['GET'])
@log_performance
def get_active_tasks():
"""Get list of currently active (processing) tasks."""
logger.debug(f"Active tasks request from IP {request.remote_addr}")
try:
# Get all processing tasks, no pagination needed for active tasks
result = get_task_list(
status_filter=TASK_STATUS_PROCESSING,
page=1,
page_size=1000, # Large page size to get all active tasks
sort_by='updated_at',
sort_order='asc', # Oldest first
cleanup=False
)
active_tasks = result['tasks']
active_tasks = [_lean_task_summary(t) for t in active_tasks]
logger.debug(f"Returning {len(active_tasks)} active tasks")
return _format_response(200, "活跃任务查询成功", {
'active_tasks': active_tasks,
'count': len(active_tasks)
})
except Exception as e:
logger.error(f"Error getting active tasks: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")
@task_pool_bp.route('/queue', methods=['GET'])
@log_performance
def get_queued_tasks():
"""Get list of queued (pending) tasks."""
logger.debug(f"Queued tasks request from IP {request.remote_addr}")
try:
# Get all pending tasks, sorted by creation time
result = get_task_list(
status_filter=TASK_STATUS_PENDING,
page=1,
page_size=1000, # Large page size to get all queued tasks
sort_by='created_at',
sort_order='asc', # Oldest first (FIFO)
cleanup=False
)
queued_tasks = result['tasks']
queued_tasks = [_lean_task_summary(t) for t in queued_tasks]
logger.debug(f"Returning {len(queued_tasks)} queued tasks")
return _format_response(200, "队列任务查询成功", {
'queued_tasks': queued_tasks,
'count': len(queued_tasks),
'queue_position_info': "任务按创建时间排序,较早的任务优先处理"
})
except Exception as e:
logger.error(f"Error getting queued tasks: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")

View File

@ -0,0 +1,220 @@
"""
Tasks Blueprint
Handles task management endpoints: status query, update, and deletion.
"""
from flask import Blueprint, request
from ..shared import (
get_task_status,
update_task_status,
cleanup_old_tasks,
_format_response,
log_performance,
logger,
task_status,
_build_simple_downloads_from_results,
TASK_STATUS_COMPLETED,
TASK_STATUS_FAILED,
TASK_STATUS_PROCESSING,
TASK_STATUS_PENDING,
)
# Create blueprint
tasks_bp = Blueprint('tasks', __name__, url_prefix='/task')
@tasks_bp.route('/<task_id>', methods=['GET'])
@log_performance
def get_task_status_endpoint(task_id):
"""Get the status of a processing task."""
logger.debug(f"Status request for task {task_id}")
try:
# Note: cleanup_old_tasks() is disabled for individual task queries
# to preserve historical task data for task pool management
# cleanup_old_tasks()
task_info = get_task_status(task_id)
if task_info.get("status") == "not_found":
logger.warning(f"Status request for non-existent task {task_id} from IP {request.remote_addr}")
return _format_response(404, "任务未找到")
data = {
"task_id": task_id,
"status": task_info["status"],
"message": task_info.get("message", ""),
"updated_at": task_info.get("updated_at", 0)
}
if task_info["status"] == TASK_STATUS_COMPLETED:
results = task_info.get("results", [])
data["results"] = results
# Add direct download shortcuts for frontend (if available or can be derived)
downloads = task_info.get("downloads") or _build_simple_downloads_from_results(results)
if downloads:
data["downloads"] = downloads
logger.debug(f"Task {task_id}: Returning {len(results)} completed results")
return _format_response(200, "任务查询成功", data)
elif task_info["status"] == TASK_STATUS_FAILED:
error_msg = task_info.get("error", "未知错误")
data["error"] = error_msg
logger.warning(f"Task {task_id}: Returning failure status - {error_msg}")
# Return 200 for failed tasks since this is expected behavior, not an HTTP error
return _format_response(200, "任务处理失败", data)
else:
# Processing or pending status
return _format_response(200, "任务查询成功", data)
except Exception as e:
logger.error(f"Error retrieving status for task {task_id}: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")
@tasks_bp.route('/<task_id>', methods=['PUT'])
@log_performance
def update_task(task_id):
"""Update task status and information."""
logger.info(f"Task update request for {task_id} from IP {request.remote_addr}")
try:
# Validate task exists
task_info = get_task_status(task_id)
if task_info.get("status") == "not_found":
logger.warning(f"Update request for non-existent task {task_id}")
return _format_response(404, "任务未找到")
# Parse request data
data = request.get_json()
if not data:
return _format_response(400, "请求体必须是 JSON 格式")
# Validate allowed fields
allowed_fields = ['status', 'message', 'priority']
valid_statuses = [TASK_STATUS_PENDING, TASK_STATUS_PROCESSING,
TASK_STATUS_COMPLETED, TASK_STATUS_FAILED]
updates = {}
for field in allowed_fields:
if field in data:
if field == 'status' and data[field] not in valid_statuses:
return _format_response(400, f"无效状态。必须是以下之一: {', '.join(valid_statuses)}")
updates[field] = data[field]
if not updates:
return _format_response(400, "没有有效的字段可更新")
# Update task status
current_status = task_info.get('status')
new_status = updates.get('status', current_status)
message = updates.get('message', task_info.get('message'))
# Special handling for status changes
if 'status' in updates:
if new_status == TASK_STATUS_COMPLETED:
# For completed tasks, we might want to add fake results if none exist
if not task_info.get('results'):
logger.warning(f"Marking task {task_id} as completed but no results found")
elif new_status == TASK_STATUS_FAILED:
# For failed tasks, error message is required
error_msg = updates.get('message', 'Task manually marked as failed')
update_task_status(task_id, new_status, error_msg)
else:
update_task_status(task_id, new_status, message)
else:
# Only update message
update_task_status(task_id, current_status, message)
# Update priority if provided
if 'priority' in updates:
task_status[task_id]['priority'] = updates['priority']
# Get updated task info
updated_task = get_task_status(task_id)
data = {
"task_id": task_id,
"status": "updated",
"task_info": {
"status": updated_task.get("status"),
"message": updated_task.get("message"),
"updated_at": updated_task.get("updated_at", 0),
"priority": updated_task.get("priority", "normal")
}
}
logger.info(f"Task {task_id} updated: {updates}")
return _format_response(200, "任务更新成功", data)
except Exception as e:
logger.error(f"Error updating task {task_id}: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")
@tasks_bp.route('/<task_id>', methods=['DELETE'])
@log_performance
def delete_task(task_id):
"""Delete a task and its associated files."""
logger.info(f"Task deletion request for {task_id} from IP {request.remote_addr}")
try:
# Validate task exists
task_info = get_task_status(task_id)
if task_info.get("status") == "not_found":
logger.warning(f"Delete request for non-existent task {task_id}")
return _format_response(404, "任务未找到")
# Check if task is currently processing
if task_info.get("status") in [TASK_STATUS_PROCESSING, TASK_STATUS_PENDING]:
return _format_response(409, "无法删除当前正在处理或等待处理的任务", {
"task_status": task_info.get("status")
})
# Delete associated files
from pathlib import Path
from flask import current_app
import shutil
output_folder = Path(current_app.config['OUTPUT_FOLDER'])
task_folder = output_folder / task_id
files_deleted = 0
total_size_deleted = 0
if task_folder.exists():
try:
# Calculate total size before deletion
for file_path in task_folder.rglob('*'):
if file_path.is_file():
total_size_deleted += file_path.stat().st_size
# Delete the entire task folder
shutil.rmtree(task_folder)
files_deleted = 1 # Count as one folder deleted
logger.info(f"Deleted task folder: {task_folder}")
except Exception as e:
logger.error(f"Error deleting task folder {task_folder}: {str(e)}")
return _format_response(500, f"删除任务文件失败: {str(e)}")
# Remove from task status tracking
if task_id in task_status:
del task_status[task_id]
logger.info(f"Removed task {task_id} from status tracking")
data = {
"task_id": task_id,
"status": "deleted",
"details": {
"folders_deleted": files_deleted,
"total_size_deleted": total_size_deleted,
"task_status": task_info.get("status")
}
}
logger.info(f"Task {task_id} deleted successfully")
return _format_response(200, "任务及相关文件删除成功", data)
except Exception as e:
logger.error(f"Error deleting task {task_id}: {str(e)}", exc_info=True)
return _format_response(500, "内部服务器错误")

View File

@ -0,0 +1,134 @@
"""
Upload Blueprint
Handles file upload and processing initiation endpoints.
"""
import uuid
import threading
from pathlib import Path
from flask import Blueprint, request, current_app
from werkzeug.utils import secure_filename
import yaml
from io import BytesIO
from ..app import process_data_async
from ..shared import _format_response, log_performance, logger, ALLOWED_DATA_EXTENSIONS, ALLOWED_CONFIG_EXTENSIONS, allowed_file,update_task_status, TASK_STATUS_PENDING, TASK_STATUS_FAILED
# Create blueprint
upload_bp = Blueprint('upload', __name__, url_prefix='/upload')
@upload_bp.route('', methods=['POST'])
@log_performance
def upload_file():
logger.info("Received upload request")
logger.info(f"Request content length: {request.content_length} bytes")
# Check if data file is present
if 'file' not in request.files:
logger.warning("Upload failed: No data file part in request")
return _format_response(400, "未找到数据文件部分")
data_file = request.files['file']
config_file = request.files.get('config')
# Log file details
logger.info(f"Data file: {data_file.filename} (size: {getattr(data_file, 'content_length', 'unknown')} bytes)")
if config_file:
logger.info(f"Config file: {config_file.filename} (size: {getattr(config_file, 'content_length', 'unknown')} bytes)")
else:
logger.info("No custom config file provided, will use default")
if data_file.filename == '':
logger.warning("Upload failed: No data file selected (empty filename)")
return _format_response(400, "未选择数据文件")
if not allowed_file(data_file.filename, ALLOWED_DATA_EXTENSIONS):
logger.warning(f"Upload failed: Invalid data file type {data_file.filename} - allowed: {ALLOWED_DATA_EXTENSIONS}")
return _format_response(400, "无效的数据文件类型。只允许 .xlsx 和 .xls 格式。")
# Generate unique job ID
job_id = str(uuid.uuid4())
logger.info(f"Generated job ID: {job_id}")
# 1) Parse config content (parse in memory without saving first)
if config_file and config_file.filename != '':
if not allowed_file(config_file.filename, ALLOWED_CONFIG_EXTENSIONS):
return _format_response(400, "无效的配置文件类型。只允许 .yaml 和 .yml 格式。")
config_file.stream.seek(0)
config_text = config_file.read().decode('utf-8', errors='ignore')
try:
active_config = yaml.safe_load(config_text)
except Exception:
return _format_response(400, "配置文件解析失败")
# Reset stream for saving
config_file.stream = BytesIO(config_text.encode('utf-8'))
else:
default_config_path = Path(__file__).parent.parent / "gasflux_config.yaml"
with open(default_config_path, 'r', encoding='utf-8') as f:
active_config = yaml.safe_load(f)
# 2) Create job directories based on config['output_dir']
output_base = Path(active_config['output_dir']).expanduser()
job_upload_dir = output_base / "uploads" / job_id
job_output_dir = output_base / "outputs" / job_id
job_upload_dir.mkdir(parents=True, exist_ok=True)
job_output_dir.mkdir(parents=True, exist_ok=True)
logger.info(f"Job {job_id}: Created directories - Upload: {job_upload_dir}, Output: {job_output_dir}")
# 3) Save data file to job_upload_dir
data_filename = secure_filename(data_file.filename)
data_path = job_upload_dir / data_filename
try:
data_file.seek(0)
data_file.save(str(data_path))
logger.info(f"Job {job_id}: Data file saved successfully - Path: {data_path}")
except Exception as e:
logger.error(f"Job {job_id}: Failed to save data file {data_filename}: {str(e)}")
return _format_response(500, "保存数据文件失败")
# 4) Save config file to job_upload_dir
if config_file and config_file.filename != '':
config_filename = secure_filename(config_file.filename)
config_path = job_upload_dir / config_filename
try:
config_file.seek(0)
config_file.save(str(config_path))
active_config_path = config_path
logger.info(f"Job {job_id}: Custom config saved successfully - Path: {config_path}")
except Exception as e:
logger.error(f"Job {job_id}: Failed to save config file {config_filename}: {str(e)}")
return _format_response(500, "保存配置文件失败")
else:
# Copy default config for record keeping
config_path = job_upload_dir / "config.yaml"
with open(config_path, 'w', encoding='utf-8') as f:
yaml.safe_dump(active_config, f, allow_unicode=True)
active_config_path = config_path
logger.info(f"Job {job_id}: Default config saved for record - Path: {config_path}")
# Initialize task status
update_task_status(job_id, TASK_STATUS_PENDING, "Task queued for processing")
logger.info(f"Job {job_id}: Task status initialized as PENDING")
# Start background processing
try:
thread = threading.Thread(
target=process_data_async,
args=(job_id, data_path, active_config_path, job_output_dir)
)
thread.daemon = True
thread.start()
logger.info(f"Job {job_id}: Background processing thread started successfully")
except Exception as e:
logger.error(f"Job {job_id}: Failed to start background processing thread: {str(e)}")
update_task_status(job_id, TASK_STATUS_FAILED, error=str(e))
return _format_response(500, "启动处理失败")
logger.info(f"Job {job_id}: Upload process completed successfully, returning job ID to client")
return _format_response(202, "任务已接受并加入处理队列", {
"status": "accepted",
"job_id": job_id,
"task_status_url": f"/task/{job_id}"
})

View File

@ -0,0 +1,233 @@
"""
Web Blueprint
Provides web interface for the GasFlux API.
"""
import time
from pathlib import Path
from flask import Blueprint, render_template_string, current_app
from ..shared import log_performance, logger
from ..app import Config
# Create blueprint
web_bp = Blueprint('web', __name__)
@web_bp.route('/')
@log_performance
def index():
logger.debug("Index page requested")
# 递归查找所有生成的 HTML 报告
start_time = time.time()
all_reports = []
# 优先用 app.config 中的目录,其次回退到 Config.OUTPUT_FOLDER都不存在则不列出文件
output_root = current_app.config.get('OUTPUT_FOLDER') or getattr(Config, 'OUTPUT_FOLDER', None)
if not output_root:
output_path = None
else:
output_path = Path(output_root)
if output_path and output_path.exists():
try:
for file in output_path.rglob("*.html"):
# 获取相对于 OUTPUT_FOLDER 的相对路径,用于下载链接
rel_path = file.relative_to(output_path).as_posix()
all_reports.append(rel_path)
scan_duration = time.time() - start_time
logger.debug(f"Report scan completed in {scan_duration:.3f}s - found {len(all_reports)} HTML reports")
except Exception as e:
logger.error(f"Error scanning for reports: {str(e)}")
all_reports = []
else:
logger.debug("No output directory configured yet, skipping report scan")
all_reports = []
return render_template_string('''
<!doctype html>
<html>
<head>
<title>GasFlux Web API</title>
<style>
body { font-family: sans-serif; margin: 40px; line-height: 1.6; background-color: #f4f7f6; }
.container { max-width: 900px; margin: auto; background: white; padding: 30px; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
.upload-section { background: #f8f9fa; padding: 25px; border-radius: 8px; border-left: 5px solid #3498db; margin-bottom: 30px; }
.form-group { margin-bottom: 20px; }
label { display: block; font-weight: bold; margin-bottom: 8px; color: #34495e; }
input[type="file"] { display: block; width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
input[type="submit"] { background: #3498db; color: white; border: none; padding: 12px 25px; border-radius: 4px; cursor: pointer; font-size: 16px; transition: background 0.3s; }
input[type="submit"]:hover { background: #2980b9; }
.results-section { margin-top: 40px; }
.report-item { margin-bottom: 15px; padding: 15px; border: 1px solid #eee; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; }
.report-info { display: flex; flex-direction: column; }
.report-link { font-weight: bold; color: #2980b9; text-decoration: none; font-size: 1.1em; }
.report-link:hover { text-decoration: underline; }
.report-path { font-size: 0.85em; color: #7f8c8d; margin-top: 4px; }
.api-docs { margin-top: 50px; padding: 20px; background: #e8f4f8; border-radius: 8px; font-size: 0.9em; }
code { background: #eee; padding: 2px 5px; border-radius: 3px; font-family: monospace; }
</style>
</head>
<body>
<div class="container">
<h1>GasFlux Web API 控制台</h1>
<div class="upload-section">
<h2>新建处理任务</h2>
<form id="uploadForm" enctype=multipart/form-data>
<div class="form-group">
<label for="data_file">数据文件 (Excel):</label>
<input type="file" name="file" id="data_file" required>
</div>
<div class="form-group">
<label for="config_file">配置文件 (YAML) [可选]:</label>
<input type="file" name="config" id="config_file">
</div>
<button type="submit" id="submitBtn">开始上传并分析</button>
</form>
<div id="taskStatus" style="display: none; margin-top: 20px; padding: 15px; background: #e8f8e8; border-radius: 5px; border: 1px solid #28a745;">
<h3>任务状态</h3>
<p id="statusMessage">正在上传文件...</p>
<div id="progressBar" style="width: 100%; height: 20px; background: #f0f0f0; border-radius: 10px; margin: 10px 0; display: none;">
<div id="progressFill" style="height: 100%; background: #28a745; border-radius: 10px; width: 0%; transition: width 0.3s;"></div>
</div>
<p id="taskId" style="font-size: 0.9em; color: #666;"></p>
</div>
</div>
<div class="results-section">
<h2>已生成的报告</h2>
<div id="reports">
{% for report in reports %}
<div class="report-item">
<div class="report-info">
<a class="report-link" href="/download/{{ report }}" target="_blank">{{ report.split('/')[-1] }}</a>
<span class="report-path">任务 ID: {{ report.split('/')[0] }}</span>
</div>
<a href="/download/{{ report }}" download class="report-link" style="font-size: 0.9em;">下载</a>
</div>
{% else %}
<p style="color: #95a5a6;">暂无已生成的报告。</p>
{% endfor %}
</div>
</div>
<div class="api-docs">
<h3>API 调用指南 (开发者)</h3>
<p><strong>健康检查:</strong> <code>GET /health</code></p>
<p><strong>上传分析:</strong> <code>POST /upload</code></p>
<p><strong>查询任务状态:</strong> <code>GET /task/&lt;task_id&gt;</code></p>
<p>参数: <code>file</code> (Excel), <code>config</code> (YAML, 可选)</p>
<p>示例: <code>curl -X POST -F "file=@data.xlsx" http://localhost:5000/upload</code></p>
<p>状态查询: <code>curl http://localhost:5000/task/your-task-id</code></p>
</div>
<script>
document.getElementById('uploadForm').addEventListener('submit', async function(e) {
e.preventDefault();
const formData = new FormData(this);
const submitBtn = document.getElementById('submitBtn');
const taskStatus = document.getElementById('taskStatus');
const statusMessage = document.getElementById('statusMessage');
const taskIdElement = document.getElementById('taskId');
const progressBar = document.getElementById('progressBar');
const progressFill = document.getElementById('progressFill');
// Disable form and show status
submitBtn.disabled = true;
submitBtn.textContent = '上传中...';
taskStatus.style.display = 'block';
progressBar.style.display = 'block';
progressFill.style.width = '10%';
try {
// Upload file
statusMessage.textContent = '正在上传文件...';
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
const taskId = result.data.job_id;
statusMessage.textContent = '文件上传成功,开始处理数据...';
taskIdElement.textContent = `任务ID: ${taskId}`;
progressFill.style.width = '30%';
// Poll for status
let pollCount = 0;
const maxPolls = 300; // 5 minutes max (every 1 second)
const pollStatus = async () => {
try {
const statusResponse = await fetch(`/task/${taskId}`);
const status = await statusResponse.json();
if (status.data.status === 'completed') {
statusMessage.textContent = '处理完成!正在准备下载链接...';
progressFill.style.width = '100%';
submitBtn.textContent = '处理完成!';
submitBtn.disabled = false;
// Reload page to show new reports
setTimeout(() => {
window.location.reload();
}, 2000);
} else if (status.data.status === 'failed') {
statusMessage.textContent = `处理失败: ${status.data.error || '未知错误'}`;
progressFill.style.backgroundColor = '#dc3545';
progressFill.style.width = '100%';
submitBtn.textContent = '处理失败';
submitBtn.disabled = false;
} else {
// Still processing
statusMessage.textContent = status.data.message || '正在处理中...';
const progressPercent = Math.min(30 + (pollCount * 70 / maxPolls), 90);
progressFill.style.width = `${progressPercent}%`;
pollCount++;
if (pollCount < maxPolls) {
setTimeout(pollStatus, 1000);
} else {
statusMessage.textContent = '处理超时,请稍后手动检查状态';
submitBtn.textContent = '处理超时';
submitBtn.disabled = false;
}
}
} catch (error) {
console.error('Status check failed:', error);
statusMessage.textContent = '状态检查失败,请手动刷新页面查看结果';
submitBtn.textContent = '状态检查失败';
submitBtn.disabled = false;
}
};
// Start polling
setTimeout(pollStatus, 1000);
} catch (error) {
console.error('Upload failed:', error);
statusMessage.textContent = `上传失败: ${error.message}`;
progressFill.style.backgroundColor = '#dc3545';
progressFill.style.width = '100%';
submitBtn.textContent = '上传失败';
submitBtn.disabled = false;
}
});
</script>
</div>
</body>
</html>
''', reports=all_reports)

View File

@ -29,13 +29,14 @@ from datetime import datetime
import sys import sys
import os import os
from collections import Counter from collections import Counter
import yaml
try: try:
from tqdm import tqdm from tqdm import tqdm
HAS_TQDM = True HAS_TQDM = True
except ImportError: except ImportError:
HAS_TQDM = False HAS_TQDM = False
print("⚠️ 未安装tqdm库将不显示进度条。如需进度条请运行: pip install tqdm") print("WARNING: 未安装tqdm库将不显示进度条。如需进度条请运行: pip install tqdm")
def create_height_bins(heights, bin_size=2.0): def create_height_bins(heights, bin_size=2.0):
@ -82,7 +83,7 @@ def create_height_bins(heights, bin_size=2.0):
# 导入qiya模块 # 导入qiya模块
try: try:
from .qiya import get_pressure_at_location from .qiya import get_pressure_at_location
print("✅ 成功导入qiya模块")
except ImportError as e: except ImportError as e:
print(f"❌ 导入qiya模块失败: {e}") print(f"❌ 导入qiya模块失败: {e}")
print("请确保GasFlux包结构完整") print("请确保GasFlux包结构完整")
@ -104,13 +105,13 @@ def load_excel_data(file_path):
# 读取Excel文件 # 读取Excel文件
df = pd.read_excel(file_path) df = pd.read_excel(file_path)
print(f"✅ 成功读取数据:{len(df)} 行,{len(df.columns)} ") print(f"SUCCESS: Successfully loaded data: {len(df)} rows, {len(df.columns)} columns")
print(f"列名:{list(df.columns)}") print(f"列名:{list(df.columns)}")
return df return df
except Exception as e: except Exception as e:
print(f"❌ 读取文件失败: {e}") print(f"ERROR: Failed to read file: {e}")
sys.exit(1) sys.exit(1)
@ -132,11 +133,11 @@ def remove_columns(df, columns_to_remove):
missing_columns = [col for col in columns_to_remove if col not in df.columns] missing_columns = [col for col in columns_to_remove if col not in df.columns]
if missing_columns: if missing_columns:
print(f"⚠️ 以下列不存在(跳过): {missing_columns}") print(f"以下列不存在(跳过): {missing_columns}")
if existing_columns: if existing_columns:
df = df.drop(columns=existing_columns) df = df.drop(columns=existing_columns)
print(f"已删除 {len(existing_columns)}") print(f"已删除 {len(existing_columns)}")
return df return df
@ -158,7 +159,7 @@ def extract_hour_from_filename(filename):
if match: if match:
return match.group(1) return match.group(1)
else: else:
print(f"⚠️ 无法从文件名 '{filename}' 中提取小时信息,使用默认值 '00'") print(f"无法从文件名 '{filename}' 中提取小时信息,使用默认值 '00'")
return "00" return "00"
@ -181,7 +182,7 @@ def fix_time_column(df, filename):
# 检查时间列是否存在 # 检查时间列是否存在
if '时间' not in df.columns: if '时间' not in df.columns:
print("未找到 '时间'") print("未找到 '时间'")
return df return df
# 修正时间格式 # 修正时间格式
@ -231,18 +232,18 @@ def convert_coordinates(df):
""" """
print("转换经纬度坐标...") print("转换经纬度坐标...")
if '经度' in df.columns: if 'stGPSPositionX' in df.columns:
original_lon = df['经度'].head(3).tolist() original_lon = df['stGPSPositionX'].head(3).tolist()
df['经度'] = df['经度'] / 1e7 df['stGPSPositionX'] = df['stGPSPositionX'] / 1e7
converted_lon = df['经度'].head(3).tolist() converted_lon = df['stGPSPositionX'].head(3).tolist()
print("经度转换示例:") print("经度转换示例:")
for orig, conv in zip(original_lon, converted_lon): for orig, conv in zip(original_lon, converted_lon):
print(".6f") print(".6f")
if '纬度' in df.columns: if 'stGPSPositionY' in df.columns:
original_lat = df['纬度'].head(3).tolist() original_lat = df['stGPSPositionY'].head(3).tolist()
df['纬度'] = df['纬度'] / 1e7 df['stGPSPositionY'] = df['stGPSPositionY'] / 1e7
converted_lat = df['纬度'].head(3).tolist() converted_lat = df['stGPSPositionY'].head(3).tolist()
print("纬度转换示例:") print("纬度转换示例:")
for orig, conv in zip(original_lat, converted_lat): for orig, conv in zip(original_lat, converted_lat):
print(".6f") print(".6f")
@ -265,42 +266,54 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
""" """
print("计算气压数据...") print("计算气压数据...")
# 检查必要列是否存在 # 检查必要列是否存在(支持原始列名和新列名)
required_cols = ['日期', '时间', '经度', '纬度', '融合高程'] # 原始数据中的列名
original_cols = ['qStrDate', 'qStrTime', 'stGPSPositionX', 'stGPSPositionY', 'fAltitudeFused']
# 坐标转换后的列名经纬度已被除以1e7
converted_cols = ['qStrDate', 'qStrTime', 'stGPSPositionX', 'stGPSPositionY', 'fAltitudeFused']
# 优先使用转换后的列名(如果存在),否则使用原始列名
date_col = 'qStrDate' if 'qStrDate' in df.columns else '日期'
time_col = 'qStrTime' if 'qStrTime' in df.columns else '时间'
lon_col = 'stGPSPositionX' if 'stGPSPositionX' in df.columns else '经度'
lat_col = 'stGPSPositionY' if 'stGPSPositionY' in df.columns else '纬度'
height_col = 'fAltitudeFused' if 'fAltitudeFused' in df.columns else '融合高程'
required_cols = [date_col, time_col, lon_col, lat_col, height_col]
missing_cols = [col for col in required_cols if col not in df.columns] missing_cols = [col for col in required_cols if col not in df.columns]
if missing_cols: if missing_cols:
print(f"缺少必要列: {missing_cols}") print(f"缺少必要列: {missing_cols}")
return df return df
# 检查高度变化范围 # 检查高度变化范围
height_min = df['融合高程'].min() height_min = df[height_col].min()
height_max = df['融合高程'].max() height_max = df[height_col].max()
height_range = height_max - height_min height_range = height_max - height_min
print(f"🏔️ 高度范围: {height_min:.1f} - {height_max:.1f} 米 (变化: {height_range:.1f} 米)") print(f"高度范围: {height_min:.1f} - {height_max:.1f} 米 (变化: {height_range:.1f} 米)")
# 创建高度分档 # 创建高度分档
height_bins = create_height_bins(df['融合高程'], height_bin_size) height_bins = create_height_bins(df[height_col], height_bin_size)
print(f"📏 高度分档: {len(height_bins)} 个档位 (间隔: {height_bin_size:.1f} 米)") print(f"高度分档: {len(height_bins)} 个档位 (间隔: {height_bin_size:.1f} 米)")
for i, (bin_min, bin_max, bin_center, count) in enumerate(height_bins): 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}行)") print(f" 档位{i+1}: {bin_min:.1f}-{bin_max:.1f}m (中心: {bin_center:.1f}m, 数据: {count}行)")
# 决定计算策略 # 决定计算策略
if height_range <= height_tolerance: if height_range <= height_tolerance:
# 高度变化小,只计算一次气压 # 高度变化小,只计算一次气压
print("🎯 高度变化小,将使用平均高度计算一次气压") print("高度变化小,将使用平均高度计算一次气压")
use_single_calculation = True use_single_calculation = True
mean_height = df['融合高程'].mean() mean_height = df[height_col].mean()
print(f"📍 使用平均高度: {mean_height:.1f}") print(f"使用平均高度: {mean_height:.1f}")
elif len(height_bins) == 1: elif len(height_bins) == 1:
# 只有一个高度档位,使用档位中心高度 # 只有一个高度档位,使用档位中心高度
print("📦 只有一个高度档位,使用档位中心高度") print("只有一个高度档位,使用档位中心高度")
use_single_calculation = True use_single_calculation = True
mean_height = height_bins[0][2] # bin_center mean_height = height_bins[0][2] # bin_center
print(f"📍 使用档位中心高度: {mean_height:.1f}") print(f"使用档位中心高度: {mean_height:.1f}")
else: else:
# 高度变化大,使用分档计算 # 高度变化大,使用分档计算
print("🏗️ 使用高度分档策略减少API调用") print("使用高度分档策略减少API调用")
use_single_calculation = False use_single_calculation = False
# 确定要处理的行数 # 确定要处理的行数
@ -309,10 +322,10 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
sample_df = df.copy() sample_df = df.copy()
actual_samples = len(df) actual_samples = len(df)
if not use_single_calculation: if not use_single_calculation:
print(f"📊 将计算所有 {len(df)} 行的气压数据") print(f"将计算所有 {len(df)} 行的气压数据")
else: else:
# 限制采样数量 # 限制采样数量
print(f"⚠️ 数据量较大 ({len(df)} 行),只对前 {max_samples} 行计算气压") print(f"数据量较大 ({len(df)} 行),只对前 {max_samples} 行计算气压")
sample_df = df.head(max_samples).copy() sample_df = df.head(max_samples).copy()
actual_samples = max_samples actual_samples = max_samples
@ -325,11 +338,11 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
first_row = sample_df.iloc[0] first_row = sample_df.iloc[0]
# 转换日期格式 - 只提取日期部分,移除任何时间信息 # 转换日期格式 - 只提取日期部分,移除任何时间信息
date_str = str(first_row['日期']) date_str = str(first_row[date_col])
if ' ' in date_str: if ' ' in date_str:
date_str = date_str.split(' ')[0] date_str = date_str.split(' ')[0] # 处理 "2026-01-15 00:00:00" 格式
elif 'T' in date_str: elif 'T' in date_str:
date_str = date_str.split('T')[0] date_str = date_str.split('T')[0] # 处理ISO格式
if '/' in date_str: if '/' in date_str:
date_str = date_str.replace('/', '-') date_str = date_str.replace('/', '-')
@ -343,8 +356,15 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
# 使用数据的代表性时间(整点小时,众数) # 使用数据的代表性时间(整点小时,众数)
time_strings = [] time_strings = []
for time_val in sample_df['时间']: for time_val in sample_df[time_col]:
time_str = str(time_val).strip() time_str = str(time_val).strip()
# 处理时间字符串,提取正确的部分
# 如果时间字符串包含多个时间部分(如 "00:00:00 08:37:12"),取最后一个
if ' ' in time_str:
time_parts = time_str.split()
time_str = time_parts[-1] # 取最后一个有效的时间部分
if ':' in time_str: if ':' in time_str:
# 确保是有效的 HH:MM 格式,然后取整点小时 # 确保是有效的 HH:MM 格式,然后取整点小时
parts = time_str.split(':') parts = time_str.split(':')
@ -368,8 +388,8 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
print("正在计算平均气压...") print("正在计算平均气压...")
pressure = get_pressure_at_location( pressure = get_pressure_at_location(
lat=sample_df['纬度'].mean(), lat=sample_df[lat_col].mean(),
lon=sample_df['经度'].mean(), lon=sample_df[lon_col].mean(),
altitude=mean_height, altitude=mean_height,
date=formatted_date, date=formatted_date,
time=formatted_time time=formatted_time
@ -377,18 +397,18 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
if pressure is not None: if pressure is not None:
pressures = [pressure] * len(sample_df) pressures = [pressure] * len(sample_df)
print("平均气压计算成功,将应用到所有行") print("平均气压计算成功,将应用到所有行")
else: else:
print("平均气压计算失败") print("平均气压计算失败")
pressures = [None] * len(sample_df) pressures = [None] * len(sample_df)
except Exception as e: except Exception as e:
print(f"平均气压计算失败: {e}") print(f"平均气压计算失败: {e}")
pressures = [None] * len(sample_df) pressures = [None] * len(sample_df)
else: else:
# 使用高度分档策略 # 使用高度分档策略
print("🏗️ 开始分档计算气压...") print("开始分档计算气压...")
# 为每个高度档位计算气压 # 为每个高度档位计算气压
bin_pressures = {} # bin_center -> pressure bin_pressures = {} # bin_center -> pressure
@ -402,19 +422,19 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
try: try:
# 使用第一行数据作为代表来获取日期和时间 # 使用第一行数据作为代表来获取日期和时间
# 找到这个档位中的一行数据 # 找到这个档位中的一行数据
bin_rows = sample_df[(sample_df['融合高程'] >= bin_min) & bin_rows = sample_df[(sample_df[height_col] >= bin_min) &
(sample_df['融合高程'] <= bin_max)] (sample_df[height_col] <= bin_max)]
if len(bin_rows) == 0: if len(bin_rows) == 0:
continue continue
first_row = bin_rows.iloc[0] first_row = bin_rows.iloc[0]
# 转换日期格式 - 只提取日期部分,移除任何时间信息 # 转换日期格式 - 只提取日期部分,移除任何时间信息
date_str = str(first_row['日期']) date_str = str(first_row[date_col])
if ' ' in date_str: if ' ' in date_str:
date_str = date_str.split(' ')[0] date_str = date_str.split(' ')[0] # 处理 "2026-01-15 00:00:00" 格式
elif 'T' in date_str: elif 'T' in date_str:
date_str = date_str.split('T')[0] date_str = date_str.split('T')[0] # 处理ISO格式
if '/' in date_str: if '/' in date_str:
date_str = date_str.replace('/', '-') date_str = date_str.replace('/', '-')
@ -424,14 +444,21 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
year, month, day = date_parts year, month, day = date_parts
formatted_date = f"{year}-{month.zfill(2)}-{day.zfill(2)}" formatted_date = f"{year}-{month.zfill(2)}-{day.zfill(2)}"
else: else:
print(f"⚠️ 档位高度 {bin_center:.1f}m 日期格式异常: {date_str}") print(f"档位高度 {bin_center:.1f}m 日期格式异常: {date_str}")
bin_pressures[bin_center] = None bin_pressures[bin_center] = None
continue continue
# 使用该档位数据的代表性时间(整点小时) # 使用该档位数据的代表性时间(整点小时)
time_strings = [] time_strings = []
for time_val in bin_rows['时间']: for time_val in bin_rows[time_col]:
time_str = str(time_val).strip() time_str = str(time_val).strip()
# 处理时间字符串,提取正确的部分
# 如果时间字符串包含多个时间部分(如 "00:00:00 08:37:12"),取最后一个
if ' ' in time_str:
time_parts = time_str.split()
time_str = time_parts[-1] # 取最后一个有效的时间部分
if ':' in time_str: if ':' in time_str:
# 确保是有效的 HH:MM 格式,然后取整点小时 # 确保是有效的 HH:MM 格式,然后取整点小时
parts = time_str.split(':') parts = time_str.split(':')
@ -456,8 +483,8 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
print(" 无有效时间数据使用默认中午12:00") print(" 无有效时间数据使用默认中午12:00")
# 计算这个档位的气压(使用平均位置和档位中心高度) # 计算这个档位的气压(使用平均位置和档位中心高度)
avg_lat = bin_rows['纬度'].mean() avg_lat = bin_rows[lat_col].mean()
avg_lon = bin_rows['经度'].mean() avg_lon = bin_rows[lon_col].mean()
pressure = get_pressure_at_location( pressure = get_pressure_at_location(
lat=avg_lat, lat=avg_lat,
@ -475,14 +502,14 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
iterator.set_description(f"计算档位 (成功: {success_count}/{len(bin_pressures)})") iterator.set_description(f"计算档位 (成功: {success_count}/{len(bin_pressures)})")
except Exception as e: except Exception as e:
print(f"计算高度档位 {bin_center:.1f}m 气压失败: {e}") print(f"计算高度档位 {bin_center:.1f}m 气压失败: {e}")
bin_pressures[bin_center] = None bin_pressures[bin_center] = None
# 为每一行分配对应档位的气压 # 为每一行分配对应档位的气压
pressures = [] pressures = []
for idx, row in sample_df.iterrows(): for idx, row in sample_df.iterrows():
# 找到这个高度对应的档位 # 找到这个高度对应的档位
height = row['融合高程'] height = row[height_col]
assigned_pressure = None assigned_pressure = None
for bin_min, bin_max, bin_center, count in height_bins: for bin_min, bin_max, bin_center, count in height_bins:
@ -492,7 +519,7 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
pressures.append(assigned_pressure) pressures.append(assigned_pressure)
print(f"完成分档气压计算,共 {len(bin_pressures)} 个档位,{len([p for p in bin_pressures.values() if p is not None])} 个成功") print(f"完成分档气压计算,共 {len(bin_pressures)} 个档位,{len([p for p in bin_pressures.values() if p is not None])} 个成功")
# 添加气压列 # 添加气压列
df['pressure'] = None # 初始化 df['pressure'] = None # 初始化
@ -513,7 +540,7 @@ def calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_s
avg_pressure = sum(valid_pressures) / len(valid_pressures) avg_pressure = sum(valid_pressures) / len(valid_pressures)
print(f"成功计算 {len(valid_pressures)}/{actual_samples} 个气压值,平均值: {avg_pressure:.1f} hPa") print(f"成功计算 {len(valid_pressures)}/{actual_samples} 个气压值,平均值: {avg_pressure:.1f} hPa")
else: else:
print("⚠️ 未能计算出任何气压值") print("未能计算出任何气压值")
return df return df
@ -529,13 +556,13 @@ def adjust_altitude(df):
""" """
print("调整融合高程...") print("调整融合高程...")
if '融合高程' in df.columns: if 'fAltitudeFused' in df.columns:
min_altitude = df['融合高程'].min() min_altitude = df['fAltitudeFused'].min()
print(".2f") print(".2f")
original_alt = df['融合高程'].head(3).tolist() original_alt = df['fAltitudeFused'].head(3).tolist()
df['融合高程'] = df['融合高程'] - min_altitude df['fAltitudeFused'] = df['fAltitudeFused'] - min_altitude
adjusted_alt = df['融合高程'].head(3).tolist() adjusted_alt = df['fAltitudeFused'].head(3).tolist()
print("高度调整示例:") print("高度调整示例:")
for orig, adj in zip(original_alt, adjusted_alt): for orig, adj in zip(original_alt, adjusted_alt):
@ -546,7 +573,7 @@ def adjust_altitude(df):
def merge_timestamp(df): def merge_timestamp(df):
""" """
融合日期和时间列为时间戳 融合日期和时间列为时间戳(修正时间格式)
Args: Args:
df: 输入DataFrame df: 输入DataFrame
@ -554,57 +581,48 @@ def merge_timestamp(df):
Returns: Returns:
pd.DataFrame: 融合后的DataFrame pd.DataFrame: 融合后的DataFrame
""" """
print("融合日期和时间...") print("融合日期和时间(修正时间格式)...")
if '日期' in df.columns and '时间' in df.columns: if 'qStrDate' in df.columns and 'qStrTime' in df.columns:
timestamps = [] timestamps = []
for idx, row in df.iterrows(): for idx, row in df.iterrows():
try: try:
date_str = str(row['日期']) date_str = str(row['qStrDate']).strip()
time_str = str(row['时间']) time_str = str(row['qStrTime']).strip()
# 理日期字符串 - 移除任何时间部分 # 理日期字符串,提取纯日期部分
date_str = date_str.strip() # 如果日期字符串包含时间部分(如 "2026-01-15 00:00:00"),取日期部分
if ' ' in date_str: if ' ' in date_str:
date_str = date_str.split(' ')[0] # 只取日期部分 date_parts = date_str.split()
if 'T' in date_str: date_str = date_parts[0] # 取第一个部分作为日期
date_str = date_str.split('T')[0] # 处理ISO格式
# 标准化日期格式 # 处理时间字符串,提取正确的部分
if '/' in date_str: # 如果时间字符串包含多个时间部分(如 "00:00:00 08:37:12"),取最后一个
date_str = date_str.replace('/', '-') if ' ' in time_str:
time_parts = time_str.split()
# 取最后一个有效的时间部分
time_str = time_parts[-1]
# 确保日期格式正确 # 确保时间格式正确
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: if ':' in time_str and len(time_str.split(':')) >= 2:
time_formatted = time_str # 组合日期和修正后的时间
timestamp = f"{date_str} {time_str}"
else: else:
print(f"⚠️ 时间格式异常: '{time_str}',使用默认时间") timestamp = f"{date_str} 12:00:00" # 默认中午时间
time_formatted = "12:00:00" print(f" 时间格式异常 '{row['qStrTime']}',使用默认时间")
# 组合时间戳 - 直接连接日期和时间
timestamp = f"{date_formatted} {time_formatted}"
timestamps.append(timestamp) timestamps.append(timestamp)
except Exception as e: except Exception as e:
print(f"处理第 {idx+1} 行时间戳失败: {e}") print(f"处理第 {idx+1} 行时间戳失败: {e}")
timestamps.append(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") timestamps.append(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
df['timestamp'] = timestamps df['timestamp'] = timestamps
print("时间戳融合示例:") print("时间戳融合示例:")
for i in range(min(3, len(timestamps))): for i in range(min(3, len(timestamps))):
print(f" {df.loc[i, '日期']} + {df.loc[i, '时间']}{timestamps[i]}") print(f" {df.loc[i, 'qStrDate']} + {df.loc[i, 'qStrTime']}{timestamps[i]}")
return df return df
@ -623,83 +641,104 @@ def rename_columns(df):
# 定义字段映射 # 定义字段映射
column_mapping = { column_mapping = {
'timestamp': 'timestamp', # 时间戳(已创建) 'timestamp': 'timestamp', # 时间戳(已创建)
'经度': 'longitude', # 经度 → latitude 'stGPSPositionX': 'longitude', # 经度 → longitude
'纬度': 'latitude', # 纬度 → longitude 'stGPSPositionY': 'latitude', # 纬度 → latitude
'融合高程': 'height_ato', # 融合高程 → height_ato 'fAltitudeFused': 'height_ato', # 融合高程 → height_ato
'修正风向': 'winddir', # 修正风向 → winddir 'fFixedWindDirection': 'winddir', # 修正风向 → winddir
'修正风速': 'windspeed', # 修正风速 → windspeed 'fFixedWindSpeed': 'windspeed', # 修正风速 → windspeed
'风温': 'temperature', # 风温 → temperature 'fWindTemperature': 'temperature', # 风温 → temperature
'pressure': 'pressure', # 气压(已计算) 'CO2': 'CO2', # CO2浓度 → co2
'CH4': 'ch4', # CH4保持不变 'pitch': 'course_elevation', # pitch → course_elevation
'pitch': 'course_elevation', # pitch → course_elevation 'yaw': 'course_azimuth' # yaw → course_azimuth
'yaw': 'course_azimuth' # yaw → course_azimuth
} }
# 重命名存在的列 # 先复制字段,再对复制的字段重命名
columns_to_rename = {} columns_renamed = []
for old_name, new_name in column_mapping.items(): for old_name, new_name in column_mapping.items():
if old_name in df.columns: if old_name in df.columns:
columns_to_rename[old_name] = new_name # 复制字段到新名称
df[new_name] = df[old_name].copy()
columns_renamed.append((old_name, new_name))
print(f" 复制并重命名: {old_name}{new_name}")
if columns_to_rename: if columns_renamed:
df = df.rename(columns=columns_to_rename) print(f"共处理了 {len(columns_renamed)} 个字段")
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 return df
def process_excel_file(file_path): def ensure_float64_types(df, config=None):
"""
确保数值字段为float64类型以满足GasFlux处理要求
Args:
df: 输入DataFrame
config: 配置字典包含gases字段
Returns:
pd.DataFrame: 数据类型转换后的DataFrame
"""
print("确保数值字段类型为float64...")
# 定义基础需要转换为float64的字段
float64_columns = [
'longitude', 'latitude', 'height_ato', # 位置和高度
'winddir', 'windspeed', 'temperature', # 风和温度
'pressure', # 气压
'course_elevation', 'course_azimuth' # 姿态角
]
# 如果提供了配置添加gases中的气体列
if config and 'gases' in config:
gas_columns = list(config['gases'].keys())
float64_columns.extend(gas_columns)
print(f"从配置中添加气体列: {gas_columns}")
converted_count = 0
for col in float64_columns:
if col in df.columns:
try:
original_dtype = df[col].dtype
df[col] = df[col].astype('float64')
new_dtype = df[col].dtype
if original_dtype != new_dtype:
print(f" 转换: {col} ({original_dtype}{new_dtype})")
converted_count += 1
except Exception as e:
print(f" 转换失败: {col} - {e}")
if converted_count > 0:
print(f"共转换了 {converted_count} 个字段的数据类型为float64")
else:
print("所有数值字段已经是float64类型")
return df
def process_excel_file(file_path, config_path=None):
""" """
处理单个Excel文件的主函数 处理单个Excel文件的主函数
Args: Args:
file_path: Excel文件路径 file_path: Excel文件路径
config_path: 配置文件路径用于读取gases配置
""" """
print(f"=== 开始处理文件: {file_path} ===\n") print(f"=== 开始处理文件: {file_path} ===\n")
# 获取文件名(用于时间修正)
filename = Path(file_path).name
# 1. 读取数据 # 1. 读取数据
df = load_excel_data(file_path) df = load_excel_data(file_path)
# 2. 删除不需要的列 # 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) df = convert_coordinates(df)
# 5. 计算气压 # 4. 计算气压数据
df = calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_size=2.0) # 计算所有行高度容差10米分档2米 df = calculate_pressure(df, max_samples=None, height_tolerance=10.0, height_bin_size=2.0) # 计算所有行高度容差10米分档2米
# 6. 高度调整 # 5. 高度调整
df = adjust_altitude(df) df = adjust_altitude(df)
# 7. 时间戳融合 # 6. 时间戳融合(保持原有时间格式)
df = merge_timestamp(df) df = merge_timestamp(df)
# 调试:检查当前列 # 调试:检查当前列
@ -707,28 +746,41 @@ def process_excel_file(file_path):
if 'timestamp' in df.columns: if 'timestamp' in df.columns:
print(f"timestamp列示例: {df['timestamp'].head(3).tolist()}") print(f"timestamp列示例: {df['timestamp'].head(3).tolist()}")
# 8. 字段重命名 # 7. 字段重命名
df = rename_columns(df) df = rename_columns(df)
# 8. 确保数值字段类型为float64
# 读取配置以获取gases字段
config = None
if config_path:
try:
with open(config_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
except Exception as e:
print(f"读取配置文件失败: {e}")
df = ensure_float64_types(df, config)
# 保存处理结果 # 保存处理结果
output_path = Path(file_path).with_suffix('.processed.csv') output_path = Path(file_path).with_suffix('.processed.csv')
df.to_csv(output_path, index=False) df.to_csv(output_path, index=False, encoding='utf-8-sig')
print(f"\n处理完成!") print(f"\n处理完成!")
print(f"📁 输出文件: {output_path}") print(f"输出文件: {output_path}")
print(f"📊 最终数据形状: {df.shape[0]}× {df.shape[1]}") print(f"最终数据形状: {df.shape[0]}× {df.shape[1]}")
print(f"📋 最终列名: {list(df.columns)}") print(f"最终列名: {list(df.columns)}")
return df return df
def process_file(input_file, output_file=None): def process_file(input_file, output_file=None, config_file=None):
""" """
直接处理Excel文件的函数不使用命令行参数 直接处理Excel文件的函数不使用命令行参数
Args: Args:
input_file: 输入Excel文件路径字符串或Path对象 input_file: 输入Excel文件路径字符串或Path对象
output_file: 输出CSV文件路径可选字符串或Path对象 output_file: 输出CSV文件路径可选字符串或Path对象
config_file: 配置文件路径可选用于读取gases配置
Returns: Returns:
pd.DataFrame: 处理后的DataFrame pd.DataFrame: 处理后的DataFrame
@ -744,13 +796,13 @@ def process_file(input_file, output_file=None):
raise ValueError(f"输入文件必须是Excel格式 (.xlsx 或 .xls),当前文件: {input_path}") raise ValueError(f"输入文件必须是Excel格式 (.xlsx 或 .xls),当前文件: {input_path}")
# 处理文件 # 处理文件
df = process_excel_file(str(input_path)) df = process_excel_file(str(input_path), config_file)
# 如果指定了输出路径,额外保存一份 # 如果指定了输出路径,额外保存一份
if output_file: if output_file:
output_path = Path(output_file) output_path = Path(output_file)
df.to_csv(output_path, index=False) df.to_csv(output_path, index=False, encoding='utf-8-sig')
print(f"📁 额外保存到: {output_path}") print(f"额外保存到: {output_path}")
return df return df
@ -769,17 +821,17 @@ def interactive_input():
while True: while True:
input_file = input("请输入Excel文件路径 (例如: data.xlsx): ").strip() input_file = input("请输入Excel文件路径 (例如: data.xlsx): ").strip()
if not input_file: if not input_file:
print("文件路径不能为空,请重新输入") print("文件路径不能为空,请重新输入")
continue continue
input_path = Path(input_file) input_path = Path(input_file)
if not input_path.exists(): if not input_path.exists():
print(f"文件不存在: {input_path}") print(f"文件不存在: {input_path}")
print("提示: 请确保文件路径正确,或者将文件放在当前目录下") print("提示: 请确保文件路径正确,或者将文件放在当前目录下")
continue continue
if input_path.suffix.lower() not in ['.xlsx', '.xls']: if input_path.suffix.lower() not in ['.xlsx', '.xls']:
print(f"文件格式错误: {input_path.suffix}") print(f"文件格式错误: {input_path.suffix}")
print("只支持 .xlsx 和 .xls 格式的Excel文件") print("只支持 .xlsx 和 .xls 格式的Excel文件")
continue continue
@ -791,13 +843,13 @@ def interactive_input():
output_file = None output_file = None
print("使用默认输出文件名") print("使用默认输出文件名")
print(f"\n输入确认:") print(f"\n输入确认:")
print(f" 输入文件: {input_file}") print(f" 输入文件: {input_file}")
print(f" 输出文件: {output_file or '自动生成'}") print(f" 输出文件: {output_file or '自动生成'}")
confirm = input("\n确认开始处理? (y/N): ").strip().lower() confirm = input("\n确认开始处理? (y/N): ").strip().lower()
if confirm not in ['y', 'yes', '', '确认']: if confirm not in ['y', 'yes', '', '确认']:
print("用户取消操作") print("用户取消操作")
return None, None return None, None
return input_file, output_file return input_file, output_file
@ -823,7 +875,7 @@ def main(input_file=None, output_file=None, interactive=False):
try: try:
return process_file(input_file, output_file) return process_file(input_file, output_file)
except Exception as e: except Exception as e:
print(f"处理失败: {e}") print(f"处理失败: {e}")
raise raise
# 否则使用命令行参数 # 否则使用命令行参数
@ -881,7 +933,7 @@ def main(input_file=None, output_file=None, interactive=False):
if not input_file: if not input_file:
parser.print_help() parser.print_help()
print("\n" + "="*60) print("\n" + "="*60)
print("📖 使用示例:") print("使用示例:")
print("="*60) print("="*60)
print("1. 命令行模式:") print("1. 命令行模式:")
print(" python data_processor.py your_file.xlsx") print(" python data_processor.py your_file.xlsx")
@ -900,11 +952,11 @@ def main(input_file=None, output_file=None, interactive=False):
# 检查输入文件 # 检查输入文件
input_path = Path(input_file) input_path = Path(input_file)
if not input_path.exists(): if not input_path.exists():
print(f"错误:输入文件不存在: {input_path}") print(f"错误:输入文件不存在: {input_path}")
sys.exit(1) sys.exit(1)
if input_path.suffix.lower() not in ['.xlsx', '.xls']: if input_path.suffix.lower() not in ['.xlsx', '.xls']:
print(f"错误输入文件必须是Excel格式 (.xlsx 或 .xls)") print(f"错误输入文件必须是Excel格式 (.xlsx 或 .xls)")
sys.exit(1) sys.exit(1)
# 处理文件 # 处理文件
@ -914,16 +966,16 @@ def main(input_file=None, output_file=None, interactive=False):
# 如果指定了输出路径,额外保存一份 # 如果指定了输出路径,额外保存一份
if output_file: if output_file:
output_path = Path(output_file) output_path = Path(output_file)
df.to_csv(output_path, index=False) df.to_csv(output_path, index=False, encoding='utf-8-sig')
print(f"📁 额外保存到: {output_path}") print(f"额外保存到: {output_path}")
return df return df
except KeyboardInterrupt: except KeyboardInterrupt:
print("\n⚠️ 用户中断处理") print("\n用户中断处理")
sys.exit(1) sys.exit(1)
except Exception as e: except Exception as e:
print(f"\n处理失败: {e}") print(f"\n处理失败: {e}")
import traceback import traceback
traceback.print_exc() traceback.print_exc()
sys.exit(1) sys.exit(1)

View File

@ -192,8 +192,13 @@ class SpiralSpatialProcessingStrategy(SpatialProcessingStrategy):
self.data_processor.circle_center_x, self.data_processor.circle_center_x,
self.data_processor.circle_center_y, self.data_processor.circle_center_y,
) = processing.circle_deviation(self.data_processor.df, x_col="utm_easting", y_col="utm_northing") ) = processing.circle_deviation(self.data_processor.df, x_col="utm_easting", y_col="utm_northing")
# 使用配置中第一个气体的归一化列名
primary_gas = self.data_processor.gases[0]
y_col = f"{primary_gas}_normalised"
self.data_processor.df = processing.recentre_azimuth( self.data_processor.df = processing.recentre_azimuth(
self.data_processor.df, r=self.data_processor.circle_radius self.data_processor.df, r=self.data_processor.circle_radius, y=y_col
) )
self.data_processor.df["x"] = self.data_processor.df["circumference_distance"] self.data_processor.df["x"] = self.data_processor.df["circumference_distance"]
for gas_name in self.data_processor.gases: for gas_name in self.data_processor.gases:
@ -304,10 +309,11 @@ class DataProcessor:
].std() ].std()
def process_main(data_file: Path, config_file: Path) -> None: def process_main(data_file: Path, config_file: Path, task_id: str | None = None) -> None:
"""Main function to run the pipeline.""" """Main function to run the pipeline."""
config = load_config(config_file) config = load_config(config_file)
name = data_file.stem # 优先使用 task_id否则退回文件 stem
name = task_id if task_id else data_file.stem
df = read_csv(data_file) df = read_csv(data_file)
processor = DataProcessor(config, df) processor = DataProcessor(config, df)

View File

@ -66,47 +66,52 @@ def generate_reports(name: str, processor, config: dict):
Generates reports, configuration files, and processed output variables for gasflux processing runs. Generates reports, configuration files, and processed output variables for gasflux processing runs.
Parameters: Parameters:
name (str): The name identifier for the current processing run. name (str): The name identifier for the current processing run (task_id).
processor (object): The processing object containing report data and output variables. processor (object): The processing object containing report data and output variables.
config (dict): Configuration dictionary used for processing. config (dict): Configuration dictionary used for processing.
""" """
output_dir = Path(config["output_dir"]).expanduser() output_dir = Path(config["output_dir"]).expanduser()
processing_time = datetime.now() processing_time = datetime.now()
output_path = output_dir / name / processing_time.strftime("%Y-%m-%d_%H-%M-%S-%f_processing_run") # Save directly to outputs/{task_id} directory
output_path = output_dir / "outputs" / name
output_path.mkdir(parents=True, exist_ok=True) output_path.mkdir(parents=True, exist_ok=True)
# Save reports # Save reports
for gas, report in processor.reports.items(): for gas, report in processor.reports.items():
report_path = output_path / f"{name}_{gas}_report.html" timestamp_str = processing_time.strftime("%Y%m%d_%H%M%S")
report_path = output_path / f"{gas}_report_{timestamp_str}.html"
with open(report_path, "w", encoding="utf-8") as file: with open(report_path, "w", encoding="utf-8") as file:
file.write(report) file.write(report)
# Save config # Save config
header = f"# Gasflux output config for file {name} from processing run at {processing_time}\n" header = f"# Gasflux output config for task {name} from processing run at {processing_time}\n"
config_path = output_path / f"{name}_config.yaml" timestamp_str = processing_time.strftime("%Y%m%d_%H%M%S")
config_path = output_path / f"config_{timestamp_str}.yaml"
with open(config_path, "w") as file: with open(config_path, "w") as file:
file.write(header) file.write(header)
yaml.safe_dump(config, file) yaml.safe_dump(config, file)
# Save DataFrame to CSV # Save DataFrame to Excel
if hasattr(processor, 'df') and processor.df is not None: if hasattr(processor, 'df') and processor.df is not None:
csv_path = output_path / f"{name}_data.csv" timestamp_str = processing_time.strftime("%Y%m%d_%H%M%S")
processor.df.to_csv(csv_path, index=False) excel_path = output_path / f"processed_data_{timestamp_str}.xlsx"
logger.info(f"DataFrame saved to {csv_path}") processor.df.to_excel(excel_path, index=False, engine='openpyxl')
logger.info(f"DataFrame saved to {excel_path}")
# Save output variables # Save output variables
output_vars = processor.output_vars output_vars = processor.output_vars
# output_vars = delete_large_arrays(output_vars, threshold_size=50) # output_vars = delete_large_arrays(output_vars, threshold_size=50)
header = ( header = (
f"# Gasflux output variables for file {name} from processing run at {processing_time}\n" f"# Gasflux output variables for task {name} from processing run at {processing_time}\n"
) )
filename = output_path / f"{name}_output_vars.json" timestamp_str = processing_time.strftime("%Y%m%d_%H%M%S")
filename = output_path / f"output_vars_{timestamp_str}.json"
with open(filename, "w") as file: with open(filename, "w") as file:
file.write(header) file.write(header)
json.dump( json.dump(
output_vars, file, default=lambda item: item.tolist() if isinstance(item, np.ndarray) else item, indent=4 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}") logger.info(f"Task {name} results saved to {output_path}")
def delete_large_arrays(output_vars: dict, threshold_size: int) -> dict: def delete_large_arrays(output_vars: dict, threshold_size: int) -> dict:

View File

@ -81,7 +81,7 @@ def main():
if args.output: if args.output:
processed_csv = Path(args.output) processed_csv = Path(args.output)
else: else:
processed_csv = input_path.with_suffix('.processed.csv') processed_csv = input_path.with_suffix('_processed.csv')
# 确定配置文件 # 确定配置文件
if args.config: if args.config:
@ -98,7 +98,7 @@ def main():
try: try:
# 第一步:数据预处理 # 第一步:数据预处理
print("🔄 第一步:数据预处理...") print("🔄 第一步:数据预处理...")
processed_df = process_file(str(input_path), str(processed_csv)) processed_df = process_file(str(input_path), str(processed_csv), str(config_file))
print(f"✅ 数据预处理完成,输出文件: {processed_csv}") print(f"✅ 数据预处理完成,输出文件: {processed_csv}")
print() print()

704
src/gasflux/shared.py Normal file
View File

@ -0,0 +1,704 @@
"""
Shared utilities and constants for GasFlux API.
This module contains shared functions and variables to avoid circular imports.
"""
import time
import logging
from functools import wraps
from flask import request, current_app, g
from pathlib import Path
import threading
# Task status constants
TASK_STATUS_PENDING = "pending"
TASK_STATUS_PROCESSING = "processing"
TASK_STATUS_COMPLETED = "completed"
TASK_STATUS_FAILED = "failed"
# Global task status storage
task_status = {}
# Task status persistence file override (set by app on startup)
_TASK_STATUS_FILE_PATH: Path | None = None
_TASK_STATUS_FILE_LOCK = threading.Lock()
def set_task_status_file_path(path: str | Path):
"""Set the task status persistence file path (used across threads without Flask app context)."""
global _TASK_STATUS_FILE_PATH
_TASK_STATUS_FILE_PATH = Path(path)
def _build_simple_downloads_from_results(results: list[dict]) -> dict:
"""Build direct download shortcuts for common files (minimal, frontend-friendly)."""
downloads: dict = {}
def set_once(key: str, url: str):
if key not in downloads and url:
downloads[key] = url
for item in results or []:
if not isinstance(item, dict):
continue
rel_path = item.get('rel_path')
if not rel_path:
continue
name_l = (item.get('name') or '').lower()
url = f"/download/{rel_path}"
if name_l.endswith('.xlsx'):
set_once('data_xlsx', url)
elif name_l.endswith('.xls'):
set_once('data_xls', url)
elif name_l.endswith('ch4_report.html'):
set_once('report_ch4', url)
elif name_l.endswith('co2_report.html'):
set_once('report_co2', url)
elif name_l.endswith(('.yaml', '.yml')):
set_once('config', url)
elif name_l.endswith('.json') and 'output_vars' in name_l:
set_once('metadata', url)
elif name_l.endswith('.html'):
set_once('report_html', url)
return downloads
# File extension constants
ALLOWED_DATA_EXTENSIONS = {'xlsx', 'xls'}
ALLOWED_CONFIG_EXTENSIONS = {'yaml', 'yml'}
# Statistics collector
class StatisticsCollector:
"""Collects and manages API statistics."""
def __init__(self):
self.start_time = time.time()
self.stats = {
'requests': {
'total': 0,
'by_method': {},
'by_endpoint': {},
'by_status': {},
'response_times': [],
'errors': 0
},
'tasks': {
'total_created': 0,
'total_completed': 0,
'total_failed': 0,
'by_status': {
'pending': 0,
'processing': 0,
'completed': 0,
'failed': 0
},
'processing_times': []
},
'performance': {
'avg_response_time': 0,
'max_response_time': 0,
'min_response_time': float('inf'),
'uptime_seconds': time.time() - self.start_time
}
}
def record_request(self, method, endpoint, status_code, response_time):
"""Record an API request."""
self.stats['requests']['total'] += 1
# Method stats
if method not in self.stats['requests']['by_method']:
self.stats['requests']['by_method'][method] = 0
self.stats['requests']['by_method'][method] += 1
# Endpoint stats
if endpoint not in self.stats['requests']['by_endpoint']:
self.stats['requests']['by_endpoint'][endpoint] = 0
self.stats['requests']['by_endpoint'][endpoint] += 1
# Status stats
status_category = str(status_code // 100 * 100) # 200, 400, 500, etc.
if status_category not in self.stats['requests']['by_status']:
self.stats['requests']['by_status'][status_category] = 0
self.stats['requests']['by_status'][status_category] += 1
# Response time stats
self.stats['requests']['response_times'].append(response_time)
# Keep only last 1000 response times for memory efficiency
if len(self.stats['requests']['response_times']) > 1000:
self.stats['requests']['response_times'] = self.stats['requests']['response_times'][-1000:]
# Error tracking
if status_code >= 400:
self.stats['requests']['errors'] += 1
# Update performance stats
self._update_performance_stats()
def record_task_status_change(self, old_status, new_status):
"""Record task status changes."""
if old_status == "unknown": # New task
self.stats['tasks']['total_created'] += 1
if new_status == TASK_STATUS_COMPLETED:
self.stats['tasks']['total_completed'] += 1
self.stats['tasks']['by_status']['completed'] += 1
elif new_status == TASK_STATUS_FAILED:
self.stats['tasks']['total_failed'] += 1
self.stats['tasks']['by_status']['failed'] += 1
elif new_status == TASK_STATUS_PROCESSING:
self.stats['tasks']['by_status']['processing'] += 1
elif new_status == TASK_STATUS_PENDING:
self.stats['tasks']['by_status']['pending'] += 1
def record_task_completion_time(self, completion_time):
"""Record task completion time."""
self.stats['tasks']['processing_times'].append(completion_time)
def reset_stats(self):
"""Reset all statistics."""
current_time = time.time()
self.start_time = current_time
self.stats = {
'requests': {
'total': 0,
'by_method': {},
'by_endpoint': {},
'by_status': {},
'response_times': [],
'errors': 0
},
'tasks': {
'total_created': 0,
'total_completed': 0,
'total_failed': 0,
'by_status': {
'pending': 0,
'processing': 0,
'completed': 0,
'failed': 0
},
'processing_times': []
},
'performance': {
'avg_response_time': 0,
'max_response_time': 0,
'min_response_time': float('inf'),
'uptime_seconds': current_time - self.start_time
}
}
def _update_performance_stats(self):
"""Update performance statistics."""
response_times = self.stats['requests']['response_times']
if response_times:
self.stats['performance']['avg_response_time'] = sum(response_times) / len(response_times)
self.stats['performance']['max_response_time'] = max(response_times)
self.stats['performance']['min_response_time'] = min(response_times)
self.stats['performance']['uptime_seconds'] = time.time() - self.start_time
def get_summary(self):
"""Get a summary of current statistics."""
current_time = time.time()
uptime = current_time - self.start_time
# Calculate rates
requests_per_second = self.stats['requests']['total'] / max(uptime, 1)
error_rate = (self.stats['requests']['errors'] / max(self.stats['requests']['total'], 1)) * 100
# Task completion rate
total_tasks_processed = self.stats['tasks']['total_completed'] + self.stats['tasks']['total_failed']
task_success_rate = (self.stats['tasks']['total_completed'] / max(total_tasks_processed, 1)) * 100
return {
'summary': {
'uptime_seconds': uptime,
'uptime_formatted': self._format_uptime(uptime),
'requests_total': self.stats['requests']['total'],
'requests_per_second': round(requests_per_second, 2),
'error_rate_percent': round(error_rate, 2),
'active_tasks': len([t for t in task_status.values()
if t.get('status') in [TASK_STATUS_PENDING, TASK_STATUS_PROCESSING]])
},
'requests': {
'by_method': self.stats['requests']['by_method'],
'by_status': self.stats['requests']['by_status'],
'top_endpoints': dict(sorted(self.stats['requests']['by_endpoint'].items(),
key=lambda x: x[1], reverse=True)[:10])
},
'tasks': {
'total_created': self.stats['tasks']['total_created'],
'total_completed': self.stats['tasks']['total_completed'],
'total_failed': self.stats['tasks']['total_failed'],
'success_rate_percent': round(task_success_rate, 2),
'by_status': self.stats['tasks']['by_status']
},
'performance': {
'avg_response_time_ms': round(self.stats['performance']['avg_response_time'] * 1000, 2),
'max_response_time_ms': round(self.stats['performance']['max_response_time'] * 1000, 2),
'min_response_time_ms': round(self.stats['performance']['min_response_time'] * 1000, 2)
if self.stats['performance']['min_response_time'] != float('inf') else 0
}
}
def _format_uptime(self, seconds):
"""Format uptime in human readable format."""
days, remainder = divmod(int(seconds), 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
parts = []
if days > 0:
parts.append(f"{days}d")
if hours > 0:
parts.append(f"{hours}h")
if minutes > 0:
parts.append(f"{minutes}m")
parts.append(f"{seconds}s")
return " ".join(parts)
# Create global statistics collector instance
stats_collector = StatisticsCollector()
# Shared utility functions
def log_performance(func):
"""Decorator to log function performance."""
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
try:
result = func(*args, **kwargs)
duration = time.time() - start_time
logger.debug(f"PERF: {func.__name__} completed in {duration:.3f}s")
return result
except Exception as e:
duration = time.time() - start_time
logger.error(f"PERF: {func.__name__} failed after {duration:.3f}s - Error: {str(e)}")
raise
return wrapper
def log_request_info():
"""Log incoming request information."""
if hasattr(request, 'remote_addr'):
logger.info(f"REQUEST: {request.method} {request.url} - IP: {request.remote_addr} - User-Agent: {request.headers.get('User-Agent', 'Unknown')}")
def log_response_info(response):
"""Log outgoing response information."""
if hasattr(request, 'url_rule') and request.url_rule:
endpoint = request.url_rule.rule
else:
endpoint = request.path
start_time = getattr(g, 'start_time', None)
if start_time:
duration = time.time() - start_time
logger.info(f"RESPONSE: {request.method} {endpoint} - Status: {response.status_code} - Duration: {duration:.3f}s" if duration else f"RESPONSE: {request.method} {endpoint} - Status: {response.status_code}")
def update_task_status(task_id, status, message=None, results=None, error=None):
"""Update task status in the global dictionary."""
timestamp = time.time()
old_status = task_status.get(task_id, {}).get("status", "unknown")
task_status[task_id] = {
"status": status,
"message": message,
"results": results,
"error": error,
"updated_at": timestamp,
"created_at": task_status.get(task_id, {}).get("created_at", timestamp)
}
# Record status change in statistics
stats_collector.record_task_status_change(old_status, status)
# Log detailed status change with context
log_msg = f"Task {task_id} status changed: {old_status} -> {status}"
if message:
log_msg += f" | Message: {message}"
if results:
log_msg += f" | Results count: {len(results) if isinstance(results, list) else 'N/A'}"
if error:
log_msg += f" | Error: {error}"
log_level = logging.ERROR if status == TASK_STATUS_FAILED else logging.INFO
logger.log(log_level, log_msg)
# Save task status to file for persistence
logger.debug(f"Saving task {task_id} status '{status}' to persistent storage")
save_task_status_to_file()
def get_task_status(task_id):
"""Get task status from global dictionary."""
if task_id in task_status:
return task_status[task_id]
return {"status": "not_found"}
def cleanup_old_tasks():
"""Clean up old completed tasks to prevent memory leak."""
current_time = time.time()
max_age = 24 * 3600 # 24 hours
to_remove = []
for task_id, task_info in task_status.items():
task_age = current_time - task_info.get("updated_at", 0)
if task_age > max_age:
to_remove.append(task_id)
logger.info(f"Task {task_id} scheduled for cleanup (age: {task_age:.1f}s, status: {task_info.get('status')})")
initial_count = len(task_status)
for task_id in to_remove:
del task_status[task_id]
if to_remove:
logger.info(f"Cleanup completed: removed {len(to_remove)} tasks, {len(task_status)} tasks remaining")
else:
logger.debug(f"Cleanup check: no old tasks to remove ({len(task_status)} active tasks)")
def get_task_list(status_filter=None, page=1, page_size=20, sort_by='updated_at', sort_order='desc', cleanup=True):
"""
Get paginated list of tasks with optional filtering and sorting.
Args:
status_filter (str or list): Filter by task status. Can be single status or list of statuses.
page (int): Page number (1-based).
page_size (int): Number of tasks per page.
sort_by (str): Sort field ('created_at', 'updated_at', 'status').
sort_order (str): Sort order ('asc' or 'desc').
cleanup (bool): Whether to cleanup old tasks before returning list.
Returns:
dict: {
'tasks': list of task summaries,
'total': total number of tasks,
'page': current page,
'page_size': page size,
'total_pages': total pages,
'has_next': has next page,
'has_prev': has previous page
}
"""
if cleanup:
cleanup_old_tasks() # Clean up old tasks before returning list
# Filter tasks
filtered_tasks = []
for task_id, task_info in task_status.items():
if status_filter:
if isinstance(status_filter, str):
if task_info.get('status') != status_filter:
continue
elif isinstance(status_filter, list):
if task_info.get('status') not in status_filter:
continue
filtered_tasks.append((task_id, task_info))
# Sort tasks
def safe_numeric_sort(value):
"""Safely convert value to numeric for sorting."""
try:
if isinstance(value, (int, float)):
return value
elif isinstance(value, str):
# Try to convert string timestamp to float
return float(value)
else:
return 0
except (ValueError, TypeError):
return 0
reverse_order = sort_order.lower() == 'desc'
if sort_by == 'created_at':
filtered_tasks.sort(key=lambda x: safe_numeric_sort(x[1].get('created_at', 0)), reverse=reverse_order)
elif sort_by == 'updated_at':
filtered_tasks.sort(key=lambda x: safe_numeric_sort(x[1].get('updated_at', 0)), reverse=reverse_order)
elif sort_by == 'status':
filtered_tasks.sort(key=lambda x: x[1].get('status', ''), reverse=reverse_order)
else:
# Default sort by updated_at desc
filtered_tasks.sort(key=lambda x: safe_numeric_sort(x[1].get('updated_at', 0)), reverse=True)
# Paginate
total_tasks = len(filtered_tasks)
total_pages = (total_tasks + page_size - 1) // page_size
start_idx = (page - 1) * page_size
end_idx = start_idx + page_size
paginated_tasks = filtered_tasks[start_idx:end_idx]
# Format task summaries
task_summaries = []
for task_id, task_info in paginated_tasks:
summary = {
'task_id': task_id,
'status': task_info.get('status'),
'message': task_info.get('message'),
'created_at': task_info.get('created_at'),
'updated_at': task_info.get('updated_at'),
'has_results': bool(task_info.get('results')),
'has_error': bool(task_info.get('error'))
}
task_summaries.append(summary)
return {
'tasks': task_summaries,
'total': total_tasks,
'page': page,
'page_size': page_size,
'total_pages': total_pages,
'has_next': page < total_pages,
'has_prev': page > 1
}
def get_task_pool_stats():
"""
Get task pool statistics.
Returns:
dict: Task pool statistics including counts by status.
"""
# Note: cleanup_old_tasks() is disabled for task pool stats
# to preserve historical task data for management purposes
# cleanup_old_tasks() # Clean up old tasks before calculating stats
stats = {
'total_tasks': len(task_status),
'status_counts': {},
'active_tasks': 0,
'queued_tasks': 0,
'completed_tasks': 0,
'failed_tasks': 0
}
for task_info in task_status.values():
status = task_info.get('status')
if status:
stats['status_counts'][status] = stats['status_counts'].get(status, 0) + 1
if status == TASK_STATUS_PROCESSING:
stats['active_tasks'] += 1
elif status == TASK_STATUS_PENDING:
stats['queued_tasks'] += 1
elif status == TASK_STATUS_COMPLETED:
stats['completed_tasks'] += 1
elif status == TASK_STATUS_FAILED:
stats['failed_tasks'] += 1
return stats
def _get_status_file():
"""Get the task status file path, preferring OUTPUT_FOLDER for reliability."""
if _TASK_STATUS_FILE_PATH is not None:
return _TASK_STATUS_FILE_PATH
try:
# Prefer OUTPUT_FOLDER which is more reliable and writable
from flask import current_app
output_dir = current_app.config.get('OUTPUT_FOLDER')
if output_dir:
return Path(output_dir) / "task_status.json"
except Exception:
pass
# Fall back to module directory (for development)
return Path(__file__).parent / "task_status.json"
def _to_json_safe(obj):
"""Convert numpy types and other non-JSON-serializable objects to JSON-safe types."""
# Preserve JSON-native types
if obj is None or isinstance(obj, (str, int, float, bool)):
return obj
# Recursively handle containers
if isinstance(obj, list):
return [_to_json_safe(v) for v in obj]
if isinstance(obj, tuple):
return [_to_json_safe(v) for v in obj]
if isinstance(obj, dict):
return {str(k): _to_json_safe(v) for k, v in obj.items()}
try:
import numpy as np
if isinstance(obj, (np.integer,)):
return int(obj)
if isinstance(obj, (np.floating,)):
return float(obj)
if isinstance(obj, (np.bool_,)):
return bool(obj)
if isinstance(obj, (np.ndarray,)):
return obj.tolist()
except Exception:
pass
# Non-builtin/unknown types, fall back to string representation
try:
return str(obj)
except Exception:
return None
def save_task_status_to_file():
"""Save current task status to JSON file for persistence."""
try:
import json
import os
from pathlib import Path
status_file = _get_status_file()
logger.debug(f"Attempting to save {len(task_status)} task statuses to {status_file}")
# Guard: 避免用空内存覆盖已有文件
if not task_status and status_file.exists():
logger.info("Skipping task status save: empty in-memory status and file already exists")
return
# Ensure only one thread writes the status file at a time (prevents Windows replace/lock issues)
with _TASK_STATUS_FILE_LOCK:
status_to_save = {}
for task_id, task_info in task_status.items():
try:
clean_info = {}
for k, v in task_info.items():
if k == 'results' and isinstance(v, list):
# Keep only metadata for results, remove potentially large data fields
cleaned_results = []
for item in v:
if isinstance(item, dict):
cleaned_item = {kk: vv for kk, vv in item.items() if kk not in ['data', 'arrays']}
# Normalize result metadata for persistence
name = cleaned_item.get('name') or ''
rel_path = cleaned_item.get('rel_path') or ''
# Normalize size to int
size = cleaned_item.get('size', 0)
try:
size = int(size)
except Exception:
size = 0
cleaned_item['size'] = size
# Infer/normalize type if missing or unknown
t = cleaned_item.get('type')
if (not t) or (t == 'unknown'):
t = _get_file_type(name or rel_path)
cleaned_item['type'] = t
# Convert numpy types / other objects to JSON-safe
for kk, vv in list(cleaned_item.items()):
cleaned_item[kk] = _to_json_safe(vv)
cleaned_results.append(cleaned_item)
clean_info['results'] = cleaned_results
# Slim persistence: store only direct downloads for frontend
clean_info['downloads'] = _build_simple_downloads_from_results(cleaned_results)
# Ensure each result has a download_url (optional but handy)
for r in clean_info['results']:
if isinstance(r, dict) and r.get('rel_path') and not r.get('download_url'):
r['download_url'] = f"/download/{r['rel_path']}"
else:
clean_info[k] = _to_json_safe(v)
status_to_save[task_id] = clean_info
logger.debug(f"Processed task {task_id} with status {clean_info.get('status')}")
except Exception as task_e:
logger.warning(f"Failed to process task {task_id}: {task_e}")
# Skip this task but continue with others
continue
# Ensure the directory exists
status_file.parent.mkdir(parents=True, exist_ok=True)
# Write to a unique temporary file first, then rename for atomicity with fsync
temp_file = status_file.with_suffix(f'.{os.getpid()}.tmp')
with open(temp_file, 'w', encoding='utf-8') as f:
json.dump(status_to_save, f, indent=2, ensure_ascii=False)
f.flush()
os.fsync(f.fileno()) # Force write to disk
# Atomic rename
temp_file.replace(status_file)
logger.info(f"Successfully saved {len(status_to_save)} task statuses to {status_file}")
except Exception as e:
logger.error(f"Failed to save task status to file: {e}", exc_info=True)
def load_task_status_from_file():
"""Load task status from JSON file on startup."""
try:
import json
status_file = _get_status_file()
if not status_file.exists():
logger.info("No task status file found, starting with empty task pool")
return
# Ensure no writer thread is updating the file while we read it
with _TASK_STATUS_FILE_LOCK:
with open(status_file, 'r', encoding='utf-8') as f:
loaded_status = json.load(f)
# Restore task status
global task_status
task_status.clear()
task_status.update(loaded_status)
logger.info(f"Loaded {len(loaded_status)} task statuses from {status_file}")
except Exception as e:
logger.warning(f"Failed to load task status from file: {e}")
def allowed_file(filename, allowed_extensions):
"""Check if file extension is allowed."""
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in allowed_extensions
def _format_response(code, message, data=None):
"""Format API response in unified format."""
response = {
"code": code,
"message": message,
"data": data if data is not None else {}
}
return response, code
def _get_file_type(filename):
"""Determine file type from filename."""
fn = (filename or '').lower()
if fn.endswith('.html'):
return 'report'
elif fn.endswith(('.csv', '.xlsx', '.xls')):
return 'data'
elif fn.endswith('.yaml') or fn.endswith('.yml'):
return 'config'
elif fn.endswith('.json'):
return 'metadata'
else:
return 'other'
# Initialize logger
logger = logging.getLogger('gasflux_api')

View File

View File

@ -1,205 +0,0 @@
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

@ -1,58 +0,0 @@
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)