unit_grouping.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. from fastapi import APIRouter, Depends, HTTPException, Query
  2. from sqlalchemy.orm import Session
  3. from typing import Dict, Any, List
  4. import logging
  5. from ..database import get_db
  6. from ..services.unit_grouping_service import UnitGroupingService
  7. logger = logging.getLogger(__name__)
  8. router = APIRouter()
  9. @router.get("/h_xtfx",
  10. summary="获取单元h_xtfx分类结果",
  11. description="基于点位数据计算各单元的土壤环境质量类别(h_xtfx),使用反距离加权插值算法")
  12. async def get_unit_h_xtfx_result(db: Session = Depends(get_db)) -> Dict[str, Any]:
  13. """
  14. 获取单元h_xtfx分类结果
  15. 该接口实现以下功能:
  16. 1. 获取单元几何数据和点位数据
  17. 2. 判断每个单元内包含的点位
  18. 3. 根据点位的h_xtfx值计算单元的h_xtfx值
  19. 4. 使用反距离加权插值算法进行计算
  20. 算法逻辑:
  21. - 如果单元内无严格管控类点位:
  22. - 优先判断某类别占比是否≥80%,是则直接采用该类别
  23. - 否则对优先保护类和安全利用类点位进行插值
  24. - 如果单元内有严格管控类点位:
  25. - 对所有点位(包括严格管控类)进行插值
  26. Returns:
  27. Dict[str, Any]: 包含以下字段的响应:
  28. - success: 是否成功
  29. - data: 单元ID到h_xtfx值的映射
  30. - statistics: 统计信息
  31. - error: 错误信息(如果失败)
  32. Raises:
  33. HTTPException: 当数据库查询失败或处理异常时抛出
  34. """
  35. try:
  36. logger.info("开始获取单元h_xtfx分类结果")
  37. # 创建服务实例
  38. service = UnitGroupingService(db)
  39. # 获取结果
  40. result = service.get_unit_h_xtfx_result()
  41. if not result["success"]:
  42. logger.error(f"服务层处理失败: {result.get('error', 'Unknown error')}")
  43. raise HTTPException(
  44. status_code=500,
  45. detail=f"计算单元h_xtfx值失败: {result.get('error', 'Unknown error')}"
  46. )
  47. logger.info(f"成功获取 {result['statistics']['total_units']} 个单元的h_xtfx结果")
  48. return result
  49. except HTTPException:
  50. raise
  51. except Exception as e:
  52. logger.error(f"获取单元h_xtfx结果时发生异常: {str(e)}")
  53. raise HTTPException(
  54. status_code=500,
  55. detail=f"内部服务器错误: {str(e)}"
  56. )
  57. @router.get("/statistics",
  58. summary="获取单元分组统计信息",
  59. description="获取单元分组的统计摘要信息")
  60. async def get_unit_grouping_statistics(db: Session = Depends(get_db)) -> Dict[str, Any]:
  61. """
  62. 获取单元分组统计信息
  63. 提供单元分组的统计摘要,包括:
  64. - 总单元数
  65. - 有数据的单元数
  66. - 无数据的单元数
  67. - 各类别的分布情况
  68. Returns:
  69. Dict[str, Any]: 统计信息
  70. """
  71. try:
  72. logger.info("开始获取单元分组统计信息")
  73. # 创建服务实例
  74. service = UnitGroupingService(db)
  75. # 获取完整结果以提取统计信息
  76. result = service.get_unit_h_xtfx_result()
  77. if not result["success"]:
  78. raise HTTPException(
  79. status_code=500,
  80. detail=f"获取统计信息失败: {result.get('error', 'Unknown error')}"
  81. )
  82. # 返回统计信息
  83. return {
  84. "success": True,
  85. "statistics": result["statistics"]
  86. }
  87. except HTTPException:
  88. raise
  89. except Exception as e:
  90. logger.error(f"获取统计信息时发生异常: {str(e)}")
  91. raise HTTPException(
  92. status_code=500,
  93. detail=f"内部服务器错误: {str(e)}"
  94. )
  95. @router.get("/unit/{unit_id}",
  96. summary="获取特定单元的h_xtfx值",
  97. description="获取指定单元ID的h_xtfx分类结果")
  98. async def get_unit_h_xtfx_by_id(unit_id: int, db: Session = Depends(get_db)) -> Dict[str, Any]:
  99. """
  100. 获取特定单元的h_xtfx值
  101. Args:
  102. unit_id: 单元ID
  103. Returns:
  104. Dict[str, Any]: 包含单元h_xtfx值的响应
  105. """
  106. try:
  107. logger.info(f"开始获取单元 {unit_id} 的h_xtfx值")
  108. # 创建服务实例
  109. service = UnitGroupingService(db)
  110. # 获取所有结果
  111. result = service.get_unit_h_xtfx_result()
  112. if not result["success"]:
  113. raise HTTPException(
  114. status_code=500,
  115. detail=f"获取单元数据失败: {result.get('error', 'Unknown error')}"
  116. )
  117. # 检查指定单元是否存在
  118. if unit_id not in result["data"]:
  119. raise HTTPException(
  120. status_code=404,
  121. detail=f"未找到单元 {unit_id}"
  122. )
  123. return {
  124. "success": True,
  125. "unit_id": unit_id,
  126. "h_xtfx": result["data"][unit_id]
  127. }
  128. except HTTPException:
  129. raise
  130. except Exception as e:
  131. logger.error(f"获取单元 {unit_id} 的h_xtfx值时发生异常: {str(e)}")
  132. raise HTTPException(
  133. status_code=500,
  134. detail=f"内部服务器错误: {str(e)}"
  135. )
  136. @router.get("/units/batch",
  137. summary="批量获取单元信息",
  138. description="使用ORM方式批量获取指定单元的基本信息")
  139. async def get_units_batch(
  140. unit_ids: List[int] = Query(..., description="单元ID列表"),
  141. db: Session = Depends(get_db)
  142. ) -> Dict[str, Any]:
  143. """
  144. 批量获取单元信息
  145. Args:
  146. unit_ids: 单元ID列表
  147. Returns:
  148. Dict[str, Any]: 包含单元信息的响应
  149. """
  150. try:
  151. logger.info(f"开始批量获取 {len(unit_ids)} 个单元的信息")
  152. # 创建服务实例
  153. service = UnitGroupingService(db)
  154. # 使用ORM方式批量获取单元信息
  155. units = service.get_units_by_ids(unit_ids)
  156. # 转换为字典格式
  157. unit_data = []
  158. for unit in units:
  159. unit_data.append({
  160. "gid": unit.gid,
  161. "BSM": unit.BSM,
  162. "PXZQMC": unit.PXZQMC,
  163. "CXZQMC": unit.CXZQMC,
  164. "SUM_NYDTBM": float(unit.SUM_NYDTBM) if unit.SUM_NYDTBM else None,
  165. "Shape_Area": float(unit.Shape_Area) if unit.Shape_Area else None
  166. })
  167. return {
  168. "success": True,
  169. "total_requested": len(unit_ids),
  170. "total_found": len(units),
  171. "data": unit_data
  172. }
  173. except Exception as e:
  174. logger.error(f"批量获取单元信息时发生异常: {str(e)}")
  175. raise HTTPException(
  176. status_code=500,
  177. detail=f"内部服务器错误: {str(e)}"
  178. )
  179. @router.get("/points/statistics",
  180. summary="获取点位统计信息",
  181. description="使用ORM方式获取点位按h_xtfx分类的统计信息")
  182. async def get_points_statistics(db: Session = Depends(get_db)) -> Dict[str, Any]:
  183. """
  184. 获取点位统计信息
  185. 返回按h_xtfx分类的点位数量统计
  186. Returns:
  187. Dict[str, Any]: 点位统计信息
  188. """
  189. try:
  190. logger.info("开始获取点位统计信息")
  191. # 创建服务实例
  192. service = UnitGroupingService(db)
  193. # 使用ORM方式获取统计信息
  194. point_stats = service.get_point_count_by_h_xtfx()
  195. # 计算总数
  196. total_points = sum(point_stats.values())
  197. # 计算百分比
  198. percentage_stats = {}
  199. for category, count in point_stats.items():
  200. percentage_stats[category] = {
  201. "count": count,
  202. "percentage": round(count / total_points * 100, 2) if total_points > 0 else 0
  203. }
  204. return {
  205. "success": True,
  206. "total_points": total_points,
  207. "distribution": percentage_stats
  208. }
  209. except Exception as e:
  210. logger.error(f"获取点位统计信息时发生异常: {str(e)}")
  211. raise HTTPException(
  212. status_code=500,
  213. detail=f"内部服务器错误: {str(e)}"
  214. )
  215. @router.get("/points/by-area",
  216. summary="按区域获取点位数据",
  217. description="使用ORM方式获取特定区域的点位数据")
  218. async def get_points_by_area(
  219. area_name: str = Query(None, description="区域名称(县名称)"),
  220. db: Session = Depends(get_db)
  221. ) -> Dict[str, Any]:
  222. """
  223. 按区域获取点位数据
  224. Args:
  225. area_name: 区域名称(县名称),如果为空则获取所有区域
  226. Returns:
  227. Dict[str, Any]: 点位数据
  228. """
  229. try:
  230. logger.info(f"开始获取区域 '{area_name}' 的点位数据")
  231. # 创建服务实例
  232. service = UnitGroupingService(db)
  233. # 使用ORM方式获取点位数据
  234. points = service.get_points_in_area(area_name)
  235. # 转换为字典格式
  236. point_data = []
  237. for point in points:
  238. point_data.append({
  239. "id": point.id,
  240. "dwmc": point.dwmc,
  241. "xmc": point.xmc,
  242. "zmc": point.zmc,
  243. "cmc": point.cmc,
  244. "h_xtfx": point.h_xtfx,
  245. "lat": float(point.lat) if point.lat else None,
  246. "lon": float(point.lon) if point.lon else None,
  247. "ph": float(point.ph) if point.ph else None
  248. })
  249. # 统计该区域的h_xtfx分布
  250. h_xtfx_stats = {}
  251. for point in points:
  252. if point.h_xtfx:
  253. h_xtfx_stats[point.h_xtfx] = h_xtfx_stats.get(point.h_xtfx, 0) + 1
  254. return {
  255. "success": True,
  256. "area_name": area_name or "全部区域",
  257. "total_points": len(points),
  258. "h_xtfx_distribution": h_xtfx_stats,
  259. "data": point_data
  260. }
  261. except Exception as e:
  262. logger.error(f"获取区域点位数据时发生异常: {str(e)}")
  263. raise HTTPException(
  264. status_code=500,
  265. detail=f"内部服务器错误: {str(e)}"
  266. )
  267. @router.get("/database/summary",
  268. summary="获取数据库摘要信息",
  269. description="获取数据库中单元和点位的摘要统计")
  270. async def get_database_summary(db: Session = Depends(get_db)) -> Dict[str, Any]:
  271. """
  272. 获取数据库摘要信息
  273. Returns:
  274. Dict[str, Any]: 数据库摘要信息
  275. """
  276. try:
  277. logger.info("开始获取数据库摘要信息")
  278. # 创建服务实例
  279. service = UnitGroupingService(db)
  280. # 使用ORM方式获取各种统计信息
  281. total_units = service.get_unit_count()
  282. point_stats = service.get_point_count_by_h_xtfx()
  283. total_points = sum(point_stats.values())
  284. return {
  285. "success": True,
  286. "summary": {
  287. "total_units": total_units,
  288. "total_points": total_points,
  289. "points_with_h_xtfx": total_points,
  290. "h_xtfx_categories": len(point_stats),
  291. "point_distribution": point_stats
  292. }
  293. }
  294. except Exception as e:
  295. logger.error(f"获取数据库摘要信息时发生异常: {str(e)}")
  296. raise HTTPException(
  297. status_code=500,
  298. detail=f"内部服务器错误: {str(e)}"
  299. )
  300. @router.get("/areas/statistics",
  301. summary="获取各区域统计信息",
  302. description="使用ORM聚合查询获取各区域的h_xtfx分布统计")
  303. async def get_areas_statistics(db: Session = Depends(get_db)) -> Dict[str, Any]:
  304. """
  305. 获取各区域统计信息
  306. 使用ORM的高级聚合查询功能,按区域分组统计h_xtfx分布
  307. Returns:
  308. Dict[str, Any]: 各区域的统计信息
  309. """
  310. try:
  311. logger.info("开始获取各区域统计信息")
  312. # 创建服务实例
  313. service = UnitGroupingService(db)
  314. # 使用ORM方式获取区域统计信息
  315. area_stats = service.get_area_statistics()
  316. # 计算总体统计
  317. total_areas = len(area_stats)
  318. total_points_by_area = {}
  319. for area_name, stats in area_stats.items():
  320. total_points_by_area[area_name] = sum(stats.values())
  321. return {
  322. "success": True,
  323. "total_areas": total_areas,
  324. "area_statistics": area_stats,
  325. "area_totals": total_points_by_area
  326. }
  327. except Exception as e:
  328. logger.error(f"获取各区域统计信息时发生异常: {str(e)}")
  329. raise HTTPException(
  330. status_code=500,
  331. detail=f"内部服务器错误: {str(e)}"
  332. )