diff --git a/AGENTS.md b/AGENTS.md
index 0507a56..40e713d 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -354,9 +354,17 @@ runtime\python\python.exe scripts\column_survey.py --csv "data/*.csv"
## 近期变更 (beta-clean 分支)
-- views.py (2000+ 行单体) → `analysis/views/` 包 (12 模块)
-- tool_registry.py → `analysis/tools/` 包 (17 模块)
-- 删除 `simple_analysis/` 模块 (已移至 master 分支独立维护)
-- 工具数量从 27 升至 30 (新增 export_entities_json, diagnostic toolbox 扩展)
-- 模板目录重组: 6 个分析页面在 `analysis/`, 6 个功能页面在 `tianxuan/`
-- 新增 `analysis/distance.py` (距离计算) 和 `analysis/nl_describe.py` (自然语言描述)
+- views.py (2000+ 行单体) → `analysis/views/` 包 (13 模块)
+- tool_registry.py (3000+ 行) → `analysis/tools/` 包 (18 模块)
+- 默认聚类算法改为 AgglomerativeClustering
+- 移除实体概念,直接对原始行聚类 (entity_value = row_N)
+- cluster_detail 显示原始数据行而非实体画像
+- run_detail 新增全域 SVD 特征分析 + LLM 工作流时间线
+- 3D 地球侧栏复用 `/globe/?embed=1`(iframe + postMessage 联动)
+- UI 全面中文化
+- 非阻塞启动 (run.bat 打印 PID 后退出)
+
+## 待办
+
+- [ ] **前端 UI 验证**: 打开 `prototype_cluster_ui.html` 查看交互设计是否符合要求
+- [ ] **更新前端原型**后,将验证通过的交互逻辑合并到正式模板
diff --git a/analysis/management/commands/run_pipeline.py b/analysis/management/commands/run_pipeline.py
index 6f761ec..d992411 100644
--- a/analysis/management/commands/run_pipeline.py
+++ b/analysis/management/commands/run_pipeline.py
@@ -69,7 +69,7 @@ class Command(BaseCommand):
run.save(update_fields=['total_flows'])
from analysis.views import _run_clustering_pipeline
_run_clustering_pipeline(
- run=run, store=store, entity_ds_id=ds_id,
+ run=run, store=store, ds_id=ds_id,
feature_columns=feature_cols,
algorithm=algo, min_cluster_size=5,
run_umap=True,
diff --git a/analysis/nl_describe.py b/analysis/nl_describe.py
index 9f89418..15a5de0 100644
--- a/analysis/nl_describe.py
+++ b/analysis/nl_describe.py
@@ -285,6 +285,7 @@ def describe_feature(
feature_name: str,
value: float,
std_dev: float | None = None,
+ cluster_std: float | None = None,
) -> str:
"""Generate a Chinese natural-language description for a single feature.
@@ -296,14 +297,15 @@ def describe_feature(
The feature's mean value in the current context (cluster mean).
std_dev : float | None
Optional Z-score magnitude (``abs(distinguishing_score)``). When
- provided and >= 1.0, appends a deviation suffix like
- "比全局均值高2.1个标准差".
+ provided and >= 1.0, appends a deviation suffix.
+ cluster_std : float | None
+ Optional within-cluster standard deviation. Describes how spread
+ the values are within this cluster (high = scattered, low = tight).
Returns
-------
str
- Natural-language description string, e.g.
- ``"中等数据包 (720 bytes),比全局均值高2.1个标准差"``.
+ Natural-language description string.
"""
meaning = _lookup_meaning(feature_name)
category = _resolve_category(feature_name)
@@ -322,7 +324,6 @@ def describe_feature(
meaning=meaning)
break
except Exception:
- # Fall through to next template on format errors
continue
if not text:
@@ -332,6 +333,13 @@ def describe_feature(
if std_dev is not None and std_dev >= 1.0:
text += f",比全局均值高{std_dev:.1f}个标准差"
+ # Append within-cluster variance context
+ if cluster_std is not None and cluster_std > 0:
+ if cluster_std > 2.0:
+ text += "(簇内离散度高)"
+ elif cluster_std < 0.3:
+ text += "(簇内高度集中)"
+
return text
@@ -380,11 +388,13 @@ def describe_cluster(
name = f.get("feature_name", "")
mean = f.get("mean")
score = abs(f.get("distinguishing_score", 0.0))
+ cstd = f.get("std")
if mean is None or name == "":
continue
- desc = describe_feature(name, float(mean), std_dev=score if score >= 1.0 else None)
+ desc = describe_feature(name, float(mean), std_dev=score if score >= 1.0 else None,
+ cluster_std=float(cstd) if cstd is not None else None)
sentences.append(desc)
if not sentences:
diff --git a/analysis/views/globe.py b/analysis/views/globe.py
index b460d62..b2375f6 100644
--- a/analysis/views/globe.py
+++ b/analysis/views/globe.py
@@ -4,6 +4,7 @@ import logging
import traceback
from django.shortcuts import render
+from django.views.decorators.clickjacking import xframe_options_exempt
from analysis.constants import GLOBE_MAX_ROWS
from analysis.models import AnalysisRun
@@ -112,6 +113,10 @@ def _extract_flows_from_df(df, MAX_ROWS):
return flows
+from django.views.decorators.clickjacking import xframe_options_exempt
+
+
+@xframe_options_exempt
def globe_view(request):
from analysis.geoip import lookup as geo_lookup
from analysis.data_loader import load_csv_directory, load_from_db
diff --git a/data/geoip_cache.json b/data/geoip_cache.json
index 9ff8287..355651e 100644
--- a/data/geoip_cache.json
+++ b/data/geoip_cache.json
@@ -45,5 +45,639 @@
"lon": 77.0,
"city": "",
"country": "印度"
+ },
+ "anon, hosting": null,
+ "-108.418446": null,
+ "-63.303819": null,
+ "156.494253": {
+ "lat": 34.053,
+ "lon": -118.2642,
+ "city": "洛杉矶",
+ "country": "美国"
+ },
+ "174.324906": {
+ "lat": 43.6425,
+ "lon": -79.3872,
+ "city": "",
+ "country": "加拿大"
+ },
+ "91.251045": {
+ "lat": 53.55,
+ "lon": 10.0,
+ "city": "汉堡市",
+ "country": "德国"
+ },
+ "136.838644": {
+ "lat": 42.3223,
+ "lon": -83.1763,
+ "city": "迪尔伯恩",
+ "country": "美国"
+ },
+ "-135.232683": null,
+ "134.708535": {
+ "lat": 45.4763,
+ "lon": -122.6408,
+ "city": "Portland",
+ "country": "美国"
+ },
+ "172.779207": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "76.375007": {
+ "lat": 35.6507,
+ "lon": -78.4564,
+ "city": "Clayton",
+ "country": "美国"
+ },
+ "-37.054377": null,
+ "58.368656": {
+ "lat": 35.685,
+ "lon": 139.7514,
+ "city": "东京",
+ "country": "日本"
+ },
+ "-128.312338": null,
+ "-86.295682": null,
+ "-83.710197": null,
+ "-117.654327": null,
+ "-94.931072": null,
+ "-31.118326": null,
+ "41.94697": {
+ "lat": -29.0,
+ "lon": 24.0,
+ "city": "",
+ "country": "南非"
+ },
+ "-175.557379": null,
+ "None": null,
+ "90.484378": {
+ "lat": 50.6846,
+ "lon": 1.7610999999999999,
+ "city": "维尔维涅",
+ "country": "法国"
+ },
+ "91.136808": {
+ "lat": 50.8934,
+ "lon": 7.8856,
+ "city": "Freudenberg",
+ "country": "德国"
+ },
+ "98.398423": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-37.351993": null,
+ "108.8728": {
+ "lat": 33.5363,
+ "lon": -117.0439,
+ "city": "特曼库拉",
+ "country": "美国"
+ },
+ "-40.490238": null,
+ "-108.320482": null,
+ "-42.599081": null,
+ "60.847895": {
+ "lat": 30.2936,
+ "lon": 120.1614,
+ "city": "杭州",
+ "country": "中国"
+ },
+ "-70.344735": null,
+ "-17.065978": null,
+ "-17.594761": null,
+ "3.748318": {
+ "lat": 41.1412,
+ "lon": -73.2637,
+ "city": "Fairfield",
+ "country": "美国"
+ },
+ "117.90784": {
+ "lat": 21.0333,
+ "lon": 105.85,
+ "city": "Hanoi",
+ "country": "越南"
+ },
+ "-178.325477": null,
+ "47.034714": {
+ "lat": 45.3155,
+ "lon": -75.837,
+ "city": "Ottawa",
+ "country": "加拿大"
+ },
+ "12.6356": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-4.376563": null,
+ "117.415791": {
+ "lat": 21.0333,
+ "lon": 105.85,
+ "city": "Hanoi",
+ "country": "越南"
+ },
+ "-95.943745": null,
+ "115.811466": {
+ "lat": 37.57,
+ "lon": 126.98,
+ "city": "",
+ "country": "大韩民国"
+ },
+ "82.858229": {
+ "lat": 54.5842,
+ "lon": -1.5631,
+ "city": "Darlington",
+ "country": "英国"
+ },
+ "120.177108": {
+ "lat": 39.8897,
+ "lon": 115.275,
+ "city": "Hebei",
+ "country": "中国"
+ },
+ "12.054574": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-112.238338": null,
+ "-161.091649": null,
+ "24.207799": {
+ "lat": 40.3698,
+ "lon": -80.634,
+ "city": "斯托本维尔",
+ "country": "美国"
+ },
+ "-148.31237": null,
+ "-132.223679": null,
+ "76.252382": {
+ "lat": 35.6513,
+ "lon": -78.8336,
+ "city": "Holly Springs",
+ "country": "美国"
+ },
+ "104.839037": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-147.319447": null,
+ "-137.111721": null,
+ "-107.76671": null,
+ "-167.802595": null,
+ "168.500812": {
+ "lat": 29.7176,
+ "lon": -95.4188,
+ "city": "休斯敦",
+ "country": "美国"
+ },
+ "-19.640731": null,
+ "-36.115066": null,
+ "-31.172609": null,
+ "4.746775": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-128.714202": null,
+ "-95.66714": null,
+ "-19.935247": null,
+ "52.225763": {
+ "lat": 39.5645,
+ "lon": -75.597,
+ "city": "威尔明顿",
+ "country": "美国"
+ },
+ "-39.370987": null,
+ "162.006633": {
+ "lat": 43.7807,
+ "lon": -79.2855,
+ "city": "士嘉堡",
+ "country": "加拿大"
+ },
+ "51.696746": {
+ "lat": 51.5,
+ "lon": -0.13,
+ "city": "",
+ "country": "英国"
+ },
+ "6.673336": {
+ "lat": 31.5273,
+ "lon": -110.3607,
+ "city": "谢拉维斯塔",
+ "country": "美国"
+ },
+ "102.5503": null,
+ "-144.964956": null,
+ "-104.457778": null,
+ "83.087052": null,
+ "-125.101539": null,
+ "90.262005": {
+ "lat": 48.9018,
+ "lon": 2.4893,
+ "city": "邦迪",
+ "country": "法国"
+ },
+ "-83.715609": null,
+ "29.378547": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-57.090496": null,
+ "142.184372": {
+ "lat": 44.7314,
+ "lon": -63.6482,
+ "city": "Dartmouth",
+ "country": "加拿大"
+ },
+ "165.297813": {
+ "lat": -33.9167,
+ "lon": 18.4167,
+ "city": "Cape Town",
+ "country": "南非"
+ },
+ "105.875829": {
+ "lat": -29.0,
+ "lon": 24.0,
+ "city": "",
+ "country": "南非"
+ },
+ "160.97215": {
+ "lat": 43.286,
+ "lon": -77.6843,
+ "city": "Rochester",
+ "country": "美国"
+ },
+ "-76.327692": null,
+ "-179.768984": null,
+ "-135.649249": null,
+ "-129.397466": null,
+ "-159.604348": null,
+ "123.957119": {
+ "lat": 34.6836,
+ "lon": 113.5325,
+ "city": "郑州",
+ "country": "中国"
+ },
+ "106.508142": {
+ "lat": 28.55,
+ "lon": 115.9333,
+ "city": "南昌",
+ "country": "中国"
+ },
+ "60.737607": {
+ "lat": 45.75,
+ "lon": 126.65,
+ "city": "哈尔滨",
+ "country": "中国"
+ },
+ "12.851572": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "133.109702": {
+ "lat": 35.69,
+ "lon": 139.69,
+ "city": "",
+ "country": "日本"
+ },
+ "97.468122": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-49.099249": null,
+ "31.114424": {
+ "lat": 52.25,
+ "lon": 21.0,
+ "city": "华沙",
+ "country": "波兰"
+ },
+ "49.613214": {
+ "lat": 37.5985,
+ "lon": 126.9783,
+ "city": "首尔特别市",
+ "country": "大韩民国"
+ },
+ "-76.937967": null,
+ "24.350375": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-57.188778": null,
+ "-129.431676": null,
+ "-136.186649": null,
+ "-61.694727": null,
+ "-90.513611": null,
+ "91.194896": {
+ "lat": 49.5333,
+ "lon": 11.8,
+ "city": "哈恩巴赫",
+ "country": "德国"
+ },
+ "132.327773": {
+ "lat": 32.404,
+ "lon": -86.2539,
+ "city": "蒙哥马利",
+ "country": "美国"
+ },
+ "-112.197533": null,
+ "155.022955": null,
+ "162.854691": {
+ "lat": 51.5,
+ "lon": -0.13,
+ "city": "",
+ "country": "英国"
+ },
+ "-52.303734": null,
+ "-37.91953": null,
+ "144.662392": {
+ "lat": 37.3762,
+ "lon": -122.1826,
+ "city": "Palo Alto",
+ "country": "美国"
+ },
+ "17.315107": {
+ "lat": 37.323,
+ "lon": -122.0322,
+ "city": "Cupertino",
+ "country": "美国"
+ },
+ "97.359727": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-37.814213": null,
+ "-57.066252": null,
+ "170.670964": {
+ "lat": 47.6689,
+ "lon": -117.4369,
+ "city": "斯波坎",
+ "country": "美国"
+ },
+ "19.237916": {
+ "lat": 42.3223,
+ "lon": -83.1763,
+ "city": "迪尔伯恩",
+ "country": "美国"
+ },
+ "-77.426219": null,
+ "35.273579": {
+ "lat": 42.2776,
+ "lon": -83.7409,
+ "city": "安娜堡",
+ "country": "美国"
+ },
+ "-29.56673": null,
+ "-173.438083": null,
+ "-164.691055": null,
+ "-140.463216": null,
+ "-168.663276": null,
+ "-138.543279": null,
+ "-47.142859": null,
+ "-102.389184": null,
+ "24.754033": {
+ "lat": 32.981,
+ "lon": -80.0326,
+ "city": "Goose Creek",
+ "country": "美国"
+ },
+ "-109.476174": null,
+ "92.836244": {
+ "lat": 51.5,
+ "lon": -0.13,
+ "city": "",
+ "country": "英国"
+ },
+ "2.089979": null,
+ "82.41569": {
+ "lat": 51.6578,
+ "lon": -0.3954,
+ "city": "沃特福德",
+ "country": "英国"
+ },
+ "-117.765392": null,
+ "-112.753899": null,
+ "-147.563834": null,
+ "-27.4301": null,
+ "66.656057": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-52.329152": null,
+ "16.783619": {
+ "lat": 37.3762,
+ "lon": -122.1826,
+ "city": "Palo Alto",
+ "country": "美国"
+ },
+ "-160.668335": null,
+ "-155.782242": null,
+ "-43.415128": null,
+ "-151.682652": null,
+ "33.713437": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "151.170164": {
+ "lat": 42.8333,
+ "lon": 12.8333,
+ "city": "",
+ "country": "意大利"
+ },
+ "-2.437103": null,
+ "17.096003": null,
+ "4.372196": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "12.775114": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-26.847855": null,
+ "-2.96053": null,
+ "-136.421502": null,
+ "156.152711": {
+ "lat": 46.2857,
+ "lon": -119.2845,
+ "city": "里奇兰",
+ "country": "美国"
+ },
+ "-121.186972": null,
+ "-126.924167": null,
+ "-101.388131": null,
+ "-101.03754": null,
+ "77.828572": {
+ "lat": 52.5167,
+ "lon": 13.4,
+ "city": "柏林",
+ "country": "德国"
+ },
+ "-34.813058": null,
+ "123.011334": {
+ "lat": 23.7,
+ "lon": 90.375,
+ "city": "",
+ "country": "孟加拉"
+ },
+ "11.265017": {
+ "lat": 39.9612,
+ "lon": -82.9988,
+ "city": "哥伦布",
+ "country": "美国"
+ },
+ "11.202764": {
+ "lat": 39.9612,
+ "lon": -82.9988,
+ "city": "哥伦布",
+ "country": "美国"
+ },
+ "70.262109": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "-70.027646": null,
+ "26.990087": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "147.506751": {
+ "lat": 47.5,
+ "lon": 19.0833,
+ "city": "布达佩斯",
+ "country": "匈牙利"
+ },
+ "-107.81862": null,
+ "141.75262": {
+ "lat": 51.0,
+ "lon": 9.0,
+ "city": "",
+ "country": "德国"
+ },
+ "30.674809": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
+ },
+ "120.327798": {
+ "lat": 39.8897,
+ "lon": 115.275,
+ "city": "Hebei",
+ "country": "中国"
+ },
+ "-158.088393": null,
+ "-121.790773": null,
+ "77.908193": {
+ "lat": 50.3167,
+ "lon": 7.8,
+ "city": "Nassau",
+ "country": "德国"
+ },
+ "57.252522": {
+ "lat": 47.0,
+ "lon": 8.0,
+ "city": "",
+ "country": ""
+ },
+ "-15.466886": null,
+ "-136.800708": null,
+ "-139.560022": null,
+ "155.309838": {
+ "lat": 59.3294,
+ "lon": 18.0686,
+ "city": "",
+ "country": "瑞典"
+ },
+ "158.175545": {
+ "lat": 31.5273,
+ "lon": -110.3607,
+ "city": "谢拉维斯塔",
+ "country": "美国"
+ },
+ "-38.283752": null,
+ "146.597747": {
+ "lat": 42.3755,
+ "lon": -83.0772,
+ "city": "底特律",
+ "country": "美国"
+ },
+ "-146.199812": null,
+ "-60.696207": null,
+ "141.547786": {
+ "lat": 35.8869,
+ "lon": 14.4025,
+ "city": "Mdina",
+ "country": "马耳他"
+ },
+ "10.542121": null,
+ "169.586656": {
+ "lat": 45.0059,
+ "lon": -93.1059,
+ "city": "圣保罗",
+ "country": "美国"
+ },
+ "53.588162": {
+ "lat": 51.0,
+ "lon": 9.0,
+ "city": "",
+ "country": "德国"
+ },
+ "-48.221466": null,
+ "-104.847562": null,
+ "-97.617615": null,
+ "145.767865": {
+ "lat": 51.8425,
+ "lon": 5.8528,
+ "city": "奈梅亨",
+ "country": "荷兰"
+ },
+ "-173.124365": null,
+ "-158.431061": null,
+ "-132.023148": null,
+ "-171.873785": null,
+ "-23.369992": null,
+ "53.281077": {
+ "lat": 51.0,
+ "lon": 9.0,
+ "city": "",
+ "country": "德国"
+ },
+ "28.294006": {
+ "lat": 38.0,
+ "lon": -97.0,
+ "city": "",
+ "country": "美国"
}
}
\ No newline at end of file
diff --git a/prototype_cluster_ui.html b/prototype_cluster_ui.html
new file mode 100644
index 0000000..5241d77
--- /dev/null
+++ b/prototype_cluster_ui.html
@@ -0,0 +1,356 @@
+
+
+
+
+
+原型 — 聚类UI交互验证
+
+
+
+
+
+
+
+
+
+
+
+
UMAP 嵌入 加载中...
+
+
+
+
+
+ 全部
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/screenshot_auto.png b/screenshot_auto.png
new file mode 100644
index 0000000..3394ee2
Binary files /dev/null and b/screenshot_auto.png differ
diff --git a/screenshot_home.png b/screenshot_home.png
new file mode 100644
index 0000000..a965cf7
Binary files /dev/null and b/screenshot_home.png differ
diff --git a/screenshot_manual.png b/screenshot_manual.png
new file mode 100644
index 0000000..44bf6c2
Binary files /dev/null and b/screenshot_manual.png differ
diff --git a/screenshot_run9.png b/screenshot_run9.png
new file mode 100644
index 0000000..be17743
Binary files /dev/null and b/screenshot_run9.png differ
diff --git a/screenshot_runs.png b/screenshot_runs.png
new file mode 100644
index 0000000..f415fde
Binary files /dev/null and b/screenshot_runs.png differ
diff --git a/screenshot_upload.png b/screenshot_upload.png
new file mode 100644
index 0000000..44bf6c2
Binary files /dev/null and b/screenshot_upload.png differ
diff --git a/server_stderr.txt b/server_stderr.txt
index da0e32b..188148a 100644
--- a/server_stderr.txt
+++ b/server_stderr.txt
@@ -1,178 +1,60 @@
-Restored 2 datasets from disk
-[2026-07-23 13:06:51,899] INFO django: Restored 2 datasets from disk
-[2026-07-23 13:06:52,038] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_64 rows=9990 cols=57
-[2026-07-23 13:06:52,043] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_66 rows=2000 cols=9
-[23/Jul/2026 13:21:24] "GET / HTTP/1.1" 200 10790
-[23/Jul/2026 13:21:24,471] - Broken pipe from ('127.0.0.1', 64227)
-[2026-07-23 13:27:21,369] INFO analysis.views: [UPLOAD] Received 1998 files
-[23/Jul/2026 13:27:22] "POST /upload/csv/ HTTP/1.1" 200 178755
-[23/Jul/2026 13:27:22] "POST /runs/5/finalize/ HTTP/1.1" 200 34
-[23/Jul/2026 13:27:22] "GET /runs/5/status/ HTTP/1.1" 200 188
-[2026-07-23 13:27:22,672] INFO analysis.views: [BACKGROUND] Forcing lat/lon column ':ips.latd' to Utf8 for safe parsing
-[2026-07-23 13:27:22,672] INFO analysis.views: [BACKGROUND] Forcing lat/lon column ':ips.lond' to Utf8 for safe parsing
-[2026-07-23 13:27:22,672] INFO analysis.views: [BACKGROUND] Forcing lat/lon column ':ipd.latd' to Utf8 for safe parsing
-[2026-07-23 13:27:22,672] INFO analysis.views: [BACKGROUND] Forcing lat/lon column ':ipd.lond' to Utf8 for safe parsing
-[2026-07-23 13:27:22,672] INFO analysis.views: [BACKGROUND] Found 1998 CSV files in C:\Users\25044\AppData\Roaming\TianXuan\data\uploads\20260723_052721
-[2026-07-23 13:27:23,325] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:23,609] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:23,895] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:24,170] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:24,447] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:24,733] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:25,000] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:25,268] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:25,553] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[23/Jul/2026 13:27:25] "GET /runs/5/status/ HTTP/1.1" 200 242
-[2026-07-23 13:27:25,838] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:26,116] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:26,392] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:26,668] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:26,946] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:27,231] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:27,497] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:27,782] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:28,071] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:28,349] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[2026-07-23 13:27:28,621] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=495 mode=append
-[23/Jul/2026 13:27:28] "GET /runs/5/status/ HTTP/1.1" 200 243
-[2026-07-23 13:27:28,713] INFO analysis.data_loader: [SAVE_TO_DB] table=_data_68 rows=90 mode=append
-E:\hjq\天璇\analysis\views.py:584: PerformanceWarning: Determining the column names of a LazyFrame requires resolving its schema, which is a potentially expensive operation. Use `LazyFrame.collect_schema().names()` to get the column names without this warning.
- if lat_lon_col in lf.columns:
-[2026-07-23 13:27:29,071] INFO analysis.views: [BACKGROUND] Restored numeric types for 16 columns: ['1ipp', '2tmo', '4dbn', '4dur', '4srs', '8ack', '8byt', '8dbd', '8did', '8pak']
-[2026-07-23 13:27:29,150] INFO analysis.views: [BACKGROUND] SVD: 15 components from 16 numeric columns (explained variance ratio sum=1.0000)
-[23/Jul/2026 13:27:31] "GET /runs/5/status/ HTTP/1.1" 200 223
-[23/Jul/2026 13:27:56] "POST /analyze/run/ HTTP/1.1" 200 45
-[23/Jul/2026 13:27:56] "GET /runs/5/status/ HTTP/1.1" 200 223
-[2026-07-23 13:27:57,344] INFO analysis.tool_registry: [CLUSTER_INPUT] rows=9990 cols=10 feature_cols=['1ipp', '2tmo', '4dbn', '4dur', '4srs', '8ack', '8byt', '8dbd', '8did', '8pak']
-[2026-07-23 13:27:57,344] INFO analysis.tool_registry: [CLUSTER_SCALE] Starting StandardScaler...
-[2026-07-23 13:27:57,344] INFO analysis.tool_registry: [CLUSTER_SCALE] Done. shape=(9990, 10)
-E:\hjq\天璇\runtime\python\Lib\site-packages\sklearn\cluster\_hdbscan\hdbscan.py:722: FutureWarning: The default value of `copy` will change from False to True in 1.10. Explicitly set a value for `copy` to silence this warning.
- warn(
-[23/Jul/2026 13:27:59] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:02] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:06] "GET /runs/5/status/ HTTP/1.1" 200 240
-E:\hjq\天璇\runtime\python\Lib\site-packages\umap\umap_.py:1952: UserWarning: n_jobs value 1 overridden to 1 by setting random_state. Use no seed for parallelism.
- warn(
-[23/Jul/2026 13:28:09] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:12] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:15] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:18] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:21] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:24] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:27] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:30] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:33] "GET /runs/5/status/ HTTP/1.1" 200 240
-[23/Jul/2026 13:28:37] "GET /runs/5/status/ HTTP/1.1" 200 240
-[2026-07-23 13:28:38,183] INFO analysis.geoip: [GEOIP] loaded 803 ranges from E:\hjq\天璇\data\geoip_data.txt (0 skipped)
-E:\hjq\天璇\runtime\python\Lib\site-packages\umap\umap_.py:1952: UserWarning: n_jobs value 1 overridden to 1 by setting random_state. Use no seed for parallelism.
- warn(
-[23/Jul/2026 13:28:40] "GET /runs/5/status/ HTTP/1.1" 200 254
-Restored 3 datasets from disk
-[2026-07-23 21:16:22,571] INFO django: Restored 3 datasets from disk
-[2026-07-23 21:16:22,802] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_64 rows=9990 cols=57
-[2026-07-23 21:16:22,804] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_66 rows=2000 cols=9
-[2026-07-23 21:16:22,992] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_68 rows=9990 cols=57
-[23/Jul/2026 21:16:44] "GET / HTTP/1.1" 200 12728
-[23/Jul/2026 21:16:44] "GET /static/tianxuan/favicon.svg HTTP/1.1" 304 0
-[23/Jul/2026 21:17:14] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:17:20] "HEAD / HTTP/1.1" 200 0
-Restored 3 datasets from disk
-[2026-07-23 21:22:58,596] INFO django: Restored 3 datasets from disk
-[2026-07-23 21:22:58,783] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_64 rows=9990 cols=57
-[2026-07-23 21:22:58,801] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_66 rows=2000 cols=9
-[2026-07-23 21:22:59,009] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_68 rows=9990 cols=57
-[23/Jul/2026 21:22:59] "GET / HTTP/1.1" 200 12728
-Restored 3 datasets from disk
-[2026-07-23 21:37:07[23/Jul/2026 21:37:07] "GET / HTTP/1.1" 200 12728
[[23/Jul/2026 21:37:38] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:37:49] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:38:08] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:38:38] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:39:08] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:39:38] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:39:43] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:39:45] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:39:49] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:40:08] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:40:38] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:41:35] "HEAD / HTTP/1.1" 200 0
-Restored 3 datasets from disk
-[2026-07-23 21:42:01,918] INFO django: Restored 3 datasets from disk
-[2026-07-23 21:42:02,145] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_64 rows=9990 cols=57
-[2026-07-23 21:42:02,153] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_66 rows=2000 cols=9
-[2026-07-23 21:42:02,295] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_68 rows=9990 cols=57
-esponse = wrapped_callback(request, *callback_args, **callback_kwargs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\simple_analysis\views.py", line 796, in index
- File "E:\hjq\\runtime\python\Lib\site-packages\django\shortcuts.py", line 24, in render
- content = loader.render_to_string(template_name, context, request, using=using)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\runtime\python\Lib\site-packages\django\template\loader.py", line 61, in render_to_string
- template = get_template(template_name, using=using)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\runtime\python\Lib\site-packages\django\template\loader.py", line 19, in get_template
- raise TemplateDoesNotExist(template_name, chain=chain)
-django.template.exceptions.TemplateDoesNotExist: simple_analysis/simple_analysis.html
-[2026-07-23 21:41:56,536] ERROR django.request: Internal Server Error: /simple/
-Traceback (most recent call last):
- File "E:\hjq\\runtime\python\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
- response = get_response(request)
- ^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\runtime\python\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
- response = wrapped_callback(request, *callback_args, **callback_kwargs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\simple_analysis\views.py", line 796, in index
- File "E:\hjq\\runtime\python\Lib\site-packages\django\shortcuts.py", line 24, in render
- content = loader.render_to_string(template_name, context, request, using=using)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\runtime\python\Lib\site-packages\django\template\loader.py", line 61, in render_to_string
- template = get_template(template_name, using=using)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File "E:\hjq\\runtime\python\Lib\site-packages\django\template\loader.py", line 19, in get_template
- raise TemplateDoesNotExist(template_name, chain=chain)
-django.template.exceptions.TemplateDoesNotExist: simple_analysis/simple_analysis.html
-[23/Jul/2026 21:41:56] "GET /simple/ HTTP/1.1" 500 80559
-Not Found: /favicon.ico
-[2026-07-23 21:41:56,814] WARNING django.request: Not Found: /favicon.ico
-[23/Jul/2026 21:41:56] "GET /favicon.ico HTTP/1.1" 404 6872
-Restored 3 datasets from disk
-[2026-07-23 21:45:23,039] INFO django: Restored 3 datasets from disk
-[2026-07-23 21:45:23,182] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_64 rows=9990 cols=57
-[2026-07-23 21:45:23,190] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_66 rows=2000 cols=9
-[2026-07-23 21:45:23,314] INFO analysis.data_loader: [LOAD_FROM_DB_LAZY] table=_data_68 rows=9990 cols=57
-[23/Jul/2026 21:45:28] "GET / HTTP/1.1" 200 12645
-[23/Jul/2026 21:45:31] "GET /upload/ HTTP/1.1" 200 19078
-[23/Jul/2026 21:45:44] "POST /runs/5/delete/ HTTP/1.1" 200 17
-[23/Jul/2026 21:45:44] "GET /upload/ HTTP/1.1" 200 18534
-[23/Jul/2026 21:45:46] "POST /runs/4/delete/ HTTP/1.1" 200 17
-[23/Jul/2026 21:45:46] "GET /upload/ HTTP/1.1" 200 17939
-[23/Jul/2026 21:45:48] "POST /runs/3/delete/ HTTP/1.1" 200 17
-[23/Jul/2026 21:45:48] "GET /upload/ HTTP/1.1" 200 17395
-[23/Jul/2026 21:45:51] "POST /runs/2/delete/ HTTP/1.1" 200 17
-[23/Jul/2026 21:45:51] "GET /upload/ HTTP/1.1" 200 16853
-[23/Jul/2026 21:45:52] "POST /runs/1/delete/ HTTP/1.1" 200 17
-[23/Jul/2026 21:45:52] "GET /upload/ HTTP/1.1" 200 16136
-[23/Jul/2026 21:46:23] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:46:53] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:47:23] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:47:53] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:48:23] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:48:53] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:49:23] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:49:53] "HEAD / HTTP/1.1" 200 0
-[23/Jul/2026 21:50:23] "HEAD / HTTP/1.1" 200 0
-Restored 3 datasets from disk
-[2026-07-23 21:50:50,464] INFO django: Restored 3 datasets from disk
-[23/Jul/2026 21:50:54] "GET /analyze/manual/ HTTP/1.1" 200 65847
-[23/Jul/2026 21:50:54] "GET /tools/plan/ HTTP/1.1" 200 13
-[23/Jul/2026 21:50:57] "GET /analyze/auto/ HTTP/1.1" 200 39486
-[23/Jul/2026 21:51:09] "GET /runs/ HTTP/1.1" 200 9674
-[2026-07-23 21:51:10,324] INFO analysis.geoip: [GEOIP] loaded 0 ranges (0 skipped)
-[2026-07-23 21:51:10,325] INFO analysis.geoip: [GEOIP] loaded 12 cached entries
-[23/Jul/2026 21:51:10] "GET /globe/ HTTP/1.1" 200 18520
-[23/Jul/2026 21:51:10] "GET /static/tianxuan/three.min.js HTTP/1.1" 304 0
-[23/Jul/2026 21:51:10] "GET /static/tianxuan/world_borders.js HTTP/1.1" 304 0
-[23/Jul/2026 21:51:10] "GET /static/tianxuan/three.min.js HTTP/1.1" 304 0
-[23/Jul/2026 21:51:10] "GET /static/tianxuan/world_borders.js HTTP/1.1" 304 0
-[23/Jul/2026 21:51:10] "GET /static/tianxuan/earth_atmos_2048.jpg HTTP/1.1" 304 0
-[23/Jul/2026 21:51:27] "GET /config/ HTTP/1.1" 200 14372
-[23/Jul/2026 21:51:31] "GET /analyze/auto/ HTTP/1.1" 200 39486
+Restored 1 datasets from disk
+[2026-07-24 12:30:18,755] INFO analysis.data_loader: [LOAD] files=1 total_rows_est=200
+[2026-07-24 12:30:18,742] INFO django: Restored 1 datasets from disk
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=0cph dtype=String
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=0crv dtype=String
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=0rnd dtype=String
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=0rnt dtype=String
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=0ver dtype=String
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=1ipp dtype=Int64
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=2tmo dtype=Float64
+[2026-07-24 12:30:18,811] INFO analysis.data_loader: [LOAD_SCHEMA] col=4dbn dtype=Int64
+[2026-07-24 12:30:18,817] INFO analysis.data_loader: [LOAD_SCHEMA] col=4dur dtype=Float64
+[2026-07-24 12:30:18,817] INFO analysis.data_loader: [LOAD_SCHEMA] col=4ksz dtype=Int64
+[2026-07-24 12:30:18,817] INFO analysis.data_loader: [LOAD_SCHEMA] col=4srs dtype=Int64
+[2026-07-24 12:30:18,817] INFO analysis.data_loader: [LOAD_SCHEMA] col=8ack dtype=Int64
+[2026-07-24 12:30:18,817] INFO analysis.data_loader: [LOAD_SCHEMA] col=8byt dtype=Int64
+[2026-07-24 12:30:18,817] INFO analysis.data_loader: [LOAD_SCHEMA] col=8dbd dtype=Int64
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=8did dtype=Int64
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=8pak dtype=Int64
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=8ppk dtype=Int64
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=8seq dtype=Float64
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=8ses dtype=Float64
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd dtype=String
+[2026-07-24 12:30:18,818] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.anon dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.city dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.doma dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.ispn dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.latd dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.lond dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ipd.orgn dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.anon dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.city dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.doma dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.ispn dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.latd dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.lond dtype=String
+[2026-07-24 12:30:18,822] INFO analysis.data_loader: [LOAD_SCHEMA] col=:ips.orgn dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=:prd dtype=Int64
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=:prs dtype=Int64
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=cipher-suite dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=client-ip dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=cnam dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=crcc dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=dcnt dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=ecdhe-named-curve dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=name dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=orga dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=orgu dtype=Int64
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=scnt dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=server-ip dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=snam dtype=String
+[2026-07-24 12:30:18,827] INFO analysis.data_loader: [LOAD_SCHEMA] col=source-node dtype=String
+[2026-07-24 12:30:18,832] INFO analysis.data_loader: [LOAD_SCHEMA] col=tabl dtype=String
+[2026-07-24 12:30:18,832] INFO analysis.data_loader: [LOAD_SCHEMA] col=time dtype=String
+[2026-07-24 12:30:18,832] INFO analysis.data_loader: [LOAD_SCHEMA] col=timestamp dtype=Float64
+[2026-07-24 12:30:18,840] INFO analysis.data_loader: [CLEAN] Generic numeric coercion applied: [':ipd.lond', ':ipd.doma', ':ipd.ispn', 'cnam', ':ips.ispn', ':ips.doma', 'orga', 'snam', 'time', ':ips.orgn', ':ipd.orgn', 'crcc', ':ips.latd', ':ipd.latd', ':ips.city', ':ipd.city', ':ips.lond']
+[2026-07-24 12:30:18,840] INFO analysis.data_loader: [CLEAN] HEX columns added hex_pairs_count: ['0cph', '0crv', '0ver', '0rnt', '0rnd']
+[24/Jul/2026 12:30:37] "HEAD / HTTP/1.1" 200 0
+[24/Jul/2026 12:31:07] "HEAD / HTTP/1.1" 200 0
diff --git a/server_stdout.txt b/server_stdout.txt
index 65e4148..76bedb5 100644
--- a/server_stdout.txt
+++ b/server_stdout.txt
@@ -1,65 +1,8 @@
Performing system checks...
System check identified no issues (0 silenced).
-July 23, 2026 - 13:06:51
+July 24, 2026 - 12:30:18
Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://127.0.0.1:18766/
-Quit the server with CTRL-BREAK.
-
-Performing system checks...
-
-System check identified no issues (0 silenced).
-Performing system checks...
-
-System check identified no issues (0 silenced).
-Performing system checks...
-
-System check identified no issues (0 silenced).
-July 23, 2026 - 21:16:22
-Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://0.0.0.0:8000/
-Quit the server with CTRL-BREAK.
-
-Performing system checks...
-
-System check identified no issues (0 silenced).
-Performing system checks...
-
-System check identified no issues (0 silenced).
-July 23, 2026 - 21:22:58
-Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://0.0.0.0:8000/
-Quit the server with CTRL-BREAK.
-
-Performing system checks...
-
-System check identified no issues (0 silenced).
-July 23, 2026 - 21:37:07
-Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://0.0.0.0:8000/
-Quit the server with CTRL-BREAK.
-
-Performing system checks...
-
-System check identified no issues (0 silenced).
-July 23, 2026 - 21:42:01
-Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://0.0.0.0:8000/
-Quit the server with CTRL-BREAK.
-
-Performing system checks...
-
-System check identified no issues (0 silenced).
-July 23, 2026 - 21:45:23
-Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://0.0.0.0:8000/
-Quit the server with CTRL-BREAK.
-
-Performing system checks...
-
-System check identified no issues (0 silenced).
-July 23, 2026 - 21:50:50
-Django version 4.2.30, using settings 'tianxuan.settings'
-Starting development server at http://0.0.0.0:8000/
+Starting development server at http://127.0.0.1:8765/
Quit the server with CTRL-BREAK.
diff --git a/templates/analysis/cluster_detail.html b/templates/analysis/cluster_detail.html
index 28572cd..289f472 100644
--- a/templates/analysis/cluster_detail.html
+++ b/templates/analysis/cluster_detail.html
@@ -1,4 +1,4 @@
-{% extends 'base.html' %}
+{% extends 'base.html' %}
{% load static %}
{% block title %}簇 #{{ cluster.cluster_label }} — 运行 #{{ run.display_id }}{% endblock %}
{% block content %}
@@ -53,11 +53,11 @@
{{ forloop.counter }} |
{{ f.feature_name }} |
{{ f.distinguishing_score|floatformat:3 }} |
- {{ f.mean|floatformat:3|default:"-" }} |
+ {{ f.mean|floatformat:3|default:"-" }} |
{{ f.std|floatformat:3|default:"-" }} |
- {{ f.median|floatformat:3|default:"-" }} |
- {{ f.p25|floatformat:3|default:"-" }} |
- {{ f.p75|floatformat:3|default:"-" }} |
+ {{ f.median|floatformat:3|default:"-" }} |
+ {{ f.p25|floatformat:3|default:"-" }} |
+ {{ f.p75|floatformat:3|default:"-" }} |
{% endfor %}
@@ -121,4 +121,21 @@
{% endif %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
+
+
diff --git a/templates/analysis/cluster_overview.html b/templates/analysis/cluster_overview.html
index 0fa56f0..64bdd77 100644
--- a/templates/analysis/cluster_overview.html
+++ b/templates/analysis/cluster_overview.html
@@ -9,7 +9,7 @@
.left-panel.globe-open { flex:0 0 55%; }
.right-panel { flex:0 0 0; overflow:hidden; transition:flex 0.3s; border-left:1px solid #e0e0e0; }
.right-panel.globe-open { flex:0 0 45%; }
-.globe-toggle-handle { position:absolute; z-index:10; top:50%; left:calc(100% - 24px); transform:translateY(-50%); width:24px; height:48px; background:#1a1a2e; color:#fff; border:none; border-radius:0 6px 6px 0; cursor:pointer; display:flex; align-items:center; justify-content:center; font-size:14px; transition:left 0.3s, background 0.15s; }
+.globe-toggle-handle { position:absolute; z-index:10; top:50%; left:calc(100% - 24px); transform:translateY(-50%); width:24px; height:48px; background:#1a1a2e; color:#fff; border:none; border-radius:6px 0 0 6px; cursor:pointer; display:flex; align-items:center; justify-content:center; font-size:14px; transition:left 0.3s, background 0.15s; }
.globe-toggle-handle:hover { background:#4361ee; }
.globe-toggle-handle.open { left:calc(55% - 24px); border-radius:6px 0 0 6px; }
/* ── Scatter ── */
@@ -61,7 +61,7 @@
-
UMAP 嵌入 个点
+ UMAP 嵌入 计算中...
@@ -137,6 +137,7 @@