compliance/tests/mock_seismic_api.py
2025-05-16 15:18:02 +08:00

638 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
地震体 API 模拟服务器
用于模拟地震体相关的 API 接口,用于测试 DDMS 合规性验证软件。
"""
import json
import logging
import uuid
import time
import random
from typing import Dict, Any, List, Optional, Tuple
from flask import Flask, request, jsonify, Response, send_file
import io
import numpy as np
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
app = Flask(__name__)
# 内存数据存储
seismic_files = {} # 存储地震体文件信息
export_tasks = {} # 存储导出任务信息
import_tasks = {} # 存储导入任务信息
seismic_data = {} # 存储地震体数据
# 生成唯一ID
def generate_id():
current_time = int(time.time() * 1000)
return f"{current_time}_{random.randint(1, 10)}"
# 初始化一些样例数据
def init_sample_data():
# 添加一个样例地震体
sample_seismic_id = "20221113181927_1"
seismic_files[sample_seismic_id] = {
"projectId": "testPrj1",
"surveyId": "20230117135924_2",
"seismicName": "Sample_Seismic",
"dsType": 1,
"dimensions": [
{
"dimensionNo": 1,
"dimensionName": "inline",
"serviceMin": 1,
"serviceMax": 100,
"serviceSpan": 1
},
{
"dimensionNo": 2,
"dimensionName": "xline",
"serviceMin": 1,
"serviceMax": 100,
"serviceSpan": 1
},
{
"dimensionNo": 3,
"dimensionName": "slice",
"serviceMin": 3500,
"serviceMax": 3600,
"serviceSpan": 4
}
]
}
# 初始化地震体数据 (简单的随机数据)
seismic_data[sample_seismic_id] = {
"traces": {}, # 存储道数据 {(inline, xline): values}
"h3200": b"Sample 3200 Header Data",
"h400": b"Sample 400 Header Data",
"h240": {1: b"Sample 240 Header Data for trace 1"},
"keywords": {
"h400": [{"name": "Sample H400 Keyword", "value": "Sample Value"}],
"h240": [{"name": "Sample H240 Keyword", "value": "Sample Value"}],
"gather": [{"name": "Sample Gather Keyword", "value": "Sample Value"}]
},
"coordinates": {
# 坐标映射 {(x, y): (inline, xline)}
(606406.1281141682, 6082083.338731234): (440, 333),
(609767.8725899048, 6080336.549935018): (366, 465),
(615271.9052119441, 6082017.422172886): (427, 686),
(612173.8269695987, 6084291.543435885): (521, 566)
}
}
# 5.1.1 新建地震体文件
@app.route('/api/gsc/appmodel/api/v1/seismic/file/add', methods=['POST'])
def add_seismic_file():
try:
data = request.json
seismic_id = generate_id()
# 存储地震体信息
seismic_files[seismic_id] = data
# 初始化地震体数据
seismic_data[seismic_id] = {
"traces": {},
"h3200": b"Default 3200 Header Data",
"h400": b"Default 400 Header Data",
"h240": {},
"keywords": {
"h400": [],
"h240": [],
"gather": []
},
"coordinates": {}
}
return jsonify({
"code": "0",
"msg": "",
"flag": True,
"result": seismic_id
})
except Exception as e:
logger.error(f"Error adding seismic file: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.2 Inline 写入三维地震体文件
@app.route('/api/gsc/appmodel/api/v1/seismic/3d/inline/writer/array', methods=['POST'])
def write_inline_array():
try:
data = request.json
seismic_id = data.get('seismicId')
inline_no = data.get('inlineNo')
values = data.get('values', [])
if seismic_id not in seismic_data:
return jsonify({
"msg": "Seismic file not found",
"code": 1,
"result": ""
}), 404
# 存储道数据
for xline_idx, trace_values in enumerate(values[0]):
xline_no = seismic_files[seismic_id]['dimensions'][1]['serviceMin'] + xline_idx
seismic_data[seismic_id]["traces"][(inline_no, xline_no)] = trace_values
return jsonify({
"msg": "success",
"code": 0,
"result": ""
})
except Exception as e:
logger.error(f"Error writing inline array: {e}")
return jsonify({
"msg": str(e),
"code": 1,
"result": ""
}), 500
# 5.1.3 3D 任意道写入三维地震体文件
@app.route('/api/gsc/appmodel/api/v1/seismic/3d/writer/any/array', methods=['POST'])
def write_any_array():
try:
data = request.json
seismic_id = data.get('seismicId')
traces = data.get('traces', [])
if seismic_id not in seismic_data:
return jsonify({
"msg": "Seismic file not found",
"code": 1,
"result": ""
}), 404
# 存储道数据
for trace in traces:
inline_no = trace.get('inlineNo')
xline_no = trace.get('xlineNo')
values = trace.get('values', [])
seismic_data[seismic_id]["traces"][(inline_no, xline_no)] = values
return jsonify({
"msg": "success",
"code": 0,
"result": ""
})
except Exception as e:
logger.error(f"Error writing any array: {e}")
return jsonify({
"msg": str(e),
"code": 1,
"result": ""
}), 500
# 5.1.4 导出地震体—提交任务
@app.route('/api/gsc/appmodel/api/v1/seismic/export/submit', methods=['POST'])
def submit_export():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 创建导出任务
task_id = f"export_{generate_id()}"
export_tasks[task_id] = {
"seismicId": seismic_id,
"status": "submitted",
"progress": 0,
"saveDir": data.get('saveDir', f"/export/{seismic_id}.sgy")
}
# 模拟任务开始处理
def process_task():
for i in range(1, 11):
export_tasks[task_id]["progress"] = i * 10
time.sleep(0.5) # 模拟处理时间
export_tasks[task_id]["status"] = "completed"
# 启动后台线程处理任务
import threading
thread = threading.Thread(target=process_task)
thread.daemon = True
thread.start()
return jsonify({
"code": "0",
"msg": "操作成功!",
"flag": True,
"result": {
"taskId": task_id,
"status": "submitted",
"progress": 0
}
})
except Exception as e:
logger.error(f"Error submitting export task: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.5 导出地震体—查询进度
@app.route('/api/gsc/appmodel/api/v1/seismic/export/progress', methods=['GET'])
def query_export_progress():
try:
task_id = request.args.get('taskId')
if task_id not in export_tasks:
return jsonify({
"code": "1",
"msg": "Task not found",
"flag": False,
"result": None
}), 404
task = export_tasks[task_id]
return jsonify({
"code": "0",
"msg": "操作成功!",
"flag": True,
"result": {
"taskId": task_id,
"status": task["status"],
"progress": task["progress"]
}
})
except Exception as e:
logger.error(f"Error querying export progress: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.6 导出地震体—下载
@app.route('/api/gsc/appmodel/api/v1/seismic/export/download', methods=['GET'])
def download_export():
try:
task_id = request.args.get('taskId')
if task_id not in export_tasks:
return jsonify({
"code": "1",
"msg": "Task not found",
"flag": False,
"result": None
}), 404
task = export_tasks[task_id]
if task["status"] != "completed":
return jsonify({
"code": "1",
"msg": "Task not completed",
"flag": False,
"result": None
}), 400
# 创建一个模拟的SEG-Y文件
dummy_segy = io.BytesIO()
# 添加一些随机二进制数据
dummy_segy.write(b"FAKE SEGY FILE CONTENT")
dummy_segy.seek(0)
# 如果 delFile 参数设置为 true删除任务
if request.args.get('delFile') == '1':
export_tasks.pop(task_id, None)
return send_file(
dummy_segy,
mimetype='application/octet-stream',
as_attachment=True,
download_name=f"seismic_{task['seismicId']}.sgy"
)
except Exception as e:
logger.error(f"Error downloading export: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.7 查询地震体 3200 头
@app.route('/api/gsc/appmodel/api/v1/seismic/head/h3200', methods=['POST'])
def get_h3200():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 返回二进制数据
return Response(
seismic_data[seismic_id]["h3200"],
mimetype='application/octet-stream'
)
except Exception as e:
logger.error(f"Error getting h3200: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.8 查询地震体 400 头
@app.route('/api/gsc/appmodel/api/v1/seismic/head/h400', methods=['POST'])
def get_h400():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 返回二进制数据
return Response(
seismic_data[seismic_id]["h400"],
mimetype='application/octet-stream'
)
except Exception as e:
logger.error(f"Error getting h400: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.9 查询地震体总道数
@app.route('/api/gsc/appmodel/api/v1/seismic/traces/count', methods=['POST'])
def get_traces_count():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 获取道数
trace_count = len(seismic_data[seismic_id]["traces"])
return jsonify({
"msg": "success",
"code": 0,
"result": str(trace_count)
})
except Exception as e:
logger.error(f"Error getting traces count: {e}")
return jsonify({
"msg": str(e),
"code": 1,
"result": ""
}), 500
# 5.1.10 查询地震体 240 头
@app.route('/api/gsc/appmodel/api/v1/seismic/head/h240', methods=['POST'])
def get_h240():
try:
data = request.json
seismic_id = data.get('seismicId')
trace_index = data.get('traceIndex')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 获取道头数据
if trace_index not in seismic_data[seismic_id]["h240"]:
# 如果不存在,生成一个随机的道头数据
seismic_data[seismic_id]["h240"][trace_index] = f"Sample 240 Header Data for trace {trace_index}".encode()
# 返回二进制数据
return Response(
seismic_data[seismic_id]["h240"][trace_index],
mimetype='application/octet-stream'
)
except Exception as e:
logger.error(f"Error getting h240: {e}")
return jsonify({
"code": "1",
"msg": str(e),
"flag": False,
"result": None
}), 500
# 5.1.11 查询地震体卷头关键字信息
@app.route('/api/gsc/appmodel/api/v1/seismic/h400/keyword/list', methods=['POST'])
def get_h400_keywords():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
return jsonify({
"flag": True,
"msg": "success",
"code": 0,
"result": seismic_data[seismic_id]["keywords"]["h400"]
})
except Exception as e:
logger.error(f"Error getting h400 keywords: {e}")
return jsonify({
"flag": False,
"msg": str(e),
"code": 1,
"result": None
}), 500
# 5.1.12 查询地震体道头关键字信息
@app.route('/api/gsc/appmodel/api/v1/seismic/h240/keyword/list', methods=['POST'])
def get_h240_keywords():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
return jsonify({
"flag": True,
"msg": "success",
"code": 0,
"result": seismic_data[seismic_id]["keywords"]["h240"]
})
except Exception as e:
logger.error(f"Error getting h240 keywords: {e}")
return jsonify({
"flag": False,
"msg": str(e),
"code": 1,
"result": None
}), 500
# 5.1.13 查询地震体道集关键字信息
@app.route('/api/gsc/appmodel/api/v1/seismic/gather/keyword/list', methods=['POST'])
def get_gather_keywords():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
return jsonify({
"flag": True,
"msg": "success",
"code": 0,
"result": seismic_data[seismic_id]["keywords"]["gather"]
})
except Exception as e:
logger.error(f"Error getting gather keywords: {e}")
return jsonify({
"flag": False,
"msg": str(e),
"code": 1,
"result": None
}), 500
# 5.1.14 导入地震体—查询进度
@app.route('/api/gsc/appmodel/api/v1/seismic/import/progress', methods=['POST'])
def query_import_progress():
try:
data = request.json
seismic_id = data.get('seismicId')
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 检查是否存在导入任务
task_id = f"import_{seismic_id}"
if task_id not in import_tasks:
# 创建一个模拟的导入任务
import_tasks[task_id] = {
"seismicId": seismic_id,
"status": "completed",
"progress": 100
}
task = import_tasks[task_id]
return jsonify({
"msg": "success",
"code": 0,
"result": {
"taskId": task_id,
"status": task["status"],
"progress": task["progress"]
}
})
except Exception as e:
logger.error(f"Error querying import progress: {e}")
return jsonify({
"msg": str(e),
"code": 1,
"result": None
}), 500
# 5.1.15 查询地震体点线坐标
@app.route('/api/gsc/appmodel/api/v1/seismic/coordinate/geodetic/toline', methods=['POST'])
def convert_coordinates():
try:
data = request.json
seismic_id = data.get('seismicId')
points = data.get('points', [])
if seismic_id not in seismic_data:
return jsonify({
"code": "1",
"msg": "Seismic file not found",
"flag": False,
"result": None
}), 404
# 转换坐标
result = []
for point in points:
x, y = point
# 查找最接近的已知坐标点
if (x, y) in seismic_data[seismic_id]["coordinates"]:
result.append(list(seismic_data[seismic_id]["coordinates"][(x, y)]))
else:
# 如果找不到精确匹配,返回模拟数据
result.append([random.randint(1, 100), random.randint(1, 100)])
return jsonify({
"msg": "success",
"code": 0,
"result": result
})
except Exception as e:
logger.error(f"Error converting coordinates: {e}")
return jsonify({
"msg": str(e),
"code": 1,
"result": None
}), 500
# 初始化样例数据
init_sample_data()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001, debug=True)